mirror of
https://github.com/sourabhv/FlapPyBird.git
synced 2024-11-25 16:35:52 +08:00
Split into multiple files
This commit is contained in:
parent
b7cc55bdd8
commit
7289d01000
6
Makefile
6
Makefile
@ -2,13 +2,13 @@ default:
|
||||
@make run
|
||||
|
||||
run:
|
||||
python flappy.py
|
||||
python main.py
|
||||
|
||||
web:
|
||||
pygbag flappy.py
|
||||
pygbag main.py
|
||||
|
||||
web-build:
|
||||
pygbag --build flappy.py
|
||||
pygbag --build main.py
|
||||
|
||||
init:
|
||||
@pip install -U pip; \
|
||||
|
6
main.py
Normal file
6
main.py
Normal file
@ -0,0 +1,6 @@
|
||||
import asyncio
|
||||
|
||||
from src.flappy import Flappy
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(Flappy().start())
|
0
src/__init__.py
Normal file
0
src/__init__.py
Normal file
33
src/constants.py
Normal file
33
src/constants.py
Normal file
@ -0,0 +1,33 @@
|
||||
# list of all possible players (tuple of 3 positions of flap)
|
||||
PLAYERS = (
|
||||
# red bird
|
||||
(
|
||||
"assets/sprites/redbird-upflap.png",
|
||||
"assets/sprites/redbird-midflap.png",
|
||||
"assets/sprites/redbird-downflap.png",
|
||||
),
|
||||
# blue bird
|
||||
(
|
||||
"assets/sprites/bluebird-upflap.png",
|
||||
"assets/sprites/bluebird-midflap.png",
|
||||
"assets/sprites/bluebird-downflap.png",
|
||||
),
|
||||
# yellow bird
|
||||
(
|
||||
"assets/sprites/yellowbird-upflap.png",
|
||||
"assets/sprites/yellowbird-midflap.png",
|
||||
"assets/sprites/yellowbird-downflap.png",
|
||||
),
|
||||
)
|
||||
|
||||
# list of backgrounds
|
||||
BACKGROUNDS = (
|
||||
"assets/sprites/background-day.png",
|
||||
"assets/sprites/background-night.png",
|
||||
)
|
||||
|
||||
# list of pipes
|
||||
PIPES = (
|
||||
"assets/sprites/pipe-green.png",
|
||||
"assets/sprites/pipe-red.png",
|
||||
)
|
@ -2,11 +2,15 @@ import asyncio
|
||||
import random
|
||||
import sys
|
||||
from itertools import cycle
|
||||
from typing import Dict, Tuple, Union
|
||||
|
||||
import pygame
|
||||
from pygame.locals import K_ESCAPE, K_SPACE, K_UP, KEYDOWN, QUIT
|
||||
|
||||
from .hit_mask import HitMask
|
||||
from .images import Images
|
||||
from .sounds import Sounds
|
||||
from .utils import pixel_collision
|
||||
|
||||
|
||||
class Window:
|
||||
def __init__(self, width, height):
|
||||
@ -14,41 +18,6 @@ class Window:
|
||||
self.height = height
|
||||
|
||||
|
||||
# list of all possible players (tuple of 3 positions of flap)
|
||||
PLAYERS_LIST = (
|
||||
# red bird
|
||||
(
|
||||
"assets/sprites/redbird-upflap.png",
|
||||
"assets/sprites/redbird-midflap.png",
|
||||
"assets/sprites/redbird-downflap.png",
|
||||
),
|
||||
# blue bird
|
||||
(
|
||||
"assets/sprites/bluebird-upflap.png",
|
||||
"assets/sprites/bluebird-midflap.png",
|
||||
"assets/sprites/bluebird-downflap.png",
|
||||
),
|
||||
# yellow bird
|
||||
(
|
||||
"assets/sprites/yellowbird-upflap.png",
|
||||
"assets/sprites/yellowbird-midflap.png",
|
||||
"assets/sprites/yellowbird-downflap.png",
|
||||
),
|
||||
)
|
||||
|
||||
# list of backgrounds
|
||||
BACKGROUNDS_LIST = (
|
||||
"assets/sprites/background-day.png",
|
||||
"assets/sprites/background-night.png",
|
||||
)
|
||||
|
||||
# list of pipes
|
||||
PIPES_LIST = (
|
||||
"assets/sprites/pipe-green.png",
|
||||
"assets/sprites/pipe-red.png",
|
||||
)
|
||||
|
||||
|
||||
class Flappy:
|
||||
screen: pygame.Surface
|
||||
clock: pygame.time.Clock
|
||||
@ -56,9 +25,9 @@ class Flappy:
|
||||
window: Window
|
||||
pipe_gap: int
|
||||
base_y: float
|
||||
images: Dict[str, Union[pygame.Surface, Tuple[pygame.Surface, ...]]]
|
||||
sounds: Dict[str, pygame.mixer.Sound]
|
||||
hit_masks: Dict[str, Union[Tuple[Tuple[int, ...], ...], Tuple[int, ...]]]
|
||||
images: Images
|
||||
sounds: Sounds
|
||||
hit_masks: HitMask
|
||||
|
||||
def __init__(self):
|
||||
pygame.init()
|
||||
@ -71,98 +40,9 @@ class Flappy:
|
||||
self.screen = pygame.display.set_mode(
|
||||
(self.window.width, self.window.height)
|
||||
)
|
||||
self.images = self.load_images()
|
||||
self.sounds = self.load_sounds()
|
||||
self.hit_masks = self.load_hit_masks()
|
||||
|
||||
def load_images(self):
|
||||
return {
|
||||
"numbers": list(
|
||||
(
|
||||
pygame.image.load(
|
||||
f"assets/sprites/{num}.png"
|
||||
).convert_alpha()
|
||||
for num in range(10)
|
||||
)
|
||||
),
|
||||
# game over sprite
|
||||
"gameover": pygame.image.load(
|
||||
"assets/sprites/gameover.png"
|
||||
).convert_alpha(),
|
||||
# message sprite for welcome screen
|
||||
"message": pygame.image.load(
|
||||
"assets/sprites/message.png"
|
||||
).convert_alpha(),
|
||||
# base (ground) sprite
|
||||
"base": pygame.image.load(
|
||||
"assets/sprites/base.png"
|
||||
).convert_alpha(),
|
||||
**self.randomize_images(),
|
||||
}
|
||||
|
||||
def randomize_images(self):
|
||||
# select random background sprites
|
||||
rand_bg = random.randint(0, len(BACKGROUNDS_LIST) - 1)
|
||||
# select random player sprites
|
||||
rand_player = random.randint(0, len(PLAYERS_LIST) - 1)
|
||||
# select random pipe sprites
|
||||
rand_pipe = random.randint(0, len(PIPES_LIST) - 1)
|
||||
|
||||
return {
|
||||
"background": pygame.image.load(
|
||||
BACKGROUNDS_LIST[rand_bg]
|
||||
).convert(),
|
||||
"player": (
|
||||
pygame.image.load(PLAYERS_LIST[rand_player][0]).convert_alpha(),
|
||||
pygame.image.load(PLAYERS_LIST[rand_player][1]).convert_alpha(),
|
||||
pygame.image.load(PLAYERS_LIST[rand_player][2]).convert_alpha(),
|
||||
),
|
||||
"pipe": (
|
||||
pygame.transform.flip(
|
||||
pygame.image.load(PIPES_LIST[rand_pipe]).convert_alpha(),
|
||||
False,
|
||||
True,
|
||||
),
|
||||
pygame.image.load(PIPES_LIST[rand_pipe]).convert_alpha(),
|
||||
),
|
||||
}
|
||||
|
||||
def load_sounds(self):
|
||||
if "win" in sys.platform:
|
||||
ext = "wav"
|
||||
else:
|
||||
ext = "ogg"
|
||||
return {
|
||||
"die": pygame.mixer.Sound(f"assets/audio/die.{ext}"),
|
||||
"hit": pygame.mixer.Sound(f"assets/audio/hit.{ext}"),
|
||||
"point": pygame.mixer.Sound(f"assets/audio/point.{ext}"),
|
||||
"swoosh": pygame.mixer.Sound(f"assets/audio/swoosh.{ext}"),
|
||||
"wing": pygame.mixer.Sound(f"assets/audio/wing.{ext}"),
|
||||
}
|
||||
|
||||
def load_hit_masks(self):
|
||||
return {
|
||||
# hitmask for pipes
|
||||
"pipe": (
|
||||
self.get_hit_mask(self.images["pipe"][0]),
|
||||
self.get_hit_mask(self.images["pipe"][1]),
|
||||
),
|
||||
# hitmask for player
|
||||
"player": (
|
||||
self.get_hit_mask(self.images["player"][0]),
|
||||
self.get_hit_mask(self.images["player"][1]),
|
||||
self.get_hit_mask(self.images["player"][2]),
|
||||
),
|
||||
}
|
||||
|
||||
def get_hit_mask(self, image):
|
||||
"""returns a hitmask using an image's alpha."""
|
||||
mask = []
|
||||
for x in range(image.get_width()):
|
||||
mask.append([])
|
||||
for y in range(image.get_height()):
|
||||
mask[x].append(bool(image.get_at((x, y))[3]))
|
||||
return mask
|
||||
self.images = Images()
|
||||
self.sounds = Sounds()
|
||||
self.hit_masks = HitMask(self.images)
|
||||
|
||||
async def start(self):
|
||||
while True:
|
||||
@ -180,19 +60,18 @@ class Flappy:
|
||||
|
||||
player_x = int(self.window.width * 0.2)
|
||||
player_y = int(
|
||||
(self.window.height - self.images["player"][0].get_height()) / 2
|
||||
(self.window.height - self.images.player[0].get_height()) / 2
|
||||
)
|
||||
|
||||
message_x = int(
|
||||
(self.window.width - self.images["message"].get_width()) / 2
|
||||
(self.window.width - self.images.message.get_width()) / 2
|
||||
)
|
||||
message_y = int(self.window.height * 0.12)
|
||||
|
||||
base_x = 0
|
||||
# amount by which base can maximum shift to left
|
||||
baseShift = (
|
||||
self.images["base"].get_width()
|
||||
- self.images["background"].get_width()
|
||||
self.images.base.get_width() - self.images.background.get_width()
|
||||
)
|
||||
|
||||
# player shm for up-down motion on welcome screen
|
||||
@ -207,7 +86,7 @@ class Flappy:
|
||||
sys.exit()
|
||||
if self.is_tap_event(event):
|
||||
# make first flap sound and return values for mainGame
|
||||
self.sounds["wing"].play()
|
||||
self.sounds.wing.play()
|
||||
return {
|
||||
"player_y": player_y + player_shm_vals["val"],
|
||||
"base_x": base_x,
|
||||
@ -222,13 +101,13 @@ class Flappy:
|
||||
self.player_shm(player_shm_vals)
|
||||
|
||||
# draw sprites
|
||||
self.screen.blit(self.images["background"], (0, 0))
|
||||
self.screen.blit(self.images.background, (0, 0))
|
||||
self.screen.blit(
|
||||
self.images["player"][player_index],
|
||||
self.images.player[player_index],
|
||||
(player_x, player_y + player_shm_vals["val"]),
|
||||
)
|
||||
self.screen.blit(self.images["message"], (message_x, message_y))
|
||||
self.screen.blit(self.images["base"], (base_x, self.base_y))
|
||||
self.screen.blit(self.images.message, (message_x, message_y))
|
||||
self.screen.blit(self.images.base, (base_x, self.base_y))
|
||||
|
||||
pygame.display.update()
|
||||
await asyncio.sleep(0)
|
||||
@ -262,8 +141,7 @@ class Flappy:
|
||||
|
||||
base_x = movement_nfo["base_x"]
|
||||
baseShift = (
|
||||
self.images["base"].get_width()
|
||||
- self.images["background"].get_width()
|
||||
self.images.base.get_width() - self.images.background.get_width()
|
||||
)
|
||||
|
||||
# get 2 new pipes to add to upperPipes lowerPipes list
|
||||
@ -312,10 +190,10 @@ class Flappy:
|
||||
pygame.quit()
|
||||
sys.exit()
|
||||
if self.is_tap_event(event):
|
||||
if player_y > -2 * self.images["player"][0].get_height():
|
||||
if player_y > -2 * self.images.player[0].get_height():
|
||||
playerVelY = playerFlapAcc
|
||||
playerFlapped = True
|
||||
self.sounds["wing"].play()
|
||||
self.sounds.wing.play()
|
||||
|
||||
# check for crash here
|
||||
crashTest = self.check_crash(
|
||||
@ -336,12 +214,12 @@ class Flappy:
|
||||
}
|
||||
|
||||
# check for score
|
||||
playerMidPos = player_x + self.images["player"][0].get_width() / 2
|
||||
playerMidPos = player_x + self.images.player[0].get_width() / 2
|
||||
for pipe in upperPipes:
|
||||
pipeMidPos = pipe["x"] + self.images["pipe"][0].get_width() / 2
|
||||
pipeMidPos = pipe["x"] + self.images.pipe[0].get_width() / 2
|
||||
if pipeMidPos <= playerMidPos < pipeMidPos + 4:
|
||||
score += 1
|
||||
self.sounds["point"].play()
|
||||
self.sounds.point.play()
|
||||
|
||||
# playerIndex base_x change
|
||||
if (loopIter + 1) % 3 == 0:
|
||||
@ -362,7 +240,7 @@ class Flappy:
|
||||
# more rotation to cover the threshold (calculated in visible rotation)
|
||||
playerRot = 45
|
||||
|
||||
playerHeight = self.images["player"][playerIndex].get_height()
|
||||
playerHeight = self.images.player[playerIndex].get_height()
|
||||
player_y += min(playerVelY, self.base_y - player_y - playerHeight)
|
||||
|
||||
# move pipes to left
|
||||
@ -379,23 +257,19 @@ class Flappy:
|
||||
# remove first pipe if its out of the screen
|
||||
if (
|
||||
len(upperPipes) > 0
|
||||
and upperPipes[0]["x"] < -self.images["pipe"][0].get_width()
|
||||
and upperPipes[0]["x"] < -self.images.pipe[0].get_width()
|
||||
):
|
||||
upperPipes.pop(0)
|
||||
lowerPipes.pop(0)
|
||||
|
||||
# draw sprites
|
||||
self.screen.blit(self.images["background"], (0, 0))
|
||||
self.screen.blit(self.images.background, (0, 0))
|
||||
|
||||
for uPipe, lPipe in zip(upperPipes, lowerPipes):
|
||||
self.screen.blit(
|
||||
self.images["pipe"][0], (uPipe["x"], uPipe["y"])
|
||||
)
|
||||
self.screen.blit(
|
||||
self.images["pipe"][1], (lPipe["x"], lPipe["y"])
|
||||
)
|
||||
self.screen.blit(self.images.pipe[0], (uPipe["x"], uPipe["y"]))
|
||||
self.screen.blit(self.images.pipe[1], (lPipe["x"], lPipe["y"]))
|
||||
|
||||
self.screen.blit(self.images["base"], (base_x, self.base_y))
|
||||
self.screen.blit(self.images.base, (base_x, self.base_y))
|
||||
# print score so player overlaps the score
|
||||
self.show_score(score)
|
||||
|
||||
@ -405,7 +279,7 @@ class Flappy:
|
||||
visibleRot = playerRot
|
||||
|
||||
playerSurface = pygame.transform.rotate(
|
||||
self.images["player"][playerIndex], visibleRot
|
||||
self.images.player[playerIndex], visibleRot
|
||||
)
|
||||
self.screen.blit(playerSurface, (player_x, player_y))
|
||||
|
||||
@ -418,7 +292,7 @@ class Flappy:
|
||||
score = crashInfo["score"]
|
||||
playerx = self.window.width * 0.2
|
||||
player_y = crashInfo["y"]
|
||||
playerHeight = self.images["player"][0].get_height()
|
||||
playerHeight = self.images.player[0].get_height()
|
||||
playerVelY = crashInfo["playerVelY"]
|
||||
playerAccY = 2
|
||||
playerRot = crashInfo["playerRot"]
|
||||
@ -432,9 +306,9 @@ class Flappy:
|
||||
)
|
||||
|
||||
# play hit and die sounds
|
||||
self.sounds["hit"].play()
|
||||
self.sounds.hit.play()
|
||||
if not crashInfo["groundCrash"]:
|
||||
self.sounds["die"].play()
|
||||
self.sounds.die.play()
|
||||
|
||||
while True:
|
||||
for event in pygame.event.get():
|
||||
@ -463,24 +337,20 @@ class Flappy:
|
||||
playerRot -= playerVelRot
|
||||
|
||||
# draw sprites
|
||||
self.screen.blit(self.images["background"], (0, 0))
|
||||
self.screen.blit(self.images.background, (0, 0))
|
||||
|
||||
for uPipe, lPipe in zip(upperPipes, lowerPipes):
|
||||
self.screen.blit(
|
||||
self.images["pipe"][0], (uPipe["x"], uPipe["y"])
|
||||
)
|
||||
self.screen.blit(
|
||||
self.images["pipe"][1], (lPipe["x"], lPipe["y"])
|
||||
)
|
||||
self.screen.blit(self.images.pipe[0], (uPipe["x"], uPipe["y"]))
|
||||
self.screen.blit(self.images.pipe[1], (lPipe["x"], lPipe["y"]))
|
||||
|
||||
self.screen.blit(self.images["base"], (base_x, self.base_y))
|
||||
self.screen.blit(self.images.base, (base_x, self.base_y))
|
||||
self.show_score(score)
|
||||
|
||||
playerSurface = pygame.transform.rotate(
|
||||
self.images["player"][1], playerRot
|
||||
self.images.player[1], playerRot
|
||||
)
|
||||
self.screen.blit(playerSurface, (playerx, player_y))
|
||||
self.screen.blit(self.images["gameover"], (50, 180))
|
||||
self.screen.blit(self.images.gameover, (50, 180))
|
||||
|
||||
self.clock.tick(self.fps)
|
||||
pygame.display.update()
|
||||
@ -491,7 +361,7 @@ class Flappy:
|
||||
# y of gap between upper and lower pipe
|
||||
gapY = random.randrange(0, int(self.base_y * 0.6 - self.pipe_gap))
|
||||
gapY += int(self.base_y * 0.2)
|
||||
pipeHeight = self.images["pipe"][0].get_height()
|
||||
pipeHeight = self.images.pipe[0].get_height()
|
||||
pipeX = self.window.width + 10
|
||||
|
||||
return [
|
||||
@ -505,22 +375,22 @@ class Flappy:
|
||||
totalWidth = 0 # total width of all numbers to be printed
|
||||
|
||||
for digit in scoreDigits:
|
||||
totalWidth += self.images["numbers"][digit].get_width()
|
||||
totalWidth += self.images.numbers[digit].get_width()
|
||||
|
||||
x_offset = (self.window.width - totalWidth) / 2
|
||||
|
||||
for digit in scoreDigits:
|
||||
self.screen.blit(
|
||||
self.images["numbers"][digit],
|
||||
self.images.numbers[digit],
|
||||
(x_offset, self.window.height * 0.1),
|
||||
)
|
||||
x_offset += self.images["numbers"][digit].get_width()
|
||||
x_offset += self.images.numbers[digit].get_width()
|
||||
|
||||
def check_crash(self, player, upperPipes, lowerPipes):
|
||||
"""returns True if player collides with base or pipes."""
|
||||
pi = player["index"]
|
||||
player["w"] = self.images["player"][0].get_width()
|
||||
player["h"] = self.images["player"][0].get_height()
|
||||
player["w"] = self.images.player[0].get_width()
|
||||
player["h"] = self.images.player[0].get_height()
|
||||
|
||||
# if player crashes into ground
|
||||
if player["y"] + player["h"] >= self.base_y - 1:
|
||||
@ -530,8 +400,8 @@ class Flappy:
|
||||
playerRect = pygame.Rect(
|
||||
player["x"], player["y"], player["w"], player["h"]
|
||||
)
|
||||
pipeW = self.images["pipe"][0].get_width()
|
||||
pipeH = self.images["pipe"][0].get_height()
|
||||
pipeW = self.images.pipe[0].get_width()
|
||||
pipeH = self.images.pipe[0].get_height()
|
||||
|
||||
for uPipe, lPipe in zip(upperPipes, lowerPipes):
|
||||
# upper and lower pipe rects
|
||||
@ -539,15 +409,15 @@ class Flappy:
|
||||
lPipeRect = pygame.Rect(lPipe["x"], lPipe["y"], pipeW, pipeH)
|
||||
|
||||
# player and upper/lower pipe hitmasks
|
||||
pHitMask = self.hit_masks["player"][pi]
|
||||
uHitmask = self.hit_masks["pipe"][0]
|
||||
lHitmask = self.hit_masks["pipe"][1]
|
||||
pHitMask = self.hit_masks.player[pi]
|
||||
uHitmask = self.hit_masks.pipe[0]
|
||||
lHitmask = self.hit_masks.pipe[1]
|
||||
|
||||
# if bird collided with upipe or lpipe
|
||||
uCollide = self.pixel_collision(
|
||||
uCollide = pixel_collision(
|
||||
playerRect, uPipeRect, pHitMask, uHitmask
|
||||
)
|
||||
lCollide = self.pixel_collision(
|
||||
lCollide = pixel_collision(
|
||||
playerRect, lPipeRect, pHitMask, lHitmask
|
||||
)
|
||||
|
||||
@ -555,23 +425,3 @@ class Flappy:
|
||||
return [True, False]
|
||||
|
||||
return [False, False]
|
||||
|
||||
def pixel_collision(self, rect1, rect2, hitmask1, hitmask2):
|
||||
"""Checks if two objects collide and not just their rects"""
|
||||
rect = rect1.clip(rect2)
|
||||
|
||||
if rect.width == 0 or rect.height == 0:
|
||||
return False
|
||||
|
||||
x1, y1 = rect.x - rect1.x, rect.y - rect1.y
|
||||
x2, y2 = rect.x - rect2.x, rect.y - rect2.y
|
||||
|
||||
for x in range(rect.width):
|
||||
for y in range(rect.height):
|
||||
if hitmask1[x1 + x][y1 + y] and hitmask2[x2 + x][y2 + y]:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(Flappy().start())
|
38
src/hit_mask.py
Normal file
38
src/hit_mask.py
Normal file
@ -0,0 +1,38 @@
|
||||
from typing import List, Tuple
|
||||
|
||||
from .images import Images
|
||||
|
||||
# create custom type
|
||||
HitMaskType = List[List[bool]]
|
||||
|
||||
|
||||
class HitMask:
|
||||
pipe: Tuple[HitMaskType]
|
||||
player: Tuple[HitMaskType]
|
||||
|
||||
def __init__(self, images: Images) -> None:
|
||||
# hit mask for pipe
|
||||
self.pipe = (
|
||||
self.make_hit_mask(images.pipe[0]),
|
||||
self.make_hit_mask(images.pipe[1]),
|
||||
)
|
||||
# hit mask for player
|
||||
self.player = (
|
||||
self.make_hit_mask(images.player[0]),
|
||||
self.make_hit_mask(images.player[1]),
|
||||
self.make_hit_mask(images.player[2]),
|
||||
)
|
||||
|
||||
def make_hit_mask(self, image) -> HitMaskType:
|
||||
"""returns a hit mask using an image's alpha."""
|
||||
return list(
|
||||
(
|
||||
list(
|
||||
(
|
||||
bool(image.get_at((x, y))[3])
|
||||
for y in range(image.get_height())
|
||||
)
|
||||
)
|
||||
for x in range(image.get_width())
|
||||
)
|
||||
)
|
59
src/images.py
Normal file
59
src/images.py
Normal file
@ -0,0 +1,59 @@
|
||||
import random
|
||||
from typing import List, Tuple
|
||||
|
||||
import pygame
|
||||
|
||||
from .constants import BACKGROUNDS, PIPES, PLAYERS
|
||||
|
||||
|
||||
class Images:
|
||||
numbers: List[pygame.Surface]
|
||||
gameover: pygame.Surface
|
||||
message: pygame.Surface
|
||||
base: pygame.Surface
|
||||
background: pygame.Surface
|
||||
player: Tuple[pygame.Surface]
|
||||
pipe: Tuple[pygame.Surface]
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.numbers = list(
|
||||
(
|
||||
pygame.image.load(f"assets/sprites/{num}.png").convert_alpha()
|
||||
for num in range(10)
|
||||
)
|
||||
)
|
||||
|
||||
# game over sprite
|
||||
self.gameover = pygame.image.load(
|
||||
"assets/sprites/gameover.png"
|
||||
).convert_alpha()
|
||||
# message sprite for welcome screen
|
||||
self.message = pygame.image.load(
|
||||
"assets/sprites/message.png"
|
||||
).convert_alpha()
|
||||
# base (ground) sprite
|
||||
self.base = pygame.image.load("assets/sprites/base.png").convert_alpha()
|
||||
self.randomize()
|
||||
|
||||
def randomize(self):
|
||||
# select random background sprites
|
||||
rand_bg = random.randint(0, len(BACKGROUNDS) - 1)
|
||||
# select random player sprites
|
||||
rand_player = random.randint(0, len(PLAYERS) - 1)
|
||||
# select random pipe sprites
|
||||
rand_pipe = random.randint(0, len(PIPES) - 1)
|
||||
|
||||
self.background = pygame.image.load(BACKGROUNDS[rand_bg]).convert()
|
||||
self.player = (
|
||||
pygame.image.load(PLAYERS[rand_player][0]).convert_alpha(),
|
||||
pygame.image.load(PLAYERS[rand_player][1]).convert_alpha(),
|
||||
pygame.image.load(PLAYERS[rand_player][2]).convert_alpha(),
|
||||
)
|
||||
self.pipe = (
|
||||
pygame.transform.flip(
|
||||
pygame.image.load(PIPES[rand_pipe]).convert_alpha(),
|
||||
False,
|
||||
True,
|
||||
),
|
||||
pygame.image.load(PIPES[rand_pipe]).convert_alpha(),
|
||||
)
|
23
src/sounds.py
Normal file
23
src/sounds.py
Normal file
@ -0,0 +1,23 @@
|
||||
import sys
|
||||
|
||||
import pygame
|
||||
|
||||
|
||||
class Sounds:
|
||||
die: pygame.mixer.Sound
|
||||
hit: pygame.mixer.Sound
|
||||
point: pygame.mixer.Sound
|
||||
swoosh: pygame.mixer.Sound
|
||||
wing: pygame.mixer.Sound
|
||||
|
||||
def __init__(self) -> None:
|
||||
if "win" in sys.platform:
|
||||
ext = "wav"
|
||||
else:
|
||||
ext = "ogg"
|
||||
|
||||
self.die = pygame.mixer.Sound(f"assets/audio/die.{ext}")
|
||||
self.hit = pygame.mixer.Sound(f"assets/audio/hit.{ext}")
|
||||
self.point = pygame.mixer.Sound(f"assets/audio/point.{ext}")
|
||||
self.swoosh = pygame.mixer.Sound(f"assets/audio/swoosh.{ext}")
|
||||
self.wing = pygame.mixer.Sound(f"assets/audio/wing.{ext}")
|
25
src/utils.py
Normal file
25
src/utils.py
Normal file
@ -0,0 +1,25 @@
|
||||
import pygame
|
||||
|
||||
from .hit_mask import HitMaskType
|
||||
|
||||
|
||||
def pixel_collision(
|
||||
rect1: pygame.Rect,
|
||||
rect2: pygame.Rect,
|
||||
hitmask1: HitMaskType,
|
||||
hitmask2: HitMaskType,
|
||||
):
|
||||
"""Checks if two objects collide and not just their rects"""
|
||||
rect = rect1.clip(rect2)
|
||||
|
||||
if rect.width == 0 or rect.height == 0:
|
||||
return False
|
||||
|
||||
x1, y1 = rect.x - rect1.x, rect.y - rect1.y
|
||||
x2, y2 = rect.x - rect2.x, rect.y - rect2.y
|
||||
|
||||
for x in range(rect.width):
|
||||
for y in range(rect.height):
|
||||
if hitmask1[x1 + x][y1 + y] and hitmask2[x2 + x][y2 + y]:
|
||||
return True
|
||||
return False
|
Loading…
Reference in New Issue
Block a user