From 6f75f4284a3123f46098c91ef388ec221b9fae2f Mon Sep 17 00:00:00 2001 From: gered Date: Sun, 10 Nov 2019 13:43:40 -0500 Subject: [PATCH] update example project (cleanups, enhancements, comments, etc) --- example/{ackinfo.c => assets.c} | 78 +++++++++++++++++---- example/assets.h | 28 ++++++++ example/example.c | 119 +++++++++++++++++++++++++++----- example/makefile | 2 +- 4 files changed, 193 insertions(+), 34 deletions(-) rename example/{ackinfo.c => assets.c} (85%) create mode 100644 example/assets.h diff --git a/example/ackinfo.c b/example/assets.c similarity index 85% rename from example/ackinfo.c rename to example/assets.c index 1e5d83c..b0a2729 100644 --- a/example/ackinfo.c +++ b/example/assets.c @@ -1,4 +1,17 @@ -// Function to process and ACK resource file +/* + * ACK-3D Resource File Processing + * ------------------------------- + * + * This source file is basically a copy of the ACKINFO.CPP file from the + * Windows example project discussed in chapter 14 of the book. + * + * There are some slight modifications that I've made though: + * - A global ACKENG structure is not assumed. You must pass one in to + * ProcessInfoFile() + * - Functions for processing a scrolling backdrop have been copied from the + * FDEMO/MALL demo projects and are included here since they are useful. + * - A function for loading a palette is included. + */ #include #include @@ -6,10 +19,6 @@ #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]; @@ -43,17 +52,57 @@ void ProcessBackDrop(UCHAR *bPtr) { } } +// Loads a bitmap (wall, object, screen/backdrop, etc) and returns a +// pointer to the bitmap data. The first 4-bytes of the returned pointer +// are the width and height (2 shorts) followed by the raw pixel data. +// The filename passed can be either a string specifying a file or an +// integer specifying a resource from the currently open resource file. +UCHAR* LoadBitmap(UCHAR bitmapType, char *fName) { + UCHAR *bPtr = NULL; + + switch (bitmapType) { + case BMLOAD_BBM: + bPtr = AckReadiff(fName); + break; + case BMLOAD_GIF: + bPtr = AckReadgif(fName); + break; + case BMLOAD_PCX: + bPtr = AckReadPCX(fName); + break; + } + + return bPtr; +} + +// Loads a 256 color palette and returns a pointer to the raw color data. +UCHAR* LoadPalette(int resource) { + UCHAR *ptr = NULL; + FILE *fp; + + fp = fdopen(rsHandle,"rb"); + if (!fp) + return NULL; + + fseek(fp, rbaTable[(int)resource], SEEK_SET); + + ptr = (UCHAR*)AckMalloc(768); + fread(ptr, 768, 1, fp); + + return ptr; +} + // 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) { +int LoadBackDrop(ACKENG *ae) { UCHAR *bPtr; if (ResScrollBack) { - bPtr = AckReadiff((char*)ResScrollBack); + bPtr = LoadBitmap(ae->bmLoadType, (char*)ResScrollBack); if (bPtr == NULL) return 8; @@ -64,6 +113,7 @@ int LoadBackDrop(void) { return 0; } + // Reads a text line from the resource file int ReadLine(void) { int len; @@ -110,7 +160,7 @@ char *GetNextParm(char *s) { } // Loads a wall bitmap specified in info file -int LoadWall(void) { +int LoadWall(ACKENG *ae) { int wnum, rnum, result; long pos; char *lb; @@ -133,7 +183,7 @@ int LoadWall(void) { } // Loads an object bitmap specified in info file -int LoadObject(void) { +int LoadObject(ACKENG *ae) { int onum, rnum, result; long pos; char *lb; @@ -164,7 +214,7 @@ char *SkipSpaces(char *s) { } // Creates and object of the desired style -int CreateObject(void) { +int CreateObject(ACKENG *ae) { short onum, vnum; short result, oType; short NumViews, bmPerView; @@ -289,7 +339,7 @@ int CreateObject(void) { } // Reads the ASCII info file and processes the commands. -int ProcessInfoFile(void) { +int ProcessInfoFile(ACKENG *ae) { int result; int mode; long pos; @@ -323,7 +373,7 @@ int ProcessInfoFile(void) { if (!strnicmp(LineBuffer, "ENDBITMAPS:", 11)) mode = 4; else - result = LoadWall(); + result = LoadWall(ae); break; case 2: // Object bitmaps @@ -335,14 +385,14 @@ int ProcessInfoFile(void) { if (!strnicmp(LineBuffer, "ENDBITMAPS:", 11)) mode = 5; else - result = LoadObject(); + result = LoadObject(ae); break; case 3: // Create Object if (!strnicmp(LineBuffer, "ENDDESC:", 8)) mode = 5; else - result = CreateObject(); + result = CreateObject(ae); break; case 4: // Walls topic diff --git a/example/assets.h b/example/assets.h new file mode 100644 index 0000000..31e1b75 --- /dev/null +++ b/example/assets.h @@ -0,0 +1,28 @@ +#ifndef ASSETS_H_INCLUDED +#define ASSETS_H_INCLUDED + +#include "ack3d.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern int LineNumber; +extern char LineBuffer[]; + +extern int MapResource; +extern int PalResource; +extern int ResScreenBack; +extern int ResScrollBack; + +UCHAR* LoadBitmap(UCHAR bitmapType, char *fName); +UCHAR* LoadPalette(int resource); +int LoadBackDrop(ACKENG *ae); +int ProcessInfoFile(ACKENG *ae); + +#ifdef __cplusplus +}; +#endif + +#endif + diff --git a/example/example.c b/example/example.c index ba1d96e..0b5b6c3 100644 --- a/example/example.c +++ b/example/example.c @@ -24,6 +24,7 @@ #include "ack3d.h" #include "ackeng.h" #include "ackext.h" +#include "assets.h" #define KEY_RIGHT 77 #define KEY_UP 72 @@ -33,23 +34,55 @@ #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 +#define TURN_SPEED_DECAY 2 +#define MOVE_SPEED 4 +#define MOVE_SPEED_DECAY 1 +#define BASE_MOVE_AMOUNT 5 +#define BASE_TURN_AMOUNT INT_ANGLE_2 // 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() +// file. still, this (or any other palette color data) must be manually set +// with AckSetPalette() extern unsigned char colordat[]; -int ProcessInfoFile(void); +// These are the ranges used for distance shading. Will need to be modified +// for the new color palette used. +// For ACK-3D's distance-based light shading to look best, your palette really +// needs to be designed with this in mind (and your bitmaps too). Many of the +// ACK-3D demo assets don't look so good with it. +ColorRange ranges[64] = { + 1,15, + 16,16, + 32,16, + 48,16, + 64,16, + 80,16, + 96,8, + 104,8, + 112,8, + 120,8, + 136,8, + 144,8, + 152,8, + 160,8, + 168,8, + 176,8, + 184,8, + 192,16, + 208,16, + 224,16, + 240,15, + 0,0 +}; // 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; +UCHAR *uiFrame = NULL; +UCHAR *palette = NULL; + // this game loop made semi-overcomplicated by rudimentary turn/movement // acceleration logic void GameLoop(void) { @@ -101,6 +134,7 @@ void GameLoop(void) { } if (AckKeys[KEY_SPACE]) { + AckKeys[KEY_SPACE] = 0; AckCheckDoorOpen(ae->xPlayer, ae->yPlayer, ae->PlayerAngle); } @@ -141,14 +175,10 @@ int main(int argc, char *argv[]) { // 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; + ae->WinStartX = 16; + ae->WinStartY = 12; + ae->WinEndX = 303; + ae->WinEndY = 158; printf("Initializing ACK-3D\n"); @@ -184,19 +214,48 @@ int main(int argc, char *argv[]) { return 1; } - result = ProcessInfoFile(); + result = ProcessInfoFile(ae); if (result) { - printf("Error while processing. Result code %d\n", result); + printf("Error while processing pics.dtf\n"); + printf("Result code %d\nLine number: %d\nLine: %s\n", result, LineNumber, LineBuffer); return 1; } printf("Processing scrolling backdrop\n"); // processes any (optional) scrolling backdrop that was loaded so it is // ready to be rendered - LoadBackDrop(); + LoadBackDrop(ae); + // if the resource file specified a screen/ui bitmap, then load it + if (ResScreenBack) { + uiFrame = LoadBitmap(ae->bmLoadType, (char*)ResScreenBack); + } + + // if the resource file specified a palette, then load it + if (PalResource) { + palette = LoadPalette(PalResource); + } + + // we won't be loading anything else from the resource file now, so we + // can close it AckCloseResource(); + // various other flags that can be set too. + // many of these can be set by the .INF file found in pics.dtf, so + // setting any of the ACKENG properties here would override the .INF + // settings. + ae->xPlayer = 32 *GRID_SIZE+(GRID_SIZE/2); // x = middle of grid 32 + ae->yPlayer = 32 *GRID_SIZE+(GRID_SIZE/2); // y = middle of grid 32 + ae->PlayerAngle = 0; + + ae->LightFlag = SHADING_OFF; + ae->DoorSpeed = 3; + + // Set palette for shading if needed + if (ae->LightFlag) { + AckSetupPalRanges(ae, ranges); + } + printf("Finished initializing\n"); // the main ack3d rendering functions all assume that the various fields @@ -212,10 +271,32 @@ int main(int argc, char *argv[]) { AckSetupKeyboard(); AckSetVGAmode(); - AckSetPalette(colordat); + + if (palette) { + // we loaded an explicitly specified palette from the resource file, + // so we'll set that one + AckSetPalette(palette); + } else { + // default to whatever the palette was from the last loaded bitmap + AckSetPalette(colordat); + } + + // draw the full screen/ui frame. ACK-3D won't overwrite this because + // our WinStart/WinEnd was set to only draw to the viewport box that our + // screen/ui frame bitmap should have (so we only need to render this + // bitmap once) + if (uiFrame) { + memcpy((void*)0xA0000, uiFrame+4, 64000); + } GameLoop(); + // anything allocated with AckMalloc can only be free'd with AckFree! + if (uiFrame) + AckFree(uiFrame); + if (palette) + AckFree(palette); + AckWrapUp(ae); AckSetTextMode(); diff --git a/example/makefile b/example/makefile index dd10982..662c9e4 100644 --- a/example/makefile +++ b/example/makefile @@ -7,7 +7,7 @@ acklib_lib = ..\ack_lib\acklib.lib object_files = & example.obj & - ackinfo.obj + assets.obj cc_flags_debug = /d2 /zp1 /4r /fp3 /j cc_flags_release = /d1+ /zp1 /4r /fp3 /onetx /j