2021-06-01 17:16:19 +01:00
/*
* Copyright ( c ) 2021 , Mim Hufford < mim @ hotmail . co . uk >
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
# include "Game.h"
namespace FlappyBug {
2021-12-23 22:29:00 +01:00
Game : : Game ( Bug bug , Cloud cloud )
2021-12-23 22:21:33 +01:00
: m_bug ( move ( bug ) )
2021-12-23 22:29:00 +01:00
, m_cloud ( move ( cloud ) )
2021-06-01 17:16:19 +01:00
{
set_override_cursor ( Gfx : : StandardCursor : : Hidden ) ;
start_timer ( 16 ) ;
reset ( ) ;
}
void Game : : reset ( )
{
m_active = false ;
2021-06-01 17:59:01 +01:00
m_last_score = m_difficulty ;
2021-06-01 17:16:19 +01:00
m_difficulty = 1 ;
2021-06-02 10:37:00 +01:00
m_restart_cooldown = 3 ;
2021-06-01 17:16:19 +01:00
m_bug . reset ( ) ;
m_obstacle . reset ( ) ;
}
2021-06-01 17:59:01 +01:00
void Game : : game_over ( )
{
2021-06-22 10:50:54 -04:00
if ( on_game_end )
2021-06-22 10:54:42 -04:00
m_high_score = on_game_end ( static_cast < u32 > ( m_difficulty ) ) ;
2021-06-22 10:50:54 -04:00
2021-06-01 17:59:01 +01:00
reset ( ) ;
}
2021-06-02 10:37:00 +01:00
bool Game : : ready_to_start ( ) const
{
2021-06-22 10:54:42 -04:00
if ( ! m_high_score . has_value ( ) ) {
2021-06-02 10:37:00 +01:00
return true ;
}
if ( m_restart_cooldown < = 0 ) {
return true ;
}
return false ;
}
2021-06-01 17:16:19 +01:00
void Game : : timer_event ( Core : : TimerEvent & )
{
tick ( ) ;
}
void Game : : paint_event ( GUI : : PaintEvent & event )
{
2021-06-21 15:53:50 -04:00
GUI : : Frame : : paint_event ( event ) ;
2021-06-01 17:16:19 +01:00
GUI : : Painter painter ( * this ) ;
2021-06-21 15:53:50 -04:00
painter . add_clip_rect ( frame_inner_rect ( ) ) ;
2021-06-01 17:16:19 +01:00
painter . add_clip_rect ( event . rect ( ) ) ;
2021-06-21 15:53:50 -04:00
painter . draw_tiled_bitmap ( frame_inner_rect ( ) , * m_background_bitmap ) ;
2021-06-07 11:03:01 +01:00
painter . draw_scaled_bitmap ( m_cloud . rect ( ) , * m_cloud . bitmap ( ) , m_cloud . bitmap ( ) - > rect ( ) , 0.2f ) ;
2021-06-01 17:16:19 +01:00
2021-06-02 12:18:57 +01:00
painter . fill_rect ( enclosing_int_rect ( m_obstacle . top_rect ( ) ) , m_obstacle . color ) ;
painter . fill_rect ( enclosing_int_rect ( m_obstacle . bottom_rect ( ) ) , m_obstacle . color ) ;
painter . draw_scaled_bitmap ( enclosing_int_rect ( m_bug . rect ( ) ) , * m_bug . current_bitmap ( ) , m_bug . flapping_bitmap - > rect ( ) ) ;
2021-06-01 17:16:19 +01:00
2021-06-01 17:59:01 +01:00
if ( m_active ) {
2023-06-21 02:03:32 -04:00
painter . draw_text ( m_score_rect , String : : formatted ( " {:.0} " , m_difficulty ) . release_value_but_fixme_should_propagate_errors ( ) , Gfx : : TextAlignment : : TopLeft , Color : : White ) ;
2021-06-22 10:54:42 -04:00
} else if ( m_high_score . has_value ( ) ) {
2023-06-21 02:03:32 -04:00
auto message = String : : formatted ( " Your score: {:.0} \n High score: {:.0} \n \n {} " , m_last_score , m_high_score . value ( ) , m_restart_cooldown < 0 ? " Press any key to play again " : " " ) . release_value_but_fixme_should_propagate_errors ( ) ;
2021-07-10 17:15:38 -04:00
painter . draw_text ( m_text_rect , message , Gfx : : TextAlignment : : Center , Color : : White ) ;
2021-06-01 17:59:01 +01:00
} else {
2022-07-11 17:32:29 +00:00
painter . draw_text ( m_text_rect , " Press any key to start " sv , Gfx : : TextAlignment : : Center , Color : : White ) ;
2021-06-01 17:59:01 +01:00
}
2021-06-01 17:16:19 +01:00
}
void Game : : keydown_event ( GUI : : KeyEvent & event )
{
switch ( event . key ( ) ) {
case Key_Escape :
GUI : : Application : : the ( ) - > quit ( ) ;
break ;
default :
2021-11-23 00:53:52 +00:00
player_input ( ) ;
2021-06-01 17:16:19 +01:00
break ;
}
}
2021-11-23 00:53:52 +00:00
void Game : : mousedown_event ( GUI : : MouseEvent & )
{
player_input ( ) ;
}
void Game : : player_input ( )
{
if ( ready_to_start ( ) ) {
m_active = true ;
}
if ( m_active ) {
m_bug . flap ( ) ;
}
}
2021-06-01 17:16:19 +01:00
void Game : : tick ( )
{
2021-07-10 17:15:38 -04:00
auto queue_update = [ & ] ( ) {
update ( m_score_rect ) ;
update ( m_text_rect ) ;
update ( enclosing_int_rect ( m_bug . rect ( ) ) ) ;
update ( enclosing_int_rect ( m_obstacle . top_rect ( ) ) ) ;
update ( enclosing_int_rect ( m_obstacle . bottom_rect ( ) ) ) ;
update ( m_cloud . rect ( ) ) ;
} ;
2021-06-01 17:16:19 +01:00
if ( m_active ) {
2021-07-10 17:15:38 -04:00
queue_update ( ) ;
2021-06-01 17:59:01 +01:00
m_difficulty + = 1.0f / 16.0f ;
2021-06-01 17:16:19 +01:00
m_bug . fall ( ) ;
m_bug . apply_velocity ( ) ;
2021-06-01 17:59:01 +01:00
m_obstacle . x - = 4 + m_difficulty / 16.0f ;
2021-06-07 11:03:01 +01:00
m_cloud . x - = m_difficulty / 16.0f ;
2021-06-01 17:16:19 +01:00
if ( m_bug . y > game_height | | m_bug . y < 0 ) {
2021-06-01 17:59:01 +01:00
game_over ( ) ;
2021-06-01 17:16:19 +01:00
}
if ( m_bug . rect ( ) . intersects ( m_obstacle . top_rect ( ) ) | | m_bug . rect ( ) . intersects ( m_obstacle . bottom_rect ( ) ) ) {
2021-06-01 17:59:01 +01:00
game_over ( ) ;
2021-06-01 17:16:19 +01:00
}
if ( m_obstacle . x < 0 ) {
m_obstacle . reset ( ) ;
}
2021-06-07 11:03:01 +01:00
if ( m_cloud . x < 0 ) {
m_cloud . reset ( ) ;
}
2021-06-01 17:16:19 +01:00
}
2021-06-02 10:37:00 +01:00
m_restart_cooldown - = 1.0f / 16.0f ;
2021-07-10 17:15:38 -04:00
queue_update ( ) ;
2021-06-01 17:16:19 +01:00
}
}