level messages and level sequence (1-10)

This commit is contained in:
Lephenixnoir 2021-08-21 20:44:32 +02:00
parent dcaaec7fb1
commit c664b930f2
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
12 changed files with 95 additions and 67 deletions

View File

@ -24,6 +24,9 @@ set(ASSETS
assets-cg/level/level5.txt
assets-cg/level/level6.txt
assets-cg/level/level7.txt
assets-cg/level/level8.txt
assets-cg/level/level9.txt
assets-cg/level/level10.txt
)
fxconv_declare_converters(converters.py)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 925 B

After

Width:  |  Height:  |  Size: 939 B

View File

@ -1,4 +1,4 @@
#it's good to see you.\nStay close to me and don't touch anything.
#It's good to see you.\n\nStay close to me and\ndon't touch anything.
long_vertical middle
left

View File

@ -1,4 +1,4 @@
#This will be easy.\nJuste hold left...
#This will be easy.\nJust hold left...
left

View File

@ -1,4 +1,4 @@
#There are some things worth fightinh for
#There are some things\nworth fighting for.
right
middle

View File

@ -1,3 +1,2 @@
#denial
#This will be full of unexpected twists and turns
#This will be full of\nunexpected twists and turns.
middle rotate

View File

@ -9,8 +9,11 @@ def convert(input, output, params, target):
def convert_level(input, output, params, target):
with open(input, "r") as fp:
lines = fp.read().split("\n")
lines = [tempo.split(",") for tempo in lines if not tempo.startswith("#")]
raw = fp.read().split("\n")
lines = [tempo.split(",") for tempo in raw if not tempo.startswith("#")]
messages = [l[1:].strip() for l in raw if l.startswith("#")]
message = "\n".join(l.replace("\\n", "\n") for l in messages)
print(message)
blocks = bytes()
block_count = 0
@ -62,6 +65,14 @@ def convert_level(input, output, params, target):
position = 2
# Implicit rules
# Rotating in the middle -> long
if shape < 0 and position == 2 and action in [1, 2]:
shape = 5
# In the middle -> medium
if shape < 0 and position == 2:
shape = 3
# No properties whatsoever -> normal
if shape < 0 and action == 0:
shape = 4
@ -76,6 +87,7 @@ def convert_level(input, output, params, target):
o = fxconv.ObjectData()
o += fxconv.u32(0x3f800000) # 1.0 as a float
o += fxconv.ref(bytes(message, 'utf-8') + bytes(1), padding=4)
o += fxconv.u32(block_count)
o += fxconv.ref(blocks)

View File

@ -49,6 +49,7 @@ typedef struct {
typedef struct {
float tempo;
const char *message;
int block_count;
rectmeta_t *blocks;
} level_t;
@ -60,7 +61,7 @@ typedef struct {
#define PLAYER_X 60
#define PLAYER_R 40
#define PLAYER_SIZE 8
#define CORRIDOR_SIZE 138
#define CORRIDOR_SIZE 150
#define RECT_SPEED 50 /* px/tempo */
@ -76,7 +77,7 @@ typedef struct {
typedef struct game {
int dead;
float time;
level_t *level;
level_t const *level;
rectmeta_t const *current;
rect_t table[RECT_TABLE_SIZE];
@ -123,10 +124,6 @@ void rect_physics(rect_t *r, rectmeta_t const *meta, float time);
// Levels
//---
extern level_t level1;
extern level_t level2;
extern level_t level3;
extern level_t level4;
extern level_t level5;
extern level_t level6;
extern level_t level7;
extern level_t level1, level2, level3, level4;
extern level_t level5, level6, level7, level8;
extern level_t level9, level10;

View File

@ -3,6 +3,7 @@
#include <gint/timer.h>
#include <gint/gint.h>
#include <gint/cpu.h>
#include <gint/drivers/r61524.h>
#include <fxlibc/printf.h>
#include <string.h>
@ -33,27 +34,51 @@ level_t level0 = {
}
};
void load_level(game_t *game, level_t const *lv)
{
memset(game, 0x00, sizeof *game);
game->level = lv;
game->current = lv->blocks;
game->time = -10.0;
}
int strcount(char const *str, int c)
{
int count = 0;
for(int i = 0; str[i]; i++)
count += (str[i] == c);
return count;
}
int main(void)
{
__printf_enable_fp();
/* Azur trickz */
r61524_set(0x010, 0x0010);
level_t const *story_levels[] = {
&level1, &level2, &level3, &level4, &level5, &level6, &level7,
&level8, &level9, &level10, NULL,
};
int story_position = 0;
game_t game;
memset(&game, 0x00, sizeof game);
game.level = &level4;
game.current = game.level->blocks;
game.time = -5.0;
load_level(&game, story_levels[story_position]);
volatile int need_frame = 1;
int timer = timer_configure(TIMER_ANY, 33000, GINT_CALL_SET(&need_frame));
timer_start(timer);
while (1) {
level_t const *lv = game.level;
/* Time management */
while (need_frame == 0) sleep();
need_frame = 0;
float dt = (1.0 / 30) * game.level->tempo * 2.7;
float dt = (1.0 / 30) * lv->tempo * 2.7;
game.time += dt;
/* Input analysis */
@ -84,7 +109,7 @@ int main(void)
// Find rectangles that need to be loaded, 10 tempo in advance
rectmeta_t const *meta = game.current;
while(meta < game.level->blocks + game.level->block_count) {
while(meta < lv->blocks + lv->block_count) {
if(meta - game.current > RECT_TABLE_SIZE - game.cursor)
break; /* oops, not enough array space left */
if(meta->time - 10 > game.time)
@ -100,9 +125,14 @@ int main(void)
}
// End of level
if(game.current >= game.level->blocks + game.level->block_count
&& game.cursor == 0)
break;
if(game.current >= lv->blocks + lv->block_count && game.cursor == 0) {
if(story_levels[++story_position] == NULL)
break;
load_level(&game, story_levels[story_position]);
need_frame = 1;
continue;
}
/* Physics */
@ -122,9 +152,19 @@ int main(void)
dclear(player_collision(&game) ? C_RED : C_BLACK);
if(game.time < -2)
duet_text_opt(DWIDTH*3/4, DHEIGHT/2, C_WHITE, C_NONE, DTEXT_CENTER,
DTEXT_MIDDLE, "Change is inevitable.", -1);
if(game.time < -5 && lv->message != NULL) {
int x = DWIDTH/2 + 8 * (strcount(lv->message, '\n') + 1);
/* Split at newlines */
char const *str = lv->message;
while(*str) {
char const *end = strchrnul(str, '\n');
duet_text_opt(x, DHEIGHT/2, C_WHITE, C_NONE, DTEXT_CENTER,
DTEXT_MIDDLE, str, end - str);
x -= 16;
str = end + (*end != 0);
}
}
render_player(game.player_rota);
for(int i = 0; i < game.cursor; i++)

View File

@ -70,7 +70,7 @@ void rect_load(rect_t *r, rectmeta_t const *meta)
break;
case Shape_MediumBar:
r->w = 0.2;
r->h = 0.65;
r->h = 0.62;
break;
case Shape_NormalBar:
r->w = 0.2;

View File

@ -81,12 +81,16 @@ void dtriangle(int x1, int y1, int x2, int y2, int x3, int y3, int color)
void drectoid(rect_t const *r, int color)
{
float sin, cos;
sincosf(r->r, &sin, &cos);
float x0[4] = { r->w/2, -r->w/2, -r->w/2, r->w/2 };
float y0[4] = { -r->h/2, -r->h/2, r->h/2, r->h/2 };
if(r->r == 0) {
drect(r->x+x0[1], r->y+y0[1], r->x+x0[3], r->y+y0[3], color);
return;
}
float sin, cos;
sincosf(r->r, &sin, &cos);
int x[4], y[4];
for(int i = 0; i < 4; i++) {

View File

@ -14,27 +14,23 @@ uint32_t topti_utf8_next(uint8_t const **str_pointer);
This function assumes that at least one of [fg] and [bg] is not transparent.
@vram Target position on VRAM, adjusted to [top] and [left]
@x0 @y0 Target position on VRAM
@data Glyph data
@left Left-position of subglyph
@top Top-Position of subglyph
@width Subglyph width
@height Subglyph height
@dataw Glyph width
@datah Total font height
@fg @bg Foreground and background colors */
static void topti_glyph(uint16_t *vram, uint32_t const * data, int left,
int top, int width, int height, int dataw, int datah, int fg, int bg)
static void topti_glyph(int x0, int y0, uint32_t const * data, int width,
int height, int fg, int bg)
{
/* A C version of what is usually done in assembler */
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
int bit_number = (top + y) * dataw + (left + x);
int bit_number = y * width + x;
int bit = (data[bit_number >> 5] >> (31 - (bit_number & 31))) & 1;
/* Swithing x -> datah-y-1 and y -> x here gives vertical glyphs */
/* Swithing x->height-y-1 and y->x here gives vertical glyphs */
if((bit ? fg : bg) != C_NONE)
vram[DWIDTH*x + (datah-y-1)] = bit ? fg : bg;
dpixel(x0 + (height-y-1), y0 + x, bit ? fg : bg);
}
}
}
@ -48,14 +44,6 @@ static void topti_render(int x, int y, char const *str_char, font_t const *f,
/* Raw glyph data */
uint32_t const *data = f->data;
/* Storage height, top position within glyph */
int height = f->data_height, top = 0;
/* Vertical clipping */
if(x > 395 || y > 223 || y + height <= 0) return;
if(y + height > 224) height = 224 - y;
if(y < 0) top = -y, height += y, y = 0;
/* Character spacing waiting to be drawn, in pixels */
int space = 0;
@ -71,29 +59,14 @@ static void topti_render(int x, int y, char const *str_char, font_t const *f,
int dataw = f->prop ? f->glyph_width[glyph] : f->width;
/* Draw character spacing if background is opaque */
if(space && bg >= 0) drect(x, y, x+height-1, y+space-1, bg);
if(space && bg >= 0) drect(x, y, x+f->data_height-1, y+space-1, bg);
y += space;
if(y >= DHEIGHT) break;
int index = topti_offset(f, glyph);
/* Compute horizontal intersection between glyph and screen */
int width = dataw, left = 0;
if(y + dataw <= 0)
{
y += dataw;
space = f->char_spacing;
continue;
}
if(y < 0) left = -y, width += y;
if(y + width > DHEIGHT) width = DHEIGHT - y;
/* Render glyph */
topti_glyph(gint_vram + 396 * y + x, data + index, left, top, width,
height, dataw, f->data_height, fg, bg);
topti_glyph(x, y, data + index, dataw, f->data_height, fg, bg);
/* Switching x -> y here (and some other places, but mostly here) gives
vertical text */