add new simple example project code (no assets file yet)
This commit is contained in:
parent
4321b7751d
commit
e35ecef214
492
example/ackinfo.c
Normal file
492
example/ackinfo.c
Normal file
|
@ -0,0 +1,492 @@
|
||||||
|
// Function to process and ACK resource file
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include "ack3d.h"
|
||||||
|
#include "ackeng.h"
|
||||||
|
#include "ackext.h"
|
||||||
|
|
||||||
|
// The application MUST have a global variable called ae for use by this
|
||||||
|
// routine.
|
||||||
|
extern ACKENG *ae;
|
||||||
|
|
||||||
|
// Globals
|
||||||
|
int LineNumber;
|
||||||
|
char LineBuffer[200];
|
||||||
|
short LastObjectIndex;
|
||||||
|
int MapResource;
|
||||||
|
int PalResource;
|
||||||
|
int ResScreenBack;
|
||||||
|
int ResScrollBack;
|
||||||
|
|
||||||
|
// Creates the correct arrays for displaying a rotating background
|
||||||
|
void ProcessBackDrop(UCHAR *bPtr) {
|
||||||
|
int i, j, pos;
|
||||||
|
UCHAR *aPtr;
|
||||||
|
|
||||||
|
for (i = 0; i < 320; i++) {
|
||||||
|
pos = i + 4;
|
||||||
|
aPtr = BackArray[i];
|
||||||
|
for (j = 0; j < 100; j++) {
|
||||||
|
*aPtr++ = bPtr[pos];
|
||||||
|
pos += 320;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 320; i < 640; i++) {
|
||||||
|
pos = (i - 320) + 32004;
|
||||||
|
aPtr = BackArray[i];
|
||||||
|
for (j = 0; j < 100; j++) {
|
||||||
|
*aPtr++ = bPtr[pos];
|
||||||
|
pos += 320;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Loads a background image and processes the image into the
|
||||||
|
// separate slices for use at display time. Currently a background image
|
||||||
|
// can be 640 columns wide. This number can be made dynamic if needbe and would
|
||||||
|
// need to be changed in the routine below and in the DrawBackground routine
|
||||||
|
// in the ACK engine.
|
||||||
|
int LoadBackDrop(void) {
|
||||||
|
UCHAR *bPtr;
|
||||||
|
|
||||||
|
if (ResScrollBack) {
|
||||||
|
bPtr = AckReadiff((char*)ResScrollBack);
|
||||||
|
if (bPtr == NULL)
|
||||||
|
return 8;
|
||||||
|
|
||||||
|
ProcessBackDrop(bPtr);
|
||||||
|
AckFree(bPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reads a text line from the resource file
|
||||||
|
int ReadLine(void) {
|
||||||
|
int len;
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
while (len < 200) {
|
||||||
|
if (read(rsHandle, &LineBuffer[len], 1) != 1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ch = LineBuffer[len];
|
||||||
|
if (ch == 10)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ch == 13)
|
||||||
|
break;
|
||||||
|
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
LineBuffer[len] = '\0';
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skips to the next parameter in a text line
|
||||||
|
char *GetNextParm(char *s) {
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
while (*s) {
|
||||||
|
ch = *s++;
|
||||||
|
if (ch == ',') {
|
||||||
|
while (*s) {
|
||||||
|
ch = *s;
|
||||||
|
if (ch != ',' && ch != ' ' && ch != '\t')
|
||||||
|
return s;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loads a wall bitmap specified in info file
|
||||||
|
int LoadWall(void) {
|
||||||
|
int wnum, rnum, result;
|
||||||
|
long pos;
|
||||||
|
char *lb;
|
||||||
|
|
||||||
|
lb = LineBuffer; // Info file buffer
|
||||||
|
wnum = atoi(lb); // Wall number to load into
|
||||||
|
|
||||||
|
lb = GetNextParm(lb);
|
||||||
|
|
||||||
|
if (lb == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
rnum = atoi(lb); // Resource number
|
||||||
|
|
||||||
|
pos = lseek(rsHandle, 0L, SEEK_CUR);
|
||||||
|
result = AckLoadWall(ae, (short)wnum, (char *)rnum);
|
||||||
|
lseek(rsHandle, pos, SEEK_SET);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loads an object bitmap specified in info file
|
||||||
|
int LoadObject(void) {
|
||||||
|
int onum, rnum, result;
|
||||||
|
long pos;
|
||||||
|
char *lb;
|
||||||
|
|
||||||
|
lb = LineBuffer;
|
||||||
|
onum = atoi(lb); // Object bitmap number
|
||||||
|
|
||||||
|
lb = GetNextParm(lb);
|
||||||
|
|
||||||
|
if (lb == NULL)
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
rnum = atoi(lb); // Resource number
|
||||||
|
pos = lseek(rsHandle, 0L, SEEK_CUR);
|
||||||
|
result = AckLoadObject(ae, (short)onum, (char *)rnum);
|
||||||
|
lseek(rsHandle, pos, SEEK_SET);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip any leading spaces in the string
|
||||||
|
// NOTE: Actually modifies the string passed!
|
||||||
|
char *SkipSpaces(char *s) {
|
||||||
|
while (*s == ' ' || *s == '\t' || *s == ',')
|
||||||
|
strcpy(s, &s[1]);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates and object of the desired style
|
||||||
|
int CreateObject(void) {
|
||||||
|
short onum, vnum;
|
||||||
|
short result, oType;
|
||||||
|
short NumViews, bmPerView;
|
||||||
|
USHORT flags;
|
||||||
|
char *lb;
|
||||||
|
OBJSEQ os;
|
||||||
|
|
||||||
|
lb = LineBuffer;
|
||||||
|
|
||||||
|
if (!strnicmp(lb, "NUMBER:", 7)) {
|
||||||
|
lb = &lb[7];
|
||||||
|
onum = (short)atoi(lb);
|
||||||
|
if (onum < 1 || onum > MAX_OBJECTS)
|
||||||
|
return -3;
|
||||||
|
|
||||||
|
result = AckCreateObject(ae, (short)onum);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
LastObjectIndex = onum;
|
||||||
|
lb = GetNextParm(lb);
|
||||||
|
if (lb == NULL)
|
||||||
|
return -4;
|
||||||
|
|
||||||
|
ae->ObjList[onum]->Speed = (short)atoi(lb);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
onum = LastObjectIndex; // Object number
|
||||||
|
|
||||||
|
oType = 0;
|
||||||
|
|
||||||
|
if (!strnicmp(lb, "CREATE:", 7)) {
|
||||||
|
oType = NO_CREATE;
|
||||||
|
lb = &lb[7];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(lb, "DESTROY:", 8)) {
|
||||||
|
oType = NO_DESTROY;
|
||||||
|
lb = &lb[8];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(lb, "WALK:", 5)) {
|
||||||
|
oType = NO_WALK;
|
||||||
|
lb = &lb[5];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(lb, "ATTACK:", 7)) {
|
||||||
|
oType = NO_ATTACK;
|
||||||
|
lb = &lb[7];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(lb, "INTERACT:", 9)) {
|
||||||
|
oType = NO_INTERACT;
|
||||||
|
lb = &lb[9];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!oType)
|
||||||
|
return -5;
|
||||||
|
|
||||||
|
lb = SkipSpaces(lb);
|
||||||
|
if (lb == NULL)
|
||||||
|
return -6;
|
||||||
|
|
||||||
|
flags = 0;
|
||||||
|
strupr(lb);
|
||||||
|
|
||||||
|
if (strstr(lb, "ANIMATE") != NULL)
|
||||||
|
flags |= OF_ANIMATE;
|
||||||
|
|
||||||
|
if (strstr(lb, "MOVEABLE") != NULL)
|
||||||
|
flags |= OF_MOVEABLE;
|
||||||
|
|
||||||
|
if (strstr(lb, "PASSABLE") != NULL)
|
||||||
|
flags |= OF_PASSABLE;
|
||||||
|
|
||||||
|
if (strstr(lb, "MULTIVIEW") != NULL)
|
||||||
|
flags |= OF_MULTIVIEW;
|
||||||
|
|
||||||
|
if (strstr(lb, "SHOWONCE") != NULL)
|
||||||
|
flags |= OF_ANIMONCE;
|
||||||
|
|
||||||
|
lb = GetNextParm(lb);
|
||||||
|
if (lb == NULL)
|
||||||
|
return-5;
|
||||||
|
|
||||||
|
NumViews = (short)atoi(lb);
|
||||||
|
if (NumViews < 1)
|
||||||
|
return -6;
|
||||||
|
|
||||||
|
lb = GetNextParm(lb);
|
||||||
|
if (lb == NULL)
|
||||||
|
return -7;
|
||||||
|
|
||||||
|
bmPerView = (short)atoi(lb);
|
||||||
|
if (bmPerView < 1)
|
||||||
|
return -7;
|
||||||
|
|
||||||
|
vnum = (short)(NumViews * bmPerView);
|
||||||
|
if (vnum > MAX_OBJ_BITMAPS)
|
||||||
|
return -8;
|
||||||
|
|
||||||
|
lb = GetNextParm(lb);
|
||||||
|
if (lb == NULL)
|
||||||
|
return -9;
|
||||||
|
|
||||||
|
vnum = 0;
|
||||||
|
|
||||||
|
while (lb != NULL && vnum < MAX_OBJ_BITMAPS) {
|
||||||
|
os.bitmaps[vnum++] = (short)atoi(lb);
|
||||||
|
lb = GetNextParm(lb);
|
||||||
|
}
|
||||||
|
|
||||||
|
os.bmBitmapsPerView = bmPerView;
|
||||||
|
os.flags = flags;
|
||||||
|
os.MaxBitmaps = bmPerView;
|
||||||
|
os.bmSides = NumViews;
|
||||||
|
|
||||||
|
result = (short)AckSetupObject(ae, onum, oType, &os);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reads the ASCII info file and processes the commands.
|
||||||
|
int ProcessInfoFile(void) {
|
||||||
|
int result;
|
||||||
|
int mode;
|
||||||
|
long pos;
|
||||||
|
|
||||||
|
LineNumber = 0;
|
||||||
|
// Position to start of info file within resource file
|
||||||
|
lseek(rsHandle, rbaTable[0], SEEK_SET);
|
||||||
|
|
||||||
|
mode = result = 0;
|
||||||
|
|
||||||
|
while (!result) {
|
||||||
|
LineNumber++;
|
||||||
|
if (!ReadLine())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (*LineBuffer == ';')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "END:", 4))
|
||||||
|
break;
|
||||||
|
|
||||||
|
printf(".");
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case 1: // Read walls
|
||||||
|
if (!strnicmp(LineBuffer, "LOADTYPE:", 9)) {
|
||||||
|
ae->bmLoadType = (short)atoi(&LineBuffer[9]); // Sets for GIF or BBM
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "ENDBITMAPS:", 11))
|
||||||
|
mode = 4;
|
||||||
|
else
|
||||||
|
result = LoadWall();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // Object bitmaps
|
||||||
|
if (!strnicmp(LineBuffer, "LOADTYPE:", 9)) { // Sets for GIF or BBM
|
||||||
|
ae->bmLoadType = (short)atoi(&LineBuffer[9]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "ENDBITMAPS:", 11))
|
||||||
|
mode = 5;
|
||||||
|
else
|
||||||
|
result = LoadObject();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // Create Object
|
||||||
|
if (!strnicmp(LineBuffer, "ENDDESC:", 8))
|
||||||
|
mode = 5;
|
||||||
|
else
|
||||||
|
result = CreateObject();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: // Walls topic
|
||||||
|
if (!strnicmp(LineBuffer, "BITMAPS:", 8))
|
||||||
|
mode = 1;
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "ENDWALLS:", 9))
|
||||||
|
mode = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: // Objects topic
|
||||||
|
if (!strnicmp(LineBuffer, "BITMAPS:", 8))
|
||||||
|
mode = 2;
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "OBJDESC:", 8))
|
||||||
|
mode = 3;
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "ENDOBJECTS:", 11))
|
||||||
|
mode = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (!strnicmp(LineBuffer, "WALLS:", 6)) {
|
||||||
|
mode = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "OBJECTS:", 8)) {
|
||||||
|
mode = 5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "MAPFILE:", 8)) {
|
||||||
|
MapResource = atoi(&LineBuffer[8]);
|
||||||
|
pos = lseek(rsHandle, 0L, SEEK_CUR);
|
||||||
|
result = AckReadMapFile(ae, (char*)MapResource);
|
||||||
|
lseek(rsHandle, pos, SEEK_SET);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "PALFILE:", 8)) {
|
||||||
|
PalResource = atoi(&LineBuffer[8]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "XPLAYER:", 8)) {
|
||||||
|
ae->xPlayer = (short)atoi(&LineBuffer[8]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "YPLAYER:", 8)) {
|
||||||
|
ae->yPlayer = (short)atoi(&LineBuffer[8]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "PLAYERANGLE:", 12)) {
|
||||||
|
ae->PlayerAngle = (short)atoi(&LineBuffer[12]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "SCREENBACK:", 11)) {
|
||||||
|
ResScreenBack = atoi(&LineBuffer[11]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "SCROLLBACK:", 11)) {
|
||||||
|
ResScrollBack = atoi(&LineBuffer[11]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "TOPCOLOR:", 9)) {
|
||||||
|
ae->TopColor = (short)atoi(&LineBuffer[9]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "BOTTOMCOLOR:", 12)) {
|
||||||
|
ae->BottomColor = (short)atoi(&LineBuffer[12]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "SHADING:", 8)) {
|
||||||
|
strupr(LineBuffer);
|
||||||
|
if (strstr(&LineBuffer[8], "OFF") != NULL)
|
||||||
|
ae->LightFlag = SHADING_OFF;
|
||||||
|
else
|
||||||
|
ae->LightFlag = SHADING_ON;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "FLOORS:", 7)) {
|
||||||
|
strupr(LineBuffer);
|
||||||
|
if (strstr(&LineBuffer[7], "OFF") != NULL)
|
||||||
|
ae->SysFlags |= SYS_SOLID_FLOOR;
|
||||||
|
else
|
||||||
|
ae->SysFlags &= ~SYS_SOLID_FLOOR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "CEILING:", 8)) {
|
||||||
|
strupr(LineBuffer);
|
||||||
|
if (strstr(&LineBuffer[8], "OFF") != NULL)
|
||||||
|
ae->SysFlags |= SYS_SOLID_CEIL;
|
||||||
|
else
|
||||||
|
ae->SysFlags &= ~SYS_SOLID_CEIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "SINGLEBITMAP:", 13)) {
|
||||||
|
strupr(LineBuffer);
|
||||||
|
if (strstr(&LineBuffer[13], "ON") != NULL)
|
||||||
|
ae->SysFlags |= SYS_SINGLE_BMP;
|
||||||
|
else
|
||||||
|
ae->SysFlags &= ~SYS_SINGLE_BMP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "CEILBITMAP:", 11)) {
|
||||||
|
ae->CeilBitmap = (short)atoi(&LineBuffer[11]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "FLOORBITMAP:", 12)) {
|
||||||
|
ae->FloorBitmap = (short)atoi(&LineBuffer[12]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "RESOLUTION:", 11)) {
|
||||||
|
Resolution = (short)atoi(&LineBuffer[11]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strnicmp(LineBuffer, "LOADTYPE:", 9)) {
|
||||||
|
ae->bmLoadType = (short)atoi(&LineBuffer[9]); // Sets for GIF or BBM
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
227
example/example.c
Normal file
227
example/example.c
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
/*
|
||||||
|
* Example ACK-3D Application
|
||||||
|
* --------------------------
|
||||||
|
*
|
||||||
|
* This is just a bare-bones simple "walkaround" demo application that lets
|
||||||
|
* you walk through a map.
|
||||||
|
*
|
||||||
|
* The ACK-3D demo programs, FDEMO, MALL, and also the Windows demo game
|
||||||
|
* "Station Escape", all include a fair bit more complexity and a bunch of
|
||||||
|
* hard-coded magic numbers, and other messyness.
|
||||||
|
*
|
||||||
|
* This example program is intended to be _super_ simple to get into.
|
||||||
|
* Unfortunately, ACK-3D requires a non-trivial amount of game resource file
|
||||||
|
* loading to be performed to get even a simple level up and running, but
|
||||||
|
* those details are mostly re-usable and is kept in a separate source file.
|
||||||
|
* This source file just contains the basics to initialize the engine and
|
||||||
|
* move a player around a game world.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <conio.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "ack3d.h"
|
||||||
|
#include "ackeng.h"
|
||||||
|
#include "ackext.h"
|
||||||
|
|
||||||
|
#define KEY_RIGHT 77
|
||||||
|
#define KEY_UP 72
|
||||||
|
#define KEY_LEFT 75
|
||||||
|
#define KEY_DOWN 80
|
||||||
|
#define KEY_SPACE 57
|
||||||
|
#define KEY_ESCAPE 1
|
||||||
|
|
||||||
|
#define TURN_SPEED 5
|
||||||
|
#define TURN_SPEED_DECAY 3
|
||||||
|
#define MOVE_SPEED 5
|
||||||
|
#define MOVE_SPEED_DECAY 3
|
||||||
|
#define BASE_MOVE_AMOUNT 8
|
||||||
|
#define BASE_TURN_AMOUNT INT_ANGLE_4
|
||||||
|
|
||||||
|
// ACK3D bitmap loading routines, such as AckReadiff(), will automatically
|
||||||
|
// populate (and re-populate) this array with palette found in that image
|
||||||
|
// file. still, this must be manually set with AckSetPalette()
|
||||||
|
extern unsigned char colordat[];
|
||||||
|
|
||||||
|
int ProcessInfoFile(void);
|
||||||
|
|
||||||
|
// this is the main ACK3D engine structure. holds the map, bitmaps, objects,
|
||||||
|
// and also the current state of the game world (as far as ACK3D is concerned)
|
||||||
|
ACKENG *ae;
|
||||||
|
|
||||||
|
// this game loop made semi-overcomplicated by rudimentary turn/movement
|
||||||
|
// acceleration logic
|
||||||
|
void GameLoop(void) {
|
||||||
|
int newAngle;
|
||||||
|
int moveSpeed = 0;
|
||||||
|
int moveAmount = 0;
|
||||||
|
int turnSpeed = 0;
|
||||||
|
int turnAmount = 0;
|
||||||
|
|
||||||
|
AckBuildView();
|
||||||
|
AckDisplayScreen();
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
moveAmount = BASE_MOVE_AMOUNT + moveSpeed;
|
||||||
|
turnAmount = BASE_TURN_AMOUNT + turnSpeed;
|
||||||
|
|
||||||
|
if (AckKeys[KEY_ESCAPE]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AckKeys[KEY_LEFT]) {
|
||||||
|
turnSpeed += TURN_SPEED;
|
||||||
|
ae->PlayerAngle -= turnAmount;
|
||||||
|
if (ae->PlayerAngle < 0)
|
||||||
|
ae->PlayerAngle += INT_ANGLE_360;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AckKeys[KEY_RIGHT]) {
|
||||||
|
turnSpeed += TURN_SPEED;
|
||||||
|
ae->PlayerAngle += turnAmount;
|
||||||
|
if (ae->PlayerAngle >= INT_ANGLE_360)
|
||||||
|
ae->PlayerAngle -= INT_ANGLE_360;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AckKeys[KEY_UP]) {
|
||||||
|
moveSpeed += MOVE_SPEED;
|
||||||
|
|
||||||
|
// this function handles collision detection for you reasonably
|
||||||
|
// well actually. pretty handy
|
||||||
|
AckMovePOV(ae->PlayerAngle, moveAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AckKeys[KEY_DOWN]) {
|
||||||
|
moveSpeed += MOVE_SPEED;
|
||||||
|
newAngle = ae->PlayerAngle + INT_ANGLE_180;
|
||||||
|
if (newAngle >= INT_ANGLE_360)
|
||||||
|
newAngle -= INT_ANGLE_360;
|
||||||
|
AckMovePOV(newAngle, moveAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AckKeys[KEY_SPACE]) {
|
||||||
|
AckCheckDoorOpen(ae->xPlayer, ae->yPlayer, ae->PlayerAngle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// updates object animation and various object state things
|
||||||
|
AckCheckObjectMovement();
|
||||||
|
|
||||||
|
// renders the ack3d world to an offscreen buffer. also updates some
|
||||||
|
// ack3d state (such as door opening/closing)
|
||||||
|
AckBuildView();
|
||||||
|
|
||||||
|
// copies offscreen buffer to vga framebuffer
|
||||||
|
AckDisplayScreen();
|
||||||
|
|
||||||
|
moveSpeed -= MOVE_SPEED_DECAY;
|
||||||
|
if (moveSpeed < 0)
|
||||||
|
moveSpeed = 0;
|
||||||
|
if (moveSpeed > 16)
|
||||||
|
moveSpeed = 16;
|
||||||
|
|
||||||
|
turnSpeed -= TURN_SPEED_DECAY;
|
||||||
|
if (turnSpeed < 0)
|
||||||
|
turnSpeed = 0;
|
||||||
|
if (turnSpeed > 16)
|
||||||
|
turnSpeed = 16;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int result;
|
||||||
|
|
||||||
|
printf("Example ACK-3D application\n");
|
||||||
|
|
||||||
|
ae = (ACKENG*)malloc(sizeof(ACKENG));
|
||||||
|
memset(ae, 0, sizeof(ACKENG));
|
||||||
|
|
||||||
|
// ack3d renderer viewport size. on 486 and lower-spec machines, you
|
||||||
|
// probably do not want this to be at full 320x200 for performance reasons
|
||||||
|
// even reducing 320x200 by 20% makes a nice, noticeable difference!
|
||||||
|
ae->WinStartX = 0;
|
||||||
|
ae->WinStartY = 0;
|
||||||
|
ae->WinEndX = 319;
|
||||||
|
ae->WinEndY = 199;
|
||||||
|
|
||||||
|
// various other flags that can be set too
|
||||||
|
ae->LightFlag = SHADING_ON;
|
||||||
|
ae->DoorSpeed = 3;
|
||||||
|
|
||||||
|
printf("Initializing ACK-3D\n");
|
||||||
|
|
||||||
|
// main ack3d initialization. AckInitialize builds up a bunch of lookup
|
||||||
|
// tables and other global engine things like that. kit.ovl contains a
|
||||||
|
// bunch of pre-calculate trig lookup tables. if it was not opened before
|
||||||
|
// AckInitialize is called, then AckInitialize tries to find a file called
|
||||||
|
// trig.dat in the current directory.
|
||||||
|
|
||||||
|
result = AckOpenResource("kit.ovl");
|
||||||
|
if (result) {
|
||||||
|
printf("Error opening kit.ovl\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = AckInitialize(ae);
|
||||||
|
if (result) {
|
||||||
|
printf("AckInitialize failed\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
AckCloseResource();
|
||||||
|
|
||||||
|
// the big whammy. pics.dtf has basically all your game assets and takes
|
||||||
|
// the longest. ProcessInfoFile walks through a ".inf" file that should
|
||||||
|
// have been packed in pics.dtf at the first slot. that file (which is
|
||||||
|
// just a text file) has directives to load everything else (map, bitmaps,
|
||||||
|
// object definitions, etc)
|
||||||
|
|
||||||
|
printf("Processing pics.dtf\n");
|
||||||
|
result = AckOpenResource("pics.dtf");
|
||||||
|
if (result) {
|
||||||
|
printf("Error opening pics.dtf\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = ProcessInfoFile();
|
||||||
|
if (result) {
|
||||||
|
printf("Error while processing. Result code %d\n", result);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Processing scrolling backdrop\n");
|
||||||
|
// processes any (optional) scrolling backdrop that was loaded so it is
|
||||||
|
// ready to be rendered
|
||||||
|
LoadBackDrop();
|
||||||
|
|
||||||
|
AckCloseResource();
|
||||||
|
|
||||||
|
printf("Finished initializing\n");
|
||||||
|
|
||||||
|
// the main ack3d rendering functions all assume that the various fields
|
||||||
|
// in ACKENG have been copied into a whole bunch of global variables. this
|
||||||
|
// architecture was used for performance reasons.
|
||||||
|
// ACKENG pointer fields are simply copied, so modifying the actual data
|
||||||
|
// should be fine during runtime (if you were so inclined) without needing
|
||||||
|
// to call this function again.
|
||||||
|
// other flags/number fields from ACKENG are copied, so if you needed to
|
||||||
|
// change this type of thing during runtime, you would need to call this
|
||||||
|
// function again for the change to take effect!
|
||||||
|
AckRegisterStructure(ae);
|
||||||
|
|
||||||
|
AckSetupKeyboard();
|
||||||
|
AckSetVGAmode();
|
||||||
|
AckSetPalette(colordat);
|
||||||
|
|
||||||
|
GameLoop();
|
||||||
|
|
||||||
|
AckWrapUp(ae);
|
||||||
|
AckSetTextMode();
|
||||||
|
|
||||||
|
if (kbhit())
|
||||||
|
getch();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
BIN
example/kit.ovl
Normal file
BIN
example/kit.ovl
Normal file
Binary file not shown.
58
example/makefile
Normal file
58
example/makefile
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
target_config = debug
|
||||||
|
|
||||||
|
target_name = example
|
||||||
|
|
||||||
|
acklib_incdir = ..\ack_lib
|
||||||
|
acklib_lib = ..\ack_lib\acklib.lib
|
||||||
|
|
||||||
|
object_files = &
|
||||||
|
example.obj &
|
||||||
|
ackinfo.obj
|
||||||
|
|
||||||
|
cc_flags_debug = /d2 /zp1 /4r /fp3 /j
|
||||||
|
cc_flags_release = /d1+ /zp1 /4r /fp3 /onetx /j
|
||||||
|
cc_flags = /mf /i=$(acklib_incdir) $(cc_flags_$(target_config))
|
||||||
|
|
||||||
|
link_flags_debug = debug all
|
||||||
|
link_flags_release = debug all
|
||||||
|
link_flags = $(link_flags_$(target_config))
|
||||||
|
|
||||||
|
asm_flags_debug = /zi
|
||||||
|
asm_flags_release = /zi
|
||||||
|
asm_flags = /m /ml $(asm_flags_$(target_config))
|
||||||
|
|
||||||
|
.NOCHECK
|
||||||
|
build : $(target_name).exe
|
||||||
|
|
||||||
|
.c.obj: .AUTODEPEND
|
||||||
|
wcc386 $[. /zq $(cc_flags)
|
||||||
|
|
||||||
|
.asm.obj: .AUTODEPEND
|
||||||
|
tasm $[. /t $(asm_flags)
|
||||||
|
|
||||||
|
$(target_name).lnk: $(object_files)
|
||||||
|
%create $^@
|
||||||
|
%append $^@ NAME $(target_name).exe
|
||||||
|
%append $^@ SYSTEM DOS4G
|
||||||
|
%append $^@ OPTION QUIET
|
||||||
|
%append $^@ OPTION STACK=16k
|
||||||
|
%append $^@ LIBRARY $(acklib_lib)
|
||||||
|
@for %i in ($(object_files)) do %append $^@ FILE %i
|
||||||
|
|
||||||
|
$(target_name).exe: $(object_files) $(target_name).lnk
|
||||||
|
wlink $(link_flags) @$(target_name).lnk
|
||||||
|
|
||||||
|
clean : .SYMBOLIC
|
||||||
|
del *.obj
|
||||||
|
del *.err
|
||||||
|
del $(target_name).exe
|
||||||
|
del $(target_name).lnk
|
||||||
|
|
||||||
|
.NOCHECK
|
||||||
|
run : $(target_name).exe
|
||||||
|
$(target_name).exe
|
||||||
|
|
||||||
|
.NOCHECK
|
||||||
|
debug : $(target_name).exe
|
||||||
|
wd /swap /trap=rsi $(target_name).exe
|
||||||
|
|
Loading…
Reference in a new issue