#ifndef ENGINE_C
#define ENGINE_C
//#include <evo.h>
//#include "sprite_pool.c"
#define STATE_PLAY 0
#define STATE_TALK 1
#define STATE_GAMEOVER 2
#define STATE_WIN 3
#define STATE_MENU 4
static u8 state = STATE_MENU;
#define GHOST 16
#define FAIRY 32
#define BAT 48
#define INJAN 260
#define BOOK 276
#define KNIFES 292
#define ICE 528
#define FIARY2 784
#define FROG 800
#define ICEBALL 816
#define FIREBALL 544
#define EYE 560
#define FIARY3 1040
#define SHARP_ICE 1056
#define KNIFE_LEFT 1552
//#define DEFAULT_BULLET 0x102
//#define MARISA_BULLET 0x143
//#define CIRNO_BULLET 0x100
//#define SAKUYA_BULLET 0x140
//#define FLAN_BULLET 0x101
//#define BULLET2 0x141
#define DEFAULT_BULLET 0x510
#define MARISA_BULLET 0x51a
#define CIRNO_BULLET 0x50c
#define SAKUYA_BULLET 0x514
#define FLAN_BULLET 0x50e
#define BULLET2 0x516
#define CIRNO 512
#define FLANDRE 768
#define MARISA 1024
#define MAID 1536
#define PATCHULY 1792
#define FAIRY_MB 2048
static u8 keys[40];
static u8 is_npc_right_type(Npc *n, u8 type);
//static u16 score;
static u8 hp;
static i16 scroll_pos;
static i16 hor_scroll_pos = 0;
static u32 level_loop;
static i8 scroll_speed;
static i8 hor_scroll_speed = 0;
static i8 immortality = -1;
static u8 schedule = 0;
static u8 add_cnt = 0;
static u8 push_counter = 0;
static void (*process_level)();
static u16 bullet_sprite = DEFAULT_BULLET;
void wait_for_space()
{
while (1)
{
keyboard(keys);
if (keys[KEY_SPACE])
break;
swap_screen();
}
}
static void push_npc(i16 x, i16 y, i8 dx, i8 dy, u16 tile, u8 type, u16 hp, u16 bonus)
{
i8 npc = find_free_npc();
if (npc != -1)
{
npcs[npc].sprite.tile = tile;
if (x < 16) x = 16;
if (x > 296) x = 296;
npcs[npc].sprite.x = x;
npcs[npc].sprite.y = y;
npcs[npc].sprite.dx = dx;
npcs[npc].sprite.dy = dy;
npcs[npc].hp = hp;
npcs[npc].type = type;
npcs[npc].take_bonus = bonus;
}
}
static void push_bonus(u16 type, u16 x, u16 y, i8 dx, i8 dy)
{
i8 b = find_free_bonus();
if (b >= 0)
{
bonuses[b].x = x;
bonuses[b].y = y;
bonuses[b].tile = type;
bonuses[b].dx = dx;
bonuses[b].dy = dy;
}
}
static void push_bullet(u16 x, u16 y, i8 dx, i8 dy)
{
i8 b = find_free_bullet();
if (b != -1)
{
bullets[b].x = x;
bullets[b].y = y;
bullets[b].dx = dx;
bullets[b].dy = dy;
bullets[b].tile = bullet_sprite;
}
}
static void push_star(u16 x, u16 y)
{
push_bullet(x + 2, y + 3, 2, 3);
push_bullet(x + 3, y + 0, 3, 0);
push_bullet(x + 3, y - 2, 3, -2);
push_bullet(x + 1, y - 4, 1, -4);
push_bullet(x - 1, y - 4, -1, -4);
push_bullet(x - 4, y - 3, -4, -3);
push_bullet(x - 4, y - 1, -4, -1);
push_bullet(x - 4, y + 2, -4, 2);
push_bullet(x - 2, y + 3, -2, 3);
}
static void npc_type_shoot(u8 type, i8 dx, i8 dy)
{
static u8 npc;
for (npc = 0; npc < NPC_count; npc++)
{
if (is_npc_right_type(&npcs[npc], type))
{
push_bullet(npcs[npc].sprite.x + 16, npcs[npc].sprite.y + 16, dx, dy);
}
}
}
{
if (v < 0)
return -v;
return v;
}
static i16 sign(i16 v)
{
if (v < 0)
return -1;
return 1;
}
static i16 min(i16 x, i16 y)
{
return x < y ? x : y;
}
static i16 max(i16 x, i16 y)
{
return x > y ? x : y;
}
static void npc_aimed_shoot(u8 type)
{
i16 dx;
i16 dy;
static u8 npc;
for (npc = 0; npc < NPC_count; npc++)
{
if (is_npc_right_type(&npcs[npc], type))
{
dx = player.x - npcs[npc].sprite.x;
dy = player.y - npcs[npc].sprite.y;
dx
= sign
(dx
) * min
(abs(dx
) / 8, 5);
dy
= sign
(dy
) * min
(abs(dy
) / 8, 5);
push_bullet(npcs[npc].sprite.x + 16, npcs[npc].sprite.y + 16, dx, dy);
}
}
}
static void npc_shoot(i8 dx, u8 dy)
{
static u8 npc;
for (npc = 0; npc < NPC_count; npc++)
{
if (is_npc_active(&npcs[npc]))
{
push_bullet(npcs[npc].sprite.x + 16, npcs[npc].sprite.y + 16, dx, dy);
}
}
}
static void npc_type_star(u8 type)
{
static u8 npc;
for (npc = 0; npc < NPC_count; npc++)
{
if (is_npc_right_type(&npcs[npc], type))
{
push_star(npcs[npc].sprite.x + 16, npcs[npc].sprite.y + 16);
}
}
}
static void npc_by_type_set_speed(u8 type, i8 dx, i8 dy)
{
static u8 npc;
for (npc = 0; npc < NPC_count; npc++)
{
if (is_npc_right_type(&npcs[npc], type))
{
npcs[npc].sprite.dx = dx;
npcs[npc].sprite.dy = dy;
}
}
}
static void user_fire()
{
i8 bullet = find_free_my_bullet();
if (bullet > -1)
{
my_bullets[bullet].tile = MY_BULLET;
my_bullets[bullet].x = player.x + 8;
my_bullets[bullet].y = player.y - 8;
my_bullets[bullet].dx = 0;
my_bullets[bullet].dy = -16;
}
}
static u8 is_npc_right_type(Npc *n, u8 type)
{
return n->type == type && is_npc_active(n);
}
static u8 is_player_collide_with_bullet(MovableSprite *bullet)
{
return bullet->x < player.x + 28 &&
bullet->x + 8 > player.x + 4 &&
bullet->y < player.y + 28 &&
bullet->y + 8 > player.y + 4;
}
static u8 is_player_collide_with_enemy(MovableSprite *enemy)
{
return enemy->x + 4 < player.x + 28 &&
enemy->x + 28 > player.x &&
enemy->y + 4 < player.y + 28 &&
enemy->y + 28 > player.y;
}
static u8 is_enemy_collide_with_bullet(MovableSprite *enemy, MovableSprite *bullet)
{
return enemy->x < bullet->x + 8 &&
enemy->x + 28 > bullet->x &&
enemy->y + 4 < bullet->y + 16 &&
enemy->y + 28 > bullet->y;
}
static MovableSprite *is_player_collide_with_pups()
{
static u8 cnt;
for (cnt = 0; cnt < MAX_BONUS_COUNT; cnt++)
{
if (bonuses[cnt].y < MAX_Y_RES &&
bonuses[cnt].x < player.x + 28 &&
bonuses[cnt].x + 8 > player.x + 4 &&
bonuses[cnt].y < player.y + 28 &&
bonuses[cnt].y + 8 > player.y + 4)
{
bonuses[cnt].y = MAX_Y_RES + 1;
return &bonuses[cnt];
}
}
return 0;
}
static u8 is_player_collide()
{
#ifdef CHEAT
if (cheat_on) return 0;
#endif
for (cnt = 0; cnt < BULLETS_count; cnt++)
if (is_bullet_active(&bullets[cnt]) && is_player_collide_with_bullet(&bullets[cnt]))
{
return 1;
}
for (cnt = 0; cnt < NPC_count; cnt++)
if (is_npc_active(&npcs[cnt]) && is_player_collide_with_enemy(&npcs[cnt].sprite))
{
npcs[cnt].hp--;
return 1;
}
return 0;
}
static void enemy_collision()
{
static u8 ec, cnt;
u8 is_played = 0;
for (cnt = 0; cnt < MY_BULLETS_max; cnt++)
if (is_bullet_active(&my_bullets[cnt]))
for (ec = 0; ec < NPC_count; ec++)
if (is_npc_active(&npcs[ec]) && is_enemy_collide_with_bullet(&npcs[ec].sprite, &my_bullets[cnt]))
{
if (my_bullets[cnt].tile == MY_BULLET)
my_bullets[cnt].tile = MY_BULLET + 2;
if (!is_played)
{
sfx_play(0, -3);
is_played = 1;
}
npcs[ec].hp--;
score ++;
}
}
static Npc *find_npc_by_type(u8 type)
{
u8 i;
for (i = 0; i < NPC_count; i++)
{
if (is_npc_right_type(&npcs[i], type))
{
return &npcs[i];
}
}
return 0;
}
#endif