mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 17:40:27 +00:00
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:
parent
24225df979
commit
811d9722f9
Notes:
sideshowbarker
2024-07-18 12:00:17 +09:00
Author: https://github.com/mimhufford 🔰 Commit: https://github.com/SerenityOS/serenity/commit/811d9722f91 Pull-request: https://github.com/SerenityOS/serenity/pull/7668 Reviewed-by: https://github.com/alimpfard Reviewed-by: https://github.com/gunnarbeutner
8 changed files with 257 additions and 0 deletions
4
Base/res/apps/FlappyBug.af
Normal file
4
Base/res/apps/FlappyBug.af
Normal file
|
@ -0,0 +1,4 @@
|
|||
[App]
|
||||
Name=Flappy Bug
|
||||
Executable=/bin/FlappyBug
|
||||
Category=Games
|
BIN
Base/res/icons/16x16/app-flappybug.png
Normal file
BIN
Base/res/icons/16x16/app-flappybug.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 182 B |
BIN
Base/res/icons/32x32/app-flappybug.png
Normal file
BIN
Base/res/icons/32x32/app-flappybug.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 241 B |
|
@ -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)
|
||||
|
|
7
Userland/Games/FlappyBug/CMakeLists.txt
Normal file
7
Userland/Games/FlappyBug/CMakeLists.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
set(SOURCES
|
||||
main.cpp
|
||||
Game.cpp
|
||||
)
|
||||
|
||||
serenity_app(FlappyBug ICON app-flappybug)
|
||||
target_link_libraries(FlappyBug LibGUI)
|
84
Userland/Games/FlappyBug/Game.cpp
Normal file
84
Userland/Games/FlappyBug/Game.cpp
Normal 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();
|
||||
}
|
||||
|
||||
}
|
99
Userland/Games/FlappyBug/Game.h
Normal file
99
Userland/Games/FlappyBug/Game.h
Normal 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;
|
||||
};
|
||||
|
||||
}
|
62
Userland/Games/FlappyBug/main.cpp
Normal file
62
Userland/Games/FlappyBug/main.cpp
Normal 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();
|
||||
}
|
Loading…
Reference in a new issue