├── .gitignore
├── assets
├── audio
│ ├── die.ogg
│ ├── die.wav
│ ├── hit.ogg
│ ├── hit.wav
│ ├── point.ogg
│ ├── point.wav
│ ├── wing.ogg
│ ├── wing.wav
│ ├── swoosh.ogg
│ └── swoosh.wav
└── sprites
│ ├── 0.png
│ ├── 1.png
│ ├── 2.png
│ ├── 3.png
│ ├── 4.png
│ ├── 5.png
│ ├── 6.png
│ ├── 7.png
│ ├── 8.png
│ ├── 9.png
│ ├── base.png
│ ├── play.png
│ ├── gameover.png
│ ├── message.png
│ ├── pipe-red.png
│ ├── pipe-green.png
│ ├── background-day.png
│ ├── background-night.png
│ ├── bluebird-midflap.png
│ ├── bluebird-upflap.png
│ ├── redbird-downflap.png
│ ├── redbird-midflap.png
│ ├── redbird-upflap.png
│ ├── bluebird-downflap.png
│ ├── yellowbird-midflap.png
│ ├── yellowbird-upflap.png
│ └── yellowbird-downflap.png
├── game_state.py
├── README.md
├── LICENSE
├── bird.py
├── pipe.py
├── game_variables.py
└── flappy.py
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | __pycache__
3 | .DS_Store
--------------------------------------------------------------------------------
/assets/audio/die.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/audio/die.ogg
--------------------------------------------------------------------------------
/assets/audio/die.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/audio/die.wav
--------------------------------------------------------------------------------
/assets/audio/hit.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/audio/hit.ogg
--------------------------------------------------------------------------------
/assets/audio/hit.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/audio/hit.wav
--------------------------------------------------------------------------------
/assets/sprites/0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/0.png
--------------------------------------------------------------------------------
/assets/sprites/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/1.png
--------------------------------------------------------------------------------
/assets/sprites/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/2.png
--------------------------------------------------------------------------------
/assets/sprites/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/3.png
--------------------------------------------------------------------------------
/assets/sprites/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/4.png
--------------------------------------------------------------------------------
/assets/sprites/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/5.png
--------------------------------------------------------------------------------
/assets/sprites/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/6.png
--------------------------------------------------------------------------------
/assets/sprites/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/7.png
--------------------------------------------------------------------------------
/assets/sprites/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/8.png
--------------------------------------------------------------------------------
/assets/sprites/9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/9.png
--------------------------------------------------------------------------------
/assets/audio/point.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/audio/point.ogg
--------------------------------------------------------------------------------
/assets/audio/point.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/audio/point.wav
--------------------------------------------------------------------------------
/assets/audio/wing.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/audio/wing.ogg
--------------------------------------------------------------------------------
/assets/audio/wing.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/audio/wing.wav
--------------------------------------------------------------------------------
/assets/audio/swoosh.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/audio/swoosh.ogg
--------------------------------------------------------------------------------
/assets/audio/swoosh.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/audio/swoosh.wav
--------------------------------------------------------------------------------
/assets/sprites/base.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/base.png
--------------------------------------------------------------------------------
/assets/sprites/play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/play.png
--------------------------------------------------------------------------------
/assets/sprites/gameover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/gameover.png
--------------------------------------------------------------------------------
/assets/sprites/message.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/message.png
--------------------------------------------------------------------------------
/assets/sprites/pipe-red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/pipe-red.png
--------------------------------------------------------------------------------
/assets/sprites/pipe-green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/pipe-green.png
--------------------------------------------------------------------------------
/assets/sprites/background-day.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/background-day.png
--------------------------------------------------------------------------------
/assets/sprites/background-night.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/background-night.png
--------------------------------------------------------------------------------
/assets/sprites/bluebird-midflap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/bluebird-midflap.png
--------------------------------------------------------------------------------
/assets/sprites/bluebird-upflap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/bluebird-upflap.png
--------------------------------------------------------------------------------
/assets/sprites/redbird-downflap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/redbird-downflap.png
--------------------------------------------------------------------------------
/assets/sprites/redbird-midflap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/redbird-midflap.png
--------------------------------------------------------------------------------
/assets/sprites/redbird-upflap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/redbird-upflap.png
--------------------------------------------------------------------------------
/assets/sprites/bluebird-downflap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/bluebird-downflap.png
--------------------------------------------------------------------------------
/assets/sprites/yellowbird-midflap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/yellowbird-midflap.png
--------------------------------------------------------------------------------
/assets/sprites/yellowbird-upflap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/yellowbird-upflap.png
--------------------------------------------------------------------------------
/assets/sprites/yellowbird-downflap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iJohnMaged/FlapPy-Bird/HEAD/assets/sprites/yellowbird-downflap.png
--------------------------------------------------------------------------------
/game_state.py:
--------------------------------------------------------------------------------
1 | """
2 | This module contains the class representing the game state, A simple Enum.
3 | """
4 | from enum import Enum
5 |
6 |
7 | class State(Enum):
8 | MAIN_MENU = 0
9 | PLAYING = 1
10 | GAME_OVER = 2
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FlapPy-Bird
2 |
3 | Python 3 implemention of FlappyBird game using [Arcade Library](http://arcade.academy/)
4 |
5 | ## Installation and usage
6 |
7 | Make sure to install Arcade library from [here](http://arcade.academy/installation.html)
8 | and then you can run the game using the command
9 |
10 | `python flappy.py`
11 |
12 | ## Todo
13 |
14 | * [ ] Train my [Neural Network](https://github.com/iJohnMaged/Simple-NeuralNetwork-Py)
15 | implemention to play the game.
16 |
17 | ### Screenshots
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 John Maged
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/bird.py:
--------------------------------------------------------------------------------
1 | import math
2 | import random
3 | # BAD BAD BAD
4 | from game_variables import *
5 |
6 |
7 | class Bird(arcade.AnimatedTimeSprite):
8 |
9 | def __init__(self, center_x, center_y, death_height):
10 | super().__init__(center_x=center_x, center_y=center_y)
11 | self.score = 0
12 | self.textures = []
13 | rnd = random.SystemRandom()
14 | # Randomly choose a bird color
15 | color = rnd.choice(list(BIRDS))
16 | for i in range(4):
17 | self.textures.append(arcade.load_texture(BIRDS[color][i % 3]))
18 |
19 | self.cur_texture_index = 0
20 | self.vel = 0
21 | self.dy = 0
22 | self.death_height = death_height
23 | self.dead = False
24 |
25 | def set_velocity(self, velocity):
26 | self.vel = velocity
27 |
28 | def update(self, dt=0):
29 | if self.dead:
30 | self.angle = -90
31 | if self.center_y > self.death_height + self.height//2:
32 | self.center_y -= 4
33 | return
34 |
35 | if self.vel > 0:
36 | # self.center_y += (1 - math.cos((JUMP_DY - self.vel) * math.pi)) * JUMP_STEP
37 | self.center_y += DY
38 | # self.center_y += self.vel
39 | # self.vel = 0
40 | self.vel -= DY
41 | if self.angle < 30:
42 | self.angle = min(self.angle + ANGLEP, 30)
43 | else:
44 | if self.angle > -90:
45 | self.angle = max(self.angle + ANGLEM, -90)
46 | self.center_y -= GRAVITY
47 |
48 | def flap(self):
49 | self.vel = JUMP_DY
50 |
51 | def die(self):
52 | self.dead = True
53 | arcade.play_sound(SOUNDS['die'])
54 |
--------------------------------------------------------------------------------
/pipe.py:
--------------------------------------------------------------------------------
1 | import random
2 | # BAD PRACTICE IN 3.. 2.. 1.. GO!
3 | from game_variables import *
4 |
5 | pipe = random.choice(PIPES)
6 |
7 |
8 | class Pipe(arcade.Sprite):
9 |
10 | def __init__(self, image, scale=1):
11 | """
12 | Initializer for the pipe object, it's not really correct to call this Pipe since this class is responsible of
13 | creating two pipes as an obstacle for the bird.
14 | """
15 | super().__init__(image, scale)
16 | # the amount of pixels the pipe move each frame.
17 | self.horizontal_speed = -1.5
18 | # Just a boolean to check if the bird passed this pipe successfully.
19 | self.scored = False
20 |
21 | @classmethod
22 | def random_pipe_obstacle(cls, sprites, height):
23 | """
24 | A class method that creates two pipes each with minimum height of MIN_HEIGHT and minimum MIN_GAP distance
25 | between the two pipes. Each obstacle created from this method will be placed exactly 1 pixel out of the screen.
26 | Sprites: Dictionary holding textures to both base and background (to be used as a reference to where to draw
27 | the pipe, could be improved and optimized?)
28 | """
29 | bottom_pipe = cls(pipe)
30 | bottom_pipe.top = random.randrange(sprites['base'].height + MIN_HEIGHT, height - GAP_SIZE - MIN_HEIGHT)
31 | bottom_pipe.left = sprites['background'].width
32 |
33 | top_pipe = cls(pipe)
34 | top_pipe.angle = 180
35 | top_pipe.left = sprites['background'].width
36 | top_pipe.bottom = bottom_pipe.top + GAP_SIZE
37 | # top_pipe.bottom = random.randrange(bottom_pipe.top + MIN_GAP, height - MIN_HEIGHT)
38 |
39 | return bottom_pipe, top_pipe
40 |
41 | def update(self):
42 | # Move each frame in the negative x direction.
43 | self.center_x += self.horizontal_speed
--------------------------------------------------------------------------------
/game_variables.py:
--------------------------------------------------------------------------------
1 | """
2 | This module contains very useful variables for the game.
3 | """
4 |
5 | import os
6 | import arcade
7 |
8 | # List of different pipe images (Green / Red) (Choose one)
9 | PIPES = ["assets" + os.sep + "sprites" + os.sep + "pipe-green.png", "assets" + os.sep + "sprites" + os.sep + "pipe-red.png"]
10 | # Image of the base floor
11 | BASE = "assets" + os.sep + "sprites" + os.sep + "base.png"
12 | # List of different background images (Day / Night) (Choose one)
13 | PLAY_BUTTON = "assets" + os.sep + "sprites" + os.sep + "play.png"
14 | BACKGROUNDS = ["assets" + os.sep + "sprites" + os.sep + "background-day.png", "assets" + os.sep + "sprites" + os.sep + "background-night.png"]
15 | # Dict holding the animation images for different birds colors (Choose one)
16 | BIRDS = {'yellow': ["assets" + os.sep + "sprites" + os.sep + "yellowbird-downflap.png", "assets" + os.sep + "sprites" + os.sep + "yellowbird-midflap.png",
17 | "assets" + os.sep + "sprites" + os.sep + "yellowbird-upflap.png"],
18 | 'red': ["assets" + os.sep + "sprites" + os.sep + "redbird-downflap.png", "assets" + os.sep + "sprites" + os.sep + "redbird-midflap.png",
19 | "assets" + os.sep + "sprites" + os.sep + "redbird-upflap.png"],
20 | 'blue': ["assets" + os.sep + "sprites" + os.sep + "bluebird-downflap.png", "assets" + os.sep + "sprites" + os.sep + "bluebird-midflap.png",
21 | "assets" + os.sep + "sprites" + os.sep + "bluebird-upflap.png"]}
22 | # Start screen (Tap tap!)
23 | GET_READY_MESSAGE = "assets" + os.sep + "sprites" + os.sep + "message.png"
24 | # Game over logo
25 | GAME_OVER = "assets" + os.sep + "sprites" + os.sep + "gameover.png"
26 | # dict mapping sound name to arcade sound object
27 | SOUNDS = {'wing': arcade.load_sound("assets" + os.sep + "audio" + os.sep + "wing.wav"),
28 | 'die': arcade.load_sound("assets" + os.sep + "audio" + os.sep + "die.wav"),
29 | 'hit': arcade.load_sound("assets" + os.sep + "audio" + os.sep + "hit.wav"),
30 | 'point': arcade.load_sound("assets" + os.sep + "audio" + os.sep + "point.wav"),
31 | 'swoosh': arcade.load_sound("assets" + os.sep + "audio" + os.sep + "swoosh.wav")}
32 | # TODO: Better variables names :)
33 |
34 | # Minimum height for a pipe
35 | MIN_HEIGHT = 50
36 | # Minimum gap between two pipes (The gap that a bird can go through)
37 | # MIN_GAP = 100
38 |
39 | GAP_SIZE = 120
40 |
41 | # How many pixels per jump
42 | JUMP_DY = 60
43 | # How many pixels per frame
44 | JUMP_STEP = 4
45 | DY = 2
46 | # Gravity pixels
47 | GRAVITY = 2
48 |
49 | ANGLEP = 15
50 | ANGLEM = -1.5
51 |
52 | # Images for the score board.
53 | SCORE = {
54 | '0': 'assets' + os.sep + 'sprites' + os.sep + '0.png',
55 | '1': 'assets' + os.sep + 'sprites' + os.sep + '1.png',
56 | '2': 'assets' + os.sep + 'sprites' + os.sep + '2.png',
57 | '3': 'assets' + os.sep + 'sprites' + os.sep + '3.png',
58 | '4': 'assets' + os.sep + 'sprites' + os.sep + '4.png',
59 | '5': 'assets' + os.sep + 'sprites' + os.sep + '5.png',
60 | '6': 'assets' + os.sep + 'sprites' + os.sep + '6.png',
61 | '7': 'assets' + os.sep + 'sprites' + os.sep + '7.png',
62 | '8': 'assets' + os.sep + 'sprites' + os.sep + '8.png',
63 | '9': 'assets' + os.sep + 'sprites' + os.sep + '9.png',
64 | }
65 |
--------------------------------------------------------------------------------
/flappy.py:
--------------------------------------------------------------------------------
1 | import arcade
2 | import random
3 | from bird import Bird
4 | from pipe import Pipe
5 | from game_state import State
6 | from game_variables import *
7 |
8 |
9 | class Game(arcade.Window):
10 |
11 | def __init__(self, width, height):
12 |
13 | """
14 | Initializer for the game window, note that we need to call setup() on the game object.
15 | """
16 | super().__init__(width, height, title="Flappy Bird!")
17 |
18 | self.sprites = None
19 | self.pipe_sprites = None
20 | self.bird = None
21 | # Background texture
22 | self.background = None
23 | # Base texture
24 | self.base = None
25 | # List of birds, even though we've only one bird, it's better to draw a SpriteList than to draw a Sprite
26 | self.bird_list = None
27 | # Score texture
28 | self.score_board = None
29 | # A boolean to check if the user tapped
30 | self.flapped = False
31 | # initial score
32 | self.score = None
33 | # Initial state of the game
34 | self.state = State.MAIN_MENU
35 | # The texture for the start and game over screens.
36 | self.menus = {'start': arcade.load_texture(GET_READY_MESSAGE),
37 | 'gameover': arcade.load_texture(GAME_OVER),
38 | 'play': arcade.load_texture(PLAY_BUTTON)}
39 |
40 | def setup(self):
41 | self.score = 0
42 | self.score_board = arcade.SpriteList()
43 | self.pipe_sprites = arcade.SpriteList()
44 | self.bird_list = arcade.SpriteList()
45 | # A dict holding sprites of static stuff like background & base
46 | self.background = arcade.load_texture(random.choice(BACKGROUNDS))
47 | self.base = arcade.load_texture(BASE)
48 | # A dict holding a reference to the textures
49 | self.sprites = dict()
50 | self.sprites['background'] = self.background
51 | self.sprites['base'] = self.base
52 | # The bird object itself.
53 | # The AnimatedTimeSprite makes an animated sprite that animates over time.
54 | self.bird = Bird(50, self.height//2, self.base.height)
55 | self.bird_list.append(self.bird)
56 |
57 | # Create a random pipe (Obstacle) to start with.
58 | start_pipe1 = Pipe.random_pipe_obstacle(self.sprites, self.height)
59 | self.pipe_sprites.append(start_pipe1[0])
60 | self.pipe_sprites.append(start_pipe1[1])
61 |
62 | def draw_score_board(self):
63 | """
64 | Draws the score board
65 | """
66 | self.score_board.draw()
67 |
68 | def draw_background(self):
69 | """
70 | Draws the background.
71 | """
72 | arcade.draw_texture_rectangle(self.width // 2, self.height // 2, self.background.width, self.background.height,
73 | self.background, 0)
74 |
75 | def draw_base(self):
76 | """
77 | Bet you expected what this does. :)
78 | """
79 | arcade.draw_texture_rectangle(self.width//2, self.base.height//2, self.base.width, self.base.height, self.base, 0)
80 |
81 | def on_draw(self):
82 |
83 | """
84 | This is the method called when the drawing time comes.
85 | """
86 | # Start rendering and draw all the objects
87 | arcade.start_render()
88 | # Calling "draw()" on a SpriteList object will call it on each child in the list.
89 |
90 | # Whatever the state, we need to draw background, then pipes on top, then base, then bird.
91 | self.draw_background()
92 | self.pipe_sprites.draw()
93 | self.draw_base()
94 | self.bird_list.draw()
95 |
96 | if self.state == State.MAIN_MENU:
97 | # Show the main menu
98 | texture = self.menus['start']
99 | arcade.draw_texture_rectangle(self.width//2, self.height//2 + 50, texture.width, texture.height, texture, 0)
100 |
101 | elif self.state == State.PLAYING:
102 | # Draw the score board when the player start playing.
103 | self.draw_score_board()
104 |
105 | elif self.state == State.GAME_OVER:
106 | # Draw the game over menu if the player lost + draw the score board.
107 | texture = self.menus['gameover']
108 | arcade.draw_texture_rectangle(self.width//2, self.height//2 + 50, texture.width, texture.height, texture, 0)
109 | texture = self.menus['play']
110 | arcade.draw_texture_rectangle(self.width//2, self.height//2 - 100, texture.width, texture.height, texture, 0)
111 | self.draw_score_board()
112 |
113 | def on_key_release(self, symbol, modifiers):
114 |
115 | if symbol == arcade.key.SPACE and self.state == State.MAIN_MENU:
116 | # If the game is starting, just change the state and return
117 | self.state = State.PLAYING
118 | return
119 | if symbol == arcade.key.SPACE:
120 | self.flapped = True
121 |
122 | def on_mouse_press(self, x, y, button, modifiers):
123 |
124 | if self.state == State.GAME_OVER:
125 | texture = self.menus['play']
126 | h = self.height//2 - 100
127 | w = self.width//2
128 | if w - texture.width//2 <= x <= w + texture.width//2:
129 | if h - texture.height//2 <= y <= h + texture.height//2:
130 | self.setup()
131 | self.state = State.MAIN_MENU
132 |
133 | def build_score_board(self):
134 | """
135 | Builds the score board with images. Basically how this work:
136 | 1. Calculate how many digits in the score.
137 | 2. Calculate width (Number of digits * width of each digit image width)
138 | 3. Calculate the "left" x position that makes all the images centered.
139 | 4. Just append every digit's image in the score board.
140 | :return:
141 | """
142 | score_length = len(str(self.score))
143 | score_width = 24 * score_length
144 | left = (self.width - score_width) // 2
145 | self.score_board = arcade.SpriteList()
146 | for s in str(self.score):
147 | self.score_board.append(arcade.Sprite(SCORE[s], 1, center_x=left + 12, center_y=450))
148 | left += 24
149 |
150 | def on_update(self, delta_time):
151 |
152 | """
153 | This is the method called each frame to update objects (Like their position, angle, etc..) before drawing them.
154 | """
155 | # print(delta_time)
156 | # Whatever the state, update the bird animation (as in advance the animation to the next frame)
157 | self.bird_list.update_animation()
158 |
159 | if self.state == State.PLAYING:
160 | self.build_score_board()
161 |
162 | # If the player pressed space, let the bird fly higher
163 | if self.flapped:
164 | arcade.play_sound(SOUNDS['wing'])
165 | self.bird.flap()
166 | self.flapped = False
167 |
168 | # Check if bird is too high
169 | if self.bird.top > self.height:
170 | self.bird.top = self.height
171 |
172 | # Check if bird is too low
173 | if self.bird.bottom <= self.base.height:
174 | if self.bird.change_y < 0:
175 | self.bird.change_y = 0
176 | self.bird.bottom = self.base.height
177 |
178 | new_pipe = None
179 |
180 | # Kill pipes that are no longer shown on the screen as they're useless and live in ram and create a new pipe
181 | # when needed. (If the center_x of the closest pipe to the bird passed the middle of the screen)
182 | for pipe in self.pipe_sprites:
183 | if pipe.right <= 0:
184 | pipe.kill()
185 | elif len(self.pipe_sprites) == 2 and pipe.right <= random.randrange(self.width // 2, self.width // 2 + 15):
186 | new_pipe = Pipe.random_pipe_obstacle(self.sprites, self.height)
187 |
188 | if new_pipe:
189 | self.pipe_sprites.append(new_pipe[0])
190 | self.pipe_sprites.append(new_pipe[1])
191 |
192 | # This calls "update()" Method on each object in the SpriteList
193 | self.pipe_sprites.update()
194 | self.bird.update(delta_time)
195 | self.bird_list.update()
196 |
197 | # If the bird passed the center of the pipe safely, count it as a point.
198 | # Hard coding.. :)
199 | if self.bird.center_x >= self.pipe_sprites[0].center_x and not self.pipe_sprites[0].scored:
200 | arcade.play_sound(SOUNDS['point'])
201 | self.score += 1
202 | # Well, since each "obstacle" is a two pipe system, we gotta count them both as scored.
203 | self.pipe_sprites[0].scored = True
204 | self.pipe_sprites[1].scored = True
205 | print(self.score)
206 |
207 | # Check if the bird collided with any of the pipes
208 | hit = arcade.check_for_collision_with_list(self.bird, self.pipe_sprites)
209 |
210 | if any(hit):
211 | arcade.play_sound(SOUNDS['hit'])
212 | self.state = State.GAME_OVER
213 | self.bird.die()
214 |
215 | elif self.state == State.GAME_OVER:
216 | # We need to keep updating the bird in the game over scene so it can still "die"
217 | self.bird.update()
218 |
219 |
220 | def main():
221 | game = Game(288, 512)
222 | game.setup()
223 | arcade.run()
224 |
225 |
226 | if __name__ == "__main__":
227 | main()
228 |
--------------------------------------------------------------------------------