############################################################################# # pong.py # by Patrick Devine (pdevine@sonic.net) # # This version of pong was written for a talk I gave to a python users group # to prove that it was possible to write pong in under 60 minutes. # # The code itself is a little raw (hey, it was written in under an hour), but # should demonstrate how to use OpenGL primitives with Pyglet. # import random from pyglet import font from pyglet.gl import * SCREEN_WIDTH = 640 SCREEN_HEIGHT = 480 MAX_SCORE = 9 BALL_SPEED = 280.0 WALL_HEIGHT = 10 class Ball(object): def __init__(self): self.quad = gluNewQuadric() self.reset() def update(self, dt): global score1, score2 self.x += self.dx * dt self.y += self.dy * dt # bounce off the walls if self.y <= WALL_HEIGHT * 2 - 5 or \ self.y >= SCREEN_HEIGHT - (WALL_HEIGHT * 2): self.dy = -self.dy if self.x < 0: score2 += 1 self.checkScore(score2) self.reset() elif self.x > SCREEN_WIDTH: score1 += 1 self.checkScore(score1) self.reset() def checkScore(self, score): global score1, score2 if score >= MAX_SCORE: score1 = 0 score2 = 0 def collidePaddle(self, paddle): if self.x >= paddle.x - paddle.width and \ self.x <= paddle.x + paddle.width and \ self.y >= paddle.y and \ self.y <= paddle.y + paddle.height: self.dx = -self.dx def reset(self): # start the ball in the middle of the screen self.x = SCREEN_WIDTH / 2 self.y = SCREEN_HEIGHT / 2 # make the ball move horizontally at a reasonable speed while True: self.dx = (random.random() - 0.5) * BALL_SPEED if abs(self.dx) > 30: break self.dy = (random.random() - 0.5) * BALL_SPEED def draw(self): glPushMatrix() glColor4d(255, 255, 255, 255) glTranslatef(self.x, self.y, 0) gluQuadricDrawStyle(self.quad, GLU_FILL) gluDisk(self.quad, 0, 5, 50, 1) glPopMatrix() class Paddle(object): def __init__(self, x): self.x = x self.width = 5 self.height = 40 self.y = (SCREEN_HEIGHT / 2) - (self.height / 2) def draw(self): glPushMatrix() glColor4d(255, 255, 255, 255) glLineWidth(self.width) glBegin(GL_LINES) glVertex2i(self.x, self.y) glVertex2i(self.x, self.y + self.height) glEnd() glPopMatrix() class Field(object): def __init__(self): self.netWidth = 10 self.wallWidth = 10 def draw(self): glPushMatrix() # draw net glColor4d(255, 0, 0, 255) glLineWidth(self.netWidth) glEnable(GL_LINE_STIPPLE) glLineStipple(2, 0x1111) glBegin(GL_LINES) glVertex2i(SCREEN_WIDTH / 2, 0) glVertex2i(SCREEN_WIDTH / 2, SCREEN_HEIGHT) glEnd() glDisable(GL_LINE_STIPPLE) # draw walls glColor4d(255, 255, 255, 255) glLineWidth(self.wallWidth) glBegin(GL_LINES) glVertex2i(0, 5) glVertex2i(SCREEN_WIDTH, 5) glVertex2i(0, SCREEN_HEIGHT - 5) glVertex2i(SCREEN_WIDTH, SCREEN_HEIGHT - 5) glEnd() glPopMatrix() if __name__ == '__main__': from pyglet import window from pyglet.window import key from pyglet import clock win = window.Window(width=SCREEN_WIDTH, height=SCREEN_HEIGHT) @win.event def on_key_press(symbol, modifiers): if symbol == key.UP: paddle2.y += 10 elif symbol == key.DOWN: paddle2.y -= 10 elif symbol == key.A: paddle1.y += 10 elif symbol == key.Z: paddle1.y -= 10 elif symbol == key.C: ball.dy = -ball.dy paddle1 = Paddle(10) paddle2 = Paddle(SCREEN_WIDTH - 10) ft = font.load('Arial', 40) score1 = 0 score2 = 0 score1Text = font.Text(ft, x=SCREEN_WIDTH/2 - 40, y=SCREEN_HEIGHT - 50) score2Text = font.Text(ft, x=SCREEN_WIDTH/2 + 15, y=SCREEN_HEIGHT - 50) field = Field() ball = Ball() while not win.has_exit: win.dispatch_events() tick = clock.tick() ball.update(tick) for paddle in [paddle1, paddle2]: ball.collidePaddle(paddle) win.clear() field.draw() for score, scoreText in [(score1, score1Text), (score2, score2Text)]: scoreText.text = '%d' % score scoreText.draw() paddle1.draw() paddle2.draw() ball.draw() win.flip()