FBIagent
Erfahrenes Mitglied
Guten tag,
wie im Titel dieses Threads schon angegeben, versuche ich ein Objekt mit
bestimmter Geschwindigkeit zu bewegen. Dazu habe ich mir einen kleinen
Algorythmus geschrieben, der das Objekt halt nach seiner Geschwindigkeit
bewegt. Hierzu habe ich 2 Variablen die speichern wo das Objekt gerade
ist(m_X,m_Y), 2 Variablen die speichern wo das Objekt hin
soll(m_DestX,m_DestY) und eine Variable die speichert wann angefangen
wurde sich zu bewegen(m_StartMove).
Main Algorythmus lässt das Objekt aber zu schnell wandern
wenn entweder m_X == m_DestX oder m_Y == m_DestY.
Zum starten der Bewegung gibt es eine Methode namens StartMove().
Zum aktualisieren der Position des Objekts gibt es die Methode Move(),
die bei jedem frame aufgerufen wird.
Wäre nett wenn mal jemand drüber schauen kann.
Die Zielpositionen werden in der WindowProc des fensters gesetzt:
Und hier wo gerendert wird, wird Move() aufgerufen um die Position zu aktualisieren:
wie im Titel dieses Threads schon angegeben, versuche ich ein Objekt mit
bestimmter Geschwindigkeit zu bewegen. Dazu habe ich mir einen kleinen
Algorythmus geschrieben, der das Objekt halt nach seiner Geschwindigkeit
bewegt. Hierzu habe ich 2 Variablen die speichern wo das Objekt gerade
ist(m_X,m_Y), 2 Variablen die speichern wo das Objekt hin
soll(m_DestX,m_DestY) und eine Variable die speichert wann angefangen
wurde sich zu bewegen(m_StartMove).
Main Algorythmus lässt das Objekt aber zu schnell wandern
wenn entweder m_X == m_DestX oder m_Y == m_DestY.
Zum starten der Bewegung gibt es eine Methode namens StartMove().
Zum aktualisieren der Position des Objekts gibt es die Methode Move(),
die bei jedem frame aufgerufen wird.
Wäre nett wenn mal jemand drüber schauen kann.
Code:
//////////////////// WORLDOBJECT.H
#pragma once
class WorldObject {
public:
int GetObjectId();
int GetX();
int GetY();
const char *GetName();
protected:
int m_ObjectId;
volatile int m_X;
volatile int m_Y;
char m_Name[ 32 ];
WorldObject( int ObjectId, int X, int Y );
};
//////////////////// WORLDOBJECT.CPP
#include "./WorldObject.h"
int WorldObject::GetObjectId() {
return m_ObjectId;
}
int WorldObject::GetX() {
return m_X;
}
int WorldObject::GetY() {
return m_Y;
}
const char *WorldObject::GetName() {
return m_Name;
}
WorldObject::WorldObject( int ObjectId, int X, int Y )
: m_ObjectId( ObjectId ), m_X( X ), m_Y( Y ) {
}
Code:
//////////////////// WORLDMOVEABLE.H
#pragma once
#include "./WorldObject.h"
#define MOVE_MS 100
#define MOVES_PER_MS_TICK 1
class WorldMoveable
: public WorldObject {
public:
void StartMove( int DestX, int DestY );
void StopMove();
// should be called on every frame
void Move();
virtual void OnArrived() = 0;
int GetDestX();
int GetDestY();
protected:
int m_DestX;
int m_DestY;
WorldMoveable( int ObjectId, int X, int Y );
private:
unsigned long m_StartMove;
long double m_MoveDiffX100Start;
long double m_MoveDiffY100Start;
};
//////////////////// WORLDMOVEABLE.CPP
#include "./WorldMoveable.h"
#include <windows.h>
#include <cmath>
void WorldMoveable::StartMove( int DestX, int DestY ) {
m_StartMove = GetTickCount();
m_DestX = DestX;
m_DestY = DestY;
m_MoveDiffX100Start = abs( ( long double )m_X - ( long double )m_DestX );
m_MoveDiffY100Start = abs( ( long double )m_Y - ( long double )m_DestY );
}
void WorldMoveable::StopMove() {
m_DestX = m_X;
m_DestY = m_Y;
}
// should be called on every frame
void WorldMoveable::Move() {
if ( m_X == m_DestX && m_Y == m_DestY ) return;
unsigned long Elapsed = GetTickCount() - m_StartMove;
int Moves = ( Elapsed / MOVE_MS ) * MOVES_PER_MS_TICK;
if ( Moves == 0 )return;
long ModX = m_X > m_DestX ? -1 : ( m_X < m_DestX ? 1 : 0 );
long ModY = m_Y > m_DestY ? -1 : ( m_Y < m_DestY ? 1 : 0 );
// in points
long double DiffX100 = 0;
long double DiffY100 = 0;
// percentage
long double DiffX = 0;
long double DiffY = 0;
long NextX = m_X;
long NextY = m_Y;
while ( ( m_X != m_DestX || m_Y != m_DestY ) && Moves > 0 ) {
DiffX100 = abs( ( long double )m_X - ( long double )m_DestX );
DiffY100 = abs( ( long double )m_Y - ( long double )m_DestY );
DiffX = 100.L * DiffX100 / m_MoveDiffX100Start;
DiffY = 100.L * DiffY100 / m_MoveDiffY100Start;
if ( ( DiffX < DiffY )/* || ( (int)DiffX == (int)DiffY && DiffX100 > DiffY100 )*/ ) {
NextY += ModY;
} else if ( ( DiffX > DiffY )/* || ( (int)DiffX == (int)DiffY && DiffX100 < DiffY100 )*/ ) {
NextX += ModX;
} else {
NextX += ModX;
NextY += ModY;
}
m_X = NextX;
m_Y = NextY;
--Moves;
}
// in case we didn't reach the destination yet
if ( m_X != m_DestX && m_Y != m_DestY ) m_StartMove = GetTickCount();
else if ( m_X == m_DestX && m_Y == m_DestY ) OnArrived();
}
int WorldMoveable::GetDestX() {
return m_DestX;
}
int WorldMoveable::GetDestY() {
return m_DestY;
}
WorldMoveable::WorldMoveable( int ObjectId, int X, int Y )
: WorldObject( ObjectId, X, Y ), m_DestX( X ), m_DestY( Y ) {
}
Die Zielpositionen werden in der WindowProc des fensters gesetzt:
Code:
case WM_KEYDOWN:
switch ( wParam ) {
case VK_UP:
OneNpc->StartMove( OneNpc->GetDestX(), OneNpc->GetDestY() - 50 );
break;
case VK_DOWN:
OneNpc->StartMove( OneNpc->GetDestX(), OneNpc->GetDestY() + 50 );
break;
case VK_LEFT:
OneNpc->StartMove( OneNpc->GetDestX() - 50, OneNpc->GetDestY() );
break;
case VK_RIGHT:
OneNpc->StartMove( OneNpc->GetDestX() + 50, OneNpc->GetDestY() );
break;
default:
break;
}
return 0;
Und hier wo gerendert wird, wird Move() aufgerufen um die Position zu aktualisieren:
Code:
if ( MainWindow_Init() ) {
while ( true ) {
if ( PeekMessage( &wndMsg, NULL, 0, 0, PM_REMOVE ) ) {
if ( wndMsg.message == WM_QUIT ) break;
TranslateMessage( &wndMsg );
DispatchMessage( &wndMsg );
}
MainWindow_RenderFrame();
}
}
........................................
void MainWindow_RenderFrame() {
// move npcs
/* for ( g_NpcsIter = g_Npcs.begin();g_NpcsIter != g_Npcs.end();++ g_NpcsIter ) {
(*g_NpcsIter)->Move();
}*/
OneNpc->Move();
g_D2DRenderTarget->BeginDraw();
//g_D2DRenderTarget->SetTransform( D2D1::Matrix3x2F::Identity() );
g_D2DRenderTarget->Clear( D2D1::ColorF( D2D1::ColorF::White ) );
// Calculate the number of frames per one second:
g_dwFrames++;
g_dwCurrentTime = GetTickCount(); // Even better to use timeGetTime()
g_dwElapsedTime = g_dwCurrentTime - g_dwLastUpdateTime;
if ( g_dwElapsedTime >= 10 ) {
g_FPS = g_dwFrames * ( 1000UL / g_dwElapsedTime );
g_dwFrames = 0UL;
g_dwLastUpdateTime = g_dwCurrentTime;
}
D2D1_RECT_F NpcRect;
/* // draw npc's
for ( g_NpcsIter = g_Npcs.begin();g_NpcsIter != g_Npcs.end();++ g_NpcsIter ) {
NpcRect.top = (*g_NpcsIter)->GetY() - 8;
NpcRect.bottom = (*g_NpcsIter)->GetY() + 8;
NpcRect.left = (*g_NpcsIter)->GetX() - 8;
NpcRect.right = (*g_NpcsIter)->GetX() + 8;
g_D2DRenderTarget->DrawRectangle( NpcRect, g_D2DBrushGray );
}*/
NpcRect.top = OneNpc->GetY() - 8;
NpcRect.bottom = OneNpc->GetY() + 8;
NpcRect.left = OneNpc->GetX() - 8;
NpcRect.right = OneNpc->GetX() + 8;
g_D2DRenderTarget->DrawRectangle( NpcRect, g_D2DBrushGray );
NpcRect.top = OneNpc->GetDestY() - 8;
NpcRect.bottom = OneNpc->GetDestY() + 8;
NpcRect.left = OneNpc->GetDestX() - 8;
NpcRect.right = OneNpc->GetDestX() + 8;
g_D2DRenderTarget->DrawRectangle( NpcRect, g_D2DBrushGreen );
/* g_D2DRenderPoint2.x = g_FPS;
g_D2DRenderTarget->DrawLine( g_D2DRenderPoint1, g_D2DRenderPoint2, g_D2DBrushGray, 10 );*/
// g_D2DRenderTarget->DrawTextW( itoa( FPS, szFPS, 10 ), wcslen( FPS ),
g_D2DRenderTarget->EndDraw();
}
Zuletzt bearbeitet: