#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
);
}
}
}
static i16
abs(i16 v
)
{
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