From 6429ebde910dfcf1f9ad05e3b6eaa54a56ab8ca1 Mon Sep 17 00:00:00 2001 From: schneider Date: Thu, 15 Dec 2011 21:08:02 +0100 Subject: [PATCH] added py-pong --- tools/game/py-pong/assets/ball.png | Bin 0 -> 2801 bytes tools/game/py-pong/assets/bounce-paddle.wav | Bin 0 -> 5532 bytes tools/game/py-pong/assets/bounce-wall.wav | Bin 0 -> 10924 bytes tools/game/py-pong/assets/digit_0.png | Bin 0 -> 2851 bytes tools/game/py-pong/assets/digit_1.png | Bin 0 -> 2834 bytes tools/game/py-pong/assets/digit_2.png | Bin 0 -> 2855 bytes tools/game/py-pong/assets/digit_3.png | Bin 0 -> 2850 bytes tools/game/py-pong/assets/digit_4.png | Bin 0 -> 2855 bytes tools/game/py-pong/assets/digit_5.png | Bin 0 -> 2856 bytes tools/game/py-pong/assets/digit_6.png | Bin 0 -> 2860 bytes tools/game/py-pong/assets/digit_7.png | Bin 0 -> 2843 bytes tools/game/py-pong/assets/digit_8.png | Bin 0 -> 2854 bytes tools/game/py-pong/assets/digit_9.png | Bin 0 -> 2857 bytes tools/game/py-pong/assets/dividing-line.png | Bin 0 -> 2837 bytes tools/game/py-pong/assets/logo.png | Bin 0 -> 1083 bytes tools/game/py-pong/assets/missed-ball.wav | Bin 0 -> 50860 bytes tools/game/py-pong/assets/paddle.png | Bin 0 -> 2805 bytes tools/game/py-pong/main.py | 67 +++++++++ tools/game/py-pong/pypong/__init__.py | 150 ++++++++++++++++++++ tools/game/py-pong/pypong/entity.py | 87 ++++++++++++ tools/game/py-pong/pypong/player.py | 81 +++++++++++ 21 files changed, 385 insertions(+) create mode 100644 tools/game/py-pong/assets/ball.png create mode 100644 tools/game/py-pong/assets/bounce-paddle.wav create mode 100644 tools/game/py-pong/assets/bounce-wall.wav create mode 100644 tools/game/py-pong/assets/digit_0.png create mode 100644 tools/game/py-pong/assets/digit_1.png create mode 100644 tools/game/py-pong/assets/digit_2.png create mode 100644 tools/game/py-pong/assets/digit_3.png create mode 100644 tools/game/py-pong/assets/digit_4.png create mode 100644 tools/game/py-pong/assets/digit_5.png create mode 100644 tools/game/py-pong/assets/digit_6.png create mode 100644 tools/game/py-pong/assets/digit_7.png create mode 100644 tools/game/py-pong/assets/digit_8.png create mode 100644 tools/game/py-pong/assets/digit_9.png create mode 100644 tools/game/py-pong/assets/dividing-line.png create mode 100644 tools/game/py-pong/assets/logo.png create mode 100644 tools/game/py-pong/assets/missed-ball.wav create mode 100644 tools/game/py-pong/assets/paddle.png create mode 100644 tools/game/py-pong/main.py create mode 100644 tools/game/py-pong/pypong/__init__.py create mode 100644 tools/game/py-pong/pypong/entity.py create mode 100644 tools/game/py-pong/pypong/player.py diff --git a/tools/game/py-pong/assets/ball.png b/tools/game/py-pong/assets/ball.png new file mode 100644 index 0000000000000000000000000000000000000000..f80e5218673ef787e1ddaa0c6adfdcc8a97a01a1 GIT binary patch literal 2801 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 E0Bp?U=l}o! literal 0 HcmV?d00001 diff --git a/tools/game/py-pong/assets/bounce-wall.wav b/tools/game/py-pong/assets/bounce-wall.wav new file mode 100644 index 0000000000000000000000000000000000000000..bd9f843c281971b7890cfa1831bba812661ed2dc GIT binary patch literal 10924 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 BLk<7{ literal 0 HcmV?d00001 diff --git a/tools/game/py-pong/assets/digit_1.png b/tools/game/py-pong/assets/digit_1.png new file mode 100644 index 0000000000000000000000000000000000000000..69ff19572c8c3f463e839e76f87778c70f4beb51 GIT binary patch literal 2834 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 FV1kFZNEZMA literal 0 HcmV?d00001 diff --git a/tools/game/py-pong/assets/digit_3.png b/tools/game/py-pong/assets/digit_3.png new file mode 100644 index 0000000000000000000000000000000000000000..74df4fe8df3f669be78c0758c1eb0d02486e55b4 GIT binary patch literal 2850 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 ArvLx| literal 0 HcmV?d00001 diff --git a/tools/game/py-pong/assets/digit_4.png b/tools/game/py-pong/assets/digit_4.png new file mode 100644 index 0000000000000000000000000000000000000000..5f5b150f0db5ca49d034bbdddc6b1141daba9e29 GIT binary patch literal 2855 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 FV1nKEL;(N* literal 0 HcmV?d00001 diff --git a/tools/game/py-pong/assets/digit_5.png b/tools/game/py-pong/assets/digit_5.png new file mode 100644 index 0000000000000000000000000000000000000000..24eaa605e863ca6721d8988ee8fd0228a02a8f53 GIT binary patch literal 2856 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 Eg1^;7O8@`> literal 0 HcmV?d00001 diff --git a/tools/game/py-pong/assets/digit_9.png b/tools/game/py-pong/assets/digit_9.png new file mode 100644 index 0000000000000000000000000000000000000000..c80204b3281297b450120222ae0a85d17bee0e9f GIT binary patch literal 2857 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 Hu0mjfF@!`s literal 0 HcmV?d00001 diff --git a/tools/game/py-pong/assets/dividing-line.png b/tools/game/py-pong/assets/dividing-line.png new file mode 100644 index 0000000000000000000000000000000000000000..105682b4df770adb862c2dc42c57781e8a5280b6 GIT binary patch literal 2837 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⁣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 literal 0 HcmV?d00001 diff --git a/tools/game/py-pong/assets/paddle.png b/tools/game/py-pong/assets/paddle.png new file mode 100644 index 0000000000000000000000000000000000000000..7204eec9e0c10f35a648193cf5348673838e4774 GIT binary patch literal 2805 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 0 and timestamp < now: + timestamp = now + 5000 + print clock.get_fps() + input_state['key'] = pygame.key.get_pressed() + input_state['mouse'] = pygame.mouse.get_pos() + game.update() + game.draw(output_surface) + #~ pygame.surfarray.pixels_alpha(output_surface)[:,::2] = 12 + display_surface.blit(output_surface, (0,0)) + if debug_surface: + display_surface.blit(debug_surface, (0,0)) + pygame.display.flip() + for event in pygame.event.get(): + if event.type == pygame.QUIT: + game.running = False + elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: + game.running = False + +if __name__ == '__main__': run() diff --git a/tools/game/py-pong/pypong/__init__.py b/tools/game/py-pong/pypong/__init__.py new file mode 100644 index 0000000..856f0e5 --- /dev/null +++ b/tools/game/py-pong/pypong/__init__.py @@ -0,0 +1,150 @@ +import pygame, math, random, entity + +def load_image(path): + surface = pygame.image.load(path) + surface.convert() + pygame.surfarray.pixels3d(surface)[:,:,0:1:] = 0 + return surface + +def line_line_intersect(x1, y1, x2, y2, x3, y3, x4, y4): + # Taken from http://paulbourke.net/geometry/lineline2d/ + # Denominator for ua and ub are the same, so store this calculation + d = float((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)) + # n_a and n_b are calculated as seperate values for readability + n_a = float((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) + n_b = float((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) + # Make sure there is not a division by zero - this also indicates that + # the lines are parallel. + # If n_a and n_b were both equal to zero the lines would be on top of each + # other (coincidental). This check is not done because it is not + # necessary for this implementation (the parallel check accounts for this). + if d == 0: + return False + # Calculate the intermediate fractional point that the lines potentially intersect. + ua = n_a / d + ub = n_b / d + # The fractional point will be between 0 and 1 inclusive if the lines + # intersect. If the fractional calculation is larger than 1 or smaller + # than 0 the lines would need to be longer to intersect. + if ua >= 0. and ua <= 1. and ub >= 0. and ub <= 1.: + return [x1 + (ua * (x2 - x1)), y1 + (ua * (y2 - y1))] + return False + +class Game(object): + def __init__(self, player_left, player_right, configuration): + self.player_left = player_left + self.player_right = player_right + self.configuration = configuration + self.background = pygame.Surface(configuration['screen_size']) + self.sprites = pygame.sprite.OrderedUpdates() + line = entity.Line(load_image(configuration['line_image']), self.sprites) + line.rect.topleft = ((configuration['screen_size'][0]-line.rect.width)/2, 0) + paddle_image = load_image(configuration['paddle_image']) + self.paddle_left = entity.Paddle(configuration['paddle_velocity'], paddle_image, configuration['paddle_bounds'], self.sprites) + self.paddle_right = entity.Paddle(configuration['paddle_velocity'], paddle_image, configuration['paddle_bounds'], self.sprites) + self.paddle_left.rect.topleft = (self.configuration['paddle_left_position'], (self.configuration['screen_size'][1]-self.paddle_left.rect.height)/2) + self.paddle_right.rect.topleft = (self.configuration['paddle_right_position'], (self.configuration['screen_size'][1]-self.paddle_left.rect.height)/2) + digit_images = [load_image(configuration['digit_image'] % n) for n in xrange(10)] + self.score_left = entity.Score(digit_images, self.sprites) + self.score_left.rect.topleft = configuration['score_left_position'] + self.score_right = entity.Score(digit_images, self.sprites) + self.score_right.rect.topleft = configuration['score_right_position'] + ball_image = load_image(configuration['ball_image']) + self.ball = entity.Ball(self.configuration['ball_velocity'], ball_image, self.sprites) + self.bounds = pygame.Rect(20, 0, configuration['screen_size'][0]-ball_image.get_width()-20, configuration['screen_size'][1]-ball_image.get_height()) + self.sound_missed = pygame.mixer.Sound(configuration['sound_missed']) + self.sound_paddle = pygame.mixer.Sound(configuration['sound_paddle']) + self.sound_wall = pygame.mixer.Sound(configuration['sound_wall']) + self.reset_game(random.random()<0.5) + self.running = True + + def play_sound(self, sound): + if self.configuration['sound']: + sound.play() + + def reset_game(self, serveLeft=True): + y = self.configuration['screen_size'][1] - self.ball.rect.height + self.ball.position_x = (self.configuration['screen_size'][0]-self.ball.rect.width)/2.0 + self.ball.position_y = y * random.random() + self.ball.velocity = self.configuration['ball_velocity'] + a = random.random() * math.pi / 2. - math.pi / 4. + self.ball.velocity_vec[0] = self.ball.velocity * math.cos(a) + self.ball.velocity_vec[1] = self.ball.velocity * math.sin(a) + if random.random() < 0.5: + self.ball.velocity_vec[1] = -self.ball.velocity_vec[1] + if serveLeft: + self.ball.velocity_vec[0] *= -1 + + def update(self): + # Store previous ball position for line-line intersect test later + ball_position_x = self.ball.position_x + ball_position_y = self.ball.position_y + # Update sprites and players + self.sprites.update() + self.player_left.update(self.paddle_left, self) + self.player_right.update(self.paddle_right, self) + # Paddle collision check. Could probably just do a line-line intersect but I think I prefer having the pixel-pefect result of a rect-rect intersect test as well. + if self.ball.rect.x < self.bounds.centerx: + # Left side bullet-through-paper check on ball and paddle + if self.ball.velocity_vec[0] < 0: + intersect_point = line_line_intersect( + self.paddle_left.rect.right, self.paddle_left.rect.top, + self.paddle_left.rect.right, self.paddle_left.rect.bottom, + ball_position_x-self.ball.rect.width/2, ball_position_y+self.ball.rect.height/2, + self.ball.position_x-self.ball.rect.width/2, self.ball.position_y+self.ball.rect.height/2 + ) + if intersect_point: + self.ball.position_y = intersect_point[1]-self.ball.rect.height/2 + if intersect_point or (self.paddle_left.rect.colliderect(self.ball.rect) and self.ball.rect.right > self.paddle_left.rect.right): + self.ball.position_x = self.paddle_left.rect.right + velocity = self.paddle_left.calculate_bounce(min(1,max(0,(self.ball.rect.centery - self.paddle_left.rect.y)/float(self.paddle_left.rect.height)))) + self.ball.velocity = min(self.configuration['ball_velocity_max'], self.ball.velocity * self.configuration['ball_velocity_bounce_multiplier']) + self.ball.velocity_vec[0] = velocity[0] * self.ball.velocity + self.ball.velocity_vec[1] = velocity[1] * self.ball.velocity + self.player_left.hit() + self.play_sound(self.sound_paddle) + else: + # Right side bullet-through-paper check on ball and paddle. + if self.ball.velocity_vec[0] > 0: + intersect_point = line_line_intersect( + self.paddle_right.rect.left, self.paddle_right.rect.top, + self.paddle_right.rect.left, self.paddle_right.rect.bottom, + ball_position_x-self.ball.rect.width/2, ball_position_y+self.ball.rect.height/2, + self.ball.position_x-self.ball.rect.width/2, self.ball.position_y+self.ball.rect.height/2 + ) + if intersect_point: + self.ball.position_y = intersect_point[1]-self.ball.rect.height/2 + if intersect_point or (self.paddle_right.rect.colliderect(self.ball.rect) and self.ball.rect.x < self.paddle_right.rect.x): + self.ball.position_x = self.paddle_right.rect.x - self.ball.rect.width + velocity = self.paddle_right.calculate_bounce(min(1,max(0,(self.ball.rect.centery - self.paddle_right.rect.y)/float(self.paddle_right.rect.height)))) + self.ball.velocity = min(self.configuration['ball_velocity_max'], self.ball.velocity * self.configuration['ball_velocity_bounce_multiplier']) + self.ball.velocity_vec[0] = -velocity[0] * self.ball.velocity + self.ball.velocity_vec[1] = velocity[1] * self.ball.velocity + self.player_right.hit() + self.play_sound(self.sound_paddle) + # Bounds collision check + if self.ball.rect.y < self.bounds.top: + self.ball.position_y = float(self.bounds.top) + self.ball.velocity_vec[1] = -self.ball.velocity_vec[1] + self.play_sound(self.sound_wall) + elif self.ball.rect.y > self.bounds.bottom: + self.ball.position_y = float(self.bounds.bottom) + self.ball.velocity_vec[1] = -self.ball.velocity_vec[1] + self.play_sound(self.sound_wall) + # Check the ball is still in play + if self.ball.rect.x < self.bounds.x: + self.player_left.lost() + self.player_right.won() + self.score_right.score += 1 + self.reset_game(False) + self.play_sound(self.sound_missed) + if self.ball.rect.x > self.bounds.right: + self.player_left.won() + self.player_right.lost() + self.score_left.score += 1 + self.reset_game(True) + self.play_sound(self.sound_missed) + + def draw(self, display_surface): + self.sprites.clear(display_surface, self.background) + return self.sprites.draw(display_surface) diff --git a/tools/game/py-pong/pypong/entity.py b/tools/game/py-pong/pypong/entity.py new file mode 100644 index 0000000..170be57 --- /dev/null +++ b/tools/game/py-pong/pypong/entity.py @@ -0,0 +1,87 @@ +import pygame, math +from pygame.sprite import Sprite + +class Paddle(Sprite): + def __init__(self, velocity, image, bounds_y, *groups): + Sprite.__init__(self, *groups) + self.image = image + self.rect = self.image.get_rect() + self.direction = 0 + self.velocity = velocity + self.bounds_y = bounds_y + # Like original pong, we break this up into 8 segments from the edge angle (acute_angle) to pi/2 at the center + # Changing acute_angle lets us change the extreme edge angle of the paddle. + acute_angle = .125 + # Build the angles from acute_angle to the first 0.5 center value then append the values going from the + # second center 0.5 value by using the values we just calculated reversed. + angles = [acute_angle + (0.5-acute_angle)/3.0 * n for n in xrange(4)] + angles += map(lambda x: 1 + x * -1, reversed(angles)) + # Final table is the output vector (x,y) of each angle + self.bounce_table = [(math.cos(n*math.pi-math.pi/2.0), math.sin(n*math.pi-math.pi/2.0)) for n in angles] + + def update(self): + self.rect.y = max(self.bounds_y[0], min(self.bounds_y[1]-self.rect.height, self.rect.y + self.direction * self.velocity)) + + def calculate_bounce(self, delta): + return self.bounce_table[int(round(delta * (len(self.bounce_table)-1)))] + +class Line(Sprite): + def __init__(self, image, *groups): + Sprite.__init__(self, *groups) + self.image = image + self.rect = self.image.get_rect() + +class Ball(Sprite): + def __init__(self, velocity, image, *groups): + Sprite.__init__(self, *groups) + self.velocity = velocity + self.image = image + self.rect = self.image.get_rect() + self.position_vec = [0., 0.] + self.velocity_vec = [0., 0.] + + def update(self): + self.position_vec[0] += self.velocity_vec[0] + self.position_vec[1] += self.velocity_vec[1] + self.rect.x = self.position_vec[0] + self.rect.y = self.position_vec[1] + + def set_position_x(self, value): + self.position_vec[0] = value + self.rect.left = value + position_x = property(lambda self: self.position_vec[0], set_position_x) + + def set_position_y(self, value): + self.position_vec[1] = value + self.rect.top = value + position_y = property(lambda self: self.position_vec[1], set_position_y) + +class Score(Sprite): + def __init__(self, image_list, *groups): + Sprite.__init__(self, *groups) + self.image_list = image_list + self.image = None + self.rect = pygame.Rect(0,0,0,0) + self.score = 0 + + def get_score(self): + return self.score_value + + def set_score(self, value): + self.score_value = value + digit_spacing = 8 + digit_width = self.image_list[0].get_width() + digit_height = self.image_list[0].get_height() + values = map(int, reversed(str(self.score_value))) + surface_width = len(values) * digit_width + (len(values)-1) * digit_spacing + if not self.image or self.image.get_width() < surface_width: + self.image = pygame.Surface((surface_width, digit_height)) + self.image.fill((0,0,0)) + self.rect.width = self.image.get_width() + self.rect.height = self.image.get_height() + offset = self.image.get_width()-digit_width + for i in values: + self.image.blit(self.image_list[i], (offset, 0)) + offset = offset - (digit_width + digit_spacing) + + score = property(get_score, set_score) diff --git a/tools/game/py-pong/pypong/player.py b/tools/game/py-pong/pypong/player.py new file mode 100644 index 0000000..076bd0d --- /dev/null +++ b/tools/game/py-pong/pypong/player.py @@ -0,0 +1,81 @@ +import pygame, random + +class BasicAIPlayer(object): + def __init__(self): + self.bias = random.random() - 0.5 + self.hit_count = 0 + + def update(self, paddle, game): + # Dead simple AI, waits until the ball is on its side of the screen then moves the paddle to intercept. + # A bias is used to decide which edge of the paddle is going to be favored. + if (paddle.rect.x < game.bounds.centerx and game.ball.rect.x < game.bounds.centerx) or (paddle.rect.x > game.bounds.centerx and game.ball.rect.x > game.bounds.centerx): + delta = (paddle.rect.centery + self.bias * paddle.rect.height) - game.ball.rect.centery + if abs(delta) > paddle.velocity: + if delta > 0: + paddle.direction = -1 + else: + paddle.direction = 1 + else: + paddle.direction = 0 + else: + paddle.direction = 0 + + def hit(self): + self.hit_count += 1 + if self.hit_count > 6: + self.bias = random.random() - 0.5 # Recalculate our bias, this game is going on forever + self.hit_count = 0 + + def lost(self): + # If we lose, randomise the bias again + self.bias = random.random() - 0.5 + + def won(self): + pass + +class KeyboardPlayer(object): + def __init__(self, input_state, up_key=None, down_key=None): + self.input_state = input_state + self.up_key = up_key + self.down_key = down_key + + def update(self, paddle, game): + if self.input_state['key'][self.up_key]: + paddle.direction = -1 + elif self.input_state['key'][self.down_key]: + paddle.direction = 1 + else: + paddle.direction = 0 + + def hit(self): + pass + + def lost(self): + pass + + def won(self): + pass + +class MousePlayer(object): + def __init__(self, input_state): + self.input_state = input_state + pygame.mouse.set_visible(False) + + def update(self, paddle, game): + centery = paddle.rect.centery/int(paddle.velocity) + mousey = self.input_state['mouse'][1]/int(paddle.velocity) + if centery > mousey: + paddle.direction = -1 + elif centery < mousey: + paddle.direction = 1 + else: + paddle.direction = 0 + + def hit(self): + pass + + def lost(self): + pass + + def won(self): + pass