FlappyBug: Introduce a new Flappy Bug game

This introduces a Flappy Bug game. It's pretty simple currently, but is
playable.
This commit is contained in:
Mim Hufford 2021-06-01 17:16:19 +01:00 committed by Linus Groh
parent 24225df979
commit 811d9722f9
Notes: sideshowbarker 2024-07-18 12:00:17 +09:00
8 changed files with 257 additions and 0 deletions

View file

@ -0,0 +1,4 @@
[App]
Name=Flappy Bug
Executable=/bin/FlappyBug
Category=Games

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 B

View file

@ -1,6 +1,7 @@
add_subdirectory(2048)
add_subdirectory(Breakout)
add_subdirectory(Chess)
add_subdirectory(FlappyBug)
add_subdirectory(GameOfLife)
add_subdirectory(Hearts)
add_subdirectory(Minesweeper)

View file

@ -0,0 +1,7 @@
set(SOURCES
main.cpp
Game.cpp
)
serenity_app(FlappyBug ICON app-flappybug)
target_link_libraries(FlappyBug LibGUI)

View file

@ -0,0 +1,84 @@
/*
* Copyright (c) 2021, Mim Hufford <mim@hotmail.co.uk>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "Game.h"
#include <AK/Random.h>
namespace FlappyBug {
Game::Game()
{
set_override_cursor(Gfx::StandardCursor::Hidden);
start_timer(16);
reset();
}
void Game::reset()
{
m_active = false;
m_difficulty = 1;
m_bug.reset();
m_obstacle.reset();
}
void Game::timer_event(Core::TimerEvent&)
{
tick();
}
void Game::paint_event(GUI::PaintEvent& event)
{
GUI::Painter painter(*this);
painter.add_clip_rect(event.rect());
painter.fill_rect(rect(), Color::Black);
painter.fill_rect(enclosing_int_rect(m_obstacle.top_rect()), Color::White);
painter.fill_rect(enclosing_int_rect(m_obstacle.bottom_rect()), Color::White);
painter.fill_ellipse(enclosing_int_rect(m_bug.rect()), Color::Red);
painter.draw_text({ 10, 10, 100, 100 }, String::formatted("{}", m_difficulty), Gfx::TextAlignment::TopLeft, Color::Green);
}
void Game::keydown_event(GUI::KeyEvent& event)
{
switch (event.key()) {
case Key_Escape:
GUI::Application::the()->quit();
break;
default:
m_active = true;
m_bug.flap();
break;
}
}
void Game::tick()
{
if (m_active) {
m_difficulty += 0.0001f;
m_bug.fall();
m_bug.apply_velocity();
m_obstacle.x -= 4 + m_difficulty;
if (m_bug.y > game_height || m_bug.y < 0) {
reset();
}
if (m_bug.rect().intersects(m_obstacle.top_rect()) || m_bug.rect().intersects(m_obstacle.bottom_rect())) {
reset();
}
if (m_obstacle.x < 0) {
m_obstacle.reset();
}
}
update();
}
}

View file

@ -0,0 +1,99 @@
/*
* Copyright (c) 2021, Mim Hufford <mim@hotmail.co.uk>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Optional.h>
#include <LibGUI/Application.h>
#include <LibGUI/Painter.h>
#include <LibGUI/Widget.h>
#include <LibGfx/Bitmap.h>
#include <LibGfx/Font.h>
#include <LibGfx/StandardCursor.h>
namespace FlappyBug {
class Game final : public GUI::Widget {
C_OBJECT(Game);
public:
static const int game_width = 560;
static const int game_height = 480;
private:
Game();
virtual void paint_event(GUI::PaintEvent&) override;
virtual void keydown_event(GUI::KeyEvent&) override;
virtual void timer_event(Core::TimerEvent&) override;
void tick();
void reset();
struct Bug {
const float x { 50 };
const float radius { 10 };
const float starting_y { 200 };
float y {};
float velocity {};
void reset()
{
y = starting_y;
}
Gfx::FloatRect rect() const
{
return { x - radius, y - radius, radius * 2, radius * 2 };
}
void flap()
{
const float flap_strength = 15.0f;
velocity = -flap_strength;
}
void fall()
{
const float gravity = 1.0f;
velocity += gravity;
}
void apply_velocity()
{
y += velocity;
}
};
struct Obstacle {
const float width { 20 };
float x;
float gap_top_y { 200 };
float gap_height { 175 };
void reset()
{
x = game_width;
}
Gfx::FloatRect top_rect() const
{
return { x - width, 0, width, gap_top_y };
}
Gfx::FloatRect bottom_rect() const
{
return { x - width, gap_top_y + gap_height, width, game_height - gap_top_y - gap_height };
}
};
Bug m_bug;
Obstacle m_obstacle;
bool m_active;
float m_difficulty;
};
}

View file

@ -0,0 +1,62 @@
/*
* Copyright (c) 2021, Mim Hufford <mim@hotmail.co.uk>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "Game.h"
#include <LibGUI/Application.h>
#include <LibGUI/Icon.h>
#include <LibGUI/Menu.h>
#include <LibGUI/Menubar.h>
#include <LibGUI/Window.h>
#include <unistd.h>
int main(int argc, char** argv)
{
if (pledge("stdio rpath wpath cpath recvfd sendfd cpath unix", nullptr) < 0) {
perror("pledge");
return 1;
}
auto app = GUI::Application::construct(argc, argv);
if (pledge("stdio rpath wpath cpath recvfd sendfd", nullptr) < 0) {
perror("pledge");
return 1;
}
if (unveil("/res", "r") < 0) {
perror("unveil");
return 1;
}
if (unveil(nullptr, nullptr) < 0) {
perror("unveil");
return 1;
}
auto window = GUI::Window::construct();
window->resize(FlappyBug::Game::game_width, FlappyBug::Game::game_height);
auto app_icon = GUI::Icon::default_icon("app-flappybug");
window->set_icon(app_icon.bitmap_for_size(16));
window->set_title("Flappy Bug");
window->set_double_buffering_enabled(false);
window->set_resizable(false);
window->set_main_widget<FlappyBug::Game>();
window->show();
auto menubar = GUI::Menubar::construct();
auto& game_menu = menubar->add_menu("&Game");
game_menu.add_action(GUI::CommonActions::make_quit_action([](auto&) {
GUI::Application::the()->quit();
}));
auto& help_menu = menubar->add_menu("&Help");
help_menu.add_action(GUI::CommonActions::make_about_action("Flappy Bug", app_icon, window));
window->set_menubar(move(menubar));
return app->exec();
}