194 lines
4.8 KiB
C
Executable file
194 lines
4.8 KiB
C
Executable file
/*
|
|
RUTHLESSLY minimal SAF frontend for the game
|
|
|
|
Licensed under CC0, public domain, 2023-2025
|
|
Made by blitzdoughnuts
|
|
*/
|
|
|
|
#define SAF_PROGRAM_NAME "Wake to Hell"
|
|
#define SAF_PLATFORM_SDL2
|
|
|
|
#include "saf.h" // sold separately :3
|
|
|
|
#include "saf_sprites.h"
|
|
|
|
#define WIDTH 64
|
|
#define HEIGHT 64
|
|
#define GAME_FPS 25
|
|
|
|
#define WTH_NOOPTIONS // FORCED on SAF, since options hardly have use on this platform
|
|
|
|
#include "constants.h"
|
|
#include "game.h"
|
|
|
|
#undef CAM_BOUNDS
|
|
|
|
#define CAM_BOUNDS 32
|
|
#define GROUNDLEVEL 200
|
|
|
|
#define drawSprite(spr, x, y, transform, transparent) SAF_drawImage(spr, x, y, transform, transparent)
|
|
// for ease of switching between uncompressed and compressed formats
|
|
|
|
void SAF_init()
|
|
{
|
|
start();
|
|
};
|
|
|
|
void signalDraw(uint8_t index) {
|
|
switch (index)
|
|
{
|
|
case DRAW_PLRUPARROW:
|
|
//drawSprite(sprites[7], plr.x - 20 - cam.x, plr.y - 150 - cam.y);
|
|
break;
|
|
};
|
|
};
|
|
|
|
// inline the simple stuff
|
|
static inline void signalPlaySFX(uint8_t signal) {
|
|
switch (signal)
|
|
{
|
|
case 0: SAF_playSound(1);
|
|
case 2: SAF_playSound(2);
|
|
};
|
|
};
|
|
|
|
static inline void signalPlayMUS(uint8_t signal)
|
|
{
|
|
}; // useless for SAF
|
|
|
|
void signalMisc(uint8_t signal)
|
|
{
|
|
};
|
|
|
|
void saveGame()
|
|
{
|
|
};
|
|
|
|
void loadGame()
|
|
{
|
|
};
|
|
|
|
void manageOptions()
|
|
{
|
|
};
|
|
|
|
void drawSprite_TILED(const uint8_t *image, int8_t x, int8_t y, uint8_t xscale) {
|
|
int8_t _x = x;
|
|
// tile backwards
|
|
while (_x + xscale > 0) {
|
|
drawSprite(image, _x, y, 0, 0);
|
|
_x -= xscale;
|
|
};
|
|
// tile forwards
|
|
_x = x + xscale;
|
|
while (_x < 64) {
|
|
drawSprite(image, _x, y, 0, 0);
|
|
_x += xscale;
|
|
};
|
|
};
|
|
|
|
void draw()
|
|
{
|
|
SAF_clearScreen(SAF_COLOR_BLACK);
|
|
if (fade >= 200) return;
|
|
switch (GAME_STATE)
|
|
{
|
|
case 0:
|
|
SAF_drawText("WAKE TO", 0, 0, SAF_COLOR_WHITE,1);
|
|
SAF_drawText("HELL", 0, 4, SAF_COLOR_WHITE,1);
|
|
SAF_drawText("SAF PORT", 0, 10, SAF_COLOR_WHITE,1);
|
|
|
|
SAF_drawText("PLAY", 6, 24, SAF_COLOR_WHITE,1);
|
|
SAF_drawText("OPTIONS", 6, 30, SAF_COLOR_WHITE,1);
|
|
SAF_drawText("EXIT", 6, 36, SAF_COLOR_WHITE,1);
|
|
|
|
SAF_drawText(">", 0, 24 + (6 * menu.menuselect), SAF_COLOR_WHITE,1);
|
|
break;
|
|
case 1:
|
|
drawSprite_TILED(spr_bg, -cam_x / 4, 0, 64);
|
|
if (cam_x / 4 < 0) drawSprite(spr_bg, -cam_x / 4 + 64, 0, 0, 0);
|
|
if (cam_x / 4 > 0) drawSprite(spr_bg, -cam_x / 4 - 64, 0, 0, 0);
|
|
|
|
#define INTER_X_CALC (interacts[i].x - cam_x) / 4
|
|
#define INTER_Y_CALC (interacts[i].y - cam_y) / 4
|
|
for (uint8_t i = 0; i < interacts_count; i++) {
|
|
if (!(interacts[i].flags & INTER_ACTIVE)) continue;
|
|
switch (interacts[i].objID)
|
|
{
|
|
case 255:
|
|
// to-do: "you" sprites
|
|
break;
|
|
case INTERTYPE_COAT:
|
|
drawSprite((plr.flags & FLAG_HASCOAT) ? spr_coathanger_off : spr_coathanger_on, INTER_X_CALC, INTER_Y_CALC, 0, 0);
|
|
break;
|
|
case INTERTYPE_DECOR:
|
|
// nothing, decor isn't optimal for SAF
|
|
// to-do: make a compiler toggle for it :)
|
|
break;
|
|
case INTERTYPE_ARTIFACT:
|
|
switch (interacts[i].vars[0])
|
|
{
|
|
case ARTIFACT_BADGE: drawSprite(spr_artifact_badge, INTER_X_CALC, INTER_Y_CALC, 0, 0); break;
|
|
case ARTIFACT_KNIFE: drawSprite(spr_artifact_knife, INTER_X_CALC, INTER_Y_CALC, 0, 0); break;
|
|
case ARTIFACT_MIRROR: drawSprite(spr_artifact_mirror, INTER_X_CALC, INTER_Y_CALC, 0, 0); break;
|
|
case ARTIFACT_DONUT: drawSprite(spr_artifact_donut, INTER_X_CALC, INTER_Y_CALC, 0, 0); break;
|
|
};
|
|
break;
|
|
case INTERTYPE_DOOR:
|
|
drawSprite(spr_door, INTER_X_CALC, INTER_Y_CALC, 0, 0);
|
|
break;
|
|
}
|
|
};
|
|
#undef INTER_X_CALC
|
|
#undef INTER_Y_CALC
|
|
// camera position is divided by 4 once calculated
|
|
#define PLR_X_CALC (plr.x - cam_x) / 4
|
|
#define PLR_Y_CALC (plr.y - cam_y) / 4
|
|
switch (plr.animindex)
|
|
{
|
|
case 0: default:
|
|
drawSprite(spr_plr_idle, PLR_X_CALC, PLR_Y_CALC, 0, 0);
|
|
break;
|
|
case 1:
|
|
drawSprite((plr.animframe < 2) ? spr_plr_walk : spr_plr_idle, PLR_X_CALC, PLR_Y_CALC, 0, 0);
|
|
break;
|
|
case 3:
|
|
switch (plr.animframe)
|
|
{
|
|
case 0: drawSprite(spr_plr_idle, PLR_X_CALC, PLR_Y_CALC, 0, 0); break;
|
|
case 1: drawSprite(spr_plr_enterdoor1, PLR_X_CALC, PLR_Y_CALC, 0, 0); break;
|
|
case 2: drawSprite(spr_plr_enterdoor2, PLR_X_CALC, PLR_Y_CALC, 0, 0); break;
|
|
};
|
|
break;
|
|
};
|
|
#undef PLR_X_CALC
|
|
#undef PLR_Y_CALC
|
|
break;
|
|
};
|
|
if (fade >= 128) {
|
|
for (uint8_t i = 0; i < 64; i++) {
|
|
for (uint8_t ii = 0; ii < 64; ii++) {
|
|
if ((ii % 2) == (i % 2)) {
|
|
SAF_drawPixel(i, ii, 0);
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
uint8_t SAF_loop()
|
|
{
|
|
if (SAF_buttonPressed(SAF_BUTTON_UP)) input_keys ^= KEY_UP;
|
|
if (SAF_buttonPressed(SAF_BUTTON_DOWN)) input_keys ^= KEY_DOWN;
|
|
if (SAF_buttonPressed(SAF_BUTTON_LEFT)) input_keys ^= KEY_LEFT;
|
|
if (SAF_buttonPressed(SAF_BUTTON_RIGHT)) input_keys ^= KEY_RIGHT;
|
|
if (SAF_buttonPressed(SAF_BUTTON_A)) input_keys ^= KEY_GESTURE;
|
|
if (SAF_buttonPressed(SAF_BUTTON_B)) input_keys ^= KEY_MENU;
|
|
|
|
step();
|
|
cam_x = plr.x - 48;
|
|
cam_y = 96;
|
|
draw();
|
|
|
|
return 1;
|
|
};
|