From c664b930f219f2c8c8f0286756a9df7dc2f823f9 Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Sat, 21 Aug 2021 20:44:32 +0200 Subject: [PATCH] level messages and level sequence (1-10) --- CMakeLists.txt | 3 ++ assets-cg/font.png | Bin 925 -> 939 bytes assets-cg/level/level1.txt | 2 +- assets-cg/level/level3.txt | 2 +- assets-cg/level/level5.txt | 2 +- assets-cg/level/level6.txt | 3 +- converters.py | 16 ++++++++-- src/duet.h | 15 ++++----- src/main.c | 64 ++++++++++++++++++++++++++++++------- src/physics.c | 2 +- src/render.c | 10 ++++-- src/text.c | 43 +++++-------------------- 12 files changed, 95 insertions(+), 67 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fabbd85..9fb3431 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/assets-cg/font.png b/assets-cg/font.png index ba626fbf1ae4b24aaef2bb82d8d865ae4439b64e..a20b3af626f861343689cf459db908799a74d612 100644 GIT binary patch delta 815 zcmV+~1JL}P2df8=LI)BY6QF^oV3A2EWhF^OK~#9!?VVB5s~`-8(P4{SWf$4|;QWji zAw)pI_?@R#DPnRG0s*@Gem@7mAJ%ui_OdMK9zp;Jk#P@nln?^wtOZ*EcnAO?0E7S# z0<^;KzkI*n@cHxkAe|Quuo-0lx(t!f9Ff`$e;`_9t3l(&$gu7DSV^=ayI3Gu<~CT} zAnHd6F)7gfm12QMUG*)A*|fUMJ|&RE`y+_4m*o$ z9iofEywl86QpMM#%Wz4vF8WeTpBTad0@qnWSLs)CZUYZtpAd4M!qu+wo6|{HCA9A= zDZ|kgF+}H}lEpRejUhBF!G#!~hX8aLe*i)N2mv4jfDl~*)UE@|mf9xY-KA{XkXJD1 zA+~9;y3y0js)7*n!thxA+-6_RUR$|9v4-~gm2D6VUDL>cJ>$Od$#(8Bwwzf3-&v z6d!SCchJJN;t%!PBqK>yZuT8`K7^&ncfy8oKE$vWnUfQ1Uo#E2j&FP1{hgGN@QC)4 zYl@G!pA*9$9cju}R3W@cxFtke<9iv$NCzCOrsO?kg_k4uV_BYx0D6!3_F#{Ygyl# z)Uy*e1T*lNrOQwzuLXtab$Nx>&mNX5SMpA3-Wo$}vL3YpHqx}9b=gtbX3ToORyJJ3 zi7wh|`Qso{git20t0gsdDPm;$IX5uF|HRA^R4S9#)soUAuZ1?8O2J?1G0Y7Izm*G0 t84FmI025On-(>)O_+r&TG7AL$!$0kwdT-HKS0(@e002ovPDHLkV1gg1c(?!n delta 808 zcmV+@1K0ek2b~9yLI)5!6^Xc2ACXBYR~Jb{K~#9!?VVAQtRM_U(PIBw?)PDhki0U*SMdtji15I|=w*b2Zy00;pf1b`3# zLI81s%`5}pk>DSH5CT9503ZZ_5CB4edc@ivG#-rHw|$-~Np^%53uMbY2CoN1<0v6! z1$ul^Ebs~p;mu|_MPYUrGPZhcmn$TFD%N9e2)s3h-~_;}vbCAhYB2GEw!8cRm3xRG za4OF`iCT%pS_4JUzBv)~R7mP=kDp!6+}{3C>%(l-3yzzApoT=3aa8BB%070zSYXbO zB2mEm7EZ82Fv~gwfDiye00;pf#3yi`zxi9Ki+2d?YUU!B$qJWA&|9aS#k~&6Lt))% z<|V1(XEJ1jtXUU*DW*>h;Q>3>*+OUZt5a-JesclpifB)k$j_LY?5Xp0!4 zb5P0Vn(xMc5E_=?LY%Kd0EP?zApnE`5CTAmE&*!SiDgS|lb`NV_HD=~IP?(PvY2i5 zG_$H8#Jq4kSFbzlt2t{c7bw=yUca&rf}v|VIdEh=c0SwB}je@jNGn zH=SrI8mbV!WPc?@e1feXe_rH-&Af_De8f*&Y3kGIZ+3REFa;ZY1(hA=DX<|gALIfU zG5~~s052s3yY(Rin353fiDP{YLZ&f@c}Urp$WJtX%deCL{7gHQ$!l5Pn$&X;4+Jyu znPtdOCa(pB>2-OB)@v`zl`HusH6M*3Hd&9_0h?%A(7NoXd^2W!UMm}J;zSp1wfy5C zSA(j>2iK2)XPZ*}I5gJ0u@Qsx3)CBVWI mxE?ZqK78@&AXx-Oe$&5|_0000 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) diff --git a/src/duet.h b/src/duet.h index 37d3db9..180eafa 100644 --- a/src/duet.h +++ b/src/duet.h @@ -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; diff --git a/src/main.c b/src/main.c index 535a61c..e1fcf00 100644 --- a/src/main.c +++ b/src/main.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -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++) diff --git a/src/physics.c b/src/physics.c index 02231b0..40c1ec2 100644 --- a/src/physics.c +++ b/src/physics.c @@ -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; diff --git a/src/render.c b/src/render.c index 6bcb606..224ce52 100644 --- a/src/render.c +++ b/src/render.c @@ -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++) { diff --git a/src/text.c b/src/text.c index df5f911..f9c3483 100644 --- a/src/text.c +++ b/src/text.c @@ -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 */