Solitaire: Replace animation Card with manual painting

Repeatedly allocation a new Card object is unnecessary, and makes
propagating OOM awkward. We also don't need a full card, just which
suit/rank it is and its position. So, let's save all the extra
allocation and just paint the card bitmap directly.
This commit is contained in:
Sam Atkins 2023-01-06 13:00:58 +00:00 committed by Linus Groh
parent 80c7ac0d0e
commit 98603e2b20
2 changed files with 29 additions and 18 deletions

View file

@ -55,12 +55,11 @@ void Game::timer_event(Core::TimerEvent&)
m_game_over_animation = true;
set_background_fill_enabled(false);
} else if (m_game_over_animation) {
VERIFY(!m_animation.card().is_null());
if (m_animation.card()->position().x() >= Game::width || m_animation.card()->rect().right() <= 0)
if (m_animation.position().x() >= Game::width || m_animation.card_rect().right() <= 0)
create_new_animation_card();
if (m_animation.tick())
update(m_animation.card()->rect());
update(m_animation.card_rect());
} else if (m_new_game_animation) {
if (m_new_game_animation_delay < new_game_animation_delay) {
++m_new_game_animation_delay;
@ -96,11 +95,12 @@ void Game::timer_event(Core::TimerEvent&)
void Game::create_new_animation_card()
{
auto card = Card::construct(static_cast<Cards::Suit>(get_random_uniform(to_underlying(Cards::Suit::__Count))), static_cast<Cards::Rank>(get_random_uniform(to_underlying(Cards::Rank::__Count))));
card->set_position({ get_random_uniform(Game::width - Card::width), get_random_uniform(Game::height / 8) });
auto suit = static_cast<Cards::Suit>(get_random_uniform(to_underlying(Cards::Suit::__Count)));
auto rank = static_cast<Cards::Rank>(get_random_uniform(to_underlying(Cards::Rank::__Count)));
Gfx::IntPoint position { get_random_uniform(Game::width - Card::width), get_random_uniform(Game::height / 8) };
int x_sgn = card->position().x() > (Game::width / 2) ? -1 : 1;
m_animation = Animation(card, rand_float() + .4f, x_sgn * (get_random_uniform(3) + 2), .6f + rand_float() * .4f);
int x_direction = position.x() > (Game::width / 2) ? -1 : 1;
m_animation = Animation(suit, rank, position, rand_float() + .4f, x_direction * (get_random_uniform(3) + 2), .6f + rand_float() * .4f);
}
void Game::set_background_fill_enabled(bool enabled)

View file

@ -10,6 +10,7 @@
#include <AK/Array.h>
#include <LibCards/CardGame.h>
#include <LibCards/CardPainter.h>
#include <LibCards/CardStack.h>
using Cards::Card;
@ -58,20 +59,29 @@ private:
{
}
Animation(RefPtr<Card> animation_card, float gravity, int x_vel, float bouncyness)
: m_animation_card(animation_card)
Animation(Cards::Suit suit, Cards::Rank rank, Gfx::IntPoint start_position, float gravity, int x_vel, float bouncyness)
: m_suit(suit)
, m_rank(rank)
, m_position(start_position)
, m_gravity(gravity)
, m_x_velocity(x_vel)
, m_bouncyness(bouncyness)
{
}
RefPtr<Card> card() { return m_animation_card; }
Gfx::IntRect card_rect() const
{
return {
m_position.x(), m_position.y(), Card::width, Card::height
};
}
Gfx::IntPoint position() const { return m_position; }
void draw(GUI::Painter& painter)
{
VERIFY(!m_animation_card.is_null());
m_animation_card->paint(painter);
auto bitmap = Cards::CardPainter::the().card_front(m_suit, m_rank);
painter.blit(m_position, bitmap, bitmap->rect());
m_dirty = false;
}
@ -81,15 +91,14 @@ private:
if (m_dirty)
return false;
VERIFY(!m_animation_card.is_null());
m_y_velocity += m_gravity;
if (m_animation_card->position().y() + Card::height + m_y_velocity > Game::height + 1 && m_y_velocity > 0) {
if (m_position.y() + Card::height + m_y_velocity > Game::height + 1 && m_y_velocity > 0) {
m_y_velocity = min((m_y_velocity * -m_bouncyness), -8.f);
m_animation_card->rect().set_y(Game::height - Card::height);
m_animation_card->rect().translate_by(m_x_velocity, 0);
m_position.set_y(Game::height - Card::height);
m_position.translate_by(m_x_velocity, 0);
} else {
m_animation_card->rect().translate_by(m_x_velocity, m_y_velocity);
m_position.translate_by(m_x_velocity, m_y_velocity);
}
m_dirty = true;
@ -97,7 +106,9 @@ private:
}
private:
RefPtr<Card> m_animation_card;
Cards::Suit m_suit { Cards::Suit::Spades };
Cards::Rank m_rank { Cards::Rank::Ace };
Gfx::IntPoint m_position { 0, 0 };
float m_gravity { 0 };
int m_x_velocity { 0 };
float m_y_velocity { 0 };