PONG!

0. Introducing a Paddle


Create a simple paddle object, with position and size attributes, and the ability to render itself.

Follow along with the code for each version.


1. Event-Driven Paddle


Add a simple keyboard-event handler to update the
position of the paddle object, based on user-inputs,
and then redraw it in the resulting new position.

2. Time-Driven Paddle


We should really update the paddle as part of a time-driven simulation update loop, rather than trying to implement game-logic in an event-handler.

In the JS/browser environment, this requires converting
the passage of time itself into a stream of events.

3. A Ball


It's just another time-driven object, with some attributes
(this time including a velocity) and a rendering method.

Now we have an object which truly behaves independently
of direct user-inputs. Now we're running a simulation!

IT'S ALIVE!

4. A Bouncing Ball


Our ball keeps getting away from us!

Let's fix that by making it bounce off the top and bottom of
the playfield, and "reset" if it falls off at the left or right.

5. Ball to Paddle Collision


Collision detection is a big topic in its own right, but we only need to cover the very basics here. Even so, the full geometry of circle to rectangle collision is non-trivial...

...so let's cheat.

Circle against line should be good enough here.

6. Pause and Single-Step


Diagnostics are of enormous value during development. They allow you to "visualise" and interact "live" with the otherwise invisible internal state of your system.

The ability to pause and single-step your simulation is hugely useful, and falls out naturally if you stick to the "gather / update / render" mainloop structure that I recommend.

7. A Second Paddle


You could, of course, copy-and-paste from the first one...

...but that would bad and evil and wrong, and the approach of a bloody amateur. We are professionals here, so let's do it properly...

In JavaScript, sharing code between objects is done via the use of "prototypes", which provide something broadly similar to conventional object "classes".

8. Collision (again)


Our second paddle doesn't collide so good... :-(

And the brute-force approach to fixing that would get messy. The paddle should really be in charge of its own collision logic anyway and, if we do that, things clean-up and resolve themselves rather nicely.

9. Homework


Now it's your turn. Extend the current code to:

  • Make the ball bounce off the left and right
    edges of the playfield, instead of "resetting".
  • Add a scoring system!
  • Prevent the paddles from moving out of the
    playfield, by having them "collide" with it.
  • Let the user-controlled paddles move
    left and right within 100 pixels of the edges.
  • Add a second ball, with half the velocity
    of the first one.

10. Rendering Diagnostics


It's instructive to see the actual "pattern" of the rendering behaviour and, in particular, how it relates to the
double-buffering and V-Sync behaviour of the browser.

11. Improved Time-Handling


Our current time-handling is actually quite naive.

It implicitly assumes that the timer events are "perfect" 
(which they typically are not), and there is an ugly interdependency between the timer rate and
the update logic, which leaves us prone to
"slow down", and to fragile temporal
scalability in general.

12. Frame Sync


Relying on some arbitrary timer-event is problematic too,
even if you compensate for its variability.

If the timing event is not synced to the actual screen refresh, you might be doing redundant computation and will be susceptible to "judder" ("beating") effects, due to the
imperfect sync between game and the display.

13. Simplify


Simplify the previous code, by focusing on the
"clean" solution (based on requestAnimationFrame),
and 
getting rid of all the other (inferior) setInterval stuff.

PONG!

By Pat Kerr

PONG!

The classic game, from scratch.

  • 2,699