Speech bubbles
This commit is contained in:
parent
7e67d09508
commit
c7d9f16515
13
game/game.c
13
game/game.c
@ -29,10 +29,17 @@ void game_update() {
|
||||
sys_update();
|
||||
|
||||
game_frame += 1;
|
||||
|
||||
bool allow_input = true;
|
||||
|
||||
if (sys_btn(DEVICE_BUTTON_2)) {
|
||||
game_dialogue_display("Hello, world!\nYou rock.");
|
||||
}
|
||||
|
||||
game_collectibles_update();
|
||||
game_npcs_update();
|
||||
game_player_update();
|
||||
|
||||
game_dialogue_update(&allow_input);
|
||||
game_player_update(&allow_input);
|
||||
}
|
||||
|
||||
void game_draw() {
|
||||
@ -46,4 +53,6 @@ void game_draw() {
|
||||
game_player_draw();
|
||||
|
||||
sys_camera_reset();
|
||||
|
||||
game_dialogue_draw();
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "game_collectible.h"
|
||||
#include "game_collision.h"
|
||||
#include "game_dialogue.h"
|
||||
#include "game_math.h"
|
||||
#include "game_npc.h"
|
||||
#include "game_palette.h"
|
||||
|
138
game/game_dialogue.c
Normal file
138
game/game_dialogue.c
Normal file
@ -0,0 +1,138 @@
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include "device/device.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;
|
||||
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) {
|
||||
game_dialogue_screen.visible = true;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
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_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
|
||||
);
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
11
game/game_dialogue.h
Normal file
11
game/game_dialogue.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef GAME_DIALOGUE_H
|
||||
#define GAME_DIALOGUE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
void game_dialogue_display(const char* text);
|
||||
|
||||
void game_dialogue_update(bool* allow_input);
|
||||
void game_dialogue_draw();
|
||||
|
||||
#endif // GAME_DIALOGUE_H
|
@ -37,7 +37,7 @@ void game_player_init() {
|
||||
game_player_bbox.y = game_map_player_start_y;
|
||||
}
|
||||
|
||||
void game_player_update() {
|
||||
void game_player_update(bool* allow_input) {
|
||||
game_collision collision = game_collision_move_to_contact(
|
||||
&game_player_bbox,
|
||||
game_player_dx,
|
||||
@ -63,8 +63,8 @@ void game_player_update() {
|
||||
}
|
||||
|
||||
int wanted_dx = game_player_dx;
|
||||
if (sys_btn(DEVICE_BUTTON_L)) { wanted_dx -= 0x50; }
|
||||
if (sys_btn(DEVICE_BUTTON_R)) { wanted_dx += 0x50; }
|
||||
if (*allow_input && sys_btn(DEVICE_BUTTON_L)) { wanted_dx -= 0x50; }
|
||||
if (*allow_input && sys_btn(DEVICE_BUTTON_R)) { wanted_dx += 0x50; }
|
||||
|
||||
// allow this if grounded or if it's not a change of direction
|
||||
if (
|
||||
@ -82,7 +82,7 @@ void game_player_update() {
|
||||
}
|
||||
|
||||
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_jump_frames = 13;
|
||||
game_player_grounded = false;
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define GAME_PLAYER_H
|
||||
|
||||
void game_player_init();
|
||||
void game_player_update();
|
||||
void game_player_update(bool* allow_input);
|
||||
void game_player_set_camera();
|
||||
void game_player_draw();
|
||||
|
||||
|
@ -57,7 +57,26 @@ sys_color sys_pixel_get(sys_i32 x, sys_i32 y) {
|
||||
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;
|
||||
y += sys_cam_dy;
|
||||
|
||||
|
@ -54,10 +54,16 @@ sys_color sys_pixel_get(
|
||||
|
||||
// TODO: SSET/SGET
|
||||
// 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`
|
||||
*/
|
||||
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?
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user