I have been working on this for a while now, and knowing I am not exactly the most efficient programmer in the world I was wondering if I could get some general comments on the way I am doing this before I get in so deep it becomes unfeasable to change it... It's a lot already.
This is the beginning of a Mario 3 clone, written in C++ using Direct3D. Here is an overview of the files used in the project:
And here is the code:
*edit* The spacing got messed up in almost all of these, so ignore wierd spacing issues.
main.cpp
MyD3DGame.h
This is the beginning of a Mario 3 clone, written in C++ using Direct3D. Here is an overview of the files used in the project:
And here is the code:
*edit* The spacing got messed up in almost all of these, so ignore wierd spacing issues.
main.cpp
Code:
#define SCR_WIDTH 1024
#define SCR_HEIGHT 768
#define D3D_PRESENTATION_RATE 65
#include <vector>
#include <fstream>
using namespace std;
#include <MyD3DGame.h>
#include "main.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MakeWindow(hInstance,"Super Mario XL");
InitD3D();
InitDirectInput();
InitTextures();
loadScene();
while(1)
{
//Handle OS Messages
if(PeekMessage(&msg,hwnd,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//Get and Process User Input
GetInput();
if(keys[ESCAPE])break;
//Process Every Game Object
for(int i=0; i<objectVector.size(); i++)
objectVector[i]->process();
//Draw Every Game Object
BeginDrawing();
sky.Blit(0,0);
for(i=0; i<objectVector.size(); i++)
if(objectVector[i]->onScreen())
objectVector[i]->draw();
EndDrawing();
Present();
}
CloseD3D();
//Cleanup to be added
return 0;
}
MyD3DGame.h
Code:
#pragma once
//Includes
#include <Windows.h>
#include <dinput.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <string>
#include <cstdlib>
#include <time.h>
#include <fstream>
using namespace std;
//Defines
#ifndef SCR_WIDTH
#define SCR_WIDTH 1024
#endif
#ifndef SCR_HEIGHT
#define SCR_HEIGHT 768
#endif
#ifndef D3D_PRESENTATION_RATE
#define D3D_PRESENTATION_RATE D3DPRESENT_RATE_DEFAULT
#endif
#define ESCAPE DIK_ESCAPE
#define RETURN DIK_RETURN
#define ENTER DIK_RETURN
#define SPACE DIK_SPACE
#define RIGHT DIK_RIGHT
#define LEFT DIK_LEFT
#define UP DIK_UP
#define DOWN DIK_DOWN
#define PLUS DIK_NUMPADPLUS
#define MINUS DIK_NUMPADMINUS
#define BACKSPACE DIK_BACK
//Direct3D Structures
const DWORD D3DFVF_TLVERTEX = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1;
//const DWORD D3DFVF_TLVERTEX = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1;
struct TLVERTEX
{
float x;
float y;
float z;
float rhw;
D3DCOLOR color;
float u;
float v;
};
//Windows Global Variables
HWND hwnd;
MSG msg;
//DirectInput Global Variables
LPDIRECTINPUT8 lpdi;
LPDIRECTINPUTDEVICE8 keyboard;
LPDIRECTINPUTDEVICE8 mouse;
DIMOUSESTATE mousestate;
unsigned char keys[256];
//Direct3D Global Variables
IDirect3D9* d3d;
IDirect3DDevice9* d3dDevice;
D3DCAPS9 d3dCaps;
D3DPRESENT_PARAMETERS d3dPresent;
IDirect3DVertexBuffer9* vertexBuffer;
int mousex, mousey;
D3DXMATRIX matOrtho;
D3DXMATRIX matIdentity;
//Windows Functions
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hwnd,uMessage,wParam,lParam);
}
void MakeWindow(HINSTANCE hInstance, char* title)
{
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProcedure;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = "change";
wc.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(5));
RegisterClassEx(&wc);
hwnd = CreateWindowEx(WS_EX_TOPMOST, "change", title, NULL, 0, 0, SCR_WIDTH, SCR_HEIGHT, NULL, NULL, hInstance, NULL);
ShowCursor(false);
}
//DirectInput Functions
void InitDirectInput()
{
DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&lpdi, NULL);
lpdi->CreateDevice(GUID_SysKeyboard, &keyboard, NULL);
keyboard->SetDataFormat(&c_dfDIKeyboard);
keyboard->SetCooperativeLevel(hwnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);
keyboard->Acquire();
lpdi->CreateDevice(GUID_SysMouse, &mouse, NULL);
mouse->SetCooperativeLevel(hwnd, DISCL_BACKGROUND | DISCL_EXCLUSIVE);
mouse->SetDataFormat(&c_dfDIMouse);
mouse->Acquire();
}
void GetInput()
{
keyboard->GetDeviceState(sizeof(keys),&keys);
mouse->GetDeviceState(sizeof(DIMOUSESTATE), (LPVOID)&mousestate);
mousex+=mousestate.lX;
mousey+=mousestate.lY;
if(mousex>SCR_WIDTH)mousex=SCR_WIDTH;
else if(mousex<0)mousex=0;
if(mousey>SCR_HEIGHT)mousey=SCR_HEIGHT;
else if(mousey<0)mousey=0;
}
//Direct3D Functions
void InitD3D()
{
d3d = Direct3DCreate9(D3D_SDK_VERSION);
ZeroMemory(&d3dCaps, sizeof(d3dCaps));
d3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps);
ZeroMemory(&d3dPresent,sizeof(d3dPresent));
d3dPresent.SwapEffect = D3DSWAPEFFECT_COPY;
d3dPresent.hDeviceWindow = hwnd;
d3dPresent.BackBufferCount = 1;
//d3dPresent.MultiSampleType = D3DMULTISAMPLE_NONMASKABLE;
//d3dPresent.MultiSampleQuality = 2;
d3dPresent.Windowed = false;
d3dPresent.BackBufferWidth = SCR_WIDTH;
d3dPresent.BackBufferHeight = SCR_HEIGHT;
d3dPresent.BackBufferFormat = D3DFMT_A8R8G8B8;
d3dPresent.EnableAutoDepthStencil = TRUE;
d3dPresent.AutoDepthStencilFormat = D3DFMT_D16;
d3dPresent.FullScreen_RefreshRateInHz = D3D_PRESENTATION_RATE;
d3dPresent.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
//d3dPresent.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
if(d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dPresent, &d3dDevice);
else d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dPresent, &d3dDevice);
d3dDevice->SetVertexShader(NULL);
d3dDevice->SetFVF(D3DFVF_TLVERTEX);
d3dDevice->CreateVertexBuffer(sizeof(TLVERTEX) * 4, NULL, D3DFVF_TLVERTEX, D3DPOOL_MANAGED, &vertexBuffer, NULL);
d3dDevice->SetStreamSource(0, vertexBuffer, 0, sizeof(TLVERTEX));
d3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
d3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
d3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
d3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
d3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
d3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
d3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
D3DXMatrixOrthoLH(&matOrtho, SCR_WIDTH, SCR_HEIGHT, 1.0f, 10.0f);
D3DXMatrixIdentity(&matIdentity);
d3dDevice->SetTransform(D3DTS_PROJECTION, &matOrtho);
d3dDevice->SetTransform(D3DTS_WORLD, &matIdentity);
d3dDevice->SetTransform(D3DTS_VIEW, &matIdentity);
//Setup vertices
TLVERTEX* vertices = NULL;
vertexBuffer->Lock(0, 4 * sizeof(TLVERTEX), (VOID**)&vertices, 0);
vertices[0].color = 0xffffffff;
vertices[0].x = 0.0f;
vertices[0].y = 0.0f;
vertices[0].z = 1.0f;
vertices[0].u = 0.0f;
vertices[0].v = 0.0f;
vertices[1].color = 0xffffffff;
vertices[1].x = 1.0f;
vertices[1].y = 0.0f;
vertices[1].z = 1.0f;
vertices[1].u = 1.0f;
vertices[1].v = 0.0f;
vertices[2].color = 0xffffffff;
vertices[2].x = 1.0f;
vertices[2].y = -1.0f;
vertices[2].z = 1.0f;
vertices[2].u = 1.0f;
vertices[2].v = 1.0f;
vertices[3].color = 0xffffffff;
vertices[3].x = 0.0f;
vertices[3].y = -1.0f;
vertices[3].z = 1.0f;
vertices[3].u = 0.0f;
vertices[3].v = 1.0f;
vertexBuffer->Unlock();
}
void CloseD3D()
{
if(vertexBuffer) vertexBuffer->Release();
if(d3dDevice) d3dDevice->Release();
if(d3d) d3d->Release();
}
void ClearBuffer(){d3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);}
void Present(){d3dDevice->Present(NULL, NULL, NULL, NULL);}
void BeginDrawing(){d3dDevice->BeginScene();}
void EndDrawing(){d3dDevice->EndScene ();}
ID3DXFont* CreateD3DFont(char* fontname, int size)
{
ID3DXFont* font=NULL;
D3DXCreateFont(d3dDevice,size,0,FW_NORMAL,1,false,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,ANTIALIASED_QUALITY,DEFAULT_PITCH|FF_DONTCARE,fontname,&font);
return font;
}
void DrawText(char* text, int x, int y, int width, int height, ID3DXFont* font, int color = 0xFFFFFFFF)
{
RECT fontrect = {x,y,x+width,y+height};
font->DrawText(NULL,text,-1,&fontrect,DT_LEFT|DT_NOCLIP,color);
}
//Texture Class
class Texture
{
private:
char* Filename;
IDirect3DTexture9* d3dTexture;
int width;
int height;
public:
//Constructor:
//Load the image into a IDirect3DTexture9 structure and extract its attributes
Texture(){}
Texture(char* fname){Filename = fname;}
void Init(char* fname)
{
D3DSURFACE_DESC surfaceDesc;
D3DXIMAGE_INFO SrcInfo;
D3DCOLOR colorkey = 0xFFFF00FF;
Filename = fname;
D3DXCreateTextureFromFileEx(d3dDevice, Filename, 0, 0, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_DEFAULT, colorkey, &SrcInfo, NULL, &d3dTexture);
d3dTexture->GetLevelDesc(0, &surfaceDesc);
width = surfaceDesc.Width;
height = surfaceDesc.Height;
}
void Init()
{
D3DSURFACE_DESC surfaceDesc;
D3DXIMAGE_INFO SrcInfo;
D3DCOLOR colorkey = 0xFFFF00FF;
D3DXCreateTextureFromFileEx(d3dDevice, Filename, 0, 0, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_DEFAULT, colorkey, &SrcInfo, NULL, &d3dTexture);
d3dTexture->GetLevelDesc(0, &surfaceDesc);
width = surfaceDesc.Width;
height = surfaceDesc.Height;
}
//Blit the image with rotation
//NOTE: This must be called between calls to BeginDrawing() and EndDrawing()
void Blit(int x, int y, float rotate = 0, D3DCOLOR vertexColor = 0xFFFFFFFF)
{
//D3DCOLOR vertexColor = 0xFFFFFFFF;
RECT rDest;
rDest.left = x;
rDest.right = x + width;
rDest.top = y;
rDest.bottom = y + height;
TLVERTEX* vertices;
//Lock the vertex buffer
vertexBuffer->Lock(0, 0, (void **)&vertices, NULL);
//Set up the vertices
vertices[0].color = vertexColor;
vertices[0].x = (float) rDest.left - 0.5f;
vertices[0].y = (float) rDest.top - 0.5f;
vertices[0].z = 0.0f;
vertices[0].rhw = 1.0f;
vertices[0].u = 0.0f;
vertices[0].v = 0.0f;
vertices[1].color = vertexColor;
vertices[1].x = (float) rDest.right - 0.5f;
vertices[1].y = (float) rDest.top - 0.5f;
vertices[1].z = 0.0f;
vertices[1].rhw = 1.0f;
vertices[1].u = 1.0f;
vertices[1].v = 0.0f;
vertices[2].color = vertexColor;
vertices[2].x = (float) rDest.right - 0.5f;
vertices[2].y = (float) rDest.bottom - 0.5f;
vertices[2].z = 0.0f;
vertices[2].rhw = 1.0f;
vertices[2].u = 1.0f;
vertices[2].v = 1.0f;
vertices[3].color = vertexColor;
vertices[3].x = (float) rDest.left - 0.5f;
vertices[3].y = (float) rDest.bottom - 0.5f;
vertices[3].z = 0.0f;
vertices[3].rhw = 1.0f;
vertices[3].u = 0.0f;
vertices[3].v = 1.0f;
//If the image is rotated apply the rotation
if(rotate != 0)
{
RECT rOrigin;
float centerX, centerY;
centerX = (float)(rDest.left + rDest.right) / 2;
centerY = (float)(rDest.top + rDest.bottom) / 2;
rOrigin.top = rDest.top - (int)(centerY);
rOrigin.bottom = rDest.bottom - (int)(centerY);
rOrigin.left = rDest.left - (int)(centerX);
rOrigin.right = rDest.right - (int)(centerX);
//Rotate vertices about the origin
vertices[0].x = rOrigin.left * cosf(rotate) - rOrigin.top * sinf(rotate);
vertices[0].y = rOrigin.left * sinf(rotate) + rOrigin.top * cosf(rotate);
vertices[1].x = rOrigin.right * cosf(rotate) - rOrigin.top * sinf(rotate);
vertices[1].y = rOrigin.right * sinf(rotate) + rOrigin.top * cosf(rotate);
vertices[2].x = rOrigin.right * cosf(rotate) - rOrigin.bottom * sinf(rotate);
vertices[2].y = rOrigin.right * sinf(rotate) + rOrigin.bottom * cosf(rotate);
vertices[3].x = rOrigin.left * cosf(rotate) - rOrigin.bottom * sinf(rotate);
vertices[3].y = rOrigin.left * sinf(rotate) + rOrigin.bottom * cosf(rotate);
//Translate vertices to proper position
vertices[0].x += centerX;
vertices[0].y += centerY;
vertices[1].x += centerX;
vertices[1].y += centerY;
vertices[2].x += centerX;
vertices[2].y += centerY;
vertices[3].x += centerX;
vertices[3].y += centerY;
}
//Unlock the vertex buffer
vertexBuffer->Unlock();
//Set the texture to the quad and draw to the screen
d3dDevice->SetTexture(0, d3dTexture);
d3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
}
void Blit2(int x, int y)
{
D3DXMATRIX matTranslation;
D3DXMATRIX matScaling;
D3DXMATRIX matTransform;
RECT rDest;
x-=(int)0.5*SCR_WIDTH;
y=0-y;
y+=(int)0.5*SCR_HEIGHT;
rDest.left = x;
rDest.right = x + width;
rDest.top = y;
rDest.bottom = y + height;
D3DXMatrixScaling(&matScaling, (float)(rDest.right - rDest.left), (float)(rDest.bottom - rDest.top), 1.0);
D3DXMatrixTranslation(&matTranslation, (float)x, (float)y, 1.0);
matTransform = matScaling * matTranslation;
d3dDevice->SetTransform(D3DTS_WORLD, &matTransform);
//Set the texture to the quad and draw to the screen
d3dDevice->SetTexture(0, d3dTexture);
d3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
}
void Delete()
{
d3dTexture->Release();
}
int getWidth(){return width;}
int getHeight(){return height;}
};