Pong Example

638 views
Skip to first unread message

Tristam MacDonald

unread,
Dec 8, 2008, 3:51:08 PM12/8/08
to pyglet...@googlegroups.com
In case anyone is interested, I wrote a simple pong clone using Pyglet.

The source is fairly heavily commented, and I attempted to use best practices throughout, in the hopes that it would be of use to anyone learning Pyglet.

Comments and suggestions are welcome, and you can find it here: http://swiftcoder.wordpress.com/2008/12/08/pong/

- Tristam

Philippe

unread,
Dec 8, 2008, 4:33:32 PM12/8/08
to pyglet-users
Cool, thanks, I just started learning pyglet so this is really helpful
for me since I'm making a game similar to this.

Paul

unread,
Dec 8, 2008, 5:30:33 PM12/8/08
to pyglet...@googlegroups.com
Thanks for the excellent example. I'm still learning python/pyglet and it's extremely useful to see how things should be done. Maybe it could be included in the pyglet distribution?

Alex Holkner

unread,
Dec 8, 2008, 5:43:34 PM12/8/08
to pyglet...@googlegroups.com

This is a great example, and just needs sound effects (and for the CPU
player not to cheat!). If you relicense the code under a BSD license
I can include it in the pyglet examples/ distribution.

Cheers
Alex.

Tristam MacDonald

unread,
Dec 8, 2008, 5:48:18 PM12/8/08
to pyglet...@googlegroups.com
No problem, I would be glad to contribute to the distribution. I plan to add some 'artificial stupidity' to the CPU player in the next few days, but feel free to modify the code as you see fit, and the BSD license is fine.

I intend to produce a series of these simple games, partly as the start of my game development portfolio, but also to help out anyone who needs it - I will update you all when the next is released.

- Tristam

vaibhav

unread,
Dec 9, 2008, 12:28:39 AM12/9/08
to pyglet-users
hi Tristam,
this is a great example. i better understand states now. i found one
typo in the last line of main update function, though i don't think
that 'else' condition is ever met.

# update callback
def update(dt):
# update the topmost state, if we have any
if len(states):
states[-1].update(dt)
# otherwise quit
else:
app.exit()

the last line should be
pyglet.app.exit()

thanks for the example
vaibhav

On Dec 8, 2:48 pm, "Tristam MacDonald" <swiftco...@gmail.com> wrote:
> On Mon, Dec 8, 2008 at 5:43 PM, Alex Holkner <alex.holk...@gmail.com> wrote:

Tristam MacDonald

unread,
Dec 9, 2008, 6:56:21 AM12/9/08
to pyglet...@googlegroups.com
On Tue, Dec 9, 2008 at 12:28 AM, vaibhav <bhawsar...@gmail.com> wrote:

hi Tristam,
this is a great example. i better understand states now. i found one
typo in the last line of main update function, though i don't think
that 'else' condition is ever met.

# update callback
def update(dt):
       # update the topmost state, if we have any
       if len(states):
               states[-1].update(dt)
       # otherwise quit
       else:
               app.exit()

the last line should be
               pyglet.app.exit()

Thanks, I have corrected that in the source. You are correct that it is never reached in the current app, but it is intended to make sure that the application will quit if the last state is popped (rather than get stuck in an infinite loop).

- Tristam

Paul

unread,
Dec 9, 2008, 12:12:37 PM12/9/08
to pyglet...@googlegroups.com
Also, I noticed there's a function to handle window resizing, but the window is not resizable. Adding the window attribute "resizable=True" makes it work as expected.

Tristam MacDonald

unread,
Dec 9, 2008, 12:18:24 PM12/9/08
to pyglet...@googlegroups.com
On Tue, Dec 9, 2008 at 12:12 PM, Paul <plh...@gmail.com> wrote:
Also, I noticed there's a function to handle window resizing, but the window is not resizable. Adding the window attribute "resizable=True" makes it work as expected.

I was actually just using the window resize callback to intercept the initial window size and setup the custom projection matrix. The resize handler is called not only when the window is resized, but also when it is made visible (at least the first time).

This allows one to change the resolution of the created window by changing only the parameters of the window creation, rather than having to change the dimensions in multiple places.

Allowing the user to resize the window is a bit of a mixed bag with a fixed size playing field, because you then need to enforce or compensate to match the 4x3 aspect ratio on each resize.

Paul

unread,
Dec 9, 2008, 3:58:13 PM12/9/08
to pyglet...@googlegroups.com
This change to the on_resize function will enforce a 4:3 viewport in the Pong example, thus allowing user resizing of the window without distortion:

def on_resize(width, height):

    # prevent division by zero
    if width == 0: width = 1
    if height == 0: height = 1

    # enforce 4:3 aspect ratio by reducing the excess dimension
    if 1.0 * width / height > 4.0 / 3:
        width = int(height * 4.0 / 3)
    elif 1.0 * width / height < 4.0 / 3:
        height = int(width * 3.0 / 4)

    # center viewport in window
    glViewport((window.width - width) // 2, (window.height - height) // 2, width, height)

Tristam MacDonald

unread,
Dec 9, 2008, 5:19:00 PM12/9/08
to pyglet...@googlegroups.com
On Tue, Dec 9, 2008 at 3:58 PM, Paul <plh...@gmail.com> wrote:
This change to the on_resize function will enforce a 4:3 viewport in the Pong example, thus allowing user resizing of the window without distortion:

def on_resize(width, height):

    # prevent division by zero
    if width == 0: width = 1
    if height == 0: height = 1

    # enforce 4:3 aspect ratio by reducing the excess dimension
    if 1.0 * width / height > 4.0 / 3:
        width = int(height * 4.0 / 3)
    elif 1.0 * width / height < 4.0 / 3:
        height = int(width * 3.0 / 4)

    # center viewport in window
    glViewport((window.width - width) // 2, (window.height - height) // 2, width, height)

Nice work! I was thinking of adapting the drawing code to accomplish the same effect, but that is far simpler. Mind if I include that change in the updated version next week?

- Tristam

Paul

unread,
Dec 9, 2008, 5:55:26 PM12/9/08
to pyglet...@googlegroups.com
On Tue, Dec 9, 2008 at 2:19 PM, Tristam MacDonald <swift...@gmail.com> wrote: 
Nice work! I was thinking of adapting the drawing code to accomplish the same effect, but that is far simpler. Mind if I include that change in the updated version next week?

 
Sure. In addition it might be a good idea to draw a border around the edges of the playing field so the edges can still be identified when the window is resized.

Tristam MacDonald

unread,
Dec 10, 2008, 2:18:21 PM12/10/08
to pyglet...@googlegroups.com
Where I was originally drawing the divider:

# setup the divider between the play area and the score area
batch.add(2, GL_LINES, None, ('v2i', (0,500, 800,500)))

I am now attempting to draw a border as well:

# setup the border
batch.add(8, GL_LINES, None, ('v2i', (800,600, 800,0, 800, 0, 0,0, 0,0, 0,600, 0,600, 800,600)))

But for some reason, only the right and lower edges display. If I modify the coordinates like this:

# setup the border
batch.add(8, GL_LINES, None, ('v2i', (800,600, 800,0, 800, 0, 0,0, 1,0, 1,600, 0,599, 800,599)))

Everything renders fine (except for the border being in the wrong place). I don't really get why this would make a difference, seeing as the other two edges render fine, and there is no clipping going on (lines are still within window bounds, scissor test is disabled).

In case anyone can shed light on the problem, the sample is attached.

- Tristam
pong.py

Paul

unread,
Dec 10, 2008, 5:45:38 PM12/10/08
to pyglet...@googlegroups.com
I'm building a different game based on the pong example. There seems to be some strangeness with regards to the positioning of GL_LINES so I did the border using polygons:

GAME_WIDTH = 800
GAME_HEIGHT = 600
class ScreenBorder:
    def __init__(self):
        self.thickness = 2
        self.color = (255, 255, 255, 255)

        self.border = batch.add(16, GL_QUADS, None, ('v2i', (
            0, 0,
            GAME_WIDTH, 0,
            GAME_WIDTH, self.thickness,
            0, self.thickness,
           
            0, GAME_HEIGHT - self.thickness,
            GAME_WIDTH, GAME_HEIGHT - self.thickness,
            GAME_WIDTH, GAME_HEIGHT,
            0, GAME_HEIGHT,
           
            0, 0,
            self.thickness, 0,
            self.thickness, GAME_HEIGHT,
            0, GAME_HEIGHT,
           
            GAME_WIDTH, 0,
            GAME_WIDTH - self.thickness, 0,
            GAME_WIDTH - self.thickness, GAME_HEIGHT,
            GAME_WIDTH, GAME_HEIGHT,
            )),('c4B', self.color * 16))

This seems to work well, with the border an even thickness around the screen.

Paul
Reply all
Reply to author
Forward
0 new messages