diff options
author | Andreas Kling <kling@serenityos.org> | 2021-01-12 12:03:28 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-01-12 12:04:23 +0100 |
commit | aa939c4b4b8a7eb1d22b166ebb5fb737d6e66714 (patch) | |
tree | c87472f6751c0fbb731858c8b0a4643a451a7f00 /Userland/Games/2048/BoardView.cpp | |
parent | b8d6a56fa354a268e3fbfa4fb6d146e9bf60103e (diff) | |
download | serenity-aa939c4b4b8a7eb1d22b166ebb5fb737d6e66714.zip |
Games: Move to Userland/Games/
Diffstat (limited to 'Userland/Games/2048/BoardView.cpp')
-rw-r--r-- | Userland/Games/2048/BoardView.cpp | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/Userland/Games/2048/BoardView.cpp b/Userland/Games/2048/BoardView.cpp new file mode 100644 index 0000000000..230c1eedc5 --- /dev/null +++ b/Userland/Games/2048/BoardView.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2020, the SerenityOS developers. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "BoardView.h" +#include <LibGUI/Painter.h> +#include <LibGfx/Font.h> +#include <LibGfx/FontDatabase.h> +#include <LibGfx/Palette.h> + +BoardView::BoardView(const Game::Board* board) + : m_board(board) +{ +} + +BoardView::~BoardView() +{ +} + +void BoardView::set_board(const Game::Board* board) +{ + if (m_board == board) + return; + + if (!board) { + m_board = nullptr; + return; + } + + bool must_resize = !m_board || m_board->size() != board->size(); + + m_board = board; + + if (must_resize) + resize(); + + update(); +} + +void BoardView::pick_font() +{ + String best_font_name; + int best_font_size = -1; + auto& font_database = Gfx::FontDatabase::the(); + font_database.for_each_font([&](const Gfx::Font& font) { + if (font.family() != "Liza" || font.weight() != 700) + return; + auto size = font.glyph_height(); + if (size * 2 <= m_cell_size && size > best_font_size) { + best_font_name = font.qualified_name(); + best_font_size = size; + } + }); + + auto font = font_database.get_by_name(best_font_name); + set_font(font); +} + +size_t BoardView::rows() const +{ + if (!m_board) + return 0; + return m_board->size(); +} + +size_t BoardView::columns() const +{ + if (!m_board) + return 0; + if (m_board->is_empty()) + return 0; + return (*m_board)[0].size(); +} + +void BoardView::resize_event(GUI::ResizeEvent&) +{ + resize(); +} + +void BoardView::resize() +{ + constexpr float padding_ratio = 7; + m_padding = min( + width() / (columns() * (padding_ratio + 1) + 1), + height() / (rows() * (padding_ratio + 1) + 1)); + m_cell_size = m_padding * padding_ratio; + + pick_font(); +} + +void BoardView::keydown_event(GUI::KeyEvent& event) +{ + if (!on_move) + return; + + switch (event.key()) { + case KeyCode::Key_A: + case KeyCode::Key_Left: + on_move(Game::Direction::Left); + break; + case KeyCode::Key_D: + case KeyCode::Key_Right: + on_move(Game::Direction::Right); + break; + case KeyCode::Key_W: + case KeyCode::Key_Up: + on_move(Game::Direction::Up); + break; + case KeyCode::Key_S: + case KeyCode::Key_Down: + on_move(Game::Direction::Down); + break; + default: + return; + } +} + +Gfx::Color BoardView::background_color_for_cell(u32 value) +{ + switch (value) { + case 0: + return Color::from_rgb(0xcdc1b4); + case 2: + return Color::from_rgb(0xeee4da); + case 4: + return Color::from_rgb(0xede0c8); + case 8: + return Color::from_rgb(0xf2b179); + case 16: + return Color::from_rgb(0xf59563); + case 32: + return Color::from_rgb(0xf67c5f); + case 64: + return Color::from_rgb(0xf65e3b); + case 128: + return Color::from_rgb(0xedcf72); + case 256: + return Color::from_rgb(0xedcc61); + case 512: + return Color::from_rgb(0xedc850); + case 1024: + return Color::from_rgb(0xedc53f); + case 2048: + return Color::from_rgb(0xedc22e); + default: + ASSERT(value > 2048); + return Color::from_rgb(0x3c3a32); + } +} + +Gfx::Color BoardView::text_color_for_cell(u32 value) +{ + if (value <= 4) + return Color::from_rgb(0x776e65); + return Color::from_rgb(0xf9f6f2); +} + +void BoardView::paint_event(GUI::PaintEvent&) +{ + Color background_color = Color::from_rgb(0xbbada0); + + GUI::Painter painter(*this); + + if (!m_board) { + painter.fill_rect(rect(), background_color); + return; + } + auto& board = *m_board; + + Gfx::IntRect field_rect { + 0, + 0, + static_cast<int>(m_padding + (m_cell_size + m_padding) * columns()), + static_cast<int>(m_padding + (m_cell_size + m_padding) * rows()) + }; + field_rect.center_within(rect()); + painter.fill_rect(field_rect, background_color); + + for (size_t column = 0; column < columns(); ++column) { + for (size_t row = 0; row < rows(); ++row) { + auto rect = Gfx::IntRect { + field_rect.x() + m_padding + (m_cell_size + m_padding) * column, + field_rect.y() + m_padding + (m_cell_size + m_padding) * row, + m_cell_size, + m_cell_size, + }; + auto entry = board[row][column]; + painter.fill_rect(rect, background_color_for_cell(entry)); + if (entry > 0) + painter.draw_text(rect, String::number(entry), font(), Gfx::TextAlignment::Center, text_color_for_cell(entry)); + } + } +} |