2024-08-24 22:48:12 +02:00
/*
2025-01-09 22:10:24 +01:00
SDL2 frontend for Wake to Hell
2024-08-24 22:48:12 +02:00
2025-01-09 22:10:24 +01:00
Licensed under CC0 , public domain , 2023 - 2025
2024-08-24 22:48:12 +02:00
Made by blitzdoughnuts
*/
2023-05-01 15:44:57 +02:00
2023-04-26 01:59:18 +02:00
# include <stdio.h>
2024-10-09 02:09:18 +02:00
# include <stdint.h>
2023-04-26 01:59:18 +02:00
2025-01-13 05:29:27 +01:00
# ifdef __EMSCRIPTEN__
# include <emscripten.h>
# endif
2023-04-26 01:59:18 +02:00
# include <SDL2/SDL.h>
# include <SDL2/SDL_image.h>
# undef main
2025-01-26 02:15:51 +01:00
# define WTH_PRINT(x...) printf(x)
2023-04-26 01:59:18 +02:00
# include "game.h" // keep in mind, MAIN can still access variables from the game!
2023-05-12 15:59:52 +02:00
2025-01-21 15:07:49 +01:00
// SDL2 SETTINGS
# define WTHSDL_HZ 48000 // sample rate
2024-09-06 23:04:19 +02:00
// for aspect correction
2024-09-07 00:38:23 +02:00
# define CAM_VERTOFFSET ((HEIGHT - 270) / 4)
2024-09-06 23:04:19 +02:00
2024-08-20 10:30:07 +02:00
// lookup table for font offsets, to offset the character afterwards to the left by this amount
2024-01-27 05:12:18 +01:00
static const uint8_t fontOffsets_left [ 90 ] = {
2024-08-20 10:30:07 +02:00
21 , 12 , 3 , 11 , 7 , 14 , 22 , 20 , 20 , 4 , 4 , 21 , 1 , 20 , 11 , // 33-47
8 , 10 , 6 , 11 , 10 , 8 , 9 , 6 , 13 , 7 , 5 , 23 , 21 , 5 , 24 , 6 , 24 , // 48-64
0 , 7 , 7 , 7 , 4 , 7 , 4 , 0 , 0 , 0 , 9 , 7 , 0 , 9 , 4 , 9 , 5 , 11 , 9 , 6 , 6 , 10 , 3 , 3 , 9 , 5 , // 64-96 (A-Z)
12 , 12 , 12 , 16 , 3 , 21 , // 97-102
14 , 16 , 13 , 16 , 14 , 15 , 12 , 11 , 23 , // 103-122 (a-z)
18 , 18 , 21 , 3 , 12 , 12 , 15 , 10 , 12 , 13 , 13 , 13 , 15 , 5 , 13 , 13 , 13 // 123-139
2023-05-12 15:59:52 +02:00
} ;
2023-05-16 14:19:49 +02:00
// strings here, for both ease of access and also to reduce redundancy in program string lists
2025-03-22 21:15:47 +01:00
static const char str_savegamename [ ] = " WTH_SaveGame.wths " ;
2023-05-16 14:19:49 +02:00
2025-01-26 02:04:35 +01:00
char * gestures [ 18 ] = {
2025-01-21 15:07:49 +01:00
GESTURESTR_INVALID ,
GESTURESTR_BED ,
GESTURESTR_COMPUTER ,
GESTURESTR_BADGE ,
GESTURESTR_MIRROR ,
GESTURESTR_DONUT ,
GESTURESTR_KNIFE ,
GESTURESTR_YOU ,
GESTURESTR_STOOL ,
GESTURESTR_RECEPTIONIST ,
GESTURESTR_OUTDOORS ,
GESTURESTR_BURNING ,
GESTURESTR_GASOLINE ,
2025-01-26 02:04:35 +01:00
GESTURESTR_MAIL ,
GESTURESTR_COMPUTER2 ,
GESTURESTR_NEWS1 ,
GESTURESTR_NEWS2 ,
GESTURESTR_NEWS3
2025-01-21 15:07:49 +01:00
} ;
2025-03-22 21:15:47 +01:00
# if !WTH_NOSOUND
2024-09-07 17:22:44 +02:00
# include <SDL2/SDL_mixer.h>
2023-04-26 01:59:18 +02:00
2025-01-21 15:07:49 +01:00
# define WTH_MUSCOUNT 3
# define WTH_SFXCOUNT 12
Mix_Music * music [ WTH_MUSCOUNT ] ;
Mix_Chunk * sfx [ WTH_SFXCOUNT ] ;
2024-09-07 17:22:44 +02:00
# endif
2023-04-26 01:59:18 +02:00
SDL_Texture * wintext ;
2024-12-22 18:38:33 +01:00
SDL_Texture * plrsprites [ WTH_PLR_SPRCOUNT * 2 ] ;
SDL_Texture * sprites [ WTH_SPRCOUNT ] ;
2023-04-26 01:59:18 +02:00
SDL_Rect dspdest_rect ; // this is the DESTINATION, aka screen position
2025-03-22 21:15:47 +01:00
# if WTH_FADE
2023-05-09 19:49:54 +02:00
SDL_Rect fade_rect ; // used for fading in/out
2025-03-22 21:15:47 +01:00
# endif
2023-04-26 01:59:18 +02:00
2023-05-12 15:59:52 +02:00
SDL_Point zeropoint = { 0 , 0 } ;
2023-04-26 01:59:18 +02:00
SDL_Renderer * render ;
2023-05-12 20:15:16 +02:00
SDL_Window * win ;
2023-04-26 01:59:18 +02:00
2025-01-13 05:29:27 +01:00
SDL_Event event ;
2025-01-09 22:10:24 +01:00
uint8_t renderFlags ; // flags to tell SDL2 what to draw, modified by signalDraw()
2024-05-02 03:12:39 +02:00
2023-04-26 01:59:18 +02:00
void drawSprite ( SDL_Texture * sprite , int x , int y ) {
2023-05-11 14:08:51 +02:00
dspdest_rect = ( SDL_Rect ) { x , y , 0 , 0 } ;
SDL_QueryTexture ( sprite , NULL , NULL , & dspdest_rect . w , & dspdest_rect . h ) ;
SDL_RenderCopy ( render , sprite , NULL , & dspdest_rect ) ;
2023-04-26 01:59:18 +02:00
} ;
2023-05-12 15:59:52 +02:00
FILE * DaSave ;
2025-03-22 21:15:47 +01:00
# if WTH_DEMOS
2023-08-13 16:04:30 +02:00
FILE * DaDemo ;
uint8_t demoStatus ;
uint8_t demowrite [ 1 ] ;
uint32_t demoPointer ;
2025-01-21 15:07:49 +01:00
static const char str_wintitle [ ] = GAMETITLE ; // it's only here to cut down redundancies
2023-08-13 16:04:30 +02:00
# endif
2025-03-22 21:15:47 +01:00
# if WTH_DEBUG
2024-12-14 21:00:22 +01:00
uint16_t DEBUG_keys ;
uint16_t DEBUG_lastkeys ;
2024-12-04 04:20:23 +01:00
uint8_t DEBUG_objSel ;
2024-12-14 21:00:22 +01:00
SDL_Texture * DEBUG_sprites [ 2 ] ;
2025-01-11 19:49:52 +01:00
double DEBUG_gameFPS ;
2024-12-04 04:20:23 +01:00
# endif
2024-05-09 22:55:32 +02:00
void drawRepeatingSprite ( SDL_Texture * sprite , int x , int y ) {
2023-04-26 01:59:18 +02:00
int _x = x ;
2024-05-31 22:07:34 +02:00
dspdest_rect . x = x ;
dspdest_rect . y = y ;
2023-05-11 14:08:51 +02:00
SDL_QueryTexture ( sprite , NULL , NULL , & dspdest_rect . w , & dspdest_rect . h ) ;
2024-05-31 22:12:25 +02:00
while ( _x < WIDTH ) {
2024-05-31 22:07:34 +02:00
if ( _x < - dspdest_rect . w ) {
2023-05-11 14:08:51 +02:00
_x + = dspdest_rect . w ;
2024-05-31 22:07:34 +02:00
dspdest_rect . x = _x ;
2023-04-26 01:59:18 +02:00
continue ;
} ;
SDL_RenderCopy ( render , sprite , NULL , & dspdest_rect ) ;
2023-05-11 14:08:51 +02:00
_x + = dspdest_rect . w ;
2023-04-26 01:59:18 +02:00
dspdest_rect . x = _x ;
} ;
2023-08-13 16:07:18 +02:00
_x = x ;
2024-05-31 22:07:34 +02:00
while ( _x > - dspdest_rect . w ) {
if ( _x > WIDTH ) {
_x - = dspdest_rect . w ;
dspdest_rect . x = _x ;
continue ;
} ;
2023-08-13 16:04:30 +02:00
_x - = dspdest_rect . w ;
2024-05-31 22:07:34 +02:00
SDL_RenderCopy ( render , sprite , NULL , & dspdest_rect ) ;
2023-08-13 16:04:30 +02:00
dspdest_rect . x = _x ;
} ;
2023-04-26 01:59:18 +02:00
} ;
2023-05-01 16:03:14 +02:00
void drawSpriteSheeted ( SDL_Texture * sprite , int x , int y , int frame , int x_sprdist , int y_sprdist , uint8_t flipped ) { // supports only purely horizontal sheets
2023-05-11 21:03:45 +02:00
if ( x < - x_sprdist | | x > x_sprdist + WIDTH ) return ;
2023-04-26 01:59:18 +02:00
SDL_Rect destrect = { x , y , x_sprdist , y_sprdist } ;
2023-05-16 14:19:49 +02:00
dspdest_rect . x = x_sprdist * frame ;
2025-03-22 21:15:47 +01:00
dspdest_rect . y = 0 ; // this somehow fixes an issue where the sprite would vertically stretch when moving the camera vertically, but crop off within the sprite's intended bounds. what?
2023-04-26 01:59:18 +02:00
dspdest_rect . w = x_sprdist ,
dspdest_rect . h = y_sprdist ,
2023-05-13 20:02:36 +02:00
SDL_RenderCopyEx ( render , sprite , & dspdest_rect , & destrect , 0 , & zeropoint , flipped ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE ) ;
2023-04-26 01:59:18 +02:00
} ;
2024-08-16 01:12:37 +02:00
void drawTextString ( const char * stuff , int x , int y , uint8_t color ) {
// to-do: may need optimizing?
2023-05-11 21:03:45 +02:00
switch ( color )
{
2025-01-21 15:07:49 +01:00
case 1 : SDL_SetTextureColorMod ( sprites [ WTH_SPR_FONTMAP ] , 224 , 0 , 0 ) ; break ;
/* case 2: SDL_SetTextureColorMod(sprites[5], 0, 224, 21); break;
2023-08-13 16:04:30 +02:00
case 3 : SDL_SetTextureColorMod ( sprites [ 5 ] , 0 , 31 , 224 ) ; break ;
2023-05-11 21:03:45 +02:00
case 4 : SDL_SetTextureColorMod ( sprites [ 5 ] , 255 , 255 , 0 ) ; break ;
case 5 : SDL_SetTextureColorMod ( sprites [ 5 ] , 0 , 255 , 255 ) ; break ;
case 6 : SDL_SetTextureColorMod ( sprites [ 5 ] , 255 , 0 , 255 ) ; break ;
case 7 : SDL_SetTextureColorMod ( sprites [ 5 ] , 0 , 255 , 255 ) ; break ;
case 8 : SDL_SetTextureColorMod ( sprites [ 5 ] , 255 , 255 , 0 ) ; break ;
case 9 : SDL_SetTextureColorMod ( sprites [ 5 ] , 255 , 255 , 255 ) ; break ;
2025-01-21 15:07:49 +01:00
case 10 : SDL_SetTextureColorMod ( sprites [ 5 ] , 0 , 0 , 0 ) ; break ; */
2024-05-09 22:55:32 +02:00
default : SDL_SetTextureColorMod ( sprites [ WTH_SPR_FONTMAP ] , 218 , 218 , 218 ) ; break ;
2023-05-11 21:03:45 +02:00
}
2024-08-16 01:12:37 +02:00
int16_t _x = x ;
for ( uint8_t i = 0 ; i < 255 ; i + + ) {
if ( stuff [ i ] = = ' \0 ' ) break ; // terminator character? then get outta there before stuff gets nasty
2024-08-20 10:30:07 +02:00
if ( _x < - 27 | | _x > 27 + WIDTH ) return ;
SDL_Rect destrect = { _x , y , 27 , 30 } ;
dspdest_rect . x = 27 * ( stuff [ i ] - 33 ) ;
2024-08-16 01:12:37 +02:00
dspdest_rect . y = 0 ;
2024-08-20 10:30:07 +02:00
dspdest_rect . w = 27 ;
dspdest_rect . h = 30 ;
2024-08-16 01:12:37 +02:00
SDL_RenderCopy ( render , sprites [ WTH_SPR_FONTMAP ] , & dspdest_rect , & destrect ) ;
2024-08-20 10:30:07 +02:00
_x + = ( stuff [ i ] = = 32 ) ? 16 : 27 - fontOffsets_left [ stuff [ i ] - 33 ] ;
2024-08-16 01:12:37 +02:00
} ;
2023-05-11 21:03:45 +02:00
} ;
2025-02-06 20:02:07 +01:00
uint8_t found = 0 ;
uint8_t gesture = 0 ; // keeps track of added gesture objects
2023-05-30 19:08:21 +02:00
void signalMisc ( uint8_t signal ) {
switch ( signal )
{
2025-03-22 21:15:47 +01:00
# if !WTH_NOSOUND
2023-06-08 00:33:41 +02:00
case MISC_PAUSEMUSIC : case MISC_RESUMEMUSIC : case MISC_STOPMUSIC :
if ( ! ( options [ 0 ] & WTHOPTS_DOSONG ) ) break ;
switch ( signal )
{
case MISC_PAUSEMUSIC : Mix_PauseMusic ( ) ; break ;
case MISC_RESUMEMUSIC : Mix_ResumeMusic ( ) ; break ;
case MISC_STOPMUSIC : Mix_HaltMusic ( ) ; break ;
}
break ;
2025-01-09 22:10:24 +01:00
# endif
2025-01-21 15:07:49 +01:00
case MISC_GESTURE :
for ( uint8_t i = 0 ; i < interacts_count ; i + + ) {
if ( interacts [ i ] . objID = = INTERTYPE_ARTIFACT & & interacts [ i ] . x - 30 < = plr . x & & interacts [ i ] . x + 30 > = plr . x ) {
puts ( gestures [ 3 + interacts [ i ] . vars [ 0 ] ] ) ;
found = 1 ;
break ;
} ;
if ( interacts [ i ] . objID ! = INTERTYPE_GESTURE ) continue ;
if ( interacts [ i ] . x - 30 < = plr . x & & interacts [ i ] . x + 30 > = plr . x ) {
puts ( gestures [ interacts [ i ] . vars [ 0 ] ] ) ;
found = 1 ;
break ;
} ;
} ;
if ( ! found ) {
if ( level = = ROOM_OUTDOORS ) puts ( gestures [ GESTURE_OUTDOORS ] ) ;
else puts ( gestures [ GESTURE_INVALID ] ) ;
} ;
break ;
2025-01-26 02:04:35 +01:00
case MISC_NEWROOM :
switch ( level )
{
case ROOM_HOUSE :
gesture = addObject ( 438 , GROUNDLEVEL , INTERTYPE_GESTURE ) ;
interacts [ gesture ] . vars [ 0 ] = GESTURE_COMPUTER ;
break ;
case ROOM_OUTDOORS :
gesture = addObject ( 128 , GROUNDLEVEL , INTERTYPE_GESTURE ) ;
interacts [ gesture ] . vars [ 0 ] = GESTURE_MAIL ;
break ;
} ;
break ;
2023-05-30 19:08:21 +02:00
}
} ;
2023-05-30 14:14:27 +02:00
2023-08-13 16:07:18 +02:00
# define WTH_OPTIONTEXT_X 30
2024-06-23 16:41:58 +02:00
# define WTH_OPTIONTEXT_Y 40
2023-08-13 16:04:30 +02:00
2023-05-17 20:33:19 +02:00
void drawOptions ( ) {
2024-05-17 02:37:16 +02:00
// drawRepeatingSprite has no functionality for VERTICAL tiling... fuck it, we ball
2025-01-21 15:07:49 +01:00
for ( uint16_t i = 0 ; i < HEIGHT ; i + = 64 ) {
drawRepeatingSprite ( sprites [ WTH_SPR_OPTMENU ] , 0 , i ) ;
} ;
2024-08-16 01:12:37 +02:00
drawTextString ( " Freecam " , WTH_OPTIONTEXT_X , WTH_OPTIONTEXT_Y + 32 , menu . menuselect = = 1 ? 1 : 0 ) ;
drawTextString ( ( options [ 0 ] & WTHOPTS_DEVCAM ) ? str_on : str_off , 320 , WTH_OPTIONTEXT_Y + 32 , menu . menuselect = = 1 ? 1 : 0 ) ;
drawTextString ( " Music " , WTH_OPTIONTEXT_X , WTH_OPTIONTEXT_Y + 64 , menu . menuselect = = 2 ? 1 : 0 ) ;
drawTextString ( ( options [ 0 ] & WTHOPTS_DOSONG ) ? str_on : str_off , 320 , WTH_OPTIONTEXT_Y + 64 , menu . menuselect = = 2 ? 1 : 0 ) ;
2023-05-17 20:33:19 +02:00
2025-01-31 00:16:20 +01:00
drawTextString ( str_exit , 32 , HEIGHT - 48 , menu . menuselect = = 3 ? 1 : 0 ) ;
2023-05-17 20:33:19 +02:00
} ;
2023-05-03 15:06:55 +02:00
void signalDraw ( uint8_t index ) {
switch ( index )
{
2023-05-14 06:06:21 +02:00
case DRAW_PLRUPARROW :
2025-01-01 23:39:54 +01:00
renderFlags ^ = 1 ;
2024-05-09 22:55:32 +02:00
break ;
2025-01-14 12:43:51 +01:00
case DRAW_PLRDNARROW :
renderFlags ^ = 2 ;
break ;
2023-05-03 15:06:55 +02:00
} ;
2023-04-26 01:59:18 +02:00
} ;
2023-05-25 13:34:27 +02:00
// inline the simple stuff
2023-06-08 00:33:41 +02:00
static inline void signalPlaySFX ( uint8_t signal ) {
2025-03-22 21:15:47 +01:00
# if !WTH_NOSOUND
2023-05-03 15:06:55 +02:00
Mix_PlayChannel ( - 1 , sfx [ signal ] , 0 ) ;
2024-09-07 17:22:44 +02:00
# endif
2023-05-03 15:06:55 +02:00
} ;
2023-05-01 15:44:57 +02:00
2023-06-08 00:33:41 +02:00
static inline void signalPlayMUS ( uint8_t signal ) {
2025-03-22 21:15:47 +01:00
# if !WTH_NOSOUND
2023-06-08 00:33:41 +02:00
if ( options [ 0 ] & WTHOPTS_DOSONG ) Mix_PlayMusic ( music [ signal ] , - 1 ) ;
2024-09-07 17:22:44 +02:00
# endif
2024-06-23 16:41:58 +02:00
} ;
2023-05-01 15:44:57 +02:00
2023-05-11 14:08:51 +02:00
void saveGame ( ) {
2025-03-22 21:15:47 +01:00
# if !WTH_NOOPTIONS
2023-05-16 14:19:49 +02:00
DaSave = fopen ( str_savegamename , " w " ) ;
2023-05-17 20:33:19 +02:00
fwrite ( & options , 1 , 2 , DaSave ) ;
2023-05-11 14:08:51 +02:00
fclose ( DaSave ) ;
2025-01-09 22:10:24 +01:00
# endif
2023-05-11 14:08:51 +02:00
} ;
void loadGame ( ) {
2025-03-22 21:15:47 +01:00
# if !WTH_NOOPTIONS
2023-08-13 16:04:30 +02:00
if ( ! ( DaSave = fopen ( str_savegamename , " r " ) ) ) {
2024-10-20 15:49:27 +02:00
options [ 0 ] = DEFAULT_OPTIONS ;
2023-08-13 16:04:30 +02:00
return ;
} ;
2023-08-13 16:07:18 +02:00
fread ( & options , 1 , 2 , DaSave ) ;
2023-05-11 14:08:51 +02:00
fclose ( DaSave ) ;
2025-01-09 22:10:24 +01:00
# else
options [ 0 ] = DEFAULT_OPTIONS ;
# endif
2023-05-11 14:08:51 +02:00
} ;
2023-04-26 01:59:18 +02:00
void draw ( ) {
switch ( GAME_STATE )
{
2024-09-07 17:22:44 +02:00
case GSTATE_MENU :
2023-04-26 01:59:18 +02:00
//SDL_FillRect(winsurf, NULL, 400);
2023-05-11 16:03:27 +02:00
switch ( menu . menuindex )
{
case 0 :
2024-05-09 22:55:32 +02:00
drawSprite ( sprites [ WTH_SPR_MENU ] , 0 , 0 ) ;
drawSpriteSheeted ( sprites [ WTH_SPR_MENUBUTTONS ] , 47 , 147 , ( menu . menuselect = = 0 ) ? 1 : 0 , 99 , 23 , 0 ) ;
drawSpriteSheeted ( sprites [ WTH_SPR_MENUBUTTONS ] , 47 , 170 , ( menu . menuselect = = 1 ) ? 3 : 2 , 99 , 23 , 0 ) ;
drawSpriteSheeted ( sprites [ WTH_SPR_MENUBUTTONS ] , 47 , 193 , ( menu . menuselect = = 2 ) ? 5 : 4 , 99 , 23 , 0 ) ;
2023-05-11 16:03:27 +02:00
break ;
2023-08-13 16:07:18 +02:00
case 1 : case MINDEX_XOPTIONS :
2023-05-17 20:33:19 +02:00
drawOptions ( ) ;
2023-05-11 16:03:27 +02:00
break ;
}
2024-08-16 01:12:37 +02:00
drawTextString ( VERSION_NUMBER , 0 , 0 , 0 ) ;
2023-04-26 01:59:18 +02:00
break ;
2024-09-07 17:22:44 +02:00
case GSTATE_PLAYING :
2025-01-25 20:15:23 +01:00
// draw background
2023-05-08 20:11:21 +02:00
switch ( level )
{
2025-02-06 02:54:19 +01:00
case ROOM_TEST : case ROOM_STREETS :
2025-01-21 15:07:49 +01:00
drawRepeatingSprite ( sprites [ WTH_SPR_BG_STREET ] , - cam_x , - cam_y ) ;
2023-05-08 20:11:21 +02:00
break ;
2024-10-16 12:40:21 +02:00
case ROOM_HOUSE :
2025-01-21 15:07:49 +01:00
drawSprite ( sprites [ WTH_SPR_BG_HOUSE ] , - 456 - cam_x - 75 , - cam_y ) ;
2023-05-14 06:06:21 +02:00
break ;
2024-10-16 12:40:21 +02:00
case ROOM_OUTDOORS :
2025-01-21 15:07:49 +01:00
drawRepeatingSprite ( sprites [ WTH_SPR_BG_OUTDOORS ] , - cam_x / 2 , - cam_y ) ;
2023-08-13 16:04:30 +02:00
break ;
2024-10-16 12:40:21 +02:00
case ROOM_HOSPITAL :
2025-01-21 15:07:49 +01:00
drawSprite ( sprites [ WTH_SPR_BG_HOSPITAL ] , - 45 - cam_x , - cam_y ) ;
2023-05-14 06:06:21 +02:00
break ;
2025-01-16 02:26:09 +01:00
case ROOM_H_PATIENTS :
2025-01-25 20:15:23 +01:00
drawSprite ( sprites [ WTH_SPR_BG_HOS_PATIENTS ] , - 30 - cam_x , - cam_y ) ;
2025-01-16 02:26:09 +01:00
break ;
case ROOM_H_HAMIE :
2025-01-21 15:07:49 +01:00
drawSprite ( sprites [ WTH_SPR_BG_HOS_HAMIE ] , - 45 - cam_x , - cam_y ) ;
2025-01-16 02:26:09 +01:00
break ;
case ROOM_H_RICHIE :
2025-01-21 15:07:49 +01:00
drawSprite ( sprites [ WTH_SPR_BG_HOS_RICHIE ] , - 45 - cam_x , - cam_y ) ;
2025-01-16 02:26:09 +01:00
break ;
2024-12-14 21:00:22 +01:00
case ROOM_BAR :
2025-01-21 15:07:49 +01:00
drawSprite ( sprites [ WTH_SPR_BG_BAR ] , - 250 - cam_x , - cam_y ) ;
2024-12-14 21:00:22 +01:00
break ;
2023-05-08 20:11:21 +02:00
} ;
2023-04-26 01:59:18 +02:00
2023-05-15 18:20:15 +02:00
for ( uint8_t i = 0 ; i < interacts_count ; i + + ) {
2023-05-17 20:33:19 +02:00
if ( ! ( interacts [ i ] . flags & INTER_ACTIVE ) ) continue ;
2023-05-14 06:06:21 +02:00
switch ( interacts [ i ] . objID )
{
case 255 :
2025-01-21 15:07:49 +01:00
drawSpriteSheeted ( sprites [ WTH_SPR_YOU ] , ( interacts [ i ] . x - 75 ) - cam_x , ( interacts [ i ] . y - 100 ) - cam_y , interacts [ i ] . vars [ 1 ] , 150 , 150 , ( plr . x < interacts [ i ] . x ) ? 1 : 0 ) ;
2023-05-14 06:06:21 +02:00
break ;
case INTERTYPE_COAT :
2025-01-21 15:07:49 +01:00
drawSpriteSheeted ( sprites [ WTH_SPR_COATRACK ] , interacts [ i ] . x - 35 - cam_x , ( interacts [ i ] . y - 100 ) - cam_y , ( plr . flags & FLAG_HASCOAT ) ? 1 : 0 , 70 , 100 , 0 ) ;
2023-05-30 19:08:21 +02:00
break ;
2023-06-08 00:33:41 +02:00
case INTERTYPE_DECOR :
2025-01-21 15:07:49 +01:00
drawSprite ( sprites [ interacts [ i ] . vars [ 0 ] ] , interacts [ i ] . x - cam_x , interacts [ i ] . y - cam_y ) ;
2023-06-08 00:33:41 +02:00
break ;
2023-05-30 19:08:21 +02:00
case INTERTYPE_ARTIFACT :
2025-01-21 15:07:49 +01:00
drawSpriteSheeted ( sprites [ WTH_SPR_ARTIFACTS ] , ( interacts [ i ] . x - 32 ) - cam_x , ( interacts [ i ] . y - 32 ) - cam_y , interacts [ i ] . vars [ 0 ] , 64 , 64 , 0 ) ;
2023-05-15 18:20:15 +02:00
break ;
2023-08-13 16:04:30 +02:00
case INTERTYPE_DOOR :
2025-01-21 15:07:49 +01:00
drawSpriteSheeted ( sprites [ WTH_SPR_DOOR ] , ( interacts [ i ] . x - 75 ) - cam_x , ( interacts [ i ] . y - 100 ) - cam_y , ( ( interacts [ i ] . flags & 1 < < 2 ) | | interacts [ i ] . vars [ 1 ] ) ? 1 : 0 , 150 , 150 , 0 ) ;
2023-08-13 16:04:30 +02:00
break ;
2024-08-26 02:18:27 +02:00
case INTERTYPE_STAIRS :
2025-01-21 15:07:49 +01:00
drawSpriteSheeted ( sprites [ WTH_SPR_STAIRS ] , ( interacts [ i ] . x - 75 ) - cam_x , ( interacts [ i ] . y - 100 ) - cam_y , 0 , 150 , 150 , 0 ) ;
2024-08-26 02:18:27 +02:00
break ;
case INTERTYPE_BOOK :
2025-01-21 15:07:49 +01:00
drawSpriteSheeted ( sprites [ WTH_SPR_BOOK_HAMIE ] , ( interacts [ i ] . x - 32 ) - cam_x , ( interacts [ i ] . y - 32 ) - cam_y , ( ( interacts [ i ] . flags & 1 < < 2 ) | | interacts [ i ] . vars [ 1 ] ) ? 1 : 0 , 64 , 64 , 0 ) ;
2024-08-26 02:18:27 +02:00
break ;
2025-03-22 21:15:47 +01:00
# if WTH_DEBUG
2024-12-04 04:20:23 +01:00
case INTERTYPE_GESTURE :
2025-01-21 15:07:49 +01:00
drawSprite ( DEBUG_sprites [ 0 ] , ( interacts [ i ] . x - 75 ) - cam_x , ( interacts [ i ] . y - 100 ) - cam_y ) ;
2024-12-04 04:20:23 +01:00
break ;
# endif
2023-05-14 06:06:21 +02:00
}
2023-05-03 15:06:55 +02:00
} ;
2023-08-13 16:04:30 +02:00
2025-02-06 20:02:07 +01:00
// draw player
uint8_t plrFrame = plr . animframe ;
if ( plr . animindex = = WTH_PLR_SPOOKED_SPR ) {
switch ( plr . animframe )
{
case 2 : case 3 : // stall Lukifer's initial shock for 3 frames
plrFrame = 1 ;
break ;
case 4 : case 5 : case 6 : case 7 : // cue turnaround
plrFrame - = 3 ;
break ;
case 8 : case 9 : case 10 : case 11 : case 12 : case 13 : case 14 : case 15 : case 16 : case 17 : case 18 : case 19 : case 20 : // line boil Lukifer turned around
plrFrame = 4 + ( plr . animframe & 1 ) ;
break ;
case 21 : case 22 : // Lukifer reacts in unamusement
plrFrame - = 16 ;
break ;
case 23 : case 24 : case 25 : case 26 : case 27 : case 28 : // loop unamusement
plrFrame = 7 ;
break ;
case 29 : case 30 : // go back to turning right
plrFrame - = 21 ;
break ;
} ;
} ;
drawSpriteSheeted ( plrsprites [ ( plr . flags & FLAG_HASCOAT ) ? plr . animindex : plr . animindex + WTH_PLR_SPRCOUNT ] , ( plr . x - 75 ) - cam_x , ( plr . y - 100 ) - cam_y , plrFrame , 150 , 150 , ( plr . flags & FLAG_FLIPPED ) ? 1 : 0 ) ;
2025-01-01 23:39:54 +01:00
2025-01-21 15:07:49 +01:00
if ( renderFlags & 1 ) drawSprite ( sprites [ WTH_SPR_UPARROW ] , plr . x - 20 - cam_x , plr . y - 150 - cam_y ) ;
if ( renderFlags & 2 ) drawSprite ( sprites [ WTH_SPR_UPARROW ] , plr . x - 20 - cam_x , plr . y + 25 - cam_y ) ;
2023-08-13 16:04:30 +02:00
2025-03-22 21:15:47 +01:00
# if WTH_DEBUG
2023-05-15 04:06:40 +02:00
switch ( level )
{
2024-11-09 16:59:49 +01:00
case ROOM_TEST : drawTextString ( " Test Room " , 0 , 0 , 0 ) ; break ;
case ROOM_HOUSE : drawTextString ( " House " , 0 , 0 , 0 ) ; break ;
case ROOM_OUTDOORS : drawTextString ( " Outside of House " , 0 , 0 , 0 ) ; break ;
2024-12-14 21:00:22 +01:00
case ROOM_STREETS : drawTextString ( " Endless Sidewalk " , 0 , 0 , 0 ) ; break ;
case ROOM_HOSPITAL : drawTextString ( " Hospital Lobby " , 0 , 0 , 0 ) ; break ;
2025-01-16 02:26:09 +01:00
case ROOM_H_PATIENTS : drawTextString ( " Hospital Patient Lobby " , 0 , 0 , 0 ) ; break ;
case ROOM_H_HAMIE : drawTextString ( " Hamie's Room " , 0 , 0 , 0 ) ; break ;
case ROOM_H_RICHIE : drawTextString ( " Richie's Room " , 0 , 0 , 0 ) ; break ;
2025-01-21 15:38:58 +01:00
case ROOM_H_DARK : drawTextString ( " Dark Room " , 0 , 0 , 0 ) ; break ;
case ROOM_YOU : drawTextString ( " Dark Room? " , 0 , 0 , 0 ) ; break ;
2024-12-14 21:00:22 +01:00
case ROOM_BAR : drawTextString ( " Bar " , 0 , 0 , 0 ) ; break ;
2023-05-15 04:06:40 +02:00
} ;
2023-11-27 12:35:40 +01:00
# endif
2024-06-03 16:35:17 +02:00
2025-03-22 21:15:47 +01:00
# if WTH_FADE
2024-06-03 16:35:17 +02:00
if ( fade ! = 0 ) {
2024-11-09 16:59:49 +01:00
SDL_SetRenderDrawBlendMode ( render , SDL_BLENDMODE_BLEND ) ;
2024-06-03 16:35:17 +02:00
SDL_SetRenderDrawColor ( render , 0 , 0 , 0 , fade ) ;
SDL_RenderFillRect ( render , NULL ) ;
2024-11-09 16:59:49 +01:00
} else SDL_SetRenderDrawBlendMode ( render , SDL_BLENDMODE_NONE ) ;
2025-03-22 21:15:47 +01:00
# endif
2023-05-15 18:20:15 +02:00
break ;
2024-09-07 17:22:44 +02:00
case GSTATE_PAUSED :
2023-05-15 18:20:15 +02:00
//SDL_FillRect(winsurf, NULL, 400);
2023-05-17 20:33:19 +02:00
switch ( menu . menuindex )
{
case 0 :
2025-02-02 23:17:01 +01:00
if ( plr . artifacts & 1 < < ARTIFACT_BADGE )
drawSpriteSheeted ( sprites [ WTH_SPR_ARTIFACTS ] , 248 , 96 , 0 , 64 , 64 , 0 ) ;
if ( plr . artifacts & 1 < < ARTIFACT_MIRROR )
drawSpriteSheeted ( sprites [ WTH_SPR_ARTIFACTS ] , 312 , 96 , 1 , 64 , 64 , 0 ) ;
if ( plr . artifacts & 1 < < ARTIFACT_DONUT )
drawSpriteSheeted ( sprites [ WTH_SPR_ARTIFACTS ] , 248 , 144 , 2 , 64 , 64 , 0 ) ;
if ( plr . artifacts & 1 < < ARTIFACT_KNIFE )
drawSpriteSheeted ( sprites [ WTH_SPR_ARTIFACTS ] , 312 , 144 , 3 , 64 , 64 , 0 ) ;
if ( plr . flags & FLAG_HASCOAT )
drawSpriteSheeted ( sprites [ WTH_SPR_COATRACK ] , 376 , 108 , 0 , 100 , 100 , 0 ) ;
if ( GAME_FLAGS & FLAG_HAMIEBOOK ) // TODO: Proper sprite for Hamie's book
drawTextString ( " Read Hamie's book " , 312 , 200 , 0 ) ;
2025-01-25 20:15:23 +01:00
drawTextString ( " PAUSED " , 80 , 64 , 0 ) ;
drawTextString ( " Resume " , 80 , 120 , menu . menuselect = = 0 ? 1 : 0 ) ;
drawTextString ( " Options " , 80 , 152 , menu . menuselect = = 1 ? 1 : 0 ) ;
drawTextString ( str_exit , 80 , 184 , menu . menuselect = = 2 ? 1 : 0 ) ;
2023-05-17 20:33:19 +02:00
break ;
case 1 :
drawOptions ( ) ;
break ;
}
2023-04-26 01:59:18 +02:00
break ;
2024-09-07 17:22:44 +02:00
case GSTATE_BOOK :
2024-09-06 23:04:19 +02:00
drawSpriteSheeted ( sprites [ WTH_SPR_READ_HAMIE ] , 0 , 0 , bookpage & 0x0F , 480 , 270 , 0 ) ;
2025-03-22 21:15:47 +01:00
# if WTH_FADE
2024-05-09 22:55:32 +02:00
if ( fade ! = 0 ) {
2024-11-09 16:59:49 +01:00
SDL_SetRenderDrawBlendMode ( render , SDL_BLENDMODE_BLEND ) ;
2024-05-09 22:55:32 +02:00
SDL_SetRenderDrawColor ( render , 0 , 0 , 0 , fade ) ;
SDL_RenderFillRect ( render , NULL ) ;
2024-11-09 16:59:49 +01:00
} else SDL_SetRenderDrawBlendMode ( render , SDL_BLENDMODE_NONE ) ;
2025-03-22 21:15:47 +01:00
# endif
2024-01-10 21:59:33 +01:00
break ;
2023-04-26 01:59:18 +02:00
} ;
2025-01-01 23:39:54 +01:00
renderFlags = 0 ;
2023-04-26 01:59:18 +02:00
} ;
2023-05-03 15:06:55 +02:00
uint8_t * keystates ;
2023-08-13 16:04:30 +02:00
SDL_Joystick * controllerinput ;
2023-05-03 15:06:55 +02:00
2023-04-26 01:59:18 +02:00
void keys ( ) {
2025-03-22 21:15:47 +01:00
# if WTH_DEMOS
2023-08-13 16:07:18 +02:00
if ( demoStatus ! = 2 ) {
2023-08-13 16:04:30 +02:00
# endif
2025-03-17 03:55:25 +01:00
if ( keystates [ SDL_SCANCODE_LEFT ] ) input_keys | = WTH_KEY_LEFT ;
if ( keystates [ SDL_SCANCODE_RIGHT ] ) input_keys | = WTH_KEY_RIGHT ;
if ( keystates [ SDL_SCANCODE_UP ] ) input_keys | = WTH_KEY_UP ;
if ( keystates [ SDL_SCANCODE_DOWN ] ) input_keys | = WTH_KEY_DOWN ;
if ( keystates [ SDL_SCANCODE_Z ] ) input_keys | = WTH_KEY_GESTURE ;
if ( keystates [ SDL_SCANCODE_ESCAPE ] ) input_keys | = WTH_KEY_MENU ;
2025-03-22 21:15:47 +01:00
# if WTH_DEMOS
2023-08-13 16:07:18 +02:00
} ;
# endif
2023-05-11 21:03:45 +02:00
2025-03-17 03:55:25 +01:00
if ( keystates [ SDL_SCANCODE_A ] ) xtrakeys | = WTH_KEY_LEFT ;
if ( keystates [ SDL_SCANCODE_D ] ) xtrakeys | = WTH_KEY_RIGHT ;
if ( keystates [ SDL_SCANCODE_W ] ) xtrakeys | = WTH_KEY_UP ;
if ( keystates [ SDL_SCANCODE_S ] ) xtrakeys | = WTH_KEY_DOWN ;
if ( keystates [ SDL_SCANCODE_LSHIFT ] ) xtrakeys | = WTH_KEY_ATTACK ;
2023-05-17 20:33:19 +02:00
2023-08-13 16:04:30 +02:00
if ( controllerinput ) {
2025-03-22 21:15:47 +01:00
# if WTH_DEMOS
2023-08-13 16:07:18 +02:00
if ( demoStatus ! = 2 ) {
# endif
2025-03-17 03:55:25 +01:00
if ( SDL_JoystickGetButton ( controllerinput , SDL_CONTROLLER_BUTTON_DPAD_LEFT ) | | SDL_JoystickGetAxis ( controllerinput , SDL_CONTROLLER_AXIS_LEFTX ) < - 16383 ) input_keys | = WTH_KEY_LEFT ;
if ( SDL_JoystickGetButton ( controllerinput , SDL_CONTROLLER_BUTTON_DPAD_RIGHT ) | | SDL_JoystickGetAxis ( controllerinput , SDL_CONTROLLER_AXIS_LEFTX ) > 16383 ) input_keys | = WTH_KEY_RIGHT ;
if ( SDL_JoystickGetButton ( controllerinput , SDL_CONTROLLER_BUTTON_DPAD_UP ) | | SDL_JoystickGetAxis ( controllerinput , SDL_CONTROLLER_AXIS_LEFTY ) < - 16383 ) input_keys | = WTH_KEY_UP ;
if ( SDL_JoystickGetButton ( controllerinput , SDL_CONTROLLER_BUTTON_DPAD_DOWN ) | | SDL_JoystickGetAxis ( controllerinput , SDL_CONTROLLER_AXIS_LEFTY ) > 16383 ) input_keys | = WTH_KEY_DOWN ;
if ( SDL_JoystickGetButton ( controllerinput , SDL_CONTROLLER_BUTTON_A ) ) input_keys | = WTH_KEY_GESTURE ;
if ( SDL_JoystickGetButton ( controllerinput , SDL_CONTROLLER_BUTTON_START ) ) input_keys | = WTH_KEY_MENU ;
2025-03-22 21:15:47 +01:00
# if WTH_DEMOS
2023-08-13 16:07:18 +02:00
} ;
# endif
2025-03-17 01:40:48 +01:00
2025-03-17 03:55:25 +01:00
if ( SDL_JoystickGetAxis ( controllerinput , SDL_CONTROLLER_AXIS_RIGHTX ) < - 16383 ) xtrakeys | = WTH_KEY_LEFT ;
if ( SDL_JoystickGetAxis ( controllerinput , SDL_CONTROLLER_AXIS_RIGHTX ) > 16383 ) xtrakeys | = WTH_KEY_RIGHT ;
if ( SDL_JoystickGetAxis ( controllerinput , SDL_CONTROLLER_AXIS_RIGHTY ) < - 16383 ) xtrakeys | = WTH_KEY_UP ;
if ( SDL_JoystickGetAxis ( controllerinput , SDL_CONTROLLER_AXIS_RIGHTY ) > 16383 ) xtrakeys | = WTH_KEY_DOWN ;
if ( SDL_JoystickGetButton ( controllerinput , SDL_CONTROLLER_BUTTON_X ) ) xtrakeys | = WTH_KEY_ATTACK ;
2023-08-13 16:04:30 +02:00
}
2025-03-22 21:15:47 +01:00
# if WTH_DEBUG
2023-05-17 20:33:19 +02:00
int mx , my ;
int win_width , win_height ;
SDL_GetMouseState ( & mx , & my ) ;
SDL_GetWindowSize ( win , & win_width , & win_height ) ;
2024-12-04 04:20:23 +01:00
if ( keystates [ SDL_SCANCODE_5 ] ) DEBUG_keys ^ = 1 ;
2025-01-11 19:49:52 +01:00
if ( keystates [ SDL_SCANCODE_1 ] ) DEBUG_keys ^ = 1 < < 1 ;
if ( keystates [ SDL_SCANCODE_2 ] ) DEBUG_keys ^ = 1 < < 2 ;
if ( keystates [ SDL_SCANCODE_HOME ] ) DEBUG_keys ^ = 1 < < 3 ;
if ( keystates [ SDL_SCANCODE_END ] ) DEBUG_keys ^ = 1 < < 4 ;
if ( keystates [ SDL_SCANCODE_INSERT ] ) DEBUG_keys ^ = 1 < < 5 ;
if ( keystates [ SDL_SCANCODE_PAGEUP ] ) DEBUG_keys ^ = 1 < < 6 ;
if ( keystates [ SDL_SCANCODE_BACKSPACE ] ) DEBUG_keys ^ = 1 < < 7 ;
if ( keystates [ SDL_SCANCODE_TAB ] ) DEBUG_keys ^ = 1 < < 8 ;
if ( keystates [ SDL_SCANCODE_DELETE ] ) DEBUG_keys ^ = 1 < < 9 ;
if ( keystates [ SDL_SCANCODE_PAGEDOWN ] ) DEBUG_keys ^ = 1 < < 10 ;
2024-12-04 04:20:23 +01:00
# define DEBUG_pressed(key) ((DEBUG_keys ^ key) && !(DEBUG_lastkeys ^ key))
if ( DEBUG_pressed ( 1 ) ) addObject (
2025-01-21 15:07:49 +01:00
( mx - cam_x ) / ( win_width / WIDTH ) ,
( my - cam_y ) / ( win_height / HEIGHT ) ,
2023-05-17 20:33:19 +02:00
INTERTYPE_COAT
) ;
2025-01-11 19:49:52 +01:00
if ( DEBUG_pressed ( 1 < < 1 ) ) {
2024-12-04 04:20:23 +01:00
level - - ;
LoadInRoom ( ) ;
} ;
2025-01-11 19:49:52 +01:00
if ( DEBUG_pressed ( 1 < < 2 ) ) {
2025-01-09 22:10:24 +01:00
level + + ;
2023-05-17 20:33:19 +02:00
LoadInRoom ( ) ;
} ;
2024-12-04 04:20:23 +01:00
2025-01-11 19:49:52 +01:00
if ( DEBUG_pressed ( 1 < < 3 ) ) {
2024-12-04 04:20:23 +01:00
DEBUG_objSel - - ;
printf ( " OBJECT SELECTED: %i \n " , DEBUG_objSel ) ;
} ;
2025-01-11 19:49:52 +01:00
if ( DEBUG_pressed ( 1 < < 4 ) ) {
2024-12-04 04:20:23 +01:00
DEBUG_objSel + + ;
printf ( " OBJECT SELECTED: %i \n " , DEBUG_objSel ) ;
} ;
2025-01-11 19:49:52 +01:00
if ( DEBUG_pressed ( 1 < < 5 ) ) {
2024-12-04 04:20:23 +01:00
interacts [ DEBUG_objSel ] . x - = 16 ;
printf ( " %i \n " , interacts [ DEBUG_objSel ] . x ) ;
} ;
2025-01-11 19:49:52 +01:00
if ( DEBUG_pressed ( 1 < < 6 ) ) {
2024-12-04 04:20:23 +01:00
interacts [ DEBUG_objSel ] . x + = 16 ;
printf ( " %i \n " , interacts [ DEBUG_objSel ] . x ) ;
} ;
2025-01-11 19:49:52 +01:00
if ( DEBUG_pressed ( 1 < < 8 ) ) {
2024-12-14 21:00:22 +01:00
options [ 0 ] ^ = WTHOPTS_DEVCAM ;
} ;
2025-01-11 19:49:52 +01:00
if ( DEBUG_pressed ( 1 < < 9 ) ) {
2025-01-16 02:26:09 +01:00
DEBUG_gameFPS / = 2 ;
2025-01-11 19:49:52 +01:00
} ;
if ( DEBUG_pressed ( 1 < < 10 ) ) {
2025-01-16 02:26:09 +01:00
DEBUG_gameFPS = GAME_FPS ;
2025-01-11 19:49:52 +01:00
} ;
2023-11-27 12:35:40 +01:00
2025-01-11 19:49:52 +01:00
DEBUG_lastkeys = DEBUG_keys ;
DEBUG_keys = 0 ;
2023-05-17 20:33:19 +02:00
# endif
2023-04-26 01:59:18 +02:00
} ;
2025-01-13 05:29:27 +01:00
void gameLoop ( ) {
if ( ! running ) {
printf ( " Exiting game... \n " ) ;
2025-03-22 21:15:47 +01:00
# if !WTH_NOSOUND
2025-01-21 15:07:49 +01:00
for ( int i = 0 ; i < WTH_MUSCOUNT ; i + + ) {
2025-01-13 05:29:27 +01:00
Mix_FreeMusic ( music [ i ] ) ;
}
2025-01-21 15:07:49 +01:00
for ( int i = 0 ; i < WTH_SFXCOUNT ; i + + ) {
2025-01-13 05:29:27 +01:00
Mix_FreeChunk ( sfx [ i ] ) ;
}
# endif
2025-01-21 15:07:49 +01:00
for ( int i = 0 ; i < WTH_SPRCOUNT ; i + + ) {
SDL_DestroyTexture ( sprites [ i ] ) ;
}
2025-01-13 05:29:27 +01:00
SDL_DestroyRenderer ( render ) ;
SDL_DestroyWindow ( win ) ;
2025-01-13 22:17:55 +01:00
SDL_Quit ( ) ;
2025-01-13 05:29:27 +01:00
# ifdef __EMSCRIPTEN
emscripten_cancel_main_loop ( ) ;
# endif
return ;
} ;
while ( SDL_PollEvent ( & event ) ) {
switch ( event . type )
{
case SDL_QUIT : running = 0 ; break ;
}
}
keys ( ) ;
2025-03-22 21:15:47 +01:00
# if WTH_DEMOS
2025-01-13 05:29:27 +01:00
if ( keystates [ SDL_SCANCODE_F1 ] & & demoStatus ! = 2 ) {
if ( demoStatus ! = 1 ) {
SDL_ShowSimpleMessageBox ( SDL_MESSAGEBOX_INFORMATION , str_wintitle , " Recording demo... " , NULL ) ;
2025-03-22 21:15:47 +01:00
DaDemo = fopen ( " WTH_Demo.wthd " , " w " ) ;
2025-01-13 05:29:27 +01:00
demoStatus = 1 ;
} else {
SDL_ShowSimpleMessageBox ( SDL_MESSAGEBOX_INFORMATION , str_wintitle , " Demo recording stopped " , NULL ) ;
fclose ( DaDemo ) ;
demoStatus = 0 ;
} ;
}
if ( keystates [ SDL_SCANCODE_F2 ] & & demoStatus ! = 1 ) {
if ( demoStatus ! = 2 ) {
2025-03-22 21:15:47 +01:00
DaDemo = fopen ( " WTH_Demo.wthd " , " r " ) ;
2025-01-13 05:29:27 +01:00
if ( DaDemo ) {
SDL_ShowSimpleMessageBox ( SDL_MESSAGEBOX_INFORMATION , str_wintitle , " Playing back demo... " , NULL ) ;
demoStatus = 2 ;
} ;
} else if ( demoStatus = = 2 ) {
SDL_ShowSimpleMessageBox ( SDL_MESSAGEBOX_INFORMATION , str_wintitle , " Demo playback stopped " , NULL ) ;
fclose ( DaDemo ) ;
demoStatus = 0 ;
} ;
}
switch ( demoStatus )
{
case 1 :
demowrite [ 0 ] = input_keys ;
fwrite ( demowrite , 1 , 1 , DaDemo ) ;
break ;
case 2 :
fread ( demowrite , 1 , 1 , DaDemo ) ;
input_keys = demowrite [ 0 ] ;
fseek ( DaDemo , demoPointer , SEEK_SET ) ;
demoPointer + + ;
break ;
}
# endif
# if (HEIGHT != 270)
2025-01-21 15:07:49 +01:00
cam_y = - CAM_VERTOFFSET ;
2025-01-13 05:29:27 +01:00
# endif
draw ( ) ;
step ( ) ;
SDL_RenderPresent ( render ) ;
SDL_RenderClear ( render ) ;
2025-03-22 21:15:47 +01:00
# if WTH_DEBUG
2025-01-16 02:26:09 +01:00
SDL_Delay ( ( uint32_t ) ( 1.0f / DEBUG_gameFPS * 1000 ) ) ;
2025-01-13 05:29:27 +01:00
# else
2025-01-13 22:17:55 +01:00
SDL_Delay ( ( uint32_t ) ( 1.0f / GAME_FPS * 1000 ) ) ;
2025-01-13 05:29:27 +01:00
# endif
} ;
2024-05-09 03:32:04 +02:00
int main ( int argc , char * argv [ ] ) {
2025-01-10 22:29:11 +01:00
# if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || defined(__APPLE__)
puts ( " WARNING: You are running Wake to Hell under a malware OS. Please consider switching to a less harmful system. " ) ;
# endif
2025-01-21 15:07:49 +01:00
# define REALGAMETITLE GAMETITLE " " VERSION_NUMBER
2025-03-22 21:15:47 +01:00
# if WTH_NOSOUND
2025-01-21 15:07:49 +01:00
if ( SDL_Init ( SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_JOYSTICK ) ! = 0 ) {
2025-01-13 05:29:27 +01:00
# else
2025-01-21 15:07:49 +01:00
if ( SDL_Init ( SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | MIX_INIT_MID | SDL_INIT_JOYSTICK ) ! = 0 ) {
2025-01-13 05:29:27 +01:00
# endif
2025-01-21 15:07:49 +01:00
puts ( " SDL2: Cannot initialize! " ) ;
return 1 ;
} ;
2024-09-07 17:22:44 +02:00
2025-01-21 15:07:49 +01:00
win = SDL_CreateWindow ( REALGAMETITLE , SDL_WINDOWPOS_UNDEFINED , SDL_WINDOWPOS_UNDEFINED , WIDTH , HEIGHT , SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE ) ;
2024-06-23 16:41:58 +02:00
render = SDL_CreateRenderer ( win , - 1 , SDL_RENDERER_PRESENTVSYNC ) ;
2025-01-31 00:16:20 +01:00
// parse arguments
if ( argc > 1 ) {
for ( uint8_t i = 1 ; i < argc ; i + + ) {
if ( argv [ i ] [ 0 ] = = ' - ' & & argv [ i ] [ 1 ] = = ' h ' & & ! argv [ i ] [ 2 ] ) { // HELP
2025-02-04 22:39:05 +01:00
printf ( REALGAMETITLE " (SDL2) " ) ;
2025-01-31 00:16:20 +01:00
puts ( " by blitzdoughnuts " ) ;
puts ( " This program is FREE SOFTWARE, licensed under the Creative Commons Zero plus a waiver of remaining rights. You should have gotten licensing information with the packaged game or source repository. \n See readme.txt for more information. " ) ;
return 0 ;
} ;
2025-02-02 23:17:01 +01:00
if ( argv [ i ] [ 0 ] = = ' - ' & & argv [ i ] [ 1 ] = = ' s ' & & argv [ i ] [ 2 ] & & ! argv [ i ] [ 3 ] ) { // WINDOW SCALE
if ( argv [ i ] [ 2 ] < ' 0 ' | | argv [ i ] [ 2 ] > ' 9 ' ) {
puts ( " Please give an argument to the -s parameter. \n e.g. -s2 " ) ;
2025-01-31 00:16:20 +01:00
return 0 ;
} ;
2025-02-02 23:17:01 +01:00
if ( argv [ i ] [ 2 ] = = ' 0 ' ) {
2025-01-31 00:16:20 +01:00
SDL_SetWindowFullscreen ( win , SDL_WINDOW_FULLSCREEN_DESKTOP ) ;
continue ;
} ;
2025-02-02 23:17:01 +01:00
SDL_SetWindowSize ( win , WIDTH * ( argv [ i ] [ 2 ] - ' 0 ' ) , HEIGHT * ( argv [ i ] [ 2 ] - ' 0 ' ) ) ;
2025-01-31 00:16:20 +01:00
SDL_SetWindowPosition ( win , SDL_WINDOWPOS_CENTERED , SDL_WINDOWPOS_CENTERED ) ;
} ;
} ;
} ;
2025-01-21 15:07:49 +01:00
# undef REALGAMETITLE
2023-04-26 01:59:18 +02:00
2025-01-21 15:07:49 +01:00
SDL_RenderSetLogicalSize ( render , WIDTH , HEIGHT ) ; // keep that cwispy pixew wesowutiown UwU
2023-05-12 20:15:16 +02:00
2023-05-03 15:06:55 +02:00
SDL_SetRenderDrawBlendMode ( render , SDL_BLENDMODE_NONE ) ;
2023-08-13 16:04:30 +02:00
if ( ( SDL_NumJoysticks ( ) > 0 ) ) controllerinput = SDL_JoystickOpen ( 0 ) ;
2024-09-07 17:22:44 +02:00
2025-03-22 21:15:47 +01:00
# if !WTH_NOSOUND
2024-09-07 17:22:44 +02:00
if ( Mix_OpenAudio ( 44100 , MIX_DEFAULT_FORMAT , 1 , 2048 ) ! = 0 )
puts ( " The game couldn't find a usable audio system. Check your audio devices! " ) ;
2024-11-04 01:44:31 +01:00
else {
2025-01-21 15:07:49 +01:00
music [ MUS_NMARE ] = Mix_LoadMUS ( MUSF_NMARE ) ;
music [ MUS_BAR ] = Mix_LoadMUS ( MUSF_BAR ) ;
music [ MUS_CRC ] = Mix_LoadMUS ( MUSF_CRC ) ;
2024-11-04 01:44:31 +01:00
sfx [ 0 ] = Mix_LoadWAV ( " sfx/step.wav " ) ;
sfx [ 1 ] = Mix_LoadWAV ( " sfx/jump.wav " ) ;
sfx [ 2 ] = Mix_LoadWAV ( " sfx/slam.wav " ) ;
sfx [ 3 ] = Mix_LoadWAV ( " sfx/coatpickup.wav " ) ;
sfx [ 4 ] = Mix_LoadWAV ( " sfx/dooropen.wav " ) ;
sfx [ 5 ] = Mix_LoadWAV ( " sfx/doorclose.wav " ) ;
sfx [ 6 ] = Mix_LoadWAV ( " sfx/artifact_badge.wav " ) ;
sfx [ 7 ] = Mix_LoadWAV ( " sfx/artifact_mirror.wav " ) ;
sfx [ 8 ] = Mix_LoadWAV ( " sfx/artifact_donut.wav " ) ;
sfx [ 9 ] = Mix_LoadWAV ( " sfx/artifact_knife.wav " ) ;
sfx [ 10 ] = Mix_LoadWAV ( " sfx/paperopen.wav " ) ;
sfx [ 11 ] = Mix_LoadWAV ( " sfx/paperclose.wav " ) ;
} ;
2024-09-07 17:22:44 +02:00
# endif
SDL_SetRenderDrawColor ( render , 0 , 0x01 , 0x90 , 255 ) ;
keystates = SDL_GetKeyboardState ( NULL ) ; // this was called every time keys() is ran, but apparently it's only needed to be called ONCE :)
2023-04-26 01:59:18 +02:00
2025-01-21 15:07:49 +01:00
// COAT
plrsprites [ WTH_PLR_IDLE_SPR ] = IMG_LoadTexture ( render , " sprites/plr_idle.png " ) ;
2024-12-22 18:38:33 +01:00
plrsprites [ WTH_PLR_WALK_SPR ] = IMG_LoadTexture ( render , " sprites/plr_walk.png " ) ;
plrsprites [ WTH_PLR_DOOR_SPR ] = IMG_LoadTexture ( render , " sprites/plr_enterdoor.png " ) ;
plrsprites [ WTH_PLR_SLEEP_SPR ] = IMG_LoadTexture ( render , " sprites/plr_asleep.png " ) ;
plrsprites [ WTH_PLR_IDLE1_SPR ] = IMG_LoadTexture ( render , " sprites/plr_idle1.png " ) ;
plrsprites [ WTH_PLR_UPSTAIR1_SPR ] = IMG_LoadTexture ( render , " sprites/plr_enterdoor.png " ) ;
2025-01-21 15:38:58 +01:00
plrsprites [ WTH_PLR_UPSTAIR2_SPR ] = IMG_LoadTexture ( render , " sprites/plr_upstairs2.png " ) ;
2024-12-22 18:38:33 +01:00
plrsprites [ WTH_PLR_DNSTAIR1_SPR ] = IMG_LoadTexture ( render , " sprites/plr_idle1.png " ) ;
plrsprites [ WTH_PLR_DNSTAIR2_SPR ] = IMG_LoadTexture ( render , " sprites/plr_walk.png " ) ;
2025-02-06 20:02:07 +01:00
plrsprites [ WTH_PLR_SPOOKED_SPR ] = IMG_LoadTexture ( render , " sprites/plr_surprise.png " ) ;
2025-01-21 15:07:49 +01:00
// NO COAT
plrsprites [ WTH_PLR_SPRCOUNT + WTH_PLR_IDLE_SPR ] = IMG_LoadTexture ( render , " sprites/plr_idle_coatless.png " ) ;
2024-12-22 18:38:33 +01:00
plrsprites [ WTH_PLR_SPRCOUNT + WTH_PLR_WALK_SPR ] = IMG_LoadTexture ( render , " sprites/plr_walk_coatless.png " ) ;
plrsprites [ WTH_PLR_SPRCOUNT + WTH_PLR_DOOR_SPR ] = IMG_LoadTexture ( render , " sprites/plr_enterdoor_coatless.png " ) ;
plrsprites [ WTH_PLR_SPRCOUNT + WTH_PLR_SLEEP_SPR ] = IMG_LoadTexture ( render , " sprites/plr_asleep.png " ) ;
2024-12-30 19:04:53 +01:00
plrsprites [ WTH_PLR_SPRCOUNT + WTH_PLR_IDLE1_SPR ] = IMG_LoadTexture ( render , " sprites/plr_idle1_coatless.png " ) ;
2024-12-22 18:38:33 +01:00
plrsprites [ WTH_PLR_SPRCOUNT + WTH_PLR_UPSTAIR1_SPR ] = IMG_LoadTexture ( render , " sprites/plr_enterdoor_coatless.png " ) ;
2025-01-09 22:26:32 +01:00
plrsprites [ WTH_PLR_SPRCOUNT + WTH_PLR_UPSTAIR2_SPR ] = IMG_LoadTexture ( render , " sprites/plr_upstairs2.png " ) ;
2024-12-22 18:38:33 +01:00
plrsprites [ WTH_PLR_SPRCOUNT + WTH_PLR_DNSTAIR1_SPR ] = IMG_LoadTexture ( render , " sprites/plr_idle1.png " ) ;
plrsprites [ WTH_PLR_SPRCOUNT + WTH_PLR_DNSTAIR2_SPR ] = IMG_LoadTexture ( render , " sprites/plr_walk_coatless.png " ) ;
2025-02-06 20:02:07 +01:00
plrsprites [ WTH_PLR_SPRCOUNT + WTH_PLR_SPOOKED_SPR ] = IMG_LoadTexture ( render , " sprites/plr_surprise.png " ) ;
2024-05-09 22:55:32 +02:00
sprites [ WTH_SPR_MENU ] = IMG_LoadTexture ( render , " sprites/MENU.png " ) ;
2024-08-16 01:12:37 +02:00
sprites [ WTH_SPR_FONTMAP ] = IMG_LoadTexture ( render , " sprites/fontmap.png " ) ;
2024-05-09 22:55:32 +02:00
sprites [ WTH_SPR_MENUBUTTONS ] = IMG_LoadTexture ( render , " sprites/MENUBUTTONS.png " ) ;
sprites [ WTH_SPR_UPARROW ] = IMG_LoadTexture ( render , " sprites/uparrow.png " ) ;
sprites [ WTH_SPR_OPTMENU ] = IMG_LoadTexture ( render , " sprites/OPTIONSMENU.png " ) ;
sprites [ WTH_SPR_BG_STREET ] = IMG_LoadTexture ( render , " sprites/bg.png " ) ;
sprites [ WTH_SPR_BG_HOUSE ] = IMG_LoadTexture ( render , " sprites/bg_house.png " ) ;
sprites [ WTH_SPR_BG_OUTDOORS ] = IMG_LoadTexture ( render , " sprites/bg_outdoors.png " ) ;
sprites [ WTH_SPR_BG_HOSPITAL ] = IMG_LoadTexture ( render , " sprites/bg_hospital.png " ) ;
2025-01-16 02:26:09 +01:00
sprites [ WTH_SPR_BG_HOS_PATIENTS ] = IMG_LoadTexture ( render , " sprites/bg_hos_patients.png " ) ;
sprites [ WTH_SPR_BG_HOS_HAMIE ] = IMG_LoadTexture ( render , " sprites/bg_hos_hamie.png " ) ;
sprites [ WTH_SPR_BG_HOS_RICHIE ] = IMG_LoadTexture ( render , " sprites/bg_hos_richie.png " ) ;
2024-12-14 21:00:22 +01:00
sprites [ WTH_SPR_BG_BAR ] = IMG_LoadTexture ( render , " sprites/bg_bar.png " ) ;
2024-12-22 18:38:33 +01:00
sprites [ WTH_SPR_BG_BAROUT ] = IMG_LoadTexture ( render , " sprites/bg_BARHOUSE.png " ) ;
2024-05-09 22:55:32 +02:00
sprites [ WTH_SPR_COATRACK ] = IMG_LoadTexture ( render , " sprites/coatrack.png " ) ;
sprites [ WTH_SPR_DOOR ] = IMG_LoadTexture ( render , " sprites/door.png " ) ;
2024-12-22 18:38:33 +01:00
sprites [ WTH_SPR_STAIRS ] = IMG_LoadTexture ( render , " sprites/stairs.png " ) ;
2024-05-09 22:55:32 +02:00
sprites [ WTH_SPR_ARTIFACTS ] = IMG_LoadTexture ( render , " sprites/artifacts.png " ) ;
sprites [ WTH_SPR_YOU ] = IMG_LoadTexture ( render , " sprites/you_idle.png " ) ;
sprites [ WTH_SPR_DECOR_BED ] = IMG_LoadTexture ( render , " sprites/bed.png " ) ;
sprites [ WTH_SPR_DECOR_MAILBOX ] = IMG_LoadTexture ( render , " sprites/decor_mailbox.png " ) ;
2024-12-14 21:00:22 +01:00
sprites [ WTH_SPR_DECOR_BARSTOOL ] = IMG_LoadTexture ( render , " sprites/decor_barstool.png " ) ;
2024-05-09 22:55:32 +02:00
sprites [ WTH_SPR_DECOR_HATRACK ] = IMG_LoadTexture ( render , " sprites/decor_hatrack.png " ) ;
2024-09-07 00:38:23 +02:00
sprites [ WTH_SPR_BOOK_HAMIE ] = IMG_LoadTexture ( render , " sprites/book.png " ) ;
2024-08-26 02:18:27 +02:00
sprites [ WTH_SPR_READ_HAMIE ] = IMG_LoadTexture ( render , " sprites/read_hamie.png " ) ;
2025-03-22 21:15:47 +01:00
# if WTH_DEBUG
2025-01-16 02:26:09 +01:00
DEBUG_gameFPS = GAME_FPS ;
2024-12-14 21:00:22 +01:00
DEBUG_sprites [ 0 ] = IMG_LoadTexture ( render , " sprites/DEBUG_gesture.png " ) ;
2024-12-22 18:38:33 +01:00
# endif
2023-11-27 12:35:40 +01:00
2024-05-02 03:12:39 +02:00
running = 1 ;
2023-04-26 01:59:18 +02:00
start ( ) ;
2025-01-13 05:29:27 +01:00
# ifdef __EMSCRIPTEN__
emscripten_set_main_loop ( gameLoop , 0 , 1 ) ;
# else
2025-01-13 22:17:55 +01:00
while ( running ) {
gameLoop ( ) ;
} ;
2024-11-09 16:59:49 +01:00
# endif
2023-04-26 01:59:18 +02:00
return 0 ;
2023-05-30 19:08:21 +02:00
} ;