📄 enemy.cpp
字号:
// Check the traps
if(traplist.size() > 0) {
list<TRAP>::iterator t;
for(t = traplist.begin(); t != traplist.end(); ++t) {
if(x == (*t).x && y == (*t).y) {
die();
return;
}
}
}
// Handle the burning, that is run around aimlessly
if(burning) {
if(!kicked) {
// Reduce the burning time
burn_time--;
if(burn_time == 0) {
die();
return;
}
// Choose a random direction
if(RAND(0,100) > 50 && offset == 0.0f) {
if(RAND(0,100) > 50)
dir++;
else
dir--;
if(dir > DIR_W)
dir = DIR_N;
else if(dir < DIR_N)
dir = DIR_W;
}
// Move one step
if(tx == x && ty == y) {
offset = 0.0f;
// Don't stop until there's a wall.
switch(dir) {
default:
case DIR_N: tx = x; ty = y - 1; break;
case DIR_E: tx = x + 1; ty = y; break;
case DIR_S: tx = x; ty = y + 1; break;
case DIR_W: tx = x - 1; ty = y; break;
}
// Check if the target is passable?
if(map_solid(tx, ty)) {
// Stop and choose a new dir
tx = x;
ty = y;
dir += RAND(-1,1);
if(dir < DIR_N)
dir = DIR_W;
else if(dir > DIR_W)
dir = DIR_N;
return;
}
}
// Move towards the target tile
if(offset < 1.0f && (tx != x || ty != y)) {
offset += speed;
// Check the collision between the player #1
if(p1.alive && !p1.jumping && !(using_special_power == 1 && which_special_power == BLUE_POWER_TELEPORT)) {
float dx = get_real_x() - p1.get_real_x();
float dy = get_real_y() - p1.get_real_y();
if(dx*dx + dy*dy <= 0.9f) {
// Collision happened!
// Turn around and run
tx = x;
ty = y;
offset = 0.0f;
dir += 2;
if(dir > DIR_W)
dir -= 4;
}
}
// Check the collision between the player #2
if(two_players && p2.alive && !p2.jumping && !(using_special_power == 2 && which_special_power == BLUE_POWER_TELEPORT)) {
float dx = get_real_x() - p2.get_real_x();
float dy = get_real_y() - p2.get_real_y();
if(dx*dx + dy*dy <= 0.9f) {
// Collision happened!
// Turn around and run
tx = x;
ty = y;
offset = 0.0f;
dir += 2;
if(dir > DIR_W)
dir -= 4;
}
}
// Check the collision between the potato men
if(potatoman.collide_with(this) && !kicked) {
// Potatoman "kicked" us
potatoman.kick(this);
}
// If we're reached the target tile, move again
if(offset >= 1.0f) {
x = tx;
y = ty;
offset = 0.0f;
}
}
}
// Check collisions with other enemies and spread the fire
bool burnt_somebody = false;
list<ENEMY>::iterator e;
for(e = enemylist.begin(); e != enemylist.end(); ++e) {
if(this != &(*e) && !(*e).burning) {
// Check the distance
float dx = get_real_x() - (*e).get_real_x();
float dy = get_real_y() - (*e).get_real_y();
if(dx*dx + dy*dy <= 0.9f) {
// Burn the other enemy
(*e).burning = true;
(*e).burn_time = enemy_burn_time;
(*e).speed += 0.06f;
burnt_somebody = true;
}
}
}
// Play the burning sound
if(burnt_somebody)
play_sound(SND_WILDFIRE, false);
if(!kicked)
return;
}
// Not burning below here
// Choose a random destination
if(path_pos == -1) {
// Choose a valid target
int dx = RAND(0, MAP_W-1);
int dy = RAND(0, MAP_H-1);
while(map_solid(dx, dy) || dx == x || dy == y) {
dx = RAND(0, MAP_W-1);
dy = RAND(0, MAP_H-1);
}
// Calculate the path
if(pf.find_path(x, y, dx, dy) == PATH_FAILED) {
// Well, tough luck. We'll just wait and try again later.
return;
}
// Now we've got a nice path for us!
path_pos = 0;
offset = 0.0f;
tx = pf.path[0].x;
ty = pf.path[0].y;
dir = get_dir(tx - x, ty - y);
look_player();
}
// Move one step
if(tx == x && ty == y && path_pos > -1) {
offset = 0.0f;
// Follow the path if we're not chasing
if(chase == 0 && !kicked) {
path_pos++;
tx = pf.path[path_pos].x;
ty = pf.path[path_pos].y;
dir = get_dir(tx - x, ty - y);
look_player();
}
else if(chase && !kicked) {
// We are chasing. Don't stop until there's a wall.
switch(dir) {
default:
case DIR_N: tx = x; ty = y - 1; break;
case DIR_E: tx = x + 1; ty = y; break;
case DIR_S: tx = x; ty = y + 1; break;
case DIR_W: tx = x - 1; ty = y; break;
}
// Check if the target is passable?
if(map_solid(tx, ty)) {
// Stop and choose a new path
tx = x;
ty = y;
path_pos = -1;
chase = 0;
speed -= 0.03f;
}
}
else if(kicked) {
// Potatoman has kicked us. "Fly" straight until we hit a wall.
switch(dir) {
default:
case DIR_N: tx = x; ty = y - 1; break;
case DIR_E: tx = x + 1; ty = y; break;
case DIR_S: tx = x; ty = y + 1; break;
case DIR_W: tx = x - 1; ty = y; break;
}
// Check for the wall
if(map_solid(tx, ty)) {
die();
return;
}
}
}
// Move towards the target tile
if(offset < 1.0f && (tx != x || ty != y) && path_pos > -1) {
offset += speed;
// Check the collision between the player #1
if(p1.alive && !p1.jumping && !(using_special_power == 1 && which_special_power == BLUE_POWER_TELEPORT)) {
float dx = get_real_x() - p1.get_real_x();
float dy = get_real_y() - p1.get_real_y();
if(dx*dx + dy*dy <= 0.9f) {
// Collision happened!
// Kill the player and die
p1.die();
die();
}
}
// Check the collision between the player #2
if(alive && two_players && p2.alive && !p2.jumping && !(using_special_power == 2 && which_special_power == BLUE_POWER_TELEPORT)) {
float dx = get_real_x() - p2.get_real_x();
float dy = get_real_y() - p2.get_real_y();
if(dx*dx + dy*dy <= 0.9f) {
// Collision happened!
// Kill the player and die
p2.die();
die();
}
}
// Check the collision between the potato men
if(potatoman.collide_with(this) && !kicked) {
// Potatoman "kicked" us
potatoman.kick(this);
}
// If we're reached the target tile, move again
if(offset >= 1.0f) {
x = tx;
y = ty;
offset = 0.0f;
// If this is the final destination, stay put and choose a new path
// on the next cycle
if(x == pf.dx && y == pf.dy && !chase && !kicked)
path_pos = -1;
}
}
}
// Kill the enemy
void ENEMY::die() {
if(dying)
return; // Hey, don't you die twice, man! ;)
dying = true;
kill_count++;
die_anim = 1.0f;
// Create a bonus
add_bonus((int)get_real_x(), (int)get_real_y(), type);
// Play the sound
static int last_sound = -1;
int sound = last_sound;
while(sound == last_sound)
sound = RAND(SND_DIE1, SND_DIE6);
play_sound(sound, false);
last_sound = sound;
}
// Get current x with offset
float ENEMY::get_real_x() {
// Calculate the offset
float offx = 0;
if(dir == DIR_E)
offx = offset;
else if(dir == DIR_W)
offx = -offset;
return (float)x + offx + 0.5f;
}
// Get current y with offset
float ENEMY::get_real_y() {
// Calculate the offset
float offy = 0;
if(dir == DIR_N)
offy = -offset;
else if(dir == DIR_S)
offy = offset;
return (float)y + offy + 0.5f;
}
// Draw the enemy
void ENEMY::draw() {
// Calculate the offset
float offx = 0, offz = 0;
switch(dir) {
default:
case DIR_N: offz = -offset; break;
case DIR_E: offx = offset; break;
case DIR_S: offz = offset; break;
case DIR_W: offx = -offset; break;
}
// Translate to the position
glPushMatrix();
glTranslatef(x + offx + 0.5f, size - 0.20f, y + offz + 0.5f);
// Draw the shadow
glDepthMask(GL_FALSE);
glColor3f(1,1,1);
BIND_TEXTURE(sprite_shadow);
float sh = -(size - 0.21f);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(1,1); glVertex3f( 0.6f, sh, -0.6f);
glTexCoord2f(0,1); glVertex3f(-0.6f, sh, -0.6f);
glTexCoord2f(1,0); glVertex3f( 0.6f, sh, 0.6f);
glTexCoord2f(0,0); glVertex3f(-0.6f, sh, 0.6f);
glEnd();
glDepthMask(GL_TRUE);
// Raise up if we're turning
if(turning)
glTranslatef(0, turning_raise * 0.85f, 0);
// Negate the camera rotation
glMultMatrixf(cam_neg_matrix);
// glRotatef(45.0f, 0,1,0);
// glRotatef(-30.0f, 1,0,0);
// Draw the sprite
if(burning)
glColor3f(.5f,.5f,.5f);
// Compute the texture coords according the animation frame and direction
BIND_TEXTURE(enemy_anim[type]);
int f = anim_frames[(int)anim];
float textx = 0.25f * f;
float texty = 0.25f * (3-dir);
if(!dying) {
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(textx + 0.25f, texty + 0.25f); glVertex3f( size, size, size);
glTexCoord2f(textx, texty + 0.25f); glVertex3f(-size, size, size);
glTexCoord2f(textx + 0.25f, texty); glVertex3f( size, -size, -size);
glTexCoord2f(textx, texty); glVertex3f(-size, -size, -size);
glEnd();
}
else {
// Draw the dying animation
float z = size - (2*size*(1-die_anim));
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(textx + 0.25f, texty + (die_anim*0.25f)); glVertex3f( size, z, z);
glTexCoord2f(textx, texty + (die_anim*0.25f)); glVertex3f(-size, z, z);
glTexCoord2f(textx + 0.25f, texty); glVertex3f( size, -size, -size);
glTexCoord2f(textx, texty); glVertex3f(-size, -size, -size);
glEnd();
}
glPopMatrix();
}
// Clear the enemy
void ENEMY::clear() {
x = y = 0;
tx = ty = 0;
offset = 0.0f;
speed = 0.05f;
dir = RAND(DIR_N, DIR_W);
nextdir = dir;
size = 0.85f;
anim = 0.0f;
type = 0;
alive = false;
dying = false;
die_anim = 1.0f;
path_pos = -1;
chase = 0;
burning = false;
burn_time = 0;
turning = 0;
turning_counter = 0;
turning_raise = 0.0f;
kicked = false;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -