Kinetic.js – A Kinetic Canvas – First... the HTML5 Canvas



Kinetic.js – A Kinetic Canvas – First... the HTML5 Canvas

0 0


kinetic-talk

Putting paul hutson's FES talk online.

On Github atleastimtrying / kinetic-talk

Kinetic.js

A Kinetic Canvas

Presented by Paul Hutson

First... the HTML5 Canvas

  • The canvas tag is "New" with HTML5
  • It enables us to dynamically generate interactive images in the browser
  • It works across most modern devices and browsers - for instance, Safari on the iPhone

You could say it's like Flash... ...but without having to download any plugins.

Enter Kinetic

  • An API used to create images on the screen.
  • JavaScript based (as all Canvas creation is) - meaning it should be familiar to you all and easy to pick up.

How Kinetic Works

Kinetic is applied to a div container within the body of the HTML page to create a "Stage" for the rest of your image.


                    var stage = new Kinetic.Stage({
                        container: 'containerdiv',
                        width: 578,
                        height: 200
                    });

					    

Layers

On top of the stage you can use layers where objects are stored


                    var layer = new Kinetic.Layer();

                    stage.add(layer);

					    

Kinetic Objects

There are loads of different predifined types of objects (circles, lines, rectangles, text, etc).

You can also images and sprites that canbe used to create more complex applications.

In addition to the above you are able tocreate custom shapes using coordinates.

Groups

"Groups" are able to contain one or more objects on the screen.

They allow you to easily manipulate the objects with a single call (i.e. animate, fade out, remove/destroy).

Moving Pictures

There are two different ways ofmoving things within the Canvas

Transitions & Animations

Transitions

This is the easiest way to move objects or groups around around the stage...


                            shape.transitionTo({
                              x: 100,
                              y: 100,
                              duration: 1
                            });

					        

For reference, this is also how you fade things in and out as well by changing the opacity of the filter.

Animations

More complicated, but can be used to create custom animations.


                var anim = new Kinetic.Animation(function(frame) {
                    var time = frame.time,
                        timeDiff = frame.timeDiff,
                        frameRate = frame.frameRate;

                    // update stuff
                }, layer);

                anim.start();

					        

Events

The user can interact with the Canvas by using normalJS style actions : Click, Touch, Hover, etc...


                        shape.on('click', function(evt){
                            // do stuff
                        });

					        

You can also use keys and controllers to interact with the canvas...

SNAKE! SNAKE!!

Creating the classic game "Snake" in Kinetic uses a numberof different elements from the Kinetic Framework.

Page Outline:

<body> 
	<div id="container"><!--none--></div> 
	<div id="newGameContainer">
		<input type="button" value="New Game" onclick="deaded=true;NewGame();"/>
	</div>
</body>
                            

SNAKE! SNAKE!! - Pt2

Page Load:

// On the start of the page, run this..
$(document).ready(function() {
	// Create the stage
	stage = new Kinetic.Stage({
		    container: 'container',
		    width: 300,
		    height: 300
	});
		
	// Now add a new layer
	layer = new Kinetic.Layer();
		      	
	// Now add the scoring layer
	scoringLayer = new Kinetic.Layer();
		      	
	// Create some text
	scoreText = new Kinetic.Text({
		    x: 10,
		    y: 10,
		    text: 'Press "New Game" to start a new game\n\nUse the arrow keys to control the snake.',
		    fontSize: 10,
		    fontFamily: 'Calibri',
		    textFill: 'green'
	});
	scoringLayer.add(scoreText);
		      	
	// Create a text element ready for the death message
	highlightText = new Kinetic.Text({
		    x: 0,
		    y: 100,
		    width: 300,
		    text: '',
		    fontSize: 20,
		    fontFamily: 'Calibri',
		    textFill: 'red',
		    align: 'center'
	});
	scoringLayer.add(highlightText);
		      	
	// add the layer to the stage
	stage.add(layer);
	stage.add(scoringLayer);
});
                            

SNAKE! SNAKE!! - Pt3

New Game:

// Game functions
// Create a new game
function NewGame()
{
	// Remove any existing blocks 
	if (snakeLowCount!=snakeTotCount)
	{
		    for (var i=snakeLowCount;i<=snakeTotCount;i++)
		    { 
			        SnakeRemovePiece(i);
		    }
					
		    layer.remove(layer.get(".SnakeFood")[0]);
		    layer.draw();
	}
				
	// Set up everything
	grid = [];
	snakeLength = 5;
	snakeShowing = 1;
	snakeSpeed = 100;
	snakeDirection = "R";
	snakeLowCount = 1;
	snakeScore = 0;
	scoreText.setText("Score : 0"); 
	deaded = false;
	snakeHeadLocationX = 10;
	snakeHeadLocationY = 10;
	snakeTotCount = 1;
	snakeLowCount = 1;
	snakeSpeed = 100;
				
	// Reset the death message
	highlightText.setText("");
	scoringLayer.draw();
				
	// Add the first block
	AddBlock();
				
	// Start the game
	StartGame();
};
                            

SNAKE! SNAKE!! - Pt4

Adding Blocks to the Canvas:

// Add a block to the screen
function AddBlock()
{
	// Create the name item
	var newItemName = "Snake" + snakeTotCount;
				
	// Create a new group
	var newGroup = new Kinetic.Group({
		    id: newItemName,
		    name: newItemName,
		    x: snakeHeadLocationX,
		    y: snakeHeadLocationY,
		    width: 10,
		    height: 10
	});
				
	// Create the first block
	var rect = new Kinetic.Rect({
		    width: 10,
		    height: 10,
		    fill: 'black'
	});
				
	newGroup.add(rect);
				
	// Add the snake item to the grid
	grid["LOC" + snakeHeadLocationX + "," + snakeHeadLocationY] = true;
				
	// Add the block and draw it as well.
	layer.add(newGroup);
	layer.draw();
		      	
	return newGroup;
}
                            

SNAKE! SNAKE!! - Pt5

Starting and Moving:

// Start the game
function StartGame()
{
	// Generate new snake food.
	SnakeFood();
				
	// Now start the moving
	SnakeMove();
				
	// Draw the scoring layer
	scoringLayer.draw();
}
			
// Move the snake
function SnakeMove()
{
	// Variables for use in the snake move function
	var newHeadX = snakeHeadLocationX;
	var newHeadY = snakeHeadLocationY;
				
	// New X and Y position
	if (snakeDirection == "R")
	{
		    newHeadX = snakeHeadLocationX + 10;	
	} else if (snakeDirection == "L") {
		    newHeadX = snakeHeadLocationX - 10;
	} else if (snakeDirection == "U") {
		    newHeadY = snakeHeadLocationY - 10;
	} else {
		    newHeadY = snakeHeadLocationY + 10;
	};
	
	// Set the size to be longer
	snakeShowing++;
	snakeTotCount++;
	
	// Check whether it is colliding
	SnakeCheckNoCollide(newSnakeElement,newHeadX,newHeadY);
	
	// Check whether the snake is still alive.
	if (!deaded)
	{
		    // Set the new head location
		    snakeHeadLocationX = newHeadX;
		    snakeHeadLocationY = newHeadY;
					
		    // Add the first block
		    var newSnakeElement = AddBlock();
				
		    // Now set the count down for the piece removal
		    if (snakeShowing == snakeLength)
		    {
			        SnakeRemovePiece(snakeLowCount);	
		    };
				
		    // Let the snake eat
		    SnakeEat();
				
		    // Set this to make this work next time.
		    setTimeout("SnakeMove();",snakeSpeed);
	};
}
                            

SNAKE! SNAKE!! - Pt6

Eating and Removing Pieces:

// Snake Food Location
function SnakeEat()
{
	// Check whether the snake head and the food are in the same place
	if ((snakeHeadLocationX==snakeFoodLocX)&&(snakeHeadLocationY==snakeFoodLocY))
	{
		    // Increase the size of the snake by one
		    snakeLength++;
					
		    // Remove the existing snake food
		    layer.remove(layer.get(".SnakeFood")[0]);
		    layer.draw();
					
		    // Update the score
		    snakeScore+=10;
					
		    // Make this faster
		    if (snakeSpeed>10)
		    {
			        snakeSpeed-=4;	
		    }
					
		    // Now change the text.
		    scoreText.setText("Score : " + snakeScore); 
		    scoringLayer.draw();
					
		    // Generate a bit more food
		    SnakeFood();
	}
}
			
// Remove a snake piece after a timeout
function SnakeRemovePiece(PieceID)
{	
	// Create the name item
	var itemName = ".Snake" + PieceID;
				
	// Advance the snake low count along
	snakeLowCount++;
				
	// Update the amount showing and remove an item
	snakeShowing--;
				
	// Get the shape from the layer
	var shape = layer.get(itemName)[0];
				
	if (shape!=undefined)
	{
		    // Set the grid location to false
		    grid["LOC" + shape.getX() + "," + shape.getY()] = false;
					
		    // Remove a block and refresh the layer.
		    layer.remove(shape);
		    layer.draw();
	}
}
                            

SNAKE! SNAKE!! - Pt7

Collision:

// Check whether the snake collides with the wall..
// .. or itself.
function SnakeCheckNoCollide(newSnakeElement,snakeHeadLocationNewX,snakeHeadLocationNewY)
{
	// Check if the snake has collided with the border.
	if (((snakeHeadLocationNewX>290) || (snakeHeadLocationNewX<=-10)) || ((snakeHeadLocationNewY>290) ||(snakeHeadLocationNewY<=-10)))
	{
		    deaded = true; 
	} else if (grid["LOC" + snakeHeadLocationNewX + "," + snakeHeadLocationNewY]) {
		    deaded = true; 
	};
				
	// if the snake has hit something (i.e. died) display the /death message/
	if (deaded)
	{
		    highlightText.setText("Perrriill, Deaattthhhh!\nGAME OVER");
		    scoringLayer.draw();
	};
}
                            

SNAKE! SNAKE!! - Pt8

Gametime:

Questions?

THE END