kobodl/enemy.cpp
Ville Lindholm dbc223eb84
Initial commit
Import existing source tree; original VCS history is no longer available.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-28 16:35:31 +03:00

1430 lines
27 KiB
C++

/*(GPL)
------------------------------------------------------------
Kobo Deluxe - An enhanced SDL port of XKobo
------------------------------------------------------------
* Copyright (C) 1995, 1996 Akira Higuchi
* Copyright (C) 2001-2003, 2007 David Olofson
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "screen.h"
#include "manage.h"
#include "enemies.h"
#include "myship.h"
#include "random.h"
#include <math.h>
///////////////////////////////////////////////////////////////////////////////
// Fast integer atan() approximation. Input is 24:8 fixed point.
// Output is 0..64 for 0..45 deg, accurate accurate down to LSB.
// In: q = 256 * minv / maxv (0..256 <==> 0..1)
// Out: atan(q / 256) * 256 (0..64 <==> 0..45 deg)
///////////////////////////////////////////////////////////////////////////////
// atan() approximations for 0..9 deg:
// a = 83 * q / 256 - q*q / 2844 (+/- 2.1%)
// a = 82 * q / 256 - k*k / 8500 - x*x*x / 1600000 (+/- 0.6%)
///////////////////////////////////////////////////////////////////////////////
static inline int fastatan(int q)
{
int q2 = q * q;
int q3 = q2 * q;
return (82 * q >> 8) - (62 * q2 >> 19) - (10 * q3 >> 24);
}
static int speed2dir(int sx, int sy, int frames)
{
if(!sx && !sy)
return 0;
int at2;
if(sx > 0)
{
// Right
if(sy < 0)
{
// Top-right quadrant
sy = -sy;
if(sy > sx)
at2 = fastatan(sx * 256 / sy);
else
at2 = 128 - fastatan(sy * 256 / sx);
}
else
{
// Bottom-right quadrant
if(sx > sy)
at2 = 128 + fastatan(sy * 256 / sx);
else
at2 = 256 - fastatan(sx * 256 / sy);
}
}
else
{
// Left
sx = -sx;
if(sy > 0)
{
// Bottom-left quadrant
if(sy > sx)
at2 = 256 + fastatan(sx * 256 / sy);
else
at2 = 384 - fastatan(sy * 256 / sx);
}
else
{
// Top-left quadrant
sy = -sy;
if(sx > sy)
at2 = 384 + fastatan(sy * 256 / sx);
else
at2 = 512 - fastatan(sx * 256 / sy);
}
}
at2 = (at2 * frames + 256) >> 9;
return at2 > frames - 1 ? 1 : at2 + 1;
}
/*
* ===========================================================================
* (template)
* ===========================================================================
*/
inline void _enemy::move_enemy_m(int quick, int maxspeed)
{
if(diffx > 0)
{
if(h > -maxspeed)
h -= quick;
}
else if(diffx < 0)
{
if(h < maxspeed)
h += quick;
}
if(diffy > 0)
{
if(v > -maxspeed)
v -= quick;
}
else if(diffy < 0)
{
if(v < maxspeed)
v += quick;
}
}
inline void _enemy::move_enemy_template(int quick, int maxspeed)
{
if(diffx > 0)
{
if(h > -maxspeed)
h -= quick;
}
else if(diffx < 0)
{
if(h < maxspeed)
h += quick;
}
if(diffy > 0)
{
if(v > -maxspeed)
v -= quick;
}
else if(diffy < 0)
{
if(v < maxspeed)
v += quick;
}
int ndi = speed2dir(h, v, 16);
if(ndi > 0)
di = ndi;
}
inline void _enemy::move_enemy_template_2(int quick, int maxspeed)
{
h = -PIXEL2CS(diffy) / (1<<quick);
v = PIXEL2CS(diffx) / (1<<quick);
if(diffx > 0)
{
if(h > -maxspeed)
h -= quick;
}
else if(diffx < 0)
{
if(h < maxspeed)
h += quick;
}
if(diffy > 0)
{
if(v > -maxspeed)
v -= quick;
}
else if(diffy < 0)
{
if(v < maxspeed)
v += quick;
}
int ndi = speed2dir(h, v, 16);
if(ndi > 0)
di = ndi;
}
inline void _enemy::move_enemy_template_3(int quick, int maxspeed)
{
h = PIXEL2CS(diffy) / (1<<quick);
v = -PIXEL2CS(diffx) / (1<<quick);
if(diffx > 0)
{
if(h > -maxspeed)
h -= quick;
}
else if(diffx < 0)
{
if(h < maxspeed)
h += quick;
}
if(diffy > 0)
{
if(v > -maxspeed)
v -= quick;
}
else if(diffy < 0)
{
if(v < maxspeed)
v += quick;
}
int ndi = speed2dir(h, v, 16);
if(ndi > 0)
di = ndi;
}
inline void _enemy::shot_template(const enemy_kind * ekp,
int shift, int rnd, int maxspeed)
{
int vx = -diffx;
int vy = -diffy;
if(rnd)
{
vx += gamerand.get() & (rnd - 1) - (rnd >> 1);
vy += gamerand.get() & (rnd - 1) - (rnd >> 1);
}
vx = PIXEL2CS(vx) / (1<<shift);
vy = PIXEL2CS(vy) / (1<<shift);
if(maxspeed > 0)
{
if(vx > maxspeed)
vx = maxspeed;
else if(vx < -maxspeed)
vx = -maxspeed;
if(vy > maxspeed)
vy = maxspeed;
else if(vy < -maxspeed)
vy = -maxspeed;
}
enemies.make(ekp, CS2PIXEL(x + vx), CS2PIXEL(y + vy), vx,
vy);
if(enemies.is_intro)
return;
if(&ring == ekp)
sound.g_launch_ring(x, y);
else if(&beam == ekp)
sound.g_launch_beam(x, y);
else if(&bomb1 == ekp || &bomb2 == ekp)
sound.g_launch_bomb(x, y);
else
sound.g_launch(x, y);
}
void _enemy::shot_template_8_dir(const enemy_kind * ekp)
{
static int vx[] = { 0, 200, 300, 200, 0, -200, -300, -200 };
static int vy[] = { -300, -200, 0, 200, 300, 200, 0, -200 };
int i;
for(i = 0; i < 8; i++)
enemies.make(ekp, CS2PIXEL(x), CS2PIXEL(y), vx[i],
vy[i]);
if(&ring == ekp)
sound.g_m_launch_ring(x, y);
else if(&beam == ekp)
sound.g_m_launch_beam(x, y);
else if(&bomb1 == ekp || &bomb2 == ekp)
sound.g_m_launch_bomb(x, y);
else
sound.g_m_launch(x, y);
}
void _enemy::kill_default()
{
enemies.make(enemies.randexp(), CS2PIXEL(x), CS2PIXEL(y),
h >> 1, v >> 1);
sound.g_enemy_explo(x, y);
release();
}
/*
* ===========================================================================
* beam
* ===========================================================================
*/
void _enemy::make_beam()
{
di = 1 + pubrand.get(4);
health = 1;
shootable = 0;
damage = 20;
}
void _enemy::move_beam()
{
if(norm >= ((VIEWLIMIT >> 1) + 32))
release();
di += pubrand.get(1) + 1;
if(di > 16)
di = 1;
}
void _enemy::kill_beam()
{
enemies.make(&beamexpl, CS2PIXEL(x), CS2PIXEL(y));
release();
}
const enemy_kind beam = {
0,
&_enemy::make_beam,
&_enemy::move_beam,
&_enemy::kill_beam,
2,
B_BULLETS, 0,
LAYER_BULLETS
};
/*
* ===========================================================================
* rock
* ===========================================================================
*/
void _enemy::make_rock()
{
count = 500;
health = game.rock_health;
damage = game.rock_damage;
di = gamerand.get(5) + 1;
a = gamerand.get(1) ? 1 : -1;
switch(gamerand.get() % 3)
{
case 0:
bank = B_ROCK1;
break;
case 1:
bank = B_ROCK2;
break;
case 2:
bank = B_ROCK3;
break;
}
}
void _enemy::move_rock()
{
if(bank == B_ROCK3)
{
di += a;
if(di < 1)
di += 48;
else if(di > 48)
di -= 48;
}
else
di = ((di + a - 1) & 31) + 1;
}
void _enemy::kill_rock()
{
enemies.make(&rockexpl, CS2PIXEL(x), CS2PIXEL(y), h >> 1, v >> 1);
sound.g_rock_explo(x, y);
release();
}
const enemy_kind rock = {
10,
&_enemy::make_rock,
&_enemy::move_rock,
&_enemy::kill_rock,
4,
B_ROCK1, 0,
LAYER_ENEMIES
};
/*
* ===========================================================================
* ring
* ===========================================================================
*/
void _enemy::make_ring()
{
count = 500;
health = 20;
damage = 30;
di = 1;
}
void _enemy::move_ring()
{
di += 1 + pubrand.get(1);
if(di > 16)
di = 1;
}
void _enemy::kill_ring()
{
enemies.make(&ringexpl, CS2PIXEL(x), CS2PIXEL(y), h >> 1, v >> 1);
sound.g_ring_explo(x, y);
release();
}
const enemy_kind ring = {
1,
&_enemy::make_ring,
&_enemy::move_ring,
&_enemy::kill_ring,
4,
B_RING, 0,
LAYER_BULLETS
};
/*
* ===========================================================================
* bomb
* ===========================================================================
*/
void _enemy::make_bomb()
{
count = 500;
health = 20;
damage = 70;
di = 1;
}
void _enemy::move_bomb1()
{
int h1 = ABS(diffx);
int v1 = ABS(diffy);
if(((h1 < 100) && (v1 < 30)) || (h1 < 30) && (v1 < 100))
{
int vx1 = PIXEL2CS(-diffx) / (3*8);
int vy1 = PIXEL2CS(-diffy) / (3*8);
int vx2 = vx1, vx3 = vx1;
int vy2 = vy1, vy3 = vy1;
int i;
for(i = 0; i < 4; i++)
{
int tmp = vx2;
vx2 += (vy2 >> 4);
vy2 -= (tmp >> 4);
tmp = vx3;
vx3 -= (vy3 >> 4);
vy3 += (tmp >> 4);
}
enemies.make(&beam, CS2PIXEL(x), CS2PIXEL(y), vx2, vy2);
enemies.make(&beam, CS2PIXEL(x), CS2PIXEL(y), vx3, vy3);
enemies.make(&bombdeto, CS2PIXEL(x), CS2PIXEL(y), vx1, vy1);
sound.g_bomb_deto(x, y);
release();
}
if(++di > 16)
di = 1;
}
const enemy_kind bomb1 = {
5,
&_enemy::make_bomb,
&_enemy::move_bomb1,
&_enemy::kill_default,
5,
B_BOMB, 0,
LAYER_ENEMIES
};
/*
* ===========================================================================
* bomb2
* ===========================================================================
*/
void _enemy::move_bomb2()
{
int h1 = ABS(diffx);
int v1 = ABS(diffy);
if(((h1 < 100) && (v1 < 20)) || (h1 < 20) && (v1 < 100))
{
int vx1 = PIXEL2CS(-diffx) / (3*8);
int vy1 = PIXEL2CS(-diffy) / (3*8);
int vx2 = vx1, vx3 = vx1;
int vy2 = vy1, vy3 = vy1;
int i;
for(i = 0; i < 6; i++)
{
int tmp = vx2;
vx2 += (vy2 >> 4);
vy2 -= (tmp >> 4);
tmp = vx3;
vx3 -= (vy3 >> 4);
vy3 += (tmp >> 4);
}
int vx4 = vx2, vx5 = vx3;
int vy4 = vy2, vy5 = vy3;
for(i = 0; i < 6; i++)
{
int tmp = vx2;
vx2 += (vy2 >> 4);
vy2 -= (tmp >> 4);
tmp = vx3;
vx3 -= (vy3 >> 4);
vy3 += (tmp >> 4);
}
enemies.make(&beam, CS2PIXEL(x), CS2PIXEL(y), vx1, vy1);
enemies.make(&beam, CS2PIXEL(x), CS2PIXEL(y), vx2, vy2);
enemies.make(&beam, CS2PIXEL(x), CS2PIXEL(y), vx3, vy3);
enemies.make(&beam, CS2PIXEL(x), CS2PIXEL(y), vx4, vy4);
enemies.make(&beam, CS2PIXEL(x), CS2PIXEL(y), vx5, vy5);
enemies.make(&bombdeto, CS2PIXEL(x), CS2PIXEL(y), vx1, vy1);
sound.g_bomb_deto(x, y);
release();
}
if(--di < 1)
di = 16;
}
const enemy_kind bomb2 = {
20,
&_enemy::make_bomb,
&_enemy::move_bomb2,
&_enemy::kill_default,
5,
B_BOMB, 0,
LAYER_ENEMIES
};
/*
* ===========================================================================
* explosionX
* Various explosions
* ===========================================================================
*/
void _enemy::make_expl()
{
health = 1;
damage = 0;
shootable = 0;
switch(bank)
{
case B_EXPLO1:
case B_BOMBDETO:
a = 8;
break;
case B_EXPLO3:
case B_EXPLO4:
case B_EXPLO5:
case B_ROCKEXPL:
a = 12;
break;
case B_RINGEXPL:
frame = 8 * pubrand.get(1);
a = 8;
break;
case B_BULLETEXPL:
a = 6;
break;
case B_BOLTEXPL:
frame = 6 * pubrand.get(1);
di = pubrand.get(2);
a = 6;
break;
}
}
void _enemy::move_expl()
{
if(++di > a)
release();
}
const enemy_kind explosion = {
0,
&_enemy::make_expl,
&_enemy::move_expl,
&_enemy::kill_default,
-1,
B_EXPLO1, 0,
LAYER_FX
};
const enemy_kind explosion3 = {
0,
&_enemy::make_expl,
&_enemy::move_expl,
&_enemy::kill_default,
-1,
B_EXPLO3, 0,
LAYER_FX
};
const enemy_kind explosion4 = {
0,
&_enemy::make_expl,
&_enemy::move_expl,
&_enemy::kill_default,
-1,
B_EXPLO4, 0,
LAYER_FX
};
const enemy_kind explosion5 = {
0,
&_enemy::make_expl,
&_enemy::move_expl,
&_enemy::kill_default,
-1,
B_EXPLO5, 0,
LAYER_FX
};
/*
* ===========================================================================
* ringexpl
* Ring dies in a flash
* ===========================================================================
*/
const enemy_kind ringexpl = {
0,
&_enemy::make_expl,
&_enemy::move_expl,
&_enemy::kill_default,
-1,
B_RINGEXPL, 0,
LAYER_FX
};
/*
* ===========================================================================
* beamexpl
* Enemy "bullet" discharges
* ===========================================================================
*/
const enemy_kind beamexpl = {
0,
&_enemy::make_expl,
&_enemy::move_expl,
&_enemy::kill_default,
-1,
B_BULLETEXPL, 0,
LAYER_FX
};
/*
* ===========================================================================
* boltexpl
* Player bolt discharges
* ===========================================================================
*/
const enemy_kind boltexpl = {
0,
&_enemy::make_expl,
&_enemy::move_expl,
&_enemy::kill_default,
-1,
B_BOLTEXPL, 0,
LAYER_FX
};
/*
* ===========================================================================
* rockexpl
* Rock *finally* explodes
* ===========================================================================
*/
const enemy_kind rockexpl = {
0,
&_enemy::make_expl,
&_enemy::move_expl,
&_enemy::kill_default,
-1,
B_ROCKEXPL, 0,
LAYER_FX
};
/*
* ===========================================================================
* bombdeto
* Bomb detonation (not really an explosion!)
* ===========================================================================
*/
const enemy_kind bombdeto = {
0,
&_enemy::make_expl,
&_enemy::move_expl,
&_enemy::kill_default,
-1,
B_BOMBDETO, 0,
LAYER_ENEMIES
};
/*
* ===========================================================================
* cannon
* ===========================================================================
*/
void _enemy::make_cannon()
{
count = 0;
health = 20;
damage = 75;
b = enemies.eint1() - 1;
a = gamerand.get() & b;
}
void _enemy::move_cannon()
{
(count)++;
(count) &= (b);
if(count == a && norm < ((VIEWLIMIT >> 1) + 8))
{
int shift = (enemies.ek1() == &beam) ? 6 : 5;
this->shot_template(enemies.ek1(), shift, 32, 0);
}
}
void _enemy::kill_cannon()
{
enemies.make(&pipe1, CS2PIXEL(x), CS2PIXEL(y));
sound.g_base_node_explo(x, y);
release();
}
const enemy_kind cannon = {
10,
&_enemy::make_cannon,
&_enemy::move_cannon,
&_enemy::kill_cannon,
4,
-1, 0,
LAYER_BASES
};
/*
* ===========================================================================
* core
* ===========================================================================
*/
void _enemy::make_core()
{
count = 0;
health = 20;
damage = 150;
b = enemies.eint2() - 1;
a = gamerand.get() & b;
}
void _enemy::move_core()
{
(count)++;
(count) &= (b);
if(count == a && norm < ((VIEWLIMIT >> 1) + 8))
{
int shift = (enemies.ek2() == &beam) ? 6 : 5;
this->shot_template(enemies.ek2(), shift, 0, 0);
}
}
void _enemy::kill_core()
{
enemies.make(&pipe2, CS2PIXEL(x), CS2PIXEL(y), 0, 0, 3);
enemies.make(&pipe2, CS2PIXEL(x), CS2PIXEL(y), 0, 0, 7);
enemies.make(&pipe2, CS2PIXEL(x), CS2PIXEL(y), 0, 0, 1);
enemies.make(&pipe2, CS2PIXEL(x), CS2PIXEL(y), 0, 0, 5);
enemies.make(&explosion4, CS2PIXEL(x), CS2PIXEL(y));
sound.g_base_core_explo(x, y);
release();
manage.destroyed_a_core();
}
const enemy_kind core = {
200,
&_enemy::make_core,
&_enemy::move_core,
&_enemy::kill_core,
4,
-1, 0,
LAYER_BASES
};
/*
* ===========================================================================
* pipe1
* ===========================================================================
*/
void _enemy::make_pipe1()
{
health = 1;
damage = 0;
shootable = 0;
count = 4;
a = 0;
b = 0;
}
void _enemy::move_pipe1()
{
sound.g_pipe_rumble(x, y);
if((norm < ((VIEWLIMIT >> 1) + 32)) && (count == 1))
enemies.make(&explosion,
CS2PIXEL(x) + pubrand.get(4) - 8,
CS2PIXEL(y) + pubrand.get(4) - 8,
0, 0, 1);
if(++count < 4)
return;
count = 0;
int x1 = (CS2PIXEL(x) & (WORLD_SIZEX - 1)) >> 4;
int y1 = (CS2PIXEL(y) & (WORLD_SIZEY - 1)) >> 4;
int a_next = 0;
int x_next = 0;
int y_next = 0;
int m = screen.get_map(x1, y1);
int p = MAP_BITS(m);
if(IS_SPACE(p))
{
release();
return;
}
if(norm < ((VIEWLIMIT >> 1) + 32))
enemies.make(enemies.randexp(), CS2PIXEL(x), CS2PIXEL(y),
0, 0, b);
b = 1;
if((p ^ a) == U_MASK)
{
a_next = D_MASK;
y_next = -PIXEL2CS(16);
}
if((p ^ a) == R_MASK)
{
a_next = L_MASK;
x_next = PIXEL2CS(16);
}
if((p ^ a) == D_MASK)
{
a_next = U_MASK;
y_next = PIXEL2CS(16);
}
if((p ^ a) == L_MASK)
{
a_next = R_MASK;
x_next = -PIXEL2CS(16);
}
if(a_next)
{
screen.set_map(x1, y1, 0);
x += x_next;
y += y_next;
a = a_next;
return;
}
if(!(p & CORE))
screen.set_map(x1, y1, m ^ a);
release();
}
const enemy_kind pipe1 = {
0,
&_enemy::make_pipe1,
&_enemy::move_pipe1,
&_enemy::kill_default,
-1,
-1, 0,
LAYER_BASES
};
/*
* ===========================================================================
* pipe2
* ===========================================================================
*/
void _enemy::make_pipe2()
{
int x1 = (CS2PIXEL(x) & (WORLD_SIZEX - 1)) >> 4;
int y1 = (CS2PIXEL(y) & (WORLD_SIZEY - 1)) >> 4;
screen.set_map(x1, y1, 0);
health = 1;
damage = 0;
shootable = 0;
count = 4;
switch (di)
{
case 1:
a = D_MASK;
y -= PIXEL2CS(16);
break;
case 3:
a = L_MASK;
x += PIXEL2CS(16);
break;
case 5:
a = U_MASK;
y += PIXEL2CS(16);
break;
case 7:
a = R_MASK;
x -= PIXEL2CS(16);
break;
}
}
void _enemy::move_pipe2()
{
if((norm < ((VIEWLIMIT >> 1) + 32)) && (count == 1))
enemies.make(&explosion,
CS2PIXEL(x) + pubrand.get(4) - 8,
CS2PIXEL(y) + pubrand.get(4) - 8,
0, 0, 1);
if(++count < 4)
{
sound.g_pipe_rumble(x, y);
return;
}
count = 0;
int x1 = (CS2PIXEL(x) & (WORLD_SIZEX - 1)) >> 4;
int y1 = (CS2PIXEL(y) & (WORLD_SIZEY - 1)) >> 4;
int a_next = 0;
int x_next = 0;
int y_next = 0;
int p = MAP_BITS(screen.get_map(x1, y1));
if(IS_SPACE(p))
{
release();
return;
}
if((p ^ a) == 0)
{
manage.add_score(30);
release();
enemies.erase_cannon(x1, y1);
screen.set_map(x1, y1, 0);
sound.g_base_node_explo(x, y);
if(norm < ((VIEWLIMIT >> 1) + 32))
enemies.make(enemies.randexp(), CS2PIXEL(x), CS2PIXEL(y));
return;
}
if((p ^ a) == HARD)
{
release();
screen.set_map(x1, y1, 0);
sound.g_pipe_rumble(x, y);
if(norm < ((VIEWLIMIT >> 1) + 32))
enemies.make(enemies.randexp(), CS2PIXEL(x), CS2PIXEL(y),
0, 0, 1);
return;
}
if((p ^ a) == U_MASK)
{
a_next = D_MASK;
y_next = -PIXEL2CS(16);
}
if((p ^ a) == R_MASK)
{
a_next = L_MASK;
x_next = PIXEL2CS(16);
}
if((p ^ a) == D_MASK)
{
a_next = U_MASK;
y_next = PIXEL2CS(16);
}
if((p ^ a) == L_MASK)
{
a_next = R_MASK;
x_next = -PIXEL2CS(16);
}
screen.set_map(x1, y1, 0);
sound.g_pipe_rumble(x, y);
if(norm < ((VIEWLIMIT >> 1) + 32))
enemies.make(enemies.randexp(), CS2PIXEL(x), CS2PIXEL(y),
0, 0, 1);
if(a_next)
{
x += x_next;
y += y_next;
a = a_next;
return;
}
p ^= a;
if(p & U_MASK)
enemies.make(&pipe2, CS2PIXEL(x), CS2PIXEL(y), 0, 0, 1);
if(p & R_MASK)
enemies.make(&pipe2, CS2PIXEL(x), CS2PIXEL(y), 0, 0, 3);
if(p & D_MASK)
enemies.make(&pipe2, CS2PIXEL(x), CS2PIXEL(y), 0, 0, 5);
if(p & L_MASK)
enemies.make(&pipe2, CS2PIXEL(x), CS2PIXEL(y), 0, 0, 7);
manage.add_score(10);
release();
}
const enemy_kind pipe2 = {
0,
&_enemy::make_pipe2,
&_enemy::move_pipe2,
&_enemy::kill_default,
-1,
-1, 0,
LAYER_BASES
};
/*
* ===========================================================================
* enemy1
* Gray Dumb Missile
* ===========================================================================
*/
void _enemy::make_enemy1()
{
di = 1;
health = 20;
}
void _enemy::move_enemy1()
{
this->move_enemy_template(2, 256);
}
const enemy_kind enemy1 = {
2,
&_enemy::make_enemy1,
&_enemy::move_enemy1,
&_enemy::kill_default,
6,
B_MISSILE1, 0,
LAYER_ENEMIES
};
/*
* ===========================================================================
* enemy2
* Teal Firing Fighter
* ===========================================================================
*/
void _enemy::make_enemy2()
{
di = 1;
health = 20;
count = gamerand.get() & 63;
}
void _enemy::move_enemy2()
{
this->move_enemy_template(4, 192);
if(--(count) <= 0)
{
if(norm < ((VIEWLIMIT >> 1) + 8))
{
this->shot_template(&beam, 5, 0, 0);
}
count = 32;
}
}
const enemy_kind enemy2 = {
10,
&_enemy::make_enemy2,
&_enemy::move_enemy2,
&_enemy::kill_default,
6,
B_FIGHTER, 0,
LAYER_ENEMIES
};
/*
* ===========================================================================
* enemy3
* Maroon Homing Missile
* ===========================================================================
*/
void _enemy::make_enemy3()
{
di = 1;
health = 20;
}
void _enemy::move_enemy3()
{
this->move_enemy_template(32, 96);
}
const enemy_kind enemy3 = {
1,
&_enemy::make_enemy3,
&_enemy::move_enemy3,
&_enemy::kill_default,
6,
B_MISSILE2, 0,
LAYER_ENEMIES
};
/*
* ===========================================================================
* enemy4
* Blue Homing Missile
* ===========================================================================
*/
void _enemy::make_enemy4()
{
di = 1;
health = 20;
}
void _enemy::move_enemy4()
{
this->move_enemy_template(4, 96);
}
const enemy_kind enemy4 = {
1,
&_enemy::make_enemy4,
&_enemy::move_enemy4,
&_enemy::kill_default,
6,
B_MISSILE3, 0,
LAYER_ENEMIES
};
/*
* ===========================================================================
* enemy5
* Green Boomerang Fighter
* ===========================================================================
*/
void _enemy::make_enemy()
{
count = gamerand.get() & 127;
di = 1;
health = 20;
a = 0;
}
void _enemy::move_enemy5()
{
if(a == 0)
{
if(norm > ((VIEWLIMIT >> 1) - 32))
this->move_enemy_template(6, 192);
else
a = 1;
}
else
{
if(norm < VIEWLIMIT)
this->move_enemy_template_2(4, 192);
else
a = 0;
}
if(enemies.is_intro)
{
if(gamerand.get(7) > 110)
hit(1);
}
else if((--count) <= 0)
{
count = 8;
if(norm > ((VIEWLIMIT >> 1) - 32))
this->shot_template(&beam, 6, 0, 0);
}
}
const enemy_kind enemy5 = {
5,
&_enemy::make_enemy,
&_enemy::move_enemy5,
&_enemy::kill_default,
6,
B_BMR_GREEN, 0,
LAYER_ENEMIES
};
/*
* ===========================================================================
* enemy6
* Purple Boomerang Fighter
* ===========================================================================
*/
void _enemy::move_enemy6()
{
if(a == 0)
{
if(norm > ((VIEWLIMIT >> 1) - 0))
this->move_enemy_template(6, 192);
else
a = 1;
}
else
{
if(norm < VIEWLIMIT)
this->move_enemy_template_2(5, 192);
else
a = 0;
}
if((--count) <= 0)
{
count = 128;
if(norm > ((VIEWLIMIT >> 1) - 32))
this->shot_template(&beam, 6, 0, 0);
}
}
const enemy_kind enemy6 = {
2,
&_enemy::make_enemy,
&_enemy::move_enemy6,
&_enemy::kill_default,
6,
B_BMR_PURPLE, 0,
LAYER_ENEMIES
};
/*
* ===========================================================================
* enemy7
* Pink Boomerang Fighter
* ===========================================================================
*/
void _enemy::move_enemy7()
{
if(a == 0)
{
if(norm > ((VIEWLIMIT >> 1) - 32))
this->move_enemy_template(6, 192);
else
a = 1;
}
else
{
if(norm < VIEWLIMIT)
this->move_enemy_template_3(4, 192);
else
a = 0;
}
if(enemies.is_intro)
{
if(gamerand.get(7) > 110)
hit(1);
}
else if((--count) <= 0)
{
count = 8;
if(norm > ((VIEWLIMIT >> 1) - 32))
this->shot_template(&beam, 6, 0, 0);
}
}
const enemy_kind enemy7 = {
5,
&_enemy::make_enemy,
&_enemy::move_enemy7,
&_enemy::kill_default,
6,
B_BMR_PINK, 0,
LAYER_ENEMIES
};
/*
* ===========================================================================
* enemy_m1
* ===========================================================================
*/
void _enemy::make_enemy_m1()
{
di = 1;
health = 20 * 26;
count = gamerand.get() & 15;
}
void _enemy::move_enemy_m1()
{
this->move_enemy_m(3, 128);
if(++di > 16)
di = 1;
if((count--) <= 0)
{
count = 4;
if(norm < ((VIEWLIMIT >> 1) - 16))
{
this->shot_template(&enemy1, 4, 0, 0);
}
}
if(health < 200)
{
this->shot_template_8_dir(&enemy2);
release();
}
}
const enemy_kind enemy_m1 = {
50,
&_enemy::make_enemy_m1,
&_enemy::move_enemy_m1,
&_enemy::kill_default,
12,
B_BIGSHIP, 0,
LAYER_ENEMIES
};
/*
* ===========================================================================
* enemy_m2
* ===========================================================================
*/
void _enemy::make_enemy_m2()
{
di = 1;
health = 20 * 26;
count = gamerand.get() & 15;
}
void _enemy::move_enemy_m2()
{
this->move_enemy_m(3, 128);
if(++di > 16)
di = 1;
if((count--) <= 0)
{
count = 8;
if(norm < ((VIEWLIMIT >> 1) + 8))
{
this->shot_template(&enemy2, 4, 128, 192);
}
}
if(health < 200)
{
this->shot_template_8_dir(&bomb2);
release();
}
}
const enemy_kind enemy_m2 = {
50,
&_enemy::make_enemy_m2,
&_enemy::move_enemy_m2,
&_enemy::kill_default,
12,
B_BIGSHIP, 0,
LAYER_ENEMIES
};
/*
* ===========================================================================
* enemy_m3
* ===========================================================================
*/
void _enemy::make_enemy_m3()
{
di = 1;
health = 20 * 26;
count = gamerand.get() & 15;
}
void _enemy::move_enemy_m3()
{
this->move_enemy_m(3, 128);
if(--di < 1)
di = 16;
if((count--) <= 0)
{
count = 64;
if(norm < ((VIEWLIMIT >> 1) + 8))
{
this->shot_template_8_dir(&bomb2);
}
}
if(health < 200)
{
this->shot_template_8_dir(&rock);
release();
}
}
const enemy_kind enemy_m3 = {
50,
&_enemy::make_enemy_m3,
&_enemy::move_enemy_m3,
&_enemy::kill_default,
12,
B_BIGSHIP, 0,
LAYER_ENEMIES
};
/*
* ===========================================================================
* enemy_m4
* ===========================================================================
*/
void _enemy::make_enemy_m4()
{
di = 1;
health = 20 * 26;
count = gamerand.get() & 15;
}
void _enemy::move_enemy_m4()
{
this->move_enemy_m(2, 96);
if(--di < 1)
di = 16;
static const enemy_kind *shot[8] = {
&enemy1, &enemy2, &bomb2, &ring, &enemy1, &enemy2, &ring,
&enemy1
};
if((count--) <= 0)
{
count = 64;
if(norm < ((VIEWLIMIT >> 1) + 8))
{
this->shot_template_8_dir(shot[gamerand.get() & 7]);
}
}
if(health < 200)
{
this->shot_template_8_dir(&rock);
release();
}
}
const enemy_kind enemy_m4 = {
100,
&_enemy::make_enemy_m4,
&_enemy::move_enemy_m4,
&_enemy::kill_default,
12,
B_BIGSHIP, 0,
LAYER_ENEMIES
};
/*---------------------------------------------------------------------------*/
/* void _enemy::make_xxxx(){}
* void _enemy::move_xxxx(){}
* void _enemy::die_xxxx(){}
* enemy_kind xxxxx = {
* score,
* make_xxxx, move_xxxx, die_xxx,
* hitsize,
* bank, frame, tilesize
* };
*/