I want to create an html5 game which contains multiple sprites.
For different elements I want to create an fixed fps.
For example:
Walk - 10 fps, so 10 sprites will be shown within 1 second
Run - 15 fps
Attack - 3 fps
How can I create this with requestAnimationFrame and not using set timeout or setinterval.
You can use the timestamp feature of requestAnimationFrame to trigger animations at different desired frames-per-second
function animate(timestamp){
// timestamp is a representation of the current elapsed time
}
The method is to set individual times when you want each action to be executed:
WalkTriggerTime = timest + 1000/desiredFPS;
Then do the action when the requestAnimationFrame timestamp exceeds this trigger time
if( timestamp > WalkTriggerTime ){
// execute a walk
// and reset the trigger timer
WalkTriggerTime = timest + 1000/desiredFPS;
}
Example Code and a Demo: http://jsfiddle.net/m1erickson/D6SU8/
<!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");
var animations=[]
var fps03={x:20,y:20,fps:03,frameCount:0,triggerTime:null,}
var fps10={x:20,y:40,fps:10,frameCount:0,triggerTime:null,}
var fps15={x:20,y:60,fps:15,frameCount:0,triggerTime:null,}
var stopAnimation=false;
animations.push(fps03,fps10,fps15);
for(var i=0;i<animations.length;i++){
var a=animations[i];
ctx.fillText(a.fps,a.x,a.y)
}
requestAnimationFrame(animate);
function animate(t){
if(!stopAnimation){requestAnimationFrame(animate);}
for(var i=0;i<animations.length;i++){
var a=animations[i];
if(!a.triggerTime){a.triggerTime=t+1000/a.fps;}
if(t>a.triggerTime){
a.triggerTime=t+1000/a.fps;
a.frameCount++;
ctx.clearRect(a.x+20,a.y-15,19,20)
ctx.fillText(a.frameCount,a.x+20,a.y)
ctx.fillRect(a.x+40,a.y-10,a.frameCount,15);
if(a.x+40+a.frameCount>canvas.width-20){stopAnimation=true;}
}
}
}
}); // end $(function(){});
</script>
</head>
<body>
<h4>Using the timestamp feature of RAF to control fps</h4>
<h4>Left#:fps, Mid#:Execution Count</h4>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
Related
I have been looking for a solution for this for a long time and I just could not find what I was looking for. I have made a code that is an automatic traffic light and it loops through. How can I change it so when I click it goes through the sequence and stops when it gets back to Red?
<!DOCTYPE html>
<html>
<head>
<title>Demo</title>
</head>
<body onload="startTime();">
<img id="img1" />
<script>
var imgArray = new Array("Red.jpg","RedA.jpg","Green.jpg","Amber.jpg");
var imgCount = 0;
function startTime() {
if(imgCount == imgArray.length) {
imgCount = 0;
}
document.getElementById("img1").src = imgArray[imgCount];
imgCount++;
setTimeout("startTime()", 1000);
}
</script>
</body>
</body>
</html>
You just need to change setTimeout function syntax.
setTimeout(function(){
startTime();
},1000);
Check working example
I want to be able to create diagrams and drawings on the fly, using input from the user.
If I have 2 text boxes for width and height, i want to be able to draw a rectangle based on user entered values, if they change the value in the input fields i want the drawing to change.
is canvas capable of this? does it need to work along with javascript?
thanks
Yes, you can listen for text-inputs and issue appropriate canvas drawing commands.
All canvas commands must be issued in javascript...so yes, javascript is required.
Here's annotated code and a Demo: http://jsfiddle.net/m1erickson/f6E6Y/
<!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(){
// get a reference to the canvas and context
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
// vars for current width and height of a canvas rectangle
var width=50;
var height=35;
// references to the input-text elements
// used to let user change the rect width & height
var $width=document.getElementById('width');
var $height=document.getElementById('height')
// set the initial input-text values to the width/height vars
$width.value=width;
$height.value=height;
// call the draw command
draw();
// listen for keyup events on width & height input-text elements
// Get the current values from input-text & set the width/height vars
// call draw to redraw the rect with the current width/height values
$width.addEventListener("keyup", function(){
width=this.value;
draw();
}, false);
$height.addEventListener("keyup", function(){
height=this.value;
draw();
}, false);
// draw() clears the canvas and redraws the rect
// based on user input
function draw(){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillRect(40,40,width,height);
}
}); // end $(function(){});
</script>
</head>
<body>
Width:<input type="text" id="width"><br>
height:<input type="text" id="height"><br>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
I need to set up a background canvas with a load of images drawn on at various places. Nothing changes on this background, so I want to do it all at once. I think I know how to do that. Then each frame I want to copy that background canvas (ultimately just a part of it) to my main screen canvas people see.
I am doing the following:
g_CanvasScreen = document.getElementById("m_Canvas");
g_CanvasScreenContext = g_CanvasScreen.getContext("2d");
g_OffScreenBackground = document.createElement("canvas");
g_OffScreenBackgroundContext = g_CanvasScreen.getContext("2d");
I believe this gets the main screen canvas from the hmtl5 page g_CanvasScreen.
I believe g_OffScreenBackground is a newly created canvas in memory.
Once all images have loaded I then draw all the images in the correct places to the background screen by calling the function:
DrawMapToBackground(g_OffScreenBackground, g_OffScreenBackgroundContext, 2000, 1600);
2000 x 1600 is the size of the offscreen background.
This then leads to the thing I am not sure about. I believe this will blit the background canvas to the main screen:
g_CanvasScreenContext.drawImage(g_OffScreenBackground,
0, 0, g_OffScreenBackground.width, g_OffScreenBackground.height,
screenX, screenY, g_OffScreenBackground.width, g_OffScreenBackground.height);
Is this last function correct? Can I do a canvas to canvas blit? Should I be doing this another way?
Instead of redrawing the background each time, just put 2 canvas’s on top of each other.
First draw the background image once on the bottom canvas.
Then use the top canvas to draw all your “changing” drawings.
Here’s code and a Fiddle: http://jsfiddle.net/m1erickson/pSjEt/
<!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>
#container{
position:relative;
border:1px solid blue;
width:500px;
height:300px;
}
.subcanvs{
position:absolute;
width:100%;
height:100%;
}
</style>
<script>
$(function(){
var bk=document.getElementById("background");
var bkCtx=bk.getContext("2d");
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var bkimg=new Image();
bkimg.onload=function(){
bk.width=bkimg.width;
bk.height=bkimg.height;
canvas.width=bkimg.width;
canvas.height=bkimg.height;
bkCtx.drawImage(bkimg,0,0);
draw();
}
bkimg.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/skyGrass.png";
var x=50;
function draw(){
x+=5;
if(x>300){x=50;}
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.beginPath();
ctx.arc(x,100,30,0,Math.PI*2,false);
ctx.strokeStyle="gold";
ctx.fillStyle="yellow";
ctx.lineWidth=5;
ctx.stroke();
ctx.fill();
setTimeout(draw,1000);
}
}); // end $(function(){});
</script>
</head>
<body>
<div id="container">
<canvas id="background" class="subcanvs"></canvas>
<canvas id="canvas" class="subcanvs"></canvas>
</div>
</body>
</html>
I was working on a solution based on
http://www.giscloud.com/sandbox/jsapi/html5/?mid=11695
On line 15, you can see the import (multi-line for easy reading)
<script type="text/javascript"
src="http://maps.google.com/maps/api/js?sensor=false">
</script>
Which in the last week started loading v3.10 (release) instead of v3.9 (now frozen).
The problem as you can see from the page is that the canvases are now loaded in the "MapPane" layer well below the other 6 layers (Ref: MapPanes). That layer is not interactive.
Has anyone come across such an issue, or better yet, is using the very solution in the link - and has upgraded it for v3.10?
JS Fiddle
doesn't work (v3.10)
works (v3.9)
More info
In v3.9, the map panes are laid out as
<div .. (parent)
<div .. z-index:100.. > --- << changed to 150
<div .. z-index:101.. >
<div .. z-index:102.. >
<div .. z-index:103.. >
<div .. z-index:104.. >
<div .. z-index:105.. >
<div .. z-index:106.. >
The code in the solution manipulates the z-index of the first pane ("MapPane"), which goes against the API's intentions...
el.map.getDiv().firstChild.firstChild.firstChild.firstChild.style.zIndex=150
My custom solution sets it to 104 instead, as I make use of the overlayMouseTarget (105) and floatPane (106) layers which need to go above it.
In v3.10, they have been rearranged as follows (you can make out the z-indexes 100-106):
<div .. (parent)
<div .. z-index:200.. >
<div .. z-index:101.. >
<div .. z-index:201.. >
<div .. z-index:102.. >
<div .. z-index:103.. >
<div .. z-index:202.. >
<div .. z-index:104.. >
<div .. z-index:105.. >
<div .. z-index:106.. >
<div .. z-index:100.. >
< overlay tile divs > --<< the divs parenting the canvases in the solution
<canvas ... >
I am thinking that the proper "fix" is to get the tiles moved to the floatShadow MapPane, but does it provide the tiling benefits that an OverlayMapType does, which seems to underpin the solution?
Direct access to pane is not better way.
To get panes correctly, your code should like this:
var dummyLayer = new google.maps.OverlayView();
dummyLayer.onAdd = function() {
var panes = this.getPanes();
console.log(panes.mapPane);
panes.mapPane.style.zIndex = 500;
};
dummyLayer.onRemove = function() {};
dummyLayer.draw = function() {};
dummyLayer.setMap(map);
Ok, I post whole code of yours.
<!doctype html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
<title>GIS Cloud HTML5 Canvas Example</title>
<style>
body, html {
padding: 0;
margin: 0;
overflow: hidden;
}
</style>
<meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
<link href="http://code.google.com/apis/maps/documentation/javascript/examples/standard.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" src="http://api.giscloud.com/sandbox/html5c.js"></script>
<script type="text/javascript">
var map;
function initialize() {
map = new google.maps.Map(document.getElementById("map_canvas"));
map.setZoom(4);
map.setMapTypeId('terrain');
map.setCenter(new google.maps.LatLng(35.818521016151, -100.932382588817));
var dummyLayer = new google.maps.OverlayView();
dummyLayer.onAdd = function() {
var panes = this.getPanes();
console.log(panes.mapPane);
panes.mapPane.style.zIndex = 500;
};
dummyLayer.onRemove = function() {
};
dummyLayer.draw = function() {
};
dummyLayer.setMap(map);
var gcmap = new giscloud.Html5Map(11695, map);
map.overlayMapTypes.insertAt(0, gcmap);
map.overlayMapTypes.insertAt(0, 0);
}
</script>
</head>
<body onload="initialize()">
<div style="text-align:center"><h2>GIS Cloud HTML5 Canvas Example</h2><p>Showing interactive HTML5 vector map overlay hosted on GIS Cloud. The original project is here. </p></div> <div id="map_canvas" style="width: 70%; height: 75%;margin:auto"></div>
<br />
<center>requires HTML5 compatible browser - article & benchmark: rasters vs vectors</center>
</body>
</html>
I am trying to design a piece of rotating text on a website and need help on where to start and how to accomplish this. I want it to say "Our Business Is _ Your Business." and where the _ is i want it to rotate with different words such as "growing" , "building" , "helping" ect. I can code html and am familiar with javascript and jquery. I dont want to do it with flash. At this point i have basic code written for mock up.
<html>
<head>
<title>Rotating Text</title>
<style type="text/css">
body,td,th {
font-family: "Arial Black", Gadget, sans-serif;
font-size: 16px;
color: #00C;
}
</style>
</head>
<body>
<p><strong>Our Business Is Your Business!</strong></p>
</body>
</html>
Any help would be greatly appreciated.
You could accomplish this with jQuery easily, replace the area that you wish to replace with a span, and use jQuery to replace the contexts of that span with a random word from your array.
HTML:
<p><strong>Our Business Is <span id='test'>XXX</span> Your Business!</strong></p>
jQuery:
<script type='text/javascript'>
$(document).ready(function(){
//Sets your words into an array
var phrases =new Array("growing","building","helping");
//Selects a random one
var random = Math.floor(Math.random()*phrases.length);
//Sets your area to use that random word
$("#test").text(phrases[random]);
});
</script>
Working Demo
If you required a rotation, you could simply wrap that inside of a setInterval function:
jQuery:
function setRandomWord()
{
var phrases =new Array("growing","building","helping");
//Selects a random one
var random = Math.floor(Math.random()*phrases.length);
//Sets your area to use that random word
$("#test").text(phrases[random]);
}
//Your function will fire every 5 seconds...
setInterval(setRandomWord,5000);
Working Demo with Interval
Full Code for Copy Pasting:
<html>
<head>
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js' type='text/javascript'></script>
<script type='text/javascript'>
$(document).ready(function(){
function setRandomWord(){
var phrases =new Array("growing","building","helping");
$("#test").text(phrases[Math.floor(Math.random()*phrases.length)]);
}
setInterval(setRandomWord,3000);
});
</script>
</head>
<body>
<p><strong>Our Business Is <span id='test'>bettering</span> Your Business!</strong></p>
</body>
</html>
You can use setInterval example
var words = ['Growing', 'building'];
var index = 0;
function rotate() {
document.getElementById('text').innerHTML = "Our Business Is " + words[(index++)%(words.length)] + " Your Business!!";
}
setInterval(rotate, 2000);
You can create an array, populate it with the words you want, and then choose a random element of that array.
var words = new Array();
words[0] = "word 1";
words[1] = "word 2";
words[2] = "word 3";
words[3] = "words 4";
var randomnumber=Math.floor(Math.random()*4)
alert(words[randomnumber]);
where 4 dictates that the random number will fall between 0-3. To increase the range to, say, 100, simply change 4 to 101 instead