Skip to content
This repository has been archived by the owner on Sep 20, 2023. It is now read-only.

Commit

Permalink
Merge pull request #695 from tresinformal/tianjian2
Browse files Browse the repository at this point in the history
Implement invulnerability after shrinking
  • Loading branch information
TheoPannetier authored May 10, 2023
2 parents b8d2de4 + 14e7522 commit 55b0d45
Show file tree
Hide file tree
Showing 7 changed files with 270 additions and 25 deletions.
220 changes: 202 additions & 18 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ void game::tick()
shrink_losing_player(*this);
}

/// PASSIVE STATE ///
increment_passive_timers();

reset_passive_timers();
/// PASSIVE STATE ///

/// Sequence is important: firstly do_actions(), then apply_inertia(), finally reset_player_action()
// Actions issued by the players are executed
do_actions();
Expand Down Expand Up @@ -176,6 +182,42 @@ void game::kill_player(const int index)
get_player(index).die();
}


/// PASSIVE STATE ///
void game::set_player_state_passive(player &p) noexcept
{
p.set_state_passive();
}

void game::remove_player_state_passive(player &p) noexcept
{
p.remove_state_passive();
}

void game::increment_passive_timers() noexcept
{
for (player &p : m_player)
{
if (is_passive(p))
{
p.increment_passive_timer();
}
}
}

void game::reset_passive_timers() noexcept
{
for (player &p : m_player)
{
if (is_passive(p) && p.get_passive_timer() >= p.get_duration_passive())
{
p.reset_passive_timer();
p.remove_state_passive();
}
}
}
/// PASSIVE STATE ///

void game::resolve_wall_collisions()
{
for(auto& player : m_player)
Expand Down Expand Up @@ -295,6 +337,8 @@ void grow_winning_player(game &g)

const int winner_index = get_winning_player_index(g, first_player_index, second_player_index);
player& winning_player = g.get_player(winner_index);
const int loser_index = get_losing_player_index(g, first_player_index, second_player_index);
player& losing_player = g.get_player(loser_index);
winning_player.grow();
}

Expand All @@ -306,6 +350,7 @@ void shrink_losing_player(game &g)
const int loser_index = get_losing_player_index(g, first_player_index, second_player_index);
player& losing_player = g.get_player(loser_index);
losing_player.shrink();
g.set_player_state_passive(losing_player);
}

void save(const game& g, const std::string& filename)
Expand Down Expand Up @@ -583,54 +628,193 @@ void test_game() //!OCLINT tests may be many
assert(losing_player_size_after < losing_player_size_before);
}

//#define FIX_ISSUE_381
#define FIX_ISSUE_381
#ifdef FIX_ISSUE_381
///A player can become invulnerable
/// A player can become passive
{
game g;

assert(is_active(g.get_player(0)));
become_invulnerable(g.get_player(0));
assert(is_invulnerable(g.get_player(0)));
g.set_player_state_passive(g.get_player(0));
assert(is_passive(g.get_player(0)));
}

/// A player can become passive, using player.set_state_passive()
{
game g;

assert(is_active(g.get_player(0)));
g.get_player(0).set_state_passive();
assert(is_passive(g.get_player(0)));
}

/// A player can become non-passive again
{
game g;

assert(is_active(g.get_player(0)));
g.set_player_state_passive(g.get_player(0));
g.remove_player_state_passive(g.get_player(0));
assert(!is_passive(g.get_player(0)));
}

/// A player can become non-passive again, using player.remove_state_passive()
{
game g;

assert(is_active(g.get_player(0)));
g.get_player(0).set_state_passive();
g.get_player(0).remove_state_passive();
assert(!is_passive(g.get_player(0)));
}
#endif

#define FIX_ISSUE_382
#ifdef FIX_ISSUE_382
///An invulnerable player cannot shrink
/// An passive player cannot grow
{
game g;

//Make the first player invulnerable
become_invulnerable(g.get_player(0));
// Make the first player passive
g.set_player_state_passive(g.get_player(0));

// Make player 1 and 2 overlap
g.get_player(1).set_x(get_x(g.get_player(0)));
g.get_player(1).set_y(get_y(g.get_player(0)));
assert(has_collision(g));

// After a tick, invulnerable player does not shrink
const int inv_player_size_before = get_nth_player_size(g, 0);
const int first_player_index = get_collision_members(g)[0];
const int second_player_index = get_collision_members(g)[1];
const int winner_index = get_winning_player_index(g, first_player_index, second_player_index);

assert(winner_index == 0);

// After a tick, passive player does not grow
const int inv_player_size_before = get_nth_player_size(g, winner_index);
g.tick();
const int inv_player_size_after = get_nth_player_size(g, 0);
const int inv_player_size_after = get_nth_player_size(g, winner_index);
assert(inv_player_size_after == inv_player_size_before);
}

/// An passive player cannot shrink
{
game g;

//Make the first player passive
g.set_player_state_passive(g.get_player(1));

// Make player 1 and 2 overlap
g.get_player(1).set_x(get_x(g.get_player(0)));
g.get_player(1).set_y(get_y(g.get_player(0)));

const int first_player_index = get_collision_members(g)[1];
const int second_player_index = get_collision_members(g)[0];
const int loser_index = get_losing_player_index(g, first_player_index, second_player_index);

assert(loser_index == 1);

// After a tick, passive player does not shrink
const int inv_player_size_before = get_nth_player_size(g, loser_index);
g.tick();
const int inv_player_size_after = get_nth_player_size(g, loser_index);
assert(inv_player_size_after == inv_player_size_before);
}
#endif

//#define FIX_ISSUE_463

#define FIX_ISSUE_463
#ifdef FIX_ISSUE_463
// Players lose invulnerability after a short time
// Can get and set a player's passive state
{
game g;
player& p = g.get_player(0);

// Check default duration
assert(p.get_duration_passive() == 2000);

int new_duration = 200;
p.set_duration_passive(new_duration);
assert(p.get_duration_passive() == new_duration);
}

// Game cannot increment a player's passive timer unless it is passive
{
game g;
player& p = g.get_player(0);
assert(!is_passive(p));
assert(p.get_passive_timer() == 0);

g.increment_passive_timers();
assert(p.get_passive_timer() == 0);

int timer_before = p.get_passive_timer();
p.set_state_passive();
g.increment_passive_timers();
int timer_after = p.get_passive_timer();
int difference = timer_after - timer_before;
assert(difference == 1);
}

// A player's passive timer cannot be bigger than its passive duration,
// Otherwise it will be reset to 0
{
game g;
player& p = g.get_player(0);
g.set_player_state_passive(p);
int duration = p.get_duration_passive();
for (int i = 0; i < duration - 1; i++)
{
assert(p.get_state() == player_state::passive);
int timer_before = p.get_passive_timer();
g.tick();
int timer_after = p.get_passive_timer();
int difference = timer_after - timer_before;
assert(difference == 1);
assert(timer_after <= duration);
}
g.tick();
assert(!p.get_passive_timer());
int timer = p.get_passive_timer();
assert(timer == 0);
}

// Game cannot reset a player's passive timer if it's less than duration
{
game g;
player& p = g.get_player(0);

int timer = p.get_passive_timer();
assert(timer == 0);

p.set_state_passive();
int duration = p.get_duration_passive();

for (int i = 0; i < duration - 1; i++)
{
int timer_before = p.get_passive_timer();
g.tick();
int timer_after = p.get_passive_timer();
int difference = timer_after - timer_before;
assert(difference == 1);
assert(timer_after <= duration);
timer_before = p.get_passive_timer();
g.reset_passive_timers();
timer_after = p.get_passive_timer();
assert(timer_after == timer_before);
}
}

// Players lose passive state after a short time
{
game g;
player& p = g.get_player(0);
const int duration_invulnerability = p.get_duration_invulnerability();
become_invulnerable(p);
for (int t = 0; t < duration_invulnerability; t++)
const int duration_passive = p.get_duration_passive();
g.set_player_state_passive(p);
for (int t = 0; t < duration_passive; t++)
{
assert(is_invulnerable(p));
assert(is_passive(p));
g.tick();
}
assert(!is_invulnerable(p));
assert(!is_passive(p));
assert(p.get_state() == player_state::active);
}
#endif
Expand Down
12 changes: 12 additions & 0 deletions src/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,18 @@ class game
/// Assumes that index exists, else crashes
void kill_player(const int index);

/// PASSIVE STATE ///
void set_player_state_passive(player &p) noexcept;

void remove_player_state_passive(player &p) noexcept;

/// Increment all players' passive timers, if applicable, in every tick
void increment_passive_timers() noexcept;

/// Reset all players' passive timers, if applicable, in every tick
void reset_passive_timers() noexcept;
/// PASSIVE STATE ///

/// Apply inertia to player movement
void apply_inertia();

Expand Down
4 changes: 3 additions & 1 deletion src/game_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@ bool has_any_interplayer_collision(const game &g) noexcept
for (int j = i + 1; j < n_players; ++j)
{
auto& rhs_pl = g.get_player(j);
if(is_alive(rhs_pl))
if(is_alive(rhs_pl)
&& !is_passive(winning_player)
&& !is_passive(losing_player) )
{
if (are_colliding(lhs_pl, rhs_pl))
{
Expand Down
11 changes: 9 additions & 2 deletions src/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ void add_action(player& p, action_type action) noexcept

bool are_colliding(const player &lhs, const player &rhs) noexcept
{
if (lhs.get_state() == player_state::active
&& rhs.get_state() == player_state::active)
if (lhs.get_state() != player_state::dead
&& rhs.get_state() != player_state::dead)
{
const double dx = std::abs(get_x(lhs) - get_x(rhs));
const double dy = std::abs(get_y(lhs) - get_y(rhs));
Expand Down Expand Up @@ -215,6 +215,13 @@ bool is_dead(const player& p) noexcept
return p.get_state() == player_state::dead;
}

/// PASSIVE STATE ///
bool is_passive(const player& p) noexcept
{
return p.get_state() == player_state::passive;
}
/// PASSIVE STATE ///

int get_colorhash(const player &p) noexcept
{
assert(p.get_color().get_red() == 0 || p.get_color().get_red() == 255);
Expand Down
Loading

0 comments on commit 55b0d45

Please sign in to comment.