The bat can inflict chicken TF

This commit is contained in:
Pyrex 2024-02-29 14:31:44 -08:00
parent 0a3a8cb8ab
commit 6c25396d4b
13 changed files with 308 additions and 58 deletions

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 601 B

After

Width:  |  Height:  |  Size: 603 B

View File

@ -34,6 +34,7 @@ void game_update() {
game_collectibles_update();
game_dialogue_update(&allow_input);
game_inflict_update(&allow_input);
game_npcs_update(&allow_input);
game_player_update(&allow_input);
}
@ -50,6 +51,7 @@ void game_draw() {
sys_camera_reset();
game_dialogue_draw();
game_player_draw_hud();
game_inflict_draw();
game_dialogue_draw();
}

View File

@ -4,6 +4,7 @@
#include "game_collectible.h"
#include "game_collision.h"
#include "game_dialogue.h"
#include "game_inflict.h"
#include "game_math.h"
#include "game_npc.h"
#include "game_palette.h"

View File

@ -1,6 +1,7 @@
#include <assert.h>
#include <stdbool.h>
#include "device/device.h"
#include "sys/sys.h"
#include "game.h"
#define GAME_DIALOGUE_MAX_N_CHARS 256
@ -14,6 +15,7 @@ typedef enum {
struct {
bool visible;
bool modal;
const char* dialogue;
sys_i32 w;
@ -27,8 +29,9 @@ struct {
uint8_t game_dialogue_frame;
void game_dialogue_display(const char* text) {
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);
@ -88,14 +91,21 @@ void game_dialogue_update(bool* allow_input) {
}
}
}
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;
sys_i32 cx = DEVICE_W / 2;
sys_i32 cy = DEVICE_H - game_dialogue_screen.h / 2 - 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) {
@ -114,12 +124,15 @@ void game_dialogue_draw() {
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,
1
game_dialogue_screen.modal ? 0 : 1
);
if (game_dialogue_screen.state == GAME_DIALOGUE_SCREEN_STATE_BOB_OUT) {
@ -129,6 +142,13 @@ void game_dialogue_draw() {
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);

View File

@ -3,7 +3,8 @@
#include <stdbool.h>
void game_dialogue_display(const char* text);
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();

119
game/game_inflict.c Normal file
View 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
View 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

View File

@ -112,9 +112,13 @@ void game_npc_trigger_dialogue(sys_i32 npc_id) {
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);
game_dialogue_display(dialogue, false);
}
void game_npcs_draw() {

View File

@ -27,6 +27,8 @@ game_player_collectibles_t game_player_collectibles = {
.n_dollars=0
};
game_player_phase_t game_player_phase = GAME_PLAYER_PHASE_CROC;
typedef enum {
GAME_PLAYER_ANIM_STANDING,
GAME_PLAYER_ANIM_WALKING,
@ -45,6 +47,25 @@ void game_player_init() {
}
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_player_bbox,
game_player_dx,
@ -65,13 +86,13 @@ void game_player_update(bool* allow_input) {
// round up
0x7f * sys_sgn_i32(game_player_dx)
) / 0x80;
if (sys_abs_i32(game_player_dx) > 0x140) {
game_player_dx = sys_sgn_i32(game_player_dx) * 0x140;
if (sys_abs_i32(game_player_dx) > dx_max) {
game_player_dx = sys_sgn_i32(game_player_dx) * dx_max;
}
int wanted_dx = game_player_dx;
if (*allow_input && sys_btn(DEVICE_BUTTON_L)) { wanted_dx -= 0x50; }
if (*allow_input && sys_btn(DEVICE_BUTTON_R)) { wanted_dx += 0x50; }
if (*allow_input && sys_btn(DEVICE_BUTTON_L)) { wanted_dx -= ddx; }
if (*allow_input && sys_btn(DEVICE_BUTTON_R)) { wanted_dx += ddx; }
// allow this if grounded or if it's not a change of direction
if (
@ -159,17 +180,24 @@ void game_player_set_camera() {
}
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) {
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;
case GAME_PLAYER_ANIM_FLOATING:
game_player_image = 6;
game_player_image = base + 6;
break;
default:
case GAME_PLAYER_ANIM_STANDING:
game_player_image = 0;
game_player_image = base + 0;
break;
}

View File

@ -7,6 +7,12 @@ typedef struct {
} 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);

View File

@ -3909,22 +3909,6 @@
"overrideTilesetUid": null,
"gridTiles": [],
"entityInstances": [
{
"__identifier": "player_spawn",
"__grid": [15,7],
"__pivot": [0,0],
"__tags": [],
"__tile": { "tilesetUid": 119, "x": 0, "y": 0, "w": 16, "h": 16 },
"__smartColor": "#BE4A2F",
"iid": "86fd73b0-b0a0-11ee-9688-65c9ba3d6485",
"width": 16,
"height": 16,
"defUid": 108,
"px": [120,56],
"fieldInstances": [],
"__worldX": 376,
"__worldY": 488
},
{
"__identifier": "npc",
"__grid": [26,12],
@ -6081,6 +6065,38 @@
],
"__worldX": 944,
"__worldY": 160
},
{
"__identifier": "player_spawn",
"__grid": [16,11],
"__pivot": [0,0],
"__tags": [],
"__tile": { "tilesetUid": 119, "x": 0, "y": 0, "w": 16, "h": 16 },
"__smartColor": "#BE4A2F",
"iid": "86fd73b0-b0a0-11ee-9688-65c9ba3d6485",
"width": 16,
"height": 16,
"defUid": 108,
"px": [128,88],
"fieldInstances": [],
"__worldX": 896,
"__worldY": 232
},
{
"__identifier": "collectible_cake",
"__grid": [12,6],
"__pivot": [0,0],
"__tags": [],
"__tile": { "tilesetUid": 118, "x": 0, "y": 0, "w": 32, "h": 32 },
"__smartColor": "#D77643",
"iid": "63fa9dd0-b0a0-11ee-9688-1128c6b1c0cf",
"width": 32,
"height": 32,
"defUid": 117,
"px": [96,48],
"fieldInstances": [],
"__worldX": 864,
"__worldY": 192
}
]
},
@ -6112,9 +6128,9 @@
0,0,0,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,
3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,
3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,
3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,0,0,0,0,0,0,0,0,3,
3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,0,0,3,3,3,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,
@ -6196,22 +6212,14 @@
{ "px": [232,64], "src": [8,88], "f": 0, "t": 67, "d": [80,285], "a": 1 },
{ "px": [240,64], "src": [8,88], "f": 0, "t": 67, "d": [80,286], "a": 1 },
{ "px": [248,64], "src": [8,88], "f": 0, "t": 67, "d": [80,287], "a": 1 },
{ "px": [160,72], "src": [8,88], "f": 0, "t": 67, "d": [80,308], "a": 1 },
{ "px": [168,72], "src": [8,88], "f": 0, "t": 67, "d": [80,309], "a": 1 },
{ "px": [176,72], "src": [8,88], "f": 0, "t": 67, "d": [80,310], "a": 1 },
{ "px": [184,72], "src": [8,88], "f": 0, "t": 67, "d": [80,311], "a": 1 },
{ "px": [192,72], "src": [8,88], "f": 0, "t": 67, "d": [80,312], "a": 1 },
{ "px": [200,72], "src": [8,88], "f": 0, "t": 67, "d": [80,313], "a": 1 },
{ "px": [208,72], "src": [8,88], "f": 0, "t": 67, "d": [80,314], "a": 1 },
{ "px": [216,72], "src": [8,88], "f": 0, "t": 67, "d": [80,315], "a": 1 },
{ "px": [224,72], "src": [8,88], "f": 0, "t": 67, "d": [80,316], "a": 1 },
{ "px": [232,72], "src": [8,88], "f": 0, "t": 67, "d": [80,317], "a": 1 },
{ "px": [240,72], "src": [8,88], "f": 0, "t": 67, "d": [80,318], "a": 1 },
{ "px": [248,72], "src": [8,88], "f": 0, "t": 67, "d": [80,319], "a": 1 },
{ "px": [240,80], "src": [8,88], "f": 0, "t": 67, "d": [80,350], "a": 1 },
{ "px": [248,80], "src": [8,88], "f": 0, "t": 67, "d": [80,351], "a": 1 },
{ "px": [240,88], "src": [8,88], "f": 0, "t": 67, "d": [80,382], "a": 1 },
{ "px": [248,88], "src": [8,88], "f": 0, "t": 67, "d": [80,383], "a": 1 },
{ "px": [192,104], "src": [8,88], "f": 0, "t": 67, "d": [80,440], "a": 1 },
{ "px": [200,104], "src": [8,88], "f": 0, "t": 67, "d": [80,441], "a": 1 },
{ "px": [128,112], "src": [8,88], "f": 0, "t": 67, "d": [80,464], "a": 1 },
{ "px": [136,112], "src": [8,88], "f": 0, "t": 67, "d": [80,465], "a": 1 },
{ "px": [144,112], "src": [8,88], "f": 0, "t": 67, "d": [80,466], "a": 1 },
@ -6268,11 +6276,13 @@
{ "px": [232,136], "src": [8,88], "f": 0, "t": 67, "d": [80,573], "a": 1 },
{ "px": [240,136], "src": [8,88], "f": 0, "t": 67, "d": [80,574], "a": 1 },
{ "px": [248,136], "src": [8,88], "f": 0, "t": 67, "d": [80,575], "a": 1 },
{ "px": [232,80], "src": [0,112], "f": 0, "t": 84, "d": [79,349], "a": 1 },
{ "px": [232,72], "src": [0,112], "f": 0, "t": 84, "d": [79,317], "a": 1 },
{ "px": [160,72], "src": [8,112], "f": 0, "t": 85, "d": [78,308], "a": 1 },
{ "px": [208,120], "src": [8,104], "f": 0, "t": 79, "d": [77,506], "a": 1 },
{ "px": [200,16], "src": [0,104], "f": 0, "t": 78, "d": [76,89], "a": 1 },
{ "px": [192,32], "src": [0,104], "f": 0, "t": 78, "d": [76,152], "a": 1 },
{ "px": [168,56], "src": [0,104], "f": 0, "t": 78, "d": [76,245], "a": 1 },
{ "px": [184,104], "src": [0,104], "f": 0, "t": 78, "d": [76,439], "a": 1 },
{ "px": [120,120], "src": [0,104], "f": 0, "t": 78, "d": [76,495], "a": 1 },
{ "px": [104,136], "src": [0,104], "f": 0, "t": 78, "d": [76,557], "a": 1 },
{ "px": [200,0], "src": [0,88], "f": 0, "t": 66, "d": [75,25], "a": 1 },
@ -6282,24 +6292,27 @@
{ "px": [168,48], "src": [0,88], "f": 0, "t": 66, "d": [75,213], "a": 1 },
{ "px": [152,64], "src": [0,88], "f": 0, "t": 66, "d": [75,275], "a": 1 },
{ "px": [152,72], "src": [0,88], "f": 0, "t": 66, "d": [75,307], "a": 1 },
{ "px": [232,80], "src": [0,88], "f": 0, "t": 66, "d": [75,349], "a": 1 },
{ "px": [232,88], "src": [0,88], "f": 0, "t": 66, "d": [75,381], "a": 1 },
{ "px": [120,112], "src": [0,88], "f": 0, "t": 66, "d": [75,463], "a": 1 },
{ "px": [104,128], "src": [0,88], "f": 0, "t": 66, "d": [75,525], "a": 1 },
{ "px": [160,80], "src": [8,96], "f": 0, "t": 73, "d": [74,340], "a": 1 },
{ "px": [168,80], "src": [8,96], "f": 0, "t": 73, "d": [74,341], "a": 1 },
{ "px": [176,80], "src": [8,96], "f": 0, "t": 73, "d": [74,342], "a": 1 },
{ "px": [184,80], "src": [8,96], "f": 0, "t": 73, "d": [74,343], "a": 1 },
{ "px": [192,80], "src": [8,96], "f": 0, "t": 73, "d": [74,344], "a": 1 },
{ "px": [200,80], "src": [8,96], "f": 0, "t": 73, "d": [74,345], "a": 1 },
{ "px": [208,80], "src": [8,96], "f": 0, "t": 73, "d": [74,346], "a": 1 },
{ "px": [216,80], "src": [8,96], "f": 0, "t": 73, "d": [74,347], "a": 1 },
{ "px": [224,80], "src": [8,96], "f": 0, "t": 73, "d": [74,348], "a": 1 },
{ "px": [168,72], "src": [8,96], "f": 0, "t": 73, "d": [74,309], "a": 1 },
{ "px": [176,72], "src": [8,96], "f": 0, "t": 73, "d": [74,310], "a": 1 },
{ "px": [184,72], "src": [8,96], "f": 0, "t": 73, "d": [74,311], "a": 1 },
{ "px": [192,72], "src": [8,96], "f": 0, "t": 73, "d": [74,312], "a": 1 },
{ "px": [200,72], "src": [8,96], "f": 0, "t": 73, "d": [74,313], "a": 1 },
{ "px": [208,72], "src": [8,96], "f": 0, "t": 73, "d": [74,314], "a": 1 },
{ "px": [216,72], "src": [8,96], "f": 0, "t": 73, "d": [74,315], "a": 1 },
{ "px": [224,72], "src": [8,96], "f": 0, "t": 73, "d": [74,316], "a": 1 },
{ "px": [240,96], "src": [8,96], "f": 0, "t": 73, "d": [74,414], "a": 1 },
{ "px": [248,96], "src": [8,96], "f": 0, "t": 73, "d": [74,415], "a": 1 },
{ "px": [208,104], "src": [16,88], "f": 0, "t": 68, "d": [73,442], "a": 1 },
{ "px": [208,112], "src": [16,88], "f": 0, "t": 68, "d": [73,474], "a": 1 },
{ "px": [176,32], "src": [8,80], "f": 0, "t": 61, "d": [72,150], "a": 1 },
{ "px": [184,32], "src": [8,80], "f": 0, "t": 61, "d": [72,151], "a": 1 },
{ "px": [160,56], "src": [8,80], "f": 0, "t": 61, "d": [72,244], "a": 1 },
{ "px": [192,96], "src": [8,80], "f": 0, "t": 61, "d": [72,408], "a": 1 },
{ "px": [200,96], "src": [8,80], "f": 0, "t": 61, "d": [72,409], "a": 1 },
{ "px": [128,104], "src": [8,80], "f": 0, "t": 61, "d": [72,432], "a": 1 },
{ "px": [136,104], "src": [8,80], "f": 0, "t": 61, "d": [72,433], "a": 1 },
{ "px": [144,104], "src": [8,80], "f": 0, "t": 61, "d": [72,434], "a": 1 },
@ -6307,9 +6320,6 @@
{ "px": [160,104], "src": [8,80], "f": 0, "t": 61, "d": [72,436], "a": 1 },
{ "px": [168,104], "src": [8,80], "f": 0, "t": 61, "d": [72,437], "a": 1 },
{ "px": [176,104], "src": [8,80], "f": 0, "t": 61, "d": [72,438], "a": 1 },
{ "px": [184,104], "src": [8,80], "f": 0, "t": 61, "d": [72,439], "a": 1 },
{ "px": [192,104], "src": [8,80], "f": 0, "t": 61, "d": [72,440], "a": 1 },
{ "px": [200,104], "src": [8,80], "f": 0, "t": 61, "d": [72,441], "a": 1 },
{ "px": [112,120], "src": [8,80], "f": 0, "t": 61, "d": [72,494], "a": 1 },
{ "px": [216,120], "src": [8,80], "f": 0, "t": 61, "d": [72,507], "a": 1 },
{ "px": [224,120], "src": [8,80], "f": 0, "t": 61, "d": [72,508], "a": 1 },
@ -6319,10 +6329,12 @@
{ "px": [96,136], "src": [8,80], "f": 0, "t": 61, "d": [72,556], "a": 1 },
{ "px": [152,80], "src": [0,96], "f": 0, "t": 72, "d": [71,339], "a": 1 },
{ "px": [232,96], "src": [0,96], "f": 0, "t": 72, "d": [71,413], "a": 1 },
{ "px": [208,104], "src": [16,80], "f": 0, "t": 62, "d": [69,442], "a": 1 },
{ "px": [160,80], "src": [16,96], "f": 0, "t": 74, "d": [70,340], "a": 1 },
{ "px": [208,96], "src": [16,80], "f": 0, "t": 62, "d": [69,410], "a": 1 },
{ "px": [192,16], "src": [0,80], "f": 0, "t": 60, "d": [68,88], "a": 1 },
{ "px": [168,32], "src": [0,80], "f": 0, "t": 60, "d": [68,149], "a": 1 },
{ "px": [152,56], "src": [0,80], "f": 0, "t": 60, "d": [68,243], "a": 1 },
{ "px": [184,96], "src": [0,80], "f": 0, "t": 60, "d": [68,407], "a": 1 },
{ "px": [120,104], "src": [0,80], "f": 0, "t": 60, "d": [68,431], "a": 1 },
{ "px": [104,120], "src": [0,80], "f": 0, "t": 60, "d": [68,493], "a": 1 },
{ "px": [88,136], "src": [0,80], "f": 0, "t": 60, "d": [68,555], "a": 1 }
@ -6395,7 +6407,7 @@
"fieldInstances": [
{ "__identifier": "sprite_id", "__type": "Int", "__value": 4, "__tile": null, "defUid": 125, "realEditorValues": [{ "id": "V_Int", "params": [4] }] },
{ "__identifier": "palette_id", "__type": "Int", "__value": 4, "__tile": null, "defUid": 126, "realEditorValues": [{ "id": "V_Int", "params": [4] }] },
{ "__identifier": "inflict_id", "__type": "Int", "__value": 1, "__tile": null, "defUid": 127, "realEditorValues": [{ "id": "V_Int", "params": [1] }] },
{ "__identifier": "inflict_id", "__type": "Int", "__value": 2, "__tile": null, "defUid": 127, "realEditorValues": [{ "id": "V_Int", "params": [2] }] },
{ "__identifier": "dialogue", "__type": "Array<String>", "__value": [
"Birthday cake. Yes... delicious. Now focus... on the eyes...",
"I'm very, very good at that."

View File

@ -167,6 +167,7 @@ void sys_oval_draw_ext(
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?
// alois' algorithm for this implies the bounds are inclusive
x1 -= 1; y1 -= 1;
@ -235,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) {
assert(sys_get_initialized());