diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..99e4b84 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__ +build \ No newline at end of file diff --git a/README.md b/README.md index 022bf1f..56ea033 100644 --- a/README.md +++ b/README.md @@ -14,14 +14,21 @@ A Windows build of the game is available [here](https://polymars.itch.io/flappuc Grab the latest release of Python from [here](https://www.python.org/downloads/) **and** install Pygame by executing ``pip install pygame``. **Note:** If the ``pip install pygame`` did not work for you, then try this: -1. Windows: +1. Windows or Linux: ``python -m pip install pygame`` 2. Mac: ``python3 -m pip install pygame`` -3. Linux: -Same as windows. +3. Browser +```sh +pip install pygbag +cd .. +pygbag Flappuccino +``` +Then +http://localhost:8000 Ensure ``main.py`` is in the same directory as ``./data`` and execute ``python main.py``. +**Note:** If python does not work, try python3, py, or py3. ## Contributing Pull requests are welcome! For major refactors, please open an issue first to discuss what you would like to improve. Feel free to create a fork of this repository and use the code for any noncommercial purposes. diff --git a/background.py b/background.py index 097a092..b422614 100644 --- a/background.py +++ b/background.py @@ -1,11 +1,17 @@ import pygame +import colorsys + + class Background: + uncolored_sprite = pygame.image.load('data/gfx/bg.png') + def __init__(self): self.sprite = pygame.image.load('data/gfx/bg.png') self.position = 0 - self.uncoloredSprite = pygame.image.load('data/gfx/bg.png') - def setSprite(self, tint): - copy = self.uncoloredSprite.copy() - color = colorsys.hsv_to_rgb(tint,1,1) - copy.fill((color[0]*255, color[1]*255, color[2]*255), special_flags=pygame.BLEND_ADD) - self.sprite = copy \ No newline at end of file + + def set_sprite(self, tint: float) -> None: + copy = self.uncolored_sprite.copy() + color = colorsys.hsv_to_rgb(tint, 1, 1) + copy.fill((color[0]*255, color[1]*255, color[2]*255), + special_flags=pygame.BLEND_ADD) + self.sprite = copy diff --git a/bean.py b/bean.py index 5b212bb..c81bf45 100644 --- a/bean.py +++ b/bean.py @@ -1,6 +1,9 @@ import pygame -class Bean: - def __init__(self): - self.sprite = pygame.image.load('data/gfx/bean.png') + + +class Bean: + sprite = pygame.image.load('data/gfx/bean.png') + + def __init__(self, x_pos: float = 0, y_pos: float = 0): self.position = pygame.Vector2() - self.position.xy \ No newline at end of file + self.position.xy = x_pos, y_pos diff --git a/button.py b/button.py index ef92dfb..45e0289 100644 --- a/button.py +++ b/button.py @@ -1,7 +1,18 @@ import pygame +from pygame.image import load + + class Button: - def __init__(self): - self.price = 3 - self.level = 1 - sprite = pygame.image.load('data/gfx/button.png') - typeIndicatorSprite = pygame.image.load('data/gfx/null_indicator.png') + sprite = load('data/gfx/button.png') + type_indicator_sprite = load('data/gfx/null_indicator.png') + + def __init__(self, index: int, indicator: str) -> None: + self.price = 5 + self.level = 1 + self.index = index + self.type_indicator_sprite = load(indicator) + self.position = pygame.Vector2() + self.position.xy = 220 + (self.index*125), 393 + + def set_price(self, new_price: int) -> None: + self.price = new_price diff --git a/data/sfx/bean-pygbag.ogg b/data/sfx/bean-pygbag.ogg new file mode 100644 index 0000000..a3efbf1 Binary files /dev/null and b/data/sfx/bean-pygbag.ogg differ diff --git a/data/sfx/dead-pygbag.ogg b/data/sfx/dead-pygbag.ogg new file mode 100644 index 0000000..1cb5540 Binary files /dev/null and b/data/sfx/dead-pygbag.ogg differ diff --git a/data/sfx/flap-pygbag.ogg b/data/sfx/flap-pygbag.ogg new file mode 100644 index 0000000..da10b3e Binary files /dev/null and b/data/sfx/flap-pygbag.ogg differ diff --git a/data/sfx/upgrade-pygbag.ogg b/data/sfx/upgrade-pygbag.ogg new file mode 100644 index 0000000..289c7c5 Binary files /dev/null and b/data/sfx/upgrade-pygbag.ogg differ diff --git a/main.py b/main.py index a4256fa..8f84558 100644 --- a/main.py +++ b/main.py @@ -1,277 +1,280 @@ -import pygame, sys, time, random, colorsys, math -from pygame.math import Vector2 +#!/usr/bin/env python3 +# Tells Unix operating systems to run with Python3 when it gets executed + +import pygame +import sys +import time +import random +import colorsys +import math +import pygame.display as Display +import asyncio from pygame.locals import * -from .player import Player -from .background import Background -from .button import Button -from .bean import Bean -from .utils import clamp -from .utils import checkCollisions - - -def main(): - pygame.init() - # set the display - DISPLAY=pygame.display.set_mode((640,480),0,32) - pygame.display.set_caption('Flappuccino') - pygame.display.set_icon(Bean().sprite) - # get fonts - font = pygame.font.Font('data/fonts/font.otf', 100) - font_small = pygame.font.Font('data/fonts/font.otf', 32) - font_20 = pygame.font.Font('data/fonts/font.otf', 20) - # get some images - shop = pygame.image.load('data/gfx/shop.png') - shop_bg = pygame.image.load('data/gfx/shop_bg.png') - retry_button = pygame.image.load('data/gfx/retry_button.png') - logo = pygame.image.load('data/gfx/logo.png') - title_bg = pygame.image.load('data/gfx/bg.png') - title_bg.fill((255, 30.599999999999998, 0.0), special_flags=pygame.BLEND_ADD) - shadow = pygame.image.load('data/gfx/shadow.png') - # get sounds - flapfx = pygame.mixer.Sound("data/sfx/flap.wav") - upgradefx = pygame.mixer.Sound("data/sfx/upgrade.wav") - beanfx = pygame.mixer.Sound("data/sfx/bean.wav") - deadfx = pygame.mixer.Sound("data/sfx/dead.wav") - # colors - WHITE=(255,255,255) # constant - # variables - rotOffset = -5 - # creating a new object player - player = Player() +from pygame.mixer import Sound +from pygame.font import Font +from pygame.image import load as Image +from player import Player +from background import Background +from button import Button +from bean import Bean +from utils import * + +# initialize the game +pygame.init() + +# set the display +Display.set_caption('Flappuccino') +Display.set_icon(Bean.sprite) +DISPLAY = Display.set_mode((640, 480), pygame.RESIZABLE | pygame.SCALED, 32) + +player = Player() + +# get fonts +font = Font('data/fonts/font.otf', 100) +font_small = Font('data/fonts/font.otf', 32) +font_20 = Font('data/fonts/font.otf', 20) + +# get some images +shop = Image('data/gfx/shop.png') +shop_bg = Image('data/gfx/shop_bg.png') +retry_button = Image('data/gfx/retry_button.png') +logo = Image('data/gfx/logo.png') +title_bg = Image('data/gfx/bg.png') +title_bg.fill((255, 30.599999999999998, 0.0), special_flags=pygame.BLEND_ADD) +shadow = Image('data/gfx/shadow.png') +indicators = ['data/gfx/flap_indicator.png', + 'data/gfx/speed_indicator.png', 'data/gfx/beanup_indicator.png'] + +# sounds +if ['win64', 'win32', 'win', 'linux'].__contains__(sys.platform): + sound_ext = '.wav' +else: + sound_ext = '-pybag.ogg' +flapfx = pygame.mixer.Sound("data/sfx/flap" + sound_ext) +upgradefx = pygame.mixer.Sound("data/sfx/upgrade" + sound_ext) +beanfx = pygame.mixer.Sound("data/sfx/bean" + sound_ext) +deadfx = pygame.mixer.Sound("data/sfx/dead" + sound_ext) + +# colors +WHITE = (255, 255, 255) # constant + + +def start(): + global bean_multiplier, beans, buttons, last_time, clicked, jump, dt, mouse_x, mouse_y, scroll + last_time = time.time() + clicked = False + jump = False + scroll = True + dt = 0 + bean_multiplier = 5 beans = [] buttons = [] + mouse_x, mouse_y = pygame.mouse.get_pos() + player.reset() # adding three buttons - for i in range(3): buttons.append(Button()) - # now simply loading images based off of indexes in the list - buttons[0].typeIndicatorSprite = pygame.image.load('data/gfx/flap_indicator.png') - buttons[0].price = 5 - buttons[1].typeIndicatorSprite = pygame.image.load('data/gfx/speed_indicator.png') - buttons[1].price = 5 - buttons[2].typeIndicatorSprite = pygame.image.load('data/gfx/beanup_indicator.png') - buttons[2].price = 30 + for i in range(3): + buttons.append(Button(i, indicators[i])) + buttons[2].set_price(30) # getting 5 beans - for i in range(5): beans.append(Bean()) - # now looping through the beans list - for bean in beans: - bean.position.xy = random.randrange(0, DISPLAY.get_width() - bean.sprite.get_width()), beans.index(bean)*-200 - player.position.y + for i in range(5): + beans.append(Bean(random.randrange(0, DISPLAY.get_width() - + Bean().sprite.get_width()), i * -200 - player.position.y)) + Sound.play(flapfx) + + +def func_one(toggle: bool = True) -> None: + global dt, last_time, mouse_x, mouse_y, clicked, jump + # calculate the change in time (dt) + dt = (time.time() - last_time) * 60 + # save the current time + last_time = time.time() + if (toggle): + # resetting clicked and jump flags to false + clicked = False + jump = False + # get the position of the mouse + mouse_x, mouse_y = pygame.mouse.get_pos() + event_handler() + + +def event_handler() -> None: + global jump, clicked + for event in pygame.event.get(): + if event.type == pygame.KEYDOWN and event.key == K_SPACE: + jump = True + if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: + clicked = True + if clicked and mouse_y < DISPLAY.get_height() - 90: + jump = True + if event.type == QUIT: + pygame.quit() + sys.exit() + + +async def main() -> None: + global clicked, bean_multiplier, beans, scroll + start() + # creating a list of backgrounds, with each index being an object bg = [Background(), Background(), Background()] - # some variables that we need - beanCount = 0 - startingHeight = player.position.y - height = 0 - health = 100 - flapForce = 3 - beanMultiplier = 5 - dead = False - # we need the framerate and then the time - framerate = 60 - last_time = time.time() - splashScreenTimer = 0 - #splash screen - # playing a sound - pygame.mixer.Sound.play(flapfx) - while splashScreenTimer < 100: - dt = time.time() - last_time - dt *= 60 - last_time = time.time() - - splashScreenTimer += dt - - for event in pygame.event.get(): - # if the user clicks the button - if event.type==QUIT: - pygame.quit() - sys.exit() + # startingHeight = 100 (the initial y position of the player) + starting_height = player.position.y + # splash screen + splash_screen_timer = 0 + while splash_screen_timer < 100: + func_one(False) + splash_screen_timer += dt DISPLAY.fill((231, 205, 183)) # fill the start message on the top of the game - startMessage = font_small.render("POLYMARS", True, (171, 145, 123)) - DISPLAY.blit(startMessage, (DISPLAY.get_width()/2 - startMessage.get_width()/2, DISPLAY.get_height()/2 - startMessage.get_height()/2)) - + start_message = font_small.render("POLYMARS", True, (171, 145, 123)) + DISPLAY.blit(start_message, (DISPLAY.get_width()/2 - start_message.get_width() / + 2, DISPLAY.get_height()/2 - start_message.get_height()/2)) # update display - pygame.display.update() + Display.update() + await asyncio.sleep(0) # wait for 10 seconds pygame.time.delay(10) - - titleScreen = True + # title screen - pygame.mixer.Sound.play(flapfx) - while titleScreen: - dt = time.time() - last_time - dt *= 60 - last_time = time.time() - # get the position of the mouse - mouseX,mouseY = pygame.mouse.get_pos() - # getting the keys pressed - clicked = False - keys = pygame.key.get_pressed() - # checking events - for event in pygame.event.get(): - if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: - clicked = True - # if the player quits - if event.type==QUIT: - pygame.quit() - sys.exit() + title_screen = True + Sound.play(flapfx) + while title_screen: + func_one() # so the user clicked, and by any change the mouse's position was on the buttons - if (clicked and checkCollisions(mouseX, mouseY, 3, 3, DISPLAY.get_width()/2 - retry_button.get_width()/2, 288, retry_button.get_width(), retry_button.get_height())): + if (clicked and check_collisions(mouse_x, mouse_y, 3, 3, DISPLAY.get_width()/2 - retry_button.get_width()/2, 288, retry_button.get_width(), retry_button.get_height())): clicked = False - pygame.mixer.Sound.play(upgradefx) - titleScreen = False + title_screen = False + Sound.play(upgradefx) DISPLAY.fill(WHITE) - DISPLAY.blit(title_bg, (0,0)) - DISPLAY.blit(shadow, (0,0)) - DISPLAY.blit(logo, (DISPLAY.get_width()/2 - logo.get_width()/2, DISPLAY.get_height()/2 - logo.get_height()/2 + math.sin(time.time()*5)*5 - 25)) - DISPLAY.blit(retry_button, (DISPLAY.get_width()/2 - retry_button.get_width()/2, 288)) - startMessage = font_small.render("START", True, (0, 0, 0)) - DISPLAY.blit(startMessage, (DISPLAY.get_width()/2 - startMessage.get_width()/2, 292)) - - pygame.display.update() + DISPLAY.blit(title_bg, (0, 0)) + DISPLAY.blit(shadow, (0, 0)) + DISPLAY.blit(logo, (DISPLAY.get_width()/2 - logo.get_width()/2, + DISPLAY.get_height()/2 - logo.get_height()/2 + math.sin(time.time()*5)*5 - 25)) + DISPLAY.blit(retry_button, (DISPLAY.get_width() / + 2 - retry_button.get_width()/2, 288)) + start_message = font_small.render("START", True, (0, 0, 0)) + DISPLAY.blit(start_message, (DISPLAY.get_width() / + 2 - start_message.get_width()/2, 292)) + + Display.update() + await asyncio.sleep(0) pygame.time.delay(10) # the main game loop while True: - dt = time.time() - last_time - dt *= 60 - last_time = time.time() - # again, get the position - mouseX,mouseY = pygame.mouse.get_pos() + func_one() + + cam_offset = -player.position.y + \ + (DISPLAY.get_height() - player.current_sprite.get_size()[1])/2 + if (cam_offset <= 0): + if (not player.dead): + player.kill(deadfx) + scroll = False + cam_offset = 0 - jump = False - clicked = False - keys = pygame.key.get_pressed() - # get events - for event in pygame.event.get(): - if event.type==pygame.KEYDOWN and event.key==K_SPACE: - jump = True - if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: - clicked = True - if clicked and mouseY < DISPLAY.get_height() - 90: - jump = True - if event.type==QUIT: - pygame.quit() - sys.exit() - - camOffset = -player.position.y + DISPLAY.get_height()/2 - player.currentSprite.get_size()[1]/2 - DISPLAY.fill(WHITE) for o in bg: - o.setSprite(((player.position.y/50) % 100) / 100) + o.set_sprite(((player.position.y/50) % 100) / 100) DISPLAY.blit(o.sprite, (0, o.position)) + color = colorsys.hsv_to_rgb( + ((player.position.y/50) % 100) / 100, 0.5, 0.5) + current_height_marker = font.render( + str(player.height), True, (color[0]*255, color[1]*255, color[2]*255, 50)) + DISPLAY.blit(current_height_marker, (DISPLAY.get_width()/2 - current_height_marker.get_width()/2, cam_offset + round( + (player.position.y - starting_height)/DISPLAY.get_height())*DISPLAY.get_height() + player.current_sprite.get_height() - 40)) - color = colorsys.hsv_to_rgb(((player.position.y/50) % 100) / 100,0.5,0.5) - currentHeightMarker = font.render(str(height), True, (color[0]*255, color[1]*255, color[2]*255, 50 )) - DISPLAY.blit(currentHeightMarker, (DISPLAY.get_width()/2 - currentHeightMarker.get_width()/2, camOffset + round((player.position.y - startingHeight)/DISPLAY.get_height())*DISPLAY.get_height() + player.currentSprite.get_height() - 40)) - for bean in beans: - DISPLAY.blit(bean.sprite, (bean.position.x, bean.position.y + camOffset)) - - DISPLAY.blit(pygame.transform.rotate(player.currentSprite, clamp(player.velocity.y, -10, 5)*rotOffset), (player.position.x,player.position.y + camOffset)) + DISPLAY.blit(bean.sprite, (bean.position.x, + bean.position.y + cam_offset)) + + DISPLAY.blit(pygame.transform.rotate(player.current_sprite, clamp( + player.velocity.y, -10, 5)*player.rot_offset), (player.position.x, player.position.y + cam_offset)) DISPLAY.blit(shop_bg, (0, 0)) - pygame.draw.rect(DISPLAY,(81,48,20),(21,437,150*(health/100),25)) + pygame.draw.rect(DISPLAY, (81, 48, 20), + (21, 437, 150*(player.health/100), 25)) DISPLAY.blit(shop, (0, 0)) - + for button in buttons: - DISPLAY.blit(button.sprite, (220 + (buttons.index(button)*125), 393)) - priceDisplay = font_small.render(str(button.price), True, (0,0,0)) - DISPLAY.blit(priceDisplay, (262 + (buttons.index(button)*125), 408)) - levelDisplay = font_20.render('Lvl. ' + str(button.level), True, (200,200,200)) - DISPLAY.blit(levelDisplay, (234 + (buttons.index(button)*125), 441)) - DISPLAY.blit(button.typeIndicatorSprite, (202 + (buttons.index(button)*125), 377)) - beanCountDisplay = font_small.render(str(beanCount).zfill(7), True, (0,0,0)) - DISPLAY.blit(beanCountDisplay, (72, 394)) - if dead: + DISPLAY.blit(button.sprite, (220 + (button.index*125), 393)) + price_display = font_small.render( + str(button.price), True, (0, 0, 0)) + DISPLAY.blit(price_display, (262 + (button.index*125), 408)) + level_display = font_20.render( + f'Lvl. {button.level}', True, (200, 200, 200)) + DISPLAY.blit(level_display, (234 + (button.index*125), 441)) + DISPLAY.blit(button.type_indicator_sprite, + (202 + (button.index*125), 377)) + + bean_count_display = font_small.render( + str(player.bean_count).zfill(7), True, (0, 0, 0)) + DISPLAY.blit(bean_count_display, (72, 394)) + + if player.dead: DISPLAY.blit(retry_button, (4, 4)) - deathMessage = font_small.render("RETRY", True, (0, 0, 0)) - DISPLAY.blit(deathMessage, (24, 8)) - - height = round(-(player.position.y - startingHeight)/DISPLAY.get_height()) - - player.position.x += player.velocity.x*dt - if player.position.x + player.currentSprite.get_size()[0] > 640: - player.velocity.x = -abs(player.velocity.x) - player.currentSprite = player.leftSprite - rotOffset = 5 - if player.position.x < 0: - player.velocity.x = abs(player.velocity.x) - player.currentSprite = player.rightSprite - rotOffset = -5 - if jump and not dead: - player.velocity.y = -flapForce - pygame.mixer.Sound.play(flapfx) - player.position.y += player.velocity.y*dt - player.velocity.y = clamp(player.velocity.y + player.acceleration*dt, -99999999999, 50) - - health -= 0.2*dt - if health <= 0 and not dead: - dead = True - pygame.mixer.Sound.play(deadfx) - + death_message = font_small.render("RETRY", True, (0, 0, 0)) + DISPLAY.blit(death_message, (24, 8)) + + if (scroll): + player.set_height( + round(-(player.position.y - starting_height)/DISPLAY.get_height())) + player.position.x += player.velocity.x*dt + if player.position.x < 0 or player.position.x + player.current_sprite.get_size()[0] > 640: + player.flip() + if jump and not player.dead: + player.velocity.y = -player.flap_force + Sound.play(flapfx) + player.position.y += player.velocity.y*dt + player.velocity.y = clamp( + player.velocity.y + player.acceleration*dt, -99999999999, 50) + + if not player.dead: + player.health -= 0.2*dt + if player.health <= 0: + player.kill(deadfx) for bean in beans: - if bean.position.y + camOffset + 90 > DISPLAY.get_height(): + if bean.position.y + cam_offset + 90 > DISPLAY.get_height(): bean.position.y -= DISPLAY.get_height()*2 - bean.position.x = random.randrange(0, DISPLAY.get_width() - bean.sprite.get_width()) - if (checkCollisions(player.position.x, player.position.y, player.currentSprite.get_width(), player.currentSprite.get_height(), bean.position.x, bean.position.y, bean.sprite.get_width(), bean.sprite.get_height())): - dead = False - pygame.mixer.Sound.play(beanfx) - beanCount += 1 - health = 100 + bean.position.x = random.randrange( + 0, DISPLAY.get_width() - bean.sprite.get_width()) + if (check_collisions(player.position.x, player.position.y, player.current_sprite.get_width(), player.current_sprite.get_height(), bean.position.x, bean.position.y, bean.sprite.get_width(), bean.sprite.get_height())): + Sound.play(beanfx) + player.bean_count += 1 + player.health = 100 bean.position.y -= DISPLAY.get_height() - random.randrange(0, 200) - bean.position.x = random.randrange(0, DISPLAY.get_width() - bean.sprite.get_width()) + bean.position.x = random.randrange( + 0, DISPLAY.get_width() - bean.sprite.get_width()) for button in buttons: - buttonX,buttonY = 220 + (buttons.index(button)*125), 393 - if clicked and not dead and checkCollisions(mouseX, mouseY, 3, 3, buttonX, buttonY, button.sprite.get_width(), button.sprite.get_height()): - if (beanCount >= button.price): - pygame.mixer.Sound.play(upgradefx) + if clicked and not player.dead and check_collisions(mouse_x, mouse_y, 3, 3, button.position.x, button.position.y, button.sprite.get_width(), button.sprite.get_height()): + if (player.bean_count >= button.price): + Sound.play(upgradefx) button.level += 1 - beanCount -= button.price + player.bean_count -= button.price button.price = round(button.price*2.5) - if (buttons.index(button) == 0): - flapForce *= 1.5 - if (buttons.index(button) == 1): + if (button.index == 0): + player.flap_force *= 1.5 + if (button.index == 1): player.velocity.x *= 1.5 - if (buttons.index(button) == 2): - oldBeanMultipler = beanMultiplier - beanMultiplier += 10 - for i in range(beanMultiplier): - beans.append(Bean()) - beans[-1].position.xy = random.randrange(0, DISPLAY.get_width() - bean.sprite.get_width()), player.position.y - DISPLAY.get_height() - random.randrange(0, 200) - - if dead and clicked and checkCollisions(mouseX, mouseY, 3, 3, 4, 4, retry_button.get_width(), retry_button.get_height()): - health = 100 - player.velocity.xy = 3, 0 - player.position.xy = 295, 100 - player.currentSprite = player.rightSprite - beanCount = 0 - height = 0 - flapForce = 3 - beanMultiplier = 5 - buttons = [] - for i in range(3): buttons.append(Button()) - buttons[0].typeIndicatorSprite = pygame.image.load('data/gfx/flap_indicator.png') - buttons[0].price = 5 - buttons[1].typeIndicatorSprite = pygame.image.load('data/gfx/speed_indicator.png') - buttons[1].price = 5 - buttons[2].typeIndicatorSprite = pygame.image.load('data/gfx/beanup_indicator.png') - buttons[2].price = 30 - beans = [] - for i in range(5): beans.append(Bean()) - for bean in beans: - bean.position.xy = random.randrange(0, DISPLAY.get_width() - bean.sprite.get_width()), beans.index(bean)*-200 - player.position.y - pygame.mixer.Sound.play(upgradefx) - dead = False - - - bg[0].position = camOffset + round(player.position.y/DISPLAY.get_height())*DISPLAY.get_height() - bg[1].position = bg[0].position + DISPLAY.get_height() + if (button.index == 2): + bean_multiplier += 5 + for _ in range(bean_multiplier): + beans.append(Bean(random.randrange(0, DISPLAY.get_width() - Bean().sprite.get_width( + )), player.position.y - DISPLAY.get_height() - random.randrange(0, 200))) + + if player.dead and clicked and check_collisions(mouse_x, mouse_y, 3, 3, 4, 4, retry_button.get_width(), retry_button.get_height()): + start() + + bg[0].position = cam_offset + \ + round(player.position.y/DISPLAY.get_height())*DISPLAY.get_height() + bg[1].position = bg[0].position + DISPLAY.get_height() bg[2].position = bg[0].position - DISPLAY.get_height() - - pygame.display.update() + + Display.update() + await asyncio.sleep(0) pygame.time.delay(10) if __name__ == "__main__": - main() + asyncio.run(main()) diff --git a/player.py b/player.py index 3f4f819..b82ca63 100644 --- a/player.py +++ b/player.py @@ -1,11 +1,38 @@ import pygame + class Player: position = pygame.Vector2() - position.xy = 295, 100 velocity = pygame.Vector2() - velocity.xy = 3, 0 - acceleration = 0.1 - rightSprite = pygame.image.load('data/gfx/player.png') - leftSprite = pygame.transform.flip(rightSprite, True, False) - currentSprite = rightSprite \ No newline at end of file + right_sprite = pygame.image.load('data/gfx/player.png') + left_sprite = pygame.transform.flip(right_sprite, True, False) + + def __init__(self): + self.dead = False + self.health = 100 + self.height = 0 + self.position.xy = 295, 100 + self.velocity.xy = 3, 0 + self.acceleration = 0.1 + self.flap_force = 3 + self.bean_count = 0 + self.rot_offset = -5 + self.current_sprite = self.right_sprite + + def reset(self) -> None: + self.__init__() + + def kill(self, sound: str) -> None: + self.dead = True + pygame.mixer.Sound.play(sound) + + def set_height(self, new_height: float) -> None: + self.height = new_height + + def flip(self) -> None: + self.velocity.x *= -1 + self.rot_offset *= -1 + if self.current_sprite == self.right_sprite: + self.current_sprite = self.left_sprite + else: + self.current_sprite = self.right_sprite diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..231dd17 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +pygame \ No newline at end of file diff --git a/utils.py b/utils.py index dad03a7..4967998 100644 --- a/utils.py +++ b/utils.py @@ -1,9 +1,10 @@ -def clamp(value, min, max): - if value < min: - return min - if value > max: - return max +def clamp(value, min_, max_): + if value < min_: + return min_ + if value > max_: + return max_ return value -def checkCollisions(a_x, a_y, a_width, a_height, b_x, b_y, b_width, b_height): + +def check_collisions(a_x, a_y, a_width, a_height, b_x, b_y, b_width, b_height): return (a_x + a_width > b_x) and (a_x < b_x + b_width) and (a_y + a_height > b_y) and (a_y < b_y + b_height)