mirror of
https://github.com/jmarshall23/Hellfire.git
synced 2026-08-17 16:40:41 +02:00
Initial commit.
This commit is contained in:
@@ -0,0 +1,760 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* RPG.CPP
|
||||
*
|
||||
* This is a simple game which demonstrates the use of synchonous networking.
|
||||
* It is basically an Ultima IV style tiled graphics engine, with Warcraft
|
||||
* style mouse controls.
|
||||
*
|
||||
* At the beginning of the game, each player sends out two null orders.
|
||||
* During the game, players send out orders as they are received from the
|
||||
* user (a sample order would be "move to this location"), and fabricate
|
||||
* null orders as necessary to make sure there are always at least two in
|
||||
* transit.
|
||||
*
|
||||
* Each turn, each player waits until he has received the next set of orders
|
||||
* from all players, and then executes all orders, starting at the lowest
|
||||
* player number. Since orders are processed at the same time and in the
|
||||
* same order on every computer in the network, the game stays in sync.
|
||||
*
|
||||
***/
|
||||
|
||||
#include <windows.h>
|
||||
#include <storm.h>
|
||||
#include "bnetart.h"
|
||||
|
||||
#define PROGRAMID 'RPG1'
|
||||
#define VERSIONID 1
|
||||
#define MAXPLAYERS 8
|
||||
#define TITLE "RPG Example"
|
||||
#define ARTDIR "art\\"
|
||||
#define NETARTDIR "netart\\"
|
||||
|
||||
#define ORDER_NULL 0
|
||||
#define ORDER_START 1
|
||||
#define ORDER_MOVE 2
|
||||
#define ORDER_QUIT 3
|
||||
|
||||
#define TILE_DEEPSEA 0
|
||||
#define TILE_SEA 1
|
||||
#define TILE_SHALLOWSEA 2
|
||||
#define TILE_SWAMP 3
|
||||
#define TILE_GRASS 4
|
||||
#define TILE_BRUSH 5
|
||||
#define TILE_FOREST 6
|
||||
#define TILE_HILLS 7
|
||||
#define TILE_MOUNTAINS 8
|
||||
#define TILE_DUNGEON 9
|
||||
#define TILE_TOWN 10
|
||||
#define TILE_CASTLE 11
|
||||
#define TILE_VILLAGE 12
|
||||
|
||||
#define SCREENCX 640
|
||||
#define SCREENCY 480
|
||||
#define SCREENTILESX 20
|
||||
#define SCREENTILESY 15
|
||||
#define SCROLLCX 672
|
||||
#define SCROLLCY 512
|
||||
#define SCROLLTILESX 21
|
||||
#define SCROLLTILESY 16
|
||||
#define TILES 16
|
||||
#define TILECX 32
|
||||
#define TILECY 32
|
||||
#define WORLDMAPCX 256
|
||||
#define WORLDMAPCY 256
|
||||
|
||||
LPBYTE cursor = NULL;
|
||||
POINT cursorpos = {0,0};
|
||||
DWORD localplayer = 0;
|
||||
POINT orderpos[MAXPLAYERS];
|
||||
PALETTEENTRY pe[256];
|
||||
LPBYTE player = NULL;
|
||||
POINT playerpos[MAXPLAYERS];
|
||||
DWORD players = 0;
|
||||
LPBYTE scrollbuffer = NULL;
|
||||
POINT scrollpos;
|
||||
POINT scrollvel = {0,0};
|
||||
BOOL started = 0;
|
||||
LPBYTE tileset = NULL;
|
||||
LPBYTE worldmap = NULL;
|
||||
|
||||
BOOL CALLBACK CreateCallback (SNETCREATEDATAPTR createdata,
|
||||
SNETPROGRAMDATAPTR programdata,
|
||||
SNETPLAYERDATAPTR playerdata,
|
||||
SNETUIDATAPTR interfacedata,
|
||||
SNETVERSIONDATAPTR versiondata,
|
||||
DWORD *playerid);
|
||||
BOOL LoadGraphicsData ();
|
||||
void MovePlayer (DWORD player);
|
||||
void CALLBACK OnButtonDown (LPPARAMS params);
|
||||
void CALLBACK OnClose (LPPARAMS params);
|
||||
void CALLBACK OnEraseBkgnd (LPPARAMS params);
|
||||
void CALLBACK OnPaint (LPPARAMS params);
|
||||
void CALLBACK OnVkEscape (LPPARAMS params);
|
||||
void CALLBACK OnVkSpace (LPPARAMS params);
|
||||
BOOL ProcessOrders ();
|
||||
BOOL UpdateScrollVelocity ();
|
||||
|
||||
//===========================================================================
|
||||
BOOL CALLBACK ArtCallback (DWORD providerid,
|
||||
DWORD artid,
|
||||
LPPALETTEENTRY pe,
|
||||
LPBYTE buffer,
|
||||
DWORD buffersize,
|
||||
int *width,
|
||||
int *height,
|
||||
int *bitdepth) {
|
||||
|
||||
char filename[MAX_PATH] = "";
|
||||
|
||||
if (providerid == 'BNET') {
|
||||
// Check for battlenet specific art
|
||||
switch (artid) {
|
||||
|
||||
case SNET_ART_BACKGROUND: strcpy(filename,NETARTDIR "chat_bkg.pcx"); break;
|
||||
case SNET_ART_BATTLE_LISTBOX: strcpy(filename, NETARTDIR "bnlist.pcx"); break;
|
||||
|
||||
case SNET_ART_BATTLE_BTNS: strcpy(filename, NETARTDIR "bnbuttns.pcx"); break;
|
||||
|
||||
case SNET_ART_BATTLE_HELP_BKG: strcpy(filename, NETARTDIR "lpopup.pcx"); break;
|
||||
case SNET_ART_JOINBACKGROUND: strcpy(filename, NETARTDIR "bnjoinbg.pcx"); break;
|
||||
|
||||
case SNET_ART_BATTLE_REDLAG: strcpy(filename, NETARTDIR "redlag.pcx"); break;
|
||||
case SNET_ART_BATTLE_YELLOWLAG: strcpy(filename, NETARTDIR "yellolag.pcx"); break;
|
||||
case SNET_ART_BATTLE_GREENLAG: strcpy(filename, NETARTDIR "greenlag.pcx"); break;
|
||||
}
|
||||
|
||||
}
|
||||
else if ((providerid == 'IPXN') || (providerid == 'TEST')) {
|
||||
switch (artid) {
|
||||
case SNET_ART_BACKGROUND: strcpy(filename, NETARTDIR "ipx_bkg.pcx"); break;
|
||||
}
|
||||
}
|
||||
else if (providerid == 0) {
|
||||
switch (artid) {
|
||||
case SNET_ART_BACKGROUND: strcpy(filename, NETARTDIR "connect.pcx"); break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!filename[0]) {
|
||||
// Check for generic artwork
|
||||
switch (artid) {
|
||||
case SNET_ART_JOINBACKGROUND: // fall through
|
||||
case SNET_ART_BACKGROUND: strcpy(filename,NETARTDIR "menu.pcx"); break;
|
||||
case SNET_ART_BUTTONTEXTURE: strcpy(filename,NETARTDIR "but_lrg.pcx"); break;
|
||||
case SNET_ART_POPUPBACKGROUND: strcpy(filename,NETARTDIR "lpopup.pcx"); break;
|
||||
case SNET_ART_HELPBACKGROUND: strcpy(filename,NETARTDIR "lpopup.pcx"); break;
|
||||
|
||||
case SNET_ART_BUTTON_XSML: strcpy(filename,NETARTDIR "but_xsm.pcx"); break;
|
||||
case SNET_ART_BUTTON_SML: strcpy(filename,NETARTDIR "but_sml.pcx"); break;
|
||||
case SNET_ART_BUTTON_MED: strcpy(filename,NETARTDIR "but_med.pcx"); break;
|
||||
case SNET_ART_BUTTON_LRG: strcpy(filename,NETARTDIR "but_lrg.pcx"); break;
|
||||
}
|
||||
}
|
||||
|
||||
if (filename[0])
|
||||
return SBmpLoadImage(filename,pe,buffer,buffersize,width,height,bitdepth);
|
||||
else
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void ChooseStartingLocations () {
|
||||
for (DWORD loop = 0; loop < MAXPLAYERS; ++loop) {
|
||||
BOOL found = 0;
|
||||
while (!found) {
|
||||
int x = rand() % WORLDMAPCX;
|
||||
int y = rand() % WORLDMAPCY;
|
||||
if (*(worldmap+y*WORLDMAPCX+x) == TILE_GRASS) {
|
||||
found = 1;
|
||||
for (DWORD loop2 = 1; loop2 < loop; ++loop2)
|
||||
if ((playerpos[loop2].x == x) && (playerpos[loop2].y == y))
|
||||
found = 0;
|
||||
if (found) {
|
||||
orderpos[loop].x = x;
|
||||
orderpos[loop].y = y;
|
||||
playerpos[loop].x = x;
|
||||
playerpos[loop].y = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
BOOL Connect () {
|
||||
|
||||
// BUILD A PROGRAM DATA RECORD
|
||||
SNETPROGRAMDATA programdata;
|
||||
ZeroMemory(&programdata,sizeof(SNETPROGRAMDATA));
|
||||
programdata.size = sizeof(SNETPROGRAMDATA);
|
||||
programdata.programname = TITLE;
|
||||
programdata.programid = PROGRAMID;
|
||||
programdata.versionid = VERSIONID;
|
||||
programdata.maxplayers = MAXPLAYERS;
|
||||
|
||||
// GENERATE A PLAYER NAME
|
||||
char computername[MAX_COMPUTERNAME_LENGTH+1] = "";
|
||||
DWORD size = MAX_COMPUTERNAME_LENGTH+1;
|
||||
GetComputerName(computername,&size);
|
||||
|
||||
// BUILD A PLAYER DATA RECORD
|
||||
SNETPLAYERDATA playerdata;
|
||||
ZeroMemory(&playerdata,sizeof(SNETPLAYERDATA));
|
||||
playerdata.size = sizeof(SNETPLAYERDATA);
|
||||
playerdata.playername = computername;
|
||||
|
||||
// BUILD AN INTERFACE DATA RECORD
|
||||
SNETUIDATA interfacedata;
|
||||
ZeroMemory(&interfacedata,sizeof(SNETUIDATA));
|
||||
interfacedata.size = sizeof(SNETUIDATA);
|
||||
interfacedata.parentwindow = SDrawGetFrameWindow();
|
||||
interfacedata.artcallback = ArtCallback;
|
||||
interfacedata.createcallback = CreateCallback;
|
||||
|
||||
// SELECT A NETWORK PROVIDER
|
||||
while (SNetSelectProvider(NULL,
|
||||
&programdata,
|
||||
&playerdata,
|
||||
&interfacedata,
|
||||
NULL,
|
||||
NULL)) {
|
||||
|
||||
// SELECT A GAME
|
||||
if (SNetSelectGame(0,
|
||||
&programdata,
|
||||
&playerdata,
|
||||
&interfacedata,
|
||||
NULL,
|
||||
&localplayer))
|
||||
return 1;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
BOOL CALLBACK ConnectIdleProc (DWORD) {
|
||||
DWORD currtime = GetTickCount();
|
||||
|
||||
// TWICE A SECOND, UPDATE THE LIST OF PLAYERS
|
||||
{
|
||||
static DWORD lasttime = 0;
|
||||
if (currtime-lasttime > 1000)
|
||||
lasttime = currtime-500;
|
||||
while (currtime-lasttime >= 500) {
|
||||
|
||||
// DRAW THE LIST
|
||||
LPBYTE videobuffer;
|
||||
int videopitch;
|
||||
if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) {
|
||||
SGdiSetPitch(videopitch);
|
||||
SNetGetNumPlayers(NULL,&players,NULL);
|
||||
++players;
|
||||
for (DWORD loop = 0; loop < players; ++loop) {
|
||||
char buffer[SNET_MAXNAMELENGTH+2] = "0 ";
|
||||
buffer[0] += (char)loop;
|
||||
if (SNetGetPlayerName(loop,buffer+2,SNET_MAXNAMELENGTH))
|
||||
SGdiTextOut(videobuffer,4,loop*20,PALETTEINDEX(255-loop),buffer);
|
||||
}
|
||||
SGdiTextOut(videobuffer,440,20,PALETTEINDEX(255),"PRESS SPACE TO START");
|
||||
SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer);
|
||||
}
|
||||
|
||||
lasttime += 500;
|
||||
}
|
||||
}
|
||||
|
||||
// FOUR TIMES A SECOND, PROCESS ORDERS
|
||||
{
|
||||
static DWORD lasttime = 0;
|
||||
if (currtime-lasttime > 1000)
|
||||
lasttime = currtime-250;
|
||||
while (currtime-lasttime >= 250) {
|
||||
if (ProcessOrders())
|
||||
lasttime += 250;
|
||||
else
|
||||
lasttime = GetTickCount();
|
||||
currtime = GetTickCount();
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
BOOL CALLBACK CreateCallback (SNETCREATEDATAPTR createdata,
|
||||
SNETPROGRAMDATAPTR programdata,
|
||||
SNETPLAYERDATAPTR playerdata,
|
||||
SNETUIDATAPTR interfacedata,
|
||||
SNETVERSIONDATAPTR versiondata,
|
||||
DWORD *playerid) {
|
||||
return SNetCreateGame(playerdata->playername,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
createdata->maxplayers,
|
||||
playerdata->playername,
|
||||
NULL,
|
||||
playerid);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
BOOL CreateScrollBuffer () {
|
||||
scrollbuffer = (LPBYTE)ALLOC(SCROLLTILESX*TILECX*SCROLLTILESY*TILECY);
|
||||
return (scrollbuffer != NULL);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void Destroy () {
|
||||
if (cursor) {
|
||||
FREE(cursor);
|
||||
cursor = NULL;
|
||||
}
|
||||
if (player) {
|
||||
FREE(player);
|
||||
player = NULL;
|
||||
}
|
||||
if (scrollbuffer) {
|
||||
FREE(scrollbuffer);
|
||||
scrollbuffer = NULL;
|
||||
}
|
||||
if (tileset) {
|
||||
FREE(tileset);
|
||||
tileset = NULL;
|
||||
}
|
||||
if (worldmap) {
|
||||
FREE(worldmap);
|
||||
worldmap = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void DrawScreen () {
|
||||
LPBYTE videobuffer;
|
||||
int pitch;
|
||||
if (SDrawLockSurface(SDRAW_SURFACE_BACK,NULL,&videobuffer,&pitch)) {
|
||||
int startx = scrollpos.x % SCROLLCX;
|
||||
int starty = scrollpos.y % SCROLLCY;
|
||||
|
||||
// BLT FROM THE SCROLL BUFFER ONTO THE BACK SURFACE
|
||||
SBltROP3(videobuffer,
|
||||
scrollbuffer+starty*SCROLLCX+startx,
|
||||
min(SCREENCX,SCROLLCX-startx),
|
||||
min(SCREENCY,SCROLLCY-starty),
|
||||
pitch,
|
||||
SCROLLCX,
|
||||
0,
|
||||
SRCCOPY);
|
||||
if (SCROLLCX-startx < SCREENCX)
|
||||
SBltROP3(videobuffer+SCROLLCX-startx,
|
||||
scrollbuffer+starty*SCROLLCX,
|
||||
SCREENCX+startx-SCROLLCX,
|
||||
min(SCREENCY,SCROLLCY-starty),
|
||||
pitch,
|
||||
SCROLLCX,
|
||||
0,
|
||||
SRCCOPY);
|
||||
if (SCROLLCY-starty < SCREENCY)
|
||||
SBltROP3(videobuffer+(SCROLLCY-starty)*pitch,
|
||||
scrollbuffer+startx,
|
||||
min(SCREENCX,SCROLLCX-startx),
|
||||
SCREENCY+starty-SCROLLCY,
|
||||
pitch,
|
||||
SCROLLCX,
|
||||
0,
|
||||
SRCCOPY);
|
||||
if ((SCROLLCX-startx < SCREENCX) &&
|
||||
(SCROLLCY-starty < SCREENCY))
|
||||
SBltROP3(videobuffer+(SCROLLCY-starty)*pitch+SCROLLCX-startx,
|
||||
scrollbuffer,
|
||||
SCREENCX+startx-SCROLLCX,
|
||||
SCREENCY+starty-SCROLLCY,
|
||||
pitch,
|
||||
SCROLLCX,
|
||||
0,
|
||||
SRCCOPY);
|
||||
|
||||
// DRAW THE MOUSE CURSOR ONTO THE BACK SURFACE
|
||||
if (started) {
|
||||
GetCursorPos(&cursorpos);
|
||||
SBltROP3(videobuffer+cursorpos.y*pitch+cursorpos.x,
|
||||
cursor,
|
||||
min(32,SCREENCX-cursorpos.x),
|
||||
min(32,SCREENCY-cursorpos.y),
|
||||
pitch,
|
||||
32,
|
||||
0,
|
||||
SRCPAINT);
|
||||
}
|
||||
|
||||
SDrawUnlockSurface(SDRAW_SURFACE_BACK,videobuffer);
|
||||
SDrawFlipPage();
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void FillScrollBuffer (LPRECT rect) {
|
||||
int startxtile = scrollpos.x/TILECX;
|
||||
int startytile = scrollpos.y/TILECY;
|
||||
int startxpos = (scrollpos.x % SCROLLCX)/TILECX;
|
||||
int startypos = (scrollpos.y % SCROLLCY)/TILECY;
|
||||
for (int y = rect->top; y <= rect->bottom; ++y) {
|
||||
int mapy = startytile+y+((y >= startypos) ? 0 : SCROLLTILESY)-startypos;
|
||||
for (int x = rect->left; x <= rect->right; ++x) {
|
||||
int mapx = startxtile+x+((x >= startxpos) ? 0 : SCROLLTILESX)-startxpos;
|
||||
int tile = min(TILES-1,*(worldmap+mapy*WORLDMAPCX+mapx));
|
||||
SBltROP3(scrollbuffer+y*TILECY*SCROLLCX+x*TILECX,
|
||||
tileset+tile*TILECX,
|
||||
TILECX,
|
||||
TILECY,
|
||||
SCROLLCX,
|
||||
TILES*TILECX,
|
||||
0,
|
||||
SRCCOPY);
|
||||
}
|
||||
}
|
||||
for (DWORD loop = 0; loop < players; ++loop) {
|
||||
if ((playerpos[loop].x >= startxtile) &&
|
||||
(playerpos[loop].y >= startytile) &&
|
||||
(playerpos[loop].x < startxtile+SCROLLTILESX) &&
|
||||
(playerpos[loop].y < startytile+SCROLLTILESY)) {
|
||||
int posx = (startxpos+(playerpos[loop].x-startxtile)) % SCROLLTILESX;
|
||||
int posy = (startypos+(playerpos[loop].y-startytile)) % SCROLLTILESY;
|
||||
if ((posx >= rect->left) && (posx <= rect->right) &&
|
||||
(posy >= rect->top) && (posy <= rect->bottom)) {
|
||||
DWORD pattern = ((255-loop) << 24) | ((255-loop) << 16) | ((255-loop) << 8) | (255-loop);
|
||||
// pattern 11110000
|
||||
// source 11001100
|
||||
// dest 10101010
|
||||
// --------
|
||||
// rop 11100010 = 0xE2
|
||||
SBltROP3(scrollbuffer+posy*TILECY*SCROLLCX+posx*TILECX,
|
||||
player,
|
||||
TILECX,
|
||||
TILECY,
|
||||
SCROLLCX,
|
||||
TILECX,
|
||||
pattern,
|
||||
0xE20746);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
BOOL CALLBACK GameIdleProc (DWORD) {
|
||||
DWORD currtime = GetTickCount();
|
||||
|
||||
// FOUR TIMES A SECOND, MOVE THE PLAYERS
|
||||
{
|
||||
static DWORD lasttime = GetTickCount();
|
||||
if (currtime-lasttime > 1000)
|
||||
lasttime = currtime-250;
|
||||
while (currtime-lasttime >= 250) {
|
||||
for (DWORD loop = 0; loop < players; ++loop)
|
||||
MovePlayer(loop);
|
||||
RECT rect = {0,0,SCROLLTILESX-1,SCROLLTILESY-1};
|
||||
FillScrollBuffer(&rect);
|
||||
lasttime += 250;
|
||||
}
|
||||
}
|
||||
|
||||
// TWICE A SECOND, PROCESS ORDERS
|
||||
{
|
||||
static DWORD lasttime = GetTickCount();
|
||||
if (currtime-lasttime > 2000)
|
||||
lasttime = currtime-500;
|
||||
while (currtime-lasttime >= 500) {
|
||||
if (ProcessOrders())
|
||||
lasttime += 500;
|
||||
else
|
||||
lasttime = GetTickCount();
|
||||
currtime = GetTickCount();
|
||||
}
|
||||
}
|
||||
|
||||
// PROCESS SCROLLING
|
||||
if (UpdateScrollVelocity()) {
|
||||
|
||||
// UPDATE THE SCROLL POSITION
|
||||
POINT oldscrollpos = scrollpos;
|
||||
scrollpos.x = max(0,min(WORLDMAPCX*TILECX-SCROLLCX,scrollpos.x+scrollvel.x));
|
||||
scrollpos.y = max(0,min(WORLDMAPCY*TILECY-SCROLLCY,scrollpos.y+scrollvel.y));
|
||||
|
||||
// UPDATE THE SCROLL BUFFER
|
||||
if (scrollpos.x/TILECX != oldscrollpos.x/TILECX) {
|
||||
int updatex = (scrollvel.x > 0) ? (oldscrollpos.x % SCROLLCX)/TILECX
|
||||
: (scrollpos.x % SCROLLCX)/TILECX;
|
||||
RECT rect = {updatex,0,updatex,SCROLLTILESY-1};
|
||||
FillScrollBuffer(&rect);
|
||||
}
|
||||
if (scrollpos.y/TILECY != oldscrollpos.y/TILECY) {
|
||||
int updatey = (scrollvel.y > 0) ? (oldscrollpos.y % SCROLLCY)/TILECY
|
||||
: (scrollpos.y % SCROLLCY)/TILECY;
|
||||
RECT rect = {0,updatey,SCROLLTILESX-1,updatey};
|
||||
FillScrollBuffer(&rect);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// DRAW THE SCREEN
|
||||
DrawScreen();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
BOOL CALLBACK IdleProc (DWORD count) {
|
||||
if (started)
|
||||
return GameIdleProc(count);
|
||||
else
|
||||
return ConnectIdleProc(count);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void IssueOrder (LPDWORD paramarray, DWORD paramcount) {
|
||||
SNetSendTurn(paramarray,
|
||||
paramcount*sizeof(DWORD));
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
BOOL Initialize (HINSTANCE instance) {
|
||||
if (!SDrawAutoInitialize(instance,
|
||||
TITLE "_CLASS",
|
||||
TITLE,
|
||||
NULL,
|
||||
SDRAW_SERVICE_PAGEFLIP)) {
|
||||
SDrawMessageBox("Unable to initialize DirectDraw.",TITLE,0);
|
||||
return 0;
|
||||
}
|
||||
if (!LoadGraphicsData()) {
|
||||
SDrawMessageBox("Unable to load graphics data.",TITLE,0);
|
||||
return 0;
|
||||
}
|
||||
if (!CreateScrollBuffer()) {
|
||||
SDrawMessageBox("Out of memory.",TITLE,0);
|
||||
return 0;
|
||||
}
|
||||
SMsgRegisterMessage(NULL,WM_ERASEBKGND,OnEraseBkgnd);
|
||||
if (!Connect())
|
||||
return 0;
|
||||
ChooseStartingLocations();
|
||||
scrollpos.x = max(0,min(WORLDMAPCX*TILECX-SCROLLCX,playerpos[localplayer].x*TILECX-SCROLLCX/2));
|
||||
scrollpos.y = max(0,min(WORLDMAPCY*TILECY-SCROLLCY,playerpos[localplayer].y*TILECY-SCROLLCY/2));
|
||||
SDrawUpdatePalette(0,256,&pe[0]);
|
||||
SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose);
|
||||
SMsgRegisterMessage(NULL,WM_LBUTTONDOWN,OnButtonDown);
|
||||
SMsgRegisterMessage(NULL,WM_PAINT ,OnPaint);
|
||||
SMsgRegisterMessage(NULL,WM_RBUTTONDOWN,OnButtonDown);
|
||||
SMsgRegisterKeyDown(NULL,VK_ESCAPE ,OnVkEscape);
|
||||
SMsgRegisterKeyDown(NULL,VK_SPACE ,OnVkSpace);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
BOOL LoadGraphicsData () {
|
||||
|
||||
// LOAD IN THE CURSOR
|
||||
cursor = (LPBYTE)ALLOC(32*32);
|
||||
if (!cursor)
|
||||
return 0;
|
||||
if (!SBmpLoadImage(ARTDIR "cursor.pcx",NULL,cursor,32*32))
|
||||
return 0;
|
||||
|
||||
// LOAD IN THE PLAYER IMAGE
|
||||
player = (LPBYTE)ALLOC(32*32);
|
||||
if (!player)
|
||||
return 0;
|
||||
if (!SBmpLoadImage(ARTDIR "player.pcx",NULL,player,32*32))
|
||||
return 0;
|
||||
|
||||
// LOAD IN THE WORLD MAP
|
||||
worldmap = (LPBYTE)ALLOC(WORLDMAPCX*WORLDMAPCY);
|
||||
if (!worldmap)
|
||||
return 0;
|
||||
if (!SBmpLoadImage(ARTDIR "map.pcx",NULL,worldmap,WORLDMAPCX*WORLDMAPCY))
|
||||
return 0;
|
||||
|
||||
// LOAD IN THE GRAPHICS TILESET
|
||||
tileset = (LPBYTE)ALLOC(TILES*TILECX*TILECY);
|
||||
if (!tileset)
|
||||
return 0;
|
||||
if (!SBmpLoadImage(ARTDIR "tileset.pcx",&pe[0],tileset,TILES*TILECX*TILECY))
|
||||
return 0;
|
||||
|
||||
// CREATE A FONT
|
||||
HSGDIFONT font;
|
||||
{
|
||||
HFONT winfont = CreateFont(-17,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET,
|
||||
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,
|
||||
VARIABLE_PITCH | FF_ROMAN,TEXT("Times New Roman"));
|
||||
if (!SGdiImportFont(winfont,&font))
|
||||
return 0;
|
||||
DeleteObject(winfont);
|
||||
}
|
||||
if (!SGdiSelectObject(font))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void MovePlayer (DWORD player) {
|
||||
int xdir = orderpos[player].x-playerpos[player].x;
|
||||
xdir = (xdir > 0) ? 1 : xdir ? -1 : 0;
|
||||
int ydir = orderpos[player].y-playerpos[player].y;
|
||||
ydir = (ydir > 0) ? 1 : ydir ? -1 : 0;
|
||||
if (xdir) {
|
||||
BYTE tile = *(worldmap+playerpos[player].y*WORLDMAPCX+playerpos[player].x+xdir);
|
||||
if ((tile >= TILE_GRASS) && (tile != TILE_MOUNTAINS))
|
||||
playerpos[player].x += xdir;
|
||||
}
|
||||
if (ydir) {
|
||||
BYTE tile = *(worldmap+(playerpos[player].y+ydir)*WORLDMAPCX+playerpos[player].x);
|
||||
if ((tile >= TILE_GRASS) && (tile != TILE_MOUNTAINS))
|
||||
playerpos[player].y += ydir;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void CALLBACK OnButtonDown (LPPARAMS params) {
|
||||
if (started) {
|
||||
DWORD order[3] = {ORDER_MOVE,
|
||||
(scrollpos.x+LOWORD(params->lparam))/TILECX,
|
||||
(scrollpos.y+HIWORD(params->lparam))/TILECY};
|
||||
IssueOrder(&order[0],3);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void CALLBACK OnClose (LPPARAMS) {
|
||||
Destroy();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void CALLBACK OnEraseBkgnd (LPPARAMS params) {
|
||||
params->useresult = 1;
|
||||
params->result = 1;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void CALLBACK OnPaint (LPPARAMS params) {
|
||||
if (scrollbuffer && tileset) {
|
||||
RECT rect = {0,0,SCROLLTILESX-1,SCROLLTILESY-1};
|
||||
FillScrollBuffer(&rect);
|
||||
DrawScreen();
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void CALLBACK OnVkEscape (LPPARAMS) {
|
||||
DWORD order = ORDER_QUIT;
|
||||
IssueOrder(&order,1);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void CALLBACK OnVkSpace (LPPARAMS) {
|
||||
if (!started) {
|
||||
DWORD order = ORDER_START;
|
||||
IssueOrder(&order,1);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
BOOL ProcessOrders () {
|
||||
|
||||
// MAKE SURE THERE ARE ALWAYS AT LEAST TWO ORDERS IN TRANSIT
|
||||
{
|
||||
DWORD turns;
|
||||
if (SNetGetTurnsInTransit(&turns)) {
|
||||
while (turns < 2) {
|
||||
DWORD order = ORDER_NULL;
|
||||
IssueOrder(&order,1);
|
||||
++turns;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GATHER ORDERS FROM ALL PLAYERS
|
||||
LPDWORD data[MAXPLAYERS];
|
||||
DWORD databytes[MAXPLAYERS];
|
||||
DWORD playerstatus[MAXPLAYERS];
|
||||
BOOL insync = 1;
|
||||
{
|
||||
int timeout = 20;
|
||||
while ((!SNetReceiveTurns(0,players,(LPVOID *)&data[0],&databytes[0],&playerstatus[0])) &&
|
||||
--timeout) {
|
||||
insync = 0;
|
||||
Sleep(50);
|
||||
}
|
||||
if (!timeout) {
|
||||
SDrawMessageBox("network error",TITLE,0);
|
||||
SDrawPostClose();
|
||||
}
|
||||
}
|
||||
|
||||
// PROCESS EACH PLAYER'S ORDERS
|
||||
for (DWORD player = 0; player < players; ++player)
|
||||
if (data[player] && databytes[player])
|
||||
switch (*data[player]) {
|
||||
|
||||
case ORDER_START:
|
||||
started = 1;
|
||||
break;
|
||||
|
||||
case ORDER_MOVE:
|
||||
orderpos[player].x = *(data[player]+1);
|
||||
orderpos[player].y = *(data[player]+2);
|
||||
break;
|
||||
|
||||
case ORDER_QUIT:
|
||||
SDrawPostClose();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return insync;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
BOOL UpdateScrollVelocity () {
|
||||
|
||||
// DETERMINE THE SCROLL DIRECTION
|
||||
POINT pos;
|
||||
GetCursorPos(&pos);
|
||||
int x = (pos.x == 639) ? 1 : pos.x ? 0 : -1;
|
||||
int y = (pos.y == 479) ? 1 : pos.y ? 0 : -1;
|
||||
int velx = (scrollvel.x > 0) ? 1 : scrollvel.x ? -1 : 0;
|
||||
int vely = (scrollvel.y > 0) ? 1 : scrollvel.y ? -1 : 0;
|
||||
|
||||
// UPDATE THE X VELOCITY
|
||||
if (x) {
|
||||
if ((velx != x) || (abs(scrollvel.x) < 24))
|
||||
scrollvel.x += (abs(scrollvel.x) > 12) ? 2*x : x;
|
||||
}
|
||||
else if (velx)
|
||||
scrollvel.x -= velx;
|
||||
|
||||
// UPDATE THE Y VELOCITY
|
||||
if (y) {
|
||||
if ((vely != y) || (abs(scrollvel.y) < 16))
|
||||
scrollvel.y += (abs(scrollvel.y) > 8) ? 2*y : y;
|
||||
}
|
||||
else if (vely)
|
||||
scrollvel.y -= vely;
|
||||
|
||||
return (scrollvel.x || scrollvel.y);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) {
|
||||
if (!Initialize(instance)) {
|
||||
Destroy();
|
||||
return 1;
|
||||
}
|
||||
return SMsgDoMessageLoop(IdleProc);
|
||||
}
|
||||
Reference in New Issue
Block a user