Compare commits
5 Commits
f0f3fb0282
...
c1a3ecd1f4
Author | SHA1 | Date |
---|---|---|
Lephenixnoir | c1a3ecd1f4 | |
Lephenixnoir | f2b3b9eeb9 | |
Lephenixnoir | c06904d3ae | |
Lephenixnoir | cd3b187a55 | |
Lephenixnoir | 7ae7684100 |
Binary file not shown.
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 21 KiB |
Binary file not shown.
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 8.7 KiB |
|
@ -1,19 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.8" tiledversion="1.8.6" orientation="orthogonal" renderorder="right-down" width="24" height="11" tilewidth="16" tileheight="16" infinite="0" nextlayerid="3" nextobjectid="1">
|
||||
<map version="1.9" tiledversion="1.9.2" orientation="orthogonal" renderorder="right-down" width="24" height="11" tilewidth="16" tileheight="16" infinite="0" nextlayerid="3" nextobjectid="1">
|
||||
<tileset firstgid="1" source="../tilesets/heaven.tsx"/>
|
||||
<layer id="1" name="Ground" width="24" height="11">
|
||||
<data encoding="csv">
|
||||
0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,
|
||||
0,0,0,0,2,7,8,8,7,15,15,16,15,8,8,7,2,2,2,2,2,2,2,0,
|
||||
0,0,0,0,2,4,4,4,4,6,3,3,3,6,6,6,2,2,15,15,16,15,2,0,
|
||||
0,2,2,2,2,4,4,3,6,6,6,6,6,3,6,6,2,2,4,4,4,5,2,0,
|
||||
0,2,8,8,7,4,3,4,2,2,2,2,4,3,3,5,8,8,5,5,5,4,2,0,
|
||||
0,2,6,6,6,6,6,4,7,2,2,7,6,4,5,3,5,5,5,5,5,5,2,0,
|
||||
0,2,6,6,6,3,4,4,4,8,8,6,4,6,2,2,2,2,5,5,5,5,2,0,
|
||||
0,2,6,6,6,6,3,3,3,3,3,3,3,4,8,8,2,2,5,4,4,4,2,0,
|
||||
0,2,2,2,2,2,2,2,2,2,2,2,3,4,4,4,2,2,2,2,2,2,2,0,
|
||||
0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,0,0,0,0,0,0,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0
|
||||
12,12,12,12,12,2,2,2,2,12,12,12,12,2,2,2,2,12,12,12,12,12,12,12,
|
||||
12,12,12,12,12,7,8,8,7,15,15,16,15,8,8,7,2,2,2,2,2,2,12,12,
|
||||
12,12,12,12,12,4,4,4,4,6,3,3,3,6,6,6,2,2,15,15,16,15,12,12,
|
||||
12,12,2,2,2,4,4,3,6,6,6,6,6,3,6,6,2,2,4,4,4,5,7,12,
|
||||
12,12,8,8,7,4,3,4,2,2,2,2,4,3,3,5,8,8,5,5,5,4,5,12,
|
||||
12,12,6,6,6,6,6,4,7,2,2,7,6,4,5,3,5,5,5,5,5,5,5,12,
|
||||
12,12,6,6,6,3,4,4,4,8,8,6,4,6,2,2,2,2,5,5,5,5,5,12,
|
||||
12,12,6,6,6,6,3,3,3,3,3,3,3,4,8,8,2,2,5,4,4,4,12,12,
|
||||
12,12,12,6,6,6,3,3,3,3,12,12,3,4,4,4,3,5,5,5,12,12,12,12,
|
||||
12,12,12,12,3,3,3,3,3,12,12,12,12,3,3,3,3,3,12,12,12,12,12,12,
|
||||
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="2" name="Decorations" width="24" height="11">
|
||||
|
@ -25,9 +25,9 @@
|
|||
0,0,17,17,0,0,0,0,0,0,0,0,0,0,0,9,0,0,10,0,11,9,0,0,
|
||||
0,0,9,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,20,10,0,0,
|
||||
0,0,0,20,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,9,0,0,0,9,9,9,9,0,0,0,11,0,0,0,0,9,0,10,11,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,11,10,11,11,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,0,0,0,
|
||||
0,0,9,0,0,0,0,0,9,9,0,0,0,11,0,0,0,0,9,0,10,11,0,0,
|
||||
0,0,0,0,0,0,9,9,9,0,0,0,11,10,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,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,0,0,0
|
||||
</data>
|
||||
</layer>
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 929 B After Width: | Height: | Size: 13 KiB |
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<tileset version="1.8" tiledversion="1.8.6" name="heaven" tilewidth="16" tileheight="16" tilecount="24" columns="8">
|
||||
<tileset version="1.9" tiledversion="1.9.2" name="heaven" tilewidth="16" tileheight="16" tilecount="24" columns="8">
|
||||
<image source="heaven.png" width="128" height="48"/>
|
||||
<tile id="1">
|
||||
<properties>
|
||||
<property name="plane" value="CEILING"/>
|
||||
<property name="plane" value="WALL"/>
|
||||
<property name="solid" type="bool" value="true"/>
|
||||
</properties>
|
||||
</tile>
|
||||
|
@ -52,6 +52,12 @@
|
|||
<frame tileid="18" duration="200"/>
|
||||
</animation>
|
||||
</tile>
|
||||
<tile id="11">
|
||||
<properties>
|
||||
<property name="plane" value="CEILING"/>
|
||||
<property name="solid" type="bool" value="true"/>
|
||||
</properties>
|
||||
</tile>
|
||||
<tile id="14">
|
||||
<properties>
|
||||
<property name="plane" value="WALL"/>
|
||||
|
|
|
@ -43,7 +43,7 @@ entity_t *aoe_make_attack(uint16_t type, entity_t *origin, vec2 dir)
|
|||
aoe_t *aoe = getcomp(e, aoe);
|
||||
|
||||
rect hitbox = { 0 };
|
||||
fixed_t distance = fix(0.625);
|
||||
fixed_t distance = fix(0.5);
|
||||
anim_t const *anim = NULL;
|
||||
bool rotate = true;
|
||||
fixed_t lifetime = fix(0);
|
||||
|
@ -52,6 +52,7 @@ entity_t *aoe_make_attack(uint16_t type, entity_t *origin, vec2 dir)
|
|||
if(type == AOE_HIT) {
|
||||
anim = &anims_skill_hit;
|
||||
hitbox = (rect){ -fix(4)/16, fix(3)/16, -fix(4)/16, fix(3)/16 };
|
||||
distance = fix(0.375);
|
||||
}
|
||||
else if(type == AOE_PROJECTILE || type == AOE_PROJECTILE_FAST) {
|
||||
anim = &anims_skill_projectile;
|
||||
|
|
|
@ -311,7 +311,7 @@ void enemy_ai(game_t *g, entity_t *e, fixed_t dt)
|
|||
fighter_t *f = getcomp(e, fighter);
|
||||
|
||||
if(f->enemy->id == &slime_1) {
|
||||
if(move_within_range_of_player(g, e, fix(1.0), dt)) {
|
||||
if(move_within_range_of_player(g, e, fix(0.5), dt)) {
|
||||
contact_attack(g, e);
|
||||
}
|
||||
}
|
||||
|
@ -331,7 +331,7 @@ void enemy_ai(game_t *g, entity_t *e, fixed_t dt)
|
|||
skill_use(g, e, 1, (vec2){0,0});
|
||||
}
|
||||
|
||||
if(move_within_range_of_player(g, e, fix(1.0), dt)) {
|
||||
if(move_within_range_of_player(g, e, fix(0.5), dt)) {
|
||||
contact_attack(g, e);
|
||||
ai_data->retreat_period = fix(1.5);
|
||||
}
|
||||
|
@ -339,7 +339,7 @@ void enemy_ai(game_t *g, entity_t *e, fixed_t dt)
|
|||
}
|
||||
|
||||
else if(f->enemy->id == &fire_slime_4) {
|
||||
if(move_within_range_of_player(g, e, fix(1.0), dt)) {
|
||||
if(move_within_range_of_player(g, e, fix(0.75), dt)) {
|
||||
/* Use the fire charge attack; if it fails, normal attack */
|
||||
if(use_skill_towards_player(g, e, 1)) {
|
||||
visible_set_anim(e, &anims_fire_slime_Fire, 2);
|
||||
|
|
108
src/menu.c
108
src/menu.c
|
@ -8,6 +8,7 @@
|
|||
#include <gint/usb.h>
|
||||
#include <gint/usb-ff-bulk.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct {
|
||||
/* Same mechanism as in game_t */
|
||||
|
@ -50,24 +51,50 @@ static void menu_render_game(menu_game_t *mg)
|
|||
DIMAGE_NONE);
|
||||
}
|
||||
|
||||
static void darken_vram(void)
|
||||
{
|
||||
int top_margin = 0; // 24;
|
||||
int bottom_margin = 0; // 32;
|
||||
|
||||
uint32_t *v = (void *)(gint_vram + top_margin * DWIDTH);
|
||||
int N = DWIDTH * (DHEIGHT - top_margin - bottom_margin) / 2;
|
||||
|
||||
for(int i = 0; i < N; i++)
|
||||
// v[i] = (v[i] & 0xf7def7de) >> 1;
|
||||
v[i] = (v[i] & 0xe79ce79c) >> 2;
|
||||
}
|
||||
|
||||
static void menu_update_animations(menu_game_t *mg, fixed_t dt)
|
||||
{
|
||||
for(int i = 0; i < mg->map->width * mg->map->height; i++)
|
||||
mg->map_anim[i] += fround(dt * 1000);
|
||||
}
|
||||
|
||||
static void dsprint(int x, int y, int fg1, int fg2, char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char str[256];
|
||||
va_start(args, fmt);
|
||||
vsnprintf(str, 256, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
dtext(x, y+1, fg2, str);
|
||||
dtext(x, y, fg1, str);
|
||||
}
|
||||
|
||||
int menu_level_select(int start)
|
||||
{
|
||||
extern bopti_image_t img_menu_title, img_menu_arrows;
|
||||
extern bopti_image_t img_menu_title;
|
||||
|
||||
menu_game_t *options[LEVEL_COUNT];
|
||||
#define OPTION_COUNT LEVEL_COUNT
|
||||
/* Don't show the sandbox in the menu; ALPHA+EXE to enter it instead */
|
||||
#define OPTION_COUNT (LEVEL_COUNT-1)
|
||||
|
||||
for(int i = 0; i < LEVEL_COUNT; i++)
|
||||
options[i] = menu_load_game(level_all[i]);
|
||||
|
||||
int selection = (start >= 0 && start < OPTION_COUNT) ? start : 0;
|
||||
int target_x=0, x=0;
|
||||
int target_y=0, y=0;
|
||||
/* Time spent in the transition animation that moves the GUI items away
|
||||
before starting the level. */
|
||||
fixed_t transition_time = fix(0.0);
|
||||
|
@ -82,21 +109,20 @@ int menu_level_select(int start)
|
|||
sleep();
|
||||
fixed_t dt = fix(1) / FRAME_RATE;
|
||||
|
||||
if(x != target_x) {
|
||||
int dx = (target_x - x) / 6;
|
||||
if(x < target_x && dx < 6)
|
||||
dx = min(target_x-x, 6);
|
||||
if(x > target_x && dx > -6)
|
||||
dx = max(target_x-x, -6);
|
||||
x += dx;
|
||||
if(y != target_y) {
|
||||
int dy = (target_y - y) / 4;
|
||||
if(y < target_y && dy < 6)
|
||||
dy = min(target_y-y, 6);
|
||||
if(y > target_y && dy > -6)
|
||||
dy = max(target_y-y, -6);
|
||||
y += dy;
|
||||
}
|
||||
|
||||
/* GUI positioning variables, accounting for the final transition */
|
||||
fixed_t TRANSITION_LEN = fix(0.75);
|
||||
int LOGO_Y = cubic(9, 9-85, transition_time, TRANSITION_LEN);
|
||||
int ARROW1_X = cubic(16, 16-50, transition_time, TRANSITION_LEN);
|
||||
int ARROW2_X = cubic(345, 345+50, transition_time, TRANSITION_LEN);
|
||||
int NAME_Y = cubic(DHEIGHT-24, DHEIGHT+10, transition_time,
|
||||
int LOGO_Y = cubic(5, 5-80, transition_time, TRANSITION_LEN);
|
||||
int LEVELS_X = cubic(40, 40-200, transition_time, TRANSITION_LEN);
|
||||
int HISCORE_X = cubic(DWIDTH-80, DWIDTH, transition_time,
|
||||
TRANSITION_LEN);
|
||||
|
||||
extern font_t font_rogue;
|
||||
|
@ -105,27 +131,37 @@ int menu_level_select(int start)
|
|||
dclear(C_BLACK);
|
||||
|
||||
for(int i = 0; i < OPTION_COUNT; i++) {
|
||||
if(-x <= (i-1)*DWIDTH)
|
||||
if(-y <= (i-1)*DHEIGHT)
|
||||
continue;
|
||||
if(-x >= (i+1)*DWIDTH)
|
||||
if(-y >= (i+1)*DHEIGHT)
|
||||
continue;
|
||||
|
||||
int local_offset = x + i*DWIDTH;
|
||||
fixed_t map_center = fix(options[i]->map->width) / 2;
|
||||
options[i]->camera.x = map_center - fix(local_offset) / TILE_WIDTH;
|
||||
int local_offset = y + i*DHEIGHT;
|
||||
fixed_t map_center = fix(options[i]->map->height) / 2;
|
||||
options[i]->camera.y =
|
||||
map_center - fix(local_offset + 2) / TILE_HEIGHT;
|
||||
menu_render_game(options[i]);
|
||||
|
||||
dprint_opt(DWIDTH/2 + local_offset, NAME_Y, C_WHITE, C_NONE,
|
||||
DTEXT_CENTER, DTEXT_MIDDLE, "%s", options[i]->level->name);
|
||||
}
|
||||
if(transition_time == 0)
|
||||
darken_vram();
|
||||
|
||||
dimage(148, LOGO_Y, &img_menu_title);
|
||||
if(selection > 0)
|
||||
dsubimage(ARROW1_X, 93, &img_menu_arrows, 0, 0, 35, 42,
|
||||
DIMAGE_NONE);
|
||||
if(selection < OPTION_COUNT - 1)
|
||||
dsubimage(ARROW2_X, 93, &img_menu_arrows, 35, 0, 35, 42,
|
||||
DIMAGE_NONE);
|
||||
render_small_text(LEVELS_X, 80, C_WHITE, "PLAY", -1);
|
||||
render_small_text(HISCORE_X, 80, C_WHITE, "HIGH SCORE", -1);
|
||||
for(int i = 0; i < OPTION_COUNT; i++) {
|
||||
dsprint(LEVELS_X, 95+16*i,
|
||||
(i == selection) ? C_WHITE : C_RGB(20, 20, 20), C_BLACK,
|
||||
"%s%s",
|
||||
(i == selection) ? "> " : "", options[i]->level->name);
|
||||
// TODO: Wire high score to main menu
|
||||
dsprint(HISCORE_X, 95+16*i,
|
||||
(i == selection) ? C_WHITE : C_RGB(20, 20, 20), C_BLACK,
|
||||
"%03d", 0);
|
||||
}
|
||||
render_small_text(LEVELS_X, 180, C_WHITE, "OTHER", -1);
|
||||
dsprint(LEVELS_X, 195,
|
||||
(selection == OPTION_COUNT) ? C_WHITE : C_RGB(20, 20, 20), C_BLACK,
|
||||
(selection == OPTION_COUNT) ? "> Credits" : "Credits");
|
||||
|
||||
dfont(old_font);
|
||||
dupdate();
|
||||
|
@ -144,18 +180,20 @@ int menu_level_select(int start)
|
|||
usb_fxlink_videocapture(false);
|
||||
}
|
||||
|
||||
if(transition_time <= fix(0.0)
|
||||
&& key == KEY_LEFT && selection > 0) {
|
||||
if(key == KEY_UP && selection > 0) {
|
||||
selection--;
|
||||
target_x += DWIDTH;
|
||||
target_y += DHEIGHT;
|
||||
}
|
||||
if(transition_time <= fix(0.0)
|
||||
&& key == KEY_RIGHT && selection < OPTION_COUNT - 1) {
|
||||
if(key == KEY_DOWN && selection < OPTION_COUNT) {
|
||||
selection++;
|
||||
target_x -= DWIDTH;
|
||||
target_y -= DHEIGHT;
|
||||
}
|
||||
|
||||
if(key == KEY_EXE || key == KEY_SHIFT) {
|
||||
if(key == KEY_EXE && keydown(KEY_ALPHA)) {
|
||||
selection = LEVEL_COUNT - 1;
|
||||
break;
|
||||
}
|
||||
if((key == KEY_EXE || key == KEY_SHIFT) && transition_time == 0) {
|
||||
transition_time = dt;
|
||||
}
|
||||
else if(transition_time > fix(0.0)) {
|
||||
|
|
50
src/render.c
50
src/render.c
|
@ -448,31 +448,27 @@ static void anim_frame_render_outline(int x, int y, anim_frame_t const *frame,
|
|||
frame->x, frame->y, frame->w, frame->h, color);
|
||||
}
|
||||
|
||||
static int small_text(int x, int y, int color, char const *text, int size)
|
||||
int render_small_text(int x, int y, int color, char const *text, int size)
|
||||
{
|
||||
extern bopti_image_t img_hud_small;
|
||||
(void)color;
|
||||
|
||||
if(size < 0)
|
||||
size = strlen(text);
|
||||
|
||||
if(!strncmp(text, "SHIFT", size)) {
|
||||
dsubimage(x-1, y+3, &img_hud_small, 0, 0, 27, 8, DIMAGE_NONE);
|
||||
return 27-1;
|
||||
}
|
||||
if(!strncmp(text, "HP", size)) {
|
||||
dsubimage(x-1, y+3, &img_hud_small, 0, 8, 12, 8, DIMAGE_NONE);
|
||||
return 12-1;
|
||||
}
|
||||
if(!strncmp(text, "ATK", size)) {
|
||||
dsubimage(x-1, y+3, &img_hud_small, 0, 16, 17, 8, DIMAGE_NONE);
|
||||
return 17-1;
|
||||
}
|
||||
if(!strncmp(text, "MAG", size)) {
|
||||
dsubimage(x-1, y+3, &img_hud_small, 0, 24, 19, 8, DIMAGE_NONE);
|
||||
return 19-1;
|
||||
}
|
||||
if(!strncmp(text, "DEF", size)) {
|
||||
dsubimage(x-1, y+3, &img_hud_small, 0, 32, 18, 8, DIMAGE_NONE);
|
||||
return 18-1;
|
||||
static char const *texts[] = {
|
||||
"SHIFT", "HP", "ATK", "MAG", "DEF", "PLAY", "HIGH SCORE", "OTHER"
|
||||
};
|
||||
static int const widths[] = {
|
||||
27, 12, 17, 19, 18, 22, 51, 28
|
||||
};
|
||||
|
||||
for(size_t i = 0; i < sizeof texts / sizeof texts[0]; i++) {
|
||||
if(!strncmp(text, texts[i], size)) {
|
||||
dsubimage(x-1, y+3, &img_hud_small, 0, 8*i, widths[i], 8,
|
||||
DIMAGE_NONE);
|
||||
return widths[i] - 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -508,12 +504,12 @@ static void dtext_multi(int x0, int y, int color, char const *str)
|
|||
|
||||
while(*str) {
|
||||
if(!strncmp(str, "HP", 2)) {
|
||||
x += small_text(x, y, color, str, 2) + 1;
|
||||
x += render_small_text(x, y, color, str, 2) + 1;
|
||||
str += 2;
|
||||
}
|
||||
else if(!strncmp(str, "ATK", 3) || !strncmp(str, "MAG", 3) ||
|
||||
!strncmp(str, "DEF", 3)) {
|
||||
x += small_text(x, y, color, str, 3) + 1;
|
||||
x += render_small_text(x, y, color, str, 3) + 1;
|
||||
str += 3;
|
||||
}
|
||||
else if(*str == '\n') {
|
||||
|
@ -704,7 +700,7 @@ void render_game(game_t const *g, bool show_hitboxes)
|
|||
if(desc)
|
||||
dtext_multi(x1+7, 123, C_WHITE, desc);
|
||||
|
||||
int dx = small_text(x1+7, 156, -1, "SHIFT", -1);
|
||||
int dx = render_small_text(x1+7, 156, -1, "SHIFT", -1);
|
||||
char const *use_str = "Use";
|
||||
if(item_is_equip(selected_item)) {
|
||||
use_str = "Equip";
|
||||
|
@ -728,16 +724,16 @@ void render_game(game_t const *g, bool show_hitboxes)
|
|||
switched_equipment[selected_slot] = g->menu_cursor;
|
||||
growth_equip = player_compute_growth(g->player, switched_equipment);
|
||||
|
||||
small_text(x2+14, 100, C_WHITE, "HP", -1);
|
||||
render_small_text(x2+14, 100, C_WHITE, "HP", -1);
|
||||
print_stat_opt(x2+44, 100, growth_equip.HP, growth_base.HP,
|
||||
"%d/%d", player_f->HP, player_f->HP_max);
|
||||
small_text(x2+14, 114, C_WHITE, "ATK", -1);
|
||||
render_small_text(x2+14, 114, C_WHITE, "ATK", -1);
|
||||
print_stat(x2+44, 114, player_f->ATK, growth_equip.ATK,
|
||||
growth_base.ATK);
|
||||
small_text(x2+14, 128, C_WHITE, "MAG", -1);
|
||||
render_small_text(x2+14, 128, C_WHITE, "MAG", -1);
|
||||
print_stat(x2+44, 128, player_f->MAG, growth_equip.MAG,
|
||||
growth_base.MAG);
|
||||
small_text(x2+14, 142, C_WHITE, "DEF", -1);
|
||||
render_small_text(x2+14, 142, C_WHITE, "DEF", -1);
|
||||
print_stat(x2+44, 142, player_f->DEF, growth_equip.DEF,
|
||||
growth_base.DEF);
|
||||
dfont(old_font);
|
||||
|
|
|
@ -71,3 +71,6 @@ void render_game(struct game const *g, bool show_hitboxes);
|
|||
/* Render pathfinding results on the grid. */
|
||||
void render_pfg_all2one(pfg_all2one_t const *paths, camera_t const *c,
|
||||
uint8_t *occupation);
|
||||
|
||||
/* Render one of some predefined short strings using an image. */
|
||||
int render_small_text(int x, int y, int color, char const *text, int size);
|
||||
|
|
Loading…
Reference in New Issue