Glitchy Animation on Canvas - javascript

On my main bottom layer where the player moves and elevators move I use this frame rate:
var requestAnimFrame = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000/60);
};
When the player dies I use this frame rate for the explosion animation.
var requestAnimFrameExplode = function(callback) {
window.setTimeout(callback, 1000/15);
};
Now all this works fine, however on one of my levels I have elevators moving up and down etc that use the main bottom layer frame rate, but when the player dies the explosion frame rate players(makes things slower so you can see the animation for 1 sec) so this makes the elevators slow down for 1 sec and makes it look glitchy.
In my game Loop I have:
if(Death ==true)
{
requestAnimFrameExplode(Loop); //calls loop again but slower so animation explode shows
DrawSpawnAnimation(); //this draws the explode animation
}
else
{
requestAnimFrame(Loop); //when Death is false it calls at normal fast framerate for player movement etc
}
My question is how to stop this glitching? How can I Make the elevators and other thing sin the loop run the same time even if the animation is playing?

Here’s an animation illustration that uses both requestAnimationFrame and setTimeout.
It would be more performant to use RAF to drive both animations, but both are presented here for illustration purposes.
This RAF animation loop runs your elevator and looks like this:
var fps1 = 60;
function runElevator() {
setTimeout(function() {
// request another loop
raf1=requestAnimFrame(runElevator);
// update the elevator properties (current Y and directon)
elevatorY+=elevatorSpeed*elevatorDirection;
if(elevatorY+elevatorHeight>canvasB.height || elevatorY<30){
elevatorDirection= -elevatorDirection;
}
// call the function that draws the elevator frame
drawElevator(elevatorX,elevatorY,elevatorWidth,elevatorHeight)
}, 1000 / fps1);
}
The setTimeout animation loop runs your explosion and looks like this:
var fps2 = 30;
function runExplosion() {
// update the explosion properties (the current radius of the explosion)
explosionRadius+=1.5;
// check if the explosion is done
if(explosionRadius<explosionMaxRadius){
// the explosion is not done, draw another explosion frame
drawExplosion(explosionX,explosionY,explosionRadius);
// and request another loop
setTimeout(runExplosion, 1000/fps2);
}else{
// the explosion is done, clear the top canvas and “we’re outta here!”
ctxT.clearRect(0,0,canvasT.width,canvasT.width);
}
}
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/YzqUF/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; padding:20px;}
#container{position:relative;}
canvas{border:1px solid red; position:absolute; top:0; left:0}
</style>
<script>
$(function(){
var canvasT=document.getElementById("canvasTop");
var ctxT=canvasT.getContext("2d");
var canvasB=document.getElementById("canvasBottom");
var ctxB=canvasB.getContext("2d");
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
var elevatorX=30;
var elevatorY=30;
var elevatorWidth=40;
var elevatorHeight=60;
var elevatorSpeed=2;
var elevatorDirection=1;
ctxT.strokeStyle="orange";
var explosionX=100;
var explosionY=200;
var explosionStartingRadius=10;
var explosionEndingRadius=25;
var explosionRadius=explosionStartingRadius;
var raf1;
var raf2;
runElevator();
function explode(x,y,maxRadius){
explosionX=x;
explosionY=y;
explosionMaxRadius=maxRadius
explosionRadius=10;
ctxT.clearRect(0,0,canvasB.width,canvasB.height);
ctxT.beginPath();
ctxT.arc(x,y,explosionRadius,0,Math.PI*2,false)
ctxT.closePath();
ctxT.fillStyle="yellow"
ctxT.fill();
ctxT.stroke();
ctxT.fillStyle="orange";
runExplosion();
}
var fps1 = 60;
function runElevator() {
setTimeout(function() {
raf1=requestAnimFrame(runElevator);
elevatorY+=elevatorSpeed*elevatorDirection;
if(elevatorY+elevatorHeight>canvasB.height || elevatorY<30){
elevatorDirection= -elevatorDirection;
}
drawElevator(elevatorX,elevatorY,elevatorWidth,elevatorHeight)
}, 1000 / fps1);
}
var fps2 = 30;
function runExplosion() {
explosionRadius+=1.5;
if(explosionRadius<explosionMaxRadius){
drawExplosion(explosionX,explosionY,explosionRadius);
setTimeout(runExplosion, 1000/fps2);
}else{
ctxT.clearRect(0,0,canvasT.width,canvasT.width);
}
}
function drawElevator(x,y,width,height){
ctxB.clearRect(0,0,canvasB.width,canvasB.height);
ctxB.beginPath();
ctxB.moveTo(x+width/2,0);
ctxB.lineTo(x+width/2,y);
ctxB.rect(x,y,width,height);
ctxB.stroke();
ctxB.fill();
}
function drawExplosion(x,y,radius){
ctxT.beginPath();
ctxT.arc(x,y,radius,0,Math.PI*2,false);
ctxT.closePath()
ctxT.stroke();
}
$("#explode").click(function(){ explode(150,150,75); });
}); // end $(function(){});
</script>
</head>
<body>
<button id="explode">Explode</button>
<div id="container">
<canvas id="canvasTop" width=300 height=300></canvas>
<canvas id="canvasBottom" width=300 height=300></canvas>
</div>
</body>
</html>

It sounds like you're trying to control the speed of your animation by controlling the framerate. I recommend refactoring so that framerate is independent of animation speed.
In other words, don't slow down your explosion by lowering your framerate. You should slow it down by making the flames / debris move less between each frame.
That said, slowing the whole level down (elevators and all) when you die sounds like kind of a neat effect ;)

Related

Buggy canvas animation on click with JavaScript

I'm trying to run a simple animation each time when user clicks on canvas. I'm sure I did something wrong as the animation doesn't even fire at times. I have never used canvas animation before and have difficulty understanding how it should be constructed within a for loop.
fgCanvas.on('mousedown', function(e) {
var cX = Math.round((e.offsetX - m) / gS),
cY = Math.round((e.offsetY - m) / gS);
clickDot({x:cX,y:cY});
});
function clickDot(data) {
for (var i = 1; i < 100; i++) {
fctx.clearRect(0, 0, pW, pH);
fctx.beginPath();
fctx.arc(data.x * gS + m, data.y * gS + m, i/10, 0, Math.PI * 2);
fctx.strokeStyle = 'rgba(255,255,255,' + i/10 + ')';
fctx.stroke();
}
requestAnimationFrame(clickDot);
}
Full code is here: http://jsfiddle.net/3Nk4A/
The other question is how can slow down the animation or add some easing, so the rings are drawn slower towards the end when they disappear?
You can use requestAnimationFrame plus easing functions to create your desired effect:
A Demo: http://jsfiddle.net/m1erickson/cevGf/
requestAnimationFrame creates an animation loop by itself--so there's no need to use a for-loop inside requestAnimationFrame's animation loop.
In its simplest form, this requestAnimationFrame loop will animate your circle:
var counter=1;
animate();
function animate(){
// stop the animation after it has run 100 times
if(counter>100){return;}
// there's more animating to do, so request another loop
requestAnimationFrame(animate);
// calc the circle radius
var radius=counter/10;
// draw your circle
}
To get the animation to speed-up or slow-down, you can use easings. Easings change a value (like your radius) over time, but they change that value unevenly. Easings speed-up and slow-down over the duration of the animation.
Robert Penner made a great set of easing algorithms. Dan Rogers coded them in javascript:
https://github.com/danro/jquery-easing/blob/master/jquery.easing.js
You can see working examples of his easing functions here:
http://easings.net/
Here's annotated code using requestAnimationFrame plus easings to animate your circles.
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
// canvas related variables
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var $canvas=$("#canvas");
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var scrollX=$canvas.scrollLeft();
var scrollY=$canvas.scrollTop();
// set the context styles
ctx.lineWidth=1;
ctx.strokeStyle="gold";
ctx.fillStyle="#888";
// variables used to draw & animate the ring
var PI2=Math.PI*2;
var ringX,ringY,ringRadius,ingCounter,ringCounterVelocity;
// fill the canvas with a background color
ctx.fillRect(0,0,canvas.width,canvas.height);
// tell handleMouseDown to handle all mousedown events
$("#canvas").mousedown(function(e){handleMouseDown(e);});
// set the ring variables and start the animation
function ring(x,y){
ringX=x;
ringY=y;
ringRadius=0;
ringCounter=0;
ringCounterVelocity=4;
requestAnimationFrame(animate);
}
// the animation loop
function animate(){
// return if the animation is complete
if(ringCounter>200){return;}
// otherwise request another animation loop
requestAnimationFrame(animate);
// ringCounter<100 means the ring is expanding
// ringCounter>=100 means the ring is shrinking
if(ringCounter<100){
// expand the ring using easeInCubic easing
ringRadius=easeInCubic(ringCounter,0,15,100);
}else{
// shrink the ring using easeOutCubic easing
ringRadius=easeOutCubic(ringCounter-100,15,-15,100);
}
// draw the ring at the radius set using the easing functions
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.beginPath();
ctx.arc(ringX,ringY,ringRadius,0,PI2);
ctx.closePath();
ctx.stroke();
// increment the ringCounter for the next loop
ringCounter+=ringCounterVelocity;
}
// Robert Penner's easing functions coded by Dan Rogers
//
// https://github.com/danro/jquery-easing/blob/master/jquery.easing.js
//
// now=elapsed time,
// startValue=value at start of easing,
// deltaValue=amount the value will change during the easing,
// duration=total time for easing
function easeInCubic(now, startValue, deltaValue, duration) {
return deltaValue*(now/=duration)*now*now + startValue;
}
function easeOutCubic(now, startValue, deltaValue, duration) {
return deltaValue*((now=now/duration-1)*now*now + 1) + startValue;
}
// handle mousedown events
function handleMouseDown(e){
// tell the browser we'll handle this event
e.preventDefault();
e.stopPropagation();
// calc the mouse position
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// animate a ring at the mouse position
ring(mouseX,mouseY);
}
}); // end $(function(){});
</script>
</head>
<body>
<h4>Click in the canvas to draw animated circle with easings.</h4>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

Painting On A Canvas And Deleting It Automatically (HTML5)

Here's my objective. I want to literally paint on a canvas element then automatically erase it in a quick gradual manner. The similar implementation is somewhat like this: http://mario.ign.com/3D-era/super-mario-sunshine
I want to make it simple. I just simply want to paint and then erase the recently painted stroke. Where do I start? Is there a simple approach on painting on a canvas without using any kind of plugin? I am currently using wPaint.js and it's not really what I want. Is there a way of painting on a canvas and undoing without too much complex code?
Here is how to let the user draw a self-disappearing line:
Create a polyline by saving points to an array when the user drags the mouse.
In an animation loop, clear the screen and redraw that polyline.
But each loop, leave out the earliest points (making the earliest points “disappear”).
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/LT6Ln/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
ctx.lineCap = "round";
ctx.lineJoin = "round";
ctx.lineWidth=15;
var canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var isDown=false;
var points=[];
var minPoint=0;
var PI2=Math.PI*2
var radius=20;
var fps = 20;
var lastTime=0;
animate();
function animate() {
setTimeout(function() {
requestAnimFrame(animate);
// draw a polyline using the saved points array
// but start later in the array each animation loop
if(minPoint<points.length){
ctx.clearRect(0,0,canvas.width,canvas.height)
ctx.beginPath();
ctx.moveTo(points[minPoint].x,points[minPoint.y]);
for(var i=minPoint+1;i<points.length;i++){
var pt=points[i];
ctx.lineTo(pt.x,pt.y);
}
ctx.stroke();
minPoint++;
}
}, 1000 / fps);
}
function handleMouseDown(e){
isDown=true;
}
function handleMouseUp(e){
isDown=false;
}
function handleMouseOut(e){
isDown=false;
}
function handleMouseMove(e){
if(!isDown){return;}
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// accumulate points for the polyline but throttle
// the capture to prevent clustering of points
if(Date.now()-lastTime>20){
points.push({x:mouseX,y:mouseY});
lastTime=Date.now();
}
}
$("#canvas").mousedown(function(e){handleMouseDown(e);});
$("#canvas").mousemove(function(e){handleMouseMove(e);});
$("#canvas").mouseup(function(e){handleMouseUp(e);});
$("#canvas").mouseout(function(e){handleMouseOut(e);});
}); // end $(function(){});
</script>
</head>
<body>
<h3>Drag to create a self-clearing line.</h3>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
[ Update: Using complex effects instead of a simple line ]
Sure. You can use a spraypaint effect instead of a line.
However, this effect requires some expensive processing!
The spraypaint effect is often created by drawing multiple random 1x1 pixels around a centerpoint.
Assuming 10 droplets per “spray”, every point along your polyline requires:
10 X fillRect(x,y,1,1) draws on the canvas (instead of 1 X lineTo for the simple line).
20 X Math.random,
10 X Math.cos and
10 X Math.sin.
Here’s an example fiddle of a “spraypaint” effect: http://jsfiddle.net/m1erickson/zJ2ZR/
Keep in mind that all this processing must take place within the small time allowed by requestAnimationFrame (often 16-50 milliseconds per frame).
Doing the expensive spraypaint on each of 20-50 accumulated points along the polyline will likely not fit inside the time of an RAF frame.
To make spraypainting fit inside the time allowed by RAF, you will need to “cache” the effect:
Create 1 random “spray” in a 10px by 10px offscreen canvas.
Create an image from that canvas using canvas.toDataURL.
Add that image to an array.
Repeat step #1 maybe a dozen times (to get a good variety of random spray images)
Then instead of context.lineTo or spraypainting on-the-fly, just do this:
context.drawImage(myCachedSprays[nextSprayIndex],point.x,point.y);
Use Kinetic.js . Its is very easy to learn. By this you can add or remove any painted stroke very easly.
See the working of it from here : http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-batch-draw/

Making website elements align to a (small) grid

So I have an idea for a site design where the background is a grid of small (say 10px) color-shifting squares. Ideally, I'd like to have the elements on the page line up with this grid, however most of the guides for website grids revolve around the 960 grid system, which isn't small enough for my purposes.
Anyone have any suggestions for how to achieve this? Also, if anyone has any ideas for how to do the color-shifting grid thing, I'd definitely appreciate that as well!
Here's how to create a constantly changing, multi-colored grid
You can fill an 8x8 grid with rectangles (one at a time) like this:
var n=parseInt(Math.random()*64);
var r=parseInt(n/8);
var c=n-r*8;
ctx.fillStyle=randomColor();
ctx.fillRect(c*20,r*20,20,20);
You can generate a random color like this:
function randomColor(){
return("#"+Math.floor(Math.random()*16777215).toString(16));
}
Add an animation loop and you’re good to go!
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/n2ymp/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" />
<script src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
var fps = 30;
function animate() {
setTimeout(function() {
requestAnimFrame(animate);
// Drawing code goes here
var n=parseInt(Math.random()*64);
var r=parseInt(n/8);
var c=n-r*8;
ctx.fillStyle=randomColor();
ctx.fillRect(c*20,r*20,20,20);
}, 1000 / fps);
}
// create a random color object {red,green,blue}
function randomColor(){
return("#"+Math.floor(Math.random()*16777215).toString(16));
}
animate();
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=600 height=400></canvas>
</body>
</html>

Draw a (progressive) paint splash on a canvas

I'm looking for a simple method which can able me to draw in a canvas a paint splash like this on :
One method will be to fire a lot of small particles which will paint a little circle, but I don't want to manage a lot of particle objects.
EDIT : example here: jsfiddle.net/MK73j/4/
A second method will be to have few images and manipulate scale and rotation, but I want to have a good random on the effect.
A third method will be to make some random litte points, join them with bezier curves and fill the content, but I will have only a single mark.
Well I don't know if there is a better method to have an effect which looks like this image or if I have to choose on of the 3 I thought about.
You can use illusion to create a nice splat effect.
Since objects “grow” as they approach, you can animate an increasing size plus a little motion to create your splat effect.
You can use context.drawImage to handle the resizing:
context.drawImage(splashImg, 0 ,0, splashImg.width, splashImg.height,
newX, newY, newWidth, newHeight);
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/r8Grf/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
$("go").html("Loading...");
var count=80;
var win=new Image();
var splash;
win.onload=function(){
splash=new Image();
splash.onload=function(){
ctx.drawImage(win,0,0);
}
splash.src="http://dl.dropbox.com/u/139992952/splash2.svg";
}
win.src="http://dl.dropbox.com/u/139992952/window.png";
$("#go").click(function(){ count=80; animate(); });
function animate() {
// drawings
if(--count>1){
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.drawImage(win,0,0);
ctx.globalCompositeOperation = 'destination-over';
ctx.drawImage(splash,0,0,splash.width,splash.height,25,25,splash.width/count,splash.height/count);
ctx.restore();
}
// request new frame
requestAnimFrame(function() {
animate();
});
}
}); // end $(function(){});
</script>
</head>
<body>
<br/><button id="go">Splash!</button><br/><br/>
<canvas id="canvas" width=326 height=237></canvas>
</body>
</html>

JavaScript game loop playing catch up/blury/ghosted in chrome/browsers

I have been trying to set up a javascript game loop and I have two issues I am running into. I find that in chrome when I lose focus of the browser window and then click back the animation I have running does this weird "catch up" thing where it quickly runs through the frames it should of been rendering in the background. I also have noticed that the animation is blury when moving at the current speed I have it at yet other people have been able to get their canvas drawings to move quickly and still look crisp. I know their seems to be a lot out about this but I cant make sense of what my issue really is. I thought this was a recommended way to create a game loop.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Frame Test</title>
<link href="/css/bootstrap.css" media="all" rel="stylesheet" type="text/css" />
<script language="javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"
type="text/javascript">
</script>
<script language="javascript" src="js/jquery.hotkeys.js" type="text/javascript"></script>
<script language="javascript" src="js/key_status.js" type="text/javascript"></script>
<script language="javascript" src="js/util.js" type="text/javascript"></script>
<script language="javascript" src="js/sprite.js" type="text/javascript"></script>
</head>
<body>
<button id="button1">
Toggle Loop</button>
<h1 id="frameCount">
Game Loop Test</h1>
<canvas id="gameCanvas" width="800" height="500">
<p>Your browser doesn't support canvas.</p>
</canvas>
<script type='text/javascript'>
// demo code used for playing around with javascript-canvas animations
var frameCount = 0;
var drawingCanvas = document.getElementById('gameCanvas');
// Check the element is in the DOM and the browser supports canvas
if (drawingCanvas.getContext) {
var context = drawingCanvas.getContext('2d');
var x = 100;
var y = 100;
var right = true;
context.strokeStyle = "#000000";
context.fillStyle = "Green";
context.beginPath();
context.arc(x, y, 50, 0, Math.PI * 2, true);
context.closePath();
context.stroke();
context.fill();
}
function Timer(settings) {
this.settings = settings;
this.timer = null;
this.on = false; //Bool that represents if the timer is running or stoped
this.fps = settings.fps || 30; //Target frames per second value
this.interval = Math.floor(1000 / 30);
this.timeInit = null; //Initial time taken when start is called
return this;
}
Timer.prototype =
{
run: function () {
var $this = this;
this.settings.run();
this.timeInit += this.interval;
this.timer = setTimeout(
function () { $this.run() },
this.timeInit - (new Date).getTime()
);
},
start: function () {
if (this.timer == null) {
this.timeInit = (new Date).getTime();
this.run();
this.on = true;
}
},
stop: function () {
clearTimeout(this.timer);
this.timer = null;
this.on = false;
},
toggle: function () {
if (this.on) { this.stop(); }
else { this.start(); }
}
}
var timer = new Timer({
fps: 30,
run: function () {
//---------------------------------------------run game code here------------------------------------------------------
//Currently Chorme is playing a catch up game with the frames to be drawn when the user leaves the browser window and then returns
//A simple canvas animation is drawn here to try and figure out how to solve this issue. (Most likely related to the timer implimentation)
//Once figured out probably the only code in this loop should be something like
//updateGameLogic();
//updateGameCanvas();
frameCount++;
if (drawingCanvas.getContext) {
// Initaliase a 2-dimensional drawing context
//Canvas commands go here
context.clearRect((x - 52), 48, (x + 52), 104);
// Create the yellow face
context.strokeStyle = "#000000";
context.fillStyle = "Green";
context.beginPath();
if (right) {
x = x + 6;
if (x > 500)
right = false;
} else {
x = x - 6;
if (x < 100)
right = true;
}
context.arc(x, 100, 50, 0, Math.PI * 2, true);
context.closePath();
context.stroke();
context.fill();
}
document.getElementById("frameCount").innerHTML = frameCount;
//---------------------------------------------end of game loop--------------------------------------------------------
}
});
document.getElementById("button1").onclick = function () { timer.toggle(); };
frameCount++;
document.getElementById("frameCount").innerHTML = frameCount;
</script>
</body>
</html>
-------------Update ---------------------
I have used requestanimation frame and that has solved the frame rate problam but I still get weird ghosting/bluring when the animation is running. any idea how I should be drawing this thing?
Okay, so part of your problem is that when you switch tabs, Chrome throttles down its performance.
Basically, when you leave, Chrome slows all of the calculations on the page to 1 or 2 fps (battery-saver, and more performance for the current tab).
Using setTimeout in the way that you have is basically scheduling all of these calls, which sit and wait for the user to come back (or at most are only running at 1fps).
When the user comes back, you've got hundreds of these stacked calls, waiting to be handled, and because they've all been scheduled earlier, they've all passed their "wait" time, so they're all going to execute as fast as possible (fast-forward), until the stack is emptied to where you have to start waiting 32ms for the next call.
A solution to this is to stop the timer when someone leaves -- pause the game.
On some browsers which support canvas games in meaningful ways, there is also support for a PageVisibility API. You should look into it.
For other browsers, it'll be less simple, but you can tie to a blur event on the window for example.
Just be sure that when you restart, you also clear your interval for your updates.
Ultimately, I'd suggest moving over to `requestAnimationFrame, because it will intelligently handle frame rate, and also handle the throttling you see, due to the stacked calls, but your timer looks like a decent substitute for browsers which don't yet have it.
As for blurriness, that needs more insight.
Reasons off the top of my head, if you're talking about images, are either that your canvas' width/height are being set in CSS, somewhere, or your sprites aren't being used at a 1:1 scale from the image they're pulled from.
It can also come down to sub-pixel positioning of your images, or rotation.
Hope that helps a little.
...actually, after looking at your code again, try removing "width" and "height" from your canvas in HTML, and instead, change canvas.width = 800; canvas.height = 500; in JS, and see if that helps any.

Categories

Resources