Skip to content

Commit

Permalink
Fix tanks clipping into blocks when pushed by other tanks
Browse files Browse the repository at this point in the history
  • Loading branch information
commandblockguy committed Jan 13, 2021
1 parent 2ddce94 commit c8cd80d
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 55 deletions.
6 changes: 6 additions & 0 deletions src/ai/ai.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@
void ai_process_move(Tank *tank) {
profiler_add(ai_move);
switch(tank->type) {
case (PLAYER):
break;
case (IMMOBILE):
case (IMMOB_MISSILE):
default:
tank->velocity_x = 0;
tank->velocity_y = 0;
break;
case (BASIC):
case (INVISIBLE):
Expand Down
5 changes: 3 additions & 2 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,15 @@ uint8_t play_mission(const serialized_tank_t *ser_tanks) {


profiler_start(physics);
//dbg_printf("0: %p\n", PhysicsBody::objects[0]);
for(auto & object : PhysicsBody::objects) {
//dbg_printf("%p\n", *it);
object->process();
}
profiler_start(pb_collision);
process_collisions();
profiler_end(pb_collision);
for(auto & object : PhysicsBody::objects) {
object->tick();
}
profiler_end(physics);

if(!game.player_alive) {
Expand Down
9 changes: 8 additions & 1 deletion src/objects/mine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@
Mine::Mine(Tank *tank) {
width = MINE_SIZE;
height = MINE_SIZE;
respect_holes = true;
tile_collisions = false;
respect_holes = false;

position_x = tank->position_x + (TANK_SIZE - MINE_SIZE) / 2;
position_y = tank->position_y + (TANK_SIZE - MINE_SIZE) / 2;

velocity_x = 0;
velocity_y = 0;

parent = tank;

Expand Down
14 changes: 14 additions & 0 deletions src/objects/physicsbody.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,17 @@ void PhysicsBody::render(uint8_t layer) {
pdraw_RectRegion(x, y, width, height);
gfx_Rectangle(x, y, width, height);
}

void PhysicsBody::tick() {
position_x += velocity_x;
position_y += velocity_y;

if(tile_collisions) {
direction_t dir = process_tile_collision();
handle_tile_collision(dir);
}
}

void PhysicsBody::handle_tile_collision(__attribute__((unused)) direction_t dir) {

}
5 changes: 5 additions & 0 deletions src/objects/physicsbody.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class PhysicsBody {
uint height;
PhysicsBody *parent;

bool tile_collisions;
// Whether or not to collide with holes
bool respect_holes;

Expand All @@ -40,12 +41,16 @@ class PhysicsBody {
bool center_distance_less_than(PhysicsBody *other, uint dis) const;
bool collides_line(line_seg_t *seg) const;

void tick();

static void sort();

virtual void kill();
virtual void process() = 0;
virtual void render(uint8_t layer);

virtual void handle_tile_collision(direction_t dir);

// Polymorphic ping-pong (aka "visitor pattern," apparently)
virtual void handle_collision(PhysicsBody *other) = 0;
virtual void collide(Tank *tank) = 0;
Expand Down
54 changes: 22 additions & 32 deletions src/objects/shell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
Shell::Shell(Tank *tank) {
width = SHELL_SIZE;
height = SHELL_SIZE;
tile_collisions = true;
respect_holes = false;

bounces = Tank::max_bounces[tank->type];
Expand Down Expand Up @@ -41,21 +42,10 @@ Shell::~Shell() {
void Shell::process() {
profiler_add(shells);

direction_t collide_dir;
//Add velocity
position_x += velocity_x;
position_y += velocity_y;

if(!left_tank_hitbox && !detect_collision(parent)) {
left_tank_hitbox = true;
}

collide_dir = process_tile_collision();

if(collide_dir) {
ricochet(collide_dir);
}

profiler_end(shells);
}

Expand All @@ -73,27 +63,6 @@ void Shell::render(uint8_t layer) {
profiler_end(render_shells);
}

bool Shell::ricochet(direction_t dir) {
if(!bounces) {
kill();
return false;
}

//shell_t is still alive
if(dir & UP || dir & DOWN) {
velocity_y *= -1;
update_direction();
bounces--;
}
if(dir & LEFT || dir & RIGHT) {
velocity_x *= -1;
update_direction();
bounces--;
}

return true;
}

void Shell::update_direction() {
angle_t angle = fast_atan2(velocity_y, velocity_x);
direction = angle_to_shell_direction(angle);
Expand All @@ -119,3 +88,24 @@ void Shell::collide(Mine *mine) {
kill();
mine->kill();
}

void Shell::handle_tile_collision(direction_t dir) {
if(!dir) return;

if(!bounces) {
kill();
return;
}

//shell_t is still alive
if(dir & UP || dir & DOWN) {
velocity_y *= -1;
update_direction();
bounces--;
}
if(dir & LEFT || dir & RIGHT) {
velocity_x *= -1;
update_direction();
bounces--;
}
}
5 changes: 2 additions & 3 deletions src/objects/shell.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ class Shell: public PhysicsBody {

void process();
void render(uint8_t layer);
//Bounce a shell off a wall
//Returns whether or not the shell is still alive
bool ricochet(direction_t dir);
void update_direction();

static uint8_t angle_to_shell_direction(angle_t angle) {
Expand All @@ -48,6 +45,8 @@ class Shell: public PhysicsBody {
void collide(Tank *tank);
void collide(Shell *shell);
void collide(Mine *mine);

void handle_tile_collision(direction_t dir);
};

#endif //TANKS_SHELL_H
27 changes: 10 additions & 17 deletions src/objects/tank.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const uint8_t Tank::velocities[] = {(uint8_t)TANK_SPEED_NORMAL,
Tank::Tank(const serialized_tank_t *ser_tank, uint8_t id) {
width = TANK_SIZE;
height = TANK_SIZE;
tile_collisions = true;
respect_holes = true;

type = ser_tank->type;
Expand Down Expand Up @@ -77,13 +78,7 @@ void Tank::process() {
ai_process_fire(this);
profiler_end(ai);

position_x += velocity_x;
position_y += velocity_y;

if(!(kb_IsDown(kb_Key1) && this == game.player))
process_tile_collision();

profiler_add(tanks);
profiler_end(tanks);
}

void Tank::render(uint8_t layer) {
Expand Down Expand Up @@ -140,8 +135,6 @@ void Tank::lay_mine() {
dbg_printf("Failed to allocate mine\n");
return;
}
mine->position_x = position_x + (TANK_SIZE - MINE_SIZE) / 2;
mine->position_y = position_y + (TANK_SIZE - MINE_SIZE) / 2;

num_mines++;
}
Expand Down Expand Up @@ -193,20 +186,20 @@ void Tank::collide(Tank *tank) {

//pick the direction with the smallest distance
if(dis_up < dis_left && dis_up < dis_right) {
position_y += dis_up / 2;
tank->position_y -= dis_up / 2;
velocity_y += dis_up / 2;
tank->velocity_y -= dis_up / 2;
}
if(dis_left < dis_up && dis_left < dis_down) {
position_x += dis_left / 2;
tank->position_x -= dis_left / 2;
velocity_x += dis_left / 2;
tank->velocity_x -= dis_left / 2;
}
if(dis_down < dis_left && dis_down < dis_right) {
position_y -= dis_down / 2;
tank->position_y += dis_down / 2;
velocity_y -= dis_down / 2;
tank->velocity_y += dis_down / 2;
}
if(dis_right < dis_up && dis_right < dis_down) {
position_x -= dis_right / 2;
tank->position_x += dis_right / 2;
velocity_x -= dis_right / 2;
tank->velocity_x += dis_right / 2;
}
}

Expand Down

0 comments on commit c8cd80d

Please sign in to comment.