• Advertisement
  • Popular Tags

  • Popular Now

  • Advertisement
  • Similar Content

    • By eldwin11929
      We're looking for a Unity (C#) Programmer for our 2D Project. We're looking for a new lead programmer to continue with an existing project.
       
      Project is an open-world RTS, and is very close to a prototyping (playable) phase. Our existing lead, unfortunately, has no more time for the project, and thus we are in search of a new one who is interested.
       
      Game is purely fantasy based, and we'll be able to give you much more detailed info about the project as we begin to work you into it.
       
      You'll be working with our junior developer, who has been here since the beginning.
       
      Primary skills needed are just being able to work within Unity. But skills within XML are also a plus.
       
      Our list of major goals we'd need you to do is minimal, yet still fairly extensive:
      -Edit our current Pathfinding system to account for a few extra features.
      -Setup our global map system. You’ll be working off an existing random node-map web generator and existing random map generation system and essentially linking the two together. This includes handling random spawns (which has already been semi-setup) unique to each node’s respective map.
      -Further implementation of an existing random spawning algorithm (used to spawn things like enemies randomly across the Map).
      -Making sure to Save and Record all respective aspects of what was mentioned above.
      -Handling our XML database- database is created, but we’ll need to be integrating it. This includes all various things from units to abilities and so forth. Will also need to handle implementing an object’s unique attributes we cannot take care of within XML.
      -Various Content Implementation (to be done once our XML has been integrated).
      -Various Saving and Recording of all respective aspects of the database info mentioned above.
      -Various Performance Enhancements.
      -Potential for various misc things, such as further UI work.
      -Setting up a Menu system.
       
      We have a considerable amount of things done already- however I must warn ahead of time we have quite a bit of unclean code, which may be fairly overwhelming for a new developer on the project.
       
      Let me know your rates per hour, and we'll see if we can work out a good deal between both of us. Royalties are also included.
       
      If interested, send an email to: eldwin11929@yahoo.com
       
      Thanks!
    • By Ronan Hayes
      So i am working on a java swing breakout game and am on the last task to complete, which is detecting collision with a brick and then deleting it from the array so it cannot be seen on the screen. I have created a for loop which is somewhat working however the ball bounces off the bat/paddle and goes straight through the first few rows of bricks and then start to detect only the rows around the 6/7th row. Here is the loop i am working on. 
      public void runAsSeparateThread() { final float S = 3; // Units to move (Speed) try { synchronized ( Model.class ) // Make thread safe { GameObj ball = getBall(); // Ball in game GameObj bat = getBat(); // Bat ArrayList<GameObj> bricks = getBricks(); // Bricks } while (runGame) { synchronized ( Model.class ) // Make thread safe { float x = ball.getX(); // Current x,y position float y = ball.getY(); // Deal with possible edge of board hit if (x >= W - B - BALL_SIZE) ball.changeDirectionX(); if (x <= 0 + B ) ball.changeDirectionX(); if (y >= H - B - BALL_SIZE) // Bottom { ball.changeDirectionY(); addToScore( HIT_BOTTOM ); } if (y <= 0 + M ) ball.changeDirectionY(); // As only a hit on the bat/ball is detected it is // assumed to be on the top or bottom of the object. // A hit on the left or right of the object // has an interesting affect boolean hit = false; // *[3]******************************************************[3]* // * Fill in code to check if a visible brick has been hit * // * The ball has no effect on an invisible brick * // ************************************************************** for ( int i = 0; i <= 60; i++ ){ GameObj brick1 = bricks.get(i); if ( brick1.hitBy(ball) ){ bricks.remove(i); //hit = true; ball.changeDirectionY(); //ball.changeDirectionX(); addToScore(50); } } if (hit) ball.changeDirectionY(); if ( ball.hitBy(bat) ) ball.changeDirectionY(); } modelChanged(); // Model changed refresh screen Thread.sleep( fast ? 2 : 20 ); ball.moveX(S); ball.moveY(S); } } catch (Exception e) { Debug.error("Model.runAsSeparateThread - Error\n%s", e.getMessage() ); } } } i need to be able to break each brick individually and for them to rebound ... this is the code that i am working with so far 
      for ( int i = 0; i <= 60; i++ ){ GameObj brick1 = bricks.get(i); if ( brick1.hitBy(ball) ){ bricks.remove(i); //hit = true; ball.changeDirectionY(); //ball.changeDirectionX(); addToScore(50); } }  
    • By Jiraya
      For a 2D game, does using a float2 for position increases performance in any way?
      I know that in the end the vertex shader will have to return a float4 anyway, but does using a float2 decreases the amount of data that will have to be sent from the CPU to the GPU?
       
    • By ThunderTwonk
      Hello everyone, I am working on a game idea and since I am still in the process of learning C# and the features available in unity I was hoping some of you might be able to offer me a little insight on things in general for getting started.
      I guess the basic components of what I'm wanting to create would be a Multi-levels management/city builder/rpg.
      The goal is to provide a framework for players to interact with, build in and affect the world both from a 3rd person action RPG as well as a zoomed out 4x style view (This would be something unlocked through gameplay)
       
      As for my questions go I was wondering if anyone had resources that could help me learn.  I've been on youtube as well as enrolled in an online course for basic unity and C# and will continue those but if anyone has any words of advice, a place that has good information and tutorials etc.
       
      Thanks for your time.
    • By INFRA
      SCAN. DRILL. SURVIVE.   ISOLATED Release in May 1st 2018   https://store.steampowered.com/app/805950/Isolated/   A game by Jérémie Bertrand Music & Sound Design by Pierrick Querolle *** Our solar system has been invaded by strangers. For the purpose of a possible negotiation, a team of astronauts is sent to the moon. Alas, they are shot before even arriving on the scene. Only one astronaut survives the crash and his only goal will be to go home...   GAMEPLAY   Shoot enemy ships to avoid being invaded. Be precise in your movements, because it's better to lose a bit of life at the top than to lose it all at the bottom. Take out your drill to destroy the stones in your path. Validate your identity to cross the different laboratories. Reach the flag before losing your three lives.   And all that... at the same time! Will you be able to go home? If the answer is yes, how long will it take?
  • Advertisement
  • Advertisement

Drawing point seems to lag behind...

Recommended Posts

I have this Direct2D framework set up, it render a constant 60FPS and this is my code in my draw call:

	mRenderTarger->Clear(D2D1::ColorF(0.41f, 0.41f, 0.41f, 1.0f));

	GetCursorPos(&mMouse);
	ScreenToClient(mhWindow, &mMouse);
	D2D1_POINT_2F point2 = D2D1::Point2F(mMouse.x, mMouse.y);
	
	//wrapper function of the Direct2D FillEllipse function
	drawPoint(point2, 6.f, D2D1::ColorF(1.0f, 0.15f, 0.30f, 1.f));

Now even without moving the mouse too fase, the point drawn kind of lag behind a bit, and moving the mouse faster, the point is drawn as far as 5cm from my mouse cursor so the lag is visible.

Any idea why this accurs and how to fix it? 

Edited by MarcusAseth

Share this post


Link to post
Share on other sites
Advertisement

I'm not an expert in this, but it's common for the mouse cursor to be handled by the display drivers as a special case, rather than explicitly rendered onscreen by the application. This means it can display the new position as close to instantly as possible, whereas a normal 3D rendering pipeline might take quite some time for a rendered frame to work its way through to the display.

Share this post


Link to post
Share on other sites

How are you invoking your actual rendering? Is it in the WM_PAINT handler of your message loop, by chance?

(If not, please show the code that invokes it and the code that drives you main loop... and probably your actual window procedure as well; those are the likely culprits).

Share this post


Link to post
Share on other sites

The drawing code is in the game loop and it is called when there are no messages from PeekMessage, inbetween the BeginDraw() and EndDraw() calls, and I'm running it in the Debug mode but without the debug (CTRL+F5 on visual studio).

Framework2D "D2DApp" code:

Spoiler

#include "D2DApp.h"
#include <iostream>
#include <sstream>

LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	D2DApp* pD2DApp = reinterpret_cast<D2DApp*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
	if (pD2DApp) { return pD2DApp->WinProc(hwnd, msg, wParam, lParam); }
	else { return DefWindowProc(hwnd, msg, wParam, lParam); }
}


D2DApp::D2DApp(HINSTANCE instance, std::wstring caption, float width, float height)
	: mInstance{ instance }, mhWindow{ nullptr }, mClientWidth{ width }, mClientHeight{ height }, mWindowCaption{ caption },
	mTimer{}, mAppPaused{ false }, mFactory{ nullptr }, mRenderTarger{ nullptr }, mBrush{ nullptr }
{
}


D2DApp::~D2DApp()
{
	if (mBrush) { mBrush->Release(); }
	if (mRenderTarger) { mRenderTarger->Release(); }
	if (mFactory) { mFactory->Release(); }
}

bool D2DApp::Init()
{
	//Register Window
	WNDCLASS mainWindow{};
	mainWindow.lpfnWndProc = WindowProc;
	mainWindow.hInstance = mInstance;
	mainWindow.hCursor = LoadCursor(mInstance, IDC_ARROW);
	mainWindow.lpszClassName = L"mainWindow";
	if (!RegisterClassW(&mainWindow))
	{
		MessageBoxW(mhWindow, L"Couldn't register the window", 0, 0);
		return false;
	}
	//Create Window
	RECT rect{ 0,0,mClientWidth,mClientHeight };
	AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, false);
	int newWidth = rect.right - rect.left;
	int newHeight = rect.bottom - rect.top;
	int monitorWidth = GetSystemMetrics(SM_CXSCREEN);
	int monitorHeight = GetSystemMetrics(SM_CYSCREEN);
	mhWindow = CreateWindowExW(0, mainWindow.lpszClassName, mWindowCaption.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
							   monitorWidth / 2 - newWidth / 2, monitorHeight / 2 - newHeight / 2, newWidth, newHeight,
							   0, 0, mInstance, 0);
	if (!mhWindow)
	{
		MessageBoxW(mhWindow, L"Couldn't create the window", 0, 0);
		return false;
	}
	UpdateWindow(mhWindow);
	SetWindowLongPtr(mhWindow, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));

	//Init D2D
	HRESULT hr;

	//Create Factory
	hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &mFactory);
	if (hr != S_OK) {
		MessageBoxW(mhWindow, L"Couldn't create the D2D1 factory", 0, 0);
		return false;
	}

	//Create HwndRenderTarget
	D2D1_RENDER_TARGET_PROPERTIES RTProp{};
	RTProp.type = D2D1_RENDER_TARGET_TYPE_HARDWARE;
	RTProp.pixelFormat.format = DXGI_FORMAT_R8G8B8A8_UNORM;
	D2D1_HWND_RENDER_TARGET_PROPERTIES hWndRTProp{};
	hWndRTProp.hwnd = mhWindow;
	hWndRTProp.pixelSize.width = mClientWidth;
	hWndRTProp.pixelSize.height = mClientHeight;

	hr = mFactory->CreateHwndRenderTarget(RTProp, hWndRTProp, &mRenderTarger);
	if (hr != S_OK) {
		MessageBoxW(mhWindow, L"Couldn't create the HwndRenderTarget", 0, 0);
		return false;
	}

	//Create Solid Brush
	hr = mRenderTarger->CreateSolidColorBrush(D2D1::ColorF(0.4f, 0.3f, 0.7f, 1.0f), &mBrush);
	if (hr != S_OK) {
		MessageBoxW(mhWindow, L"Couldn't create the solid brush", 0, 0);
		return false;
	}

	return true;
}
int D2DApp::Run()
{
	MSG msg{};
	mTimer.reset();
	while (msg.message != WM_QUIT)
	{
		if (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessageW(&msg);
		}
		else
		{
			//Timer Tick
			mTimer.tick();

			if (!mAppPaused)
			{
				CalculateFrameStats();
				Update(mTimer.deltaTime());

				BeginDraw();
				Draw();
				EndDraw();
			}
			else
			{
				Sleep(100);
			}

		}
	}

	return (int)msg.wParam;
}
void D2DApp::Update(float dt)
{
}
void D2DApp::Draw()
{
}
void D2DApp::BeginDraw()
{
	mRenderTarger->BeginDraw();
}

void D2DApp::EndDraw()
{
	mRenderTarger->EndDraw();
}

LRESULT D2DApp::WinProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
	switch (msg)
	{
	case WM_DESTROY:
	case WM_CLOSE:
	{
		PostQuitMessage(0);
	}break;
	}
	return DefWindowProc(hwnd, msg, wparam, lparam);
}

void D2DApp::CalculateFrameStats()
{
	static int frameCnt = 0;
	static float timeElapsed = 0.0f;
	frameCnt++;

	if ((mTimer.totalTime() - timeElapsed) >= 1.0f)
	{
		float fps = (float)frameCnt; 
		float mspf = 1000.0f / fps;

		std::wostringstream outs;
		//outs.precision(6);
		outs << mWindowCaption.c_str() << "    "
			<< "FPS: " << fps << "    "
			<< "Frame Time: " << mspf << " (ms)";
		SetWindowTextW(mhWindow, outs.str().c_str());

		frameCnt = 0;
		timeElapsed += 1.0f;
	}
}

 

 

class that inherits from the Framework2D "D2DApp" and run everything (does the drawing calls) the:

Spoiler

#include "TrigClient.h"
#include <DirectXMath.h>
#include <iostream>
using std::cout; using std::endl;

#define rad(x) DirectX::XMConvertToRadians(x)
#define deg(x) DirectX::XMConvertToDegrees(x)

TrigClient::TrigClient(HINSTANCE instance, std::wstring caption, float width, float height)
    :D2DApp(instance, caption, width, height), mOriginX{ 0 }, mOriginY{ 0 }, mAngle{ 0 }, mAngleChange{ 70.f },
    mWaveBox{}, mMouse{ 0 }, mDashedLine{ nullptr }, mTriangleGeo{ nullptr }
{
}


TrigClient::~TrigClient()
{
    if (mDashedLine) { mDashedLine->Release(); }
    if (mTriangleGeo) { mTriangleGeo->Release(); }
}

bool TrigClient::Init()
{
    if (!D2DApp::Init())
    {
        return false;
    }
    //Additional initialization
    mOriginX = { mClientWidth / 2.f };
    mOriginY = { mClientHeight / 3.5f };

    //waveBox
    float waveBoxPadding = 50.f;
    float  waveBoxWidth = 350.f;
    float  waveBoxHeight = 250.f;
    mWaveBox.bottom = mClientHeight - waveBoxPadding;
    mWaveBox.top = mWaveBox.bottom - waveBoxHeight;
    mWaveBox.left = waveBoxPadding;
    mWaveBox.right = mWaveBox.left + waveBoxWidth;

    D2D1_STROKE_STYLE_PROPERTIES dashedLineProp{};
    dashedLineProp.startCap = D2D1_CAP_STYLE_FLAT;
    dashedLineProp.endCap = D2D1_CAP_STYLE_FLAT;
    dashedLineProp.dashCap = D2D1_CAP_STYLE_ROUND;
    dashedLineProp.lineJoin = D2D1_LINE_JOIN_MITER;
    dashedLineProp.miterLimit = 60.f;
    dashedLineProp.dashStyle = D2D1_DASH_STYLE_CUSTOM; //try DOT
    dashedLineProp.dashOffset = 3.3f; // might want to use this to animate the dashLine
    float dashes[] = { 6.0f, 6.0f, 6.0f };

    HRESULT hr = mFactory->CreateStrokeStyle(dashedLineProp, dashes, ARRAYSIZE(dashes), &mDashedLine);
    if (hr != S_OK) {
        MessageBoxW(mhWindow, L"failed to create dashed line", 0, 0);
        return false;
    }

    return true;
}

void TrigClient::Update(float dt)
{
    mAngle += mAngleChange*dt;

    float oneCircleTime = 360 / mAngleChange; //time required to complete 1 revolution, in seconds
    unsigned pointResolution = 30;
    float pointsPerSecond = 1 / pointResolution; //how often points are added, in seconds

    static float addPointTimer = 0;
    addPointTimer += dt;
    //evaluate every t | determines wave resolution
    if (addPointTimer >= pointsPerSecond)
    {
        //function to turn into a wave
        D2D1_POINT_2F newPoint = { mTimer.totalTime() ,cos(rad(mAngle)) };
        
        //add new point
        mWavePoints.push_back(newPoint);

        //remove old Points
        for (size_t i = 0; i < mWavePoints.size(); i++)
        {
            if (mTimer.totalTime() - mWavePoints.front().x >= oneCircleTime) {
                mWavePoints.pop_front();
            }
            else {
                break;
            }
        }

        addPointTimer = 0;
    }
}

void TrigClient::Draw()
{
    //background
    mRenderTarger->Clear(D2D1::ColorF(0.41f, 0.41f, 0.41f, 1.0f));
    makeGrid(25);

    //circle stuff
    float radius = 250.f;
    D2D1_POINT_2F point1 = D2D1::Point2F(radius * cos(rad(mAngle)), radius * sin(rad(mAngle)));
    circileFromOrigin(radius, 3.f, D2D1::ColorF(0.2f, 0.65f, 0.86f, 1.f));
    lineFromOrigin(point1, 2.f, D2D1::ColorF(0.46f, 0.76f, 0.86f, 1.f));
    drawPointFromOrigin(point1, 6.f, D2D1::ColorF(1.0f, 0.15f, 0.30f, 1.f));
    projectionX(point1);
    perpX(point1);
    triangleAreaDisplay(point1);

    //draw wave box
    drawWaveBox(cos(rad(mAngle)));
}

void TrigClient::drawWaveBox(const float point)
{
    //transparent box base
    mBrush->SetColor(D2D1::ColorF(0.4f, 0.4f, 0.4f, 0.65f));
    mRenderTarger->FillRectangle(mWaveBox, mBrush);
    //box outline
    mBrush->SetColor(D2D1::ColorF(0.9f, 0.9f, 0.0f, 0.45f));
    mRenderTarger->DrawRectangle(mWaveBox, mBrush);

    //horizontal line
    mBrush->SetColor(D2D1::ColorF(0.08f, 0.08f, 0.08f, 1.0f));
    float boxWidth = mWaveBox.right - mWaveBox.left;
    float boxHeight = mWaveBox.bottom - mWaveBox.top;
    float marks = 50;
    float linePaddingH = 20;
    float linePaddingV = 10;
    float lineBoundLeft = mWaveBox.left + linePaddingH;
    float lineBoundRight = mWaveBox.right - linePaddingH;
    float lineBoundBottom = mWaveBox.bottom - linePaddingV;
    float lineLength = lineBoundRight - lineBoundLeft;
    float intervalSpace = lineLength / marks;

    mRenderTarger->DrawLine(D2D1::Point2(lineBoundLeft, lineBoundBottom),
                            D2D1::Point2(lineBoundRight, lineBoundBottom), mBrush, 1.f);
    //horizontal marks
    for (size_t i = 0; i <= marks; i++) {
        mRenderTarger->DrawLine(D2D1::Point2(lineBoundLeft + (intervalSpace*i), lineBoundBottom - 5),
                                D2D1::Point2(lineBoundLeft + (intervalSpace*i), lineBoundBottom + 5), mBrush, 1.f);
    }

    //internal box
    float internalBoxTop = mWaveBox.top + (mWaveBox.bottom - lineBoundBottom) + linePaddingV;
    float internalBoxBottom = lineBoundBottom - linePaddingV;
    mBrush->SetColor(D2D1::ColorF(0.24f, 0.24f, 0.24f, 0.85f));
    mRenderTarger->FillRectangle(D2D1::RectF(lineBoundLeft, //left
                                             internalBoxTop, //top
                                             lineBoundRight, //right
                                             internalBoxBottom),// bottom
                                 mBrush);
    //draw wave
    float internalBoxMidY = internalBoxTop + ((internalBoxBottom - internalBoxTop) / 2);
    float oneCircleTime = 360 / mAngleChange;
    float graphHSpace = lineBoundRight - lineBoundLeft;
    float graphYSpace = internalBoxBottom - internalBoxTop;
    for (auto& point : mWavePoints)
    {
        float pointAge = mTimer.totalTime() - point.x;
        drawPoint(D2D1::Point2F(lineBoundLeft + ((graphHSpace / oneCircleTime) * pointAge),//X
                                internalBoxMidY + (-point.y * graphYSpace / 2.05f))//Y
                  , 2.6f, D2D1::ColorF(-point.y, point.y, point.y, 0.85f));
    }
}

void TrigClient::projectionX(const D2D1_POINT_2F& p)
{
    mBrush->SetColor(D2D1::ColorF(0.5f, 0.75f, 0.30f, 1.f));
    mRenderTarger->DrawLine(D2D1::Point2F(mOriginX + p.x, mOriginY - p.y), D2D1::Point2F(mOriginX + p.x, mOriginY), mBrush, 1.f, mDashedLine);
    drawPointFromOrigin(D2D1::Point2F(p.x, 0), 5.f, D2D1::ColorF(0.5f, 0.75f, 0.30f, 1.f));
}

void TrigClient::perpX(const D2D1_POINT_2F& p)
{
    mBrush->SetColor(D2D1::ColorF(0.5f, 0.75f, 0.30f, 1.f));
    mRenderTarger->DrawLine(D2D1::Point2F(mOriginX + p.x, mOriginY - p.y), D2D1::Point2F(mOriginX, mOriginY - p.y), mBrush, 1.f, mDashedLine);
    drawPointFromOrigin(D2D1::Point2F(0, p.y), 5.f, D2D1::ColorF(0.5f, 0.75f, 0.30f, 1.f));
}

void TrigClient::triangleAreaDisplay(const D2D1_POINT_2F& p)
{
    //free previous triangle
    if (mTriangleGeo) { mTriangleGeo->Release(); }

    //create triangle path geo
    HRESULT hr = mFactory->CreatePathGeometry(&mTriangleGeo);
    if (hr != S_OK) {
        assert(hr == S_OK);
        MessageBoxW(mhWindow, L"failed to create triangle path geo", 0, 0);
    }

    ID2D1GeometrySink* pSink;
    D2D1_POINT_2F tringle[3] = {
                                { mOriginX + p.x,mOriginY},
                                { mOriginX + p.x , mOriginY - p.y},
                                { mOriginX, mOriginY }
    };

    mTriangleGeo->Open(&pSink);
    pSink->BeginFigure(D2D1::Point2F(mOriginX, mOriginY), D2D1_FIGURE_BEGIN_FILLED);
    //build shape here//
    pSink->AddLines(tringle, 3);
    ////////////
    pSink->EndFigure(D2D1_FIGURE_END_CLOSED);
    pSink->Close();
    pSink->Release();

    //draw shape
    float point = cos(rad(mAngle));
    mBrush->SetColor(D2D1::ColorF(-point, point, point, 0.7f));
    mRenderTarger->FillGeometry(mTriangleGeo, mBrush);
}

void TrigClient::makeGrid(float spacing)
{
    mBrush->SetColor(D2D1::ColorF(0.0f, 0.0f, 0.0f, 1.0f));
    //Major Horizontal and Vertical lines
    mRenderTarger->DrawLine(D2D1::Point2F(0.0f, mOriginY),
                            D2D1::Point2F(mClientWidth, mOriginY),
                            mBrush, 2.f);
    mRenderTarger->DrawLine(D2D1::Point2F(mOriginX, 0.0f),
                            D2D1::Point2F(mOriginX, mClientHeight),
                            mBrush, 2.f);

    //Vertical lines

    unsigned leftLines = (int)(mOriginX / spacing);
    unsigned righttLines = (int)((mClientWidth - mOriginX) / spacing);
    unsigned verticalLines = leftLines > righttLines ? leftLines : righttLines;

    for (size_t i = 1; i <= verticalLines; i++)
    {
        //left
        mRenderTarger->DrawLine(D2D1::Point2F(mOriginX - (i*spacing), 0.f),
                                D2D1::Point2F(mOriginX - (i*spacing), mClientHeight),
                                mBrush, 0.25f);
        //right
        mRenderTarger->DrawLine(D2D1::Point2F(mOriginX + (i*spacing), 0.f),
                                D2D1::Point2F(mOriginX + (i*spacing), mClientHeight),
                                mBrush, 0.25f);
    }

    //Horizontal lines

    unsigned topLines = (int)(mOriginY / spacing);
    unsigned bottomtLines = (int)((mClientHeight - mOriginY) / spacing);
    unsigned horizontalLines = topLines > bottomtLines ? topLines : bottomtLines;
    for (size_t i = 1; i <= horizontalLines; i++)
    {
        //up
        mRenderTarger->DrawLine(D2D1::Point2F(0.f, mOriginY - (i*spacing)),
                                D2D1::Point2F(mClientWidth, mOriginY - (i*spacing)),
                                mBrush, 0.25f);
        //down
        mRenderTarger->DrawLine(D2D1::Point2F(0.f, mOriginY + (i*spacing)),
                                D2D1::Point2F(mClientWidth, mOriginY + (i*spacing)),
                                mBrush, 0.25f);
    }
}

void TrigClient::lineFromOrigin(const D2D1_POINT_2F& p, float strokeSize, const D2D1_COLOR_F& color)
{
    if (color.a != -1.f) {
        mBrush->SetColor(color);
    }
    mRenderTarger->DrawLine(D2D1::Point2F(mOriginX, mOriginY),
                            D2D1::Point2F(mOriginX + p.x, mOriginY - p.y), mBrush, strokeSize);
}

void TrigClient::circileFromOrigin(const float radius, float strokeSize, const D2D1_COLOR_F& color)
{
    if (color.a != -1.f) {
        mBrush->SetColor(color);
    }
    mRenderTarger->DrawEllipse(D2D1::Ellipse(D2D1::Point2F(mOriginX, mOriginY), radius, radius),
                               mBrush, strokeSize);
}

void TrigClient::drawPoint(const D2D1_POINT_2F& p, float radius, const D2D1_COLOR_F& color)
{
    if (color.a != -1.f) {
        mBrush->SetColor(color);
    }
    mRenderTarger->FillEllipse(D2D1::Ellipse(D2D1::Point2F(p.x, p.y), radius, radius), mBrush);
}

void TrigClient::drawPointFromOrigin(const D2D1_POINT_2F& p, float radius, const D2D1_COLOR_F& color)
{
    if (color.a != -1.f) {
        mBrush->SetColor(color);
    }
    mRenderTarger->FillEllipse(D2D1::Ellipse(D2D1::Point2F(mOriginX + p.x, mOriginY - p.y), radius, radius),
                               mBrush);
}

 

Since is a long read of code and I don't really need to have a circle that follow my mouse in real time don't sweat it trying to solve this guys, I don't even have the code for that circle in there anymore.

But if anyone has more insight into this I would still like to know more :)

Also is worth mentioning I have fixed 60FPS by default and I believe it has to do with the D2D intialization, so maybe is just D2D 

Edited by MarcusAseth

Share this post


Link to post
Share on other sites

The most obvious factor is that the Sleep(100) in your core loop will always halt your application (and thus your updating and rendering of the position of the shape) for at least 100 milliseconds, if not more. The cursor, being driven by the OS, blissfully does not care about that and will update the cursor in realtime.

That Sleep() is not needed. It's often seen used to "make sure we don't use 100% of the CPU," but that goal itself is often based on a false premise and even then, sleeping the whole thread for an arbitrary amount of time isn't the solution.

If your base class WndProc is doing anything with mouse-moved events that is time-consuming, that can also throttle back your core loop since mouse-moved events are _very_ spammy. Similarly, if the base framework class is trying to force a WM_PAINT, which is a low-priority but spammy (even though it's coelsced) message, and doesn't actually correctly handle that WM_PAINT, that can also throttle back your core loop by causing the branch into the positive case for the PeekMessage check to be taken way, way more frequently than you generally want. I'd verify those.

Share this post


Link to post
Share on other sites

That sleep is actually never called because the if (!mAppPaused) is always true since I am not handling pause, I am not processing any inputs and I have no WM_PAINT cases :P

Wish I knew how to share the exe with you guys so you can feel the lag for yourself :/

Edited by MarcusAseth

Share this post


Link to post
Share on other sites

So the "paused" clause is literally for like, "user has paused the game" or otherwise suspended the application and not to pause the loop to throttle down to your target framerate? That does mean the sleep is probably not the cause of your lag, unless you're accidentally flip-flopping the state of the gating variable someplace (breakpoint in the debugger to verify), although the Sleep() is still not the best way to handle that. Neither here nor there, though.

You can upload the .exe someplace, although the chance that somebody will download a random .exe is slim (and you'll want to make sure you upload an appropriately self-contained package, e.g., not a debug build etc). You could also upload a .zip of the project and somebody might be willing to build and verify it for you. Or try making a video and sharing that.

Something else you might try as a diagnostics technique is to make the shape move back and forth on its own, without mouse input. Then observe the behavior as it runs, keeping your mouse still and your hands off the keyboard. Then, observe the behavior as it runs while you move the mouse frantically over the window. This can help rule out whether the delay is due to a factor of the Win32 message queue size or simply a constant issue.

Share this post


Link to post
Share on other sites

There is a 4th possibility, searching this awesome forum for a solution, which is 7 years old :D  

mind in a box said:

Quote

This is because VSync. To turn it off, just do that when you create the rendertarget:

V_RETURN(MyVars.D2DFactory->CreateHwndRenderTarget( RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,PixelFormat(DXGI_FORMAT_UNKNOWN ,D2D1_ALPHA_MODE_PREMULTIPLIED )), HwndRenderTargetProperties( hw, SizeU( WindowSize.right - WindowSize.left, WindowSize.bottom - WindowSize.top),D2D1_PRESENT_OPTIONS_IMMEDIATELY ), &MyVars.RT));

This will unlock your FPS.

EDIT: Oh, didn't read you post carefully. :( But try setting off vsync, and please show how you set up Direct2D. In my engine, it renders just very fast...

And indeed, switching to D2D1_PRESENT_OPTIONS_IMMEDIATELY that 5cm of lag turned into 2-3mm, much much better! :D

Still thanks for all the good tips jpetrie, and double thanks to mind in a box for the (almost) perfect solution :)  (perfect would be 0mm :P )

Edited by MarcusAseth

Share this post


Link to post
Share on other sites

It's almost like I mentioned rendering latency in my first reply! (Almost, because I probably wasn't explicit enough about it.)

Be aware that D2D1_PRESENT_OPTIONS_IMMEDIATELY has side-effects. Make sure you can live with them.

Share this post


Link to post
Share on other sites
2 minutes ago, Kylotan said:

Be aware that D2D1_PRESENT_OPTIONS_IMMEDIATELY has side-effects. Make sure you can live with them.

What are this side effects? GPU meltdown? :D

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Advertisement