GPWiki.org
GPWiki.org
It is currently Sun May 26, 2013 7:03 am

All times are UTC




Post new topic Reply to topic  [ 3 posts ] 
Author Message
 Post subject: DirectX Advice
PostPosted: Sun Jun 17, 2012 4:34 pm 
Rookie

Joined: Sun Jun 17, 2012 4:29 pm
Posts: 2
Hey guys, i'm just starting some actual programming with DirectX, and I was hoping someone could go over my code so far and tell me how well it's organized, and how well I could fix it. Thanks! All the program does so far is display a sprite that moves itself across the screen.

Spoiler: show
Code:
//main source code file. contains windows api code


#include <d3d9.h>
#include <d3dx9.h>
#include <ctime>
#include <cstdio>
#include "dxgraphics.h"
#include "game.h"



//window event callback function
LRESULT WINAPI WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
   switch(msg)
   {
      case WM_DESTROY:
         //release the DIrect3D Device
         if(d3ddev != NULL)
            d3ddev->Release();

         //release the direct3d object'
         if(d3d != NULL)
            d3d->Release();

         //call the "font end" shutdown function
         gameEnd(hWnd);

         //tell windows to kill this program
         PostQuitMessage(0);
         return 0;
   }

   return DefWindowProc(hWnd, msg, wParam, lParam);
}




//helper function to set up the window properties
ATOM MyRegisterClass(HINSTANCE hInstance)
{
   //create the window class structure
   WNDCLASSEX wc;
   wc.cbSize = sizeof(WNDCLASSEX);

   //fill the struct with info
   wc.style = CS_HREDRAW | CS_VREDRAW;
   wc.lpfnWndProc = (WNDPROC)WinProc;
   wc.cbClsExtra = 0;
   wc.cbWndExtra = 0;
   wc.hInstance = hInstance;
   wc.hIcon = NULL;
   wc.hCursor = LoadCursor(NULL, IDC_ARROW);
   wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
   wc.lpszMenuName = NULL;
   wc.lpszClassName = GAMETITLE;
   wc.hIconSm = NULL;

   //set up the window with the class info
   return RegisterClassEx(&wc);
}







//entry point for a windows program
int WINAPI WinMain(HINSTANCE hInstance,
               HINSTANCE hPrevInstance,
               LPSTR lpCmdLine,
               int nCmdShow)
{
   MSG msg;
   HWND hWnd;

   //register the class
   MyRegisterClass(hInstance);

   //set up the screen in windowed or fullscreen mode?
   DWORD style;

   if(FULLSCREEN)
      style = WS_EX_TOPMOST | WS_VISIBLE | WS_POPUP;
   else
      style = WS_OVERLAPPEDWINDOW;
   

   //create a new window
   hWnd = CreateWindow(
      GAMETITLE, //window class
      GAMETITLE, //title bar
      style, //windows style
      CW_USEDEFAULT, // x position of the window
      CW_USEDEFAULT, //y positin of the window
      1280, //width
      720, //height of the window
      NULL, //parent window
      NULL, //menu
      hInstance, //application instance
      NULL ); // window parameters

   //was there an error creating the window?
   if(!hWnd)
      return false;

   //display the window
   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   if(!Init_Direct3D(hWnd, SCREEN_WIDTH, SCREEN_HEIGHT, FULLSCREEN))
      return 0;

   //initialize the game
   if(!gameInit(hWnd))
   {
      MessageBoxA(hWnd, "Error initializing game", "Error", MB_OK);
      return 0;
   }

   //main message loop
   int done = 0;
   while(!done)
   {
      if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
      {
         //look for quit message
         if(msg.message == WM_QUIT)
            done = 1;

         //decode and pass messages on to WndProc
         TranslateMessage(&msg);
         DispatchMessage(&msg);
      }

      else
         //process game loop (else prevents from running after window is closed)
         gameRun(hWnd);
   }

   return msg.wParam;

}


/GAME.h
Code:
#ifndef GAME_H
#define GAME_H



#include <d3d9.h>
#include <d3dx9.h>
#include <d3dx9math.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>

#include "dxgraphics.h"
#include "sprite.h"
#include "player.h"




//application title
#define GAMETITLE "Zombie Game"

//screen set up
#define FULLSCREEN 0 //0 = windowed, 1 = fullscreen
#define SCREEN_WIDTH 1280
#define SCREEN_HEIGHT 720

//function prototypes
int gameInit(HWND);
void gameRun(HWND);
void gameEnd(HWND);


#endif


//GAME.CPP
Code:
#include "game.h"
#include "sprite.h"



//Sprite Texture Objects (Holds full sprite sheet bmp)
LPDIRECT3DTEXTURE9 main_character = NULL; //Sprite sheet for main character
SPRITE mainCharacter;
LPDIRECT3DSURFACE9 back;
LPD3DXSPRITE sprite_handler;

HRESULT result;

//timing variable
long start = GetTickCount();





//initialize the game
int gameInit(HWND hwnd)
{
   //set random number seed
      srand(time(NULL));

   //create sprite handler object
   result = D3DXCreateSprite(d3ddev, &sprite_handler);
   if(result != D3D_OK)
      return 0;


   //load the main character sprite sheet
   main_character = LoadTexture("mainCharacter.bmp", D3DCOLOR_XRGB(255, 0, 255));
   if(main_character == NULL)
      return 0;

   back = LoadSurface("background.bmp", NULL);

   //initializes the sprites properties
   mainCharacter.x = 100;
   mainCharacter.y = 150;
   mainCharacter.width = 64;
   mainCharacter.height = 64;
   mainCharacter.curframe = 0;
   mainCharacter.lastframe = 1;
   mainCharacter.animdelay = 8;
   mainCharacter.animcount = 0;
   mainCharacter.movex = 5;
   mainCharacter.movey = 0;

   return 1;
}



//the main game loop
void gameRun(HWND hwnd)
{
   //make sure the d3d device is valid
   if(d3ddev == NULL)
      return;

   //after short delay, ready for next frame?
   //this keeps the game running at a steady frame rate
   if(GetTickCount() - start >= 30)
   {
      //reset timing
      start = GetTickCount();
      
      //move the sprite
      mainCharacter.x += mainCharacter.movex;
      mainCharacter.y += mainCharacter.movey;

      //warp the sprite on the edges of the screen
      if(mainCharacter.x > SCREEN_WIDTH - mainCharacter.width)
         mainCharacter.x = 0;
      if(mainCharacter.x < 0)
         mainCharacter.x = SCREEN_WIDTH - mainCharacter.width;
      
      //has animation delay reached threshold?
      if(++mainCharacter.animcount > mainCharacter.animdelay)
      {
         //reset counter
         mainCharacter.animcount = 0;

         //animate the sprite
         if(++mainCharacter.curframe > mainCharacter.lastframe)
            mainCharacter.curframe = 0;
      }

   }

   //start rendering
   if(d3ddev->BeginScene())
   {
            //erase the entire backgoround
      d3ddev->StretchRect(back, NULL, backbuffer, NULL, D3DTEXF_NONE);

      //start sprite handler
      sprite_handler->Begin(D3DXSPRITE_ALPHABLEND);

      //create vector to update sprite position
      D3DXVECTOR3 position((float)mainCharacter.x, (float)mainCharacter.y, 0);

      //configure the rect for the source file
      RECT srcRect;
      int columns = 2;

      srcRect.left = (mainCharacter.curframe % columns) * mainCharacter.width;
      srcRect.top = (mainCharacter.curframe / columns) * mainCharacter.height;
      srcRect.right = srcRect.left + mainCharacter.width;
      srcRect.bottom = srcRect.top + mainCharacter.height;

      //draw the sprite
      sprite_handler->Draw(
         main_character,
         &srcRect,
         NULL,
         &position,
         D3DCOLOR_XRGB(255, 255, 255));

      //stop drawing
      sprite_handler->End();

      //stop rendering
      d3ddev->EndScene();
   }

   //display the back buffer on the screen
   d3ddev->Present(NULL, NULL, NULL, NULL);

}


void gameEnd(HWND hwnd)
{
   if(back != NULL)
      back->Release();

   if(sprite_handler != NULL)
      sprite_handler->Release();

      if(main_character != NULL)
      main_character->Release();
}


//SPRITE.H
Code:
#ifndef SPRITE_H
#define SPRITE_H




//sprite structure
typedef struct
{
   int x, y;
   int width, height;
   int movex, movey;
   int curframe, lastframe;
   int animdelay, animcount;
} SPRITE;

//function prototypes
int Collision(SPRITE sprite1, SPRITE sprite2); //collision detection function



#endif


//SPRITE.CPP
Code:
#include "sprite.h"
#include <Windows.h>
#include <d3d9.h>




//collision function. tests for collision
int Collision(SPRITE sprite1, SPRITE sprite2)
{
   RECT rect1;
   rect1.left = sprite1.x + 1;
   rect1.top = sprite1.y + 1;
   rect1.right = sprite1.x + sprite1.width - 1;
   rect1.bottom = sprite1.y + sprite1.height - 1;

   RECT rect2;
   rect2.left = sprite2.x + 1;
   rect2.top = sprite2.y + 1;
   rect2.right = sprite2.x + sprite2.width - 1;
   rect2.bottom = sprite2.y + sprite2.height -1;

   RECT dest;
   return IntersectRect(&dest, &rect1, &rect2);
}




Top
 Profile  
 
 Post subject: Re: DirectX Advice
PostPosted: Sun Jun 17, 2012 6:58 pm 
Rookie

Joined: Sun Jun 17, 2012 4:29 pm
Posts: 2
Whoops. Actually forgot a few files. Here are the other two.

Spoiler: show
//dxgraphics.h
Code:
#ifndef DXGRAPHICS_H
#define DXGRAPHICS_H




//function prototypes
int Init_Direct3D(HWND, int, int, int);
LPDIRECT3DSURFACE9 LoadSurface(char*, D3DCOLOR);
LPDIRECT3DTEXTURE9 LoadTexture(char*, D3DCOLOR);

//variable declarations
extern LPDIRECT3D9 d3d;
extern LPDIRECT3DDEVICE9 d3ddev;
extern LPDIRECT3DSURFACE9 backbuffer;

#endif


//DXGRAPHICS.CPP
Code:
#include <d3d9.h>
#include <d3dx9.h>
#include "dxgraphics.h"

//variable declarations
LPDIRECT3D9 d3d = NULL;
LPDIRECT3DDEVICE9 d3ddev = NULL;
LPDIRECT3DSURFACE9 backbuffer = NULL;




int Init_Direct3D(HWND hwnd, int width, int height, int fullscreen)
{
   //initialize direct3d
   d3d = Direct3DCreate9(D3D_SDK_VERSION);
   if(d3d == NULL)
   {
      MessageBoxA(hwnd, "Error init-ing Direct3D", "Error", MB_OK);
      return 0;
   }

   D3DPRESENT_PARAMETERS d3dpp;
   ZeroMemory(&d3dpp, sizeof(d3dpp));

   d3dpp.Windowed = (!fullscreen);
   d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
   d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
   d3dpp.BackBufferCount = 1;
   d3dpp.BackBufferWidth = width;
   d3dpp.BackBufferHeight = height;
   d3dpp.hDeviceWindow = hwnd;
   d3dpp.EnableAutoDepthStencil = TRUE;
   d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
   d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

   //create the Direct3D device
   d3d->CreateDevice(
      D3DADAPTER_DEFAULT,
      D3DDEVTYPE_HAL,
      hwnd,
      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
      &d3dpp,
      &d3ddev);

   if(d3ddev == NULL)
   {
      MessageBoxA(hwnd, "Error creating Direct3D device", "Error", MB_OK);
      return 0;
   }

   //clear the back buffer to black
   d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);

   //create pointer to the back buffer
   d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);

   return 1;
}



LPDIRECT3DSURFACE9 LoadSurface(char* filename, D3DCOLOR transcolor)
{
   LPDIRECT3DSURFACE9 image = NULL;
   D3DXIMAGE_INFO info;
   HRESULT result;

   //get width and height from bitmap file
   result = D3DXGetImageInfoFromFile(filename, &info);
   if(result != D3D_OK)
      return NULL;

   //create surface
   result = d3ddev->CreateOffscreenPlainSurface(
      info.Width, //width of the surface
      info.Height, //height of the surface
      D3DFMT_X8R8G8B8, //surface format
      D3DPOOL_DEFAULT, //memory pool to use
      &image, //pointer to the surface
      NULL); //reserved(always NULL)

   if(result != D3D_OK)
      return NULL;

   //load surface from file into newly created surface
   result = D3DXLoadSurfaceFromFile(
      image, //destination surface
      NULL, //destionation pallatte
      NULL, //destionation rectangle
      filename, //source filename
      NULL, //source rectangle
      D3DX_DEFAULT, //controls how the image is filtered
      transcolor, //for transparency (0 for none)
      NULL); //source mage info(USUALLY NULL)

   //make sure the file was loaded okay
   if(result != D3D_OK)
      return NULL;

   return image;
}


LPDIRECT3DTEXTURE9 LoadTexture(char *filename, D3DCOLOR transcolor)
{
   //the texture poitner
   LPDIRECT3DTEXTURE9 texture = NULL;

   //the struct for reading bitmap file info
   D3DXIMAGE_INFO info;

   //standard Windows return value
   HRESULT result;

   //get width and height from bitmap file
   result = D3DXGetImageInfoFromFile(filename, &info);
   if(result != D3D_OK)
      return NULL;

   //create the new texture by loading a bitmap image file
   D3DXCreateTextureFromFileEx(
      d3ddev, //Drect3D device object
      filename, //bitmap filename
      info.Width, //bitmap image width
      info.Height, //bitmap image height
      1, //mip map levels(1 for no chain)
      D3DPOOL_DEFAULT, // the type of surface (standard)
      D3DFMT_UNKNOWN, //surface format (default)'
      D3DPOOL_DEFAULT, //memory class for the texture
      D3DX_DEFAULT, //image filter
      D3DX_DEFAULT, //mip filter
      transcolor, //color key for transparency
      &info, //bitmap file info
      NULL, //color palatte
      &texture); //destination texture

   //make sure the bitmap texture was loaded correctly
   if(result != D3D_OK)
      return NULL;

   return texture;
}



Now that's all of them, I swear. Thanks!


Top
 Profile  
 
 Post subject: Re: DirectX Advice
PostPosted: Wed Jun 20, 2012 5:09 pm 
Shake'n'Baker

Joined: Sun May 27, 2012 6:01 pm
Posts: 62
Hi Mr_Fraggs

Firstly, its worth noting your code is Procedural and i suspect your heading for Defensive Programming.

I am an Object Oriented and Design By Contract advocate, but its whatever suits you.

For me, i want my code to "fail hard and fail fast". Code that treats all bugs as fatal, and fails as close to the point of origin as possible.

For me, this is the best way to debug.

From that point of view, there are a few things to limit "soft bugs".

Put const in your function parameters for variables that are by reference and used as inputs.

As for code, your variable declarations are alittle suspect.

While your code is valid, id discourage from over use of global variables. setting start = gettickcount() globally is not wise either. I do not understand the purpose of making your dx objects external either?

use sizeof(varname) instead of sizeof(type), this means if the type changes, you have less code to change. If you use the type and forget to change it somewhere, you can create soft bugs which are hard to catch.

your game loop does not account for gaps that maybe larger than 30ms. Treating ever update the same without taking note of how long its been will cause you problems later on.

You are using C style casting which is not advised as they can have too meanings, a conversion (int)3 or a cast (int)"hello". These C style casts can cause soft bugs which will be a nightmare to catch.

You currently return wParams from one of your functions. From my understanding the meaning of this only makes sense when you know the msg type? msg is continually updated so i suspect this is an error?

When something fails, make sure to return the state of your application back to something usable. you have a "return" after a null checking if, make sure you leave things tidy (put d3d to null etc).

hope this helps
cxzuk


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group