Presented by Paul Hutson
You could say it's like Flash...
...but without having to download any plugins.
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
});
On top of the stage you can use layers where objects are stored
var layer = new Kinetic.Layer();
stage.add(layer);
There are loads of different predifined types
of objects (circles, lines, rectangles, text, etc).
You can also images and sprites that can
be used to create more complex applications.
In addition to the above you are able to
create custom shapes using coordinates.
"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).
There are two different ways of
moving things within the Canvas
Transitions & Animations
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.
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();
The user can interact with the Canvas by using normal
JS 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...
Creating the classic game "Snake" in Kinetic uses a number
of 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>
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);
});
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();
};
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;
}
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);
};
}
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();
}
}
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();
};
}
Gametime: