Initial game loop implemented with fixed time step. Loads tiles and levels directly from uncompressed DAVE.EXE. Draws levels 20x10 tiles at a time with support for scrolling. Renderer is set to logical size of 320x200 with SDL automatically handling scaling and letterboxing. Makefiles work with MinGW now.

This commit is contained in:
Slipyx 2018-07-08 01:31:03 -04:00
parent 952b7099fb
commit 7c72390767
6 changed files with 125 additions and 14 deletions

View File

@ -33,7 +33,9 @@ CFLAGS_g +=
# libs
ifdef ISWIN
LDFLAGS_g +=
CFLAGS_g += -I../SDL2-2.0.8/include
LDFLAGS_g += -L../SDL2-2.0.8/lib \
-lmingw32 -lSDL2main -lSDL2 -lopengl32 -mconsole
else
CFLAGS_g += -I/usr/include/SDL2
LDFLAGS_g += -lSDL2

122
lmdave.c
View File

@ -7,55 +7,161 @@ game_assets_t* g_assets = NULL;
// initialize a new game state
void init_game() {
gs->quit = 1;
gs->current_level = 1;
gs->quit = 0;
gs->current_level = 0;
gs->view_x = 0;
gs->view_y = 0;
gs->scroll_x = 0;
// returns array of NUM_EXE_LEVELS that was loaded by the util lib
gs->levels = GetLevels();
}
// initialize game assets
void init_assets( SDL_Renderer* r ) {
// get loaded tile surface array from util lib
SDL_Surface** tileSfcs = GetTileSurfaces();
// convert each surface from util's array to g_asset texture array
for ( int i = 0; i < NUM_EXE_TILES; ++i ) {
g_assets->tile_tx[i] = SDL_CreateTextureFromSurface( r, tileSfcs[i] );
}
}
// poll input
void check_input() {
SDL_Event ev;
SDL_PollEvent( &ev );
if ( ev.type == SDL_QUIT ) gs->quit = 1;
if ( ev.type == SDL_KEYDOWN ) {
switch ( ev.key.keysym.sym ) {
case SDLK_RIGHT:
gs->scroll_x = 15; break;
case SDLK_LEFT:
gs->scroll_x = -15; break;
case SDLK_DOWN:
gs->current_level++; break;
case SDLK_UP:
gs->current_level--; break;
}
}
}
// update game logic
void update_game() {
if ( gs->current_level == 0xff ) gs->current_level = 0;
if ( gs->current_level > NUM_EXE_LEVELS - 1 )
gs->current_level = NUM_EXE_LEVELS - 1;
// scrolling
if ( gs->scroll_x > 0 ) {
if ( gs->view_x == 80 ) gs->scroll_x = 0;
else { gs->view_x++; gs->scroll_x--; }
}
if ( gs->scroll_x < 0 ) {
if ( gs->view_x == 0 ) gs->scroll_x = 0;
else { gs->view_x--; gs->scroll_x++; }
}
}
// draw to renderer
void render( SDL_Renderer* r ) {
// clear backbuffer
SDL_RenderClear( r );
SDL_Rect dst;
// draw level 20x10 tiles at 16x16px
for ( int j = 0; j < 10; ++j ) {
dst.y = j * 16;
dst.w = 16; dst.h = 16;
for ( int i = 0; i < 20; ++i ) {
dst.x = i * 16;
uint8_t til = gs->levels[gs->current_level].tiles[j * 100 + gs->view_x + i];
SDL_RenderCopy( r, g_assets->tile_tx[til], NULL, &dst );
}
}
// flip buffers
SDL_RenderPresent( r );
}
// rendering scale
const uint8_t R_SCALE = 3;
//const uint8_t R_SCALE = 3;
int main( int argc, char** argv ) {
// initialize resources from DAVE.EXE
// load resources from DAVE.EXE
LoadTiles();
LoadLevels();
gs = malloc( sizeof(game_state_t) );
init_game();
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
SDL_CreateWindowAndRenderer( 320 * R_SCALE, 200 * R_SCALE, 0, &window, &renderer );
if ( SDL_Init( SDL_INIT_VIDEO ) )
SDL_Log( "SDL Init error: %s\n", SDL_GetError() );
// SDL_Window* window = NULL;
// SDL_Renderer* renderer = NULL;
// if ( SDL_CreateWindowAndRenderer( 960, 720, SDL_WINDOW_RESIZABLE, &window, &renderer ) )
// SDL_Log( "SDL WindowAndRenderer error: %s\n", SDL_GetError() );
// create window and renderer
SDL_Window* window = SDL_CreateWindow( "lmdave", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
1280, 720, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL );
if ( window == NULL ) {
SDL_Log( "SDL_CreateWindow error: %s\n", SDL_GetError() );
SDL_Quit(); return EXIT_FAILURE;
}
SDL_Renderer* renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED
| SDL_RENDERER_PRESENTVSYNC );
if ( renderer == NULL ) {
SDL_DestroyWindow( window );
SDL_Log( "SDL_CreateRenderer error: %s\n", SDL_GetError() );
SDL_Quit(); return EXIT_FAILURE;
}
// set internal rendering size
SDL_RenderSetLogicalSize( renderer, 320, 200 );
//SDL_RenderSetScale( renderer, R_SCALE, R_SCALE );
// scaling hint
//SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "linear" );
g_assets = malloc( sizeof(game_assets_t) );
init_assets( renderer );
// tile surfaces should be converted as textures inside g_assets now
FreeTileSurfaces();
// clear initial frame
SDL_SetRenderDrawColor( renderer, 0, 0, 0, 0xff );
SDL_RenderClear( renderer );
// main loop
while ( !gs->quit ) {
// fixed timestep
uint32_t st = SDL_GetTicks();
check_input();
update_game();
render( renderer );
//uint32_t et = SDL_GetTicks();
uint32_t delay = 16 - (SDL_GetTicks() - st);
delay = delay > 16 ? 0 : delay;
SDL_Delay( delay );
}
// destroy each tile texture
for ( int i = 0; i < NUM_EXE_TILES; ++i )
SDL_DestroyTexture( g_assets->tile_tx[i] );
free( g_assets );
free( gs );
}
// cleanup SDL
SDL_DestroyRenderer( renderer );
SDL_DestroyWindow( window );
SDL_Quit();
return EXIT_SUCCESS;
}

View File

@ -10,9 +10,11 @@
typedef struct {
uint8_t quit;
uint8_t current_level;
// view and scroll are per tile
uint8_t view_x, view_y;
int8_t scroll_x;
level_t* levels; // grabbed from util
level_t* levels; // grabbed from util, NUM_EXE_LEVELS count
} game_state_t;
// game assets
@ -22,4 +24,3 @@ typedef struct {
} game_assets_t;
#endif

View File

@ -32,7 +32,9 @@ CFLAGS_g += -DUTIL_BIN
# libs
ifdef ISWIN
LDFLAGS_g +=
LDFLAGS_g += -L../../SDL2-2.0.8/lib \
-lmingw32 -lSDL2main -lSDL2 -mconsole
CFLAGS_g += -I../../SDL2-2.0.8/include
else
CFLAGS_g += -I/usr/include/SDL2
LDFLAGS_g += -lSDL2

View File

@ -1,6 +1,7 @@
// extract tilesxxx.bmp from uncompressed DAVE.EXE
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
#include "util.h"

View File

@ -20,7 +20,7 @@ void FreeTileSurfaces();
// byte[24] unsed padding
// note: player start and monster starts are hardcoded
typedef struct {
int8_t path[256];
uint8_t path[256];
uint8_t tiles[1000];
uint8_t pad[24];
} level_t;
@ -32,4 +32,3 @@ void SaveLevels();
void CreateWorldMap();
#endif