Pong in < 250 lines of JS!

This is a crude example of a playable game that can be expressed in less than 250 lines of code!

Demo

Code

  1<!DOCTYPE html>
  2<html>
  3<body>
  4  <canvas id="game"> </canvas>
  5  <script type="text/javascript">
  6    var game = (function() {
  7      var Width = 800, Height = 450;
  8      var canvas = document.getElementById("game");
  9      var FPS = 1000 / 60;
 10      canvas.width = Width;
 11      canvas.height = Height;
 12      canvas.setAttribute('tabindex', 1);
 13      var ctx = canvas.getContext("2d");
 14
 15      var BG = {
 16        Color: '#333',
 17        Paint: function() {
 18          ctx.fillStyle = this.Color;
 19          ctx.fillRect(0, 0, Width, Height);
 20        }
 21      };
 22
 23      var Ball = { Radius: 5, Color: '#999', X: 0, Y: 0, VelX: 0, VelY: 0 };
 24      Ball.Paint = function() {
 25        ctx.beginPath();
 26        ctx.fillStyle = this.Color;
 27        ctx.arc(this.X, this.Y, this.Radius, 0, Math.PI * 2, false);
 28        ctx.fill();
 29        this.Update();
 30      };
 31      Ball.Update = function() {
 32        this.X += this.VelX;
 33        this.Y += this.VelY;
 34      };
 35      Ball.Reset = function() {
 36        this.X = Width / 2;
 37        this.Y = Height / 2;
 38        this.VelX = (!!Math.round(Math.random() * 1) ? 1.5 : -1.5);
 39        this.VelY = (!!Math.round(Math.random() * 1) ? 1.5 : -1.5);
 40      };
 41
 42      function Paddle(position) {
 43        this.Color = '#999';
 44        this.Width = 5;
 45        this.Height = 100;
 46        this.X = 0;
 47        this.Y = Height / 2 - this.Height / 2;
 48        this.Score = 0;
 49        if (position == 'left')
 50          this.X = 0;
 51        else this.X = Width - this.Width;
 52        this.Paint = function() {
 53          ctx.fillStyle = this.Color;
 54          ctx.fillRect(this.X, this.Y, this.Width, this.Height);
 55          ctx.fillStyle = this.Color;
 56          ctx.font = "normal 10pt Calibri";
 57          if (position == 'left') {
 58            ctx.textAlign = "left";
 59            ctx.fillText("score: " + Player.Score, 10, 10);
 60          } else {
 61            ctx.textAlign = "right";
 62            ctx.fillText("score: " + Computer.Score, Width - 10, 10);
 63          }
 64        };
 65        this.IsCollision = function() {
 66          if (Ball.X - Ball.Radius > this.Width + this.X || this.X > Ball.Radius * 2 + Ball.X - Ball.Radius)
 67            return false;
 68          if (Ball.Y - Ball.Radius > this.Height + this.Y || this.Y > Ball.Radius * 2 + Ball.Y - Ball.Radius)
 69            return false;
 70          return true;
 71        };
 72      };
 73
 74      window.requestAnimFrame = (function() {
 75        return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {
 76          return window.setTimeout(callback, FPS);
 77        };
 78      })();
 79      window.cancelRequestAnimFrame = (function() {
 80        return window.cancelAnimationFrame || window.webkitCancelRequestAnimationFrame || window.mozCancelRequestAnimationFrame || window.oCancelRequestAnimationFrame || window.msCancelRequestAnimationFrame || clearTimeout
 81      })();
 82
 83      var Computer = new Paddle();
 84      var Player = new Paddle('left');
 85
 86      function Paint() {
 87        ctx.beginPath();
 88        BG.Paint();
 89        Computer.Paint();
 90        Player.Paint();
 91        Ball.Paint();
 92      }
 93
 94      function MouseMove(e) {
 95        Player.Y = e.pageY - Player.Height / 2;
 96      }
 97      canvas.addEventListener("mousemove", MouseMove, true);
 98
 99      function Loop() {
100        init = requestAnimFrame(Loop);
101        Paint();
102        if (Player.IsCollision() || Computer.IsCollision()) {
103          Ball.VelX = Ball.VelX * -1;
104          Ball.VelX += (Ball.VelX > 0 ? 0.5 : -0.5);
105          if (Math.abs(Ball.VelX) > Ball.Radius * 1.5)
106            Ball.VelX = (Ball.VelX > 0 ? Ball.Radius * 1.5 : Ball.Radius * -1.5);
107        }
108        if (Ball.Y - Ball.Radius < 0 || Ball.Y + Ball.Radius > Height)
109          Ball.VelY = Ball.VelY * -1;
110        if (Ball.X - Ball.Radius <= 0) {
111          Computer.Score++;
112          Ball.Reset();
113        } else if (Ball.X + Ball.Radius > Width) {
114          Player.Score++;
115          Ball.Reset();
116        }
117        if (Computer.Score === 10)
118          GameOver(false);
119        else if (Player.Score === 10)
120          GameOver(true);
121        Computer.Y = (Computer.Y + Computer.Height / 2 < Ball.Y ? Computer.Y + Computer.Vel : Computer.Y - Computer.Vel);
122      };
123
124      function GameOver(win) {
125        cancelRequestAnimFrame(init);
126        BG.Paint();
127        ctx.fillStyle = "#999";
128        ctx.font = "bold 40px Calibri";
129        ctx.textAlign = "center";
130        ctx.fillText((win ? "YOU WON!" : "GAME OVER"), Width / 2, Height / 2);
131        ctx.font = "normal 16px Calibri";
132        ctx.fillText("refresh to replay", Width / 2, Height / 2 + 20);
133      }
134      return {
135        Start: function() {
136          Ball.Reset();
137          Player.Score = 0;
138          Computer.Score = 0;
139          Computer.Vel = 1.25;
140          Loop();
141        }
142      };
143    })();
144    game.Start();
145  </script>
146</body>
147</html>