On Github atleastimtrying / kinetic-talk
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 canbe used to create more complex applications.
In addition to the above you are able tocreate 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 ofmoving 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 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...
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>
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: