Archived

This topic is now archived and is closed to further replies.

burntgorilla

Attacking Issues

Recommended Posts

Hi, being pretty new to games programming, I got myself a book (Isometric with DirectX 7.0). I took one of the examples (19_2), and decided to add a small attacking feature. Basically, all it does is delete the unit from the team list and renders a tile over it. However, when I compile and run it in VC++, when I go to attack, the game closes and returns to the VC++ scrren. I ran the actual .exe, but attacking in this does nothing. The complete code is here: http://uk.briefcase.yahoo.com/ The username is burntgorilla and the password is kietas Hope you can help - I'm not sure what I'm doing wrong. --------------- |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| **************************************************************** I'll try to answer here- it seems better place to be honest, I think reason of closing can bet sudden exit from function for whatever reason. try running program in debug(ging) mode so you may get more info. Hinghly likely is (may be) memory problem, since when you hit "wrong place" in memory result can be unpredictable. so check your pointers, make breakpoints, debug and HAVE FUN ! [edited by - burntgorilla on January 22, 2003 9:03:14 PM]

Share this post


Link to post
Share on other sites
Firstly I really don''t recommend giving out that information to people, you should just of posted the code in a nice source box on here. People can now abuse your yahoo account. I can''t actually help you, but look at what you have changed. What could make it exit the program? Post the bit of code you added into this forum and..

GO CHANGE YOUR PASSWORD ON THAT ACCOUNT NOW!

=*=
If things seem bad, think that they can get a whole load worse, and they don''t seem so bad anymore

=*=

Share this post


Link to post
Share on other sites
Find out in WHICH command the error lies (ie the command that is executed when the program crashed). Two ways to do this : 1°/ write to a file the name of the command being executed. 2°/ comment out commands until it works.

Once you have found out what command is causing the crash, begin wondering about what this command implies : is all required data initialized? are you using a correct pointer? For all data that is used in this command, check if it is correct :
-> has it been initialized?
-> does it still exist? (you could have deleted it)
-> is it of the type required? (check the documentation for API calls)...

ToohrVyk
-------------
Extatica - a free 3d game engine
Available soon!
Click here to learn more

Share this post


Link to post
Share on other sites
Well, to begin with, I only made that account for putting up the code, so I don''t really mind what happens to it. I didn''t post just the code, since I wasn''t sure which file was the error. I''ll include it here anyway. Debugging always seems to crash the PC, which makes things a little harder. Running the actual .exe doesn''t crash the program, the selected unit still flashes, etc., the commands to delete the unit don''t seem to do anything. I can''t seem to get any programs to open at the moment, so I''m restart and post the code (don''t ask why it did that, I don''t know).

Share this post


Link to post
Share on other sites
Hand-debugging always works. Just work in a "scientist" fashion : experiment with your code (comment in/out lines) until it works/stops working, and then you know the last parameter you changed was responsible for the crash.

ToohrVyk
-------------
Extatica - a free 3d game engine
Available soon!
Click here to learn more

Share this post


Link to post
Share on other sites
Well, there only is two lines of code releating to the attacking, and I''ve tried different combinations of commenting them out, but no luck. The units are stored in STD list (sorry if that''s incorrect), and I was wondering if it was something to do with them, although to me it seems unlikely.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Make sure that you don''t use an iterator after erasing what it was pointing to. The standard template library''s list.erase function returns an iterator that points to the element after the one that was erased. The iterator that was used as a parameter to erase becomes invalid after the call to erase, and using it can cause problems like the one you described (the program crashing).

Share this post


Link to post
Share on other sites
Well, remove is used instead of erase, so prehaps it isn''t a STD list. Though it does say... I hate it when someone makes all these stupid suggestions on a forum, and now I''m doing it...
Hre''s the code that deletes the unit, BTW.

mlMap[pEnemyUnit->ptPosition.x][pEnemyUnit->ptPosition.y].ulUnitList.remove(pEnemyUnit);

Share this post


Link to post
Share on other sites
If the removal of neither of those lines solved the problem, then the problem may :
-> lie in another part of the program
-> be caused by more than one call (in which case you have 2 bugs, not 1).

Question :
-> what is the last command executed by your program?
-> what is the command that should have been called, but the program crashed before it ended?

ToohrVyk
-------------
Extatica - a free 3d game engine
Available soon!
Click here to learn more

Share this post


Link to post
Share on other sites
But I thought I''d make it nice and simple for you, you worthless little peon.

The last command bit could be a little tricky. The different gamestates are held in a switch statement, for the sake of simplicity. So the last command by the program would be the Esc. key. The last command from the Attack case should be to change the gamestate to GS_IDLE, but it never seems to make it there. I''m not sure what the game actually gets to, since the debugger always crashes. Here''s the code anyway:


  

//////////////////////////////////////////////////////////////////////////////

//INCLUDES

//////////////////////////////////////////////////////////////////////////////

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include "DDFuncs.h"
#include "TileSet.h"
#include "IsoHexCore.h"
#include "IsoRenderer.h"
#include <list>

//////////////////////////////////////////////////////////////////////////////

//DEFINES

//////////////////////////////////////////////////////////////////////////////

//name for our window class

#define WINDOWCLASS "ISOHEX19"
//title of the application

#define WINDOWTITLE "IsoHex 19-2"

const int MAPWIDTH=40;
const int MAPHEIGHT=40;

//gamestates

const int GS_IDLE=0;//waits for a keypress

const int GS_STARTTURN=1;//starts a players turn

const int GS_ENDTURN=2;//ends a players turn

const int GS_NEXTUNIT=3;//finds the next unit to move

const int GS_MOVE=4; // movement

const int GS_NULLMOVE=5;//tells a unit to not move

const int GS_SKIPMOVE=6;//temporarily skip the move

const int GS_HOLDPOSITION=7;//fortify

const int GS_CLICKSELECT=8;//when a click occurs, this gamestate is selected

const int GS_CLICKCENTER=9;//click on a map location with none of the players units

const int GS_CLICKSTACK=10;//click on a map location with at least two of the players units

const int GS_PICKUNIT=11;//pick unit from the selection window

const int GS_BUILD=12;// handles all building

const int GS_ATTACK=13;//handles attacking


//////////////////////////////////////////////////////////////////////////////

//TYPEDEFS/STRUCTS

//////////////////////////////////////////////////////////////////////////////

struct UnitInfo//unit information structure

{
int iType;//type of unit

int iTeam;//team to which the unit belongs

bool bTeamBuild;//has team built yet?

POINT ptPosition;//map location of the unit

int iMovePoints;//number of movepoints left this turn

bool bHolding;//true if holding position

int iHealthPoints;
};

typedef UnitInfo *PUNITINFO;//pointer type alias for unitinfo


typedef std::list<PUNITINFO> UNITLIST;//list of units

typedef std::list<PUNITINFO>::iterator UNITLISTITER;//iterator for unit list


//////////////////////////////////////////////////////////////////////////////

//PROTOTYPES

//////////////////////////////////////////////////////////////////////////////

bool Prog_Init();//game data initalizer

void Prog_Loop();//main game loop

void Prog_Done();//game clean up


//minimap functions

void SetupMiniMap();//does initial setup of the minimap

void UpdateMiniMap();//updates the minimap to reflect current game status

void RedrawMiniMap();//redraws the minimap to reflect current gamestate

void ShowMiniMap();//shows the minimap on-screen

void DestroyMiniMap();//cleans up the minimap


//////////////////////////////////////////////////////////////////////////////

//GLOBALS

//////////////////////////////////////////////////////////////////////////////

HINSTANCE hInstMain=NULL;//main application handle

HWND hWndMain=NULL;//handle to our main window


//game state

int iGameState=GS_IDLE;
int iCurrentTeam=0;//the team whose turn it currently is


//directdraw

LPDIRECTDRAW7 lpdd=NULL;
LPDIRECTDRAWSURFACE7 lpddsMain=NULL;
LPDIRECTDRAWSURFACE7 lpddsBack=NULL;
LPDIRECTDRAWSURFACE7 lpddsFrame=NULL;
LPDIRECTDRAWSURFACE7 lpddsMiniMap=NULL;//minimap surface


//tilesets

CTileSet tsBack;//background

CTileSet tsUnit;//unit

CTileSet tsShield;//shields

CTileSet tsPressEnter;//press enter text

CTileSet tsMiniMap;//minimap tileset

CTileSet tsBarrack;//barrack tile


//offsets for the shields

POINT ptShieldOffset[2];//one for each unit


//isohexcore components

CTilePlotter TilePlotter;//plotter

CTileWalker TileWalker;//walker

CScroller Scroller;//scroller

CMouseMap MouseMap;//mousemap

CRenderer Renderer;//renderer


//minimap components

CTilePlotter MiniTilePlotter;
CScroller MiniScroller;

POINT ptScroll;//keep track of how quickly we scroll

POINT ptClick;//keep track of the clicked position


//map location structure

struct MapLocation
{
UNITLIST ulUnitList;//list of units on this map location

};

MapLocation mlMap[MAPWIDTH][MAPHEIGHT];//map array

UNITLIST MainUnitList;//unit list for all units

UNITLIST TeamUnitList;//unit list for teams(Current Players Turn)

PUNITINFO pCurrentUnit;//current unit being moved

bool bFlash;//controls the flashing of the current unit

ISODIRECTION idMoveUnit;//direction in which the unit will be moved

bool bMovedUnit;//indicates whether or not a unit has been moved by the current player this turn

PUNITINFO pEnemyUnit;//the enemy



//unit selection variables(for selecting stacks of units)

RECT rcSelectWindow;//the selection window

POINT ptCellSize;//size of selection cell

PUNITINFO SelectUnitList[20];//unit selection list (max of 20 units)

POINT ptUnitOffset;//offset for placing units in the selection window

DWORD dwSelectWindowColor;//color for the selection window


//minimap array

int* MiniMap;//current minimap array


//rendering functionprototype

void RenderFunc(LPDIRECTDRAWSURFACE7 lpddsDst,RECT* rcClip,int xDst,int yDst,int xMap,int yMap);


//////////////////////////////////////////////////////////////////////////////

//WINDOWPROC

//////////////////////////////////////////////////////////////////////////////

LRESULT CALLBACK TheWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
//which message did we get?

switch(uMsg)
{
case WM_LBUTTONDOWN://beginning of click-select

{
//process differently, depending on gamestate

switch(iGameState)
{
case GS_IDLE:
{
//grab the mouse position

POINT ptCursor;
ptCursor.x=LOWORD(lParam);
ptCursor.y=HIWORD(lParam);
//use the mousemap to get click position

ptClick=MouseMap.MapMouse(ptCursor);
}break;
}
return(0);//handled

}break;
case WM_LBUTTONUP://end of click-select

{
//process differently, depending on gamestate

switch(iGameState)
{
case GS_IDLE:
{
//grab the mouse position

POINT ptCursor;
ptCursor.x=LOWORD(lParam);
ptCursor.y=HIWORD(lParam);
//use the mousemap to get click position

POINT ptMap=MouseMap.MapMouse(ptCursor);
//check map position against ptClick

if(ptMap.x==ptClick.x && ptMap.y==ptClick.y)
{
//set gamestate to GS_CLICKSELECT

iGameState=GS_CLICKSELECT;
}
}break;
case GS_PICKUNIT:
{
//grab the mouse position

POINT ptMouse;
ptMouse.x=LOWORD(lParam);
ptMouse.y=HIWORD(lParam);
//check to see if the click was within the select window

if(PtInRect(&rcSelectWindow,ptMouse))
{
//within the select window

//determine which cell was clicked

ptMouse.x-=rcSelectWindow.left;//subtract top left of the window

ptMouse.y-=rcSelectWindow.top;
ptMouse.x/=ptCellSize.x;//divide by cellsize

ptMouse.y/=ptCellSize.y;
int cellnum=ptMouse.x+5*ptMouse.y;//calc cell number

//check for a NULL

if(SelectUnitList[cellnum]==NULL)
{
//empty cell

//do nothing

return(0);
}
else
{
//non-empty cell

//check if the unit has any movement points left

if(SelectUnitList[cellnum]->iMovePoints==0)
{
//no movement points

//do nothing

return(0);
}
else
{
//check for holding position

if(SelectUnitList[cellnum]->bHolding)
{
//set holding to false

SelectUnitList[cellnum]->bHolding=false;
}
//remove this unit from the team list

TeamUnitList.remove(SelectUnitList[cellnum]);
//re-add this unit to the team list at the beginning

TeamUnitList.push_front(SelectUnitList[cellnum]);
//select next unit

iGameState=GS_NEXTUNIT;
//add entire screen to update rect

Renderer.AddRect(Scroller.GetScreenSpace());
}
}
}
else
{
//outside of select window

iGameState=GS_NEXTUNIT;
}
}break;
}
return(0);//handled

}break;
case WM_KEYDOWN:
{
switch(wParam)
{
case VK_ESCAPE:
{
DestroyWindow(hWndMain);
return(0);
}break;
case VK_RETURN://at end of turn, if no unit has been moved

{
if(iGameState==GS_IDLE && pCurrentUnit==NULL) iGameState=GS_ENDTURN;
return(0);
}break;
case VK_SPACE://do not move unit

{
if(iGameState==GS_IDLE && pCurrentUnit!=NULL) iGameState=GS_NULLMOVE;//only respond when gamestate is GS_IDLE;

return(0);
}break;
case ''W''://wait to move this unit later

{
if(iGameState==GS_IDLE && pCurrentUnit!=NULL) iGameState=GS_SKIPMOVE;//skip this unit for now

}break;
case ''H''://tell unit to hold position

{
if(iGameState==GS_IDLE && pCurrentUnit!=NULL) iGameState=GS_HOLDPOSITION;//tell the unit to hold position

}break;
case ''C''://center on the current unit

{
if(iGameState==GS_IDLE && pCurrentUnit!=NULL)
{
//plot the current unit''s world position

POINT ptPlot=TilePlotter.PlotTile(pCurrentUnit->ptPosition);
//adjust by half width and height of the screen

ptPlot.x-=(Scroller.GetScreenSpaceWidth()/2);
ptPlot.y-=(Scroller.GetScreenSpaceHeight()/2);
//set the anchor

Scroller.SetAnchor(&ptPlot);
//add update rect to renderer

Renderer.AddRect(Scroller.GetScreenSpace());
}
}break;
case ''B''://build a barrack

{
if(iGameState==GS_IDLE && pCurrentUnit!=NULL) iGameState=GS_BUILD;//build the barrack

}break;
case VK_NUMPAD8:
case VK_UP:
{
if(iGameState==GS_IDLE && pCurrentUnit!=NULL)//gamestate must be GS_IDLE

{
idMoveUnit=ISO_NORTH;//move to the north

POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position

if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking

{
if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty

{
iGameState=GS_MOVE;//set the unit in motion

}
else
{
UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list

PUNITINFO pUnitInfo=*iter;//get the unit from the list

if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team

{
iGameState=GS_MOVE;
}
else
{
pUnitInfo = pEnemyUnit;
iGameState=GS_ATTACK;
}
}
}
}
}break;
case VK_NUMPAD9:
case VK_PRIOR:
{
if(iGameState==GS_IDLE && pCurrentUnit!=NULL)//gamestate must be GS_IDLE

{
idMoveUnit=ISO_NORTHEAST;//move to the north

POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position

if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking

{
if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty

{
iGameState=GS_MOVE;//set the unit in motion

}
else
{
UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list

PUNITINFO pUnitInfo=*iter;//get the unit from the list

if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team

{
iGameState=GS_MOVE;
}
else
{
pUnitInfo = pEnemyUnit;
iGameState=GS_ATTACK;
}
}
}
}
}break;
case VK_NUMPAD6:
case VK_RIGHT:
{
if(iGameState==GS_IDLE && pCurrentUnit!=NULL)//gamestate must be GS_IDLE

{
idMoveUnit=ISO_EAST;//move to the north

POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position

if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking

{
if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty

{
iGameState=GS_MOVE;//set the unit in motion

}
else
{
UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list

PUNITINFO pUnitInfo=*iter;//get the unit from the list

if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team

{
iGameState=GS_MOVE;
}
else
{
pUnitInfo = pEnemyUnit;
iGameState=GS_ATTACK;
}
}
}
}
}break;
case VK_NUMPAD3:
case VK_NEXT:
{
if(iGameState==GS_IDLE && pCurrentUnit!=NULL)//gamestate must be GS_IDLE

{
idMoveUnit=ISO_SOUTHEAST;//move to the north

POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position

if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking

{
if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty

{
iGameState=GS_MOVE;//set the unit in motion

}
else
{
UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list

PUNITINFO pUnitInfo=*iter;//get the unit from the list

if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team

{
iGameState=GS_MOVE;
}
else
{
pUnitInfo = pEnemyUnit;
iGameState=GS_ATTACK;
}
}
}
}
}break;
case VK_NUMPAD2:
case VK_DOWN:
{
if(iGameState==GS_IDLE && pCurrentUnit!=NULL)//gamestate must be GS_IDLE

{
idMoveUnit=ISO_SOUTH;//move to the north

POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position

if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking

{
if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty

{
iGameState=GS_MOVE;//set the unit in motion

}
else
{
UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list

PUNITINFO pUnitInfo=*iter;//get the unit from the list

if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team

{
iGameState=GS_MOVE;
}
else
{
pUnitInfo = pEnemyUnit;
iGameState=GS_ATTACK;
}
}
}
}
}break;
case VK_NUMPAD1:
case VK_END:
{
if(iGameState==GS_IDLE && pCurrentUnit!=NULL)//gamestate must be GS_IDLE

{
idMoveUnit=ISO_SOUTHWEST;//move to the north

POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position

if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking

{
if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty

{
iGameState=GS_MOVE;//set the unit in motion

}
else
{
UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list

PUNITINFO pUnitInfo=*iter;//get the unit from the list

if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team

{
iGameState=GS_MOVE;
}
else
{
pUnitInfo = pEnemyUnit;
iGameState=GS_ATTACK;
}
}
}
}
}break;
case VK_NUMPAD4:
case VK_LEFT:
{
if(iGameState==GS_IDLE && pCurrentUnit!=NULL)//gamestate must be GS_IDLE

{
idMoveUnit=ISO_WEST;//move to the north

POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position

if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking

{
if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty

{
iGameState=GS_MOVE;//set the unit in motion

}
else
{
UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list

PUNITINFO pUnitInfo=*iter;//get the unit from the list

if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team

{
iGameState=GS_MOVE;
}
else
{
pUnitInfo = pEnemyUnit;
iGameState=GS_ATTACK;
}
}
}
}
}break;
case VK_NUMPAD7:
case VK_HOME:
{
if(iGameState==GS_IDLE && pCurrentUnit!=NULL)//gamestate must be GS_IDLE

{
idMoveUnit=ISO_NORTHWEST;//move to the north

POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position

if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking

{
if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty

{
iGameState=GS_MOVE;//set the unit in motion

}
else
{
UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list

PUNITINFO pUnitInfo=*iter;//get the unit from the list

if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team

{
iGameState=GS_MOVE;
}
else
{
pUnitInfo = pEnemyUnit;
iGameState=GS_ATTACK;
}
}
}
}
}break;
}
}break;
case WM_DESTROY://the window is being destroyed

{

//tell the application we are quitting

PostQuitMessage(0);

//handled message, so return 0

return(0);

}break;
case WM_PAINT://the window needs repainting

{
//a variable needed for painting information

PAINTSTRUCT ps;

//start painting

HDC hdc=BeginPaint(hwnd,&ps);

/////////////////////////////

//painting code would go here

/////////////////////////////


//end painting

EndPaint(hwnd,&ps);

//handled message, so return 0

return(0);
}break;
}

//pass along any other message to default message handler

return(DefWindowProc(hwnd,uMsg,wParam,lParam));
}


//////////////////////////////////////////////////////////////////////////////

//WINMAIN

//////////////////////////////////////////////////////////////////////////////

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
//assign instance to global variable

hInstMain=hInstance;

//create window class

WNDCLASSEX wcx;

//set the size of the structure

wcx.cbSize=sizeof(WNDCLASSEX);

//class style

wcx.style=CS_OWNDC | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;

//window procedure

wcx.lpfnWndProc=TheWindowProc;

//class extra

wcx.cbClsExtra=0;

//window extra

wcx.cbWndExtra=0;

//application handle

wcx.hInstance=hInstMain;

//icon

wcx.hIcon=LoadIcon(NULL,IDI_APPLICATION);

//cursor

wcx.hCursor=LoadCursor(NULL,IDC_ARROW);

//background color

wcx.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);

//menu

wcx.lpszMenuName=NULL;

//class name

wcx.lpszClassName=WINDOWCLASS;

//small icon

wcx.hIconSm=NULL;

//register the window class, return 0 if not successful

if(!RegisterClassEx(&wcx)) return(0);

//create main window

hWndMain=CreateWindowEx(0,WINDOWCLASS,WINDOWTITLE, WS_POPUP | WS_VISIBLE,0,0,400,300,NULL,NULL,hInstMain,NULL);

//error check

if(!hWndMain) return(0);

//if program initialization failed, then return with 0

if(!Prog_Init()) return(0);

//message structure

MSG msg;

//message pump

for(;;)
{
//look for a message

if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
//there is a message


//check that we arent quitting

if(msg.message==WM_QUIT) break;

//translate message

TranslateMessage(&msg);

//dispatch message

DispatchMessage(&msg);
}

//run main game loop

Prog_Loop();
}

//clean up program data

Prog_Done();

//return the wparam from the WM_QUIT message

return(msg.wParam);
}

//////////////////////////////////////////////////////////////////////////////

//INITIALIZATION

//////////////////////////////////////////////////////////////////////////////

bool Prog_Init()
{
//create IDirectDraw object

lpdd=LPDD_Create(hWndMain,DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT);

//set display mode

lpdd->SetDisplayMode(800,600,16,0,0);

//create primary surface

lpddsMain=LPDDS_CreatePrimary(lpdd,1);

//get back buffer

lpddsBack=LPDDS_GetSecondary(lpddsMain);

//create the frame buffer

lpddsFrame=LPDDS_CreateOffscreen(lpdd,800,600);

//load in the mousemap

MouseMap.Load("MouseMap.bmp");

//set up the tile plotter

TilePlotter.SetMapType(ISOMAP_DIAMOND);//diamond mode

TilePlotter.SetTileSize(MouseMap.GetWidth(),MouseMap.GetHeight());//grab width and height from mousemap


//set up tile walker to diamond mode

TileWalker.SetMapType(ISOMAP_DIAMOND);

//set up screeen space

RECT rcTemp;
SetRect(&rcTemp,0,0,600,600);
Scroller.SetScreenSpace(&rcTemp);

//load in tiles and other images

tsBack.Load(lpdd,"backgroundts.bmp");
tsUnit.Load(lpdd,"units.bmp");
tsShield.Load(lpdd,"shields.bmp");
tsPressEnter.Load(lpdd,"PressEnter.bmp");
tsBarrack.Load(lpdd,"barrack.bmp");

//calculate the shield offsets

ptShieldOffset[0].x=tsUnit.GetTileList()[0].rcSrc.right-tsUnit.GetTileList()[0].ptAnchor.x;
ptShieldOffset[0].y=tsUnit.GetTileList()[0].rcSrc.top-tsUnit.GetTileList()[0].ptAnchor.y;
ptShieldOffset[1].x=tsUnit.GetTileList()[1].rcSrc.right-tsUnit.GetTileList()[1].ptAnchor.x;
ptShieldOffset[1].y=tsUnit.GetTileList()[1].rcSrc.top-tsUnit.GetTileList()[1].ptAnchor.y;

//grab tile extent from tileset

CopyRect(&rcTemp,&tsBack.GetTileList()[0].rcDstExt);

//calculate the worldspace

Scroller.CalcWorldSpace(&TilePlotter,&rcTemp,MAPWIDTH,MAPHEIGHT);

//calculate the mousemap reference point

MouseMap.CalcReferencePoint(&TilePlotter,&rcTemp);

//calculate anchor space

Scroller.CalcAnchorSpace();

//set wrap modes for scroller

Scroller.SetHWrapMode(WRAPMODE_CLIP);
Scroller.SetVWrapMode(WRAPMODE_CLIP);

//set scroller anchor to (0,0)

Scroller.GetAnchor()->x=0;
Scroller.GetAnchor()->y=0;

//attach scroller and tilewalker to mousemap

MouseMap.SetScroller(&Scroller);
MouseMap.SetTileWalker(&TileWalker);

//set up the map to a random tilefield

int x;
int y;
for(x=0;x<MAPWIDTH;x++)
{
for(y=0;y<MAPHEIGHT;y++)
{
mlMap[x][y].ulUnitList.clear();//clear out the list for this map location

}
}

//place the units

int team;
int count;
PUNITINFO pUnitInfo;
POINT ptTest;
for(team=0;team<2;team++)//place units for both teams

{
for(count=0;count<20;count++)//place 20 units for each team

{
//check for a valid placement

bool found=false;
while(!found)
{
//random placement

ptTest.x=rand()%MAPWIDTH;
ptTest.y=rand()%MAPHEIGHT;
//check for a unit at that position

if(mlMap[ptTest.x][ptTest.y].ulUnitList.empty())
{
//unit list at location is empty... you can place the unit

found=true;
}
else
{
//unit list is not empty, so must be occupied by the same team to be a valid location

UNITLISTITER iter=mlMap[ptTest.x][ptTest.y].ulUnitList.begin();//get iterator to beginning of list

pUnitInfo=*iter;//grab the items stored

//check for the same team

if(pUnitInfo->iTeam==team)
{
//same team, valid location

found=true;
}

}
}
//create the unit

pUnitInfo=new UnitInfo;
pUnitInfo->iTeam=team;//team

pUnitInfo->iType=rand()%2;//type

pUnitInfo->bHolding=false;//not holding position

pUnitInfo->ptPosition=ptTest;//location

//place unit in the main list

MainUnitList.push_back(pUnitInfo);
//place unit on the map

mlMap[pUnitInfo->ptPosition.x][pUnitInfo->ptPosition.y].ulUnitList.push_back(pUnitInfo);
}
}

//calculate the extent rect

RECT rcExtent;
CopyRect(&rcExtent,&tsBack.GetTileList()[0].rcDstExt);//set to background extent

UnionRect(&rcExtent,&rcExtent,&tsUnit.GetTileList()[0].rcDstExt);//union with unit extent

rcExtent.right+=tsShield.GetTileList()[0].rcDstExt.right;//adjust the extent for the width of the shield


//set up the renderer

Renderer.SetBackBuffer(lpddsBack);
Renderer.SetExtentRect(&rcExtent);
Renderer.SetFrameBuffer(lpddsFrame);
Renderer.SetMapSize(MAPWIDTH,MAPHEIGHT);
Renderer.SetMouseMap(&MouseMap);
Renderer.SetPlotter(&TilePlotter);
Renderer.SetRenderFunction(RenderFunc);
Renderer.SetScroller(&Scroller);
Renderer.SetUpdateRectCount(100);
Renderer.SetWalker(&TileWalker);

//set the initial gamestate

iGameState=GS_STARTTURN;
iCurrentTeam=0;//current team

TeamUnitList.clear();//clear out the team''s unit list


//set up the selection window variables

DDPIXELFORMAT ddpf;
DDPF_Clear(&ddpf);
lpddsMain->GetPixelFormat(&ddpf);//grab pixel format

ddpf.dwRBitMask=(ddpf.dwRBitMask*3/4)&(ddpf.dwRBitMask);//calculate 3/4 red

ddpf.dwGBitMask=(ddpf.dwGBitMask*3/4)&(ddpf.dwGBitMask);//calc 3/4 green

ddpf.dwBBitMask=(ddpf.dwBBitMask*3/4)&(ddpf.dwBBitMask);//calc 3/4 blue

dwSelectWindowColor=ddpf.dwBBitMask | ddpf.dwRBitMask | ddpf.dwGBitMask;//make select window color


//calculate the cell size

RECT rcCell;
CopyRect(&rcCell,&tsUnit.GetTileList()[0].rcDstExt);
UnionRect(&rcCell,&rcCell,&tsUnit.GetTileList()[1].rcDstExt);
rcCell.right+=(tsShield.GetTileList()[0].rcDstExt.right-tsShield.GetTileList()[0].rcDstExt.left);
//cell size

ptCellSize.x=rcCell.right-rcCell.left;
ptCellSize.y=rcCell.bottom-rcCell.top;
//unit offset

ptUnitOffset.x=-rcCell.left;
ptUnitOffset.y=-rcCell.top;
//calculate select window rect

SetRect(&rcSelectWindow,0,0,ptCellSize.x*5,ptCellSize.y*4);
//center the select window

OffsetRect(&rcSelectWindow,320-rcSelectWindow.right/2,240-rcSelectWindow.bottom/2);

//update the entire screenspace

Renderer.AddRect(Scroller.GetScreenSpace());

//setup the minimap

SetupMiniMap();
UpdateMiniMap();
RedrawMiniMap();
ShowMiniMap();

return(true);//return success

}

//////////////////////////////////////////////////////////////////////////////

//CLEANUP

//////////////////////////////////////////////////////////////////////////////

void Prog_Done()
{
//destroy minimap

DestroyMiniMap();

//release frame buffer

LPDDS_Release(&lpddsFrame);

//release main/back surfaces

LPDDS_Release(&lpddsMain);

//release directdraw

LPDD_Release(&lpdd);
}

//////////////////////////////////////////////////////////////////////////////

//MAIN GAME LOOP

//////////////////////////////////////////////////////////////////////////////

void Prog_Loop()
{
switch(iGameState)
{
case GS_STARTTURN://start the current team''s turn

{
PUNITINFO pUnitInfo;//variable to check for the team''s units

UNITLISTITER iter;//iterator for the main unit list

for(iter=MainUnitList.begin();iter!=MainUnitList.end();iter++)//iterate through the main unit list

{
pUnitInfo=*iter;//grab the unit from the list

if(pUnitInfo->iTeam==iCurrentTeam)//does this unit belong to the current team?

{
//give the unit a movement point

pUnitInfo->iMovePoints=3+pUnitInfo->iType;
//add this unit to the team list

TeamUnitList.push_back(pUnitInfo);
}
}
//set moved unit flag to false

bMovedUnit=false;
//set the next gamestate

iGameState=GS_NEXTUNIT;
}break;
case GS_NEXTUNIT://select the next unit as the current unit

{
//set current unit to NULL

pCurrentUnit=NULL;
if(TeamUnitList.empty())//if the team unit list is empty

{
//if a unit has been moved, send to end of turn

if(bMovedUnit)
{
iGameState=GS_ENDTURN;//end the turn

}
else
{
//send to GS_IDLE

iGameState=GS_IDLE;//send to idle state

}
}
else
{
//turn is not over

UNITLISTITER iter=TeamUnitList.begin();//get the first unit in the team list

pCurrentUnit=*iter;//grab the unit from the list

TeamUnitList.pop_front();//remove the unit from the list


//check to see if this unit is holding position

if(pCurrentUnit->bHolding) return;//go to next unit


mlMap[pCurrentUnit->ptPosition.x][pCurrentUnit->ptPosition.y].ulUnitList.remove(pCurrentUnit);//remove the unit from the map location

mlMap[pCurrentUnit->ptPosition.x][pCurrentUnit->ptPosition.y].ulUnitList.push_front(pCurrentUnit);//place unit at the top of the map locations unit list


POINT ptPlot=TilePlotter.PlotTile(pCurrentUnit->ptPosition);//plot the unit''s location

POINT ptScreen=Scroller.WorldToScreen(ptPlot);//translate into screen coordinates


if(!PtInRect(Scroller.GetScreenSpace(),ptScreen))//check to see if point is within screenspace

{
//not on screen

ptPlot.x-=(Scroller.GetScreenSpaceWidth()/2);
ptPlot.y-=(Scroller.GetScreenSpaceHeight()/2);
//set the anchor

Scroller.SetAnchor(&ptPlot);
Renderer.AddRect(Scroller.GetScreenSpace());
}
iGameState=GS_IDLE;//set to idling gamestate

}
}break;
case GS_ENDTURN://end of a player''s turn

{
//clear out team unit list(just to be sure)

TeamUnitList.clear();

//change team

iCurrentTeam=1-iCurrentTeam;

iGameState=GS_STARTTURN;//set gamestate to start next turn

}break;
case GS_NULLMOVE://do not move the current unit

{
//set the moved flag to true

bMovedUnit=true;
//set movement points to 0

pCurrentUnit->iMovePoints=0;
//don''t really do anything, just go to the next unit

pCurrentUnit=NULL;
iGameState=GS_NEXTUNIT;
}break;
case GS_SKIPMOVE://skip this unit for now

{
//put unit at end of team unit list

TeamUnitList.push_back(pCurrentUnit);
pCurrentUnit=NULL;//set current unit to NULL

iGameState=GS_NEXTUNIT;//select the next unit

}break;
case GS_HOLDPOSITION://tell unit to hold position

{
//set holding flag

pCurrentUnit->bHolding=true;
//show the holding unit

Renderer.AddTile(pCurrentUnit->ptPosition.x,pCurrentUnit->ptPosition.y);
pCurrentUnit=NULL;
bFlash=true;
//set next gamestate

iGameState=GS_NEXTUNIT;
DWORD dwTimeStart=GetTickCount();//get the frame start time

//scroll the frame (0,0)

Renderer.ScrollFrame(0,0);
//update the frame

Renderer.UpdateFrame();
//flip to show the back buffer

lpddsMain->Flip(0,DDFLIP_WAIT);
//wait until 500 ms have passed

while(GetTickCount()-dwTimeStart<500);
}break;
case GS_MOVE:
{
//set the moved flag to true

bMovedUnit=true;
//remove the unit from the map location

mlMap[pCurrentUnit->ptPosition.x][pCurrentUnit->ptPosition.y].ulUnitList.remove(pCurrentUnit);
Renderer.AddTile(pCurrentUnit->ptPosition.x,pCurrentUnit->ptPosition.y);
//move the unit

pCurrentUnit->ptPosition=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);
//place the unit on its new map location

mlMap[pCurrentUnit->ptPosition.x][pCurrentUnit->ptPosition.y].ulUnitList.push_front(pCurrentUnit);
Renderer.AddTile(pCurrentUnit->ptPosition.x,pCurrentUnit->ptPosition.y);
//subtract a movement point

pCurrentUnit->iMovePoints--;
//check to see if this unit is finished moving

if(pCurrentUnit->iMovePoints==0)
{
//done moving

pCurrentUnit=NULL;
//set next gamestate

iGameState=GS_NEXTUNIT;
}
else
{
//not done moving

iGameState=GS_IDLE;
}
bFlash=true;
DWORD dwTimeStart=GetTickCount();//get the frame start time

//scroll the frame (0,0)

Renderer.ScrollFrame(0,0);
//update the frame

Renderer.UpdateFrame();
//flip to show the back buffer

lpddsMain->Flip(0,DDFLIP_WAIT);
//wait until 500 ms have passed

while(GetTickCount()-dwTimeStart<500);
}break;
case GS_IDLE://the game is idling, update the frame, but thats about it.

{
DWORD dwTimeStart=GetTickCount();//get the frame start time

//scroll the frame (0,0)

Renderer.ScrollFrame(0,0);

//toggle unit flash

bFlash=!bFlash;

//if the current unit is not null

if(pCurrentUnit!=NULL)
{
//add the tile in which the current unit lives

Renderer.AddTile(pCurrentUnit->ptPosition.x,pCurrentUnit->ptPosition.y);
}

//update the frame

Renderer.UpdateFrame();

//if the current unit IS null

if(pCurrentUnit==NULL)
{
//show the end of turn marker if bflash is true

if(bFlash) tsPressEnter.PutTile(lpddsBack,0,0,iCurrentTeam);
}

//redo the minimap

UpdateMiniMap();
RedrawMiniMap();
ShowMiniMap();

//flip to show the back buffer

lpddsMain->Flip(0,DDFLIP_WAIT);
//wait until 200 ms have passed

while(GetTickCount()-dwTimeStart<200);
}break;
case GS_CLICKSELECT:
{
//check map location for emptiness

if(mlMap[ptClick.x][ptClick.y].ulUnitList.empty())
{
//map location is empty

iGameState=GS_CLICKCENTER;//we want to center on this map location

}
else
{
//map location is not empty

//look at top of list

UNITLISTITER iter=mlMap[ptClick.x][ptClick.y].ulUnitList.begin();
PUNITINFO pUnitInfo=*iter;
//check that if this unit belongs to the current team

if(pUnitInfo->iTeam==iCurrentTeam)
{
//belongs to current team

//one unit?

if(mlMap[ptClick.x][ptClick.y].ulUnitList.size()==1)
{
//a single unit(already contained in pUnitInfo)

//is this the current unit?

if(pUnitInfo==pCurrentUnit)
{
//this is the current unit

iGameState=GS_IDLE;//return to the neutral gamestate

}
else
{
//this is not the current unit

//does this unit have any movement points left?

if(pUnitInfo->iMovePoints>0)
{
//has movement points left

//push the current unit to front of team list

if(pCurrentUnit) TeamUnitList.push_front(pCurrentUnit);
pCurrentUnit=NULL;
//set holding to false for the new unit

pUnitInfo->bHolding=false;
//remove new unit from team list

TeamUnitList.remove(pUnitInfo);
//put new unit in front of team list

TeamUnitList.push_front(pUnitInfo);
//go to gs_nextunit

iGameState=GS_NEXTUNIT;
}
else
{
//does not have movement points left

//go back to gs_idle

iGameState=GS_IDLE;
}
}
}
else
{
//place the current unit at the front of the list

if(pCurrentUnit) TeamUnitList.push_front(pCurrentUnit);
//a stack of units

iGameState=GS_CLICKSTACK;
}
}
else
{
//does not belong to current team

iGameState=GS_CLICKCENTER;//we want to center on this map location

}
}
}break;
case GS_CLICKCENTER:
{
//center on clicked tile

POINT ptPlot=TilePlotter.PlotTile(ptClick);//plot tile

ptPlot.x-=(Scroller.GetScreenSpaceWidth()/2);//adjust by half screenspace

ptPlot.y-=(Scroller.GetScreenSpaceHeight()/2);
Scroller.SetAnchor(&ptPlot);//set anchor

Renderer.AddRect(Scroller.GetScreenSpace());
//return to GS_IDLE

iGameState=GS_IDLE;
}break;
case GS_CLICKSTACK:
{
//prepare the stack

int count;
for(count=0;count<20;count++)//clear out the list

SelectUnitList[count]=NULL;
//reset count to 0

count=0;
//iterate through the list of units at the current map location

UNITLISTITER iter;//iterator

PUNITINFO pUnitInfo;//unit info

for(iter=mlMap[ptClick.x][ptClick.y].ulUnitList.begin();count<20 && iter!=mlMap[ptClick.x][ptClick.y].ulUnitList.end();iter++)//iterate through list

{
pUnitInfo=*iter;//grab the unit

//place unit in list

SelectUnitList[count]=pUnitInfo;
//add 1 to count

count++;
}
//send to next gamestate

iGameState=GS_PICKUNIT;
}break;
case GS_PICKUNIT:
{
//no scrolling

Renderer.ScrollFrame(0,0);
//update frame

Renderer.UpdateFrame();
//place select window onto display

DDBLTFX ddbltfx;
DDBLTFX_Clear(&ddbltfx);
ddbltfx.dwFillColor=dwSelectWindowColor;
lpddsBack->Blt(&rcSelectWindow,NULL,NULL,DDBLT_WAIT | DDBLT_COLORFILL,&ddbltfx);
//show the units

int cellx,celly;//cell position

int cellnum;//number of the cell

int pixelx,pixely;//pixel position

for(celly=0;celly<4;celly++)
{
for(cellx=0;cellx<5;cellx++)
{
cellnum=cellx+celly*5;//calculate the cell number

//check that the unit exists

if(SelectUnitList[cellnum])
{
//calculate pixel position

pixelx=rcSelectWindow.left+ptCellSize.x*cellx;
pixely=rcSelectWindow.top+ptCellSize.y*celly;
//plot the units position

pixelx+=ptUnitOffset.x;
pixely+=ptUnitOffset.y;
//put the unit

tsUnit.PutTile(lpddsBack,pixelx,pixely,SelectUnitList[cellnum]->iType);
//move the pixel to place shielf

pixelx+=ptShieldOffset[SelectUnitList[cellnum]->iType].x;
pixely+=ptShieldOffset[SelectUnitList[cellnum]->iType].y;
//place appropriate shield

if(SelectUnitList[cellnum]->bHolding)
{
//unit is holding

tsShield.PutTile(lpddsBack,pixelx,pixely,iCurrentTeam*2+4);
}
else
{
//unit is not holding

if(SelectUnitList[cellnum]->iMovePoints)
{
//unit has movement points left

tsShield.PutTile(lpddsBack,pixelx,pixely,iCurrentTeam*2);
}
else
{
//unit does not have movement points left

tsShield.PutTile(lpddsBack,pixelx,pixely,iCurrentTeam*2+8);
}
}
}
}
}break;
//flip

lpddsMain->Flip(0,DDFLIP_WAIT);
}
case GS_BUILD:
{
//MapLocation mlBarrackPosition;

//mlMap[pCurrentUnit->ptPosition.x][pCurrentUnit->ptPosition.y]=mlBarrackPosition;

//void RenderBarrack (RECT* rcClip, mlBarrackPosition);

//{

// tsBarrack.ClipTile(rcClip, mlBarrackPosition);

//}

}break;
case GS_ATTACK:
{
mlMap[pEnemyUnit->ptPosition.x][pEnemyUnit->ptPosition.y].ulUnitList.remove(pEnemyUnit);
Renderer.AddTile(pEnemyUnit->ptPosition.x,pEnemyUnit->ptPosition.y);
iGameState = GS_IDLE;
}break;
}
}
void RenderFunc(LPDIRECTDRAWSURFACE7 lpddsDst,RECT* rcClip,int xDst,int yDst,int xMap,int yMap)
{
//put background tile

tsBack.ClipTile(lpddsDst,rcClip,xDst,yDst,0);
//check for an empty list

if(!mlMap[xMap][yMap].ulUnitList.empty())
{
//list is not empty

UNITLISTITER iter=mlMap[xMap][yMap].ulUnitList.begin();//get iterator to beginning of list

PUNITINFO pUnitInfo=*iter;//grab the item

//if this is the current unit

if(pUnitInfo==pCurrentUnit)
{
//this is the current unit

if(!bFlash) return;//if flash is "off" dont render

}
tsUnit.ClipTile(lpddsDst,rcClip,xDst,yDst,pUnitInfo->iType);//place the unit

iter++;//move to the next item in the list

if(iter==mlMap[xMap][yMap].ulUnitList.end())//if the end of the list, this is a single unit

{
if(pUnitInfo->bHolding)//if holding position

{//holding

tsShield.ClipTile(lpddsDst,rcClip,xDst+ptShieldOffset[pUnitInfo->iType].x,yDst+ptShieldOffset[pUnitInfo->iType].y,pUnitInfo->iTeam*2+4);//place the shield

}
else
{//not holding

tsShield.ClipTile(lpddsDst,rcClip,xDst+ptShieldOffset[pUnitInfo->iType].x,yDst+ptShieldOffset[pUnitInfo->iType].y,pUnitInfo->iTeam*2);//place the shield

}
}
else//more than one unit... this is a stack

{
if(pUnitInfo->bHolding)//if holding position

{//holding

tsShield.ClipTile(lpddsDst,rcClip,xDst+ptShieldOffset[pUnitInfo->iType].x,yDst+ptShieldOffset[pUnitInfo->iType].y,pUnitInfo->iTeam*2+5);//place the shield

}
else
{//not holding

tsShield.ClipTile(lpddsDst,rcClip,xDst+ptShieldOffset[pUnitInfo->iType].x,yDst+ptShieldOffset[pUnitInfo->iType].y,pUnitInfo->iTeam*2+1);//place the shield

}
}
}
}

void SetupMiniMap()//does initial setup of the minimap

{
//create the surface

lpddsMiniMap=LPDDS_CreateOffscreen(lpdd,160,80);
//load in the tileset

tsMiniMap.Load(lpdd,"minimapts.bmp");
//initialize the minimap arrays

MiniMap=new int[MAPWIDTH*MAPHEIGHT];
for(int count=0;count<MAPWIDTH*MAPHEIGHT;count++)
{
MiniMap[count]=0;
}
//initialize iso components

//tile plotter

MiniTilePlotter.SetMapType(ISOMAP_DIAMOND);
MiniTilePlotter.SetTileSize(4,2);
//scroller

//calc worldspace

MiniScroller.CalcWorldSpace(&MiniTilePlotter,&tsMiniMap.GetTileList()[0].rcDstExt,MAPWIDTH,MAPHEIGHT);
//set screen-space

RECT rcMiniScreenSpace;
SetRect(&rcMiniScreenSpace,0,0,160,80);
MiniScroller.SetScreenSpace(&rcMiniScreenSpace);
//set the anchor

POINT ptAnchor;
ptAnchor.x=MiniScroller.GetWorldSpace()->left;
ptAnchor.y=MiniScroller.GetWorldSpace()->top;
MiniScroller.SetAnchor(&ptAnchor);

}

void UpdateMiniMap()//updates the minimap array

{
//upate the minimap array to reflect game status

for(int y=0;y<MAPHEIGHT;y++)//loop through rows

{
for(int x=0;x<MAPWIDTH;x++)//loop through columns

{
MiniMap[y*MAPWIDTH+x]=0;
//if empty, place a zero

if(mlMap[x][y].ulUnitList.empty())
{
MiniMap[y*MAPWIDTH+x]=0;
}
else
{
//occupied by a player

UNITLISTITER iter=mlMap[x][y].ulUnitList.begin();
PUNITINFO pUnitInfo=*iter;
if(pUnitInfo!=pCurrentUnit || bFlash) MiniMap[y*MAPWIDTH+x]=1+pUnitInfo->iTeam;//put team info into minimap array

}
}
}
}

void RedrawMiniMap()//redraws the minimap to reflect current gamestate

{
//redraw the entire minimap

//in real code, you can keep two arrays

//one valid this frame and one valid last frame

//and then only blit the changes from last frame to this one

//thus reducing the number of blits

//clear out the minimap surface

DDBLTFX ddbltfx;
DDBLTFX_ColorFill(&ddbltfx,0);
lpddsMiniMap->Blt(NULL,NULL,NULL,DDBLT_WAIT | DDBLT_COLORFILL,&ddbltfx);
POINT ptPlot;//plotting point

for(int y=0;y<MAPHEIGHT;y++)//loop through rows

{
for(int x=0;x<MAPWIDTH;x++)//loop through columns

{
//put the mini-tile

ptPlot.x=x;
ptPlot.y=y;
//plot map position

ptPlot=MiniTilePlotter.PlotTile(ptPlot);
//convert to screen coords

ptPlot=MiniScroller.WorldToScreen(ptPlot);
tsMiniMap.PutTile(lpddsMiniMap,ptPlot.x,ptPlot.y,MiniMap[y*MAPWIDTH+x]);
}
}
//show a rectangle around viewable area on minimap

HDC hdc;
lpddsMiniMap->GetDC(&hdc);//borrow the dc from the minimap surface


//get the anchor point from the main scroller

POINT ptAnchor;
ptAnchor.x=Scroller.GetAnchor()->x;
ptAnchor.y=Scroller.GetAnchor()->y;

//scale down by a factor of 16(to go from a 64x32 tile to 4x2)

ptAnchor.x/=16;
ptAnchor.y/=16;

//subtract the mini-scroller''s upper left

ptAnchor.x-=MiniScroller.GetWorldSpace()->left;
ptAnchor.y-=MiniScroller.GetWorldSpace()->top;

//move to position in minimap

MoveToEx(hdc,ptAnchor.x,ptAnchor.y,NULL);
//draw box, one line at a time

LineTo(hdc,ptAnchor.x+30,ptAnchor.y);//30 is 480/16

LineTo(hdc,ptAnchor.x+30,ptAnchor.y+30);
LineTo(hdc,ptAnchor.x,ptAnchor.y+30);
LineTo(hdc,ptAnchor.x,ptAnchor.y);

lpddsMiniMap->ReleaseDC(hdc);//restore the dc to the minimap

}

void ShowMiniMap()//shows the minimap on-screen

{
RECT rcSrc;//src blitting rect

RECT rcDst;//destination blitting rect

//set src rect

SetRect(&rcSrc,0,0,160,80);
//set dest rect

CopyRect(&rcDst,&rcSrc);
OffsetRect(&rcDst,600,0);
//do the blit

lpddsBack->Blt(&rcDst,lpddsMiniMap,&rcSrc,DDBLT_WAIT,NULL);
}

void DestroyMiniMap()//cleans up the minimap

{
//delete minimap array

delete[] MiniMap;
//destroy minimap surface

if(lpddsMiniMap)
{
lpddsMiniMap->Release();
lpddsMiniMap=NULL;
}
//destroy minimap tileset

tsMiniMap.Unload();
}



I just noticed there at the end, would it be the minimap? It has no removal functions. I''ll have a look.



Share this post


Link to post
Share on other sites
quote:
Original post by burntgorilla
No, didn''t work. Does VC++ automatically quit a program that gets caught in a loop?


It is provably impossible to determine whether a program is stuck in a loop or not ( see Halting Problem ). So don''t expect VC++ to do it.


[ Start Here ! | How To Ask Smart Questions | Recommended C++ Books | C++ FAQ Lite | Function Ptrs | CppTips Archive ]
[ Header Files | File Format Docs | LNK2001 | C++ STL Doc | STLPort | Free C++ IDE | Boost C++ Lib | MSVC6 Lib Fixes ]

Share this post


Link to post
Share on other sites