Crafting Pong in Playcraft JS

This is the first part of a series of articles documenting my experience with building a Pong clone in the Playcraft Engine for JavaScript. Looking for Part II or Part III?

For about six months, I had been working on building a JavaScript engine for my Pong Kombat¬†resurrection project. My previous attempts were using pre-built engines, like XNA and Cocos 2D, but in the web world, the engines I had been researching weren’t a good fit for me, for a variety of reasons. If there’s one thing I learned during those six months, it was that there is a lot of stuff involved in building an engine that is optimized for it’s platform.

There was one engine that intrigued me, though, and I signed up for Playcraft Labs’ beta program. Having all the research and experiences behind me, I decided to give it a try, and I knew instantly that this was the perfect engine for me. Not only had it been written in the same style that I was attempting (Entity-Component-System), it was also much further along, having a physics engine, particle emitters, and took into account all the JavaScript quirks I had been reading about: things like a memory manager for pooling objects and curbing garbage collection.

This is going to be a three-part series of articles detailing my experience in creating a Pong clone using the Playcraft beta v0.5.5. So to start things off, head on over and download the latest version of the Playcraft Engine. Note: Registration is required to gain access to the beta resources.

Once you have downloaded the archive and unzipped it, you’ll see some demos and a projects folder for you to work out of. Check out the demos to make sure everything is running. You may need to run it from a webserver or localhost in order to avoid cross-domain requests.

I highly recommend reviewing the sample project and the Guides that are available for registered users of the beta, as the provide a lot of valuable information on the structure of a Playcraft game and all the neat stuff at your disposal. Let’s start by making a copy of the `yourgame` folder. I’ll call it “pong”.

Looking at the index.html, we have a pretty straight-forward template for creating the game. I renamed the relevant titles to reflect the name of my game.

index.html – Naming the project

<head>
   <title>Playcraft Pong</title>
   // ...
   <script>
   pc.start( 'pcGameCanvas', 'Pong', 'js/', [ 'game.js' ] );
   </script>
</head>

The included game.js file is where all the real action takes place. It contains an instance of the game object and an instance of a scene that renders a box on the screen. I renamed the game object to reflect the name of my game and the second parameter of the pc.start call in the index.html file above.

game.js – Naming the game object

Pong = pc.Game.extend( 'Pong',
   // ...
);

Everything else in the game object extension is for adding the scene instance and handling resources like images and sounds. The GameScene object contains a layer for handling entities, or the various things that make up the game. In Pong, the entities are the paddles, the ball, score, etc. The Playcraft engine has various systems for handling things like rendering a scene. Adding the Render system tells the engine that this layer is going to need the logic for rendering objects every draw cycle.

That explains the Entity and System parts of the Entity-Component-System. The components are snippets of reusable code that can be added to an entity. Things like describing where an entity is on the screen, or what an entity looks like are examples of components. This allows you to mix and match components as needed, reducing redundancy and cruft.

The sample project shows how to render a red box on the screen. The box entity, utilizes two components: a Rect component for describing what it looks like, and a Spatial component for describing where it is. Both of these components require the Render system. Other components, like Physics or Effects, will need their corresponding systems in order to work properly.

For Pong, we need a ball, so let’s start by changing the box code in the game scene to draw a circle instead.

game.js – Box to Ball

// box : null,
ball : null,

init : function( )
{
   // ...
   this.ball = pc.Entity.create( this.gameLayer );
   this.ball.addComponent( pc.components.Circle.create( { color : '#FFFFFF' } ) );
   this.ball.addComponent( pc.components.Spatial.create( { x : 200, y : 200, w : 15, h : 15 } ) );
   // ...
},

White-Circle

After hitting refresh, we see a circle drawn where the red box used to be. How would you make it so the ball is in the center of the screen? Hint: you can get the screen size by using the pc.device.canvasWidth and .canvasHeight variables.

We also need two paddles, one for the player on the left, and one for the computer opponent on the right. We can use the same concept as the ball but use Rect component instead. It’s worth noting that the spatial component describes the location of the upper left part of the entity, so you’ll need to accommodate that in your positioning.

game.js – Adding Paddles

ball : null,
player : null,
opponent : null,

init : function( )
{
   // ...
   this.ball.addComponent( pc.components.Spatial.create( { x : pc.device.canvas.width / 2 - 8, y : pc.device.canvas.height / 2 - 8, w : 15, h : 15 } ) );

   this.player = pc.Entity.create( this.gameLayer );
   this.player.addComponent( pc.components.Rect.create( { color : '#FFFFFF' } ) );
   this.player.addComponent( pc.components.Spatial.create( { x : pc.device.canvas.width * 0.1, y : pc.device.canvas.height / 2 - 50, w : 15, h : 100 } ) );

   this.opponent = pc.Entity.create( this.gameLayer );
   this.opponent.addComponent( pc.components.Rect.create( { color : '#FFFFFF' } ) );
   this.opponent.addComponent( pc.components.Spatial.create( { x : pc.device.canvas.width * 0.9 - 15, y : pc.device.canvas.height / 2 - 50, w : 15, h : 100 } ) );
   // ...
}

The only other entities we need are two text objects for displaying the player and opponent scores. Adding text is just the same as adding the shapes as above. Using the API documentation and demos, we just need to create an entity with the Text and Spatial components.

game.js – Scores

// ...
playerScore : null,
opponentScore : null,

init : function( )
{
   // ...
   this.playerScore = pc.Entity.create( this.gameLayer );
   this.playerScore.addComponent( pc.components.Text.create( { color : '#FFFFFF', fontHeight : pc.device.canvas.height * 0.1, text : [ '0' ] } ) );
   this.playerScore.addComponent( pc.components.Spatial.create( { x : pc.device.canvas.width * 0.25, y : pc.device.canvas.height * 0.1 } ) );

   this.opponentScore = pc.Entity.create( this.gameLayer );
   this.opponentScore.addComponent( pc.components.Text.create( { color : '#FFFFFF', fontHeight : pc.device.canvas.height * 0.1, text : [ '0' ] } ) );
   this.opponentScore.addComponent( pc.components.Spatial.create( { x : pc.device.canvas.width * 0.75, y : pc.device.canvas.height * 0.1 } ) );
   // ...
}

Entities

Now we have a scene that renders all of the visible entities that make up Pong. It’s actually starting to take some form! As you can see in the sample project, adding input is fairly simple in Playcraft. I’ll take a look at making things moving in the next post.

View the full index.html Source
View the full js/game.js Source 

 

To be continued…