Currently I'm trying to get a Tiled map to load correctly. I've spent the majority of a day searching for help including on here and I've found nothing. So I decided to go on my instinct, rewrite the code from how I thought it should work, and ignore the Beginning Game Programming book I have, because the chapter involving tile maps is using LPDIRECT3DSURFACE9 instead of a LPDIRECT3DTEXTURE9, and I need the transparency.
So I removed all the extra code, and I'm left with what my gut tells me should render the tile map if it didn't throw an exception. I have spent all day with varying success on rendering the map, which is why I'm stripping it down to bare minimum of what it needs.
Unhandled exception at 0x00893eaa in Platformer.exe: 0xC0000005: Access violation reading location 0x008a9000.
The specific function that this error points to is this:
void BuildGameWorld()
{
int x, y;
LPDIRECT3DTEXTURE9 tiles = nullptr;
//load the texture file
tiles = LoadTexture("tiles_spritesheet.png", D3DCOLOR_XRGB(255, 0, 255));
for(y = 0; y < GAMEWORLDHEIGHT; y++)
{
for(x = 0; x < GAMEWORLDWIDTH; x++)
{
/****** THIS LINE HERE ******/
DrawTile(tiles, MAPDATA[y * MAPWIDTH + x], 2, 70, 70, 12, backbuffer, x * 70, y * 70, D3DCOLOR_XRGB(255,255,255));
}
}
//release the texture file
tiles->Release();
}
The rest of the source code is here
//Filename: MyDirectX.h
#pragma once
//header files
#define WIN32_EXTRA_LEAN
#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <ctime>
#include <iostream>
#include <sstream>
#include <iomanip>
using namespace std;
//libraries
#pragma comment(lib,"winmm.lib")
#pragma comment(lib,"user32.lib")
#pragma comment(lib,"gdi32.lib")
#pragma comment(lib,"dxguid.lib")
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
//program values
extern const string APPTITLE;
extern const int SCREENW;
extern const int SCREENH;
extern bool gameover;
//Direct3D objects
extern LPDIRECT3D9 d3d;
extern LPDIRECT3DDEVICE9 d3ddev;
extern LPDIRECT3DSURFACE9 backbuffer;
extern LPD3DXSPRITE spriteobj;
//Direct3D functions
bool Direct3D_Init(HWND hwnd, int width, int height, bool fullscreen);
void Direct3D_Shutdown();
LPDIRECT3DSURFACE9 LoadSurface(string filename);
void DrawSurface(LPDIRECT3DSURFACE9 dest, float x, float y, LPDIRECT3DSURFACE9 source);
LPDIRECT3DTEXTURE9 LoadTexture(string filename, D3DCOLOR transcolor = D3DCOLOR_XRGB(0,0,0));
//game functions
bool Game_Init(HWND window);
void Game_Run(HWND window);
void Game_End();
void DrawTile(LPDIRECT3DTEXTURE9 source, int frame,int spacing, int width, int height, int columns, LPDIRECT3DSURFACE9 dest, int destx, int desty, D3DCOLOR color);
void BuildGameWorld();
//Filename: MyDirectX.cpp
#include "MyDirectX.h"
#include <iostream>
using namespace std;
//Direct3D variables
LPDIRECT3D9 d3d = NULL;
LPDIRECT3DDEVICE9 d3ddev = NULL;
LPDIRECT3DSURFACE9 backbuffer = NULL;
LPD3DXSPRITE spriteobj;
bool Direct3D_Init(HWND window, int width, int height, bool fullscreen)
{
//initialize Direct3D
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (!d3d) return false;
//set Direct3D presentation parameters
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.hDeviceWindow = window;
d3dpp.Windowed = (!fullscreen);
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.EnableAutoDepthStencil = 1;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight = height;
//create Direct3D device
d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);
if (!d3ddev) return false;
//get a pointer to the back buffer surface
d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
//create sprite object
D3DXCreateSprite(d3ddev, &spriteobj);
return 1;
}
void Direct3D_Shutdown()
{
if (spriteobj) spriteobj->Release();
if (d3ddev) d3ddev->Release();
if (d3d) d3d->Release();
}
void DrawSurface(LPDIRECT3DSURFACE9 dest, float x, float y, LPDIRECT3DSURFACE9 source)
{
//get width/height from source surface
D3DSURFACE_DESC desc;
source->GetDesc(&desc);
//create rects for drawing
RECT source_rect = {0, 0, (long)desc.Width, (long)desc.Height };
RECT dest_rect = { (long)x, (long)y, (long)x+desc.Width, (long)y+desc.Height};
//draw the source surface onto the dest
d3ddev->StretchRect(source, &source_rect, dest, &dest_rect, D3DTEXF_NONE);
}
LPDIRECT3DSURFACE9 LoadSurface(string filename)
{
LPDIRECT3DSURFACE9 image = NULL;
//get width and height from bitmap file
D3DXIMAGE_INFO info;
HRESULT result = D3DXGetImageInfoFromFile(filename.c_str(), &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, //destination palette
NULL, //destination rectangle
filename.c_str(), //source filename
NULL, //source rectangle
D3DX_DEFAULT, //controls how image is filtered
D3DCOLOR_XRGB(0,0,0), //for transparency (0 for none)
NULL); //source image info (usually NULL)
//make sure file was loaded okay
if (result != D3D_OK) return NULL;
return image;
}
LPDIRECT3DTEXTURE9 LoadTexture(std::string filename, D3DCOLOR transcolor)
{
LPDIRECT3DTEXTURE9 texture = NULL;
//get width and height from bitmap file
D3DXIMAGE_INFO info;
HRESULT result = D3DXGetImageInfoFromFile(filename.c_str(), &info);
if (result != D3D_OK) return NULL;
//create the new texture by loading a bitmap image file
D3DXCreateTextureFromFileEx(
d3ddev, //Direct3D device object
filename.c_str(), //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 (from loaded file)
NULL, //color palette
&texture ); //destination texture
//make sure the bitmap textre was loaded correctly
if (result != D3D_OK) return NULL;
return texture;
}
//Filename: MyGame.cpp
#include "MyDirectX.h"
using namespace std;
const string APPTITLE = "2D Platformer";
const int SCREENW = 1024;
const int SCREENH = 768;
//settings for the scroller
const int TILEWIDTH = 70;
const int TILEHEIGHT = 70;
const int MAPWIDTH = 30;
const int MAPHEIGHT = 10;
//scrolling window size
const int WINDOWWIDTH = (SCREENW / TILEWIDTH) * TILEWIDTH;
const int WINDOWHEIGHT = (SCREENH / TILEHEIGHT) * TILEHEIGHT;
//entire gameworld dimensions
const int GAMEWORLDWIDTH = TILEWIDTH * MAPWIDTH;
const int GAMEWORLDHEIGHT = TILEHEIGHT * MAPHEIGHT;
int MAPDATA[MAPWIDTH*MAPHEIGHT] =
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,
10,10,10,10,10,10,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,153,
153,153,153,153,153,153,153,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,153,
153,153,153,153,153,153,153,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,133,0,0,153,
153,153,153,153,153,153,153,10,10,10,10,10,103,103,103,103,103,103,103,103,103,103,103,103,103,10,10,10,10,153,
153,153,153,153,153,153,153,153,153,153,153,153,44,44,44,44,44,44,44,44,44,44,44,44,44,153,153,153,153,153
};
bool Game_Init(HWND window)
{
//initialize Direct3D
Direct3D_Init(window, SCREENW, SCREENH, false);
//create a pointer to the backbuffer
d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
return true;
}
void Game_Run(HWND window)
{
//make sure the Direct3D device is valid
if (!d3ddev) return;
//clear the scene
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,100), 1.0f, 0);
//start rendering
if (d3ddev->BeginScene())
{
spriteobj->Begin(D3DXSPRITE_ALPHABLEND);
BuildGameWorld();
spriteobj->End();
//stop rendering
d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL);
}
//exit when escape key is pressed
if (GetAsyncKeyState(VK_ESCAPE))
gameover = true;
}
void Game_End()
{
//free memory and shut down
Direct3D_Shutdown();
}
void DrawTile(LPDIRECT3DTEXTURE9 source, int frame,int spacing, int width, int height, int columns, LPDIRECT3DSURFACE9 dest, int destx, int desty, D3DCOLOR color)
{
//get dimensions for the tile
RECT r1;
r1.left = ((frame % columns) + spacing * frame) * width;
r1.top = (frame / columns) * height;
r1.right = r1.left + width;
r1.bottom = r1.top + height;
//draw the sprite
spriteobj->Draw(source, &r1, &D3DXVECTOR3(r1.right / 2, r1.bottom / 2, 0), &D3DXVECTOR3(destx, desty, 0), color);
}
void BuildGameWorld()
{
int x, y;
LPDIRECT3DTEXTURE9 tiles = nullptr;
//load the texture file
tiles = LoadTexture("tiles_spritesheet.png", D3DCOLOR_XRGB(255, 0, 255));
for(y = 0; y < GAMEWORLDHEIGHT; y++)
{
for(x = 0; x < GAMEWORLDWIDTH; x++)
{
DrawTile(tiles, MAPDATA[y * MAPWIDTH + x], 2, 70, 70, 12, backbuffer, x * 70, y * 70, D3DCOLOR_XRGB(255,255,255));
}
}
//release the texture file
tiles->Release();
}
//Filename: MyWindows.cpp
#include "MyDirectX.h"
using namespace std;
bool gameover = false;
LRESULT WINAPI WinProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY:
gameover = true;
PostQuitMessage(0);
return 0;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
//initialize window settings
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
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(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = APPTITLE.c_str();
wc.hIconSm = NULL;
RegisterClassEx(&wc);
//create a new window
HWND window = CreateWindow( APPTITLE.c_str(), APPTITLE.c_str(),
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
SCREENW, SCREENH, NULL, NULL, hInstance, NULL);
if (window == 0) return 0;
//display the window
ShowWindow(window, nCmdShow);
UpdateWindow(window);
//initialize the game
if (!Game_Init(window)) return 0;
// main message loop
MSG message;
while (!gameover)
{
if (PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
//process game loop
Game_Run(window);
}
//shutdown
Game_End();
return message.wParam;
}
Your map is declared as
While you are using x, y indexes as
Where