help the newbie, help the newbie

Started by
7 comments, last by PyroniaWatches 20 years, 4 months ago
ive tried to do bullets again and again. where you have a gun on screen, press spacebar and woah! its a shot, unfortunately if you press it again it delets the shot you just fired and refires it. if you wait until the shot is out of the screen, same thing. does anyone know how to make it so that if you press it, it fires and then if you press it again, hey!, it fires a new shot. and so on and so forth, but every time the shot you fired goes out of the screen it deletes itself. its like a....machine gun (so to speak). please, im trying to make a 2D shooter, where you walk around and shoot people but i need this gun thing working. please, any advice would be greatly apreciated. Thanks in advance
Advertisement
hmmm, whats your code so far?

-www.penten.tk-
You just have to create an array of bullets and keep track of each''s state, and when you shoot, set the bullets state on. Like this (C/C++?):

const int MAX_BULLETS_ON_SCREEN = 50;
const int BULLET_STATE_ON = 1;
const int BULLET_STATE_OFF = 0;

struct BULLETS
{
int state;
int x, y;
// All the other stuff
}bullets[MAX_BULLETS_ON_SCREEN];

// Some code..

// Now its time to shoot
for(int i = 0; i < MAX_BULLETS_ON_SCREEN; i++)
{
if(bullets.state == BULLET_STATE_OFF)
{
// You can shoot this one
Shoot(&bullets);<br> bullets.state = BULLET_STATE_ON;<br> }<br>}<br><br><br>Maybe that isn''t the fastest way to do it, but it works.<br><br>Hope that helps. </i>
that may be slow but its the best code i gotten so far. thanks
[removed and regular posting account noted]

[edited by - michalson on December 18, 2003 7:59:52 PM]
k i will post my code soon enough and here it is:
#include <windows.h>
#include <vector>

#define WIN_WID 640
#define WIN_HGT 480

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

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

#define THE_COLOR RGB(255,0,255)

#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
};

struct Bullet
{
int x;
int state;
int y;
bool destroyed;
};

struct Ship
{
int x;
int y;
};
// 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

HBITMAP three_bmp = (HBITMAP)LoadImage(NULL,"laser_blast.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
HBITMAP back_bmp = (HBITMAP)LoadImage(NULL,"background.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
HBITMAP ship_bmp = (HBITMAP)LoadImage(NULL,"ship.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);

const int MAX_BULLETS = 100;
const int BULLET_STATE_ON = 1;
const int BULLET_STATE_OFF = 0;
Ship player;
Bullet bullets[MAX_BULLETS];
#define STATE_ONE 1
#define STATE_TWO 2
#define STATE_THREE 3
int x = 0;
int x_vel = 10;
int y = 0;
#define TIME_OF_DELAY 10;
bool animate(int bullet_per_second);
int wait = 0;
HDC wonder = NULL;
int state = STATE_ONE;
SDBuffer doubleBuff = {0}; // This is our "double buffer" struct

// *** End of Globals
void key();
// 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);
void check_bullets();
void game_init();
// 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};


// 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,
"www.GameTutorials.com -- Double Buffering",
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
HBITMAP img_bmp = (HBITMAP)LoadImage(hinstance,"background.bmp",IMAGE_BITMAP,
0,0,LR_LOADFROMFILE);

// Error Check
if(!img_bmp)
{
UnregisterClass(class_name,hinstance);
return EXIT_FAILURE; // Couldn''t load our image
}

game_init();
// Change To FullScreen

// Create a compatible HDC so that we can draw our "img_bmp"
HDC img_dc = CreateCompatibleDC(doubleBuff.win_dc);
wonder = img_dc;
if(!img_dc)
{
UnregisterClass(class_name,hinstance);
return EXIT_FAILURE;
}

// Select our "img_bmp" into the "img_dc"
HBITMAP old_bmp = (HBITMAP)SelectObject(img_dc,img_bmp);

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

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())
{
check_bullets();
key();
#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,ship_bmp);

BitBlt(doubleBuff.back_dc,player.x,player.y,250,350,img_dc,0,0,SRCCOPY);

for(int i = 0; i < MAX_BULLETS; i++)
{
old_bmp = (HBITMAP)SelectObject(img_dc,three_bmp);

BitBlt(doubleBuff.back_dc,bullets.x,bullets.y,27,50,img_dc,<br> 0,0,SRCCOPY);<br> }<br><br> // Then we draw the back buffer to the front buffer (our window)<br> BitBlt(doubleBuff.win_dc,0,0,doubleBuff.rect.right,<br> doubleBuff.rect.bottom,doubleBuff.back_dc,0,0,SRCCOPY);<br><br> #else // No double buffering in use<br><br> // We fill our window with solid white so we can clear away the "old"<br> // position of the image<br> FillRect(doubleBuff.win_dc,&doubleBuff.rect,(HBRUSH)GetStockObject(WHITE_BRUSH));<br><br> // Blit the image to the window<br><br> // **NOTE** Do not be mislead by the use of the "doubleBuff" variable.<br> // We are &#79;NLY using this to access the window''s HDC. Absolutely<br> // no double buffering goes &#111;n in the between the #else and the <br> // #endif. Be sure to look at how worse it looks without double<br> // buffering.<br><br> #endif<br> }<br><br> }<br><br> // Free up our image memory<br> SelectObject(img_dc,old_bmp);<br> DeleteDC(img_dc);<br><br> // Free up all the memory associated with our back buffer<br> FreeDoubleBuffer(doubleBuff);<br><br> UnregisterClass(class_name,hinstance); // Free up WNDCLASSEX<br> return msg.wParam;<br>}<br><br>// The WinProc<br>LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)<br>{<br> PAINTSTRUCT ps;<br> <br> // Depending &#111;n the message – we''ll do different stuff<br> switch(message)<br> { <br> case WM_PAINT:<br> <br> BeginPaint(hwnd,&ps);<br> EndPaint(hwnd,&ps);<br> return 0;<br><br> // Message we get when the mouse moves<br> case WM_MOUSEMOVE:<br><br> xPos = LOWORD(lparam); // X position of cursor <br> yPos = HIWORD(lparam); // Y position of cursor<br> return 0;<br><br> case WM_DESTROY:<br> case WM_CLOSE:<br> <br> PostQuitMessage(0);<br> return 0;<br><br> } // end of switch(message)<br><br> return DefWindowProc(hwnd, message, wparam, lparam);<br>}<br><br>// Here will create/initialize our double buffer<br>// Return true &#111;n success, false &#111;n failure<br>bool InitDoubleBuffer(SDBuffer &doubleBuff)<br>{<br> // Error Check<br> if(!doubleBuff.win_hwnd)<br> return false; // Not a valid window HWND<br><br> // First and foremost we are going to get and store off the CLIENT RECT of our<br> // window. The client area (client rect) is the portion of a window where the<br> // application displays output, such as text, graphics, etc, etc<br> GetClientRect(doubleBuff.win_hwnd,&doubleBuff.rect); // Get the client RECT<br><br> // The next thing we are going to do is store off the window''s <br> // HDC. Remember you can think of the HDC as a way to "talk to" all of the <br> // pixels that make up the window.<br> doubleBuff.win_dc = GetDC(doubleBuff.win_hwnd); // Get the window''s HDC<br><br> // Error Check<br> if(doubleBuff.win_dc == NULL)<br> return false;<br><br> // Okay we have the window''s HDC. What we want to do is create a replicable <br> // in memory of the window''s pixels that we are able to draw to. So that<br> // means we''ll need a HDC that can interface (is compatible to) the window''s<br> // HDC. Thus we create a compatible HDC<br> doubleBuff.back_dc = CreateCompatibleDC(doubleBuff.win_dc); <br><br> // Error Check<br> if(doubleBuff.back_dc == NULL)<br> return false;<br><br> // So now we have a means to talk to our back buffer, but we DO NOT have <br> // the buffer (the set aside memory that will hold the pixel information).<br> // No worries, we''ll just create a compatible bitmap the SAME size as <br> // our window''s client area<br> doubleBuff.back_bmp = CreateCompatibleBitmap(doubleBuff.win_dc,<br> doubleBuff.rect.right,<br> doubleBuff.rect.bottom);<br><br> // Error Check<br> if(doubleBuff.back_bmp == NULL)<br> return false;<br><br> // If we get here that means we were successful in creating a "buffer" that <br> // mimics the windows front buffer. But before we can draw to our newly <br> // created buffer, we have to tell the "back buffer''s HDC" that it is <br> // associated with (or in charge of) the "back buffer''s HBITMAP – Thus we<br> // select the created back buffer into our back buffer''s device context<br> doubleBuff.old_bmp = (HBITMAP)SelectObject(doubleBuff.back_dc,doubleBuff.back_bmp); <br><br> // **NOTE** remember we save off the return from SelectObject() so we can FULLY <br> // free up memory before we close the application<br><br> return true; // We be buff<br>}<br><br>// This function will free up all the memory we allocated<br>void FreeDoubleBuffer(SDBuffer &doubleBuff)<br>{<br> // Error Check<br> if(!doubleBuff.win_hwnd)<br> return;<br><br> if(doubleBuff.old_bmp) // If we have a double buffer<br> {<br> // Select back the original "bitmap"<br> SelectObject(doubleBuff.back_dc,doubleBuff.old_bmp);<br><br> // Free up memory<br> DeleteObject(doubleBuff.back_bmp);<br> DeleteDC(doubleBuff.back_dc);<br> }<br><br> if(doubleBuff.win_dc) // If we have the window''s device context<br> {<br> // Relese the device context<br> ReleaseDC(doubleBuff.win_hwnd,doubleBuff.win_dc);<br> }<br><br> // Set everything to zero<br> memset(&doubleBuff,0,sizeof(SDBuffer));<br>}<br><br>// Locks the frame rate at "frame_rate"<br>// Returns true when it''s okay to draw, false otherwise<br>bool LockFrameRate(int frame_rate)<br>{<br> static float lastTime = 0.0f;<br> <br> // Get current time in seconds (milliseconds * .001 = seconds)<br> float currentTime = GetTickCount() * 0.001f; <br><br> // Get the elapsed time by subtracting the current time from the last time<br> // If the desired frame rate amount of seconds has passed – return true (ie Blit())<br> if((currentTime - lastTime) > (1.0f / frame_rate))<br> {<br> // Reset the last time<br> lastTime = currentTime; <br> return true;<br> }<br><br> return false;<br>}<br><br>void key()<br>{<br> if(KEYDOWN(VK_ESCAPE))<br> {<br> PostQuitMessage(0);<br> }<br>}<br><br>void check_bullets()<br>{<br> if(KEYDOWN(VK_SPACE))<br> {<br> if(animate(2) == TRUE)<br> { <br> for(int i = 0; i < MAX_BULLETS; i++)<br> {<br> if(bullets.state == BULLET_STATE_OFF)<br> {<br> // You can shoot this &#111;ne<br> bullets.state = BULLET_STATE_ON;<br> break;<br> }<br> }<br> }<br> }<br><br> for(int fire = 0; fire < MAX_BULLETS; fire++)<br> {<br> if(bullets[fire].state == BULLET_STATE_ON)<br> {<br> bullets[fire].y -= 5;<br> }<br><br> if(bullets[fire].y <= 0)<br> {<br> bullets[fire].y = WIN_HGT;<br> bullets[fire].state = BULLET_STATE_OFF;<br> }<br> }<br>}<br><br>void game_init()<br>{<br> for(int i = 0; i < MAX_BULLETS; i++)<br> {<br> bullets.x = 200;<br> bullets.y = WIN_HGT;<br> }<br>}<br><br>bool animate(int bullet_per_second)<br>{<br> static float lastTime = 0.0f;<br> float elapsedTime = 0.0;<br><br> // Get current time in seconds (milliseconds * .001 = seconds)<br> float currentTime = timeGetTime() * 0.001f; <br><br> // Get the elapsed time by subtracting the current time from the last time<br> elapsedTime = currentTime - lastTime;<br><br> // Check if the time since we last checked is over (1 second / framesPerSecond)<br> if( elapsedTime > (1.0f / bullet_per_second) )<br> {<br> // Reset the last time<br> lastTime = currentTime; <br><br> // Return TRUE, to animate the next frame of animation<br> return TRUE;<br> }<br><br> // We don''t animate right now.<br> return FALSE;<br>}<br><br>k, tell me what im doing wrong (if anything).<br>o and if i change the function BitBlt(); to TransparentBlt(); you can shoot about 3 times before the whole program screws up. o and Anonymous Poster FSCK YOU, stop posting S*IT. A**H*LE. </i>
Shouldn''t you test if the bullet is flying before you draw it?You should also keep old_bmp = ... outside that for loop.
Do it like this instead:

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

for(int i = 0; i < MAX_BULLETS; i++)
{
if(bullets.state == BULLET_STATE_ON)
{
BitBlt(doubleBuff.back_dc,bullets.x,bullets.y,27,50,img_dc,<br>0,0,SRCCOPY);<br>}<br>}<br><br><br>That is the &#111;nly bad thing I found in your code, so if TransparentBlit doesn''t work, I have no idea what could cause crashing. </i>
What the bloody hell happened in here?
the only thing that would make it crash is microsofts post that the transparentblt(); function leaks memory in Win98 and NT so....if you have any solutions to this one..hehe...please tell me...of course if your solution is to use BitBlt();...i already thought of that but i want it transparent......so....what to do????? and what do you mean what the bloody hell happened???

This topic is closed to new replies.

Advertisement