topical media & game development
mobile-graphic-easel-examples-Game.htm / htm
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>CreateJS Example: Space Rocks Game</title>
<script>
// this sets the namespace for CreateJS to the window object, so you can instantiate objects without specifying
// the namespace: "new Graphics()" instead of "new createjs.Graphics()"
// this is a quick way to make projects built on pervious versions of EaselJS run without extensive modifications
</script>
<script type="text/javascript" src="mobile-graphic-easel-examples-assets-preloadjs-0.3.0.min.js"></script>
<script type="text/javascript" src="mobile-graphic-easel-examples-assets-soundjs-0.4.0.min.js"></script>
<script type="text/javascript" src="mobile-graphic-easel-src-easeljs-utils-UID.js"></script>
<script type="text/javascript" src="mobile-graphic-easel-src-easeljs-geom-Matrix2D.js"></script>
<script type="text/javascript" src="mobile-graphic-easel-src-easeljs-events-EventDispatcher.js"></script>
<script type="text/javascript" src="mobile-graphic-easel-src-easeljs-display-DisplayObject.js"></script>
<script type="text/javascript" src="mobile-graphic-easel-src-easeljs-display-Container.js"></script>
<script type="text/javascript" src="mobile-graphic-easel-src-easeljs-display-Stage.js"></script>
<script type="text/javascript" src="mobile-graphic-easel-src-easeljs-events-MouseEvent.js"></script>
<script type="text/javascript" src="mobile-graphic-easel-src-easeljs-display-Shape.js"></script>
<script type="text/javascript" src="mobile-graphic-easel-src-easeljs-display-Graphics.js"></script>
<script type="text/javascript" src="mobile-graphic-easel-src-easeljs-utils-Ticker.js"></script>
<script type="text/javascript" src="mobile-graphic-easel-src-easeljs-display-Text.js"></script>
<!-- We also provide hosted minified versions of all CreateJS libraries.
http://code.createjs.com -->
<!-- Game script below -->
<script type="text/javascript" src="mobile-graphic-easel-examples-assets-SpaceRock.js"></script>
<script type="text/javascript" src="mobile-graphic-easel-examples-assets-Ship.js"></script>
<script>
var DIFFICULTY = 2; //how fast the game gets mor difficult
var ROCK_TIME = 110; //aprox tick count until a new asteroid gets introduced
var SUB_ROCK_COUNT = 4; //how many small rocks to make on rock death
var BULLET_TIME = 5; //ticks between bullets
var BULLET_ENTROPY = 100; //how much energy a bullet has before it runs out.
var TURN_FACTOR = 7; //how far the ship turns per frame
var BULLET_SPEED = 17; //how fast the bullets move
var KEYCODE_ENTER = 13; //usefull keycode
var KEYCODE_SPACE = 32; //usefull keycode
var KEYCODE_UP = 38; //usefull keycode
var KEYCODE_LEFT = 37; //usefull keycode
var KEYCODE_RIGHT = 39; //usefull keycode
var KEYCODE_W = 87; //usefull keycode
var KEYCODE_A = 65; //usefull keycode
var KEYCODE_D = 68; //usefull keycode
var shootHeld; //is the user holding a shoot command
var lfHeld; //is the user holding a turn left command
var rtHeld; //is the user holding a turn right command
var fwdHeld; //is the user holding a forward command
var timeToRock; //difficulty adjusted version of ROCK_TIME
var nextRock; //ticks left until a new space rock arrives
var nextBullet; //ticks left until the next shot is fired
var rockBelt; //space rock array
var bulletStream; //bullet array
var canvas; //Main canvas
var stage; //Main display stage
var ship; //the actual ship
var alive; //wheter the player is alive
var messageField; //Message display field
var scoreField; //score Field
var loadingInterval = 0;
var preload;
//register key functions
document.onkeydown = handleKeyDown;
document.onkeyup = handleKeyUp;
var preload;
function init() {
if (window.top != window) {
document.getElementById("header").style.display = "none";
}
if (!createjs.Sound.initializeDefaultPlugins()) {
document.getElementById("error").style.display = "block";
document.getElementById("content").style.display = "none";
return;
}
if (createjs.Sound.BrowserDetect.isIOS || createjs.Sound.BrowserDetect.isAndroid) { // || createjs.Sound.BrowserDetect.isBlackberry OJR blackberry has not been tested yet
document.getElementById("mobile").style.display = "block";
document.getElementById("content").style.display = "none";
return;
}
canvas = document.getElementById("gameCanvas");
stage = new createjs.Stage(canvas);
messageField = new createjs.Text("Loading", "bold 24px Arial", "#FFFFFF");
messageField.maxWidth = 1000;
messageField.textAlign = "center";
messageField.x = canvas.width / 2;
messageField.y = canvas.height / 2;
stage.addChild(messageField);
stage.update(); //update the stage to show text
// begin loading content (only sounds to load)
var manifest = [
{id:"begin", src:"mobile-graphic-easel-examples-assets-Game-Spawn.mp3|../../mobile-graphic-easel-examples-assets-Game-Spawn.ogg"},
{id:"break", src:"mobile-graphic-easel-examples-assets-Game-Break.mp3|../../mobile-graphic-easel-examples-assets-Game-Break.ogg", data:6},
{id:"death", src:"mobile-graphic-easel-examples-assets-Game-Death.mp3|../../mobile-graphic-easel-examples-assets-Game-Death.ogg"},
{id:"laser", src:"mobile-graphic-easel-examples-assets-Game-Shot.mp3|../../mobile-graphic-easel-examples-assets-Game-Shot.ogg", data:6},
{id:"music", src:"mobile-graphic-easel-examples-assets-18-machinae_supremacy-lord_krutors_dominion.mp3|../../mobile-graphic-easel-examples-assets-18-machinae_supremacy-lord_krutors_dominion.ogg"}
];
preload = new createjs.LoadQueue();
preload.installPlugin(createjs.Sound);
preload.addEventListener("complete", doneLoading); // add an event listener for when load is completed
preload.addEventListener("progress", updateLoading);
preload.loadManifest(manifest);
}
function stop() {
if (preload != null) { preload.close(); }
createjs.Sound.stop();
}
function updateLoading() {
messageField.text = "Loading " + (preload.progress*100|0) + "%"
stage.update();
}
function doneLoading(event) {
clearInterval(loadingInterval);
scoreField = new createjs.Text("0", "bold 12px Arial", "#FFFFFF");
scoreField.textAlign = "right";
scoreField.x = canvas.width - 10;
scoreField.y = 22;
scoreField.maxWidth = 1000;
messageField.text = "Welcome: Click to play";
// start the music
createjs.Sound.play("music", createjs.Sound.INTERRUPT_NONE, 0, 0, -1, 0.4);
watchRestart();
}
function watchRestart() {
//watch for clicks
stage.addChild(messageField);
stage.update(); //update the stage to show text
canvas.onclick = handleClick;
}
function handleClick() {
//prevent extra clicks and hide text
canvas.onclick = null;
stage.removeChild(messageField);
// indicate the player is now on screen
createjs.Sound.play("begin");
restart();
}
//reset all game logic
function restart() {
//hide anything on stage and show the score
stage.removeAllChildren();
scoreField.text = (0).toString();
stage.addChild(scoreField);
//new arrays to dump old data
rockBelt = new Array();
bulletStream = new Array();
//create the player
alive = true;
ship = new Ship();
ship.x = canvas.width / 2;
ship.y = canvas.height / 2;
//log time untill values
timeToRock = ROCK_TIME;
nextRock = nextBullet = 0;
//reset key presses
shootHeld = lfHeld = rtHeld = fwdHeld = dnHeld = false;
//ensure stage is blank and add the ship
stage.clear();
stage.addChild(ship);
//start game timer
if (!createjs.Ticker.hasEventListener("tick")) {
createjs.Ticker.addEventListener("tick", tick);
}
}
function tick(event) {
//handle firing
if(nextBullet <= 0) {
if(alive && shootHeld){
nextBullet = BULLET_TIME;
fireBullet();
}
} else {
nextBullet--;
}
//handle turning
if(alive && lfHeld){
ship.rotation -= TURN_FACTOR;
} else if(alive && rtHeld) {
ship.rotation += TURN_FACTOR;
}
//handle thrust
if(alive && fwdHeld){
ship.accelerate();
}
//handle new spaceRocks
if(nextRock <= 0) {
if(alive){
timeToRock -= DIFFICULTY; //reduce spaceRock spacing slowly to increase difficulty with time
var index = getSpaceRock(SpaceRock.LRG_ROCK);
rockBelt[index].floatOnScreen(canvas.width, canvas.height);
nextRock = timeToRock + timeToRock*Math.random();
}
} else {
nextRock--;
}
//handle ship looping
if(alive && outOfBounds(ship, ship.bounds)) {
placeInBounds(ship, ship.bounds);
}
//handle bullet movement and looping
for(bullet in bulletStream) {
var o = bulletStream[bullet];
if(!o || !o.active) { continue; }
if(outOfBounds(o, ship.bounds)) {
placeInBounds(o, ship.bounds);
}
o.x += Math.sin(o.rotation*(Math.PI/-180))*BULLET_SPEED;
o.y += Math.cos(o.rotation*(Math.PI/-180))*BULLET_SPEED;
if(--o.entropy <= 0) {
stage.removeChild(o);
o.active = false;
}
}
//handle spaceRocks (nested in one loop to prevent excess loops)
for(spaceRock in rockBelt) {
var o = rockBelt[spaceRock];
if(!o || !o.active) { continue; }
//handle spaceRock movement and looping
if(outOfBounds(o, o.bounds)) {
placeInBounds(o, o.bounds);
}
o.tick(event);
//handle spaceRock ship collisions
if(alive && o.hitRadius(ship.x, ship.y, ship.hit)) {
alive = false;
stage.removeChild(ship);
messageField.text = "You're dead: Click or hit enter to play again";
stage.addChild(messageField);
watchRestart();
//play death sound
createjs.Sound.play("death", createjs.Sound.INTERRUPT_ANY);
continue;
}
//handle spaceRock bullet collisions
for(bullet in bulletStream) {
var p = bulletStream[bullet];
if(!p || !p.active) { continue; }
if(o.hitPoint(p.x, p.y)) {
var newSize;
switch(o.size) {
case SpaceRock.LRG_ROCK: newSize = SpaceRock.MED_ROCK;
break;
case SpaceRock.MED_ROCK: newSize = SpaceRock.SML_ROCK;
break;
case SpaceRock.SML_ROCK: newSize = 0;
break;
}
//score
if(alive) {
addScore(o.score);
}
//create more
if(newSize > 0) {
var i;
var index;
var offSet;
for(i=0; i < SUB_ROCK_COUNT; i++){
index = getSpaceRock(newSize);
offSet = (Math.random() * o.size*2) - o.size;
rockBelt[index].x = o.x + offSet;
rockBelt[index].y = o.y + offSet;
}
}
//remove
stage.removeChild(o);
rockBelt[spaceRock].active = false;
stage.removeChild(p);
bulletStream[bullet].active = false;
// play sound
createjs.Sound.play("break", createjs.Sound.INTERUPT_LATE, 0, 0.8);
}
}
}
//call sub ticks
ship.tick(event);
stage.update(event);
}
function outOfBounds(o, bounds) {
//is it visibly off screen
return o.x < bounds*-2 || o.y < bounds*-2 || o.x > canvas.width+bounds*2 || o.y > canvas.height+bounds*2;
}
function placeInBounds(o, bounds) {
//if its visual bounds are entirely off screen place it off screen on the other side
if(o.x > canvas.width+bounds*2) {
o.x = bounds*-2;
} else if(o.x < bounds*-2) {
o.x = canvas.width+bounds*2;
}
//if its visual bounds are entirely off screen place it off screen on the other side
if(o.y > canvas.height+bounds*2) {
o.y = bounds*-2;
} else if(o.y < bounds*-2) {
o.y = canvas.height+bounds*2;
}
}
function fireBullet() {
//create the bullet
var o = bulletStream[getBullet()];
o.x = ship.x;
o.y = ship.y;
o.rotation = ship.rotation;
o.entropy = BULLET_ENTROPY;
o.active = true;
//draw the bullet
o.graphics.beginStroke("#FFFFFF").moveTo(-1, 0).lineTo(1, 0);
// play the shot sound
createjs.Sound.play("laser", createjs.Sound.INTERUPT_LATE);
}
function getSpaceRock(size) {
var i = 0;
var len = rockBelt.length;
//pooling approach
while(i <= len){
if(!rockBelt[i]) {
rockBelt[i] = new SpaceRock(size);
break;
} else if(!rockBelt[i].active) {
rockBelt[i].activate(size);
break;
} else {
i++;
}
}
if(len == 0) {
rockBelt[0] = new SpaceRock(size);
}
stage.addChild(rockBelt[i]);
return i;
}
function getBullet() {
var i = 0;
var len = bulletStream.length;
//pooling approach
while(i <= len){
if(!bulletStream[i]) {
bulletStream[i] = new createjs.Shape();
break;
} else if(!bulletStream[i].active) {
bulletStream[i].active = true;
break;
} else {
i++;
}
}
if(len == 0) {
bulletStream[0] = new createjs.Shape();
}
stage.addChild(bulletStream[i]);
return i;
}
//allow for WASD and arrow control scheme
function handleKeyDown(e) {
//cross browser issues exist
if(!e){ var e = window.event; }
switch(e.keyCode) {
case KEYCODE_SPACE: shootHeld = true; return false;
case KEYCODE_A:
case KEYCODE_LEFT: lfHeld = true; return false;
case KEYCODE_D:
case KEYCODE_RIGHT: rtHeld = true; return false;
case KEYCODE_W:
case KEYCODE_UP: fwdHeld = true; return false;
case KEYCODE_ENTER: if(canvas.onclick == handleClick){ handleClick(); }return false;
}
}
function handleKeyUp(e) {
//cross browser issues exist
if(!e){ var e = window.event; }
switch(e.keyCode) {
case KEYCODE_SPACE: shootHeld = false; break;
case KEYCODE_A:
case KEYCODE_LEFT: lfHeld = false; break;
case KEYCODE_D:
case KEYCODE_RIGHT: rtHeld = false; break;
case KEYCODE_W:
case KEYCODE_UP: fwdHeld = false; break;
}
}
function addScore(value) {
//trust the field will have a number and add the score
scoreField.text = (Number(scoreField.text) + Number(value)).toString();
}
</script>
<link rel="stylesheet" type="text/css" href="mobile-graphic-easel-examples-assets-demoStyles.css" />
<style type="text/css">
#content {
user-select: none;
background-color:#000000;
width: 960px;
height: 400px;
}
</style>
</head>
<body onload="init();">
<header id="header" class="SoundJS">
<h1><span class="text-product">Sound<strong>JS</strong></span> Space Rocks Game</h1>
<p>Example use of SoundJS for a game, built <a href="http://www.easeljs.com" target="_blank">EaselJS</a> a canvas management tool.
Music Copyright © 2010 <a href="http://machinaesupremacy.com" target="_blank">Machinae Supremacy</a> - Lord Krutors Dominion. Used with permission for non commercial use.</p>
</header>
<div id="content">
<canvas id="gameCanvas" width="960" height="400"></canvas>
</div>
<div id="error">
<h1>Sorry!</h1>
<p>SoundJS is not currently supported in your browser.</p>
<p>We are currently working on support for iOS. Please <a href="http://github.com/CreateJS/SoundJS/issues" target="_blank">log a bug</a>
if you see this in any other browsers.</p>
</div>
</body>
</html>
(C) Æliens
04/09/2009
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.