I'm trying to create a RPG game and for a test I thought I might draw the same tile(20x20 pixels) over the whole window(720x480), it works and renders the tiles fine but the amount of memory and CPU power it requires is way too much. It roughly allocates 400MB and uses roughly 35% of the CPU, the image is a .bmp file format and it's file size is 856 bytes. I use new on each object and add each one to a vector, I also delete each one for clear up. Here's the code:
This the main class
main.h
#ifndef MAIN_H
#define MAIN_H
#include <vector>
#include <d3d9.h>
#include "Keyboard.h"
#include "Mouse.h"
#include "Graphics.h"
#include "Tile.h"
#include "Timer.h"
#define WIDTH 720
#define HEIGHT 480
class Main
{
public:
Main(HWND hWnd, const KeyboardServer& kServer, const MouseServer& mServer);
~Main();
public:
void Go();
void ComposeFrame();
public:
IDirect3DDevice9* device;
private:
Graphics gfx;
KeyboardClient kbd;
MouseClient mouse;
Timer time;
};
#endif
main.cpp
#include "Main.h"
std::vector<Tile*> tileList;
Main::Main(HWND hWnd, const KeyboardServer& kServer, const MouseServer& mServer)
:
gfx(hWnd),
kbd(kServer),
mouse(mServer)
{
device = gfx.device;
for (int y = 0; y < HEIGHT; y += 20)
{
for (int x = 0; x < WIDTH; x += 20)
{
// Set the current index for the map and add it to the tile list
Tile* temp = new Tile;
temp->Init(x, y);
tileList.push_back(temp);
}
}
for (int x = 0; x < tileList.size(); x++){
tileList[x]->Create(device);
}
}
Main::~Main()
{}
void Main::Go(){
gfx.beginFrame();
ComposeFrame();
gfx.endFrame();
}
void Main::ComposeFrame(){
for (int x = 0; x < tileList.size(); x++){
tileList[x]->Draw();
}
}
Here is the tile class
tile.h
#pragma once
#include <d3dx9.h>
#include <string>
#include "Keyboard.h"
#include "Mouse.h"
#include "Tile.h"
class Tile
{
public:
Tile();
~Tile();
public:
void Draw();
void Create(IDirect3DDevice9* device);
void Init(int x, int y);
private:
LPDIRECT3DTEXTURE9 tex;
LPD3DXSPRITE sprite;
D3DXVECTOR3 position;
D3DCOLOR colour;
int width, height, x, y;
char filePath[50];
};
tile.cpp
#include "Tile.h"
Tile::Tile()
{
colour = D3DCOLOR_ARGB(255, 255, 255, 255);
width = 20;
height = 20;
position.x = 0;
position.y = 0;
position.z = 0;
strcpy(filePath, "Grass.bmp");
}
Tile::~Tile()
{}
void Tile::Init(int x, int y){
position.x = x;
position.y = y;
}
void Tile::Create(IDirect3DDevice9* device){
D3DXCreateTextureFromFileEx(device, filePath, width, height, 1, D3DPOOL_DEFAULT,
D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &tex);
//Attempt to create the sprite
D3DXCreateSprite(device, &sprite);
}
void Tile::Draw(){
sprite->Begin(D3DXSPRITE_ALPHABLEND); //method of drawing
sprite->Draw(tex, NULL, NULL, &position, colour); //actually drawing
sprite->End(); //ending the drawing
}
I just want to make it so the game doesn't allocate as much memory and use much less of CPU. Sorry if I have used code incorrectly it is my first time for programming a game, advice would be appreciated, thank you.
EDIT This is the window cpp
Window.cpp
#include <Windows.h>
#include "Keyboard.h"
#include "Mouse.h"
#include "Main.h"
#define WIDTH 720
#define HEIGHT 480
static KeyboardServer kServ;
static MouseServer mServ;
#define VK_W 87 //W keycode
#define VK_A 65 //A keycode
#define VK_S 83 //S keycode
#define VK_D 68 //D keycode
LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
// ************ KEYBOARD MESSAGES ************ //
case WM_KEYDOWN:
switch (wParam)
{
case VK_UP:
kServ.OnUpPressed();
break;
case VK_DOWN:
kServ.OnDownPressed();
break;
case VK_LEFT:
kServ.OnLeftPressed();
break;
case VK_RIGHT:
kServ.OnRightPressed();
break;
case VK_SPACE:
kServ.OnSpacePressed();
break;
case VK_RETURN:
kServ.OnEnterPressed();
break;
case VK_W:
kServ.OnWPressed();
break;
case VK_A:
kServ.OnAPressed();
break;
case VK_S:
kServ.OnSPressed();
break;
case VK_D:
kServ.OnDPressed();
break;
case VK_ESCAPE:
kServ.OnEscPressed();
break;
case VK_SHIFT:
kServ.OnShiftPressed();
break;
}
break;
case WM_KEYUP:
switch (wParam)
{
case VK_UP:
kServ.OnUpReleased();
break;
case VK_DOWN:
kServ.OnDownReleased();
break;
case VK_LEFT:
kServ.OnLeftReleased();
break;
case VK_RIGHT:
kServ.OnRightReleased();
break;
case VK_SPACE:
kServ.OnSpaceReleased();
break;
case VK_RETURN:
kServ.OnEnterReleased();
break;
case VK_W:
kServ.OnWReleased();
break;
case VK_A:
kServ.OnAReleased();
break;
case VK_S:
kServ.OnSReleased();
break;
case VK_D:
kServ.OnDReleased();
break;
case VK_SHIFT:
kServ.OnShiftReleased();
break;
}
break;
// ************ END KEYBOARD MESSAGES ************ //
// ************ MOUSE MESSAGES ************ //
case WM_MOUSEMOVE:
{
int x = (short)LOWORD(lParam);
int y = (short)HIWORD(lParam);
if (x > 0 && x < WIDTH && y > 0 && y < HEIGHT)
{
mServ.OnMouseMove(x, y);
if (!mServ.IsInWindow())
{
SetCapture(hWnd);
mServ.OnMouseEnter();
}
}
else
{
if (wParam & (MK_LBUTTON | MK_RBUTTON))
{
x = max(0, x);
x = min(x - 1, x);
y = max(0, y);
y = min(y - 1, y);
mServ.OnMouseMove(x, y);
}
else
{
ReleaseCapture();
mServ.OnMouseLeave();
mServ.OnLeftReleased();
mServ.OnRightReleased();
}
}
}
break;
case WM_LBUTTONDOWN:
mServ.OnLeftPressed();
break;
case WM_RBUTTONDOWN:
mServ.OnRightPressed();
break;
case WM_LBUTTONUP:
mServ.OnLeftReleased();
break;
case WM_RBUTTONUP:
mServ.OnRightReleased();
break;
// ************ END MOUSE MESSAGES ************ //
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, INT)
{
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0, 0,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
"Win32Window", NULL };
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
RegisterClassEx(&wc);
RECT wr;
GetClientRect(GetDesktopWindow(), &wr); //gets size of window and sets it to wr RECT
wr.left = (wr.right / 2) - (WIDTH / 2);
wr.top = (wr.bottom / 2) - (HEIGHT / 2);
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
HWND hWnd = CreateWindowW(L"Win32Window", L"Win32Window",
WS_OVERLAPPEDWINDOW, wr.left, wr.top, WIDTH, HEIGHT,
NULL, NULL, wc.hInstance, NULL);
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);
Main *main;
MSG msg;
main = new Main(hWnd, kServ, mServ);
ZeroMemory(&msg, sizeof(msg));
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
main->Go();
}
}
UnregisterClass("Win32Window", wc.hInstance);
return 0;
}
Sleep(0.033);
after themain->Go();
. I'm not too familiar with the windows way of doing things so there might be a better place to make that call. You might want to take a peek there to get a bit more info on this particular issue: gameprogrammingpatterns.com/game-loop.html#take-a-little-nap – Alexandre Vaillancourt Mar 9 at 21:37