Compare commits
6 Commits
f5f5e2c20b
...
main
Author | SHA1 | Date | |
---|---|---|---|
6c25396d4b | |||
0a3a8cb8ab | |||
1a89e4f3b6 | |||
60e1a4ed43 | |||
c7d9f16515 | |||
7e67d09508 |
@@ -5,6 +5,7 @@ cc_library(
|
|||||||
name = "game",
|
name = "game",
|
||||||
srcs = glob(["*.c"]) + [
|
srcs = glob(["*.c"]) + [
|
||||||
"art/game_collectibles.c",
|
"art/game_collectibles.c",
|
||||||
|
"art/game_hud.c",
|
||||||
"art/game_npcs.c",
|
"art/game_npcs.c",
|
||||||
"art/game_player.c",
|
"art/game_player.c",
|
||||||
"art/game_tiles.c",
|
"art/game_tiles.c",
|
||||||
@@ -17,6 +18,7 @@ cc_library(
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_sprites(name="game_collectibles", n=24)
|
add_sprites(name="game_collectibles", n=24)
|
||||||
|
add_sprites(name="game_hud", n=2)
|
||||||
add_sprites(name="game_player", n=96)
|
add_sprites(name="game_player", n=96)
|
||||||
add_sprites(name="game_npcs", n=64)
|
add_sprites(name="game_npcs", n=64)
|
||||||
add_sprites(name="game_tiles", n=120)
|
add_sprites(name="game_tiles", n=120)
|
||||||
|
BIN
game/art/game_hud.aseprite
Normal file
BIN
game/art/game_hud.aseprite
Normal file
Binary file not shown.
8
game/art/game_hud.h
Normal file
8
game/art/game_hud.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef GAME_HUD_H
|
||||||
|
#define GAME_HUD_H
|
||||||
|
|
||||||
|
#include "sys/sys.h"
|
||||||
|
|
||||||
|
extern sys_spritesheet spr_game_hud;
|
||||||
|
|
||||||
|
#endif // ART_GAME_HUD_H
|
BIN
game/art/game_hud.png
Normal file
BIN
game/art/game_hud.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 218 B |
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 500 B After Width: | Height: | Size: 623 B |
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 601 B After Width: | Height: | Size: 603 B |
14
game/game.c
14
game/game.c
@@ -29,10 +29,14 @@ void game_update() {
|
|||||||
sys_update();
|
sys_update();
|
||||||
|
|
||||||
game_frame += 1;
|
game_frame += 1;
|
||||||
game_collectibles_update();
|
|
||||||
game_npcs_update();
|
|
||||||
game_player_update();
|
|
||||||
|
|
||||||
|
bool allow_input = true;
|
||||||
|
|
||||||
|
game_collectibles_update();
|
||||||
|
game_dialogue_update(&allow_input);
|
||||||
|
game_inflict_update(&allow_input);
|
||||||
|
game_npcs_update(&allow_input);
|
||||||
|
game_player_update(&allow_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_draw() {
|
void game_draw() {
|
||||||
@@ -46,4 +50,8 @@ void game_draw() {
|
|||||||
game_player_draw();
|
game_player_draw();
|
||||||
|
|
||||||
sys_camera_reset();
|
sys_camera_reset();
|
||||||
|
|
||||||
|
game_player_draw_hud();
|
||||||
|
game_inflict_draw();
|
||||||
|
game_dialogue_draw();
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include "game_collectible.h"
|
#include "game_collectible.h"
|
||||||
#include "game_collision.h"
|
#include "game_collision.h"
|
||||||
|
#include "game_dialogue.h"
|
||||||
|
#include "game_inflict.h"
|
||||||
#include "game_math.h"
|
#include "game_math.h"
|
||||||
#include "game_npc.h"
|
#include "game_npc.h"
|
||||||
#include "game_palette.h"
|
#include "game_palette.h"
|
||||||
|
@@ -66,6 +66,12 @@ void game_collectibles_update() {
|
|||||||
game_collectible_bubble.x=c->x / PIXEL_SZ_MICROPIXEL;
|
game_collectible_bubble.x=c->x / PIXEL_SZ_MICROPIXEL;
|
||||||
game_collectible_bubble.y=c->y / PIXEL_SZ_MICROPIXEL + game_collectible_wobb();
|
game_collectible_bubble.y=c->y / PIXEL_SZ_MICROPIXEL + game_collectible_wobb();
|
||||||
game_collectible_bubble.r=r * PIXEL_SZ_MICROPIXEL;
|
game_collectible_bubble.r=r * PIXEL_SZ_MICROPIXEL;
|
||||||
|
|
||||||
|
switch (c->type) {
|
||||||
|
case GAME_COLLECTIBLE_TYPE_CAKE: game_player_collectibles.n_cake += 16; break;
|
||||||
|
case GAME_COLLECTIBLE_TYPE_MONEY_BIG: game_player_collectibles.n_dollars += 5; break;
|
||||||
|
case GAME_COLLECTIBLE_TYPE_MONEY_SMALL: game_player_collectibles.n_dollars += 1; break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
158
game/game_dialogue.c
Normal file
158
game/game_dialogue.c
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "device/device.h"
|
||||||
|
#include "sys/sys.h"
|
||||||
|
#include "game.h"
|
||||||
|
|
||||||
|
#define GAME_DIALOGUE_MAX_N_CHARS 256
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GAME_DIALOGUE_SCREEN_STATE_BOB_IN,
|
||||||
|
GAME_DIALOGUE_SCREEN_STATE_TYPEWRITER,
|
||||||
|
GAME_DIALOGUE_SCREEN_STATE_WAIT,
|
||||||
|
GAME_DIALOGUE_SCREEN_STATE_BOB_OUT,
|
||||||
|
} game_dialogue_screen_state;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
bool visible;
|
||||||
|
bool modal;
|
||||||
|
const char* dialogue;
|
||||||
|
|
||||||
|
sys_i32 w;
|
||||||
|
sys_i32 h;
|
||||||
|
|
||||||
|
game_dialogue_screen_state state;
|
||||||
|
sys_i32 state_progress;
|
||||||
|
sys_i32 n_chars_shown;
|
||||||
|
sys_i32 n_chars;
|
||||||
|
} game_dialogue_screen;
|
||||||
|
|
||||||
|
uint8_t game_dialogue_frame;
|
||||||
|
|
||||||
|
void game_dialogue_display(const char* text, bool modal) {
|
||||||
|
game_dialogue_screen.visible = true;
|
||||||
|
game_dialogue_screen.modal = modal;
|
||||||
|
game_dialogue_screen.dialogue = text;
|
||||||
|
sys_measure_text(text, &game_dialogue_screen.w, &game_dialogue_screen.h);
|
||||||
|
|
||||||
|
game_dialogue_screen.state = GAME_DIALOGUE_SCREEN_STATE_BOB_IN;
|
||||||
|
game_dialogue_screen.state_progress = 0;
|
||||||
|
game_dialogue_screen.n_chars_shown = 0;
|
||||||
|
game_dialogue_screen.n_chars = strlen(text);
|
||||||
|
assert(game_dialogue_screen.n_chars <= GAME_DIALOGUE_MAX_N_CHARS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_dialogue_update(bool* allow_input) {
|
||||||
|
game_dialogue_frame = ((uint32_t) game_dialogue_frame + 1) & 0xff;
|
||||||
|
|
||||||
|
if (
|
||||||
|
game_dialogue_screen.visible &&
|
||||||
|
game_dialogue_screen.state < GAME_DIALOGUE_SCREEN_STATE_BOB_OUT
|
||||||
|
) {
|
||||||
|
*allow_input = false;
|
||||||
|
|
||||||
|
if (sys_btnp(DEVICE_BUTTON_0, false)) {
|
||||||
|
if (game_dialogue_screen.state < GAME_DIALOGUE_SCREEN_STATE_WAIT) {
|
||||||
|
game_dialogue_screen.state = GAME_DIALOGUE_SCREEN_STATE_WAIT;
|
||||||
|
game_dialogue_screen.n_chars_shown = game_dialogue_screen.n_chars;
|
||||||
|
} else {
|
||||||
|
game_dialogue_screen.state = GAME_DIALOGUE_SCREEN_STATE_BOB_OUT;
|
||||||
|
game_dialogue_screen.state_progress = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (game_dialogue_screen.state) {
|
||||||
|
case GAME_DIALOGUE_SCREEN_STATE_BOB_IN:
|
||||||
|
game_dialogue_screen.state_progress += 25;
|
||||||
|
if (game_dialogue_screen.state_progress >= 0x100) {
|
||||||
|
game_dialogue_screen.state = GAME_DIALOGUE_SCREEN_STATE_TYPEWRITER;
|
||||||
|
game_dialogue_screen.state_progress = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GAME_DIALOGUE_SCREEN_STATE_TYPEWRITER:
|
||||||
|
if (game_dialogue_frame % 4 == 0) {
|
||||||
|
game_dialogue_screen.n_chars_shown = sys_min_i32(
|
||||||
|
game_dialogue_screen.n_chars_shown + 1,
|
||||||
|
game_dialogue_screen.n_chars
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (game_dialogue_screen.n_chars_shown >= game_dialogue_screen.n_chars) {
|
||||||
|
game_dialogue_screen.state = GAME_DIALOGUE_SCREEN_STATE_WAIT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GAME_DIALOGUE_SCREEN_STATE_WAIT:
|
||||||
|
break;
|
||||||
|
case GAME_DIALOGUE_SCREEN_STATE_BOB_OUT:
|
||||||
|
game_dialogue_screen.state_progress += 25;
|
||||||
|
if (game_dialogue_screen.state_progress >= 0x100) {
|
||||||
|
game_dialogue_screen.visible = false;
|
||||||
|
game_dialogue_screen.state_progress = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool game_dialogue_is_busy() {
|
||||||
|
return game_dialogue_screen.visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_dialogue_draw() {
|
||||||
|
if (!game_dialogue_screen.visible) { return; }
|
||||||
|
|
||||||
|
sys_i32 x = DEVICE_W / 2 - game_dialogue_screen.w / 2;
|
||||||
|
sys_i32 y = DEVICE_H - game_dialogue_screen.h - 8;
|
||||||
|
|
||||||
|
if (game_dialogue_screen.modal) {
|
||||||
|
y = DEVICE_H / 2 - game_dialogue_screen.h / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
sys_i32 interp_amt = 0;
|
||||||
|
switch (game_dialogue_screen.state) {
|
||||||
|
case GAME_DIALOGUE_SCREEN_STATE_BOB_IN:
|
||||||
|
interp_amt = 255 - game_dialogue_screen.state_progress;
|
||||||
|
break;
|
||||||
|
case GAME_DIALOGUE_SCREEN_STATE_BOB_OUT:
|
||||||
|
interp_amt = game_dialogue_screen.state_progress;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int x0 = x - 4;
|
||||||
|
int y0 = y - 4;
|
||||||
|
int x1 = x + game_dialogue_screen.w + 4;
|
||||||
|
int y1 = y + game_dialogue_screen.h + 4;
|
||||||
|
|
||||||
|
sys_i32 cx = (x0 + x1)/2;
|
||||||
|
sys_i32 cy = (y0 + y1)/2;
|
||||||
|
|
||||||
|
sys_oval_fill(
|
||||||
|
x0 + (cx - x0) * interp_amt / 256,
|
||||||
|
y0 + (cy - y0) * interp_amt / 256,
|
||||||
|
x1 + (cx - x1) * interp_amt / 256,
|
||||||
|
y1 + (cy - y1) * interp_amt / 256,
|
||||||
|
game_dialogue_screen.modal ? 0 : 1
|
||||||
|
);
|
||||||
|
|
||||||
|
if (game_dialogue_screen.state == GAME_DIALOGUE_SCREEN_STATE_BOB_OUT) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char chars[GAME_DIALOGUE_MAX_N_CHARS + 1];
|
||||||
|
strcpy(chars, game_dialogue_screen.dialogue);
|
||||||
|
chars[game_dialogue_screen.n_chars_shown] = 0;
|
||||||
|
|
||||||
|
if (game_dialogue_screen.modal) {
|
||||||
|
for (int dy = -2; dy <= 2; dy++) {
|
||||||
|
for (int dx = -2; dx <= 2; dx++) {
|
||||||
|
sys_print(chars, x+dx, y+dy, 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int dy = -1; dy <= 1; dy++) {
|
||||||
|
for (int dx = -1; dx <= 1; dx++) {
|
||||||
|
sys_print(chars, x+dx, y+dy, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sys_print(chars, x, y, 7);
|
||||||
|
}
|
12
game/game_dialogue.h
Normal file
12
game/game_dialogue.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#ifndef GAME_DIALOGUE_H
|
||||||
|
#define GAME_DIALOGUE_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
void game_dialogue_display(const char* text, bool modal);
|
||||||
|
bool game_dialogue_is_busy();
|
||||||
|
|
||||||
|
void game_dialogue_update(bool* allow_input);
|
||||||
|
void game_dialogue_draw();
|
||||||
|
|
||||||
|
#endif // GAME_DIALOGUE_H
|
119
game/game_inflict.c
Normal file
119
game/game_inflict.c
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
#include "game.h"
|
||||||
|
#include "device/device.h"
|
||||||
|
|
||||||
|
#define GAME_INFLICT_SCREEN_MAX_N_MODALS 4
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GAME_INFLICT_SCREEN_STATE_WAIT_FOR_DIALOGUE,
|
||||||
|
GAME_INFLICT_SCREEN_STATE_CLOSE_EYELIDS,
|
||||||
|
GAME_INFLICT_SCREEN_STATE_PERFORM_MODALS,
|
||||||
|
GAME_INFLICT_SCREEN_STATE_OPEN_EYELIDS,
|
||||||
|
GAME_INFLICT_SCREEN_STATE_INACTIVE
|
||||||
|
} game_inflict_screen_state_t;
|
||||||
|
|
||||||
|
game_inflict_screen_state_t game_inflict_screen_state =
|
||||||
|
GAME_INFLICT_SCREEN_STATE_INACTIVE;
|
||||||
|
|
||||||
|
game_inflict_type game_inflict_screen_type = 0;
|
||||||
|
sys_i32 game_inflict_screen_n_modals = 0;
|
||||||
|
sys_i32 game_inflict_screen_next_modal = 0;
|
||||||
|
sys_i32 game_inflict_screen_progress = 0;
|
||||||
|
|
||||||
|
const char* game_inflict_screen_modals[GAME_INFLICT_SCREEN_MAX_N_MODALS];
|
||||||
|
|
||||||
|
void game_inflict_apply();
|
||||||
|
|
||||||
|
void game_inflict_update(bool* allow_input) {
|
||||||
|
if (game_inflict_screen_state <= GAME_INFLICT_SCREEN_STATE_OPEN_EYELIDS) {
|
||||||
|
*allow_input = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (game_inflict_screen_state) {
|
||||||
|
case GAME_INFLICT_SCREEN_STATE_WAIT_FOR_DIALOGUE:
|
||||||
|
if (!game_dialogue_is_busy()) {
|
||||||
|
game_inflict_screen_state = GAME_INFLICT_SCREEN_STATE_CLOSE_EYELIDS;
|
||||||
|
game_inflict_screen_progress = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GAME_INFLICT_SCREEN_STATE_CLOSE_EYELIDS:
|
||||||
|
game_inflict_screen_progress += 10;
|
||||||
|
if (game_inflict_screen_progress >= 0x100) {
|
||||||
|
game_inflict_screen_state =
|
||||||
|
GAME_INFLICT_SCREEN_STATE_PERFORM_MODALS;
|
||||||
|
game_inflict_screen_progress = 0;
|
||||||
|
game_inflict_apply();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GAME_INFLICT_SCREEN_STATE_PERFORM_MODALS:
|
||||||
|
if (game_dialogue_is_busy()) {
|
||||||
|
// fine, don't do anything
|
||||||
|
} else if (game_inflict_screen_next_modal < game_inflict_screen_n_modals) {
|
||||||
|
game_dialogue_display(game_inflict_screen_modals[
|
||||||
|
game_inflict_screen_next_modal++
|
||||||
|
], true);
|
||||||
|
} else {
|
||||||
|
game_inflict_screen_state =
|
||||||
|
GAME_INFLICT_SCREEN_STATE_OPEN_EYELIDS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GAME_INFLICT_SCREEN_STATE_OPEN_EYELIDS:
|
||||||
|
game_inflict_screen_progress += 10;
|
||||||
|
if (game_inflict_screen_progress >= 0x100) {
|
||||||
|
game_inflict_screen_state =
|
||||||
|
GAME_INFLICT_SCREEN_STATE_INACTIVE;
|
||||||
|
game_inflict_screen_progress = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GAME_INFLICT_SCREEN_STATE_INACTIVE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_inflict_enqueue(int inflict_id) {
|
||||||
|
game_inflict_screen_state = GAME_INFLICT_SCREEN_STATE_WAIT_FOR_DIALOGUE;
|
||||||
|
|
||||||
|
switch (inflict_id) {
|
||||||
|
case GAME_INFLICT_TYPE_CHICKEN:
|
||||||
|
game_inflict_screen_type = GAME_INFLICT_TYPE_CHICKEN;
|
||||||
|
game_inflict_screen_n_modals = 2;
|
||||||
|
game_inflict_screen_next_modal = 0;
|
||||||
|
game_inflict_screen_modals[0] = "For your birthday...";
|
||||||
|
game_inflict_screen_modals[1] = "You're a chicken!";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_inflict_apply() {
|
||||||
|
switch (game_inflict_screen_type) {
|
||||||
|
case GAME_INFLICT_TYPE_CHICKEN:
|
||||||
|
game_player_collectibles.n_cake = 0;
|
||||||
|
game_player_phase = GAME_PLAYER_PHASE_CHICKEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_inflict_draw_eyelids(uint8_t progress);
|
||||||
|
void game_inflict_draw() {
|
||||||
|
switch (game_inflict_screen_state) {
|
||||||
|
case GAME_INFLICT_SCREEN_STATE_WAIT_FOR_DIALOGUE:
|
||||||
|
// TODO: Screen distortion
|
||||||
|
break;
|
||||||
|
case GAME_INFLICT_SCREEN_STATE_CLOSE_EYELIDS:
|
||||||
|
game_inflict_draw_eyelids(game_inflict_screen_progress & 0xff);
|
||||||
|
break;
|
||||||
|
case GAME_INFLICT_SCREEN_STATE_PERFORM_MODALS:
|
||||||
|
game_inflict_draw_eyelids(255);
|
||||||
|
break;
|
||||||
|
case GAME_INFLICT_SCREEN_STATE_OPEN_EYELIDS:
|
||||||
|
game_inflict_draw_eyelids(255 - game_inflict_screen_progress & 0xff);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_inflict_draw_eyelids(uint8_t progress) {
|
||||||
|
sys_i32 offset = DEVICE_H / 2 -
|
||||||
|
((255 - progress) * (255 - progress) * DEVICE_H/2) / (255 * 255);
|
||||||
|
sys_rect_fill(0, 0, DEVICE_W, offset, 0);
|
||||||
|
sys_rect_fill(0, DEVICE_H - offset, DEVICE_W, DEVICE_H, 0);
|
||||||
|
}
|
19
game/game_inflict.h
Normal file
19
game/game_inflict.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef GAME_INFLICT_H
|
||||||
|
#define GAME_INFLICT_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "game.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
// GAME_INFLICT_TYPE_CROC=1,
|
||||||
|
GAME_INFLICT_TYPE_CHICKEN=2,
|
||||||
|
// GAME_INFLICT_TYPE_BAT=3,
|
||||||
|
// GAME_INFLICT_TYPE_ASLEEP=4,
|
||||||
|
} game_inflict_type;
|
||||||
|
|
||||||
|
void game_inflict_update(bool* allow_input);
|
||||||
|
void game_inflict_draw();
|
||||||
|
|
||||||
|
void game_inflict_enqueue(int inflict_id);
|
||||||
|
|
||||||
|
#endif // GAME_INFLICT_H
|
@@ -1,5 +1,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include "art/game_hud.h"
|
||||||
#include "art/game_npcs.h"
|
#include "art/game_npcs.h"
|
||||||
|
#include "device/device.h"
|
||||||
#include "sys/sys.h"
|
#include "sys/sys.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
|
||||||
@@ -17,8 +19,12 @@ typedef struct {
|
|||||||
uint8_t shine;
|
uint8_t shine;
|
||||||
} game_npc_palette;
|
} game_npc_palette;
|
||||||
|
|
||||||
game_npc_palette game_npc_palettes[1] = {
|
game_npc_palette game_npc_palettes[5] = {
|
||||||
{14, 12, 13, 6, 7, 6, 7, 0, 8, 7}
|
{14, 13, 12, 6, 7, 6, 7, 0, 8, 7},
|
||||||
|
{4, 2, 3, 6, 7, 9, 10, 0, 4, 7},
|
||||||
|
{13, 0, 1, 1, 13, 11, 10, 0, 13, 7},
|
||||||
|
{7, 14, 7, 14, 7, 14, 7, 0, 14, 7},
|
||||||
|
{12, 1, 13, 12, 6, 8, 7, 0, 8, 7}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GAME_NPC_N_PALETTES (sizeof(game_npc_palettes)/sizeof(game_npc_palettes[0]))
|
#define GAME_NPC_N_PALETTES (sizeof(game_npc_palettes)/sizeof(game_npc_palettes[0]))
|
||||||
@@ -38,6 +44,7 @@ game_npc* game_npc_create(sys_i32 x, sys_i32 y) {
|
|||||||
.palette_id = 0,
|
.palette_id = 0,
|
||||||
.inflict_id = 0,
|
.inflict_id = 0,
|
||||||
.face_left = false,
|
.face_left = false,
|
||||||
|
.flip = false,
|
||||||
|
|
||||||
.n_dialogues = 0,
|
.n_dialogues = 0,
|
||||||
.no_cake_dialogue = NULL,
|
.no_cake_dialogue = NULL,
|
||||||
@@ -45,13 +52,73 @@ game_npc* game_npc_create(sys_i32 x, sys_i32 y) {
|
|||||||
|
|
||||||
.present = true,
|
.present = true,
|
||||||
.n_dialogues_seen = 0,
|
.n_dialogues_seen = 0,
|
||||||
|
.received_cake = false,
|
||||||
};
|
};
|
||||||
game_npcs[id] = npc;
|
game_npcs[id] = npc;
|
||||||
return &game_npcs[id];
|
return &game_npcs[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_npcs_update() {
|
void game_npc_trigger_dialogue(sys_i32 npc_id);
|
||||||
// TODO
|
void game_npcs_update(bool* allow_input) {
|
||||||
|
if (!*allow_input) { return; }
|
||||||
|
|
||||||
|
// check collision with player
|
||||||
|
sys_i32 player_x, player_y;
|
||||||
|
|
||||||
|
game_player_get_center(&player_x, &player_y);
|
||||||
|
for (sys_i32 i = 0; i < game_npc_next; i++) {
|
||||||
|
game_npc* n = &game_npcs[i];
|
||||||
|
|
||||||
|
if (!n->present) { continue; }
|
||||||
|
|
||||||
|
sys_i32 r_distcheck = 21 * PIXEL_SZ_MICROPIXEL;
|
||||||
|
|
||||||
|
int64_t dx = player_x - n->x;
|
||||||
|
int64_t dy = player_y - n->y;
|
||||||
|
|
||||||
|
if (
|
||||||
|
sys_btnp(DEVICE_BUTTON_0, false) &&
|
||||||
|
dx * dx + dy * dy <= r_distcheck * r_distcheck
|
||||||
|
) {
|
||||||
|
n->face_left = dx < 0;
|
||||||
|
game_npc_trigger_dialogue(i);
|
||||||
|
*allow_input = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_npc_trigger_dialogue(sys_i32 npc_id) {
|
||||||
|
const char* dialogue;
|
||||||
|
|
||||||
|
// TODO: Make it possible for the player to have the cake
|
||||||
|
game_npc* npc = &game_npcs[npc_id];
|
||||||
|
|
||||||
|
if (
|
||||||
|
!npc->received_cake &&
|
||||||
|
game_player_collectibles.n_cake <= 0 &&
|
||||||
|
npc->no_cake_dialogue != NULL
|
||||||
|
) {
|
||||||
|
dialogue = npc->no_cake_dialogue;
|
||||||
|
} else if (npc->n_dialogues_seen < npc->n_dialogues) {
|
||||||
|
dialogue = npc->dialogues[npc->n_dialogues_seen++];
|
||||||
|
} else if (npc->n_dialogues > 0) {
|
||||||
|
dialogue = npc->dialogues[npc->n_dialogues - 1];
|
||||||
|
} else {
|
||||||
|
// nothing to do with this npc
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// give the NPC cake if possible
|
||||||
|
if (!npc->received_cake && game_player_collectibles.n_cake > 0) {
|
||||||
|
npc->received_cake = true;
|
||||||
|
game_player_collectibles.n_cake -= 1;
|
||||||
|
|
||||||
|
if (npc->inflict_id != 0) {
|
||||||
|
game_inflict_enqueue(npc->inflict_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
game_dialogue_display(dialogue, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_npcs_draw() {
|
void game_npcs_draw() {
|
||||||
@@ -61,11 +128,24 @@ void game_npcs_draw() {
|
|||||||
if (!n->present) { continue; }
|
if (!n->present) { continue; }
|
||||||
|
|
||||||
game_npc_palette palette =
|
game_npc_palette palette =
|
||||||
game_npc_palettes[game_npcs[i].palette_id % GAME_NPC_N_PALETTES];
|
game_npc_palettes[n->palette_id % GAME_NPC_N_PALETTES];
|
||||||
|
|
||||||
|
if (n->received_cake) {
|
||||||
|
sys_sprite_draw_ext(
|
||||||
|
spr_game_hud,
|
||||||
|
0,
|
||||||
|
n->x / PIXEL_SZ_MICROPIXEL - 4,
|
||||||
|
n->y / PIXEL_SZ_MICROPIXEL - 18,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
!n->face_left,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
sys_dpal_set(14, palette.main);
|
sys_dpal_set(14, palette.main);
|
||||||
sys_dpal_set(12, palette.alt0_0);
|
sys_dpal_set(13, palette.alt0_0);
|
||||||
sys_dpal_set(13, palette.alt0_1);
|
sys_dpal_set(12, palette.alt0_1);
|
||||||
sys_dpal_set(6, palette.alt1_0);
|
sys_dpal_set(6, palette.alt1_0);
|
||||||
sys_dpal_set(7, palette.alt1_1);
|
sys_dpal_set(7, palette.alt1_1);
|
||||||
sys_dpal_set(9, palette.eye_0);
|
sys_dpal_set(9, palette.eye_0);
|
||||||
@@ -83,7 +163,7 @@ void game_npcs_draw() {
|
|||||||
2,
|
2,
|
||||||
2,
|
2,
|
||||||
n->face_left,
|
n->face_left,
|
||||||
false
|
n->flip
|
||||||
);
|
);
|
||||||
|
|
||||||
sys_dpal_reset();
|
sys_dpal_reset();
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
#ifndef GAME_NPC_H
|
#ifndef GAME_NPC_H
|
||||||
#define GAME_NPC_H
|
#define GAME_NPC_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include "sys/sys.h"
|
#include "sys/sys.h"
|
||||||
|
|
||||||
#define GAME_NPC_MAX_N_DIALOGUES 16
|
#define GAME_NPC_MAX_N_DIALOGUES 16
|
||||||
@@ -13,19 +14,21 @@ typedef struct {
|
|||||||
uint8_t palette_id;
|
uint8_t palette_id;
|
||||||
uint8_t inflict_id;
|
uint8_t inflict_id;
|
||||||
bool face_left;
|
bool face_left;
|
||||||
|
bool flip;
|
||||||
|
|
||||||
int n_dialogues;
|
uint8_t n_dialogues;
|
||||||
const char* no_cake_dialogue;
|
const char* no_cake_dialogue;
|
||||||
const char* dialogues[GAME_NPC_MAX_N_DIALOGUES];
|
const char* dialogues[GAME_NPC_MAX_N_DIALOGUES];
|
||||||
|
|
||||||
bool present;
|
bool present;
|
||||||
int n_dialogues_seen;
|
uint8_t n_dialogues_seen;
|
||||||
|
bool received_cake;
|
||||||
} game_npc;
|
} game_npc;
|
||||||
|
|
||||||
// pointer goes to data section and will be valid forever
|
// pointer goes to data section and will be valid forever
|
||||||
game_npc* game_npc_create(sys_i32 x, sys_i32 y);
|
game_npc* game_npc_create(sys_i32 x, sys_i32 y);
|
||||||
|
|
||||||
void game_npcs_update();
|
void game_npcs_update(bool* allow_input);
|
||||||
void game_npcs_draw();
|
void game_npcs_draw();
|
||||||
|
|
||||||
#endif // GAME_NPC_H
|
#endif // GAME_NPC_H
|
@@ -1,3 +1,5 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include "art/game_hud.h"
|
||||||
#include "art/game_player.h"
|
#include "art/game_player.h"
|
||||||
#include "art/game_tiles.h"
|
#include "art/game_tiles.h"
|
||||||
#include "device/device.h"
|
#include "device/device.h"
|
||||||
@@ -20,6 +22,13 @@ sys_i32 game_player_dx = 0;
|
|||||||
sys_i32 game_player_dy = 0;
|
sys_i32 game_player_dy = 0;
|
||||||
bool game_player_faceleft = false;
|
bool game_player_faceleft = false;
|
||||||
|
|
||||||
|
game_player_collectibles_t game_player_collectibles = {
|
||||||
|
.n_cake=0,
|
||||||
|
.n_dollars=0
|
||||||
|
};
|
||||||
|
|
||||||
|
game_player_phase_t game_player_phase = GAME_PLAYER_PHASE_CROC;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GAME_PLAYER_ANIM_STANDING,
|
GAME_PLAYER_ANIM_STANDING,
|
||||||
GAME_PLAYER_ANIM_WALKING,
|
GAME_PLAYER_ANIM_WALKING,
|
||||||
@@ -37,7 +46,26 @@ void game_player_init() {
|
|||||||
game_player_bbox.y = game_map_player_start_y;
|
game_player_bbox.y = game_map_player_start_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_player_update() {
|
void game_player_update(bool* allow_input) {
|
||||||
|
sys_i32 dx_max, ddx;
|
||||||
|
switch (game_player_phase) {
|
||||||
|
case GAME_PLAYER_PHASE_CROC:
|
||||||
|
dx_max = 0x140;
|
||||||
|
ddx = 0x50;
|
||||||
|
game_player_bbox.x_origin=0x500;
|
||||||
|
game_player_bbox.w = 0xa00;
|
||||||
|
game_player_bbox.y_origin = game_player_bbox.h = 0xa00; break;
|
||||||
|
break;
|
||||||
|
case GAME_PLAYER_PHASE_CHICKEN:
|
||||||
|
dx_max = 0xd0;
|
||||||
|
ddx = 0x30;
|
||||||
|
game_player_bbox.x_origin=0x300;
|
||||||
|
game_player_bbox.w = 0x600;
|
||||||
|
game_player_bbox.y_origin = game_player_bbox.h = 0x700; break;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
game_collision collision = game_collision_move_to_contact(
|
game_collision collision = game_collision_move_to_contact(
|
||||||
&game_player_bbox,
|
&game_player_bbox,
|
||||||
game_player_dx,
|
game_player_dx,
|
||||||
@@ -58,13 +86,13 @@ void game_player_update() {
|
|||||||
// round up
|
// round up
|
||||||
0x7f * sys_sgn_i32(game_player_dx)
|
0x7f * sys_sgn_i32(game_player_dx)
|
||||||
) / 0x80;
|
) / 0x80;
|
||||||
if (sys_abs_i32(game_player_dx) > 0x140) {
|
if (sys_abs_i32(game_player_dx) > dx_max) {
|
||||||
game_player_dx = sys_sgn_i32(game_player_dx) * 0x140;
|
game_player_dx = sys_sgn_i32(game_player_dx) * dx_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wanted_dx = game_player_dx;
|
int wanted_dx = game_player_dx;
|
||||||
if (sys_btn(DEVICE_BUTTON_L)) { wanted_dx -= 0x50; }
|
if (*allow_input && sys_btn(DEVICE_BUTTON_L)) { wanted_dx -= ddx; }
|
||||||
if (sys_btn(DEVICE_BUTTON_R)) { wanted_dx += 0x50; }
|
if (*allow_input && sys_btn(DEVICE_BUTTON_R)) { wanted_dx += ddx; }
|
||||||
|
|
||||||
// allow this if grounded or if it's not a change of direction
|
// allow this if grounded or if it's not a change of direction
|
||||||
if (
|
if (
|
||||||
@@ -82,7 +110,7 @@ void game_player_update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (game_player_grounded || game_player_coyote_frames > 0) {
|
if (game_player_grounded || game_player_coyote_frames > 0) {
|
||||||
if (sys_btnp(DEVICE_BUTTON_U, false)) {
|
if (*allow_input && sys_btnp(DEVICE_BUTTON_U, false)) {
|
||||||
game_player_dy = -0x200;
|
game_player_dy = -0x200;
|
||||||
game_player_jump_frames = 13;
|
game_player_jump_frames = 13;
|
||||||
game_player_grounded = false;
|
game_player_grounded = false;
|
||||||
@@ -129,6 +157,14 @@ void game_player_update() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void game_player_get_center(sys_i32* x, sys_i32* y) {
|
||||||
|
*x = game_player_bbox.x;
|
||||||
|
|
||||||
|
// center on me, not on feet
|
||||||
|
*y = game_player_bbox.y - 8 * PIXEL_SZ_MICROPIXEL;
|
||||||
|
}
|
||||||
|
|
||||||
void game_player_set_camera() {
|
void game_player_set_camera() {
|
||||||
sys_i32 x = game_player_bbox.x;
|
sys_i32 x = game_player_bbox.x;
|
||||||
sys_i32 y = game_player_bbox.y;
|
sys_i32 y = game_player_bbox.y;
|
||||||
@@ -144,17 +180,24 @@ void game_player_set_camera() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void game_player_draw() {
|
void game_player_draw() {
|
||||||
int game_player_image;
|
uint8_t game_player_image;
|
||||||
|
|
||||||
|
uint8_t base = 0;
|
||||||
|
switch (game_player_phase) {
|
||||||
|
default: case GAME_PLAYER_PHASE_CROC: base = 0; break;
|
||||||
|
case GAME_PLAYER_PHASE_CHICKEN: base = 32; break;
|
||||||
|
}
|
||||||
|
|
||||||
switch (game_player_anim_state) {
|
switch (game_player_anim_state) {
|
||||||
case GAME_PLAYER_ANIM_WALKING:
|
case GAME_PLAYER_ANIM_WALKING:
|
||||||
game_player_image = 2 + (game_player_anim_progress / 0x80) * 2;
|
game_player_image = base + 2 + (game_player_anim_progress / 0x80) * 2;
|
||||||
break;
|
break;
|
||||||
case GAME_PLAYER_ANIM_FLOATING:
|
case GAME_PLAYER_ANIM_FLOATING:
|
||||||
game_player_image = 6;
|
game_player_image = base + 6;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
case GAME_PLAYER_ANIM_STANDING:
|
case GAME_PLAYER_ANIM_STANDING:
|
||||||
game_player_image = 0;
|
game_player_image = base + 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,9 +225,65 @@ void game_player_anim_add_progress(uint8_t amt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void game_player_get_center(sys_i32* x, sys_i32* y) {
|
void game_player_draw_hud_number(sys_i32 number, sys_i32 x, sys_i32 y);
|
||||||
*x = game_player_bbox.x;
|
void game_player_draw_hud() {
|
||||||
|
sys_i32 y = 4;
|
||||||
|
if (game_player_collectibles.n_dollars > 0) {
|
||||||
|
sys_sprite_draw_ext(
|
||||||
|
spr_game_hud,
|
||||||
|
1,
|
||||||
|
4, y,
|
||||||
|
1, 1,
|
||||||
|
false, false
|
||||||
|
);
|
||||||
|
game_player_draw_hud_number(game_player_collectibles.n_dollars, 16, y);
|
||||||
|
y += 10;
|
||||||
|
}
|
||||||
|
if (game_player_collectibles.n_cake > 0) {
|
||||||
|
sys_sprite_draw_ext(
|
||||||
|
spr_game_hud,
|
||||||
|
0,
|
||||||
|
4, y - 1,
|
||||||
|
1, 1,
|
||||||
|
false, false
|
||||||
|
);
|
||||||
|
game_player_draw_hud_number(game_player_collectibles.n_cake, 16, y);
|
||||||
|
y += 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// center on me, not on feet
|
void game_player_draw_hud_number1(sys_i32 number, sys_i32 x, sys_i32 y, uint8_t color) {
|
||||||
*y = game_player_bbox.y - 8 * PIXEL_SZ_MICROPIXEL;
|
number = sys_min_i32(sys_max_i32(number, 0), 255);
|
||||||
|
|
||||||
|
char s[2];
|
||||||
|
s[1] = 0;
|
||||||
|
|
||||||
|
if (number >= 100) {
|
||||||
|
sys_i32 top_digit = number / 100;
|
||||||
|
assert(0 <= top_digit && top_digit < 10);
|
||||||
|
s[0] = '0' + top_digit;
|
||||||
|
number = number % 100;
|
||||||
|
sys_print(s, x, y, color);
|
||||||
|
x += 8;
|
||||||
|
}
|
||||||
|
if (number >= 10) {
|
||||||
|
sys_i32 top_digit = number / 10;
|
||||||
|
assert(0 <= top_digit && top_digit < 10);
|
||||||
|
s[0] = '0' + top_digit;
|
||||||
|
number = number % 10;
|
||||||
|
sys_print(s, x, y, color);
|
||||||
|
x += 8;
|
||||||
|
}
|
||||||
|
sys_i32 top_digit = number;
|
||||||
|
assert(0 <= top_digit && top_digit < 10);
|
||||||
|
s[0] = '0' + top_digit;
|
||||||
|
sys_print(s, x, y, color);
|
||||||
|
}
|
||||||
|
void game_player_draw_hud_number(sys_i32 number, sys_i32 x_start, sys_i32 y_start) {
|
||||||
|
for (sys_i32 dy = -1; dy <= 1; dy++) {
|
||||||
|
for (sys_i32 dx = -1; dx <= 1; dx++) {
|
||||||
|
game_player_draw_hud_number1(number, x_start+dx, y_start+dy, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
game_player_draw_hud_number1(number, x_start, y_start, 7);
|
||||||
}
|
}
|
@@ -1,11 +1,24 @@
|
|||||||
#ifndef GAME_PLAYER_H
|
#ifndef GAME_PLAYER_H
|
||||||
#define GAME_PLAYER_H
|
#define GAME_PLAYER_H
|
||||||
|
|
||||||
void game_player_init();
|
typedef struct {
|
||||||
void game_player_update();
|
sys_i32 n_cake;
|
||||||
void game_player_set_camera();
|
sys_i32 n_dollars;
|
||||||
void game_player_draw();
|
} game_player_collectibles_t;
|
||||||
|
extern game_player_collectibles_t game_player_collectibles;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GAME_PLAYER_PHASE_CROC = 0,
|
||||||
|
GAME_PLAYER_PHASE_CHICKEN = 1,
|
||||||
|
} game_player_phase_t;
|
||||||
|
extern game_player_phase_t game_player_phase;
|
||||||
|
|
||||||
|
void game_player_init();
|
||||||
|
void game_player_update(bool* allow_input);
|
||||||
void game_player_get_center(sys_i32* x, sys_i32* y);
|
void game_player_get_center(sys_i32* x, sys_i32* y);
|
||||||
|
|
||||||
|
void game_player_set_camera();
|
||||||
|
void game_player_draw();
|
||||||
|
void game_player_draw_hud();
|
||||||
|
|
||||||
#endif // GAME_PLAYER_H
|
#endif // GAME_PLAYER_H
|
File diff suppressed because it is too large
Load Diff
@@ -63,9 +63,15 @@ void map_game_map_npc_set_inflict_id(sys_i32 id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void map_game_map_npc_set_face_left(bool face_left) {
|
void map_game_map_npc_set_face_left(bool face_left) {
|
||||||
|
assert(game_map_npc_in_progress && "NPC has to be in progress");
|
||||||
game_map_npc_in_progress->face_left = face_left;
|
game_map_npc_in_progress->face_left = face_left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void map_game_map_npc_set_flip(bool flip) {
|
||||||
|
assert(game_map_npc_in_progress && "NPC has to be in progress");
|
||||||
|
game_map_npc_in_progress->flip = flip;
|
||||||
|
}
|
||||||
|
|
||||||
void map_game_map_npc_set_no_cake_dialogue(const char* dialogue) {
|
void map_game_map_npc_set_no_cake_dialogue(const char* dialogue) {
|
||||||
assert(game_map_npc_in_progress && "NPC has to be in progress");
|
assert(game_map_npc_in_progress && "NPC has to be in progress");
|
||||||
game_map_npc_in_progress->no_cake_dialogue = dialogue;
|
game_map_npc_in_progress->no_cake_dialogue = dialogue;
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
import shared
|
import shared
|
||||||
|
import textwrap
|
||||||
|
|
||||||
TEMPLATE = """
|
TEMPLATE = """
|
||||||
// generated code! be nice
|
// generated code! be nice
|
||||||
@@ -130,13 +131,13 @@ def load_mapdata(fname_ldtk):
|
|||||||
|
|
||||||
def format_field_value(ty, val):
|
def format_field_value(ty, val):
|
||||||
if ty == "Bool":
|
if ty == "Bool":
|
||||||
return "true" if val else "false", "scalar", "bool"
|
return ("true" if val else "false"), "scalar", "bool"
|
||||||
elif ty == "Int":
|
elif ty == "Int":
|
||||||
return str(val), "scalar", "sys_i32"
|
return str(val), "scalar", "sys_i32"
|
||||||
elif ty == "String":
|
elif ty == "String":
|
||||||
if val is None:
|
if val is None:
|
||||||
return "NULL", "scalar", "const char*"
|
return "NULL", "scalar", "const char*"
|
||||||
return json.dumps(val), "scalar" # this is close enough to being right in C
|
return json.dumps(wrap(val)), "scalar", "const char*" # this is close enough to being right in C
|
||||||
elif ty == "Array<Int>":
|
elif ty == "Array<Int>":
|
||||||
return [format_field_value("Int", i)[0] for i in val], "array", "sys_i32"
|
return [format_field_value("Int", i)[0] for i in val], "array", "sys_i32"
|
||||||
elif ty == "Array<String>":
|
elif ty == "Array<String>":
|
||||||
@@ -145,6 +146,9 @@ def format_field_value(ty, val):
|
|||||||
assert False, f"unknown type: {ty}"
|
assert False, f"unknown type: {ty}"
|
||||||
|
|
||||||
|
|
||||||
|
def wrap(s):
|
||||||
|
return textwrap.fill(s, width=28)
|
||||||
|
|
||||||
def annot_xy(lst, w, h):
|
def annot_xy(lst, w, h):
|
||||||
assert len(lst) == w * h
|
assert len(lst) == w * h
|
||||||
for y in range(h):
|
for y in range(h):
|
||||||
|
@@ -57,7 +57,26 @@ sys_color sys_pixel_get(sys_i32 x, sys_i32 y) {
|
|||||||
return device_pixels[y][x];
|
return device_pixels[y][x];
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_print(char* str, sys_i32 x, sys_i32 y, sys_color col) {
|
void sys_measure_text(const char* str, sys_i32* w, sys_i32* h) {
|
||||||
|
sys_i32 x = 0;
|
||||||
|
sys_i32 y = 0;
|
||||||
|
|
||||||
|
sys_i32 max_x = 0;
|
||||||
|
|
||||||
|
for (sys_i32 i = 0;; i++) {
|
||||||
|
max_x = sys_max_i32(x, max_x);
|
||||||
|
uint8_t c = str[i];
|
||||||
|
if (c == 0) { break; }
|
||||||
|
if (c == '\n') { x = 0; y += 8; continue; }
|
||||||
|
if (c == '\r') { x = 0; continue; }
|
||||||
|
x += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
*w = max_x;
|
||||||
|
*h = y + 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_print(const char* str, sys_i32 x, sys_i32 y, sys_color col) {
|
||||||
x += sys_cam_dx;
|
x += sys_cam_dx;
|
||||||
y += sys_cam_dy;
|
y += sys_cam_dy;
|
||||||
|
|
||||||
@@ -148,6 +167,7 @@ void sys_oval_draw_ext(
|
|||||||
if (x0 == x1 || y0 == y1) { return; }
|
if (x0 == x1 || y0 == y1) { return; }
|
||||||
if (x0 > x1) { sys_i32 tmp = x0; x0 = x1; x1 = tmp; }
|
if (x0 > x1) { sys_i32 tmp = x0; x0 = x1; x1 = tmp; }
|
||||||
if (y0 > y1) { sys_i32 tmp = y0; y0 = y1; y1 = tmp; }
|
if (y0 > y1) { sys_i32 tmp = y0; y0 = y1; y1 = tmp; }
|
||||||
|
// TODO: Offset by 1px so that x0/y0 is always included?
|
||||||
|
|
||||||
// alois' algorithm for this implies the bounds are inclusive
|
// alois' algorithm for this implies the bounds are inclusive
|
||||||
x1 -= 1; y1 -= 1;
|
x1 -= 1; y1 -= 1;
|
||||||
@@ -216,6 +236,43 @@ void sys_line_draw(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sys_rect_draw(
|
||||||
|
sys_i32 x0, sys_i32 y0, sys_i32 x1, sys_i32 y1, sys_color c
|
||||||
|
) {
|
||||||
|
sys_rect_draw_ext(x0, y0, x1, y1, c, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_rect_fill(
|
||||||
|
sys_i32 x0, sys_i32 y0, sys_i32 x1, sys_i32 y1, sys_color c
|
||||||
|
) {
|
||||||
|
sys_rect_draw_ext(x0, y0, x1, y1, c, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_rect_draw_ext(
|
||||||
|
sys_i32 x0, sys_i32 y0, sys_i32 x1, sys_i32 y1, sys_color c, bool fill
|
||||||
|
) {
|
||||||
|
x0 += sys_cam_dx;
|
||||||
|
y0 += sys_cam_dy;
|
||||||
|
x1 += sys_cam_dx;
|
||||||
|
y1 += sys_cam_dy;
|
||||||
|
|
||||||
|
assert(sys_get_initialized());
|
||||||
|
|
||||||
|
if (x0 == x1 || y0 == y1) { return; }
|
||||||
|
|
||||||
|
if (x0 == x1 || y0 == y1) { return; }
|
||||||
|
if (x0 > x1) { sys_i32 tmp = x0; x0 = x1; x1 = tmp; }
|
||||||
|
if (y0 > y1) { sys_i32 tmp = y0; y0 = y1; y1 = tmp; }
|
||||||
|
// TODO: Offset by 1px so that x0/y0 is always included?
|
||||||
|
|
||||||
|
for (sys_i32 y = y0; y < y1; y++) {
|
||||||
|
bool whole_line = y == y0 || y == y1;
|
||||||
|
sys_scanline_internal_set(
|
||||||
|
x0, x1, y, c, whole_line || fill
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void sys_spal_set(sys_color c0, sys_screen_color rc1) {
|
void sys_spal_set(sys_color c0, sys_screen_color rc1) {
|
||||||
assert(sys_get_initialized());
|
assert(sys_get_initialized());
|
||||||
|
|
||||||
|
@@ -54,10 +54,16 @@ sys_color sys_pixel_get(
|
|||||||
|
|
||||||
// TODO: SSET/SGET
|
// TODO: SSET/SGET
|
||||||
// TODO: FGET/FSET
|
// TODO: FGET/FSET
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output the dimensions of the text (x and y)
|
||||||
|
*/
|
||||||
|
void sys_measure_text(const char* str, sys_i32* x, sys_i32* y);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print a string `str` in the color `col`
|
* Print a string `str` in the color `col`
|
||||||
*/
|
*/
|
||||||
void sys_print(char* str, sys_i32 x, sys_i32 y, sys_color col);
|
void sys_print(const char* str, sys_i32 x, sys_i32 y, sys_color col);
|
||||||
// TODO: CURSOR? COLOR?
|
// TODO: CURSOR? COLOR?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user