From 6f8af6474e23dae67c1bfc6c4078285736acf980 Mon Sep 17 00:00:00 2001 From: sparshg <43041139+sparshg@users.noreply.github.com> Date: Tue, 23 Feb 2021 01:42:16 +0530 Subject: [PATCH 01/16] Revert "Platformer Base Created" (#12) --- src/platformer/platformer.py | 72 +++++++----------------------------- 1 file changed, 14 insertions(+), 58 deletions(-) diff --git a/src/platformer/platformer.py b/src/platformer/platformer.py index 56dd980..9f1703f 100644 --- a/src/platformer/platformer.py +++ b/src/platformer/platformer.py @@ -3,52 +3,41 @@ Github repo can be found here: https://github.com/sparshg/pycollab """ - -import pygame as pg from os import environ # Hide pygame Hello prompt environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "1" +import pygame # Declare some constants and variables WIDTH, HEIGHT = (600, 400) FPS = 60 -BLACK = (0 , 0 , 0 ) -WHITE = (255, 255, 255) +WHITE = "#F1F1F1" +BLACK = "#101010" # The main controller class Main: def __init__(self): - pg.init() - pg.display.set_caption("Platformer") + pygame.init() + pygame.display.set_caption("Platformer") + self.win = pygame.display.set_mode((WIDTH, HEIGHT)) self.running = True - self.clock = pg.time.Clock() - self.win = pg.display.set_mode((WIDTH, HEIGHT)) + self.clock = pygame.time.Clock() def check_events(self): - for event in pg.event.get(): - if event.type == pg.QUIT: + for event in pygame.event.get(): + if event.type == pygame.QUIT: main.running = False # Update things def update(self): - player.yVel += physics.gravity - player.y += player.yVel - if player.colliding(): - while player.colliding(): - if player.yVel < 0: - pass - elif player.yVel > 0: - pass - yVel = 0 + pass # Draw things def draw(self): self.win.fill(BLACK) - player.render() - platforms.render() - pg.display.update() + pygame.display.update() # The main loop def loop(self): @@ -57,43 +46,10 @@ def loop(self): self.update() self.draw() self.clock.tick(FPS) - pg.quit() -main = Main() - -class Physics: - def __init__(self): - self.gravity = 2 - self.jumpHeight = 18 - self.friction = 2 - self.acceleration = 4 - - def squareCollision(x1, y1, w1, h1, x2, y2, w2, h2): - return ((x1 + w1 > x2) and ( x1 < x2 + w2)) and ((y1 + h1 > y2) and ( y1 < y2 + h2)) -physics = Physics() - -class Player: - def __init__(self): - self.x = 0 - self.y = 0 - self.xVel = 0 - self.yVel = 0 - - def render(self): - pg.draw.rect(main.win, WHITE, (self.x, self.y, 50, 50)) - - def colliding(self): - pass -player = Player() - -class Platforms: - def __init__(self): - self.platforms = [] + pygame.quit() - def render(self): - for i in range(len(self.platforms)): - pg.draw.rect(main.win, WHITE, (self.platforms[i].x, self.platforms[i].y, 75, 75)) -platforms = Platforms() # Test if the script is directly ran if __name__ == "__main__": - main.loop() + main = Main() + main.loop() \ No newline at end of file From 51e26c08a0a66b12da0207a19f7f1d7c7cb5ccb6 Mon Sep 17 00:00:00 2001 From: MTM828 <71281115+MTM828@users.noreply.github.com> Date: Sat, 27 Feb 2021 08:55:38 +0000 Subject: [PATCH 02/16] Platformer Update (#13) * fix commits * oop stucture improved * oop stucture improved Co-authored-by: sparshg --- src/platformer/platformer.py | 88 +++++++++++++++++++++++++++++------- 1 file changed, 72 insertions(+), 16 deletions(-) diff --git a/src/platformer/platformer.py b/src/platformer/platformer.py index 9f1703f..61dc78b 100644 --- a/src/platformer/platformer.py +++ b/src/platformer/platformer.py @@ -3,53 +3,109 @@ Github repo can be found here: https://github.com/sparshg/pycollab """ + +# Import statements from os import environ # Hide pygame Hello prompt environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "1" -import pygame +import pygame as pg # Declare some constants and variables WIDTH, HEIGHT = (600, 400) FPS = 60 -WHITE = "#F1F1F1" -BLACK = "#101010" +BLACK = (0, 0, 0) +WHITE = (255, 255, 255) # The main controller class Main: def __init__(self): - pygame.init() - pygame.display.set_caption("Platformer") - - self.win = pygame.display.set_mode((WIDTH, HEIGHT)) + pg.init() + pg.display.set_caption("Platformer") self.running = True - self.clock = pygame.time.Clock() + self.clock = pg.time.Clock() + self.win = pg.display.set_mode((WIDTH, HEIGHT)) + + self.player = Player() + self.platforms = Platforms() def check_events(self): - for event in pygame.event.get(): - if event.type == pygame.QUIT: + for event in pg.event.get(): + if event.type == pg.QUIT: main.running = False # Update things def update(self): - pass + self.player.update() # Draw things - def draw(self): + def render(self): self.win.fill(BLACK) - pygame.display.update() + platforms.render() + self.player.render() + pg.display.update() # The main loop def loop(self): while self.running: self.check_events() self.update() - self.draw() + self.render() self.clock.tick(FPS) - pygame.quit() + pg.quit() + + +class Physics: + + gravity = 2 + jumpHeight = 18 + friction = 2 + acceleration = 4 + + @staticmethod + def squareCollision(x1, y1, w1, h1, x2, y2, w2, h2): + return ((x1 + w1 > x2) and (x1 < x2 + w2)) and ( + (y1 + h1 > y2) and (y1 < y2 + h2) + ) + + +class Player: + def __init__(self): + self.x = 0 + self.y = 0 + self.xVel = 0 + self.yVel = 0 + + def colliding(self): + return False + + def update(self): + self.yVel += Physics.gravity + self.y += self.yVel + if self.colliding(): + while self.colliding(): + if self.yVel < 0: + pass + elif self.yVel > 0: + pass + self.yVel = 0 + + def render(self): + pg.draw.rect(main.win, WHITE, (self.x, self.y, 50, 50)) + + +class Platforms: + def __init__(self): + self.platforms = [] + + def render(self): + for i in range(len(self.platforms)): + pg.draw.rect( + main.win, WHITE, (self.platforms[i].x, self.platforms[i].y, 75, 75) + ) # Test if the script is directly ran if __name__ == "__main__": main = Main() - main.loop() \ No newline at end of file + main.loop() From 9a759de7722066657aa110199baa3471c252225e Mon Sep 17 00:00:00 2001 From: MTM828 <71281115+MTM828@users.noreply.github.com> Date: Thu, 4 Mar 2021 17:38:22 +0000 Subject: [PATCH 03/16] Platformer Update (#17) * Update platformer.py * Update platformer.py * black auto format * simplify code Co-authored-by: sparshg --- src/platformer/platformer.py | 113 +++++++++++++++++++++++++---------- 1 file changed, 82 insertions(+), 31 deletions(-) diff --git a/src/platformer/platformer.py b/src/platformer/platformer.py index 61dc78b..6345d17 100644 --- a/src/platformer/platformer.py +++ b/src/platformer/platformer.py @@ -15,6 +15,7 @@ WIDTH, HEIGHT = (600, 400) FPS = 60 BLACK = (0, 0, 0) +GREY = (225 / 2, 225 / 2, 225 / 2) WHITE = (255, 255, 255) # The main controller @@ -25,11 +26,11 @@ def __init__(self): self.running = True self.clock = pg.time.Clock() self.win = pg.display.set_mode((WIDTH, HEIGHT)) - - self.player = Player() self.platforms = Platforms() + self.player = Player() - def check_events(self): + # For key press detection and closing the window properly + def checkEvents(self): for event in pg.event.get(): if event.type == pg.QUIT: main.running = False @@ -41,14 +42,14 @@ def update(self): # Draw things def render(self): self.win.fill(BLACK) - platforms.render() + self.platforms.render() self.player.render() pg.display.update() # The main loop def loop(self): while self.running: - self.check_events() + self.checkEvents() self.update() self.render() self.clock.tick(FPS) @@ -56,53 +57,103 @@ def loop(self): class Physics: + gravity = 0.5 + jumpHeight = -12 + friction = 0.5 + acceleration = 1 + maxXVel = 8 - gravity = 2 - jumpHeight = 18 - friction = 2 - acceleration = 4 - - @staticmethod def squareCollision(x1, y1, w1, h1, x2, y2, w2, h2): - return ((x1 + w1 > x2) and (x1 < x2 + w2)) and ( - (y1 + h1 > y2) and (y1 < y2 + h2) - ) + return x1 + w1 > x2 and x1 < x2 + w2 and y1 + h1 > y2 and y1 < y2 + h2 class Player: def __init__(self): - self.x = 0 - self.y = 0 - self.xVel = 0 - self.yVel = 0 + self.pos = pg.Vector2(250, 300) + self.vel = pg.Vector2(0, 0) def colliding(self): + for platform in main.platforms.rects: + if pg.Rect(self.pos.x, self.pos.y, 50, 50).colliderect(platform): + return True return False def update(self): - self.yVel += Physics.gravity - self.y += self.yVel + # Gravity + keyDown = pg.key.get_pressed() + self.vel.y += Physics.gravity + self.pos.y += self.vel.y if self.colliding(): while self.colliding(): - if self.yVel < 0: - pass - elif self.yVel > 0: - pass - self.yVel = 0 + if self.vel.y < 0: + self.pos.y += 0.5 + elif self.vel.y > 0: + self.pos.y -= 0.5 + if keyDown[pg.K_UP] and self.vel.y > 0: + self.vel.y = Physics.jumpHeight + else: + self.vel.y = Physics.gravity + + # Movement + # Right + + if keyDown[pg.K_RIGHT]: + self.vel.x += Physics.acceleration + if self.vel.x > Physics.maxXVel: + self.vel.x = Physics.maxXVel + + # Left + if keyDown[pg.K_LEFT]: + self.vel.x -= Physics.acceleration + if -self.vel.x > Physics.maxXVel: + self.vel.x = -Physics.maxXVel + + # Apply friction + if self.vel.x > 0: + self.vel.x -= Physics.friction + if self.vel.x < 0: + self.vel.x += Physics.friction + + # Go back to where you were before if you've hit a wall + self.pos.x += self.vel.x + if self.colliding(): + self.pos.x -= self.vel.x + self.vel.x = 0 def render(self): - pg.draw.rect(main.win, WHITE, (self.x, self.y, 50, 50)) + pg.draw.rect(main.win, GREY, (self.pos.x, self.pos.y, 50, 50)) + + +class Platform: + def __init__(self, x, y): + self.x = x + self.y = y class Platforms: def __init__(self): - self.platforms = [] + p = "p" + _ = "_" + + self.rects = [] + self.layout = [ + [p, p, p, p, p, p, p, p, p, p, p, p], + [p, _, _, _, _, _, _, _, _, _, _, p], + [p, _, _, _, _, _, _, _, _, _, _, p], + [p, p, p, _, _, p, _, _, _, _, p, p], + [p, _, _, _, _, _, _, _, _, _, _, p], + [p, _, p, _, _, _, p, p, p, p, _, p], + [p, _, _, _, _, _, _, _, _, _, _, p], + [p, p, p, p, p, p, p, p, p, p, p, p], + ] + for i in range(len(self.layout)): + for j in range(len(self.layout[i])): + if self.layout[i][j] == p: + self.rects.append(pg.Rect(j * 50, i * 50, 50, 50)) def render(self): - for i in range(len(self.platforms)): - pg.draw.rect( - main.win, WHITE, (self.platforms[i].x, self.platforms[i].y, 75, 75) - ) + for rect in self.rects: + pg.draw.rect(main.win, WHITE, rect) # Test if the script is directly ran From 2e5d17bc05d2bbf8fe79ac98f1d4146834c73253 Mon Sep 17 00:00:00 2001 From: sparshg <43041139+sparshg@users.noreply.github.com> Date: Fri, 5 Mar 2021 10:25:48 +0530 Subject: [PATCH 04/16] physics updates (#18) --- src/platformer/platformer.py | 81 +++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 30 deletions(-) diff --git a/src/platformer/platformer.py b/src/platformer/platformer.py index 6345d17..4ea78e8 100644 --- a/src/platformer/platformer.py +++ b/src/platformer/platformer.py @@ -24,10 +24,10 @@ def __init__(self): pg.init() pg.display.set_caption("Platformer") self.running = True - self.clock = pg.time.Clock() self.win = pg.display.set_mode((WIDTH, HEIGHT)) self.platforms = Platforms() self.player = Player() + Physics.clock.tick() # For key press detection and closing the window properly def checkEvents(self): @@ -52,16 +52,19 @@ def loop(self): self.checkEvents() self.update() self.render() - self.clock.tick(FPS) + Physics.dt = Physics.clock.tick(FPS) / 1000 pg.quit() class Physics: - gravity = 0.5 - jumpHeight = -12 - friction = 0.5 - acceleration = 1 - maxXVel = 8 + + clock = pg.time.Clock() + dt = 1 / FPS + gravity = 1800 + jumpHeight = -720 + friction = 1800 + xAcc = 3600 + maxXVel = 480 def squareCollision(x1, y1, w1, h1, x2, y2, w2, h2): return x1 + w1 > x2 and x1 < x2 + w2 and y1 + h1 > y2 and y1 < y2 + h2 @@ -71,6 +74,7 @@ class Player: def __init__(self): self.pos = pg.Vector2(250, 300) self.vel = pg.Vector2(0, 0) + self.onGround = True def colliding(self): for platform in main.platforms.rects: @@ -79,45 +83,62 @@ def colliding(self): return False def update(self): - # Gravity + + # Get keys keyDown = pg.key.get_pressed() - self.vel.y += Physics.gravity - self.pos.y += self.vel.y - if self.colliding(): - while self.colliding(): - if self.vel.y < 0: - self.pos.y += 0.5 - elif self.vel.y > 0: - self.pos.y -= 0.5 - if keyDown[pg.K_UP] and self.vel.y > 0: + + if self.onGround: + if keyDown[pg.K_UP]: self.vel.y = Physics.jumpHeight - else: - self.vel.y = Physics.gravity + self.onGround = False + if not self.colliding(): + self.onGround = False + else: + self.vel.y += Physics.gravity * Physics.dt + self.pos.y += self.vel.y * Physics.dt + + if self.colliding(): + if self.vel.y > 0: + while self.colliding(): + self.pos.y -= 0.5 + self.vel.y = 0 + self.onGround = True + else: + while self.colliding(): + self.pos.y += 0.5 + self.vel.y = Physics.gravity * Physics.dt - # Movement # Right - if keyDown[pg.K_RIGHT]: - self.vel.x += Physics.acceleration + self.vel.x += Physics.xAcc * Physics.dt if self.vel.x > Physics.maxXVel: self.vel.x = Physics.maxXVel # Left if keyDown[pg.K_LEFT]: - self.vel.x -= Physics.acceleration + self.vel.x -= Physics.xAcc * Physics.dt if -self.vel.x > Physics.maxXVel: self.vel.x = -Physics.maxXVel # Apply friction - if self.vel.x > 0: - self.vel.x -= Physics.friction + # If friction starts moving block in opposite direction instead of stopping, set vel to 0 if self.vel.x < 0: - self.vel.x += Physics.friction - - # Go back to where you were before if you've hit a wall - self.pos.x += self.vel.x + self.vel.x += Physics.friction * Physics.dt + if self.vel.x > 0: + self.vel.x = 0 + elif self.vel.x > 0: + self.vel.x -= Physics.friction * Physics.dt + if self.vel.x < 0: + self.vel.x = 0 + + # Wall collision + self.pos.x += self.vel.x * Physics.dt if self.colliding(): - self.pos.x -= self.vel.x + while self.colliding(): + if self.vel.x > 0: + self.pos.x -= 0.5 + else: + self.pos.x += 0.5 self.vel.x = 0 def render(self): From 42b96967e38bb38757697101eaff3bf533cc9301 Mon Sep 17 00:00:00 2001 From: sparshg Date: Sun, 7 Mar 2021 01:03:02 +0530 Subject: [PATCH 05/16] gravity --- src/gravity/gravity.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/gravity/gravity.py diff --git a/src/gravity/gravity.py b/src/gravity/gravity.py new file mode 100644 index 0000000..e69de29 From e3eb48ef51104b966dc9326fbbc48a276ed4b542 Mon Sep 17 00:00:00 2001 From: sparshg Date: Sun, 7 Mar 2021 01:33:48 +0530 Subject: [PATCH 06/16] initial commit --- src/gravity/gravity.py | 53 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/gravity/gravity.py b/src/gravity/gravity.py index e69de29..a79a84f 100644 --- a/src/gravity/gravity.py +++ b/src/gravity/gravity.py @@ -0,0 +1,53 @@ +#!/usr/bin/python +""" +Github repo can be found here: +https://github.com/sparshg/pycollab +""" + +import pygame as pg +import sys + +# Declare some constants and variables +WIDTH, HEIGHT = (1248, 702) +FPS = 60 +BLACK = "#000000" + +# The main controller +class Main: + def __init__(self): + pg.init() + pg.display.set_caption("gravity") + self.win = pg.display.set_mode((WIDTH, HEIGHT)) + self.clock = pg.time.Clock() + self.running = True + + # For key press detection and closing the window properly + def checkEvents(self): + for event in pg.event.get(): + if event.type == pg.QUIT: + self.running = False + + # Update things + def update(self): + pass + + # Draw things + def render(self): + self.win.fill(BLACK) + pg.display.update() + + # The main loop + def loop(self): + while self.running: + self.dt = self.clock.tick(FPS) / 1000 + self.checkEvents() + self.update() + self.render() + pg.quit() + sys.exit() + + +# Test if the script is directly ran +if __name__ == "__main__": + main = Main() + main.loop() From 7642b086e78f5d8a6ce3caa383e50dbfabfe0c3b Mon Sep 17 00:00:00 2001 From: sparshg <43041139+sparshg@users.noreply.github.com> Date: Mon, 8 Mar 2021 02:07:54 +0530 Subject: [PATCH 07/16] Make gravity game structure (#19) * gravity scripts * tune values * change naming --- .gitignore | 1 - .vscode/settings.json | 10 ++++++++++ src/gravity/constants.py | 5 +++++ src/gravity/{gravity.py => main.py} | 17 +++++++++-------- src/gravity/planet.py | 25 +++++++++++++++++++++++++ src/gravity/universe.py | 21 +++++++++++++++++++++ 6 files changed, 70 insertions(+), 9 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 src/gravity/constants.py rename src/gravity/{gravity.py => main.py} (78%) create mode 100644 src/gravity/planet.py create mode 100644 src/gravity/universe.py diff --git a/.gitignore b/.gitignore index 2ab793b..b6e4761 100644 --- a/.gitignore +++ b/.gitignore @@ -127,4 +127,3 @@ dmypy.json # Pyre type checker .pyre/ -.vscode diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..2df6430 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + "python.analysis.extraPaths": [ + "./src/gravity" + ], + "python.linting.pylintArgs": [ + "--disable=all", + "--enable=F,E,unreachable,duplicate-key,unnecessary-semicolon,global-variable-not-assigned,unused-variable,binary-op-exception,bad-format-string,anomalous-backslash-in-string,bad-open-mode", + "--extension-pkg-whitelist=pygame" + ] +} \ No newline at end of file diff --git a/src/gravity/constants.py b/src/gravity/constants.py new file mode 100644 index 0000000..4c8e04c --- /dev/null +++ b/src/gravity/constants.py @@ -0,0 +1,5 @@ +WIDTH, HEIGHT = (1248, 702) +FPS = 60 +BLACK = "#000000" +WHITE = "#FFFFFF" +G = 100000 # Gravitational constant diff --git a/src/gravity/gravity.py b/src/gravity/main.py similarity index 78% rename from src/gravity/gravity.py rename to src/gravity/main.py index a79a84f..69cc9b0 100644 --- a/src/gravity/gravity.py +++ b/src/gravity/main.py @@ -6,11 +6,9 @@ import pygame as pg import sys +from universe import Universe +from constants import * -# Declare some constants and variables -WIDTH, HEIGHT = (1248, 702) -FPS = 60 -BLACK = "#000000" # The main controller class Main: @@ -21,6 +19,8 @@ def __init__(self): self.clock = pg.time.Clock() self.running = True + self.universe = Universe() + # For key press detection and closing the window properly def checkEvents(self): for event in pg.event.get(): @@ -28,20 +28,21 @@ def checkEvents(self): self.running = False # Update things - def update(self): - pass + def update(self, dt): + self.universe.update(dt) # Draw things def render(self): self.win.fill(BLACK) + self.universe.render(self.win) pg.display.update() # The main loop def loop(self): while self.running: - self.dt = self.clock.tick(FPS) / 1000 + dt = self.clock.tick(FPS) / 1000 self.checkEvents() - self.update() + self.update(dt) self.render() pg.quit() sys.exit() diff --git a/src/gravity/planet.py b/src/gravity/planet.py new file mode 100644 index 0000000..474aa86 --- /dev/null +++ b/src/gravity/planet.py @@ -0,0 +1,25 @@ +import pygame as pg +from constants import * + + +class Planet: + def __init__(self, mass, radius, pos=(WIDTH / 2, HEIGHT / 2), vel=(0, 0)): + self.mass = mass + self.radius = radius + self.pos = pg.Vector2(pos) + self.vel = pg.Vector2(vel) + + def calcUpdate(self, planets): + self.field = pg.Vector2(0, 0) + for planet in planets: + r = planet.pos - self.pos + mag = r.magnitude() + if mag != 0: + self.field += G * planet.mass * r * mag ** -3 + + def applyUpdate(self, dt): + self.vel += self.field * dt + self.pos += self.vel * dt + + def render(self, surf): + pg.draw.circle(surf, WHITE, self.pos, self.radius) \ No newline at end of file diff --git a/src/gravity/universe.py b/src/gravity/universe.py new file mode 100644 index 0000000..cfa173c --- /dev/null +++ b/src/gravity/universe.py @@ -0,0 +1,21 @@ +import pygame as pg +from planet import Planet +from constants import * + + +class Universe: + def __init__(self): + self.planets = [ + Planet(10, 10, (WIDTH / 2 - 100, HEIGHT / 2), (0, 50)), + Planet(10, 10, (WIDTH / 2 + 100, HEIGHT / 2), (0, -50)), + ] + + def update(self, dt): + for planet in self.planets: + planet.calcUpdate(self.planets) + for planet in self.planets: + planet.applyUpdate(dt) + + def render(self, surf): + for planet in self.planets: + planet.render(surf) From 8e59a1f0750f79a99041cd53f96277f903702181 Mon Sep 17 00:00:00 2001 From: MTM828 <71281115+MTM828@users.noreply.github.com> Date: Sun, 2 May 2021 07:56:19 +0100 Subject: [PATCH 08/16] Split files and add trails (#22) --- .vscode/settings.json | 3 +- src/gravity/constants.py | 1 + src/gravity/main.py | 4 +- src/gravity/planet.py | 7 ++ src/platformer/constants.py | 7 ++ src/platformer/{platformer.py => main.py} | 52 +++++++------- src/platformer/physics.py | 16 +++++ src/tictactoe/constants.py | 7 ++ src/tictactoe/{tictactoe.py => main.py} | 86 ++++++++++------------- 9 files changed, 108 insertions(+), 75 deletions(-) create mode 100644 src/platformer/constants.py rename src/platformer/{platformer.py => main.py} (80%) create mode 100644 src/platformer/physics.py create mode 100644 src/tictactoe/constants.py rename src/tictactoe/{tictactoe.py => main.py} (79%) mode change 100755 => 100644 diff --git a/.vscode/settings.json b/.vscode/settings.json index 2df6430..b4268dd 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,5 +6,6 @@ "--disable=all", "--enable=F,E,unreachable,duplicate-key,unnecessary-semicolon,global-variable-not-assigned,unused-variable,binary-op-exception,bad-format-string,anomalous-backslash-in-string,bad-open-mode", "--extension-pkg-whitelist=pygame" - ] + ], + "python.formatting.provider": "black" } \ No newline at end of file diff --git a/src/gravity/constants.py b/src/gravity/constants.py index 4c8e04c..12dd174 100644 --- a/src/gravity/constants.py +++ b/src/gravity/constants.py @@ -1,5 +1,6 @@ WIDTH, HEIGHT = (1248, 702) FPS = 60 BLACK = "#000000" +GREY = "#808080" WHITE = "#FFFFFF" G = 100000 # Gravitational constant diff --git a/src/gravity/main.py b/src/gravity/main.py index 69cc9b0..332769d 100644 --- a/src/gravity/main.py +++ b/src/gravity/main.py @@ -1,7 +1,7 @@ #!/usr/bin/python """ Github repo can be found here: -https://github.com/sparshg/pycollab +https://github.com/sparshg/py-games """ import pygame as pg @@ -21,7 +21,7 @@ def __init__(self): self.universe = Universe() - # For key press detection and closing the window properly + # Key press and close button functionality def checkEvents(self): for event in pg.event.get(): if event.type == pg.QUIT: diff --git a/src/gravity/planet.py b/src/gravity/planet.py index 474aa86..2d8657b 100644 --- a/src/gravity/planet.py +++ b/src/gravity/planet.py @@ -8,6 +8,7 @@ def __init__(self, mass, radius, pos=(WIDTH / 2, HEIGHT / 2), vel=(0, 0)): self.radius = radius self.pos = pg.Vector2(pos) self.vel = pg.Vector2(vel) + self.prevPositions = [] def calcUpdate(self, planets): self.field = pg.Vector2(0, 0) @@ -18,8 +19,14 @@ def calcUpdate(self, planets): self.field += G * planet.mass * r * mag ** -3 def applyUpdate(self, dt): + self.prevPositions.append((self.pos.x, self.pos.y)) + if len(self.prevPositions) > 100: + self.prevPositions.pop(0) + self.vel += self.field * dt self.pos += self.vel * dt def render(self, surf): + for i in range(len(self.prevPositions)): + pg.draw.circle(surf, GREY, self.prevPositions[len(self.prevPositions) - i - 1], self.radius - i/self.radius) pg.draw.circle(surf, WHITE, self.pos, self.radius) \ No newline at end of file diff --git a/src/platformer/constants.py b/src/platformer/constants.py new file mode 100644 index 0000000..4d370fb --- /dev/null +++ b/src/platformer/constants.py @@ -0,0 +1,7 @@ +# Declare some constants and variables +WIDTH, HEIGHT = (600, 400) +FPS = 60 +BLACK = "#000000" +WHITE = "#FFFFFF" +ORANGE = "#FF6600" +RED = "#FF1F00" diff --git a/src/platformer/platformer.py b/src/platformer/main.py similarity index 80% rename from src/platformer/platformer.py rename to src/platformer/main.py index 4ea78e8..1388009 100644 --- a/src/platformer/platformer.py +++ b/src/platformer/main.py @@ -1,7 +1,7 @@ #!/usr/bin/python """ Github repo can be found here: -https://github.com/sparshg/pycollab +https://github.com/sparshg/py-games """ # Import statements @@ -11,12 +11,9 @@ environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "1" import pygame as pg -# Declare some constants and variables -WIDTH, HEIGHT = (600, 400) -FPS = 60 -BLACK = (0, 0, 0) -GREY = (225 / 2, 225 / 2, 225 / 2) -WHITE = (255, 255, 255) +import sys +from constants import * +from physics import Physics # The main controller class Main: @@ -29,7 +26,7 @@ def __init__(self): self.player = Player() Physics.clock.tick() - # For key press detection and closing the window properly + # For key press and close button functionality def checkEvents(self): for event in pg.event.get(): if event.type == pg.QUIT: @@ -54,20 +51,7 @@ def loop(self): self.render() Physics.dt = Physics.clock.tick(FPS) / 1000 pg.quit() - - -class Physics: - - clock = pg.time.Clock() - dt = 1 / FPS - gravity = 1800 - jumpHeight = -720 - friction = 1800 - xAcc = 3600 - maxXVel = 480 - - def squareCollision(x1, y1, w1, h1, x2, y2, w2, h2): - return x1 + w1 > x2 and x1 < x2 + w2 and y1 + h1 > y2 and y1 < y2 + h2 + sys.exit() class Player: @@ -75,10 +59,13 @@ def __init__(self): self.pos = pg.Vector2(250, 300) self.vel = pg.Vector2(0, 0) self.onGround = True + self.prevPositions = [] + self.width = 40 + self.height = 40 def colliding(self): for platform in main.platforms.rects: - if pg.Rect(self.pos.x, self.pos.y, 50, 50).colliderect(platform): + if pg.Rect(self.pos.x, self.pos.y, self.width, self.height).colliderect(platform): return True return False @@ -141,8 +128,24 @@ def update(self): self.pos.x += 0.5 self.vel.x = 0 + # Trail + self.prevPositions.append(pg.Vector2(self.pos.x, self.pos.y)) + if len(self.prevPositions) > self.width/2: + self.prevPositions.pop(0) + def render(self): - pg.draw.rect(main.win, GREY, (self.pos.x, self.pos.y, 50, 50)) + + # Ren trail + for i in range(len(self.prevPositions)): + pg.draw.rect(main.win, ORANGE, ( + self.prevPositions[len(self.prevPositions) - i - 1].x - (self.width-i*2)/2 + self.width/2, + self.prevPositions[len(self.prevPositions) - i - 1].y - (self.height-i*2)/2 + self.height/2, + self.width - i*2, + self.height - i*2 + )) + + # Ren player + pg.draw.rect(main.win, RED, (self.pos.x, self.pos.y, self.width, self.height)) class Platform: @@ -155,7 +158,6 @@ class Platforms: def __init__(self): p = "p" _ = "_" - self.rects = [] self.layout = [ [p, p, p, p, p, p, p, p, p, p, p, p], diff --git a/src/platformer/physics.py b/src/platformer/physics.py new file mode 100644 index 0000000..07e269c --- /dev/null +++ b/src/platformer/physics.py @@ -0,0 +1,16 @@ +import pygame as pg +from constants import * + + +class Physics: + + clock = pg.time.Clock() + dt = 1 / FPS + gravity = 1800 + jumpHeight = -720 + friction = 1800 + xAcc = 3600 + maxXVel = 480 + + def squareCollision(x1, y1, w1, h1, x2, y2, w2, h2): + return x1 + w1 > x2 and x1 < x2 + w2 and y1 + h1 > y2 and y1 < y2 + h2 diff --git a/src/tictactoe/constants.py b/src/tictactoe/constants.py new file mode 100644 index 0000000..2830ea8 --- /dev/null +++ b/src/tictactoe/constants.py @@ -0,0 +1,7 @@ +# Declare some constants and variables +WIDTH, HEIGHT = (600, 400) +FPS = 60 +WHITE = "#F1F1F1" +BLACK = "#101010" +ORANGE = "#FF6600" +RED = "#FF1F00" \ No newline at end of file diff --git a/src/tictactoe/tictactoe.py b/src/tictactoe/main.py old mode 100755 new mode 100644 similarity index 79% rename from src/tictactoe/tictactoe.py rename to src/tictactoe/main.py index 21d2150..82302bd --- a/src/tictactoe/tictactoe.py +++ b/src/tictactoe/main.py @@ -1,23 +1,17 @@ #!/usr/bin/python """ Github repo can be found here: -https://github.com/sparshg/pycollab +https://github.com/sparshg/py-games """ + +# Import statements from os import environ -import math # Hide pygame Hello prompt environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "1" -import pygame -from pygame.math import Vector2 +import pygame as pg -# Declare some constants and variables -WIDTH, HEIGHT = (600, 400) -FPS = 60 -WHITE = "#F1F1F1" -BLACK = "#101010" -ORANGE = "#FF6600" -RED = "#FF1F00" +from constants import * class Frame: @@ -41,7 +35,7 @@ def __init__(self, gap=110): for i in range(3): for j in range(3): self.rects.append( - pygame.Rect((-1.5 + 1 * j) * gap, (1.5 - 1 * i) * gap, gap, gap) + pg.Rect((-1.5 + 1 * j) * gap, (1.5 - 1 * i) * gap, gap, gap) ) self.rects = self.cartesian_to_standard(self.rects) @@ -84,7 +78,7 @@ def reset(): if n is not None: n.wait_and_remove = True n.remove_time = ( - 2 * n.blink_count * n.blink_dur + pygame.time.get_ticks() + 2 * n.blink_count * n.blink_dur + pg.time.get_ticks() ) def check(sum, i, j): @@ -99,7 +93,7 @@ def check(sum, i, j): if j is None: j = t self.moves[i][j].blink = True - self.moves[i][j].blink_start = pygame.time.get_ticks() + self.moves[i][j].blink_start = pg.time.get_ticks() i, j = prev reset() @@ -123,7 +117,7 @@ def check(sum, i, j): def setup_remove(self, dur=500, animate=False): if not self.remove: self.remove = True - self.remove_time = pygame.time.get_ticks() + dur + self.remove_time = pg.time.get_ticks() + dur if animate: for i in self.animations: i.setup_remove(dur) @@ -136,7 +130,7 @@ def draw(self): if move is not None: move.draw() if self.remove: - if pygame.time.get_ticks() > self.remove_time: + if pg.time.get_ticks() > self.remove_time: main.reset() @@ -158,10 +152,10 @@ def __init__(self, _type, center): def draw(self): if self.blink: - if pygame.time.get_ticks() < self.blink_start + self.blink_dur: + if pg.time.get_ticks() < self.blink_start + self.blink_dur: self.animation.update() - elif pygame.time.get_ticks() > self.blink_start + 2 * self.blink_dur: - self.blink_start = pygame.time.get_ticks() + elif pg.time.get_ticks() > self.blink_start + 2 * self.blink_dur: + self.blink_start = pg.time.get_ticks() self.blink_count -= 1 if self.blink_count == 0: self.blink = False @@ -169,7 +163,7 @@ def draw(self): self.animation.update() if self.wait_and_remove: - if pygame.time.get_ticks() > self.remove_time: + if pg.time.get_ticks() > self.remove_time: self.animation.setup_remove() main.frame.setup_remove() self.wait_and_remove = False @@ -191,7 +185,7 @@ def __init__(self, dur=500, color=WHITE, fn=EASE_OUT_QUART): self.function = fn self.remove = False self.dur = dur - self.start_time = pygame.time.get_ticks() + self.start_time = pg.time.get_ticks() self.final_time = self.start_time + dur self.type = None self.sub_animations = None @@ -200,8 +194,8 @@ def line(self, p1, p2, width=8): self.type = "line" self.finished = False self.width = width - self.p1 = Vector2(p1) - self.p2 = Vector2(p2) + self.p1 = pg.Vector2(p1) + self.p2 = pg.Vector2(p2) self.p = self.p2 - self.p1 self.length = self.p.magnitude() return self @@ -212,9 +206,9 @@ def circle(self, center=[WIDTH / 2, HEIGHT / 2], radius=38, width=8): self.width = width self.radius = radius self.r = radius - self.center = Vector2(center) - self.rect = pygame.Rect( - (center - Vector2(radius, radius)), (2 * radius, 2 * radius) + self.center = pg.Vector2(center) + self.rect = pg.Rect( + (center - pg.Vector2(radius, radius)), (2 * radius, 2 * radius) ) return self @@ -222,12 +216,12 @@ def cross(self, center=[WIDTH / 2, HEIGHT / 2], length=40, width=10): self.type = "cross" # fmt: off points = [ - Vector2(-length, 0), Vector2(length, 0), - Vector2(0, length), Vector2(0, -length) + pg.Vector2(-length, 0), pg.Vector2(length, 0), + pg.Vector2(0, length), pg.Vector2(0, -length) ] # fmt: on for point in points: - point.update(point.rotate(45) + Vector2(center)) + point.update(point.rotate(45) + pg.Vector2(center)) self.sub_animations = [ Animate(self.dur + i * 150, self.color, self.function).line( @@ -241,7 +235,7 @@ def setup_remove(self, dur=500): self.finished = True self.remove = True self.dur = dur - self.start_time = pygame.time.get_ticks() + self.start_time = pg.time.get_ticks() self.final_time = self.start_time + self.dur if self.sub_animations is not None: for i in self.sub_animations: @@ -257,8 +251,8 @@ def update(self, skip=False): # Calculate the animation if not self.finished or self.remove: - if pygame.time.get_ticks() < self.final_time and not skip: - fraction = (pygame.time.get_ticks() - self.start_time) / self.dur + if pg.time.get_ticks() < self.final_time and not skip: + fraction = (pg.time.get_ticks() - self.start_time) / self.dur if fraction < 0.01: fraction += 0.008 @@ -283,37 +277,35 @@ def update(self, skip=False): # Draw stuff if self.type == "line": - pygame.draw.line( - main.win, self.color, self.p1, self.p + self.p1, self.width - ) + pg.draw.line(main.win, self.color, self.p1, self.p + self.p1, self.width) elif self.type == "circle": - pygame.draw.circle(main.win, self.color, self.center, self.radius) - pygame.draw.circle(main.win, BLACK, self.center, self.r) + pg.draw.circle(main.win, self.color, self.center, self.radius) + pg.draw.circle(main.win, BLACK, self.center, self.r) # The main controller class Main: def __init__(self): - pygame.init() - pygame.display.set_caption("Tic-Tac-Toe") + pg.init() + pg.display.set_caption("Tic-Tac-Toe") - self.win = pygame.display.set_mode((WIDTH, HEIGHT)) + self.win = pg.display.set_mode((WIDTH, HEIGHT)) self.running = True self.frame = Frame() - self.clock = pygame.time.Clock() + self.clock = pg.time.Clock() def check_events(self): - for event in pygame.event.get(): - if event.type == pygame.QUIT: + for event in pg.event.get(): + if event.type == pg.QUIT: main.running = False - if event.type == pygame.MOUSEBUTTONUP: - self.frame.detect_click(pygame.mouse.get_pos()) + if event.type == pg.MOUSEBUTTONUP: + self.frame.detect_click(pg.mouse.get_pos()) def draw(self): self.win.fill(BLACK) self.frame.draw() - pygame.display.update() + pg.display.update() def reset(self): self.frame = Frame() @@ -324,7 +316,7 @@ def loop(self): self.check_events() self.draw() self.clock.tick(FPS) - pygame.quit() + pg.quit() # Test if the script is directly ran From 4821f8966a5e49ad7a7f6701ccda57b5b417e8f4 Mon Sep 17 00:00:00 2001 From: MTM828 Date: Fri, 13 Aug 2021 16:21:41 +0300 Subject: [PATCH 09/16] Platformer update Added a live background, a level editor, corrected function names, and improved previously written code (split more files, made simplifications, added more comments, etc.). --- .vscode/settings.json | 5 +- src/platformer/constants.py | 11 +- src/platformer/level.json | 1 + src/platformer/level_creator/constants.py | 13 + src/platformer/level_creator/file_editor.py | 27 ++ src/platformer/level_creator/main.py | 304 ++++++++++++++++++++ src/platformer/level_creator/scrolling.py | 18 ++ src/platformer/main.py | 196 ++++++++++--- src/platformer/physics.py | 9 +- src/platformer/read_level.py | 12 + 10 files changed, 553 insertions(+), 43 deletions(-) create mode 100644 src/platformer/level.json create mode 100644 src/platformer/level_creator/constants.py create mode 100644 src/platformer/level_creator/file_editor.py create mode 100644 src/platformer/level_creator/main.py create mode 100644 src/platformer/level_creator/scrolling.py create mode 100644 src/platformer/read_level.py diff --git a/.vscode/settings.json b/.vscode/settings.json index b4268dd..16f3447 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,9 @@ { "python.analysis.extraPaths": [ - "./src/gravity" + "./src/gravity", + "./src/platformer", + "./src/platformer/level_creator", + "./src/tictactoe" ], "python.linting.pylintArgs": [ "--disable=all", diff --git a/src/platformer/constants.py b/src/platformer/constants.py index 4d370fb..153a715 100644 --- a/src/platformer/constants.py +++ b/src/platformer/constants.py @@ -1,7 +1,10 @@ # Declare some constants and variables + WIDTH, HEIGHT = (600, 400) FPS = 60 -BLACK = "#000000" -WHITE = "#FFFFFF" -ORANGE = "#FF6600" -RED = "#FF1F00" +BLACK = "#000000" +WHITE = "#FFFFFF" +ORANGE = "#FF6600" +RED = "#FF1F00" +PURPLE = "#800080" +DARKPURPLE = "#301934" diff --git a/src/platformer/level.json b/src/platformer/level.json new file mode 100644 index 0000000..9593b89 --- /dev/null +++ b/src/platformer/level.json @@ -0,0 +1 @@ +{"level":[["ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground","ground"],["ground",null,null,null,"ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground",null,null,null,null,null,null,"ground",null,null,"ground",null,"ground",null,null,"ground","ground","ground",null,null,null,null,null,"ground"],["ground",null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground",null,null,null,"ground"],["ground",null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,"ground",null,null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground"],["ground","ground",null,null,null,null,null,null,null,"ground","ground","ground","ground",null,null,"ground","ground",null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground"],["ground",null,"ground",null,null,null,"ground","ground","ground",null,null,null,null,null,null,null,null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground"],["ground",null,null,null,null,null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground"],["ground",null,null,"ground","ground",null,null,null,"ground",null,null,null,null,null,null,"ground","ground","ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground"],["ground",null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,"ground","ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground"],["ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground"]]} diff --git a/src/platformer/level_creator/constants.py b/src/platformer/level_creator/constants.py new file mode 100644 index 0000000..8e502a0 --- /dev/null +++ b/src/platformer/level_creator/constants.py @@ -0,0 +1,13 @@ +# Declare some constants and variables + +WIDTH, HEIGHT = (800, 600) +FPS = 60 +BLACK = "#000000" +DARKGRAY = "#404040" +GRAY = "#808080" +LIGHTGRAY = "#d3d3d3" +WHITE = "#FFFFFF" +ORANGE = "#FF6600" +RED = "#FF1F00" +PURPLE = "#800080" +DARKPURPLE = "#301934" diff --git a/src/platformer/level_creator/file_editor.py b/src/platformer/level_creator/file_editor.py new file mode 100644 index 0000000..a6b74da --- /dev/null +++ b/src/platformer/level_creator/file_editor.py @@ -0,0 +1,27 @@ +# JSON level reader + +import json, os + +# Read level +def read_level(): + # Open file from full path (just in case the script is being ran from somewhere other than py-games/src/platformer/level_creator) + file = open(os.path.dirname(os.path.abspath(__file__)) + "\..\level.json", "r") + # Python dict + try: + data = json.load(file) + except Exception: + print("Couldn't read level, data could be corrupted.") + # Close file + file.close() + # Return Python list + return data["level"] + + +# Write level +def write_level(data): + # Same as above... + file = open(os.path.dirname(os.path.abspath(__file__)) + "\..\level.json", "w") + # Write over file + file.write('{"level":' + json.dumps(data, separators=(",", ":")) + "}\n") + # Close file + file.close() diff --git a/src/platformer/level_creator/main.py b/src/platformer/level_creator/main.py new file mode 100644 index 0000000..a42acda --- /dev/null +++ b/src/platformer/level_creator/main.py @@ -0,0 +1,304 @@ +#!/usr/bin/python +""" +Github repo can be found here: +https://github.com/sparshg/py-games +""" + +# Import statements +from os import environ + +# Hide pygame Hello prompt +environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "1" +import pygame as pg + +import sys +from constants import * +from file_editor import * +from scrolling import * + +mouseDown = False +scrollX = 0 +scrollY = 0 +scrollVel = 1 +blockSize = 50 + +# The main controller +class Main: + def __init__(self): + pg.init() + pg.display.set_caption("Platformer Level Creator") + self.running = True + self.win = pg.display.set_mode((WIDTH, HEIGHT)) + self.menuBar = MenuBar() + self.selectedBlock = SelectedBlock() + self.platforms = Platforms() + + # For key press and close button functionality + def check_events(self): + global mouseDown + for event in pg.event.get(): + if event.type == pg.QUIT: + self.running = False + if event.type == pg.MOUSEBUTTONUP: + mouseDown = True + + # Update things + def update(self): + global scrollX, scrollY + self.menuBar.update() + self.selectedBlock.update() + scrollX = get_scroll_pos()[0] + scrollY = get_scroll_pos()[1] + keys = pg.key.get_pressed() + # Save on CTRL + S + if keys[pg.K_s] and (keys[pg.K_LCTRL] or keys[pg.K_RCTRL]): + write_level(main.platforms.platforms) + + # Draw things + def render(self): + self.win.fill(BLACK) + self.platforms.render() + self.menuBar.render() + self.selectedBlock.render() + pg.display.update() + + # The main loop + def loop(self): + global mouseDown + while self.running: + self.check_events() + self.update() + self.render() + mouseDown = False + pg.quit() + sys.exit() + + +# Menu bar buttons +class MenuButton: + def __init__(self, renFun, side, id): + self.renFun = renFun + self.side = side + self.id = id + + +# Button 1 (ground) +def ren_btn1(x, y): + pg.draw.rect( + main.win, + DARKPURPLE, + ( + x + main.menuBar.height / 4, + y + main.menuBar.height / 4, + main.menuBar.height / 2, + main.menuBar.height / 2, + ), + ) + + +btn1 = MenuButton(ren_btn1, "lt", "ground") + + +# Button 2 (air/clear) +def ren_btn2(x, y): + # Draw red X + pg.draw.line( + main.win, + RED, + (x + main.menuBar.height / 4, y + main.menuBar.height / 4), + ( + x + main.menuBar.height - main.menuBar.height / 4, + y + main.menuBar.height - main.menuBar.height / 4, + ), + 10, + ) + pg.draw.line( + main.win, + RED, + ( + x + main.menuBar.height - main.menuBar.height / 4, + y + main.menuBar.height / 4, + ), + ( + x + main.menuBar.height / 4, + y + main.menuBar.height - main.menuBar.height / 4, + ), + 10, + ) + + +btn2 = MenuButton(ren_btn2, "lt", None) + + +# Button 3 (the save button) +def ren_btn3(x, y): + font = pg.font.SysFont("Segoe UI", 25) + surf = font.render("Save", 1, BLACK) + main.win.blit( + surf, + ( + x + main.menuBar.height / 2 - font.size("Save")[0] / 2, + y + main.menuBar.height / 2 - font.size("Save")[1] / 2, + ), + ) + + +btn3 = MenuButton(ren_btn3, "rt", "SAVE") + + +# Menu bar +class MenuBar: + def __init__(self): + global scrollY + self.width = WIDTH + self.height = 75 + + self.buttonClicked = None + self.buttons = [btn1, btn2, btn3] + + # Update bar + def update(self): + if self.buttonClicked != None: + main.selectedBlock.quit_selection() + main.selectedBlock.select_block(self.buttons[self.buttonClicked].id) + self.buttonClicked = None + + # Draw bar + def render(self): + # Current X + ltX = 0 + rtX = self.width - self.height + # Background + pg.draw.rect(main.win, LIGHTGRAY, (0, 0, self.width, self.height)) + # Buttons + for i in range(len(self.buttons)): + # If on right side + if self.buttons[i].side == "lt": + if pg.Rect(ltX, 0, self.height, self.height).collidepoint( + pg.mouse.get_pos() + ): + if pg.mouse.get_pressed()[0]: + pg.draw.rect( + main.win, DARKGRAY, (ltX, 0, self.height, self.height) + ) + else: + pg.draw.rect(main.win, GRAY, (ltX, 0, self.height, self.height)) + if mouseDown: + self.buttonClicked = i + self.buttons[i].renFun(ltX, 0) + ltX += self.height + # if on left side + elif self.buttons[i].side == "rt": + if pg.Rect(rtX, 0, self.height, self.height).collidepoint( + pg.mouse.get_pos() + ): + if pg.mouse.get_pressed()[0]: + pg.draw.rect( + main.win, DARKGRAY, (rtX, 0, self.height, self.height) + ) + else: + pg.draw.rect(main.win, GRAY, (rtX, 0, self.height, self.height)) + if mouseDown: + self.buttonClicked = i + self.buttons[i].renFun(rtX, 0) + rtX -= self.height + + +# Block in hand +class SelectedBlock: + def __init__(self): + self.shown = False + self.blockId = False + + # Begin selection + def select_block(self, id): + self.quit_selection() + if id != "SAVE": + self.blockId = id + self.shown = True + else: + # Save level + write_level(main.platforms.platforms) + + # Drop item in hand + def quit_selection(self): + self.blockId = False + self.shown = False + + # Place block in desired location + def place_block(self): + global scrollX, scrollY + # Collumn + y = (pg.mouse.get_pos()[1] + scrollY) // blockSize + # Cell + x = (pg.mouse.get_pos()[0] + scrollX) // blockSize + # Check if tile exists + def place(): + if y < len(main.platforms.platforms): + if x < len(main.platforms.platforms[y]): + main.platforms.platforms[y][x] = self.blockId + else: + for i in range(x - len(main.platforms.platforms[y])): + main.platforms.platforms[y].append(None) + main.platforms.platforms[y].insert(x, self.blockId) + else: + for i in range(y - len(main.platforms.platforms)): + main.platforms.platforms.append( + [None] * len(main.platforms.platforms) + ) + row = [None] * len(main.platforms.platforms[y - 1]) + row[x] = self.blockId + main.platforms.platforms.append(row) + + place() + # If pressing SHIFT key, don't unselect + if ( + not pg.key.get_pressed()[pg.K_LSHIFT] + and not pg.key.get_pressed()[pg.K_RSHIFT] + ): + self.quit_selection() + + # Update self + def update(self): + if self.shown and mouseDown: + self.place_block() + + # Draw self + def render(self): + if self.shown: + for i in range(len(main.menuBar.buttons)): + if main.menuBar.buttons[i].id == self.blockId: + main.menuBar.buttons[i].renFun( + pg.mouse.get_pos()[0] - main.menuBar.height / 2, + pg.mouse.get_pos()[1] - main.menuBar.height / 2, + ) + break + + +# Level to be rendered +class Platforms: + def __init__(self): + self.platforms = read_level() + + # Render + def render(self): + global scrollX, scrollY + for i in range(len(self.platforms)): + for j in range(len(self.platforms[i])): + if self.platforms[i][j] == "ground": + pg.draw.rect( + main.win, + DARKPURPLE, + ( + j * blockSize - scrollX, + i * blockSize - scrollY, + blockSize, + blockSize, + ), + ) + + +# Test if the script is directly ran +if __name__ == "__main__": + main = Main() + main.loop() diff --git a/src/platformer/level_creator/scrolling.py b/src/platformer/level_creator/scrolling.py new file mode 100644 index 0000000..c9c56a5 --- /dev/null +++ b/src/platformer/level_creator/scrolling.py @@ -0,0 +1,18 @@ +# Scrolling mechanism + +import pygame as pg +from main import scrollX, scrollY, scrollVel + + +def get_scroll_pos(): + global scrollX, scrollY, scrollVel + keys = pg.key.get_pressed() + if keys[pg.K_UP]: + scrollY -= scrollVel + if keys[pg.K_DOWN]: + scrollY += scrollVel + if keys[pg.K_RIGHT]: + scrollX += scrollVel + if keys[pg.K_LEFT]: + scrollX -= scrollVel + return (scrollX, scrollY) diff --git a/src/platformer/main.py b/src/platformer/main.py index 1388009..ee72f5b 100644 --- a/src/platformer/main.py +++ b/src/platformer/main.py @@ -11,9 +11,10 @@ environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "1" import pygame as pg -import sys +import sys, random from constants import * -from physics import Physics +from read_level import * +from physics import * # The main controller class Main: @@ -24,21 +25,24 @@ def __init__(self): self.win = pg.display.set_mode((WIDTH, HEIGHT)) self.platforms = Platforms() self.player = Player() + self.bgEnts = BgEnts() Physics.clock.tick() # For key press and close button functionality - def checkEvents(self): + def check_events(self): for event in pg.event.get(): if event.type == pg.QUIT: - main.running = False + self.running = False # Update things def update(self): + self.bgEnts.update() self.player.update() # Draw things def render(self): self.win.fill(BLACK) + self.bgEnts.render() self.platforms.render() self.player.render() pg.display.update() @@ -46,7 +50,7 @@ def render(self): # The main loop def loop(self): while self.running: - self.checkEvents() + self.check_events() self.update() self.render() Physics.dt = Physics.clock.tick(FPS) / 1000 @@ -54,6 +58,7 @@ def loop(self): sys.exit() +# The player class Player: def __init__(self): self.pos = pg.Vector2(250, 300) @@ -62,13 +67,18 @@ def __init__(self): self.prevPositions = [] self.width = 40 self.height = 40 + self.trailPower = 2 + # Check col with ground def colliding(self): for platform in main.platforms.rects: - if pg.Rect(self.pos.x, self.pos.y, self.width, self.height).colliderect(platform): + if pg.Rect(self.pos.x, self.pos.y, self.width, self.height).colliderect( + pg.Rect(platform.x, platform.y, platform.w, platform.h) + ): return True return False + # Update player def update(self): # Get keys @@ -108,7 +118,6 @@ def update(self): self.vel.x = -Physics.maxXVel # Apply friction - # If friction starts moving block in opposite direction instead of stopping, set vel to 0 if self.vel.x < 0: self.vel.x += Physics.friction * Physics.dt if self.vel.x > 0: @@ -129,54 +138,175 @@ def update(self): self.vel.x = 0 # Trail - self.prevPositions.append(pg.Vector2(self.pos.x, self.pos.y)) - if len(self.prevPositions) > self.width/2: - self.prevPositions.pop(0) + self.prevPositions.insert(0, pg.Vector2(self.pos.x, self.pos.y)) + if len(self.prevPositions) > self.width / 2: + self.prevPositions.pop(len(self.prevPositions) - 1) + # Render player def render(self): - # Ren trail + # Render trail for i in range(len(self.prevPositions)): - pg.draw.rect(main.win, ORANGE, ( - self.prevPositions[len(self.prevPositions) - i - 1].x - (self.width-i*2)/2 + self.width/2, - self.prevPositions[len(self.prevPositions) - i - 1].y - (self.height-i*2)/2 + self.height/2, - self.width - i*2, - self.height - i*2 - )) + pg.draw.rect( + main.win, + ORANGE, + ( + WIDTH / 2 + - self.width / 4 + - self.pos.x + + self.prevPositions[i].x + + i * self.trailPower / 2, + HEIGHT / 2 + - self.height / 4 + - self.pos.y + + self.prevPositions[i].y + + i * self.trailPower / 2, + self.width / 2 - i * self.trailPower, + self.height / 2 - i * self.trailPower, + ), + ) - # Ren player - pg.draw.rect(main.win, RED, (self.pos.x, self.pos.y, self.width, self.height)) + # Render player + pg.draw.rect( + main.win, + RED, + ( + WIDTH / 2 - self.width / 2, + HEIGHT / 2 - self.height / 2, + self.width, + self.height, + ), + ) +# Platform class class Platform: - def __init__(self, x, y): + def __init__(self, x, y, w, h, type="ground"): self.x = x self.y = y + self.w = w + self.h = h + self.type = type +# Platforms class Platforms: def __init__(self): - p = "p" + p = "ground" _ = "_" self.rects = [] - self.layout = [ - [p, p, p, p, p, p, p, p, p, p, p, p], - [p, _, _, _, _, _, _, _, _, _, _, p], - [p, _, _, _, _, _, _, _, _, _, _, p], - [p, p, p, _, _, p, _, _, _, _, p, p], - [p, _, _, _, _, _, _, _, _, _, _, p], - [p, _, p, _, _, _, p, p, p, p, _, p], - [p, _, _, _, _, _, _, _, _, _, _, p], - [p, p, p, p, p, p, p, p, p, p, p, p], - ] + self.layout = read_level() + + # Convert JSON data to Python list for i in range(len(self.layout)): for j in range(len(self.layout[i])): if self.layout[i][j] == p: - self.rects.append(pg.Rect(j * 50, i * 50, 50, 50)) + self.rects.append(Platform(j * 50, i * 50, 50, 50)) + # Render platforms def render(self): for rect in self.rects: - pg.draw.rect(main.win, WHITE, rect) + pg.draw.rect( + main.win, + DARKPURPLE, + ( + rect.x - main.player.pos.x - int(main.player.width / 2) + WIDTH / 2, + rect.y + - main.player.pos.y + - int(main.player.height / 2) + + HEIGHT / 2, + rect.w, + rect.h, + ), + ) + + +# Background objects +class BgEnts: + def __init__(self): + self.waves = self.Waves() + + # Update scene + def update(self): + self.waves.gen_waves() + self.waves.update() + + # Draw scene + def render(self): + self.waves.render() + + class Waves: + def __init__(self): + # Bigger num = less waves + # Smaller num = more waves + self.waveGenRate = 75 + # Bigger num = less thickness + # Smaller num = more thickness + self.waveThickness = 4 + + # Min/max wave size + self.minWaveSize = 10 + self.maxWaveSize = 35 + + # Min/max wave max life + self.minWaveLife = 25 + self.maxWaveLife = 125 + + # Min/max wave speed + self.minWaveSpeed = 10 + self.maxWaveSpeed = 35 + + self.waves = [] + + # Wave class + class Wave: + def __init__(self, x, y, life, speed): + self.x = x + self.y = y + self.life = life + self.speed = speed + self.frame = 0 + + # Generate waves randomly + def gen_waves(self): + if random.randint(0, self.waveGenRate) == self.waveGenRate: + self.waves.append( + self.Wave( + random.randint(0, WIDTH), + random.randint(0, HEIGHT), + random.randint(self.minWaveLife, self.maxWaveLife), + random.randint(self.minWaveSpeed, self.maxWaveSpeed), + ) + ) + + # Update waves + def update(self): + for i in range(len(self.waves)): + if self.waves[i].frame >= self.waves[i].life: + self.waves[i] = None + else: + self.waves[i].frame += 1 + # Remove empty list items + self.waves = list(filter(lambda item: item != None, self.waves)) + + # Render waves + def render(self): + for i in range(len(self.waves)): + # Use surface since pg.draw.circle doesn't support transparency + surf = pg.Surface((WIDTH, HEIGHT), pg.SRCALPHA, 32) + pg.draw.circle( + surf, + ( + # Convert hex code to RGB tuple then add allpha channel + tuple(int(PURPLE.lstrip("#")[i : i + 2], 16) for i in (0, 2, 4)) + # Alpha channel, set according to frame of wave + + (255 - 255 / self.waves[i].life * self.waves[i].frame,) + ), + (self.waves[i].x, self.waves[i].y), + self.waves[i].frame, + int(self.waves[i].frame / self.waveThickness), + ) + main.win.blit(surf, (0, 0)) # Test if the script is directly ran diff --git a/src/platformer/physics.py b/src/platformer/physics.py index 07e269c..99289a4 100644 --- a/src/platformer/physics.py +++ b/src/platformer/physics.py @@ -1,16 +1,15 @@ +# Physics settings + import pygame as pg from constants import * - +# Physics class class Physics: clock = pg.time.Clock() dt = 1 / FPS gravity = 1800 - jumpHeight = -720 + jumpHeight = -750 friction = 1800 xAcc = 3600 maxXVel = 480 - - def squareCollision(x1, y1, w1, h1, x2, y2, w2, h2): - return x1 + w1 > x2 and x1 < x2 + w2 and y1 + h1 > y2 and y1 < y2 + h2 diff --git a/src/platformer/read_level.py b/src/platformer/read_level.py new file mode 100644 index 0000000..ae8f204 --- /dev/null +++ b/src/platformer/read_level.py @@ -0,0 +1,12 @@ +# JSON level reader + +import json, os + +# Read level +def read_level(): + # Open file from full path (just in case the script is being ran from somewhere other than py-games/src/platformer) + file = open(os.path.dirname(os.path.abspath(__file__)) + "\level.json", "r") + # Python dict + data = json.load(file) + # Return Python list + return data["level"] From c113f54b8dbddf3955627f349ad56dcb10e2bfe2 Mon Sep 17 00:00:00 2001 From: MTM828 Date: Fri, 13 Aug 2021 16:23:00 +0300 Subject: [PATCH 10/16] Revert "Platformer update" This reverts commit 4821f8966a5e49ad7a7f6701ccda57b5b417e8f4. --- .vscode/settings.json | 5 +- src/platformer/constants.py | 11 +- src/platformer/level.json | 1 - src/platformer/level_creator/constants.py | 13 - src/platformer/level_creator/file_editor.py | 27 -- src/platformer/level_creator/main.py | 304 -------------------- src/platformer/level_creator/scrolling.py | 18 -- src/platformer/main.py | 196 +++---------- src/platformer/physics.py | 9 +- src/platformer/read_level.py | 12 - 10 files changed, 43 insertions(+), 553 deletions(-) delete mode 100644 src/platformer/level.json delete mode 100644 src/platformer/level_creator/constants.py delete mode 100644 src/platformer/level_creator/file_editor.py delete mode 100644 src/platformer/level_creator/main.py delete mode 100644 src/platformer/level_creator/scrolling.py delete mode 100644 src/platformer/read_level.py diff --git a/.vscode/settings.json b/.vscode/settings.json index 16f3447..b4268dd 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,9 +1,6 @@ { "python.analysis.extraPaths": [ - "./src/gravity", - "./src/platformer", - "./src/platformer/level_creator", - "./src/tictactoe" + "./src/gravity" ], "python.linting.pylintArgs": [ "--disable=all", diff --git a/src/platformer/constants.py b/src/platformer/constants.py index 153a715..4d370fb 100644 --- a/src/platformer/constants.py +++ b/src/platformer/constants.py @@ -1,10 +1,7 @@ # Declare some constants and variables - WIDTH, HEIGHT = (600, 400) FPS = 60 -BLACK = "#000000" -WHITE = "#FFFFFF" -ORANGE = "#FF6600" -RED = "#FF1F00" -PURPLE = "#800080" -DARKPURPLE = "#301934" +BLACK = "#000000" +WHITE = "#FFFFFF" +ORANGE = "#FF6600" +RED = "#FF1F00" diff --git a/src/platformer/level.json b/src/platformer/level.json deleted file mode 100644 index 9593b89..0000000 --- a/src/platformer/level.json +++ /dev/null @@ -1 +0,0 @@ -{"level":[["ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground","ground"],["ground",null,null,null,"ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground",null,null,null,null,null,null,"ground",null,null,"ground",null,"ground",null,null,"ground","ground","ground",null,null,null,null,null,"ground"],["ground",null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground",null,null,null,"ground"],["ground",null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,"ground",null,null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground"],["ground","ground",null,null,null,null,null,null,null,"ground","ground","ground","ground",null,null,"ground","ground",null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground"],["ground",null,"ground",null,null,null,"ground","ground","ground",null,null,null,null,null,null,null,null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground"],["ground",null,null,null,null,null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground"],["ground",null,null,"ground","ground",null,null,null,"ground",null,null,null,null,null,null,"ground","ground","ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground"],["ground",null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,"ground","ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground"],["ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground"]]} diff --git a/src/platformer/level_creator/constants.py b/src/platformer/level_creator/constants.py deleted file mode 100644 index 8e502a0..0000000 --- a/src/platformer/level_creator/constants.py +++ /dev/null @@ -1,13 +0,0 @@ -# Declare some constants and variables - -WIDTH, HEIGHT = (800, 600) -FPS = 60 -BLACK = "#000000" -DARKGRAY = "#404040" -GRAY = "#808080" -LIGHTGRAY = "#d3d3d3" -WHITE = "#FFFFFF" -ORANGE = "#FF6600" -RED = "#FF1F00" -PURPLE = "#800080" -DARKPURPLE = "#301934" diff --git a/src/platformer/level_creator/file_editor.py b/src/platformer/level_creator/file_editor.py deleted file mode 100644 index a6b74da..0000000 --- a/src/platformer/level_creator/file_editor.py +++ /dev/null @@ -1,27 +0,0 @@ -# JSON level reader - -import json, os - -# Read level -def read_level(): - # Open file from full path (just in case the script is being ran from somewhere other than py-games/src/platformer/level_creator) - file = open(os.path.dirname(os.path.abspath(__file__)) + "\..\level.json", "r") - # Python dict - try: - data = json.load(file) - except Exception: - print("Couldn't read level, data could be corrupted.") - # Close file - file.close() - # Return Python list - return data["level"] - - -# Write level -def write_level(data): - # Same as above... - file = open(os.path.dirname(os.path.abspath(__file__)) + "\..\level.json", "w") - # Write over file - file.write('{"level":' + json.dumps(data, separators=(",", ":")) + "}\n") - # Close file - file.close() diff --git a/src/platformer/level_creator/main.py b/src/platformer/level_creator/main.py deleted file mode 100644 index a42acda..0000000 --- a/src/platformer/level_creator/main.py +++ /dev/null @@ -1,304 +0,0 @@ -#!/usr/bin/python -""" -Github repo can be found here: -https://github.com/sparshg/py-games -""" - -# Import statements -from os import environ - -# Hide pygame Hello prompt -environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "1" -import pygame as pg - -import sys -from constants import * -from file_editor import * -from scrolling import * - -mouseDown = False -scrollX = 0 -scrollY = 0 -scrollVel = 1 -blockSize = 50 - -# The main controller -class Main: - def __init__(self): - pg.init() - pg.display.set_caption("Platformer Level Creator") - self.running = True - self.win = pg.display.set_mode((WIDTH, HEIGHT)) - self.menuBar = MenuBar() - self.selectedBlock = SelectedBlock() - self.platforms = Platforms() - - # For key press and close button functionality - def check_events(self): - global mouseDown - for event in pg.event.get(): - if event.type == pg.QUIT: - self.running = False - if event.type == pg.MOUSEBUTTONUP: - mouseDown = True - - # Update things - def update(self): - global scrollX, scrollY - self.menuBar.update() - self.selectedBlock.update() - scrollX = get_scroll_pos()[0] - scrollY = get_scroll_pos()[1] - keys = pg.key.get_pressed() - # Save on CTRL + S - if keys[pg.K_s] and (keys[pg.K_LCTRL] or keys[pg.K_RCTRL]): - write_level(main.platforms.platforms) - - # Draw things - def render(self): - self.win.fill(BLACK) - self.platforms.render() - self.menuBar.render() - self.selectedBlock.render() - pg.display.update() - - # The main loop - def loop(self): - global mouseDown - while self.running: - self.check_events() - self.update() - self.render() - mouseDown = False - pg.quit() - sys.exit() - - -# Menu bar buttons -class MenuButton: - def __init__(self, renFun, side, id): - self.renFun = renFun - self.side = side - self.id = id - - -# Button 1 (ground) -def ren_btn1(x, y): - pg.draw.rect( - main.win, - DARKPURPLE, - ( - x + main.menuBar.height / 4, - y + main.menuBar.height / 4, - main.menuBar.height / 2, - main.menuBar.height / 2, - ), - ) - - -btn1 = MenuButton(ren_btn1, "lt", "ground") - - -# Button 2 (air/clear) -def ren_btn2(x, y): - # Draw red X - pg.draw.line( - main.win, - RED, - (x + main.menuBar.height / 4, y + main.menuBar.height / 4), - ( - x + main.menuBar.height - main.menuBar.height / 4, - y + main.menuBar.height - main.menuBar.height / 4, - ), - 10, - ) - pg.draw.line( - main.win, - RED, - ( - x + main.menuBar.height - main.menuBar.height / 4, - y + main.menuBar.height / 4, - ), - ( - x + main.menuBar.height / 4, - y + main.menuBar.height - main.menuBar.height / 4, - ), - 10, - ) - - -btn2 = MenuButton(ren_btn2, "lt", None) - - -# Button 3 (the save button) -def ren_btn3(x, y): - font = pg.font.SysFont("Segoe UI", 25) - surf = font.render("Save", 1, BLACK) - main.win.blit( - surf, - ( - x + main.menuBar.height / 2 - font.size("Save")[0] / 2, - y + main.menuBar.height / 2 - font.size("Save")[1] / 2, - ), - ) - - -btn3 = MenuButton(ren_btn3, "rt", "SAVE") - - -# Menu bar -class MenuBar: - def __init__(self): - global scrollY - self.width = WIDTH - self.height = 75 - - self.buttonClicked = None - self.buttons = [btn1, btn2, btn3] - - # Update bar - def update(self): - if self.buttonClicked != None: - main.selectedBlock.quit_selection() - main.selectedBlock.select_block(self.buttons[self.buttonClicked].id) - self.buttonClicked = None - - # Draw bar - def render(self): - # Current X - ltX = 0 - rtX = self.width - self.height - # Background - pg.draw.rect(main.win, LIGHTGRAY, (0, 0, self.width, self.height)) - # Buttons - for i in range(len(self.buttons)): - # If on right side - if self.buttons[i].side == "lt": - if pg.Rect(ltX, 0, self.height, self.height).collidepoint( - pg.mouse.get_pos() - ): - if pg.mouse.get_pressed()[0]: - pg.draw.rect( - main.win, DARKGRAY, (ltX, 0, self.height, self.height) - ) - else: - pg.draw.rect(main.win, GRAY, (ltX, 0, self.height, self.height)) - if mouseDown: - self.buttonClicked = i - self.buttons[i].renFun(ltX, 0) - ltX += self.height - # if on left side - elif self.buttons[i].side == "rt": - if pg.Rect(rtX, 0, self.height, self.height).collidepoint( - pg.mouse.get_pos() - ): - if pg.mouse.get_pressed()[0]: - pg.draw.rect( - main.win, DARKGRAY, (rtX, 0, self.height, self.height) - ) - else: - pg.draw.rect(main.win, GRAY, (rtX, 0, self.height, self.height)) - if mouseDown: - self.buttonClicked = i - self.buttons[i].renFun(rtX, 0) - rtX -= self.height - - -# Block in hand -class SelectedBlock: - def __init__(self): - self.shown = False - self.blockId = False - - # Begin selection - def select_block(self, id): - self.quit_selection() - if id != "SAVE": - self.blockId = id - self.shown = True - else: - # Save level - write_level(main.platforms.platforms) - - # Drop item in hand - def quit_selection(self): - self.blockId = False - self.shown = False - - # Place block in desired location - def place_block(self): - global scrollX, scrollY - # Collumn - y = (pg.mouse.get_pos()[1] + scrollY) // blockSize - # Cell - x = (pg.mouse.get_pos()[0] + scrollX) // blockSize - # Check if tile exists - def place(): - if y < len(main.platforms.platforms): - if x < len(main.platforms.platforms[y]): - main.platforms.platforms[y][x] = self.blockId - else: - for i in range(x - len(main.platforms.platforms[y])): - main.platforms.platforms[y].append(None) - main.platforms.platforms[y].insert(x, self.blockId) - else: - for i in range(y - len(main.platforms.platforms)): - main.platforms.platforms.append( - [None] * len(main.platforms.platforms) - ) - row = [None] * len(main.platforms.platforms[y - 1]) - row[x] = self.blockId - main.platforms.platforms.append(row) - - place() - # If pressing SHIFT key, don't unselect - if ( - not pg.key.get_pressed()[pg.K_LSHIFT] - and not pg.key.get_pressed()[pg.K_RSHIFT] - ): - self.quit_selection() - - # Update self - def update(self): - if self.shown and mouseDown: - self.place_block() - - # Draw self - def render(self): - if self.shown: - for i in range(len(main.menuBar.buttons)): - if main.menuBar.buttons[i].id == self.blockId: - main.menuBar.buttons[i].renFun( - pg.mouse.get_pos()[0] - main.menuBar.height / 2, - pg.mouse.get_pos()[1] - main.menuBar.height / 2, - ) - break - - -# Level to be rendered -class Platforms: - def __init__(self): - self.platforms = read_level() - - # Render - def render(self): - global scrollX, scrollY - for i in range(len(self.platforms)): - for j in range(len(self.platforms[i])): - if self.platforms[i][j] == "ground": - pg.draw.rect( - main.win, - DARKPURPLE, - ( - j * blockSize - scrollX, - i * blockSize - scrollY, - blockSize, - blockSize, - ), - ) - - -# Test if the script is directly ran -if __name__ == "__main__": - main = Main() - main.loop() diff --git a/src/platformer/level_creator/scrolling.py b/src/platformer/level_creator/scrolling.py deleted file mode 100644 index c9c56a5..0000000 --- a/src/platformer/level_creator/scrolling.py +++ /dev/null @@ -1,18 +0,0 @@ -# Scrolling mechanism - -import pygame as pg -from main import scrollX, scrollY, scrollVel - - -def get_scroll_pos(): - global scrollX, scrollY, scrollVel - keys = pg.key.get_pressed() - if keys[pg.K_UP]: - scrollY -= scrollVel - if keys[pg.K_DOWN]: - scrollY += scrollVel - if keys[pg.K_RIGHT]: - scrollX += scrollVel - if keys[pg.K_LEFT]: - scrollX -= scrollVel - return (scrollX, scrollY) diff --git a/src/platformer/main.py b/src/platformer/main.py index ee72f5b..1388009 100644 --- a/src/platformer/main.py +++ b/src/platformer/main.py @@ -11,10 +11,9 @@ environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "1" import pygame as pg -import sys, random +import sys from constants import * -from read_level import * -from physics import * +from physics import Physics # The main controller class Main: @@ -25,24 +24,21 @@ def __init__(self): self.win = pg.display.set_mode((WIDTH, HEIGHT)) self.platforms = Platforms() self.player = Player() - self.bgEnts = BgEnts() Physics.clock.tick() # For key press and close button functionality - def check_events(self): + def checkEvents(self): for event in pg.event.get(): if event.type == pg.QUIT: - self.running = False + main.running = False # Update things def update(self): - self.bgEnts.update() self.player.update() # Draw things def render(self): self.win.fill(BLACK) - self.bgEnts.render() self.platforms.render() self.player.render() pg.display.update() @@ -50,7 +46,7 @@ def render(self): # The main loop def loop(self): while self.running: - self.check_events() + self.checkEvents() self.update() self.render() Physics.dt = Physics.clock.tick(FPS) / 1000 @@ -58,7 +54,6 @@ def loop(self): sys.exit() -# The player class Player: def __init__(self): self.pos = pg.Vector2(250, 300) @@ -67,18 +62,13 @@ def __init__(self): self.prevPositions = [] self.width = 40 self.height = 40 - self.trailPower = 2 - # Check col with ground def colliding(self): for platform in main.platforms.rects: - if pg.Rect(self.pos.x, self.pos.y, self.width, self.height).colliderect( - pg.Rect(platform.x, platform.y, platform.w, platform.h) - ): + if pg.Rect(self.pos.x, self.pos.y, self.width, self.height).colliderect(platform): return True return False - # Update player def update(self): # Get keys @@ -118,6 +108,7 @@ def update(self): self.vel.x = -Physics.maxXVel # Apply friction + # If friction starts moving block in opposite direction instead of stopping, set vel to 0 if self.vel.x < 0: self.vel.x += Physics.friction * Physics.dt if self.vel.x > 0: @@ -138,175 +129,54 @@ def update(self): self.vel.x = 0 # Trail - self.prevPositions.insert(0, pg.Vector2(self.pos.x, self.pos.y)) - if len(self.prevPositions) > self.width / 2: - self.prevPositions.pop(len(self.prevPositions) - 1) + self.prevPositions.append(pg.Vector2(self.pos.x, self.pos.y)) + if len(self.prevPositions) > self.width/2: + self.prevPositions.pop(0) - # Render player def render(self): - # Render trail + # Ren trail for i in range(len(self.prevPositions)): - pg.draw.rect( - main.win, - ORANGE, - ( - WIDTH / 2 - - self.width / 4 - - self.pos.x - + self.prevPositions[i].x - + i * self.trailPower / 2, - HEIGHT / 2 - - self.height / 4 - - self.pos.y - + self.prevPositions[i].y - + i * self.trailPower / 2, - self.width / 2 - i * self.trailPower, - self.height / 2 - i * self.trailPower, - ), - ) + pg.draw.rect(main.win, ORANGE, ( + self.prevPositions[len(self.prevPositions) - i - 1].x - (self.width-i*2)/2 + self.width/2, + self.prevPositions[len(self.prevPositions) - i - 1].y - (self.height-i*2)/2 + self.height/2, + self.width - i*2, + self.height - i*2 + )) - # Render player - pg.draw.rect( - main.win, - RED, - ( - WIDTH / 2 - self.width / 2, - HEIGHT / 2 - self.height / 2, - self.width, - self.height, - ), - ) + # Ren player + pg.draw.rect(main.win, RED, (self.pos.x, self.pos.y, self.width, self.height)) -# Platform class class Platform: - def __init__(self, x, y, w, h, type="ground"): + def __init__(self, x, y): self.x = x self.y = y - self.w = w - self.h = h - self.type = type -# Platforms class Platforms: def __init__(self): - p = "ground" + p = "p" _ = "_" self.rects = [] - self.layout = read_level() - - # Convert JSON data to Python list + self.layout = [ + [p, p, p, p, p, p, p, p, p, p, p, p], + [p, _, _, _, _, _, _, _, _, _, _, p], + [p, _, _, _, _, _, _, _, _, _, _, p], + [p, p, p, _, _, p, _, _, _, _, p, p], + [p, _, _, _, _, _, _, _, _, _, _, p], + [p, _, p, _, _, _, p, p, p, p, _, p], + [p, _, _, _, _, _, _, _, _, _, _, p], + [p, p, p, p, p, p, p, p, p, p, p, p], + ] for i in range(len(self.layout)): for j in range(len(self.layout[i])): if self.layout[i][j] == p: - self.rects.append(Platform(j * 50, i * 50, 50, 50)) + self.rects.append(pg.Rect(j * 50, i * 50, 50, 50)) - # Render platforms def render(self): for rect in self.rects: - pg.draw.rect( - main.win, - DARKPURPLE, - ( - rect.x - main.player.pos.x - int(main.player.width / 2) + WIDTH / 2, - rect.y - - main.player.pos.y - - int(main.player.height / 2) - + HEIGHT / 2, - rect.w, - rect.h, - ), - ) - - -# Background objects -class BgEnts: - def __init__(self): - self.waves = self.Waves() - - # Update scene - def update(self): - self.waves.gen_waves() - self.waves.update() - - # Draw scene - def render(self): - self.waves.render() - - class Waves: - def __init__(self): - # Bigger num = less waves - # Smaller num = more waves - self.waveGenRate = 75 - # Bigger num = less thickness - # Smaller num = more thickness - self.waveThickness = 4 - - # Min/max wave size - self.minWaveSize = 10 - self.maxWaveSize = 35 - - # Min/max wave max life - self.minWaveLife = 25 - self.maxWaveLife = 125 - - # Min/max wave speed - self.minWaveSpeed = 10 - self.maxWaveSpeed = 35 - - self.waves = [] - - # Wave class - class Wave: - def __init__(self, x, y, life, speed): - self.x = x - self.y = y - self.life = life - self.speed = speed - self.frame = 0 - - # Generate waves randomly - def gen_waves(self): - if random.randint(0, self.waveGenRate) == self.waveGenRate: - self.waves.append( - self.Wave( - random.randint(0, WIDTH), - random.randint(0, HEIGHT), - random.randint(self.minWaveLife, self.maxWaveLife), - random.randint(self.minWaveSpeed, self.maxWaveSpeed), - ) - ) - - # Update waves - def update(self): - for i in range(len(self.waves)): - if self.waves[i].frame >= self.waves[i].life: - self.waves[i] = None - else: - self.waves[i].frame += 1 - # Remove empty list items - self.waves = list(filter(lambda item: item != None, self.waves)) - - # Render waves - def render(self): - for i in range(len(self.waves)): - # Use surface since pg.draw.circle doesn't support transparency - surf = pg.Surface((WIDTH, HEIGHT), pg.SRCALPHA, 32) - pg.draw.circle( - surf, - ( - # Convert hex code to RGB tuple then add allpha channel - tuple(int(PURPLE.lstrip("#")[i : i + 2], 16) for i in (0, 2, 4)) - # Alpha channel, set according to frame of wave - + (255 - 255 / self.waves[i].life * self.waves[i].frame,) - ), - (self.waves[i].x, self.waves[i].y), - self.waves[i].frame, - int(self.waves[i].frame / self.waveThickness), - ) - main.win.blit(surf, (0, 0)) + pg.draw.rect(main.win, WHITE, rect) # Test if the script is directly ran diff --git a/src/platformer/physics.py b/src/platformer/physics.py index 99289a4..07e269c 100644 --- a/src/platformer/physics.py +++ b/src/platformer/physics.py @@ -1,15 +1,16 @@ -# Physics settings - import pygame as pg from constants import * -# Physics class + class Physics: clock = pg.time.Clock() dt = 1 / FPS gravity = 1800 - jumpHeight = -750 + jumpHeight = -720 friction = 1800 xAcc = 3600 maxXVel = 480 + + def squareCollision(x1, y1, w1, h1, x2, y2, w2, h2): + return x1 + w1 > x2 and x1 < x2 + w2 and y1 + h1 > y2 and y1 < y2 + h2 diff --git a/src/platformer/read_level.py b/src/platformer/read_level.py deleted file mode 100644 index ae8f204..0000000 --- a/src/platformer/read_level.py +++ /dev/null @@ -1,12 +0,0 @@ -# JSON level reader - -import json, os - -# Read level -def read_level(): - # Open file from full path (just in case the script is being ran from somewhere other than py-games/src/platformer) - file = open(os.path.dirname(os.path.abspath(__file__)) + "\level.json", "r") - # Python dict - data = json.load(file) - # Return Python list - return data["level"] From e862006d4575944b931b5d90b0db0224b6f9cd72 Mon Sep 17 00:00:00 2001 From: MTM828 <71281115+MTM828@users.noreply.github.com> Date: Mon, 23 Aug 2021 17:10:49 +0300 Subject: [PATCH 11/16] Added level editor and scrolling to platformer + improvements (#23) * Platformer update * Fix paths * Fix structure * . Co-authored-by: sparshg <43041139+sparshg@users.noreply.github.com> --- .vscode/settings.json | 5 +- src/platformer/constants.py | 12 +- src/platformer/level.json | 1 + src/platformer/level_creator/constants.py | 13 + src/platformer/level_creator/file_editor.py | 27 ++ src/platformer/level_creator/main.py | 304 ++++++++++++++++++++ src/platformer/level_creator/scrolling.py | 18 ++ src/platformer/main.py | 226 +++++++-------- src/platformer/physics.py | 22 +- src/platformer/platforms.py | 41 +++ src/platformer/player.py | 123 ++++++++ src/platformer/read_level.py | 12 + 12 files changed, 658 insertions(+), 146 deletions(-) create mode 100644 src/platformer/level.json create mode 100644 src/platformer/level_creator/constants.py create mode 100644 src/platformer/level_creator/file_editor.py create mode 100644 src/platformer/level_creator/main.py create mode 100644 src/platformer/level_creator/scrolling.py create mode 100644 src/platformer/platforms.py create mode 100644 src/platformer/player.py create mode 100644 src/platformer/read_level.py diff --git a/.vscode/settings.json b/.vscode/settings.json index b4268dd..16f3447 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,9 @@ { "python.analysis.extraPaths": [ - "./src/gravity" + "./src/gravity", + "./src/platformer", + "./src/platformer/level_creator", + "./src/tictactoe" ], "python.linting.pylintArgs": [ "--disable=all", diff --git a/src/platformer/constants.py b/src/platformer/constants.py index 4d370fb..76b1435 100644 --- a/src/platformer/constants.py +++ b/src/platformer/constants.py @@ -1,7 +1,13 @@ # Declare some constants and variables + WIDTH, HEIGHT = (600, 400) FPS = 60 -BLACK = "#000000" -WHITE = "#FFFFFF" +BLACK = "#000000" +DARKGRAY = "#404040" +GRAY = "#808080" +LIGHTGRAY = "#d3d3d3" +WHITE = "#FFFFFF" ORANGE = "#FF6600" -RED = "#FF1F00" +RED = "#FF1F00" +PURPLE = "#800080" +DARKPURPLE = "#301934" diff --git a/src/platformer/level.json b/src/platformer/level.json new file mode 100644 index 0000000..9593b89 --- /dev/null +++ b/src/platformer/level.json @@ -0,0 +1 @@ +{"level":[["ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground","ground"],["ground",null,null,null,"ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground",null,null,null,null,null,null,"ground",null,null,"ground",null,"ground",null,null,"ground","ground","ground",null,null,null,null,null,"ground"],["ground",null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground",null,null,null,"ground"],["ground",null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,"ground",null,null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground"],["ground","ground",null,null,null,null,null,null,null,"ground","ground","ground","ground",null,null,"ground","ground",null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground"],["ground",null,"ground",null,null,null,"ground","ground","ground",null,null,null,null,null,null,null,null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground"],["ground",null,null,null,null,null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground"],["ground",null,null,"ground","ground",null,null,null,"ground",null,null,null,null,null,null,"ground","ground","ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground"],["ground",null,null,null,"ground",null,null,null,null,null,null,null,null,null,null,null,"ground","ground",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"ground"],["ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground","ground"]]} diff --git a/src/platformer/level_creator/constants.py b/src/platformer/level_creator/constants.py new file mode 100644 index 0000000..a71c09a --- /dev/null +++ b/src/platformer/level_creator/constants.py @@ -0,0 +1,13 @@ +# Declare some constants and variables + +WIDTH, HEIGHT = (800, 600) +FPS = 60 +BLACK = "#000000" +DARKGRAY = "#404040" +GRAY = "#808080" +LIGHTGRAY = "#d3d3d3" +WHITE = "#FFFFFF" +ORANGE = "#FF6600" +RED = "#FF1F00" +PURPLE = "#800080" +DARKPURPLE = "#301934" diff --git a/src/platformer/level_creator/file_editor.py b/src/platformer/level_creator/file_editor.py new file mode 100644 index 0000000..02d953c --- /dev/null +++ b/src/platformer/level_creator/file_editor.py @@ -0,0 +1,27 @@ +# JSON level reader + +import json, os + +# Read level +def read_level(): + # Open file from full path (just in case the script is being ran from somewhere other than py-games/src/platformer/level_creator) + file = open(os.path.join(os.path.dirname(__file__), os.pardir, "level.json"), "r") + # Python dict + try: + data = json.load(file) + except Exception: + print("Couldn't read level, data could be corrupted.") + # Close file + file.close() + # Return Python list + return data["level"] + + +# Write level +def write_level(data): + # Same as above... + file = open(os.path.join(os.path.dirname(__file__), os.pardir, "level.json"), "w") + # Write over file + file.write('{"level":' + json.dumps(data, separators=(",", ":")) + "}\n") + # Close file + file.close() diff --git a/src/platformer/level_creator/main.py b/src/platformer/level_creator/main.py new file mode 100644 index 0000000..a42acda --- /dev/null +++ b/src/platformer/level_creator/main.py @@ -0,0 +1,304 @@ +#!/usr/bin/python +""" +Github repo can be found here: +https://github.com/sparshg/py-games +""" + +# Import statements +from os import environ + +# Hide pygame Hello prompt +environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "1" +import pygame as pg + +import sys +from constants import * +from file_editor import * +from scrolling import * + +mouseDown = False +scrollX = 0 +scrollY = 0 +scrollVel = 1 +blockSize = 50 + +# The main controller +class Main: + def __init__(self): + pg.init() + pg.display.set_caption("Platformer Level Creator") + self.running = True + self.win = pg.display.set_mode((WIDTH, HEIGHT)) + self.menuBar = MenuBar() + self.selectedBlock = SelectedBlock() + self.platforms = Platforms() + + # For key press and close button functionality + def check_events(self): + global mouseDown + for event in pg.event.get(): + if event.type == pg.QUIT: + self.running = False + if event.type == pg.MOUSEBUTTONUP: + mouseDown = True + + # Update things + def update(self): + global scrollX, scrollY + self.menuBar.update() + self.selectedBlock.update() + scrollX = get_scroll_pos()[0] + scrollY = get_scroll_pos()[1] + keys = pg.key.get_pressed() + # Save on CTRL + S + if keys[pg.K_s] and (keys[pg.K_LCTRL] or keys[pg.K_RCTRL]): + write_level(main.platforms.platforms) + + # Draw things + def render(self): + self.win.fill(BLACK) + self.platforms.render() + self.menuBar.render() + self.selectedBlock.render() + pg.display.update() + + # The main loop + def loop(self): + global mouseDown + while self.running: + self.check_events() + self.update() + self.render() + mouseDown = False + pg.quit() + sys.exit() + + +# Menu bar buttons +class MenuButton: + def __init__(self, renFun, side, id): + self.renFun = renFun + self.side = side + self.id = id + + +# Button 1 (ground) +def ren_btn1(x, y): + pg.draw.rect( + main.win, + DARKPURPLE, + ( + x + main.menuBar.height / 4, + y + main.menuBar.height / 4, + main.menuBar.height / 2, + main.menuBar.height / 2, + ), + ) + + +btn1 = MenuButton(ren_btn1, "lt", "ground") + + +# Button 2 (air/clear) +def ren_btn2(x, y): + # Draw red X + pg.draw.line( + main.win, + RED, + (x + main.menuBar.height / 4, y + main.menuBar.height / 4), + ( + x + main.menuBar.height - main.menuBar.height / 4, + y + main.menuBar.height - main.menuBar.height / 4, + ), + 10, + ) + pg.draw.line( + main.win, + RED, + ( + x + main.menuBar.height - main.menuBar.height / 4, + y + main.menuBar.height / 4, + ), + ( + x + main.menuBar.height / 4, + y + main.menuBar.height - main.menuBar.height / 4, + ), + 10, + ) + + +btn2 = MenuButton(ren_btn2, "lt", None) + + +# Button 3 (the save button) +def ren_btn3(x, y): + font = pg.font.SysFont("Segoe UI", 25) + surf = font.render("Save", 1, BLACK) + main.win.blit( + surf, + ( + x + main.menuBar.height / 2 - font.size("Save")[0] / 2, + y + main.menuBar.height / 2 - font.size("Save")[1] / 2, + ), + ) + + +btn3 = MenuButton(ren_btn3, "rt", "SAVE") + + +# Menu bar +class MenuBar: + def __init__(self): + global scrollY + self.width = WIDTH + self.height = 75 + + self.buttonClicked = None + self.buttons = [btn1, btn2, btn3] + + # Update bar + def update(self): + if self.buttonClicked != None: + main.selectedBlock.quit_selection() + main.selectedBlock.select_block(self.buttons[self.buttonClicked].id) + self.buttonClicked = None + + # Draw bar + def render(self): + # Current X + ltX = 0 + rtX = self.width - self.height + # Background + pg.draw.rect(main.win, LIGHTGRAY, (0, 0, self.width, self.height)) + # Buttons + for i in range(len(self.buttons)): + # If on right side + if self.buttons[i].side == "lt": + if pg.Rect(ltX, 0, self.height, self.height).collidepoint( + pg.mouse.get_pos() + ): + if pg.mouse.get_pressed()[0]: + pg.draw.rect( + main.win, DARKGRAY, (ltX, 0, self.height, self.height) + ) + else: + pg.draw.rect(main.win, GRAY, (ltX, 0, self.height, self.height)) + if mouseDown: + self.buttonClicked = i + self.buttons[i].renFun(ltX, 0) + ltX += self.height + # if on left side + elif self.buttons[i].side == "rt": + if pg.Rect(rtX, 0, self.height, self.height).collidepoint( + pg.mouse.get_pos() + ): + if pg.mouse.get_pressed()[0]: + pg.draw.rect( + main.win, DARKGRAY, (rtX, 0, self.height, self.height) + ) + else: + pg.draw.rect(main.win, GRAY, (rtX, 0, self.height, self.height)) + if mouseDown: + self.buttonClicked = i + self.buttons[i].renFun(rtX, 0) + rtX -= self.height + + +# Block in hand +class SelectedBlock: + def __init__(self): + self.shown = False + self.blockId = False + + # Begin selection + def select_block(self, id): + self.quit_selection() + if id != "SAVE": + self.blockId = id + self.shown = True + else: + # Save level + write_level(main.platforms.platforms) + + # Drop item in hand + def quit_selection(self): + self.blockId = False + self.shown = False + + # Place block in desired location + def place_block(self): + global scrollX, scrollY + # Collumn + y = (pg.mouse.get_pos()[1] + scrollY) // blockSize + # Cell + x = (pg.mouse.get_pos()[0] + scrollX) // blockSize + # Check if tile exists + def place(): + if y < len(main.platforms.platforms): + if x < len(main.platforms.platforms[y]): + main.platforms.platforms[y][x] = self.blockId + else: + for i in range(x - len(main.platforms.platforms[y])): + main.platforms.platforms[y].append(None) + main.platforms.platforms[y].insert(x, self.blockId) + else: + for i in range(y - len(main.platforms.platforms)): + main.platforms.platforms.append( + [None] * len(main.platforms.platforms) + ) + row = [None] * len(main.platforms.platforms[y - 1]) + row[x] = self.blockId + main.platforms.platforms.append(row) + + place() + # If pressing SHIFT key, don't unselect + if ( + not pg.key.get_pressed()[pg.K_LSHIFT] + and not pg.key.get_pressed()[pg.K_RSHIFT] + ): + self.quit_selection() + + # Update self + def update(self): + if self.shown and mouseDown: + self.place_block() + + # Draw self + def render(self): + if self.shown: + for i in range(len(main.menuBar.buttons)): + if main.menuBar.buttons[i].id == self.blockId: + main.menuBar.buttons[i].renFun( + pg.mouse.get_pos()[0] - main.menuBar.height / 2, + pg.mouse.get_pos()[1] - main.menuBar.height / 2, + ) + break + + +# Level to be rendered +class Platforms: + def __init__(self): + self.platforms = read_level() + + # Render + def render(self): + global scrollX, scrollY + for i in range(len(self.platforms)): + for j in range(len(self.platforms[i])): + if self.platforms[i][j] == "ground": + pg.draw.rect( + main.win, + DARKPURPLE, + ( + j * blockSize - scrollX, + i * blockSize - scrollY, + blockSize, + blockSize, + ), + ) + + +# Test if the script is directly ran +if __name__ == "__main__": + main = Main() + main.loop() diff --git a/src/platformer/level_creator/scrolling.py b/src/platformer/level_creator/scrolling.py new file mode 100644 index 0000000..c9c56a5 --- /dev/null +++ b/src/platformer/level_creator/scrolling.py @@ -0,0 +1,18 @@ +# Scrolling mechanism + +import pygame as pg +from main import scrollX, scrollY, scrollVel + + +def get_scroll_pos(): + global scrollX, scrollY, scrollVel + keys = pg.key.get_pressed() + if keys[pg.K_UP]: + scrollY -= scrollVel + if keys[pg.K_DOWN]: + scrollY += scrollVel + if keys[pg.K_RIGHT]: + scrollX += scrollVel + if keys[pg.K_LEFT]: + scrollX -= scrollVel + return (scrollX, scrollY) diff --git a/src/platformer/main.py b/src/platformer/main.py index 1388009..f56261d 100644 --- a/src/platformer/main.py +++ b/src/platformer/main.py @@ -10,173 +10,143 @@ # Hide pygame Hello prompt environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "1" import pygame as pg +import sys, random -import sys +import physics from constants import * -from physics import Physics +from player import Player +from platforms import Platforms # The main controller class Main: def __init__(self): pg.init() pg.display.set_caption("Platformer") + self.running = True self.win = pg.display.set_mode((WIDTH, HEIGHT)) self.platforms = Platforms() self.player = Player() - Physics.clock.tick() + self.bgEnts = BgEnts() + self.clock = pg.time.Clock() + self.clock.tick() # For key press and close button functionality - def checkEvents(self): + def check_events(self): for event in pg.event.get(): if event.type == pg.QUIT: - main.running = False + self.running = False # Update things def update(self): - self.player.update() + self.bgEnts.update() + self.player.update(self.platforms.rects) # Draw things def render(self): self.win.fill(BLACK) - self.platforms.render() - self.player.render() + self.bgEnts.render() + self.platforms.render(self.win, self.player) + self.player.render(self.win) pg.display.update() # The main loop def loop(self): while self.running: - self.checkEvents() + self.check_events() self.update() self.render() - Physics.dt = Physics.clock.tick(FPS) / 1000 + physics.dt = self.clock.tick(FPS) / 1000 pg.quit() sys.exit() -class Player: +# Background objects +class BgEnts: def __init__(self): - self.pos = pg.Vector2(250, 300) - self.vel = pg.Vector2(0, 0) - self.onGround = True - self.prevPositions = [] - self.width = 40 - self.height = 40 - - def colliding(self): - for platform in main.platforms.rects: - if pg.Rect(self.pos.x, self.pos.y, self.width, self.height).colliderect(platform): - return True - return False + self.waves = self.Waves() + # Update scene def update(self): + self.waves.gen_waves() + self.waves.update() - # Get keys - keyDown = pg.key.get_pressed() - - if self.onGround: - if keyDown[pg.K_UP]: - self.vel.y = Physics.jumpHeight - self.onGround = False - if not self.colliding(): - self.onGround = False - else: - self.vel.y += Physics.gravity * Physics.dt - self.pos.y += self.vel.y * Physics.dt - - if self.colliding(): - if self.vel.y > 0: - while self.colliding(): - self.pos.y -= 0.5 - self.vel.y = 0 - self.onGround = True - else: - while self.colliding(): - self.pos.y += 0.5 - self.vel.y = Physics.gravity * Physics.dt - - # Right - if keyDown[pg.K_RIGHT]: - self.vel.x += Physics.xAcc * Physics.dt - if self.vel.x > Physics.maxXVel: - self.vel.x = Physics.maxXVel - - # Left - if keyDown[pg.K_LEFT]: - self.vel.x -= Physics.xAcc * Physics.dt - if -self.vel.x > Physics.maxXVel: - self.vel.x = -Physics.maxXVel - - # Apply friction - # If friction starts moving block in opposite direction instead of stopping, set vel to 0 - if self.vel.x < 0: - self.vel.x += Physics.friction * Physics.dt - if self.vel.x > 0: - self.vel.x = 0 - elif self.vel.x > 0: - self.vel.x -= Physics.friction * Physics.dt - if self.vel.x < 0: - self.vel.x = 0 - - # Wall collision - self.pos.x += self.vel.x * Physics.dt - if self.colliding(): - while self.colliding(): - if self.vel.x > 0: - self.pos.x -= 0.5 - else: - self.pos.x += 0.5 - self.vel.x = 0 - - # Trail - self.prevPositions.append(pg.Vector2(self.pos.x, self.pos.y)) - if len(self.prevPositions) > self.width/2: - self.prevPositions.pop(0) - + # Draw scene def render(self): - - # Ren trail - for i in range(len(self.prevPositions)): - pg.draw.rect(main.win, ORANGE, ( - self.prevPositions[len(self.prevPositions) - i - 1].x - (self.width-i*2)/2 + self.width/2, - self.prevPositions[len(self.prevPositions) - i - 1].y - (self.height-i*2)/2 + self.height/2, - self.width - i*2, - self.height - i*2 - )) - - # Ren player - pg.draw.rect(main.win, RED, (self.pos.x, self.pos.y, self.width, self.height)) - - -class Platform: - def __init__(self, x, y): - self.x = x - self.y = y - - -class Platforms: - def __init__(self): - p = "p" - _ = "_" - self.rects = [] - self.layout = [ - [p, p, p, p, p, p, p, p, p, p, p, p], - [p, _, _, _, _, _, _, _, _, _, _, p], - [p, _, _, _, _, _, _, _, _, _, _, p], - [p, p, p, _, _, p, _, _, _, _, p, p], - [p, _, _, _, _, _, _, _, _, _, _, p], - [p, _, p, _, _, _, p, p, p, p, _, p], - [p, _, _, _, _, _, _, _, _, _, _, p], - [p, p, p, p, p, p, p, p, p, p, p, p], - ] - for i in range(len(self.layout)): - for j in range(len(self.layout[i])): - if self.layout[i][j] == p: - self.rects.append(pg.Rect(j * 50, i * 50, 50, 50)) - - def render(self): - for rect in self.rects: - pg.draw.rect(main.win, WHITE, rect) + self.waves.render() + + class Waves: + def __init__(self): + # Bigger num = less waves + # Smaller num = more waves + self.waveGenRate = 75 + # Bigger num = less thickness + # Smaller num = more thickness + self.waveThickness = 4 + + # Min/max wave size + self.minWaveSize = 10 + self.maxWaveSize = 35 + + # Min/max wave max life + self.minWaveLife = 25 + self.maxWaveLife = 125 + + # Min/max wave speed + self.minWaveSpeed = 10 + self.maxWaveSpeed = 35 + + self.waves = [] + + # Wave class + class Wave: + def __init__(self, x, y, life, speed): + self.x = x + self.y = y + self.life = life + self.speed = speed + self.frame = 0 + + # Generate waves randomly + def gen_waves(self): + if random.randint(0, self.waveGenRate) == self.waveGenRate: + self.waves.append( + self.Wave( + random.randint(0, WIDTH), + random.randint(0, HEIGHT), + random.randint(self.minWaveLife, self.maxWaveLife), + random.randint(self.minWaveSpeed, self.maxWaveSpeed), + ) + ) + + # Update waves + def update(self): + for i in range(len(self.waves)): + if self.waves[i].frame >= self.waves[i].life: + self.waves[i] = None + else: + self.waves[i].frame += 1 + # Remove empty list items + self.waves = list(filter(lambda item: item != None, self.waves)) + + # Render waves + def render(self): + for i in range(len(self.waves)): + # Use surface since pg.draw.circle doesn't support transparency + surf = pg.Surface((WIDTH, HEIGHT), pg.SRCALPHA, 32) + pg.draw.circle( + surf, + ( + # Convert hex code to RGB tuple then add allpha channel + tuple(int(PURPLE.lstrip("#")[i : i + 2], 16) for i in (0, 2, 4)) + # Alpha channel, set according to frame of wave + + (255 - 255 / self.waves[i].life * self.waves[i].frame,) + ), + (self.waves[i].x, self.waves[i].y), + self.waves[i].frame, + int(self.waves[i].frame / self.waveThickness), + ) + main.win.blit(surf, (0, 0)) # Test if the script is directly ran diff --git a/src/platformer/physics.py b/src/platformer/physics.py index 07e269c..c2c3006 100644 --- a/src/platformer/physics.py +++ b/src/platformer/physics.py @@ -1,16 +1,10 @@ -import pygame as pg -from constants import * +# Physics settings +from constants import FPS -class Physics: - - clock = pg.time.Clock() - dt = 1 / FPS - gravity = 1800 - jumpHeight = -720 - friction = 1800 - xAcc = 3600 - maxXVel = 480 - - def squareCollision(x1, y1, w1, h1, x2, y2, w2, h2): - return x1 + w1 > x2 and x1 < x2 + w2 and y1 + h1 > y2 and y1 < y2 + h2 +dt = 1 / FPS +gravity = 1800 +jumpHeight = -750 +friction = 1800 +xAcc = 3600 +maxXVel = 480 diff --git a/src/platformer/platforms.py b/src/platformer/platforms.py new file mode 100644 index 0000000..3e5eeca --- /dev/null +++ b/src/platformer/platforms.py @@ -0,0 +1,41 @@ +import pygame as pg +from read_level import * +from constants import * + + +class Platform: + def __init__(self, x, y, w, h, type="ground"): + self.x = x + self.y = y + self.w = w + self.h = h + self.type = type + + +# Platforms +class Platforms: + def __init__(self): + p = "ground" + _ = "_" + self.rects = [] + self.layout = read_level() + + # Convert JSON data to Python list + for i in range(len(self.layout)): + for j in range(len(self.layout[i])): + if self.layout[i][j] == p: + self.rects.append(Platform(j * 50, i * 50, 50, 50)) + + # Render platforms + def render(self, win, player): + for rect in self.rects: + pg.draw.rect( + win, + DARKPURPLE, + ( + rect.x - player.pos.x - int(player.width / 2) + WIDTH / 2, + rect.y - player.pos.y - int(player.height / 2) + HEIGHT / 2, + rect.w, + rect.h, + ), + ) diff --git a/src/platformer/player.py b/src/platformer/player.py new file mode 100644 index 0000000..d413afe --- /dev/null +++ b/src/platformer/player.py @@ -0,0 +1,123 @@ +import pygame as pg +import physics +from constants import * + + +class Player: + def __init__(self): + self.pos = pg.Vector2(250, 300) + self.vel = pg.Vector2(0, 0) + self.onGround = True + self.prevPositions = [] + self.width = 40 + self.height = 40 + self.trailPower = 2 + + # Check col with ground + def colliding(self, rects): + for platform in rects: + if pg.Rect(self.pos.x, self.pos.y, self.width, self.height).colliderect( + pg.Rect(platform.x, platform.y, platform.w, platform.h) + ): + return True + return False + + # Update player + def update(self, plats): + + # Get keys + keyDown = pg.key.get_pressed() + + if self.onGround: + if keyDown[pg.K_UP]: + self.vel.y = physics.jumpHeight + self.onGround = False + if not self.colliding(plats): + self.onGround = False + else: + self.vel.y += physics.gravity * physics.dt + self.pos.y += self.vel.y * physics.dt + + if self.colliding(plats): + if self.vel.y > 0: + while self.colliding(plats): + self.pos.y -= 0.5 + self.vel.y = 0 + self.onGround = True + else: + while self.colliding(plats): + self.pos.y += 0.5 + self.vel.y = physics.gravity * physics.dt + + # Right + if keyDown[pg.K_RIGHT]: + self.vel.x += physics.xAcc * physics.dt + if self.vel.x > physics.maxXVel: + self.vel.x = physics.maxXVel + + # Left + if keyDown[pg.K_LEFT]: + self.vel.x -= physics.xAcc * physics.dt + if -self.vel.x > physics.maxXVel: + self.vel.x = -physics.maxXVel + + # Apply friction + if self.vel.x < 0: + self.vel.x += physics.friction * physics.dt + if self.vel.x > 0: + self.vel.x = 0 + elif self.vel.x > 0: + self.vel.x -= physics.friction * physics.dt + if self.vel.x < 0: + self.vel.x = 0 + + # Wall collision + self.pos.x += self.vel.x * physics.dt + if self.colliding(plats): + while self.colliding(plats): + if self.vel.x > 0: + self.pos.x -= 0.5 + else: + self.pos.x += 0.5 + self.vel.x = 0 + + # Trail + self.prevPositions.insert(0, pg.Vector2(self.pos.x, self.pos.y)) + if len(self.prevPositions) > self.width / 2: + self.prevPositions.pop(len(self.prevPositions) - 1) + + # Render player + def render(self, win): + + # Render trail + for i in range(len(self.prevPositions)): + pg.draw.rect( + win, + ORANGE, + ( + WIDTH / 2 + - self.width / 4 + - self.pos.x + + self.prevPositions[i].x + + i * self.trailPower / 2, + HEIGHT / 2 + - self.height / 4 + - self.pos.y + + self.prevPositions[i].y + + i * self.trailPower / 2, + self.width / 2 - i * self.trailPower, + self.height / 2 - i * self.trailPower, + ), + ) + + # Render player + pg.draw.rect( + win, + RED, + ( + WIDTH / 2 - self.width / 2, + HEIGHT / 2 - self.height / 2, + self.width, + self.height, + ), + ) diff --git a/src/platformer/read_level.py b/src/platformer/read_level.py new file mode 100644 index 0000000..9cdef43 --- /dev/null +++ b/src/platformer/read_level.py @@ -0,0 +1,12 @@ +# JSON level reader + +import json, os + +# Read level +def read_level(): + # Open file from full path (just in case the script is being ran from somewhere other than py-games/src/platformer) + file = open("level.json", "r") + # Python dict + data = json.load(file) + # Return Python list + return data["level"] From 3a96759c19c04cec2ff16cb0c2ec67473cc89a53 Mon Sep 17 00:00:00 2001 From: Aaryansh Sahay <53135035+aaryanshsahay@users.noreply.github.com> Date: Sun, 2 Oct 2022 15:19:07 +0530 Subject: [PATCH 12/16] Add files via upload --- Flappy_Bird/assets/background-day.png | Bin 0 -> 7026 bytes Flappy_Bird/assets/background-night.png | Bin 0 -> 1101 bytes Flappy_Bird/assets/base.png | Bin 0 -> 470 bytes Flappy_Bird/assets/bluebird-downflap.png | Bin 0 -> 431 bytes Flappy_Bird/assets/bluebird-midflap.png | Bin 0 -> 430 bytes Flappy_Bird/assets/bluebird-upflap.png | Bin 0 -> 431 bytes Flappy_Bird/assets/gameover.png | Bin 0 -> 758 bytes Flappy_Bird/assets/message.png | Bin 0 -> 1602 bytes Flappy_Bird/assets/pipe-green.png | Bin 0 -> 2527 bytes Flappy_Bird/assets/pipe-red.png | Bin 0 -> 2439 bytes Flappy_Bird/assets/redbird-downflap.png | Bin 0 -> 425 bytes Flappy_Bird/assets/redbird-midflap.png | Bin 0 -> 426 bytes Flappy_Bird/assets/redbird-upflap.png | Bin 0 -> 425 bytes Flappy_Bird/assets/yellowbird-downflap.png | Bin 0 -> 426 bytes Flappy_Bird/assets/yellowbird-midflap.png | Bin 0 -> 425 bytes Flappy_Bird/assets/yellowbird-upflap.png | Bin 0 -> 427 bytes Flappy_Bird/game.py | 176 +++++++++++++++++++++ 17 files changed, 176 insertions(+) create mode 100644 Flappy_Bird/assets/background-day.png create mode 100644 Flappy_Bird/assets/background-night.png create mode 100644 Flappy_Bird/assets/base.png create mode 100644 Flappy_Bird/assets/bluebird-downflap.png create mode 100644 Flappy_Bird/assets/bluebird-midflap.png create mode 100644 Flappy_Bird/assets/bluebird-upflap.png create mode 100644 Flappy_Bird/assets/gameover.png create mode 100644 Flappy_Bird/assets/message.png create mode 100644 Flappy_Bird/assets/pipe-green.png create mode 100644 Flappy_Bird/assets/pipe-red.png create mode 100644 Flappy_Bird/assets/redbird-downflap.png create mode 100644 Flappy_Bird/assets/redbird-midflap.png create mode 100644 Flappy_Bird/assets/redbird-upflap.png create mode 100644 Flappy_Bird/assets/yellowbird-downflap.png create mode 100644 Flappy_Bird/assets/yellowbird-midflap.png create mode 100644 Flappy_Bird/assets/yellowbird-upflap.png create mode 100644 Flappy_Bird/game.py diff --git a/Flappy_Bird/assets/background-day.png b/Flappy_Bird/assets/background-day.png new file mode 100644 index 0000000000000000000000000000000000000000..afcb5ec982a3de74cb9186f6af3ba329d63a22bb GIT binary patch literal 7026 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 b$3|uR-wMAWen9IL0NxiM9{6v+|M9;7ImZIa literal 0 HcmV?d00001 diff --git a/Flappy_Bird/assets/background-night.png b/Flappy_Bird/assets/background-night.png new file mode 100644 index 0000000000000000000000000000000000000000..e2a2b892200b83ec7b08dfc282850ce9a0c4a5a1 GIT binary patch literal 1101 zcmeAS@N?(olHy`uVBq!ia0y~yU{qjWU}9il28vvGxkds=v7|ftIx;Y9?C1WI$O_~u zBzpw;GB8xBF)%c=FfjZA3N^f7U???UV0e|lz+g3lfkC`r&aOZkpoDaQPlzi+`{Z>m zE-`FA#L(EoFnPhB9SjVc7#J2a{Qv*|dTHz{pfbiJZ+91twtG{nfE>;OkH}&M2EHR8 z%s5q>PZ}u5UgGKN%Kn&{hk;4>`7c$V5zJDaE{-7;x87cTow&+Nq~YS031S(IVi^a; zat?m;pU`gO#(s42%^6$Y^-Cx2{_CV>86OWc2Nm$_^Jd?p`oef0H-kc7!T%ZU+>iV@ z%l{o>{psmYsw+c^51jEW;xv#zpW!K8awWv{O`!}7H+P9 z>IVy){}=rU3Vhk{0T@tdpk~#pRVA)>7G#C&O3A+vy|4S~q^xHr9P@vAuD9Q{Do&S6 zY|GEsem0@`v8v5xTU@zs{YscDe7H61@5|6fw;rorU;mhO>Ah`VpGUo&^vi9vGfU{r zdDiXUrY`z=G?{H_TG@A-&!+`+GQNtx;hn$N_LGKVc^rq9{{#icrf09No$Gu)O-6e~ zX3_3X!gt$kWoG)e@MlF`-g&twye{ebqz8_^n`gz?yge(tUawQ!WbRw`-@o4$=loxN z{JWju$4`?kI9`rj{$$--VSRm0Ns~D%3O`-(|2C^I<@b@(-iO$>o_}3-No;wp#7&Ej zk0$+!a9n;hWp5?W*bc|X?_=sO`Q6Q&{mR|U&&O@nn@LZPBsRUu37E^jYO~{4#in;M zudJ%&UjJE`x5<0f+5M?co8HO4D*W_rp`YKG{+zUvMM^~hlWjLitINs1QmbBZn3cD^ z>f`&QM;RMf067H(`lXRjuIeczm#(&}4>PyhS>S@^cTq~3P@-RpzBUp<}lE%nBN z&p$sUXUy2Mr}k?8t2n)9yQe-rs`zN9>h?$Zj#&F)t9d;Ug?S?8I*+w<|K>gCgl&AV=2 ze{NR)?y~&DPsdV=EcAa*JEOFQA`1FD$s4SY7b--Q4XuoKjota!#*4 z9oxD7{-!5IeUc)bz!+kgs^$TVsimAkDjoruO)Q*3A+snJu8p~1uXk6~I!!-$GcYNt zmbgZgq$HN4S|t~y0x1R~14Bz)17lr7!w^FYD+41dLrZM~Gb;mwhgz10Q8eV{r(~v8 W;?^*sys;jX*gakST-G@yGywpL713t^ literal 0 HcmV?d00001 diff --git a/Flappy_Bird/assets/base.png b/Flappy_Bird/assets/base.png new file mode 100644 index 0000000000000000000000000000000000000000..c374f2b34f2d8a75f74641775970314b462cb337 GIT binary patch literal 470 zcmeAS@N?(olHy`uVBq!ia0y~yUG}$vdpD;3|NsAJp`$ub4P%nGy9>KmV#jMBhqJ&VvY3H^?+6GpPSxg< z1`4v5c>21sKW64(U=n`*OLYfOXql&rV@SoVx91!=nHU*Z1GOU#a)oVZ5`81@cw_el z_QdChXJ3}N|8|*uxqK%3FN-Rz*Q7`oU(j#<^uFNA z%(zmZi&aZpBT7;dOH!?pi&B9UgOP!urLKXouAyOwp@o%!k(HsPwt<FVdQ&MBb@03g?$h5!Hn literal 0 HcmV?d00001 diff --git a/Flappy_Bird/assets/bluebird-downflap.png b/Flappy_Bird/assets/bluebird-downflap.png new file mode 100644 index 0000000000000000000000000000000000000000..d82802ab8c75244ddbe55d20995eea4a4eea8d2d GIT binary patch literal 431 zcmeAS@N?(olHy`uVBq!ia0vp^N0k@Dkc1f0k@Dkco?L|9h+ zzw~&E;BHgtpWb3Y9IZ`R2c3>Rxfbxg*G2G}TughIl7yMAS(pF(`bVnj*;A~pf4-2| z3$#|X#5JNMC9x#cD!C{XNHG{07+UHY80#7uh8S8{85mg^T521ZSs55S)UrH`q9Hdw ZB{QuOw}uJjjrBkc44$rjF6*2UngDZRiP8W7 literal 0 HcmV?d00001 diff --git a/Flappy_Bird/assets/bluebird-upflap.png b/Flappy_Bird/assets/bluebird-upflap.png new file mode 100644 index 0000000000000000000000000000000000000000..900d012ccf161de85a09c017680812aa15e5140f GIT binary patch literal 431 zcmeAS@N?(olHy`uVBq!ia0vp^N0k@DkccptHiBgLV067Py>UftDnm{r-UW|D&CBX literal 0 HcmV?d00001 diff --git a/Flappy_Bird/assets/gameover.png b/Flappy_Bird/assets/gameover.png new file mode 100644 index 0000000000000000000000000000000000000000..b1df7f5757198bec3b165e12bc139b94178b8f19 GIT binary patch literal 758 zcmeAS@N?(olHy`uVBq!ia0vp^2Y^_Mg&9bS>v~=QQY`6?zK#qG8~eHcB(ehe3dtTp zz6=aistgPb%?u1b{{!il3=E|P3=FRl7#OT(0Cnb1ia+WGRBI666XN>+KTrui5MtpD zL_lSK7I-{KkT{)kY#vZKPf3tpFwlA?HfDB44p#0zv)_qt0E#mvdAqwXbg;^L06Clm z9+AZi4BWyX%*Zfnjs#GUy~NYkmHja@4+E3%^IxhvfO@8Rx;Tb-9KSmKVD4c99@ni- z6IhviFD!5n&tUW5pQ+GrG24IE0*Ai6X|3ym)-4d-(xeqFXn{4@1l2{lx8d|iC} zkYKRyDWm<|FFuJ}t9rC^!>{QK4!%0C_*=p+*QX@Q8NAMrYM7qS=$9^Qwf?+pTIsI| zCGtVCjI$QCr5u>jz3JY^c_IhCZ`zXJ&A6fT0E68$WkKP!K@C=i3qLkKP;jW-pxkV6 zz?bQSrNym=jgA5V*M2e{xG(ZRiXrZawnOAgF@|`zH@~7B{=7TI{HpTWi=PdjLO+T# z4oU-o9h?Opt8>ukAa*&$cI$lNeYxFSSTa(s+Mk@;w!X`6s)5n8c(H zn*t+EwZt`|BqgyV)hf9t6-Y4{85mmX8W`&u8ip8JSQ!{u8Cq%^m{}PZJk+v0jG`eo aKP5A*61Rp4<&E_~4Gf;HelF{r5}E*LS`Uf< literal 0 HcmV?d00001 diff --git a/Flappy_Bird/assets/message.png b/Flappy_Bird/assets/message.png new file mode 100644 index 0000000000000000000000000000000000000000..9243ab58b2910ae63393eb28ac5867237826d7e0 GIT binary patch literal 1602 zcmZ{kdpOg39LIldIW|ifigMOTTMu)YOPX;kovjgbzqjPBo3RiTT`cC3OLY=0TXb=Y zmBic&vucSriOh8gtz-$C)XuLz&mZUeJm2T_d4Im2_xE}K@qNCT?ye*lL=OT00L;me z;0clo018lLC9o>A@?e5cj&dM70KmgM=vs&hsJDeVdXfR)G!g*L(*Zyx2RR1-2^awQ z7z_ZoLIBtlbL9|kA2_?i-Nl;-QZ5Ilel2e-X?1lKl>S5hK)K`K;GpMjqTCSnWz$Ym z@K`zC)71+Mpw0Jr1l|WIggTQ53UWo0F;J+*ItIi602KafD*!icZU&pG@lIr-sz^y4 zP=wE{BEj^^%T5Fb@1%F1N66Hh7%d>!v!o_uAmJMNo1$^yoJv9 z&8+QAN{w_yCR4T3J^s6vxOB+tc1jB+pUik+ROrlGR)1gAr}jdlH1ID!()zr71gJpf4^jw zX7D}I?w^tkxt~WQdo)tH@Gatcoq5;-y;-{pA^gdsX`I(<@6o6&g^C2%^v5OoJJWa1 zlkWgy#u7vFW05U2p-_GMrC!3MO@JPo5~y6Gb26D;kj#@vSJ$sZ|5#Y}E6{)-;+v%6 z;EW(knzEdgRGGtQ4?wuN?)PoUnW!`$F1gSEovhBwi%E+eLS=M*DL>FqN$m0HQo}SC zNmz5ClTD?>&mLPFn4>LH?vg2#PWk5ITNlav@^!3aEqP!PFQEo)J)SELSEkjhl&ppG z5D8L)vFcl5?oRs*afmSMfh+gth?#zkAXO?-w_oV+PVagxKAfXb%OiMyP*;JyD3*rd zsBbF%Tv|^@qk|7GS&PZsMb8b43-pa$Si%rKbF>Oe4N4D4-lJCAFvuG=o=43VYuRUn zA!dB?%FY?5Dd`H?gr`dEvxb+dXx~gJQxjM5`zWe&6H3lc#(nH{(YXQx2&}w~keLx| z;rnFLJ%U~Xo4PDm^v4e+$Y|I?hrCeEF-cms!^IKjlv#|r3JtsYA@BWOZ`)U}Kw?sB zIHt`fs+%ahwTVb?c~RfwI~58gaa+SD$Mo|Gi)KS1uBahxWajI=*fPRdOBIuo zzad+0m=GkVZ1Xuwk}cEv;{qdOgnyged0ojJd$lrFV!E|QwN68k>EPM~`;*l|6W(I^ zbU0_Udtvq2tG9w#QbK7`irpd3TfxA%x#h-UR1p3khuNL>sy=Novll<1*{+=5b&Qp> zIDNz=`=x7xF2&^xb;i*-a?RLc`@o4|NRU7tiW-#`=b}uAqoR~D zECC;Gf~2SBK)DEC=oO@XU!L`KH0OIO?&or*fS-L0{-713C{+!MVI!u@&M4_?Q$<*a zbcV5NFz&!$94yk(B5C@aj&9?7+;)N^qIgU__c)7=-R}81aMC(I#`hz6WlN()eI8rY z?65zO)Phn$(1C)do!2Q##mM{e>n$uZI-eRR>TG-xmyEcv#gEZ0;>F7J-=S!C*=8f1 z)7N?COlx~tj5|amS1=f^lqGUn=fO`A8Bg?&4-bitz=fTN00CHF%xz3CmL}%r-sV^w s#sX(ipfF?Y@85{o%=IVJaEDwkZF za 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 literal 0 HcmV?d00001 diff --git a/Flappy_Bird/assets/redbird-midflap.png b/Flappy_Bird/assets/redbird-midflap.png new file mode 100644 index 0000000000000000000000000000000000000000..a915f7ef6e7a12262ce0d45409fff6c8d274bf54 GIT binary patch literal 426 zcmeAS@N?(olHy`uVBq!ia0vp^N0k@DKgImN ze*OAm!EpWAnIGGYFY7b>|NlSn_`7bPG-FASUoeBivm0q3PLj8~3rE|%sZ~G@XMsm# zF#`j)FbFd;%$g$s6l5>)^mS!_%*?~UB>eoB>JFe#mZytjh{WaAix+thC~&X@gzXTG zIVc)&5J-NlR@%BPqpE(72Ajyn14`cen3hbLV0`XS)YK0F0vnczGzAN+_~+e!+40TQ zoF|iWmdNXggm9Y~S#58#G8b}<`1WAm7U6>%Qa1+f`Ta{+e<#E96XuT2PhZ3UZB;FC zjVMV;EJ?LWE=mPb3`PcqmbwPUx`u`!h89)^MplNF+6HD;1_lqcEDxh-$jwj5OsmAL UVM2LhJx~LKr>mdKI;Vst0BZ$^)&Kwi literal 0 HcmV?d00001 diff --git a/Flappy_Bird/assets/redbird-upflap.png b/Flappy_Bird/assets/redbird-upflap.png new file mode 100644 index 0000000000000000000000000000000000000000..f9ed856893d1485df2ff3db459974c5e861b611e GIT binary patch literal 425 zcmeAS@N?(olHy`uVBq!ia0vp^N0k@DKgImN ze*OAm!EpWAnIGGYFY7b>|NlSn_`7bPG-FASUoeBivm0q3PLj8~3rE|%sZ~G@XMsm# zF#`j)FbFd;%$g$s6l5>)^mS!_%*?~UB>eoB>JFe#rl*Tzh{WaIix+thC~&X@gzXTG zIVc)&P&B6TYj?ucF15Y-wSi3@DUGeu-Y_khGQs%WqUy9(&)r)ltqBsD)AZw|{HII4 zw-!ab{WnR&>*&I$f=SmFbu2j7DdVCeF`dt;Aev2jDSzGH&VHNyD=oH*D*0^$TB=&& z8c~vxSdwa$T$Bo=7>o=IEp-iybqx(e3@xk-jI0bTwGGUy3=AG>Ssq5wkei>9nO2Eg U!-Vq2dY}ddPgg&ebxsLQ0NS;QX8-^I literal 0 HcmV?d00001 diff --git a/Flappy_Bird/assets/yellowbird-downflap.png b/Flappy_Bird/assets/yellowbird-downflap.png new file mode 100644 index 0000000000000000000000000000000000000000..e9e1c77b9deb38738f6f4d184243143bca2da46b GIT binary patch literal 426 zcmeAS@N?(olHy`uVBq!ia0vp^N0k@DU)Otn z{rdG|yYcmBXZ~0)JZRAQ|NsAjlBe20X~vQuzhDN3XE)M7oFs2|7ml`jQ>%a+&H|6f zVg?3oVGw3ym^DWND9B#o>Fdh=n3;!xN%;9M)g3^gEKe855Q)pZ7Xx_@DDbdch_c|` z+Rz#`qc!rtzdq>=sjVsBUE?z}5|%k^4ByAJ!`ka$T!g!ToEOuzDa{u&IhFo(WoYXz zDx9oRkXI(;$Etnt%hpG8VzmpM7VpkfwA$Ns>~Px5;^<#p`}Q%EMVg;vcHSliv{kjl zHKHUXu_Vlzw{7+P2v7+D!wY8#kY85lg&vOJ8UAvZrIGp!Q0 Uh6&}3^*{{_p00i_>zopr0M`A6wg3PC literal 0 HcmV?d00001 diff --git a/Flappy_Bird/assets/yellowbird-midflap.png b/Flappy_Bird/assets/yellowbird-midflap.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca3c2d034b2332726bb6157591ee3319900c2fc GIT binary patch literal 425 zcmeAS@N?(olHy`uVBq!ia0vp^N0k@DU)Otn z{rdG|yYcmBXZ~0)JZRAQ|NsAjlBe20X~vQuzhDN3XE)M7oFs2|7ml`jQ>%a+&H|6f zVg?3oVGw3ym^DWND9B#o>Fdh=n3;!xN%;9M)g3^gOivfb5Q)pJ7ccT2P~cz*2-_hV zaZog3q4tiZ*WX=k-CFeW?_KXB9ZGT)DW}32LR~d)aPO9UxKJfwxlGFf6@%Z?=Pl^{ zvG%BD+$I544c4p8tvx5#F1#mwQfZCt4!*T6202kV(`MNHKjQ6|w8gBn>)PVeKuc9i zTq8@t-i!lHI literal 0 HcmV?d00001 diff --git a/Flappy_Bird/assets/yellowbird-upflap.png b/Flappy_Bird/assets/yellowbird-upflap.png new file mode 100644 index 0000000000000000000000000000000000000000..2f693da65360f492a3b364b2231c4419d9c782af GIT binary patch literal 427 zcmeAS@N?(olHy`uVBq!ia0vp^N0k@DU)Otn z{rdG|yYcmBXZ~0)JZRAQ|NsAjlBe20X~vQuzhDN3XE)M7oFs2|7ml`jQ>%a+&H|6f zVg?3oVGw3ym^DWND9B#o>Fdh=n3;!xN%;9M)g3^gY)==*5Q)pZ7b67^DDbdch=}0c z*w7lWf>q~8UGW7c%d}nbAJ~jk1Y89cDsE;t(-Tx6cDq}mWY$sdu9K+~ws_3@r^r9I zCHG+9?$S+MuIzlKO>=(;hl+0XPf?aSSe>cdvL$iD>MaNR?LSVG4zn=ZxrY0iGSFJp z64!{5l*E!$tK_0oAjM#0U}&jpV61Cs7-DE)Wng4wXsK;rW@TXTP|NZ#iiX_$l+3hB W+!`j7H`W6+FnGH9xvX= 1024: + screen.blit(pipe_surface, pipe) + else: + flip_pipe = pygame.transform.flip(pipe_surface, False, True) + screen.blit(flip_pipe, pipe) + + +def check_collision(pipes): + for pipe in pipes: + if bird_rect.colliderect(pipe): + return False + if bird_rect.top <= -100 or bird_rect.bottom >= 900: + return False + return True + + +def rotate_bird(bird): + new_bird = pygame.transform.rotozoom(bird, -bird_movement*3, 1) + return new_bird + + +def bird_animation(): + new_bird = bird_frames[bird_index] + new_bird_rect = new_bird.get_rect(center=(100, bird_rect.centery)) + return new_bird, new_bird_rect + + +def score_display(game_state): + if game_state == 'main_game': + + score_surface = game_font.render( + f'Score:{int(score)}', True, (255, 255, 255)) + score_rect = score_surface.get_rect(center=(288, 100)) + screen.blit(score_surface, score_rect) + if game_state == 'game_over': + score_surface = game_font.render( + f'Score:{int(score)}', True, (255, 255, 255)) + score_rect = score_surface.get_rect(center=(288, 100)) + screen.blit(score_surface, score_rect) + + high_score_surface = game_font.render( + f'High Score:{int(high_score)}', True, (255, 255, 255)) + high_score_rect = high_score_surface.get_rect(center=(288, 850)) + screen.blit(high_score_surface, high_score_rect) + + +def update_score(score, high_score): + if score > high_score: + high_score = score + return high_score + + +pygame.init() +screen = pygame.display.set_mode((576, 1024)) +clock = pygame.time.Clock() +game_font = pygame.font.Font('04B_19.ttf', 40) + +# game variables +gravity = 0.25 +bird_movement = 0 +game_active = True +score = 0 +high_score = 0 + +bg_surface = pygame.image.load('assets/background-day.png').convert() +bg_surface = pygame.transform.scale2x(bg_surface) + +floor_surface = pygame.image.load('assets/base.png').convert() +floor_surface = pygame.transform.scale2x(floor_surface) +floor_x_pos = 0 + +bird_downflap = pygame.transform.scale2x(pygame.image.load( + 'assets/bluebird-downflap.png')).convert_alpha() +bird_midflap = pygame.transform.scale2x(pygame.image.load( + 'assets/bluebird-midflap.png')).convert_alpha() +bird_upflap = pygame.transform.scale2x(pygame.image.load( + 'assets/bluebird-upflap.png')).convert_alpha() +bird_frames = [bird_downflap, bird_midflap, bird_upflap] +bird_index = 0 +bird_surface = bird_frames[bird_index] +bird_rect = bird_surface.get_rect(center=(100, 512)) + + +BIRDFLAP = pygame.USEREVENT + 1 +pygame.time.set_timer(BIRDFLAP, 200) + + + +pipe_surface = pygame.image.load('assets/pipe-green.png') +pipe_surface = pygame.transform.scale2x(pipe_surface) +pipe_list = [] +pipe_height = [400, 600, 800] +SPAWNPIPE = pygame.USEREVENT +pygame.time.set_timer(SPAWNPIPE, 1200) + +game_over_surface = pygame.transform.scale2x( + pygame.image.load('assets/message.png').convert_alpha()) +game_over_rect = game_over_surface.get_rect(center=(288, 512)) + +while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + sys.exit() + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_SPACE and game_active: + bird_movement = 0 + bird_movement -= 12 + if event.key == pygame.K_SPACE and game_active == False: + game_active = True + pipe_list.clear() + bird_rect.center = (100, 512) + bird_movement = 0 + score = 0 + if event.type == SPAWNPIPE: + pipe_list.extend(create_pipe()) + if event.type == BIRDFLAP: + if bird_index < 2: + bird_index += 1 + else: + bird_index = 0 + bird_surface, bird_rect = bird_animation() + screen.blit(bg_surface, (0, 0)) + + if game_active: + + bird_movement += gravity + rotated_bird = rotate_bird(bird_surface) + bird_rect.centery += bird_movement + screen.blit(rotated_bird, bird_rect) + + game_active = check_collision(pipe_list) + + pipe_list = move_pipes(pipe_list) + draw_pipes(pipe_list) + score += 0.01 + score_display('main_game') + else: + screen.blit(game_over_surface, game_over_rect) + high_score = update_score(score, high_score) + score_display('game_over') + + floor_x_pos -= 1 + draw_floor() + + if floor_x_pos <= -576: + floor_x_pos = 0 + + pygame.display.update() + clock.tick(120) From e29fd101b41a64ea4106cd53cbfc2447ceaf3dc6 Mon Sep 17 00:00:00 2001 From: Aaryansh Sahay <53135035+aaryanshsahay@users.noreply.github.com> Date: Sun, 2 Oct 2022 15:20:44 +0530 Subject: [PATCH 13/16] Create readme.md --- Flappy_Bird/readme.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 Flappy_Bird/readme.md diff --git a/Flappy_Bird/readme.md b/Flappy_Bird/readme.md new file mode 100644 index 0000000..35fe11b --- /dev/null +++ b/Flappy_Bird/readme.md @@ -0,0 +1,5 @@ +Created at : 3rd August 2020 + +Flappy bird made using pygame . + +run game.py to start the game! From fffece07c530da6af8d8ba1b7bf4782af57d464e Mon Sep 17 00:00:00 2001 From: Aaryansh Sahay <53135035+aaryanshsahay@users.noreply.github.com> Date: Sun, 2 Oct 2022 15:22:43 +0530 Subject: [PATCH 14/16] Update readme.md --- Flappy_Bird/readme.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Flappy_Bird/readme.md b/Flappy_Bird/readme.md index 35fe11b..db921f8 100644 --- a/Flappy_Bird/readme.md +++ b/Flappy_Bird/readme.md @@ -2,4 +2,6 @@ Created at : 3rd August 2020 Flappy bird made using pygame . +Need to have the font -> 04b_19.tiff installed + run game.py to start the game! From d630f5a4045cf66500067c5390194642a0b2b782 Mon Sep 17 00:00:00 2001 From: Aaryansh Sahay <53135035+aaryanshsahay@users.noreply.github.com> Date: Sun, 2 Oct 2022 15:24:18 +0530 Subject: [PATCH 15/16] Update readme.md --- Flappy_Bird/readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Flappy_Bird/readme.md b/Flappy_Bird/readme.md index db921f8..f6af77f 100644 --- a/Flappy_Bird/readme.md +++ b/Flappy_Bird/readme.md @@ -2,6 +2,7 @@ Created at : 3rd August 2020 Flappy bird made using pygame . -Need to have the font -> 04b_19.tiff installed +![image](https://user-images.githubusercontent.com/53135035/193448320-63c9befb-845a-48bd-a7c2-dfcdace2623d.png) + run game.py to start the game! From 0cf867e6d3540a4a60807b2081c93798aa7e67db Mon Sep 17 00:00:00 2001 From: Aaryansh Sahay <53135035+aaryanshsahay@users.noreply.github.com> Date: Sun, 2 Oct 2022 15:24:53 +0530 Subject: [PATCH 16/16] Add files via upload --- Flappy_Bird/04B_19.TTF | Bin 0 -> 6632 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Flappy_Bird/04B_19.TTF diff --git a/Flappy_Bird/04B_19.TTF b/Flappy_Bird/04B_19.TTF new file mode 100644 index 0000000000000000000000000000000000000000..6338c199e1d86eaec23fd27a1301a39d89d855fc GIT binary patch literal 6632 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 bk@G`C%_GH;;lkK=&W`kt^^Kn&8