Translate

Sunday, November 10, 2013

The Ping Pong Game:Python

This is the one of the first arcade video games (1972). While Pong is not particularly exciting compared to today's video games, Pong is relatively simple to build and provides a nice opportunity to work on the skills in Python.
The Game source code is given here which is written on Codeskulptor  , below is the link of my game that i have created on Codeskulptor.

Game Development Process:


  1. Code to the program template that draws a ball moving across the Pong table. We recommend that you add the positional update for the ball to the draw handler as shown in the second part of the "Motion" video.
  2. Code to the function spawn_ball that spawns a ball in the middle of the table and assigns the ball a fixed velocity (for now). Ignore the parameter direction at this point.
  3. Call to spawn_ball in the function new_game which starts a game of Pong. Note that the program templates includes an initial call to new_game in the main body of your program to get a game going immediately.
  4. Modify  code such that the ball collides with and bounces off of the top and bottom walls. Experiment with different hard-coded initial velocities to test your code.
  5. Randomization to the velocity in spawn_ball(direction) The velocity of the ball should be upwards and towards the right if direction == RIGHT and upwards and towards the left if direction == LEFT. The exact values for the horizontal and vertical components of this velocity should be generated using random.randrange(). For the horizontal velocity, we suggest a speed of around random.randrange(120, 240) pixels per second. For the vertical velocity, we suggest a speed of around random.randrange(60, 180) pixels per second. (You will need to set the signs of velocities appropriately.)
  6. Code to the draw handler that tests whether the ball touches/collides with the left and right gutters. (Remember that the gutters are offset from the left and right edges of the canvas by the width of the paddle as described in the "Pong" video.) When the ball touches a gutter, use either spawn_ball(LEFT) or spawn_ball(RIGHT) to respawn the ball in the center of the table headed towards the opposite gutter.
  7. Code that draws the left and right paddles in their respective gutters. The vertical positions of these two paddles should depend on two global variables. (In the template, the variables were paddle1_pos and paddle2_pos.)
  8. Code that modifies the values of these vertical positions via an update in the draw handler.  The update should reference two global variables that contain the vertical velocities of the paddles. (In the template, the variables werepaddle1_vel and paddle2_vel.)
  9. Update the values of these two vertical velocities using key handlers. The "w" and "s" keys should control the vertical velocity of the left paddle while the "Up arrow" and "Down arrow" key should control the velocity of the right paddle. In our version of Pong, the left paddle moves up at a constant velocity if the "w" key is pressed and moves down at a constant velocity if the "s" is pressed and is motionless if neither is pressed. (The motion if both are pressed is up to you.) To achieve this effect, you will need to use both a keydown and a keyup handler to increase/decrease the vertical velocity in an appropriate manner.
  10. Restrict  paddles to stay entirely on the canvas by adding a check before you update the paddles' vertical positions in the draw handler. In particular, test whether the current update for a paddle's position will move part of the paddle off of the screen. If it does, don't allow the update.
  11. Modify  collision code for the left and right gutters in step 6 to check whether the ball is actually striking a paddle when it touches a gutter. If so, reflect the ball back into play. This collision model eliminates the possibility of the ball striking the edge of the paddle and greatly simplifies your collision/reflection code.
  12. To moderately increase the difficulty of your game, increase the velocity of the ball by 10% each time it strikes a paddle.
  13. Add scoring to the game as shown in the Pong video lecture. Each time the ball strikes the left or right gutter (but not a paddle), the opposite player receives a point and ball is respawned appropriately.
  14. Finally, add code to new_game which resets the score before calling spawn_ball. Add a "Restart" button that calls new_game to reset the score and relaunch the ball.
Source Code:

.
import math
import simplegui
import random

#Globals

# Room dimensions
room_width = 600
room_height = 400
top_margin = 80
room_center = ( room_width/2, (room_height + top_margin)/2 )

# Ball parameters
ball_radius = 8

# Paddle parameters
player1_speed = 8
player2_speed = player1_speed
paddle_length = 80
paddle_width = 8

# Paddle Movement sensitivity
UP = (0, -1) # move paddle in up/negative Y direction
DOWN = (0, 1) # move paddle in down/positive Y direction

# Single or Two Player
player2_auto = False

"""
Classes
"""
## Geometric Primitives
# Rectangle
class Rect(object):
    def __init__(self, center, width, height, color="White"):
        self.width = width
        self.height = height
        self.center = center
        self.color = color

    def getWidth(self):
        return self.width

    def getHeight(self):
        return self.height

    def getCenter(self):
        return self.center

    def getTopLeft(self):
        """
        Calculate topLeft based on center coordinates.
        Useful when moving the rect by changing center coordinates
       """
        center = self.center
        width = self.width
        height = self.height
        return ((center[0] - width/2), (center[1] - height/2))

    def pointList(self):
        topLeft = self.getTopLeft()
        return ([topLeft, \
                 (topLeft[0] + self.width, topLeft[1]), \
                 (topLeft[0] + self.width, topLeft[1] + self.height), \
                 (topLeft[0], topLeft[1] + self.height)])

    def intersection(self, point):
        """
       Determine if a given point is inside or outside the rectangle

       point: tuple
       returns True if point is ON the edges or INSIDE the shape
       else False
       """
        topLeft = self.getTopLeft()
        xIntersect = point[0] >= topLeft[0] \
            and point[0] <= topLeft[0] + self.width

        yIntersect = point[1] >= topLeft[1] \
            and point[1] <= topLeft[1] + self.height

        return xIntersect and yIntersect

    def draw(self, canvas):
        canvas.draw_polygon(self.pointList(), 1, self.color, self.color)

# Circle
class Circle(object):
    def __init__(self, center, radius, color="White"):
        self.center = center
        self.radius = radius
        self.color = color

    def getCenter(self):
        return self.center

    def getRadius(self):
        return self.radius

    def distanceToCenter(self, point):
        """ Distance between a point somewhere in space, and the center of this circle """
        return math.sqrt( (point[0] - self.center[0])**2  + (point[1] - self.center[1])**2 )

    def getBoundingBox(self):
        return Rect(self.getCenter(), self.getRadius()*2, self.getRadius()*2)

    def intersection(self, point):
        """
       Determine if a given point is inside or outside the circle

       point: tuple
       returns True if point is ON the edges or INSIDE the shape
       else False
       """
        distance = self.distanceToCenter(point)
        return self.radius >= distance

    def draw(self, canvas):
        canvas.draw_circle(self.center, self.radius, 1, self.color, self.color)

# Classes: Vectors (cartesian)
class Vector(object):
    def __init__(self, coordinates):
        self.coordinates = coordinates

    def getCoordinates(self):
        # Returns Cartesian coordinates of this vector
        return self.coordinates

    def getMagnitude(self):
        # Returns magnitude of this vector
        x = self.coordinates[0]
        y = self.coordinates[1]
        return math.sqrt(x**2 + y**2)

    def dot(self, v2):
        """
       Dot product of this and v2
       Returns a scalar value
       """
        x = self.coordinates[0]
        y = self.coordinates[1]
        v2_coord = v2.getCoordinates()
        result = (x * v2_coord[0]) + (y * v2_coord[1])
        return result

    def __add__(self, v2):
        """
       Add this vector to another vector v2
       Returns tuple of resultant vector
       """
        x = self.coordinates[0]
        y = self.coordinates[1]
        v2_coord = v2.getCoordinates()
        result = (x + v2_coord[0], y + v2_coord[1])
        return Vector(result)

    def __sub__(self, v2):
        """
       Subtract v2 from this vector
       Returns tuple of resultant vector
       """
        x = self.coordinates[0]
        y = self.coordinates[1]
        v2_coord = v2.getCoordinates()
        result = (x - v2_coord[0], y - v2_coord[1])
        return Vector(result)

    def normalize(self):
        """
       Returns the normalized coordinates of this vector
       """
        magnitude = self.getMagnitude()
        x = self.coordinates[0]
        y = self.coordinates[1]
        result = (x/magnitude, y/magnitude)
        return Vector(result)

    def scalarMul(self, C):
        """
       Scalar multiplication of a vector
       Returns tuple containing coordinates multiplied by the scalar
       """
        x = self.coordinates[0]
        y = self.coordinates[1]
        result = (C*x, C*y)
        return Vector(result)

    def proj(self, v2):
        """
       Project this onto v2. v2 should be the surface normal of a wall or other object
       """
        n = v2.normalize()
        return n.scalarMul(self.dot(n))

    def reflectionVector(self, v2):
        """
       http://math.stackexchange.com/questions/13261/how-to-get-a-reflection-vector
       Coupe de grace; Reflects this according to the law of reflection
       v2 is the surface normal of reflecting surface

       Returns a tuple containing coordinates of reflected vector
       """
        v1_projected_v2 = (self.proj(v2)).scalarMul(2).getCoordinates()
        x = self.coordinates[0] - v1_projected_v2[0]
        y = self.coordinates[1] - v1_projected_v2[1]
        return Vector((x, y))

## Classes: Game Elements
# Ball
class Ball(Circle):
    """
   Define a ball object which is a circle with additional properties

   speed: position increment in pixels. Position will change with every
   call to move()
   direction: angle measured from positive x axis
   """
    def __init__(self, center, radius, velocity):
        Circle.__init__(self, center, radius, "Yellow")
        self.velocity = velocity

    def getSpeed(self):
        return self.velocity.getMagnitude()

    def getDirection(self):
        return self.velocity.normalize().getCoordinates()

    def setPosition(self, center):
        self.center = center

    def getVelocity(self):
        return self.velocity

    def setVelocity(self,  direction):
        self.velocity = Vector(direction)

    def move(self):
        c = self.getCenter()
        speed = self.getSpeed()
        d = self.getDirection()
        new_pos = [(c[0] + speed * d[0]), (c[1] + speed * d[1])]
        if new_pos[0] < 0:
            new_pos[0] = 0
        elif new_pos[0] > room_width - paddle_width - 1:
            new_pos[0] = room_width - paddle_width - 1
        if new_pos[1] < (top_margin + paddle_width)/2:
            new_pos[1] = (top_margin + paddle_width)/2
        elif new_pos[1] > (top_margin + paddle_width)/2 + room_height:
            new_pos[1] = room_height
        self.setPosition( tuple(new_pos) )
       

    def reflect(self, normal):
        """
           The velocity vector is reflected according to the law of reflection,
           upon collision with a surface
       """
        self.velocity = self.velocity.reflectionVector(normal)

# Paddle
class Paddle(Rect):
    """
   Define a paddle object which is a Rect with additional properties

   speed: position increment in pixels. Position will change with every
   call to move()
   direction: either down or up
   """
    def __init__(self, center, width, height, color, velocity, surfaceNormal):
        Rect.__init__(self, center, width, height, color)
        self.normal = surfaceNormal
        self.velocity = velocity

    def getSpeed(self):
        return self.velocity.getMagnitude()

    def getDirection(self):
        return self.velocity.normalize().getCoordinates()

    def getSurfaceNormal(self):
        return self.normal

    def setPosition(self, center):
        self.center = center

    def setVelocity(self, vel):
        self.velocity = Vector(vel)

    def move(self):
        speed = self.getSpeed()
        d = self.getDirection()
        newy = self.center[1] + speed * d[1]
        self.center = (self.center[0], newy)

# Wall/Boundaries
class Wall(Rect):
    """
   Define a paddle object which is a Rect with additional properties

   speed: position increment in pixels. Position will change with every
   call to move()
   direction: either down or up
   """
    def __init__(self, center, width, height, surfaceNormal):
        Rect.__init__(self, center, width, height)
        self.surfaceNormal = surfaceNormal

    def getSurfaceNormal(self):
        # Return the Surface Normal Vector
        return self.surfaceNormal

"""
   Helper functions
"""

# Random Velocity
def genRandomVelocity(sgn=0):
    if sgn != 0:
        # If sign is specified, only generate Y randomly
        x = sgn * random.randrange(120, 240)
        y = random.randrange(-1,2,2) * random.randrange(60, 180)
        return ((x/60, y/60))
    else:
        # Sign is not specified, both components are random
        x = random.randrange(-1,2,2) * random.randrange(120, 240)
        y = random.randrange(-1,2,2) * random.randrange(60, 180)
        return ((x/60, y/60))

# Determine collisions
def intersectingShapes(shape1, shape2):
    """
   Takes 2 shapes and determines if there is any overlap

   returns: True if shape1, and shape2 overlap
   """
    # Rect and Rect
    def overlappingRectangles(shape1, shape2):
        """
       If rectangles are of different sizes, need to check if vertices
       of smaller rectangle are inside the larger one.
       """
        vertices_shape1 = shape1.pointList()
        vertices_shape2 = shape2.pointList()
        for v1 in vertices_shape1:
            if shape2.intersection(v1):
                return True
        else:
            for v2 in vertices_shape2:
                if shape1.intersection(v2):
                    return True
            else:
                return False

    # Circle and Rectangle
    def overlappingCircleandRect(shape1, shape2):
        if isinstance(shape1, Circle):
            c = shape1
            r = shape2
        else:
            c = shape2
            r = shape1

        boundingBox = c.getBoundingBox()
        vertices = r.pointList()
        for vertex in vertices:
            if c.intersection(vertex):
                return True
        else:
            return overlappingRectangles(r, boundingBox)

    if isinstance(shape1, Rect) and isinstance(shape2, Rect):
        return overlappingRectangles(shape1, shape2)

    elif        isinstance(shape1, Circle) and isinstance(shape2, Rect) \
        or      isinstance(shape2, Circle) and isinstance(shape1, Rect):
        return overlappingCircleandRect(shape1, shape2)

"""
   Initialize and Load Game
"""
def game_init():
    """ Loads the game environment """
    # Game elements
    global pong_ball, top_wall, bottom_wall, player1_paddle, player2_paddle, roomRect
    # Controls, scoring
    global keyboard, player1_score, player2_score, match_point
    # Flags
    global start_game, player1_out, player2_out
    # Game Assets
    global ball_hit_sound, ball_out_sound

    # Game Elements
    # Ball
    pong_ball = Ball( room_center, ball_radius, Vector(genRandomVelocity()) )

    # Walls
    top_wall_y = top_margin/2
    bottom_wall_y = top_wall_y + room_height + paddle_width

    top_wall = Wall( (room_width/2, top_wall_y), room_width, paddle_width, Vector((0, 1)) )
    bottom_wall = Wall( (room_width/2, bottom_wall_y), room_width, paddle_width, Vector((0, -1)) )
    # print (bottom_wall.getCenter()[1] - paddle_width/2) - (top_wall.getCenter()[1] + paddle_width/2)  # should be == room_width

    # Paddles
    paddles_y = room_center[1]
    player1_vel = Vector(DOWN).scalarMul(player1_speed)
    player2_vel = Vector(DOWN).scalarMul(player2_speed)

    player1_paddle = Paddle( (paddle_width/2, paddles_y), paddle_width, paddle_length, "Red", player1_vel, Vector((1, 0)) )
    player2_paddle = Paddle( (room_width - paddle_width/2 - 1, paddles_y), paddle_width, paddle_length, "Blue", player2_vel, Vector((-1, 0)) )

    # Canvas (Game map/area)
    roomRect = Rect(room_center, room_width, room_height + top_margin)

    # User Control
    keyboard = {'up' : False,
                'down' : False,
                'w' : False,
                's' : False,
                }

    # Scoring
    player1_score = 0
    player2_score = 0
    match_point = 7

    # Flags
    start_game = False
    player1_out = False
    player2_out = False

    # Game Assets
    # Sounds
    ball_hit_sound = simplegui.load_sound("http://www.freesound.org/people/NoiseCollector/sounds/4359/download/4359__noisecollector__pongblipf4.wav")
    ball_out_sound = simplegui.load_sound("http://www.freesound.org/people/Autistic%20Lucario/sounds/142608/download/142608__autistic-lucario__error.wav")

game_init()

"""
   Movement and animation functions
"""

"""
   Ball Movements
"""

# Ball out of bounds
def ball_outOfBounds(ball):
    global player1_out, player2_out
    c = ball.getCenter()
    r = ball.getRadius()
    d = ball.getDirection()
    p1 = player1_paddle.getCenter()
    p2 = player2_paddle.getCenter()
    if d[0] < 0:
        # Ball out of bounds on left side of screen
        if (c[1] + r <= p1[1] - player1_paddle.getHeight()/2)\
        or (c[1] - r >= p1[1] + player1_paddle.getHeight()/2):
            ball_out = (c[0] - r <= paddle_width)\
                    or (c[0] + r >= room_width - paddle_width)
            if ball_out:
                player1_out = True
            return ball_out
    elif d[0] > 0:
        # Ball out of bounds on right side of screen
        if (c[1] + r <= p2[1] - player1_paddle.getHeight()/2)\
        or (c[1] - r >= p2[1] + player1_paddle.getHeight()/2):
            ball_out = (c[0] - r <= paddle_width)\
                    or (c[0] + r >= room_width - paddle_width)
            if ball_out:
                player2_out = True
            return ball_out
       
# Reset Ball Position
def ball_reset():
    """ Reset the ball, when it goes out of bounds """
    global start_game, player1_out, player2_out
    start_game = player1_out = player2_out = False  
    ball_out_sound.play()
    reset_timer.start()

# Ball Reset timer
def reset_pause():
    global start_game
    start_game = True
    pong_ball.setPosition(room_center)
    reset_timer.stop()

# Buffer zone around surfaces before smartly testing for collisions
def ball_buffer():
    """ Returns the distance between center of ball and center of paddle
       one timestep before imminent collision.
   """
    return (paddle_width/2 + pong_ball.getSpeed() + ball_radius)

# Smartly determine if ball is in dangerzone (dz) and
# collision is imminent (after one additional timestep)
dz_left = player1_paddle.getCenter()[0] + ball_buffer()
dz_right = player2_paddle.getCenter()[0] - ball_buffer()
dz_top = top_wall.getCenter()[1] + ball_buffer()
dz_bottom = bottom_wall.getCenter()[1] - ball_buffer()

def ball_collisions():
    """
   Since the game has only one moving object, with 4 fixed surfaces, and a room of known size
   significant efficiency gains can be achieved by not checking for collisions
   on every single draw callback.

   This function will smartly check for collisions based on distance between surfaces and ball
   """
    pong_ball_center = pong_ball.getCenter()
    pong_ball_dir = pong_ball.getDirection()

    # Left paddle (player 1)
    if pong_ball_center[0] <= dz_left and pong_ball_dir[0] < 0:
        if intersectingShapes(player1_paddle, pong_ball):
            ball_hit_sound.play()
            pong_ball.reflect(player1_paddle.getSurfaceNormal())
            pong_ball.setVelocity(pong_ball.getVelocity().scalarMul(1.1).getCoordinates())

    # Right paddle (player 2)
    elif pong_ball_center[0] >= dz_right and pong_ball_dir[0] > 0:
        if intersectingShapes(player2_paddle, pong_ball):
            ball_hit_sound.play()
            pong_ball.reflect(player2_paddle.getSurfaceNormal())
            pong_ball.setVelocity(pong_ball.getVelocity().scalarMul(1.1).getCoordinates())

    # Top wall
    if pong_ball_center[1] <= dz_top and pong_ball_dir[1] < 0:
        if intersectingShapes(top_wall, pong_ball):
            ball_hit_sound.play()
            pong_ball.reflect(top_wall.getSurfaceNormal())

    # Bottom wall
    elif pong_ball_center[1] >= dz_bottom and pong_ball_dir[1] > 0:
        if intersectingShapes(bottom_wall, pong_ball):
            ball_hit_sound.play()
            pong_ball.reflect(bottom_wall.getSurfaceNormal())

"""
   Scoring
"""
def calculateScores():
    global player1_score, player2_score
    # Updates scores.
    if player2_out:
        player1_score += 1
    elif player1_out:
        player2_score += 1

def isGameOver():
    return player1_score == match_point\
        or player2_score == match_point

"""
   User Controls: Paddle Movements
"""
# Determine if paddle is able to move
def paddle_validMove(paddle):
    """ Move the paddle if it won't collide with the walls """
    speed = paddle.getSpeed()
    d = paddle.getDirection()
    newy = paddle.getCenter()[1] + speed * d[1]  # predicted position of paddle center after one tick

    # Paddle moving UP
    if d[1] < 0 :
       newy -= paddle_length/2
       boundary = top_wall.getCenter()[1] + paddle_width/2
       if newy <= boundary:
            paddle.setPosition( (paddle.getCenter()[0], boundary + paddle_length/2) )
       else:
            paddle.move()
    # Paddle moving DOWN
    elif d[1] > 0 :
       newy += paddle_length/2
       boundary = bottom_wall.getCenter()[1] - paddle_width/2
       if newy >= boundary:
            paddle.setPosition( (paddle.getCenter()[0], boundary - paddle_length/2) )
       else:
            paddle.move()

# Player1 movement
def player1_move(paddle):
    if keyboard['s']:
        paddle.setVelocity(Vector(DOWN).scalarMul(player1_speed).getCoordinates())
        paddle_validMove(paddle)
    elif keyboard['w']:
        paddle.setVelocity(Vector(UP).scalarMul(player1_speed).getCoordinates())
        paddle_validMove(paddle)

# Player2 Movement
def player2_move(paddle):
    if player2_auto:
        # Computer controlled second paddle
        target = pong_ball.getCenter()
        current = paddle.getCenter()      

        # move computer paddle only after player has struck the ball and pong_ball.getCenter()[0] > room_width/2
        if pong_ball.getDirection()[0] > 0:
            if target[1] < current[1]:
                paddle.setVelocity(Vector(UP).scalarMul(player2_speed).getCoordinates())
            if target[1] > current[1]:
                paddle.setVelocity(Vector(DOWN).scalarMul(player2_speed).getCoordinates())
            paddle_validMove(paddle)
    else:
        # User controlled second paddle
        if keyboard['down']:
            paddle.setVelocity(Vector(DOWN).scalarMul(player2_speed).getCoordinates())
            paddle_validMove(paddle)
        elif keyboard['up']:
            paddle.setVelocity(Vector(UP).scalarMul(player2_speed).getCoordinates())
            paddle_validMove(paddle)


"""
   Game Animations
"""
# Movement of all objects in game
def     game_movement():
    """ Movement and collision detection for all game objects """
    # Paddles should move regardless of what the ball is doing
    player1_move(player1_paddle)
    player2_move(player2_paddle)

    # Ball: Check for boundary violations/collisions
    if not ball_outOfBounds(pong_ball):
        ball_collisions()
        pong_ball.move()

    elif ball_outOfBounds(pong_ball) and not reset_timer.is_running():
        p1Score = player1_score
        p2Score = player2_score
        calculateScores()
        ball_reset() # start reset timer
        if player1_score > p1Score:
            pong_ball.setVelocity(genRandomVelocity(-1))
        elif player2_score > p2Score:
            pong_ball.setVelocity(genRandomVelocity(1))

           
"""
   Game Draw functions
"""

def draw_scores(canvas):
    canvas.draw_text(str(player1_score), (room_width/4, (top_margin - paddle_width)/3), 24, "White")
    canvas.draw_text(str(player2_score), (room_width/4 + room_width/2, (top_margin - paddle_width)/3), 24, "White")

def game_over(canvas):
    def gameover_msg_coordinates(message, text_size):
        message_width = pong_frame.get_canvas_textwidth(message, text_size)
        x = (room_center[0] - message_width)/2
        y = room_center[1]
        return (x, y)

    if player1_score > player2_score:
        message = "P1 WIN!"
        coord = gameover_msg_coordinates(message, 24)
        canvas.draw_text(message, coord, 24, "Red")
    else:
        message = "P2 WIN!"
        coord = gameover_msg_coordinates(message, 24)
        canvas.draw_text(message, coord, 24, "Blue")

def draw_game_static_env(canvas):
    """ Draw all the static objects in the game environment """
    # centerline
    canvas.draw_line( (room_width/2, top_wall.getCenter()[1]), (room_width/2, bottom_wall.getCenter()[1]), 2, "White")
    canvas.draw_line([paddle_width, top_wall.getCenter()[1]],[paddle_width, bottom_wall.getCenter()[1]], 1, "White")
    canvas.draw_line([room_width - paddle_width - 1, top_wall.getCenter()[1]],[room_width - paddle_width, bottom_wall.getCenter()[1]], 1, "White")

    # walls
    top_wall.draw(canvas)
    bottom_wall.draw(canvas)

    # scores
    draw_scores(canvas)

def draw_ball_paddles(canvas):
    # Draw Ball
    pong_ball.draw(canvas)
    # Draw Paddles
    player1_paddle.draw(canvas)
    player2_paddle.draw(canvas)
   
# Main game callback (auto-loop)
def draw(canvas):
    global start_game

    # draw static elements
    draw_game_static_env(canvas)    

    # Check if current game is over
    if not isGameOver():
        draw_ball_paddles(canvas)
        # Check that the game is not blocked,
        # or new game has not yet been started
        if start_game:
            game_movement()
    else:
        """ Game has ended, print game results, and freeze canvas
           until user creates a new game
       """
        draw_ball_paddles(canvas)
        start_game = False
        game_over(canvas)

"""
   Event Handlers and Game Loop
"""
# New Game Button Handler

# Mouseclick- Game start
def mouseclick_startGame(position):
    global start_game
    if not start_game:
        start_game = True

# Enable single player mode, player2 paddle will be controlled by computer
def singlePlayer():
    global player2_auto
    game_init()
    player2_auto = True

# 2Player Button Handler
def twoPlayer():
    global player2_auto
    game_init()
    player2_auto = False

# Key is pushed and held down
def keydown(key):
    if key == simplegui.KEY_MAP['s']:
        keyboard['s'] = True
    elif key == simplegui.KEY_MAP['w']:
        keyboard['w'] = True
    if key == simplegui.KEY_MAP['down']:
        keyboard['down'] = True
    elif key == simplegui.KEY_MAP['up']:
        keyboard['up'] = True

# Key is released
def keyup(key):
    if key == simplegui.KEY_MAP['s']:
        keyboard['s'] = False
    elif key == simplegui.KEY_MAP['w']:
        keyboard['w'] = False
    if key == simplegui.KEY_MAP['down']:
        keyboard['down'] = False
    elif key == simplegui.KEY_MAP['up']:
        keyboard['up'] = False


"""
Game Window Settings
"""
def gameWindow_init():
    global pong_frame, reset_timer

    # Create Game Window
    pong_frame = simplegui.create_frame("Pong", roomRect.getWidth(), roomRect.getHeight(), 300)
    game_instructions = []
    game_instructions.append(pong_frame.add_label("Welcome to Pong!"))
    game_instructions.append(pong_frame.add_label(""))
    game_instructions.append(pong_frame.add_label("Up and Down arrow keys control the Blue paddle"))
    game_instructions.append(pong_frame.add_label(""))
    game_instructions.append(pong_frame.add_label("W and S keys control the Red paddle"))
    game_instructions.append(pong_frame.add_label(""))
    game_instructions.append(pong_frame.add_label("Click anywhere in the game window to start"))
    game_instructions.append(pong_frame.add_label(""))
    game_instructions.append(pong_frame.add_label("May the force be with you."))
    game_instructions.append(pong_frame.add_label(""))

    # Game Window Buttons and Controls
    # resetButton = pong_frame.add_button("New Game", new_game, 150)
    pong_frame.add_button("Single Player (vs Computer)", singlePlayer, 250)
    pong_frame.add_button("2 Player (Restart)", twoPlayer, 250)

    # Timers
    reset_timer = simplegui.create_timer(1000, reset_pause)

    # Register event handlers
    pong_frame.set_keydown_handler(keydown)
    pong_frame.set_keyup_handler(keyup)
    pong_frame.set_draw_handler(draw)
    pong_frame.set_mouseclick_handler(mouseclick_startGame)

# Start the frame animation
gameWindow_init()
pong_frame.start()

Here's the code...Enjoy the Ping Pong Game.


Pong Game on Codeskulptor

No comments:

Post a Comment