HTML5 Canvas game, timer - html

Problem
Hello, I am creating a game and am stuck on how to get a timer on the canvas. I am aware that there are plenty of questions on Stackoverflow already about this topic.
Question
Could someone please tell me why my code does not work.
Code
var game = create_game();
game.init();
function create_game() {
debugger;
var level = 1;
var projectiles_per_level = 1;
var min_speed_per_level = 1;
var max_speed_per_level = 2;
var last_projectile_time = 0;
var next_projectile_time = 0;
var width = 600;
var height = 500;
var delay = 1000;
var item_width = 30;
var item_height = 30;
var total_projectiles = 0;
var projectile_img = new Image();
var projectile_w = 30;
var projectile_h = 30;
var player_img = new Image();
var background_img = new Image();
var c, ctx;
var projectiles = [];
var player = {
x: 200,
y: 400,
score: 0
};
function init() {
background_img.src = "background.png";
projectile_img.src = "projectile.png";
player_img.src = "player.png";
level = 1;
total_projectiles = 0;
projectiles = [];
c = document.getElementById("c");
ctx = c.getContext("2d");
ctx.fillStyle = "#410b11";
ctx.fillRect(0, 0, 500, 600);
c.addEventListener("mousemove", function (e) {
//moving over the canvas.
var bounding_box = c.getBoundingClientRect();
player.x = (e.clientX - bounding_box.left) * (c.width / bounding_box.width) - player_img.width / 2;
}, false);
setupProjectiles();
requestAnimationFrame(tick);
}
function tick() {
Most of game logic is here, I deleted as it I dont believe it helped keeping it in.
var i;
var projectile;
var dateNow = Date.now();
c.width = c.width;
ctx.drawImage(background_img, 0, 0);
for (i = 0; i < projectiles.length; i++) {
projectile = projectiles[i];
if (dateNow > projectile.delay) {
projectile.y += projectile.v;
if (collision(projectile)) {
initProjectile(i);
player.score++;
} else if (projectile.y > height) {
initProjectile(i);
} else {
ctx.drawImage(projectile_img, projectile.x, projectile.y);
}
}
}
ctx.font = "bold 24px sans-serif";
ctx.fillStyle = "#d1c09c";
ctx.fillText(player.score, c.width - 50, 50);
ctx.fillText("Level: " + level, 20, 50);
ctx.drawImage(player_img, player.x, player.y);
maybeIncreaseDifficulty();
requestAnimationFrame(tick);
This is where i was going to put my code for the timer:
var startTime;
function drawElapsedTime(){
var elapsed=parseInt((new Date() - startTime)/1000);
ctx.beginPath();
ctx.fillStyle="red";
ctx.font="bold 24px sans-serif";
g.fillText(elapsed+" secs", 75,25);
g.restore();
}
}
return {
init: init
};
}
I hope this makes sense, sorry for the overload of code.

From what I see, you might have forgotten to initialize your startTime variable.
ParseInt() of something undefined returns NaN.
Make sure to assign a value to it and that this value is accessible in the scope of your drawElapsedTime() function.

Related

Make an AnalyserNode react to an HTMLAudioElement

I'm trying to get a spectroscope (sine wave) to show while an audio file is playing. The audio file plays fine but the graph only shows a flat line:
function play() {
var audio = document.querySelector('audio');
audio.load();
audio.play();
var context = new (window.AudioContext || window.webkitAudioContext)();
var source = context.createMediaElementSource(audio);
var analyser = context.createAnalyser();
analyser.minDecibels = -90;
analyser.maxDecibels = -10;
analyser.smoothingTimeConstant = 0.85;
source.connect(context.destination);
var canvas = document.querySelector('canvas');
var canvasCtx = canvas.getContext('2d');
var drawVisual;
var WIDTH = canvas.width;
var HEIGHT = canvas.height;
analyser.fftSize = 2048;
var bufferLength = analyser.fftSize;
var dataArray = new Uint8Array(bufferLength);
canvasCtx.clearRect(0, 0, WIDTH, HEIGHT);
var draw = function() {
drawVisual = requestAnimationFrame(draw);
analyser.getByteTimeDomainData(dataArray);
canvasCtx.fillStyle = 'rgb(255, 255, 255)';
canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);
canvasCtx.lineWidth = 2;
canvasCtx.strokeStyle = 'rgb(255, 0, 255)';
canvasCtx.beginPath();
var sliceWidth = WIDTH / bufferLength;
var x = 0;
for(var i = 0; i < bufferLength; i++) {
var v = dataArray[i] / 128.0;
var y = v * HEIGHT / 2;
if(i === 0) {
canvasCtx.moveTo(x, y);
} else {
canvasCtx.lineTo(x, y);
}
x += sliceWidth;
}
canvasCtx.lineTo(canvas.width, canvas.height / 2);
canvasCtx.stroke();
};
draw();
}
<audio loop src="data:audio/ogg;base64,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UkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSqmklFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimVUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFIKAJCKcACQejChDBQashIASAUAAIxRSinGnIMQMeYYY9BJKClizDnGHJSSUuUchBBSaS23yjkIIaTUUm2Zc1JaizHmGDPnpKQUW805h1JSi7HmmmvupLRWa64151paqzXXnHPNubQWa64515xzyzHXnHPOOecYc84555xzzgUA4DQ4AIAe2LA6wknRWGChISsBgFQAAAIZpRhzzjnoEFKMOecchBAihRhzzjkIIVSMOeccdBBCqBhzzDkIIYSQOecchBBCCCFzDjroIIQQQgcdhBBCCKGUzkEIIYQQSighhBBCCCGEEDoIIYQQQgghhBBCCCGEUkoIIYQQQgmhlFAAAGCBAwBAgA2rI5wUjQUWGrISAAACAIAclqBSzoRBjkGPDUHKUTMNQkw50ZliTmozFVOQORCddBIZakHZXjILAACAIAAgwAQQGCAo+EIIiDEAAEGIzBAJhVWwwKAMGhzmAcADRIREAJCYoEi7uIAuA1zQxV0HQghCEIJYHEABCTg44YYn3vCEG5ygU1TqIAAAAAAADADgAQDgoAAiIpqrsLjAyNDY4OjwCAAAAAAAFgD4AAA4PoCIiOYqLC4wMjQ2ODo8AgAAAAAAAAAAgICAAAAAAABAAAAAgIBPZ2dTAAQiVgAAAAAAAGJlAAACAAAAPuePCyUVNCgpJykqMhMUFBQfHwEBAQEBAQEBAQEBAQEdEzctLSorKy05DN3v80/tzuTbDAAIjkoywUfOEcIE+hpP+uN/gfj5tZru2igfgIQDAAAAAAAAQAEAoAc3r//fwfNvv/rq+Zf287YCJEmyCLVtAF4r78vbHxDkgw/cXzRKwAMAfv4QAL4OAAAAAAAAAAAAAJ7KAACUfwBeK+/L2x8Q5IMP3F80SoEHAPz8oQC8agAAAAAAAAAAAAB+NgsAUPcKAF4r78vbH1DkAyvuzxplAiQcAAAAAAAAAGoAVgAA8L/mpgAA8WWjAF4r7+PbPwDi/PbA/a1EKfAAgH9/EYCtAAAAAAAAAAAAAFCvUQAAPBgAXivvy9sfIPLBF+7PGiXgJACAbwAAAAAAAAAAAACAmmMAFHhiAACgMpUAFhtv8kvCS8N+Pj8wNzFQwkPX148e1XWNnjoAHQAAAAAAAAAIn45Uqd4jhK0agAfgDgFM7+99+cuBAAAA4BkbeKnpdxEAVO/v4xZaAwAAAJwRcO718GsOSABM7+99+VsDAAAA+lPC93HqWwI0AETv7/NrWgMAAAD6DwF3X5ddAkgAbGHK5YvHI8F64jVDQ8WPV23Gj1dtTo+/76dH77FDAaRMdby4jQQ2sj3eJY6lXhSNpV6sjN1drMzdlStuhwAKDg4OBgAAAAAAAAAALNkvru5u3yUwvf56EPWqzemN99h41eb0xntsPANM6+/jO5Ly/rGyAQAAQJOIESgAOhuP9CXJluV/OJCf5ewtPDjPT58+PSfsawCADigAAAAAAADak7cmS87/Oz6JMcYYc4wKUXsAAF4rj+vbH6DbB3457i+aCE4CAPgGAAoAAAAAAAAAAKDmGAD0eGIAAACqC4MBAF4rj+vbH6DbB3457i+aCE4CALgGgAIAAAAAAAAAAPCzAgBnfDUAAADV1+EBAF4rj8v7f93N+f2X4/46oznBAwD+9h0A/C0AAAAAAAAAAAAAdwEAAFj1AF4r9/uHP4CwD3y63Z81mgtOAgB4AAAAAAAAAAAAAAAYTQBwemwKAACMxwNeK4/r2x+A2wd+Oe4vGs0DJwEA/A4AAAAAAAAAAAAAlJ0AgNMwIwAAMK46XiuP41vCSzfnt98dz28lugA8AODfHw4Afk4AAAAAAAAAoAjVA1ToBgAAWP4BPro26EcSKvkNW8cpZ2/hoTcGkM/TAQAjoVAAFAoAAOHdL++QeFPqn83NVQAoN6EBEgCPADSACYAC"></audio>
<br>
<canvas width="640" height="100"></canvas>
<br>
<button onclick="play()">Play</button>
Note the audio source is hardcoded here to avoid CORS issues; normally audio.source would be set on line 3 immediately after the audio var is initialized, e.g.
var audio = document.querySelector('audio');
audio.src = 'https://www.example.com/foo.mp3';
The AnalyserNode is not connected yet. It needs to get the signal as an input which you want to analyze.
You can achieve that by changing the following line ...
source.connect(context.destination);
... into ...
source.connect(analyser).connect(context.destination);

HTML5 Canvas Floating Circles

I am trying to create a floating circles effect using HTML5 and canvas. An example of what I'm going for can be seen on https://layervault.com/ You can see the example by going to the 4th slide (titled "Introducing LayerVault for iOS") in the slider. On that slide, lots of circles are floating up out of the object. So far in my code, I am only able to get 1 circle floating up. Any ideas on the approach I should take?
My Code so far:
$(document).ready(function() {
var canvas = $("#myCanvas").get(0);
var context = canvas.getContext("2d");
var circleColors = new Array();
circleColors[0]="#f0f";
circleColors[1]="#0f0";
circleColors[2]="#00f";
circleColors[3]="#f00";
function makeCircles() {
var posX = Math.floor(Math.random()*500);
var posY = 500;
var theCircleColor = circleColors[Math.floor(Math.random()*circleColors.length)];
function renderContent()
{
context.save();
context.fillStyle=theCircleColor;
context.beginPath();
context.arc(posX,posY,40,0,2*Math.PI);
context.fill();
context.restore();
}//end function renderContent
function animationLoop()
{
canvas.width = canvas.width;
renderContent();
posY -= 5;
if (posY < -40)
posY = 500;
setTimeout(animationLoop, 33);
}//end function animationLoop
animationLoop();
}//end function makeCircles
makeCircles();
});//end document ready
You need to make an array of circles, each circle needs its own X/Y/Color and potentially speed, so they move at different rates.
So each circle will be a javascript object with
{
posX: someValue,
posY: someValue,
color: someValue,
speed: someValue
};
Then we will add many of those to an array. Here's an example using your code:
var canvas = $("#myCanvas").get(0);
var context = canvas.getContext("2d");
var circleColors = new Array();
circleColors[0] = "#f0f";
circleColors[1] = "#0f0";
circleColors[2] = "#00f";
circleColors[3] = "#f00";
var circles = [];
function makeCircles() {
for (var i = 0; i < 20; i++) {
var circle = {
posX: Math.floor(Math.random() * 500),
posY: 500,
color: circleColors[Math.floor(Math.random() * circleColors.length)],
speed: Math.floor(Math.random()*5)
};
circles.push(circle);
}
function renderContent() {
for (var i = 0; i < circles.length; i++) {
var c = circles[i];
context.fillStyle = c.color;
context.beginPath();
context.arc(c.posX, c.posY, 40, 0, 2 * Math.PI);
context.fill();
}
} //end function renderContent
function animationLoop() {
canvas.width = canvas.width;
renderContent();
for (var i = 0; i < circles.length; i++) {
var c = circles[i];
c.posY -= c.speed;
if (c.posY < -40) c.posY = 500;
}
setTimeout(animationLoop, 33);
} //end function animationLoop
animationLoop();
} //end function makeCircles
makeCircles();
And here it is live:
http://jsfiddle.net/vTaLF/

HTML5, Easel.js game problems

Been working on an easel game tutorial that involves an animated character going across the screen and avoiding crates falling from above. I've followed the code in the tutorial exactly but no joy;nothing seems to be loading (including images which are mapped correctly). No errors regarding syntax seem to occur so not sure what the problem is. It's a fair bit of code so totally understand if no-one has the time but just in case here it is ;
Site Page code (ill post the individual JavaScript file codes if anyone is interested;
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: #000;
}
</style>
<script src="lib/easeljs-0.6.0.min.js"></script>
<script src="JS/Platform.js"></script>
<script src="JS/Hero.js"></script>
<script src="JS/Crate.js"></script>
<script>
var KEYCODE_SPACE = 32, KEYCODE_LEFT = 37, KEYCODE_RIGHT = 39;
var canvas, stage, lfheld, rtheld, platforms, crates, hero, heroCenter, key, door, gameTxt;
var keyDn = false, play=true, dir="right";
var loaded = 0, vy = 0, vx = 0;
var jumping = false, inAir = true, gravity = 2;
var img = new Image();
var bgimg = new Image();
var kimg = new Image();
var dimg = new Image();
var platformW = [300, 100, 180, 260, 260, 100, 100];
var platformX = [40, 220, 320, 580, 700, 760, 760];
var platformY = [460, 380, 300, 250, 550, 350, 450];
document.onkeydown=handleKeyDown;
document.onkeyup=handleKeyUp;
function init(){
canvas = document.getElementById("canvas");
stage = new createjs.Stage(canvas);
bgimg.onload = this.handleImageLoad;
bgimg.src = "img/scene.jpg";
kimg.onload = this.handleImageLoad;
kimg.src="img/key.png";
dimg.onload = this.handleImageLoad;
dimg.src = "img/door.jpg";
img.onload = this.handleImageLoad;
img.src = "img/hero.png";
}
function handleImageLoad(event) {
loaded+=1;
if (loaded==4){
start();
}
}
function handleKeyDown(e) {
if(!e){ var e = window.event; }
switch(e.keycode) {
case KEYCODE_LEFT: lfHeld = true;
dir="left"; break;
case KEYCODE_RIGHT: rtHeld = true;
dir="right"; break;
case KEYCODE_SPACE: jump(); break;
}
}
function handleKeyUp(e) {
if(!e){ var e = window.event; }
switch(e.keycode) {
case KEYCODE_LEFT: lfHeld = false;
keyDn=false; hero.gotoAndStop("idle_h"); break;
case KEYCODE_RIGHT: rtHeld = false;
keyDn=false; hero.gotoAndStop("idle"); break;
}
}
function start(){
var bg = new createjs.Bitmap(bgimg);
stage.addChild(bg);
door = new createjs.Bitmap(dimg);
door.x = 131;
door.y = 384;
stage.addChild(door);
hero = new Hero(img);
hero.x = 80;
hero.y = 450;
stage.addChild(Hero);
crates = new Array();
paltforms = new Array();
for(i=0; i < platformW.length; i++){
var platform = new Platform(platformW[i],20);
platforms.push(platform);
stage.addChild(platform);
platform.x = platformX[i];
platform.y = platformY[i];
}
for(j=0; j < 5; j++){
var crate = new Crate();
crates.push(crate);
stage.addChild(crate);
resetCrates(crate);
}
key = new createjs.Bitmap(kimg);
key.x = 900;
key.y = 490;
stage.addChild(key);
Ticker.setFPS(30);
Ticker.addListener(window);
stage.update();
}
function tick() {
heroCenter = hero.y-40;
if (play){
vy+=gravity;
if (inAir){
hero.y+=vy;
}
if (vy>15){
vy=15;
}
for(i=0; i < platforms.length; i++){
if (hero.y >= platforms[i].y && hero.y<=(platforms[i].y+platforms[i].height) && hero.x>
platforms[i].x && hero.x<(platforms[i].
x+platforms[i].width)){;
hero.y=platforms[i].y;
vy=0;
jumping = false;
inAir = false;
break;
}else{
inAir = true;
}
}
for(j=0; j < crates.length; j++){
var ct = crates[j];
ct.y+=ct.speed;
ct.rotation+=3;
if (ct.y>650){
resetCrates(ct);
}
if (collisionHero (ct.x, ct.y, 20)){
gameOver();}
}
if (collisionHero (key.x+20, key.y+20,
20)){
key.visible=false;
door.visible=false;
}
if (collisionHero (door.x+20, door.y+40,
20) && key.visible==false){nextLevel();}
if (lfHeld){vx = -5;}
if (rtHeld){vx = 5;}
if(lfHeld && keyDn==false && inAir==false)
{
hero.gotoAndPlay("walk_h");
keyDn=true;
}
if(rtHeld && keyDn==false &&
inAir==false){
hero.gotoAndPlay("walk");
keyDn=true;
}
if (dir=="left" && keyDn==false &&
inAir==false){
hero.gotoAndStop("idle_h");
}
if (dir=="right" && keyDn==false &&
inAir==false){
hero.gotoAndStop("idle");
}
hero.x+=vx;
vx=vx*0.5;
if (hero.y>610){
gameOver();
}
}
stage.update();
}
function end(){
play=false;
var l = crates.length;
for (var i=0; i<l; i++){
var c = crates[i];
resetCrates(c);
}
hero.visible=false;
stage.update();
}
function nextLevel(){
gameTxt = new createjs.Text("Well Done\n\n",
"36px Arial", "#000");
gameTxt.text += "Prepare for Level 2";
gameTxt.textAlign = "center";
gameTxt.x = canvas.width / 2;
gameTxt.y = canvas.height / 4;
stage.addChild(gameTxt);
end();
}
function gameOver(){
gameTxt = new createjs.Text("Game Over\n\n",
"36px Arial", "#000");
gameTxt.text += "Click to Play Again.";
gameTxt.textAlign = "center";
gameTxt.x = canvas.width / 2;
gameTxt.y = canvas.height / 4;
stage.addChild(gameTxt);
end();
canvas.onclick = handleClick;
}
function handleClick() {
canvas.onclick = null;
hero.visible=true;
hero.x = 80;
hero.y = 450;
door.visible=true;
key.visible=true;
stage.removeChild(gameTxt);
play=true;
}
function collisionHero (xPos, yPos,
Radius){
var distX = xPos - hero.x;
var distY = yPos - heroCenter;
var distR = Radius + 20;
if (distX * distX + distY * distY <=
distR * distR){
return true;
}
}
function jump(){
if (jumping == false && inAir == false){
if (dir=="right"){
hero.gotoAndStop("jump");
}else{
hero.gotoAndStop("jump_h");
}
hero.y -=20;
vy = -25;
jumping = true;
keyDn=false;
}
}
function resetCrates(crt) {
crt.x = canvas.width * Math.random()|0;
crt.y = 0 - Math.random()*500;
crt.speed = (Math.random()*5)+8;
}
</script>
<title>Game</title>
</head>
<body onload="init();">
<canvas id="canvas" width="960px" height="600px"></canvas>
</body>
</html>
Adding the js files as listed in the header.
Platform.js:
(function(window) {
function Platform(w,h) {
this.width = w;
this.height = h;
this.initialize();
}
Platform.prototype = new createjs.Container ();
Platform.prototype.platformBody = null;
Platform.prototype.Container_initialize = Platform.prototype.initialize;
Platform.prototype.initialize = function() {
this.Container_initialize();
this.platformBody = new createjs.Shape();
this.addChild(this.platformBody);
this.makeShape();
}
Platform.prototype.makeShape = function() {
var g = this.platformBody.graphics;
g.drawRect(0,0,this.width,this.height);
}
window.Platform = Platform;
}(window));
Hero.js
(function(window) {
function Hero(imgHero) {
this.initialize(imgHero);
}
Hero.prototype = new createjs.BitmapAnimation();
Hero.prototype.Animation_initialize = Hero.prototype.initialize;
Hero.prototype.initialize = function(imgHero) {
var spriteSheet = new createjs.SpriteSheet({
images: [imgHero],
frames: {width: 60, height: 85, regX: 29, regY: 80}, animations: {
walk: [0, 19, "walk"],
idle: [20, 20],
jump: [21, 21] } });
SpriteSheetUtils
.addFlippedFrames(spriteSheet, true, false,
false);
this.Animation_initialize(spriteSheet);
this.gotoAndStop("idle");
}
window.Hero = Hero;
}(window));
Crate.js
(function(window) {
function Crate() {
this.initialize();
}
Crate.prototype = new createjs.Container();
Crate.prototype.img = new Image();
Crate.prototype.Container_initialize =
Crate.prototype.initialize;
Crate.prototype.initialize = function() {
this.Container_initialize();
var bmp = new createjs.Bitmap("img/crate.jpg");
bmp.x=-20;
bmp.y=-20;
this.addChild(bmp);}
window.Crate = Crate;
}(window));
I noticed that you try to initialize the EaselJS-objects without a namespace:
stage = new Stage(canvas);
But since 0.5.0 you have to use the createjs-namespace(or map the namespace to window before you do anything)
So what you would have to do now will ALL easelJS-classes is to add a createjs. before them when you are creating a new instance like this:
stage = new createjs.Stage(canvas);
Not sure if that's everything, but it's a start, hope this helps.
You can read more on CreateJS namepsacing here: https://github.com/CreateJS/EaselJS/blob/master/README_CREATEJS_NAMESPACE.txt

Requestanimationframe usage issue

I got the following RequestAnimationframe function from http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
I am trying to use it. But not sure how to call it and use it. Can someone give me a simple example. I am new to this html5 animation thing so you can understand..
I will really appreciate any help! The function is below..
(function() {
var lastTime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
window.cancelRequestAnimationFrame = window[vendors[x]+
'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() { callback(currTime + timeToCall); },
timeToCall);
lastTime = currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}())
Just paste that code into your JS or in its own file and put this inside of your rendering function at the very bottom.
requestAnimationFrame(yourrenderingfunction);
Live Demo
// requestAnimationFrame shim
(function() {
var lastTime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
window.cancelRequestAnimationFrame = window[vendors[x]+
'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() { callback(currTime + timeToCall); },
timeToCall);
lastTime = currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}())
// Sprite unimportant, just for example purpose
function Sprite(){
this.x = 0;
this.y = 50;
}
Sprite.prototype.draw = function(){
ctx.fillStyle = "rgb(255,0,0)";
ctx.fillRect(this.x, this.y, 10, 10);
}
// setup
var canvas = document.getElementsByTagName("canvas")[0],
ctx = canvas.getContext("2d");
canvas.width = 200;
canvas.height = 200;
//init the sprite
var sprite = new Sprite();
// draw the sprite and update it using request animation frame.
function update(){
ctx.clearRect(0,0,200,200);
sprite.x+=0.5;
if(sprite.x>200){
sprite.x = 0;
}
sprite.draw();
// makes it update everytime
requestAnimationFrame(update);
}
// initially calls the update function to get it started
update();

AS3 proportionally scaling external image

Currently I am using a for loop to dynamically load XML images and place them in a grid as thumbnails. I have the arrangement set and all the data is loading smoothly, but now I need to make the images scale to small 100px x 100px thumbs in small container movieclips. My code is as follows.
import gs.*;
import gs.easing.*;
var bttnHeight:Number = 20;
var select:Number = 0;
var xmlLoader:URLLoader = new URLLoader();
xmlLoader.addEventListener(Event.COMPLETE, showXML);
xmlLoader.load(new URLRequest("testxml.xml"));
var list_mc:Array = new Array();
function showXML(e:Event):void {
XML.ignoreWhitespace = true;
var nodes:XML = new XML(e.target.data);
var gallcount = nodes.gallery.length();
var list_mc = new listitem();
//Generate menu to select gallery
function populateMenu():void {
var spacing:Number = 0;
for (var i=0; i<gallcount; i++) {
list_mc[i] = new listitem();
list_mc[i].name = "li" + i;
list_mc[i].y = i*bttnHeight;
list_mc[i].gallname.text = nodes.gallery[i].attributes();
menu_mc.addChild(list_mc[i]);
list_mc[i].addEventListener(MouseEvent.ROLL_OVER, rollover);
list_mc[i].addEventListener(MouseEvent.ROLL_OUT, rollout);
list_mc[i].buttonMode = true;
list_mc[i].mouseChildren = false;
}
menu_mc.mask = mask_mc;
}
//list_mc.mask(mask_mc);
var boundryWidth = mask_mc.width;
var boundryHeight = mask_mc.height;
var diff:Number = 0;
var destY:Number = 0;
var ratio:Number = 0;
var buffer:Number = bttnHeight*2;
function findDest(e:MouseEvent):void {
if (mouseX>0 && mouseX<(boundryWidth)) {
if (mouseY >0 && mouseY<(boundryHeight)) {
ratio = mouseY/boundryHeight;
diff = menu_mc.height-boundryHeight+buffer;
destY = Math.floor(-ratio*diff)+buffer/2;
}
}
}
var tween:Number = 5;
//This creats the scroll easing
function moveMenu() {
if (menu_mc.height>boundryHeight) {
menu_mc.y += (destY-menu_mc.y)/tween;
if (menu_mc.y>0) {
menu_mc.y = 0;
} else if (menu_mc.y<(boundryHeight-menu_mc.height)) {
menu_mc.y = boundryHeight-menu_mc.height;
}
}
}
function rollover(e:Event):void {
TweenLite.to(e.currentTarget.li_bg, .4, {tint:0x334499});
}
function rollout(e:Event):void {
TweenLite.to(e.currentTarget.li_bg, .4, {removeTint:true});
}
stage.addEventListener(MouseEvent.MOUSE_MOVE, findDest);
stage.addEventListener(Event.ENTER_FRAME, moveMenu);
populateMenu();
select = 0;
//Generate thumbnails
function genThumb():void {
var photos = nodes.gallery[select].photo;
var thumbframe:Array = new Array();
var row = 0;
var column = 0;
var loaderArray:Array = new Array();
for (var i=0; i<photos.length(); i++) {
thumbframe[i] = new Sprite;
thumbframe[i].graphics.beginFill(0x0000FF);
thumbframe[i].graphics.drawRect(0,0,100,100);
thumbframe[i].graphics.endFill();
thumbframe[i].y = row;
thumbframe[i].x = column;
loaderArray[i] = new Loader();
loaderArray[i].load(new URLRequest(photos[i].text()));
trace(loaderArray[i].height);
var index = i+1;
container_mc.addChild(thumbframe[i]);
if (index%5 == 0) {
row=row+120;
column = 0;
} else {
column=column+120;
}
thumbframe[i].addChild(loaderArray[i]);
}
}
genThumb();
}
Both the loaders and the containers are in respective arrays. The images load correctly, but I am at a loss for how to scale them (ultimately I'd like to integrate a tween to animate as they load as well if possible.)
Thanks in advance for any aid!
You look like you need to scale your bitmaps into a 100x100 square. You'll need to wait until the loader has completed loading to do that because until then you won't know what the dimensions of the item are.
When you create your loader, add an event listener, like this:
loaderArray[i].contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete);
and then add this function:
function onLoadComplete(event:Event):void
{
var info:LoaderInfo = LoaderInfo(event.currentTarget);
info.removeEventListener(Event.COMPLETE);
var loader:Loader = info.loader;
var scaleWidth:Number = 100 / loader.width;
var scaleHeight:Number = 100 / loader.height;
if (scaleWidth < scaleHeight)
loader.scaleX = loader.scaleY = scaleWidth;
else
loader.scaleX = loader.scaleY = scaleHeight;
}
This may be a bit complicated, but all it really does is clean up the event listener that you had added, and find the dimensions of the loader (which it can get now because it's finished loading), and scale the loader appropriately.
If you need it to be centered within your thumbnail, add this to the bottom of the onLoadComplete method:
loader.x = (100 - loader.width) * 0.5;
loader.y = (100 - loader.height) * 0.5;
or you need it to take up the whole thumbnail and cut off the edges, change it to this (the inequality is the other-way around)
if (scaleWidth > scaleHeight)
loader.scaleX = loader.scaleY = scaleWidth;
else
loader.scaleX = loader.scaleY = scaleHeight;
and add this:
var shape:Shape = new Shape();
var g:Graphics = shape.graphics;
g.beginFill(0x00FF00);
g.drawRect(0, 0, 100, 100);
g.endFill();
loader.mask = g;
I haven't tested this, so there may be a few glitches, but hopefully it gives you the right idea.