Link to home
Start Free TrialLog in
Avatar of cpu4ghz
cpu4ghz

asked on

Direct Draw, Movement problem.

Hi i'm currently programming a small game (similar to radian 2). and have come across a small problem with moving the ship.

1. I can't move the ship North-west while shooting.
2. I can't move the ship south-west while shooting.

The keys i have used for moving are:

Forward    - W
backward  - S
Left          - A
Right        - D
Shoot      - Space.

I can move forward,backward,left,right,north-east & south east without any problems.

I have tried other keys for shoot, e.g. i tried F1 for shoot and the ship moves in all directions with no problems.

Can someone please tell me why i'm having this problem.

Note: If you see any problems with my code, e.g. style or bad programming practises please let me know =)
Also the way i've gotten the ship to shoot is probably pretty crude :) (didn't put much thought into it, Just wanted to check ways in which i could get the ship to shoot).

#include<stdlib.h>
#include<windows.h>
#include<ddraw.h>
#include<stdio.h>
#include<conio.h>

#define WIN32_LEAN_AND_MEAN
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480    
#define BPP 16               //bits per pixel

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

#define DDRAW_INIT_STRUCT(ddstruct) {memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize = sizeof(ddstruct);}

#define _RGB16BIT565(r,g,b) ((b & 31) + ((g & 63) << 5) + ((r & 31) << 11))

#define MAX_BULLET 15

#define LEFT      0x41
#define RIGHT      0x44
#define UP            0x57
#define DOWN      0x53
#define SHOOT      0x20

HWND Global_hWnd;

LPDIRECTDRAW                  Lpdd = NULL;
LPDIRECTDRAW7                  Lpdd7 = NULL;
PALETTEENTRY                  Palette[256];
LPDIRECTDRAWPALETTE            LpddPalette;
DDSURFACEDESC2                  ddsd;
LPDIRECTDRAWSURFACE7      LpddsPrimary;
LPDIRECTDRAWSURFACE7      LpddsBack;
DDPIXELFORMAT                  ddpixel;

void ShootLeftBullet(int,int,int);
void ShootRightBullet(int,int,int);
void ShootMiddleBullet(int,int,int);

int Window_Closed      = 0;

RECT rMovement;
RECT rLeftBullet[16];
RECT rRightBullet[16];
RECT rMiddleBullet[16];

int MovementXposition = 310;
int MovementYposition = 420;
int BulletVelocity        = 5;
int RateOfFire;
int BulletNumber;

LRESULT CALLBACK WinProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)
{
      PAINTSTRUCT pS;
      HDC                  hDc;

      switch(Msg)
      {                              
      case WM_CREATE:
                              break;
                                          
      case WM_PAINT:
                              hDc = BeginPaint(hWnd,&pS);

                              EndPaint(hWnd,&pS);
                              break;
      case WM_DESTROY:
                              PostQuitMessage(0);
                              break;                               
      }
      return DefWindowProc(hWnd,Msg,wParam,lParam);
}

int Game_Main(void *parms = NULL, int num_parms = 0)
{
      DDBLTFX ddbltfx;   //Used for the bliter
      
      if(Window_Closed)
            return(0);

      if(KEYDOWN(VK_ESCAPE))
      {
            PostMessage(Global_hWnd,WM_CLOSE,0,0);
            Window_Closed = 1;
      }

      //Lock the back buffer Note: this is done so you can write to the back buffer.
      LpddsBack->Lock(NULL,&ddsd,DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);

      UCHAR *Buffer = (UCHAR*)ddsd.lpSurface;

      DDRAW_INIT_STRUCT(ddbltfx);
      
      if(ddsd.lPitch == WINDOW_WIDTH)
      {
            memset(Buffer,0,640*2*480);
      }
      else
      {
            UCHAR* Buffer2 = Buffer;

            for(int Count = 0; Count<WINDOW_HEIGHT;Count++)
            {
                  memset(Buffer2,0,WINDOW_WIDTH*2);
                  Buffer2+=ddsd.lPitch;
            }
      }

      LpddsBack->Unlock(NULL);

      rMovement.left      = MovementXposition;
      rMovement.right      = MovementXposition+20;
      rMovement.top      = MovementYposition;
      rMovement.bottom= MovementYposition+50;

      ddbltfx.dwFillColor = _RGB16BIT565(255,255,255);
      LpddsBack->Blt(&rMovement,
                              NULL,
                              NULL,
                              DDBLT_COLORFILL | DDBLT_WAIT,
                              &ddbltfx);

      ddbltfx.dwFillColor = _RGB16BIT565(255,0,0);
      for(int count = 0; count<MAX_BULLET;count++)
      {

      LpddsBack->Blt(&rLeftBullet[count],
                              NULL,
                              NULL,
                              DDBLT_COLORFILL | DDBLT_WAIT,
                              &ddbltfx);

      LpddsBack->Blt(&rRightBullet[count],
                              NULL,
                              NULL,
                              DDBLT_COLORFILL | DDBLT_WAIT,
                              &ddbltfx);

      LpddsBack->Blt(&rMiddleBullet[count],
                              NULL,
                              NULL,
                              DDBLT_COLORFILL | DDBLT_WAIT,
                              &ddbltfx);
      }
      
      LpddsPrimary->Flip(NULL,DDFLIP_WAIT);

      if(KEYDOWN(LEFT))
      {
            if(MovementXposition>4)
            {
                  MovementXposition-=4;
            }
      }
      if(KEYDOWN(RIGHT))
      {
            if(MovementXposition<615)
            {
                  MovementXposition+=4;
            }
      }
      if(KEYDOWN(UP))
      {
            if(MovementYposition>2)
            {
                  MovementYposition-=4;
            }
      }
      if(KEYDOWN(DOWN))
      {
            if(MovementYposition<425)
            {
                  MovementYposition+=4;
            }
      }

      if(RateOfFire>=10)
      {
            if(KEYDOWN(SHOOT))
            {
                  ShootLeftBullet(MovementXposition,MovementYposition,BulletNumber);
                  ShootRightBullet(MovementXposition,MovementYposition,BulletNumber);
                  ShootMiddleBullet(MovementXposition,MovementYposition,BulletNumber);

                  RateOfFire=0;
                  if(BulletNumber<MAX_BULLET)
                  {
                        BulletNumber++;
                  }
                  else
                  {
                        BulletNumber=0;
                  }
            }
      }
      
      for(int Count1=0;Count1<MAX_BULLET;Count1++)
      {
            if(rLeftBullet[Count1].top>0)
            {
                  rLeftBullet[Count1].top-=8;
                  rLeftBullet[Count1].bottom-=8;

                  rRightBullet[Count1].top-=8;
                  rRightBullet[Count1].bottom-=8;

                  rMiddleBullet[Count1].top-=8;
                  rMiddleBullet[Count1].bottom-=8;
            }
            else
            {
                  rLeftBullet[Count1].top                  = 0;
                  rLeftBullet[Count1].bottom            = 0;

                  rRightBullet[Count1].top            = 0;
                  rRightBullet[Count1].bottom            = 0;
                  
                  rMiddleBullet[Count1].top            = 0;
                  rMiddleBullet[Count1].bottom      = 0;
            }
      }

      RateOfFire++;

      Sleep(10);

      return(1);
}

void ShootLeftBullet(int Xpos,int Ypos,int BulletNumber)
{
      rLeftBullet[BulletNumber].left            = Xpos;
      rLeftBullet[BulletNumber].right            = Xpos+1;
      rLeftBullet[BulletNumber].top            = Ypos;
      rLeftBullet[BulletNumber].bottom      = Ypos+10;
}

void ShootRightBullet(int Xpos,int Ypos,int BulletNumber)
{
      rRightBullet[BulletNumber].left            = Xpos+19;
      rRightBullet[BulletNumber].right      = Xpos+20;
      rRightBullet[BulletNumber].top            = Ypos;
      rRightBullet[BulletNumber].bottom      = Ypos+10;
}

void ShootMiddleBullet(int Xpos,int Ypos,int BulletNumber)
{
      rMiddleBullet[BulletNumber].left      = Xpos+9;
      rMiddleBullet[BulletNumber].right      = Xpos+11;
      rMiddleBullet[BulletNumber].top            = Ypos;
      rMiddleBullet[BulletNumber].bottom      = Ypos+10;
}

int Game_Init(void *parms = NULL, int num_parms = 0)
{
      srand(GetTickCount());

      ShowCursor(false);

      if(FAILED(DirectDrawCreate(NULL,&Lpdd,NULL)))
      {
            return(0);
      }


      if(FAILED(Lpdd->QueryInterface(IID_IDirectDraw7,(LPVOID*)&Lpdd7)))
      {
            return(0);
      }

      Lpdd->Release();
      Lpdd = NULL;

      if(FAILED(Lpdd7->SetCooperativeLevel(Global_hWnd,
                                   DDSCL_FULLSCREEN |
                                             DDSCL_EXCLUSIVE |
                                             DDSCL_ALLOWREBOOT|
                                             DDSCL_ALLOWMODEX)))/*Note: i don't think that it is required
                                                                            to addd DDSCL_ALLOWMODEX, as this only allows
                                                                              you to use 320*240, & no one uses this....*/
      {
            return(0);
      }

      Lpdd7->SetDisplayMode(WINDOW_WIDTH,WINDOW_HEIGHT,BPP,0,0);

      DDRAW_INIT_STRUCT(ddsd);

      ddsd.dwFlags      = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;

      ddsd.dwBackBufferCount = 1;

      ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |DDSCAPS_COMPLEX;

      if(FAILED(Lpdd7->CreateSurface(&ddsd,&LpddsPrimary,NULL)))
      {
            return(0);
      }

      ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;

      LpddsPrimary->GetAttachedSurface(&ddsd.ddsCaps,&LpddsBack);
      
      return(1);
}


int Game_Shutdown(void *parms = NULL, int num_parms = 0)
{
      if(LpddsPrimary)
      {
            LpddsPrimary->Release();
            LpddsPrimary = NULL;
      }

      if(LpddPalette)
      {
            LpddPalette->Release();
            LpddPalette = NULL;
      }

      if(Lpdd7)
      {
            Lpdd7->Release();
            Lpdd7 = NULL;
      }
      return(1);
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
      WNDCLASSEX WndClass;
      HWND hWnd;
      MSG Msg;

      WndClass.cbSize                  = sizeof(WNDCLASSEX);
      WndClass.hbrBackground      = (HBRUSH)GetStockObject(BLACK_BRUSH);
      WndClass.hCursor            = LoadCursor(NULL,IDC_ARROW);
      WndClass.hIcon                  = LoadIcon(NULL,IDI_ERROR);
      WndClass.hIconSm            = LoadIcon(NULL,IDI_ERROR);
      WndClass.cbClsExtra            = 0;
      WndClass.cbWndExtra            = 0;
      WndClass.hInstance            = hInstance;
      WndClass.lpszMenuName      = NULL;
      WndClass.lpszClassName      = "Class1";
      WndClass.lpfnWndProc      = WinProc;
      WndClass.style                  = CS_DBLCLKS | CS_VREDRAW |
                                  CS_HREDRAW | CS_OWNDC;

      if(!RegisterClassEx(&WndClass))
      {
            MessageBox(NULL,"Could not Register Class.","Error",MB_OK |MB_ICONERROR);
            return(-1);
      }

      /*This will create the window, and defines window properties*/
      if(!(hWnd = CreateWindowEx(NULL,
                             "Class1",
                                     "Practise Window",
                                     WS_POPUP | WS_VISIBLE,
                             350,
                                     150,
                                     WINDOW_WIDTH,
                                     WINDOW_HEIGHT,
                                     NULL,
                                     NULL,
                                 hInstance,
                                     NULL)))
      {
            MessageBox(NULL,"Could not Create Window.","Error",MB_OK|MB_ICONERROR);
      }

      Global_hWnd = hWnd;

      Game_Init();
      
      while(1)
      {
            if(PeekMessage(&Msg,NULL,0,0,PM_REMOVE))
            {
                  if(Msg.message==WM_QUIT)
                  {      
                        break;
                  }
                  TranslateMessage(&Msg);
                  DispatchMessage(&Msg);      
            }

            Game_Main();

      }
      Game_Shutdown();

      return Msg.wParam;
}







ASKER CERTIFIED SOLUTION
Avatar of davebytes
davebytes
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial