From 954a4b8b5119ad35ba4ee1783b2b43db5061fbec Mon Sep 17 00:00:00 2001 From: slipyx Date: Fri, 10 Aug 2018 23:19:28 -0400 Subject: [PATCH] Tile animations for world and entities. Implemented a fire timer for monsters to limit their fire rate. Preliminary sound support. --- build/res/jumpd8.wav | Bin 0 -> 7086 bytes build/res/pickupd8.wav | Bin 0 -> 7504 bytes draw.c | 20 +++++++++++++++++++- game.c | 22 +++++++++++++++++----- game.h | 10 ++++++++-- monster.c | 3 ++- monster.h | 1 + player.c | 8 ++++++-- player.h | 1 + sound.c | 18 ++++++++++++++++++ sound.h | 18 ++++++++++++++++++ world.c | 3 +++ 12 files changed, 93 insertions(+), 11 deletions(-) create mode 100644 build/res/jumpd8.wav create mode 100644 build/res/pickupd8.wav create mode 100644 sound.c create mode 100644 sound.h diff --git a/build/res/jumpd8.wav b/build/res/jumpd8.wav new file mode 100644 index 0000000000000000000000000000000000000000..630b180c080a97f430ebc3a8cf546e8b1db53f18 GIT binary patch literal 7086 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 literal 0 HcmV?d00001 diff --git a/build/res/pickupd8.wav b/build/res/pickupd8.wav new file mode 100644 index 0000000000000000000000000000000000000000..983e851198cb8e8ad4c873f011baf5cf12f8ae9c GIT binary patch literal 7504 zcmYk4S94oemW9=C^EiKCs-~v;eX6>8+P17nNfbpQ=bQloAV`n^gJ_DD)vZ8^5k$^8 zXE2GBEK!tXwZ~KQFu!QlJ{O?9_q`Y3`PN!{Ur3TiSzy96#-`)K7 z#y7XVx&7C%|1|#3<=4-@eEEV4Mc+Ps-uTIr}a1-Mw3P@7%e2 z8;$4K?Xg?@;N|;^_wPS^xOji@^ToT%cb8}X%v^tP=ib=Zy}S4B-oN|c_V}$w-&#MP zzkm1c{afmbw;#?g-h3`hKDc+E^*#0+AA30F{do5C+jsBYzB~W<41IcW{3UgJ;{N#f z{fP&-?@!#D9OK=vU!0zwpPiq*Jv)Cx{r1hNE*!I;9GxDYoE%e~oE+h=!JFN2!6c72 z#hc`#1(U)F@qOp{;OOw^5Rc>j$>6wm+CGm>i1;W0U&s^kL_E=yc*0!j52*V6!D0Wf zcho!XoW&lA`9h&U$Vc8wn3d zhMBY%MTrGcfrKxcaC0hz(Tn!5-=MO9i6UGg38a|GmruButP4Sp%{*$piSnc(u~-BJ zG@NR>-|2Orp|R{9vpBp?VJz+_Z9t9$K}bT2qyjl_?ueTSVY}BJGzX27FkeO*shC9}OgZU3 zZ1vjR4iYI6-D`JV@F|5wkxS_q2>WFiShabeIYc#e7pML!0u2WhW) z7{E-t0Lf%xnNTidGfBq6daYiwU#HE)Qi%i?l$=_-+iOuAWHc2*dI7muDuoPjVwp%G zRM87y{Z6~nf(o1U>ql`Vry(I_%0x2J;s6{f$k4rJuYMdB$ca*rOe7Z~Y-;AP)oC#q zq|~i$*^kB8YD@~TlIJ>XcCcF;QBB;9UhOC>luIyGMlF_$@tQmrG;OLDZkE;PZeylQ zDwRn&nL>n_gC_A-8>11|?A4AVoJuN@b1hN`Y%bs5~WxvRtskOq#+fnX0z37z7Q*9 za)e3cG6*44@n?DzM)TOrdbfHQ5-Fr4!)vlQiAp$Kf&KTOR=rd22ZYLD7+zQ*r7%yg zj`h(EtPf4MItXDiIZ8&8sTETFcDvESHcZ&6w;}6?#Hyi;q9jU*Mu4zpqlv45xLUj3 zuJvOYg&a931-lh8rF5xVZ;=dv_|mR+D*doXDOaFmN=#Eq)d-tK7zQ?4$i$6jyXco8 zjfG)3ic$+_y0y_v>_uUNpjb)cz~xGrQlgS-gzhF(DB2B0d97`UisCRBGL=*%(Fi>h zMxuJF-m120?Mg2sQeiU+LYzvjlB&h_EM;IJF0WZ@RlE2#vSH zYotL~M4?hB6-o$)C08ofIyIJ6r$`9fciAGFD-&bfP-g z5UNls)CiubV}7lUP{fwIL5Z3um|P>%if7x^dJQ8R)nr}TR_j%=wj+8qox`ZmDs&Q0je=`n7+mZg z$Y5ompnAz%vr?;7AmNrekZa&2PG0eBvr;8iuhh$pVkaoqsF019RgxF9R;>_ilt2$; z993aqxlTIUEHhdw*UR-1dDSc%UZoDNTd9(Fn7yeWrq-y?O0DKey0n zg#?vW?o7j4tyDnD^S1wM4CQD`%& zMXpXs)Y~XmD7VVIL^T?XTC2jsN`q_;6pXw@BnK!NRIO9#l?J)DS*ldZmGU3GTB2&b zQZM(_ON>=Z@E7ZwDxF57)qrbsYMtgu4Uk6TE>|*(gityNbV_Fus9eQeDOHP&u#pfE zwO(aVcq&B}Tq)5~&45w|MxjJy-dd?rE>%jEVzp4qHv=jid3E4=l~F#2rC2s{i7NFR z9|Sj{!}ReDO+qYY|<(qAni8mocAy{QJ( zY4uv-dhL@+u~aIRxx1WQ)arCP4r>i+R|4myGHm5SC0`F20rfhJ)fhA;-8ReED3NM^xO3u~;Y6B(fwMLB*$=+%a#b~~gZH%bS z0B%-*mP!S5zMQKLy#``hY^C;B3dI6wneob|#-P`Oa;;wnrRX9)3Z?Xt4wPZN-l%cM z2~u=1U&>X3W@4a5ol$F2&B0T^Rm9kGwzjV^!lO4L7)vSVF^?Fdnc5y33%5~c(pgmV zl^o__Vy?uzTBF_ohBj%X1yiMuSOjGCU~~9p1&{GK@5to@Sjp4v;TkYmnQM41dG1D4XvmvZ?$aWK$*oe5r}$!OABbXLs*XfBtBvyd&ptAm%E zMBy!F^9bjX)75>w*}%9NldVY3=5yIRoal6APiICd+@J=lZm~eg#G%L(Hw|VZI3CcL zP3r}CN0m=3lM!V$nT;0xOf;7rS@Y@Afz1qJG#e~Ni@~a$&jMz1nOvrjE~LtPdJ9}8 zj@q=oVkQTc&1drILYkw@ZL}C|+J#~!3vV``Ml-L;Om2(OYJj(p$%1Ec>0BnCD(>nn zw2_tCXw#7wnDIiYv}>@M%@#DHhNVIVEQ_u3>0BzmVYGl+ES%f2p3k7*MrU&I6*FgL zcB3acgy~#5n=A$#RyfUgm~AGTVS!*elg_4csa&$SYqBC1)Cy|X`|@cdX46@CLHCTH z#H?n!$w8C`X0j=`$!oJ%trn}rZnha6dVfBJ+zc3K;&*BrdQ+I2Msg;ZOB8lYc8k?! zv6*df+fB>a6j&xjolRz6nQc}igIPhX>)B)`oq{`+PNg!@6->3EtyaQwVLB(2NoErH zfCGRiv1y|(l}x3EER)FXBFzSBv0EHOvw*2|GM&sMv+?})kXjv9P?JB)yvcMToq%`8 zVz;5}M6FJfk7zOlFK9f!W47DCiP|kr(_%K628EL-ybdrl^O~1433!tU@OUboehF%4 zloYo0G*FU?o{<%s!%m#gwACA8=Ls;FGkY!vjNsHxvp<0%Um_Jt#WLGg2g*KeLtCBZ z#Z;Vp@g#<(qS+B8ZgrXcX;83aEE!KnGut*NnWs5w@u%X+1X1u*G_z%M+8K4)oi>-1 zk`r<87}4~O%{fhUdfEGVPppI)U)% zvd;&>V$_LfB9hv5la&+>m&0XSjKx4>#6Z*A4i}u$F2uSWZtGGKC>D>#iH6hLc2L(e z8bjT-#blIXqwz>QnhYnmnAhoYx}EOn8QW4K8ig6&cq9P|8yKSwqLCPQggPEhzMgiw zT<)RQ?O2INuV^eBd+Bt;$qL!7ALEf|Bs#3v!K%v*GwkS@X*#-FP@X&KbutnIe%eco=lc$rzk&kIOT?6bpk9jf7)C^3J$t zX5e*!!W$xMI2uAT3h4GwyJn|}hQkp&BBAI(eADTHbH+pMo^?Hrgu>xaI0PPw1S2n9 zKprTF&(5raqC-p*4y@8KU3kp87xzM;AhA&RAaW4hn#1wz%q+X-oXf<5;UL}NgXks! zGR}JDJYLsIBuLf+&_Fm4-EhwV&(6-w&Cbnu-7BGkAgco?4#JysjLYNYXc&|PL<5mc zkC!m+S?}yTc~QXt6oDW|!Mv>JXI6s&j)I||d*-~b&dq`2+j@|^fxrRv!S33emrm)4 zkEIUhFuM|MSN#>XMbZ6 zheQ{t=T~>O879fz_TEe1qJPnk3+-F-{jjsWv$IXLyS=-$`+|;_@L0lg$+x!inz8Mz z?X8`y-IxC5#id1Dtl{0-CbIQ<>-F~QofrP)CDiibGTn=7+nWUF+T7aQe!jGfT3J~_ zFRv`FZ*6h~`g-H_KbCR0yz+Pj1<}*Z%?;p<%?*5Pyjll9Q?0D7ti61-fuhH&jaQq` zS6MxNy!v=`b!~P1)yr3}a86G={;~SQ>JO+j+^bJk*I&MP@q+H>xL>^Z`x>h!sCD#@ z&!7K;)!$h?`|;`1pHR2$)*hfCm}f--3j zmNfd^xpU^a%KzgR$Z?H^kJ5(=K*(t!;AXQSv;?QT`lUwiPcjtbSb$8-z`n9|nT=K) z7DwohAz`1R@R5pr4u3;f=~cOnU?08cP;>P!!DY}Xo5B8M-#8&{KvBQ1!ku%+1ZW7I zag*2!F$p`xug>6T3gql7_rUid7@676@s$2+4F^*cr=d6C(uN_BUA+aj0XLVMi0|z1 a>aQV07z^j%@DN8hX9&L(`@~~Z&;B2?|DJUK literal 0 HcmV?d00001 diff --git a/draw.c b/draw.c index 4d25e3e..66f7310 100644 --- a/draw.c +++ b/draw.c @@ -16,6 +16,7 @@ void Draw_World( SDL_Renderer* r ) { dst.x = i * TILE_SIZE; uint8_t til = gs->levels[gs->current_level].tiles[j * 100 + gs->view_x + i]; if ( til == 0 ) continue; + til = G_UpdateFrame( til, i ); SDL_RenderCopy( r, g_assets->tile_tx[til], NULL, &dst ); } } @@ -37,12 +38,13 @@ void Draw_Player( SDL_Renderer* r ) { // grounded walk tile else if ( gs->ps.on_ground ) { til = gs->ps.last_dir >= 0 ? 53 : 57; + til += (gs->ps.tick/4) % 3; } // jump tile else if ( gs->ps.do_jump || !gs->ps.on_ground ) til = gs->ps.last_dir >= 0 ? 67 : 68; // dead - if ( gs->ps.dead_timer ) til = 129; + if ( gs->ps.dead_timer ) til = 129 + (gs->tick/4) % 4; // render // grounded debug @@ -51,6 +53,10 @@ void Draw_Player( SDL_Renderer* r ) { SDL_RenderDrawLine( r, dst.x, dst.y+dst.h, dst.x+dst.w, dst.y+dst.h ); } SDL_RenderCopy( r, g_assets->tile_tx[til], NULL, &dst ); + /*dst.w = TILE_SIZE; dst.h = TILE_SIZE; + dst.x = (gs->ps.tx - gs->view_x) * TILE_SIZE; + dst.y = gs->ps.ty * TILE_SIZE + TILE_SIZE; + SDL_RenderDrawRect( r, &dst );*/ } // draw player bullet @@ -66,6 +72,11 @@ void Draw_Bullet( SDL_Renderer* r ) { // render SDL_RenderCopy( r, g_assets->tile_tx[til], NULL, &dst ); + /*SDL_SetRenderDrawColor( r, 255, 0, 255, 255 ); + dst.w = TILE_SIZE; dst.h = TILE_SIZE; + dst.x = ((gs->ps.bullet_px / TILE_SIZE) - gs->view_x) * TILE_SIZE; + dst.y = (gs->ps.bullet_py / TILE_SIZE) * TILE_SIZE + TILE_SIZE; + SDL_RenderDrawRect( r, &dst );*/ } } @@ -81,6 +92,7 @@ void Draw_Monsters( SDL_Renderer* r ) { dst.y = TILE_SIZE + m->py;// - 10; dst.w = 24; dst.h = 20; til = m->dead_timer ? 129 : m->type; + til += (gs->tick / 3) % 4; SDL_RenderCopy( r, g_assets->tile_tx[til], NULL, &dst ); } } @@ -94,10 +106,16 @@ void Draw_MonsterBullet( SDL_Renderer* r ) { dst.y = TILE_SIZE + gs->mbullet_py; // tile 127 right, 128 left uint8_t til = gs->mbullet_dir > 0 ? 121 : 124; + til += (gs->tick / 3) % 3; dst.w = 20; dst.h = 3; // render SDL_RenderCopy( r, g_assets->tile_tx[til], NULL, &dst ); + /*SDL_SetRenderDrawColor( r, 255, 0, 255, 255 ); + dst.w = TILE_SIZE; dst.h = TILE_SIZE; + dst.x = ((gs->mbullet_px / TILE_SIZE) - gs->view_x) * TILE_SIZE; + dst.y = (gs->mbullet_py / TILE_SIZE) * TILE_SIZE + TILE_SIZE; + SDL_RenderDrawRect( r, &dst );*/ } } diff --git a/game.c b/game.c index 4d853c3..be88915 100644 --- a/game.c +++ b/game.c @@ -1,6 +1,7 @@ #include "game.h" #include "world.h" #include "draw.h" +#include "sound.h" // global game state game_state_t* gs = NULL; @@ -50,8 +51,8 @@ static void G_InitAssets( SDL_Renderer* r ) { Util_FreeTileSurfaces(); // sfx - //g_assets->sfx[0] = S_LoadChunk( "res/jumpd8.wav" ); //Mix_LoadWAV_RW( rw, 1 ); - //g_assets->sfx[1] = S_LoadChunk( "res/pickupd8.wav" ); //Mix_LoadWAV_RW( rw, 1 ); + //g_assets->sfx[SFX_JUMP] = S_LoadChunk( "res/jumpd8.wav" ); //Mix_LoadWAV_RW( rw, 1 ); + //g_assets->sfx[SFX_PICKUP] = S_LoadChunk( "res/pickupd8.wav" ); //Mix_LoadWAV_RW( rw, 1 ); } // poll input @@ -136,6 +137,17 @@ static void G_Update() { G_ClearInput(); } +// update tile animation +uint8_t G_UpdateFrame( uint8_t til, uint8_t salt ) { + uint8_t mod; + switch ( til ) { + case 6: case 25: case 129: mod = 4; break; + case 10: case 36: mod = 5; break; + default: mod = 1; break; + } + return til + (gs->tick/5+salt) % mod; +} + // main drawing routine static void G_Draw( SDL_Renderer* r ) { // clear backbuffer @@ -233,12 +245,12 @@ int main( int argc, char** argv ) { // 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 ); // free audio - //for ( int i = 0; i < sizeof(g_assets->sfx) / sizeof(g_assets->sfx[0]) ) + //for ( int i = 0; i < NUM_SFX; ++i ) //Mix_FreeChunk( g_assets->sfx[i] ); //Mix_FreeMusic( g_assets->mus ); + free( g_assets ); + free( gs ); //Mix_CloseAudio(); // cleanup SDL diff --git a/game.h b/game.h index afe7391..bc56cf7 100644 --- a/game.h +++ b/game.h @@ -2,17 +2,18 @@ #define _LMDAVE_H #include -//#include // for dealing with resources in EXE #include "util/util.h" +#include "sound.h" #include "player.h" #include "monster.h" // global game state typedef struct { uint8_t quit; + uint16_t tick; uint8_t current_level; // view and scroll are per tile uint8_t view_x, view_y; @@ -35,7 +36,7 @@ typedef struct { // tiles as textures converted from util's tile surfaces SDL_Texture* tile_tx[NUM_EXE_TILES]; // sfx - //Mix_Chunk* sfx[2]; + Mix_Chunk* sfx[NUM_SFX]; // music //Mix_Music* mus; } game_assets_t; @@ -45,4 +46,9 @@ typedef struct { // fixed frame delay #define FRAME_DELAY 33 +// common functions +// update a tile index based on game tick for animation +uint8_t G_UpdateFrame( uint8_t til, uint8_t salt ); + #endif + diff --git a/monster.c b/monster.c index 365bae8..7a2126e 100644 --- a/monster.c +++ b/monster.c @@ -35,13 +35,14 @@ void M_Fire() { for ( int i = 0; i < sizeof(gs->ms) / sizeof(gs->ms[0]); ++i ) { monster_state_t* m = &gs->ms[i]; // assumed size of 24x20 - if ( m->type && !m->dead_timer && W_IsVisible( m->px ) && W_IsClear( m->px+12, m->py+10, 0 ) ) { + if ( m->type && !m->dead_timer && W_IsVisible( m->px ) && W_IsClear( m->px+12, m->py+10, 0 ) && !m->fire_timer ) { gs->mbullet_dir = gs->ps.px < m->px ? -1 : 1; if ( gs->mbullet_dir == 1 ) gs->mbullet_px = m->px + 18; if ( gs->mbullet_dir == -1 ) gs->mbullet_px = m->px - 10; gs->mbullet_py = m->py + 10; + m->fire_timer = 15; } } } diff --git a/monster.h b/monster.h index e477943..ce31d43 100644 --- a/monster.h +++ b/monster.h @@ -5,6 +5,7 @@ typedef struct { uint8_t type; // type and tile index uint8_t dead_timer; + uint8_t fire_timer; uint8_t path_index; // current point in path uint8_t tx, ty; // tile pos int16_t px, py; // pixel pos diff --git a/player.c b/player.c index 4530680..862e2be 100644 --- a/player.c +++ b/player.c @@ -65,7 +65,7 @@ void P_PickupItem() { gs->ps.check_pickup_x = 0; gs->ps.check_pickup_y = 0; // sfx - //Mix_PlayChannel( S_CHAN_PICKUP, g_assets->sfx[1], 0 ); + //Mix_PlayChannel( S_CHAN_PICKUP, g_assets->sfx[SFX_PICKUP], 0 ); } // update collision point clear flags @@ -174,25 +174,29 @@ void P_Move() { gs->ps.px += 2; gs->ps.last_dir = 1; gs->ps.do_right = 0; + gs->ps.tick++; } if ( gs->ps.do_left ) { gs->ps.px -= 2; gs->ps.last_dir = -1; gs->ps.do_left = 0; + gs->ps.tick++; } // up and down if ( gs->ps.do_up ) { gs->ps.py -= 2; gs->ps.do_up = 0; + gs->ps.tick++; } else if ( gs->ps.do_down ) { gs->ps.py += 2; gs->ps.do_down = 0; + gs->ps.tick++; // jump } else if ( gs->ps.do_jump ) { if ( !gs->ps.jump_timer ) { gs->ps.jump_timer = 25; //gs->ps.last_dir = 0; - //Mix_PlayChannel( S_CHAN_JUMP, g_assets->sfx[0], 0 ); + //Mix_PlayChannel( S_CHAN_JUMP, g_assets->sfx[SFX_JUMP], 0 ); } if ( gs->ps.col_point[0] && gs->ps.col_point[1] ) { diff --git a/player.h b/player.h index 6095972..bef4cb6 100644 --- a/player.h +++ b/player.h @@ -12,6 +12,7 @@ typedef struct { uint8_t on_ground; // last facing direction int8_t last_dir; + uint16_t tick; // input flags uint8_t try_right; diff --git a/sound.c b/sound.c new file mode 100644 index 0000000..cdbccdc --- /dev/null +++ b/sound.c @@ -0,0 +1,18 @@ +#include "sound.h" + + +// custom chunk loader for emscripten support +Mix_Chunk* S_LoadChunk( const char* f ) { + SDL_RWops* rw = SDL_RWFromFile( f, "rb" ); + int sz = SDL_RWsize( rw ); + uint8_t* rwdat = malloc( sz ); + SDL_RWread( rw, rwdat, 1, sz ); + SDL_RWclose( rw ); + rw = SDL_RWFromConstMem( rwdat, sz ); + Mix_Chunk* chunk = Mix_LoadWAV_RW( rw, 1 ); + SDL_RWclose( rw ); + free( rwdat ); + if ( chunk == NULL ) { printf( "Failed to load chunk %s!\n", f ); return NULL; } + return chunk; +} + diff --git a/sound.h b/sound.h new file mode 100644 index 0000000..ed42c6e --- /dev/null +++ b/sound.h @@ -0,0 +1,18 @@ +#ifndef __SOUND_H +#define __SOUND_H + +#include +#include + +// sfx names +typedef enum { + SFX_JUMP, + SFX_PICKUP, + NUM_SFX +} SFX_NAME; + +// custom chunk loader for emscripten support +Mix_Chunk* S_LoadChunk( const char* f ); + +#endif + diff --git a/world.c b/world.c index c4397d2..505e8bc 100644 --- a/world.c +++ b/world.c @@ -109,6 +109,8 @@ uint8_t W_IsVisible( int16_t px ) { // level-wide state update void W_Update() { + // update world tick + gs->tick++; // check if at door and has trophy if ( gs->ps.check_door ) { if ( gs->ps.trophy ) { @@ -137,6 +139,7 @@ void W_Update() { for ( int i = 0; i < sizeof(gs->ms) / sizeof(gs->ms[0]); ++i ) { monster_state_t* m = &gs->ms[i]; if ( m->type ) { + if ( m->fire_timer ) m->fire_timer--; if ( m->dead_timer ) { m->dead_timer--; if ( !m->dead_timer ) { m->type = 0; }