Archived

This topic is now archived and is closed to further replies.

propulsion systems????

This topic is 5083 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

im trying to do a spaces ship game, but cant figure out how to work the propulsion systems. like, i cant really explain, you could go to www.arcadetown.com and take a look at Real Space Two. thats the kind of propulsion system i want to do. so...any help...appreciated. MUCHAS GRACIAS

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Ok, so what are you trying to accomplish? Do you want to simulate the physics of propulsion or are you trying to create a particle system like the one in that game? More info please.

Share this post


Link to post
Share on other sites
alrighty, if by particle engine you mean detecting the angle that the ship is facing and thrusting in that direction when the user hits a key, then yes. if you mean the fire particles that come out the back of the little ship then no. all i want to do is basicall simulate the way a car steers in one direction and then accelerates in that direction. MUCHAS GRACIAS

Share this post


Link to post
Share on other sites
quote:
Original post by PyroniaWatches
...all i want to do is basicall simulate the way a car steers in one direction and then accelerates in that direction. MUCHAS GRACIAS

Maybe you should use a 2d vector. When the user presses a direction key you just rotate the vector. For going forward add the vector to the ships position to get the new position

Share this post


Link to post
Share on other sites
Ok, I've tried the game, so I'll now try to explain how the movement works.

The first thing is momentum. When you apply thrust the ship accelerates. The ship continues to move even after the thrust has been let off because it has a certain momentum.

Keeping track of this is easy:

int shipXVelocity;
int shipYVelocity;

These two variables will determine what direction the ship is moving in even when there is no thrust.

shipX = shipX + shipXVelocity;
shipY = shipY + shipYVelocity;

This is all fine and good, but we need a way to CHANGE the ships velocity, i.e. apply thrust.

If this game were a side scroller, thrust would be easy. When ever the player hits left:

shipXVelocity = shipXVelocty - THRUST_CONSTANT

and for right:

shipXVelocity = shipXVeloctiy + THRUST_CONSTANT

The same principle holds true for moving up and down. THRUST_CONSTANT is just some number you decide upon, and this will determine how quickly the ship will accelerate.

One thing you might have noticed from Real Space two is that your ship will eventually come to a stop after you have let off the thrust-- as if there was some force dragging on our ship. To simulate this dragging effect lets go the simple route.

if ( shipXVelocity > 0) shipXVelocity = shipXVelocity - DRAG_CONSTANT
if ( shipXVelocity < 0) shipXVelocity = shipXVelocity + DRAG_CONSTANT

What happenes here is that we steal some of the energy causing our ship to move forward. DRAG_CONSTANT is just a number you define, and it will determine how much force acts against our ship. Be carefule not to make DRAG_CONSTANT higher than THRUST_CONSTANT, otherwise our ship will never be able to get moving.

You would extend the sample above to work on shipYVelocity as well. From here on out I'll ignore shipYVelocity (except where essential).

The next problem we need to solve is how to let the pilot of the ship turn in any direction, and apply thrust in that direction. This will require a wee bit of math, and a change to how we modify shipXVelocity.

The first thing we need to do is keep track of which direction the player is facing.

float shipAngle;

Everytime the player hits left, or right, shipAngle will change accordingly.

Now we need a way to convert the ship angle in to some type of force when thrust is applied. We need to keep track of two things here:

float shipXThrust;
float shipYThrust;

And then set them to something useful (here comes the math)

float raidanAngle

radianAngle = shipAngle * ( 180 / 3.14159);

shipXThrust = THRUST_CONSTANT * cos ( radianAngle);
shipYThrust = THRUST_CONSTANT * sin ( radianAngle);

The first thing we did here was convert our ships angle from degrees to radians. We had to do this because the trig functions SINe and COSine want to play in radians.

The next thing we did was to convert the angle (in radians) in to some measure of horizontal and vertical force. Imaginge a right-angled triangle. The hypontenus (longest side) of the triangle is the direction and amount (length) of THRUST we've applied. The sides of the triangle are the vertical and horizontal components of that same force.

So now that we have shipXThrust and shipYThrust we can apply it to the ships velocity.

shipXVelocity = shipXVelocity + shipXThrust;
(do the same for Y)

That's all there is to it. Your space ship can fly around in space with his own momentum.

Hope this has helped,
Will

P.S. This code was for illustrative purposes only. I don't gaurantee it will work.







[edited by - RPGeezus on January 9, 2004 1:25:41 PM]

Share this post


Link to post
Share on other sites
well....here is the code i put into my pre-game. im trying it with a block first. i know how to do rotating animation. i did the things you said to do (except for the friction/drag thing). yet it still doesn''t work. the red block comes up, u press up and it accelerates downwards but if you hold it it goes at a crazy angle, sort of like spinning of. thanks for all your help so far...here it comes:

#include <windows.h>
#include <math.h>
#include "trythis.h"

#define WIN_WID 1024
#define WIN_HGT 768

bool started = FALSE;

#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

#define IMG_WID 64 // Width of our image
#define IMG_HGT 64 // Height of our image

#define class_name "Carlos can do it"

#define DOUBLE_BUFFER 1 // Change this to zero to view the app without double buffering

// This is the struct that will hold all of our double buffering info
struct SDBuffer
{
HWND win_hwnd; // A copy of the window handle

HDC win_dc; // This is the window''s HDC
HDC back_dc; // This is the HDC to the back buffer we''re gonna make

RECT rect; // This will hold the client RECT of our window

HBITMAP back_bmp; // This is the HBITMAP that we''ll fill with an exact copy of
// our window''s HBITMAP (pixels)

HBITMAP old_bmp; // We need this guy around so we can totally free up memory when it''s
// all said and done
};

// Globals ***

int xPos = 0; // This will hold the upper left hand x-coord of the mouse
int yPos = 0; // This will hold the upper left hand y-ccord of the mouse

// *** End of Globals

// This will set up our double buffering. We return true on success, false on failure
bool InitDoubleBuffer(SDBuffer &doubleBuff);

// This funciton will free up all the memory associated with our double buffer
void FreeDoubleBuffer(SDBuffer &doubleBuff);

// Locks the frame rate at the passed in frame rate (60 FPS by default)
bool LockFrameRate(int frame_rate = 60);

// Standard callback function
LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);

int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprev, PSTR cmdline, int ishow)
{
HWND hwnd;
MSG msg;
WNDCLASSEX wndclassex = {0};

SDBuffer doubleBuff = {0}; // This is our "double buffer" struct

// Fill the fields we care about
wndclassex.cbSize = sizeof(WNDCLASSEX);
wndclassex.style = CS_HREDRAW | CS_VREDRAW;
wndclassex.lpfnWndProc = WinProc;
wndclassex.hInstance = hinstance;
wndclassex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclassex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclassex.lpszClassName = class_name;

RegisterClassEx(&wndclassex); // Register the window

hwnd = CreateWindowEx(NULL, // No extra window attributes
class_name,
"attempt at huge map",
WS_VISIBLE | WS_POPUP,
0, // Window will receive a default x pos on screen
0, // Window will receive a default y pos on screen
WIN_WID,
WIN_HGT,
NULL,
NULL,
hinstance,
NULL);

// Error check
if(!hwnd)
{
UnregisterClass(class_name,hinstance);
return EXIT_FAILURE; // Something really bad happened!
}


doubleBuff.win_hwnd = hwnd; // Set the HWND of our double buffer struct

// Attempt to initialize our double buffering
if(!InitDoubleBuffer(doubleBuff))
{
UnregisterClass(class_name,hinstance);
return EXIT_FAILURE; // Couldn''t set up double buffering
}

// Here we''ll load up our bitmap
// Create a compatible HDC so that we can draw our "img_bmp"
HDC img_dc = CreateCompatibleDC(doubleBuff.win_dc);

if(!img_dc)
{
UnregisterClass(class_name,hinstance);
return EXIT_FAILURE;
}

// Select our "img_bmp" into the "img_dc"
ShowWindow(hwnd, ishow);
UpdateWindow(hwnd);

HBITMAP old_bmp = NULL;

while(1)
{
// Check message(s) if there are any
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(msg.message == WM_QUIT)
break;

TranslateMessage(&msg);
DispatchMessage(&msg);
}
else if(LockFrameRate())
{
player.x += player.x_vel;
player.y += player.y_vel;

if(started == FALSE)
{
game_init();
started = TRUE;
}

#if DOUBLE_BUFFER // If we are using double buffering

// First we fill our back buffer to solid white (the same color as the
// background color of our window)
FillRect(doubleBuff.back_dc,&doubleBuff.rect,(HBRUSH)GetStockObject(WHITE_BRUSH));

// Next we''ll draw the bitmap to our back buffer
old_bmp = (HBITMAP)SelectObject(img_dc,player_bmp);

BitBlt(doubleBuff.back_dc,player.x,player.y,64,64,img_dc,0,0,SRCCOPY);
// Then we draw the back buffer to the front buffer (our window)
BitBlt(doubleBuff.win_dc,0,0,doubleBuff.rect.right,
doubleBuff.rect.bottom,doubleBuff.back_dc,0,0,SRCCOPY);

#else // No double buffering in use

// We fill our window with solid white so we can clear away the "old"
// position of the image
FillRect(doubleBuff.win_dc,&doubleBuff.rect,(HBRUSH)GetStockObject(WHITE_BRUSH));

// Blit the image to the window
BitBlt(doubleBuff.win_dc,xPos,yPos,xPos + IMG_WID,
yPos + IMG_HGT,img_dc,0,0,SRCCOPY);

// **NOTE** Do not be mislead by the use of the "doubleBuff" variable.
// We are ONLY using this to access the window''s HDC. Absolutely
// no double buffering goes on in the between the #else and the
// #endif. Be sure to look at how worse it looks without double
// buffering.

#endif
}

}

// Free up our image memory
SelectObject(img_dc,old_bmp);
DeleteDC(img_dc);

// Free up all the memory associated with our back buffer
FreeDoubleBuffer(doubleBuff);

UnregisterClass(class_name,hinstance); // Free up WNDCLASSEX
return msg.wParam;
}

// The WinProc
LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
key();

PAINTSTRUCT ps;

// Depending on the message -- we''ll do different stuff
switch(message)
{
case WM_PAINT:

BeginPaint(hwnd,&ps);
EndPaint(hwnd,&ps);
return 0;

// Message we get when the mouse moves
case WM_MOUSEMOVE:

xPos = LOWORD(lparam); // X position of cursor
yPos = HIWORD(lparam); // Y position of cursor
return 0;

case WM_DESTROY:
case WM_CLOSE:

PostQuitMessage(0);
return 0;

} // end of switch(message)

return DefWindowProc(hwnd, message, wparam, lparam);
}

// Here will create/initialize our double buffer
// Return true on success, false on failure
bool InitDoubleBuffer(SDBuffer &doubleBuff)
{
// Error Check
if(!doubleBuff.win_hwnd)
return false; // Not a valid window HWND

// First and foremost we are going to get and store off the CLIENT RECT of our
// window. The client area (client rect) is the portion of a window where the
// application displays output, such as text, graphics, etc, etc
GetClientRect(doubleBuff.win_hwnd,&doubleBuff.rect); // Get the client RECT

// The next thing we are going to do is store off the window''s
// HDC. Remember you can think of the HDC as a way to "talk to" all of the
// pixels that make up the window.
doubleBuff.win_dc = GetDC(doubleBuff.win_hwnd); // Get the window''s HDC

// Error Check
if(doubleBuff.win_dc == NULL)
return false;

// Okay we have the window''s HDC. What we want to do is create a replicable
// in memory of the window''s pixels that we are able to draw to. So that
// means we''ll need a HDC that can interface (is compatible to) the window''s
// HDC. Thus we create a compatible HDC
doubleBuff.back_dc = CreateCompatibleDC(doubleBuff.win_dc);

// Error Check
if(doubleBuff.back_dc == NULL)
return false;

// So now we have a means to talk to our back buffer, but we DO NOT have
// the buffer (the set aside memory that will hold the pixel information).
// No worries, we''ll just create a compatible bitmap the SAME size as
// our window''s client area
doubleBuff.back_bmp = CreateCompatibleBitmap(doubleBuff.win_dc,
doubleBuff.rect.right,
doubleBuff.rect.bottom);

// Error Check
if(doubleBuff.back_bmp == NULL)
return false;

// If we get here that means we were successful in creating a "buffer" that
// mimics the windows front buffer. But before we can draw to our newly
// created buffer, we have to tell the "back buffer''s HDC" that it is
// associated with (or in charge of) the "back buffer''s HBITMAP -- Thus we
// select the created back buffer into our back buffer''s device context
doubleBuff.old_bmp = (HBITMAP)SelectObject(doubleBuff.back_dc,doubleBuff.back_bmp);

// **NOTE** remember we save off the return from SelectObject() so we can FULLY
// free up memory before we close the application

return true; // We be buff
}

// This function will free up all the memory we allocated
void FreeDoubleBuffer(SDBuffer &doubleBuff)
{
// Error Check
if(!doubleBuff.win_hwnd)
return;

if(doubleBuff.old_bmp) // If we have a double buffer
{
// Select back the original "bitmap"
SelectObject(doubleBuff.back_dc,doubleBuff.old_bmp);

// Free up memory
DeleteObject(doubleBuff.back_bmp);
DeleteDC(doubleBuff.back_dc);
}

if(doubleBuff.win_dc) // If we have the window''s device context
{
// Relese the device context
ReleaseDC(doubleBuff.win_hwnd,doubleBuff.win_dc);
}

// Set everything to zero
memset(&doubleBuff,0,sizeof(SDBuffer));
}

// Locks the frame rate at "frame_rate"
// Returns true when it''s okay to draw, false otherwise
bool LockFrameRate(int frame_rate)
{
static float lastTime = 0.0f;

// Get current time in seconds (milliseconds * .001 = seconds)
float currentTime = GetTickCount() * 0.001f;

// Get the elapsed time by subtracting the current time from the last time
// If the desired frame rate amount of seconds has passed -- return true (ie Blit())
if((currentTime - lastTime) > (1.0f / frame_rate))
{
// Reset the last time
lastTime = currentTime;
return true;
}

return false;
}

void game_init()
{
player.x = 200;
player.y = 200;
player.shipAngle = 360;
player.x_acc = 0;
player.y_acc = 0;
player.y_vel = 0;
player.x_vel = 0;
}

void key()
{
if(KEYDOWN(VK_ESCAPE))
{
PostQuitMessage(0);
}

if(KEYDOWN(VK_LEFT))
{
player.shipAngle += .75;
}

if(KEYDOWN(VK_RIGHT))
{
player.shipAngle -= .75;
}

if(KEYDOWN(VK_UP))
{
float radianAngle;

radianAngle = player.shipAngle * (180/3.14159);

player.x_acc = cos(radianAngle);
player.y_acc = sin(radianAngle);

player.x_vel += player.x_acc;
player.y_vel += player.y_acc;
}

if(player.x_vel > 0) player.x_vel -= 5;
if(player.x_vel < 0) player.x_vel += 5;

if(player.y_vel > 0) player.y_vel -= 5;
if(player.y_vel < 0) player.y_vel += 5;
}

Share this post


Link to post
Share on other sites
Next time....


#include <windows.h>
#include <math.h>
#include "trythis.h"

#define WIN_WID 1024
#define WIN_HGT 768

bool started = FALSE;

#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

#define IMG_WID 64 // Width of our image

#define IMG_HGT 64 // Height of our image


#define class_name "Carlos can do it"

#define DOUBLE_BUFFER 1 // Change this to zero to view the app without double buffering


// This is the struct that will hold all of our double buffering info

struct SDBuffer
{
HWND win_hwnd; // A copy of the window handle


HDC win_dc; // This is the window''s HDC

HDC back_dc; // This is the HDC to the back buffer we''re gonna make


RECT rect; // This will hold the client RECT of our window


HBITMAP back_bmp; // This is the HBITMAP that we''ll fill with an exact copy of

// our window''s HBITMAP (pixels)


HBITMAP old_bmp; // We need this guy around so we can totally free up memory when it''s

// all said and done

};

// Globals ***


int xPos = 0; // This will hold the upper left hand x-coord of the mouse

int yPos = 0; // This will hold the upper left hand y-ccord of the mouse


// *** End of Globals


// This will set up our double buffering. We return true on success, false on failure

bool InitDoubleBuffer(SDBuffer &doubleBuff);

// This funciton will free up all the memory associated with our double buffer

void FreeDoubleBuffer(SDBuffer &doubleBuff);

// Locks the frame rate at the passed in frame rate (60 FPS by default)

bool LockFrameRate(int frame_rate = 60);

// Standard callback function

LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);

int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprev, PSTR cmdline, int ishow)
{
HWND hwnd;
MSG msg;
WNDCLASSEX wndclassex = {0};

SDBuffer doubleBuff = {0}; // This is our "double buffer" struct


// Fill the fields we care about

wndclassex.cbSize = sizeof(WNDCLASSEX);
wndclassex.style = CS_HREDRAW | CS_VREDRAW;
wndclassex.lpfnWndProc = WinProc;
wndclassex.hInstance = hinstance;
wndclassex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclassex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclassex.lpszClassName = class_name;

RegisterClassEx(&wndclassex); // Register the window


hwnd = CreateWindowEx(NULL, // No extra window attributes

class_name,
"attempt at huge map",
WS_VISIBLE | WS_POPUP,
0, // Window will receive a default x pos on screen

0, // Window will receive a default y pos on screen

WIN_WID,
WIN_HGT,
NULL,
NULL,
hinstance,
NULL);

// Error check

if(!hwnd)
{
UnregisterClass(class_name,hinstance);
return EXIT_FAILURE; // Something really bad happened!

}


doubleBuff.win_hwnd = hwnd; // Set the HWND of our double buffer struct


// Attempt to initialize our double buffering

if(!InitDoubleBuffer(doubleBuff))
{
UnregisterClass(class_name,hinstance);
return EXIT_FAILURE; // Couldn''t set up double buffering

}

// Here we''ll load up our bitmap

// Create a compatible HDC so that we can draw our "img_bmp"

HDC img_dc = CreateCompatibleDC(doubleBuff.win_dc);

if(!img_dc)
{
UnregisterClass(class_name,hinstance);
return EXIT_FAILURE;
}

// Select our "img_bmp" into the "img_dc"

ShowWindow(hwnd, ishow);
UpdateWindow(hwnd);

HBITMAP old_bmp = NULL;

while(1)
{
// Check message(s) if there are any

if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(msg.message == WM_QUIT)
break;

TranslateMessage(&msg);
DispatchMessage(&msg);
}
else if(LockFrameRate())
{
player.x += player.x_vel;
player.y += player.y_vel;

if(started == FALSE)
{
game_init();
started = TRUE;
}

#if DOUBLE_BUFFER // If we are using double buffering


// First we fill our back buffer to solid white (the same color as the

// background color of our window)

FillRect(doubleBuff.back_dc,&doubleBuff.rect,(HBRUSH)GetStockObject(WHITE_BRUSH));

// Next we''ll draw the bitmap to our back buffer

old_bmp = (HBITMAP)SelectObject(img_dc,player_bmp);

BitBlt(doubleBuff.back_dc,player.x,player.y,64,64,img_dc,0,0,SRCCOPY);
// Then we draw the back buffer to the front buffer (our window)

BitBlt(doubleBuff.win_dc,0,0,doubleBuff.rect.right,
doubleBuff.rect.bottom,doubleBuff.back_dc,0,0,SRCCOPY);

#else // No double buffering in use


// We fill our window with solid white so we can clear away the "old"

// position of the image

FillRect(doubleBuff.win_dc,&doubleBuff.rect,(HBRUSH)GetStockObject(WHITE_BRUSH));

// Blit the image to the window

BitBlt(doubleBuff.win_dc,xPos,yPos,xPos + IMG_WID,
yPos + IMG_HGT,img_dc,0,0,SRCCOPY);

// **NOTE** Do not be mislead by the use of the "doubleBuff" variable.

// We are ONLY using this to access the window''s HDC. Absolutely

// no double buffering goes on in the between the #else and the

// #endif. Be sure to look at how worse it looks without double

// buffering.


#endif
}

}

// Free up our image memory

SelectObject(img_dc,old_bmp);
DeleteDC(img_dc);

// Free up all the memory associated with our back buffer

FreeDoubleBuffer(doubleBuff);

UnregisterClass(class_name,hinstance); // Free up WNDCLASSEX

return msg.wParam;
}

// The WinProc

LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
key();

PAINTSTRUCT ps;

// Depending on the message -- we''ll do different stuff

switch(message)
{
case WM_PAINT:

BeginPaint(hwnd,&ps);
EndPaint(hwnd,&ps);
return 0;

// Message we get when the mouse moves

case WM_MOUSEMOVE:

xPos = LOWORD(lparam); // X position of cursor

yPos = HIWORD(lparam); // Y position of cursor

return 0;

case WM_DESTROY:
case WM_CLOSE:

PostQuitMessage(0);
return 0;

} // end of switch(message)


return DefWindowProc(hwnd, message, wparam, lparam);
}

// Here will create/initialize our double buffer

// Return true on success, false on failure

bool InitDoubleBuffer(SDBuffer &doubleBuff)
{
// Error Check

if(!doubleBuff.win_hwnd)
return false; // Not a valid window HWND


// First and foremost we are going to get and store off the CLIENT RECT of our

// window. The client area (client rect) is the portion of a window where the

// application displays output, such as text, graphics, etc, etc

GetClientRect(doubleBuff.win_hwnd,&doubleBuff.rect); // Get the client RECT


// The next thing we are going to do is store off the window''s

// HDC. Remember you can think of the HDC as a way to "talk to" all of the

// pixels that make up the window.

doubleBuff.win_dc = GetDC(doubleBuff.win_hwnd); // Get the window''s HDC


// Error Check

if(doubleBuff.win_dc == NULL)
return false;

// Okay we have the window''s HDC. What we want to do is create a replicable

// in memory of the window''s pixels that we are able to draw to. So that

// means we''ll need a HDC that can interface (is compatible to) the window''s

// HDC. Thus we create a compatible HDC

doubleBuff.back_dc = CreateCompatibleDC(doubleBuff.win_dc);

// Error Check

if(doubleBuff.back_dc == NULL)
return false;

// So now we have a means to talk to our back buffer, but we DO NOT have

// the buffer (the set aside memory that will hold the pixel information).

// No worries, we''ll just create a compatible bitmap the SAME size as

// our window''s client area

doubleBuff.back_bmp = CreateCompatibleBitmap(doubleBuff.win_dc,
doubleBuff.rect.right,
doubleBuff.rect.bottom);

// Error Check

if(doubleBuff.back_bmp == NULL)
return false;

// If we get here that means we were successful in creating a "buffer" that

// mimics the windows front buffer. But before we can draw to our newly

// created buffer, we have to tell the "back buffer''s HDC" that it is

// associated with (or in charge of) the "back buffer''s HBITMAP -- Thus we

// select the created back buffer into our back buffer''s device context

doubleBuff.old_bmp = (HBITMAP)SelectObject(doubleBuff.back_dc,doubleBuff.back_bmp);

// **NOTE** remember we save off the return from SelectObject() so we can FULLY

// free up memory before we close the application


return true; // We be buff

}

// This function will free up all the memory we allocated

void FreeDoubleBuffer(SDBuffer &doubleBuff)
{
// Error Check

if(!doubleBuff.win_hwnd)
return;

if(doubleBuff.old_bmp) // If we have a double buffer

{
// Select back the original "bitmap"

SelectObject(doubleBuff.back_dc,doubleBuff.old_bmp);

// Free up memory

DeleteObject(doubleBuff.back_bmp);
DeleteDC(doubleBuff.back_dc);
}

if(doubleBuff.win_dc) // If we have the window''s device context

{
// Relese the device context

ReleaseDC(doubleBuff.win_hwnd,doubleBuff.win_dc);
}

// Set everything to zero

memset(&doubleBuff,0,sizeof(SDBuffer));
}

// Locks the frame rate at "frame_rate"

// Returns true when it''s okay to draw, false otherwise

bool LockFrameRate(int frame_rate)
{
static float lastTime = 0.0f;

// Get current time in seconds (milliseconds * .001 = seconds)

float currentTime = GetTickCount() * 0.001f;

// Get the elapsed time by subtracting the current time from the last time

// If the desired frame rate amount of seconds has passed -- return true (ie Blit())

if((currentTime - lastTime) > (1.0f / frame_rate))
{
// Reset the last time

lastTime = currentTime;
return true;
}

return false;
}

void game_init()
{
player.x = 200;
player.y = 200;
player.shipAngle = 360;
player.x_acc = 0;
player.y_acc = 0;
player.y_vel = 0;
player.x_vel = 0;
}

void key()
{
if(KEYDOWN(VK_ESCAPE))
{
PostQuitMessage(0);
}

if(KEYDOWN(VK_LEFT))
{
player.shipAngle += .75;
}

if(KEYDOWN(VK_RIGHT))
{
player.shipAngle -= .75;
}

if(KEYDOWN(VK_UP))
{
float radianAngle;

radianAngle = player.shipAngle * (180/3.14159);

player.x_acc = cos(radianAngle);
player.y_acc = sin(radianAngle);

player.x_vel += player.x_acc;
player.y_vel += player.y_acc;
}

if(player.x_vel > 0) player.x_vel -= 5;
if(player.x_vel < 0) player.x_vel += 5;

if(player.y_vel > 0) player.y_vel -= 5;
if(player.y_vel < 0) player.y_vel += 5;
}


BTW whose code did you copy?

Share this post


Link to post
Share on other sites
the code was derived from www.GameTutorials.com, one of the tutorials on double buffering. i copied it and have used it as a base ever since. as for your redone code, i tried it and it does the same thing...so i dono what to do now. try it your self, the trythis.h file is as follows:

HBITMAP player_bmp = (HBITMAP)LoadImage(NULL,"player.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);

struct ship
{
public:
int x;
int y;
float y_vel;
float x_vel;
float y_acc;
float x_acc;
float shipAngle;
};


ship player;


void ChangeToFullScreen(int width, int height);
void key();
void game_init();

see what you get. and the bitmap is a red square 2D. i haven''t found an application that''ll let me rotate a bitmap.

Share this post


Link to post
Share on other sites
It''s not working because of a small bug.

In your code you say:

if(KEYDOWN(VK_UP))
{
float radianAngle;

radianAngle = player.shipAngle * (180/3.14159);

player.x_acc = cos(radianAngle);
player.y_acc = sin(radianAngle);

player.x_vel += player.x_acc;
player.y_vel += player.y_acc;
}

if(player.x_vel > 0) player.x_vel -= 5;
if(player.x_vel < 0) player.x_vel += 5;


This is where the problem lies.

The reason your ship is moving around all crazy like is because your call to sin ( randianAngle) and cos ( radianAngle) will return a number between -1 and 1 (I think). Either way, it will never be 5!

You add this number to your velocity, and then subtract 5. So:

xAccel = 0.2
yAccle = -0.9

xVelocty = 0.2 - 5 = -4,8.

Here is how you fix the problem:

You have to multiply cos(radianAngle) by something, like an acceleration constant. (See my original post).

ie:

player.x_acc = THRUST_CONST * cos ( radianAngle);

In this case THRUST_CONST _must_ be grater than 5 (otherwise your ship will move backwards).

Let me know if this fixed your problem.

Best of luck,
Will






Share this post


Link to post
Share on other sites
well...i tried it, but now it moves according to the mouse, i took that out and it screws up...no matter what it wont work. i did the following:

#define THRUST_CONSTANT 6

then when cos and/or sin i did this:

player.x_acc = THRUST_CONSTANT * cos(radianAngle);

.....IT STILL SCREWED up. try it your self and see but im tellin you it just wont work so....its evil

Share this post


Link to post
Share on other sites
hmm... this might not fix it, but isn''t this wrong?

radianAngle = player.shipAngle * (180/3.14159);

should be

radianAngle = player.shipAngle * (3.14159/180);

also, since C++ uses rounding that should be

radianAngle = player.shipAngle * (3.14159f/180.0f);


for example: player.shipAngle = 180
radianAngle = 180 * (3.14159 / 180) = 3.14159

Share this post


Link to post
Share on other sites
kVandaele: I think you''re right.

Try doing what kVandaele says, PyroniaWatches.

You should really learn how to use your debugger. Point your ship Right (0 degrees and 0 radians) and see what the thrust is in the x direction. Try it again with the ship facing north, west, south, etc.

At 0 degrees you should get MAX_THUST in the x Direction, and 0 in the Y. If the ships facing west you should get -MAX_THRUST in the x direction, and 0 in the Y.

The code isn''t evil, but I wrote it off the top of my head. I didn''t test it. You''ll figure it out-- just keep at it.

Best of luck,
Will

Share this post


Link to post
Share on other sites
actually your code''s quite good... I might even use it (well, modify it... Personally i believe having one velocity with an angle is more intuitive than two velocities... so if you turn 180 degrees and accelerate you''re going faster not slower -- but of course, that''s not how the site did it ). Thanks for the sine and cosine bit, i would''ve cracked my head on that in about a month

Share this post


Link to post
Share on other sites