snakeware

Python-based Linux distro for x86-64 and RPi
git clone git://squid-tech.com/snakeware.git
Log | Files | Refs | README

commit 873d0c424cf2d526380c219164f6460300b1a83f
parent fa12656edf3e48a113bbd67b186efc24f252bbc1
Author: Josh Moore <jxm5210@rit.edu>
Date:   Wed, 27 May 2020 21:01:22 -0400

Add pong game

Diffstat:
Asnakewm/apps/games/pong/README.txt | 4++++
Asnakewm/apps/games/pong/__init__.py | 16++++++++++++++++
Asnakewm/apps/games/pong/ball.py | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asnakewm/apps/games/pong/bat.py | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asnakewm/apps/games/pong/pong.py | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asnakewm/apps/games/pong/pongwindow.py | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Asnakewm/apps/games/pong/score.py | 29+++++++++++++++++++++++++++++
Asnakewm/apps/games/pong/wall.py | 10++++++++++
Msnakewm/wm.py | 6++++--
9 files changed, 303 insertions(+), 2 deletions(-)

diff --git a/snakewm/apps/games/pong/README.txt b/snakewm/apps/games/pong/README.txt @@ -0,0 +1,4 @@ +This Pong game was adapted from MyreMylar's pygame_gui_examples repo. +https://github.com/MyreMylar/pygame_gui_examples/ + +Left player moves with W/S, right player moves with Up/Down. diff --git a/snakewm/apps/games/pong/__init__.py b/snakewm/apps/games/pong/__init__.py @@ -0,0 +1,16 @@ +from .pongwindow import PongWindow + +def load(manager, params): + """ + Create Pong game and add it to the UI manager. + params[0] should be the desired size, if other than default. + """ + default_size = (50, 50) + + if params is not None and len(params) > 0: + # create PongWindow of user-specified size + PongWindow(params[0], manager) + else: + # create PongWindow of default size + PongWindow(default_size, manager) + diff --git a/snakewm/apps/games/pong/ball.py b/snakewm/apps/games/pong/ball.py @@ -0,0 +1,62 @@ +import pygame +import math +import random + + +class Ball: + def __init__(self, start_position): + self.rect = pygame.Rect(start_position, (5, 5)) + self.colour = pygame.Color(255, 255, 255) + self.position = [float(start_position[0]), float(start_position[1])] + self.start_position = [self.position[0], self.position[1]] + self.ball_speed = 120.0 + self.max_bat_bounce_angle = 5.0 * math.pi/12.0 + self.collided = False + + self.velocity = [0.0, 0.0] + self.create_random_start_vector() + + def render(self, screen): + pygame.draw.rect(screen, self.colour, self.rect) + + def create_random_start_vector(self): + y_random = random.uniform(-0.5, 0.5) + x_random = 1.0 - abs(y_random) + if random.randint(0, 1) == 1: + x_random = x_random * -1.0 + self.velocity = [x_random * self.ball_speed, y_random * self.ball_speed] + + def reset(self): + self.position = [self.start_position[0], self.start_position[1]] + self.create_random_start_vector() + + def update(self, dt, bats, walls): + self.position[0] += self.velocity[0] * dt + self.position[1] += self.velocity[1] * dt + self.rect.x = self.position[0] + self.rect.y = self.position[1] + + collided_this_frame = False + for wall in walls: + if self.rect.colliderect(wall.rect): + collided_this_frame = True + if not self.collided: + self.collided = True + self.velocity[1] = self.velocity[1] * -1 + + for bat in bats: + if self.rect.colliderect(bat.rect): + collided_this_frame = True + if not self.collided: + self.collided = True + bat_y_centre = bat.position[1] + (bat.length/2) + ball_y_centre = self.position[1] + 5 + relative_intersect_y = bat_y_centre - ball_y_centre # should be in 'bat space' between -50 and +50 + normalized_relative_intersect_y = relative_intersect_y/(bat.length/2) + bounce_angle = normalized_relative_intersect_y * self.max_bat_bounce_angle + + self.velocity[0] = self.velocity[0] * -1 + self.velocity[1] = self.ball_speed * -math.sin(bounce_angle) + + if not collided_this_frame: + self.collided = False diff --git a/snakewm/apps/games/pong/bat.py b/snakewm/apps/games/pong/bat.py @@ -0,0 +1,59 @@ +import pygame +from pygame.locals import * + + +class ControlScheme: + def __init__(self): + self.up = K_UP + self.down = K_DOWN + + +class Bat: + def __init__(self, start_pos, control_scheme, court_size): + self.control_scheme = control_scheme + self.move_up = False + self.move_down = False + self.move_speed = 450.0 + + self.court_size = court_size + + self.length = 30.0 + self.width = 5.0 + + self.position = [float(start_pos[0]), float(start_pos[1])] + + self.rect = pygame.Rect((start_pos[0], start_pos[1]), (self.width, self.length)) + self.colour = pygame.Color("#FFFFFF") + + def process_event(self, event): + if event.type == KEYDOWN: + if event.key == self.control_scheme.up: + self.move_up = True + if event.key == self.control_scheme.down: + self.move_down = True + + if event.type == KEYUP: + if event.key == self.control_scheme.up: + self.move_up = False + if event.key == self.control_scheme.down: + self.move_down = False + + def update(self, dt): + if self.move_up: + self.position[1] -= dt * self.move_speed + + if self.position[1] < 10.0: + self.position[1] = 10.0 + + self.rect.y = self.position[1] + + if self.move_down: + self.position[1] += dt * self.move_speed + + if self.position[1] > self.court_size[1] - self.length - 10: + self.position[1] = self.court_size[1] - self.length - 10 + + self.rect.y = self.position[1] + + def render(self, screen): + pygame.draw.rect(screen, self.colour, self.rect) diff --git a/snakewm/apps/games/pong/pong.py b/snakewm/apps/games/pong/pong.py @@ -0,0 +1,66 @@ +import pygame +from pygame.locals import * + +from .wall import Wall +from .bat import Bat, ControlScheme +from .ball import Ball +from .score import Score + + +class PongGame: + def __init__(self, size): + self.size = size + self.background = pygame.Surface(size) # make a background surface + self.background = self.background.convert() + self.background.fill((0, 0, 0)) + + font = pygame.font.Font(None, 24) + + self.score = Score(font) + + self.walls = [Wall((5, 5), (size[0] - 10, 10)), + Wall((5, size[1] - 10), (size[0] - 10, size[1] - 5))] + + self.bats = [] + + control_scheme_1 = ControlScheme() + control_scheme_1.up = K_w + control_scheme_1.down = K_s + + control_scheme_2 = ControlScheme() + control_scheme_2.up = K_UP + control_scheme_2.down = K_DOWN + + self.bats.append(Bat((5, int(size[1]/2)), control_scheme_1, self.size)) + self.bats.append(Bat((size[0] - 10, int(size[1]/2)), control_scheme_2, self.size)) + + self.ball = Ball((int(size[0]/2), int(size[1]/2))) + + def process_event(self, event): + for bat in self.bats: + bat.process_event(event) + + def update(self, time_delta): + for bat in self.bats: + bat.update(time_delta) + + self.ball.update(time_delta, self.bats, self.walls) + + if self.ball.position[0] < 0: + self.ball.reset() + self.score.increase_player_2_score() + elif self.ball.position[0] > self.size[0]: + self.ball.reset() + self.score.increase_player_1_score() + + def draw(self, surface): + surface.blit(self.background, (0, 0)) + + for wall in self.walls: + wall.render(surface) + + for bat in self.bats: + bat.render(surface) + + self.ball.render(surface) + self.score.render(surface, self.size) diff --git a/snakewm/apps/games/pong/pongwindow.py b/snakewm/apps/games/pong/pongwindow.py @@ -0,0 +1,53 @@ +import pygame +import pygame_gui + +from pygame_gui.ui_manager import UIManager +from pygame_gui.elements.ui_window import UIWindow +from pygame_gui.elements.ui_image import UIImage + +from .pong import PongGame + + +class PongWindow(UIWindow): + def __init__(self, position, ui_manager): + super().__init__(pygame.Rect(position, (320, 240)), ui_manager, + window_display_title='Super Awesome Pong!', + object_id='#pong_window') + + game_surface_size = self.get_container().get_size() + self.game_surface_element = UIImage(pygame.Rect((0, 0), + game_surface_size), + pygame.Surface(game_surface_size).convert(), + manager=ui_manager, + container=self, + parent_element=self) + + self.pong_game = PongGame(game_surface_size) + + #self.is_active = False + self.is_active = True + + def process_event(self, event): + handled = super().process_event(event) + if (event.type == pygame.USEREVENT and + event.user_type == pygame_gui.UI_BUTTON_PRESSED and + event.ui_object_id == "#pong_window.#title_bar" and + event.ui_element == self.title_bar): + handled = True + event_data = {'user_type': 'pong_window_selected', + 'ui_element': self, + 'ui_object_id': self.most_specific_combined_id} + window_selected_event = pygame.event.Event(pygame.USEREVENT, + event_data) + pygame.event.post(window_selected_event) + #if self.is_active: + handled = self.pong_game.process_event(event) + return handled + + def update(self, time_delta): + if self.alive() and self.is_active: + self.pong_game.update(time_delta) + + super().update(time_delta) + + self.pong_game.draw(self.game_surface_element.image) diff --git a/snakewm/apps/games/pong/score.py b/snakewm/apps/games/pong/score.py @@ -0,0 +1,29 @@ +import pygame + + +class Score: + def __init__(self, font): + self.player_1_score = 0 + self.player_2_score = 0 + self.font = font + + self.score_string = None + self.score_text_render = None + + self.update_score_text() + + def update_score_text(self): + self.score_string = str(self.player_1_score) + " - " + str(self.player_2_score) + self.score_text_render = self.font.render(self.score_string, True, pygame.Color(200, 200, 200)) + + def render(self, screen, size): + screen.blit(self.score_text_render, self.score_text_render.get_rect(centerx=size[0]/2, + centery=size[1]/10)) + + def increase_player_1_score(self): + self.player_1_score += 1 + self.update_score_text() + + def increase_player_2_score(self): + self.player_2_score += 1 + self.update_score_text() diff --git a/snakewm/apps/games/pong/wall.py b/snakewm/apps/games/pong/wall.py @@ -0,0 +1,10 @@ +import pygame + + +class Wall: + def __init__(self, top_left, bottom_right): + self.rect = pygame.Rect(top_left, (bottom_right[0] - top_left[0], bottom_right[1] - top_left[1])) + self.colour = pygame.Color("#C8C8C8") + + def render(self, screen): + pygame.draw.rect(screen, self.colour, self.rect) diff --git a/snakewm/wm.py b/snakewm/wm.py @@ -47,8 +47,8 @@ class SnakeWM: def loadapp(self, app, params=None): """ - Load and run an app based on its location (ie app="apps.test.HelloWorld"). - Apps are basically just Python packages. The loaded app directory must contain an __init__.py + Load and run a Python module as an app (ie "apps.test.HelloWorld"). + Apps are basically just Python packages. The loaded app package must contain an __init__.py with a load() function that accepts a UIManager parameter and a params list parameter. The load() function should create an instance of the app to load and add the app UI to @@ -76,6 +76,8 @@ class SnakeWM: running = False elif event.key == pygame.K_h: self.loadapp("apps.test.HelloWorld") + elif event.key == pygame.K_p: + self.loadapp("apps.games.pong") self.MANAGER.process_events(event)