I'm making an HTML5 canvas game and I want to make a grid. The map is infinite, and I want there to be a grid on the ground. But whatever I do, the same gets slower and slower over time and just gets too laggy to play.
Here's my current draw grid function.
function drawGrid() {
for (x=0;x<=canvas.width;x+=80) {
ctx.moveTo(x, offset[0] % 80);
ctx.lineTo(x, canvas.height + offset[0] % 80);
}
for (y=0;y<=canvas.height;y+=80) {
ctx.moveTo(offset[1] % 80, y);
ctx.lineTo(canvas.width + offset[1] % 80, y);
}
ctx.stroke();
}
I Just don't exactly understand why it gets so laggy.
EDIT: The canvas is cleared every frame by drawing a rectangle over everything, and this function runs every frame
I also don't think it's a different part of my code, If I run it without this function it doesn't lag.
Related
I'm coding a game in the style of agar.io where I want to move the player to the direction relative to the mouse position.
This is how I check the mouse position, returning a Vector object;
let mouse_vector = new Vector();
canvas.onmousemove = function() {
mouse_vector = mouse(event);
}
function mouse(evt) {
mouse_vector = new Vector(evt.clientX - canvas.width/2, evt.clientY - canvas.height/2);
return mouse_vector;
}
The player is an object with an x and y coordinate to which I add the vector pointing towards the mouse. I have 1 canvas that represents the world and is hidden. The other canvas is my viewport, on which I draw the cropped world relative to the player position.
I'm using requestAnimationFrame here, but I tried using Interval as well.
function draw() {
player.x += mouse_vector.x * 0.005;
player.y += mouse_vector.y * 0.005;
canvasCtx.clearRect(0, 0, canvas.width, canvas.height);
canvasCtx.drawImage(game, player.x-canvas.width/2, player.y-canvas.height/2, canvas.width, canvas.height, 0, 0, canvas.width, canvas.height);
canvasCtx.arc(canvas.width/2, canvas.height/2, player.r, 0, 2*Math.PI);
canvasCtx.fill();
requestAnimationFrame(draw);
}
My issue is that the game starts stuttering over time. I would like it to be as smooth as at the start. I'm suspecting the issue is related to some kind of caching. I've noticed the game uses a lot of CPU power. Any ideas?
The issue I was having was that I was not using the beginPath() method when filling arcs. Seems that not reseting the previous draw builds up and causes performance loss over time.
canvasCtx.beginPath(); // addition
canvasCtx.arc(canvas.width/2, canvas.height/2, player.r, 0, 2*Math.PI);
canvasCtx.fill();
So at the end of the day, you'll be re-drawing the whole map every 16ms to get 60fps which is the target of requestAnimationFrame - so you'll not be escaping the CPU hogging problem, unless you do some optimisation about the drawing.
About the logic you are doing: it doesn't seem from this piece of code that there can be anything that could be building up or leaking memory, so I suggest pasting your code to a code-sharing site like codepen.io and sharing it with the community, we'd have more chance of debugging it.
This is my pseudocode:
when move button is pressed:
currentCirclePos = circleX;
moveTimer = setInterval(move, 10);
My move function looks like this:
var move = function() {
circleX += move a bit;
};
In some cases, the element does not move at all. For those situations, I have the following code :
while(Math.abs(circleX - currentCirclePos) < some distance away){
drawCircle(circleX, circleY);
circleX += gradual shift;
}
This does not change the position of my circle gradually but draws it abruptly some distance away. I don't understand why is that happening. Could anyone help me debug the issue? Let me know if I need to post more code.
This is my requestAnimationFrame code:
requestAnimationFrame(animate);
function animate(){
ctx.clearRect(0,0,cw,ch);
ctx.rect(0, 0, cw, ch);
ctx.fillStyle = 'white';
ctx.fill();
drawCircle(circleX, circleY);
requestAnimationFrame(animate);
}
UPDATE : The while loop was not inside the animation function but now it is. However, it did not make any difference at all.
The problem is that You're using setInterval instead of requestAnimationFrame - it's more reliable way to do this kind of operations on canvas.
Please check this tutorial - author solves this problem pretty straightforward on example.
Edit: Ran the code on a more powerful computer and the grid rendered correctly. Possible hardware limitation? Computer where the problem occurred was a Samsung series 3 Chromebook. I'm thinking it has to do with trying to draw too many lines at the same time. Will test later.
I'm trying to draw a grid onto a canvas using the lineTo() method. The lines draw properly in the beginning, but any line that is drawn completely past 2048 pixels either down or to the right doesn't show up. Line going from inside this point to past it still show up on the other side, just lines that only are only drawn past the point don't show up.
Here's my JavaScript:
function drawGrid() {
//data.tiles is the map stored as an array of arrays
//tilesize = 60
var bw = data.tiles[0].length * tilesize;
var bh = data.tiles.length * tilesize;
ctx.beginPath();
for (i = bw; i >= 0; i -= tilesize) {
ctx.moveTo(i, 0);
ctx.lineTo(i, bh);
}
for (i = bh; i >= 0; i -= tilesize) {
ctx.moveTo(0, i);
ctx.lineTo(bw,i);
}
ctx.strokeStyle = "black";
ctx.stroke();
}
I've checked the data.tiles variable, and it's reading the right number. Really have no idea what I messed up here.
HTML Canvas has a maximum render area depending on your browser & hardware.
once you exceed these limits well your done pretty much.
try pre-rendering or use multiple canvas' positioned with CSS.
If you can see images drawn beyond 2048 then there's no reason a lineTo wouldn't be drawn also.
In the code you calculate bw and bh in different ways. You might check if this is a problem. If not, we'll need to see more code.
// bw uses data.tiles[0]
var bw = data.tiles[0].length * tilesize;
// bh uses data.tiles with no subscript
var bh = data.tiles.length * tilesize;
Why is it need to use context.save and context.restore() in any Javascript that is drawing lines to a canvas?
this.context = this.canvas.getContext("2d");
I am certain that it has to do with this line of code this.canvas.getContext("2d"); and canvas was defined above.
this.canvas = document.getElementById(config.canvasId);
Code:
BarChart.prototype.drawGridlines = function(){
var context = this.context;
context.save();
context.strokeStyle = this.gridColor;
context.lineWidth = 2;
// draw y axis grid lines
for (var n = 0; n < this.numGridLines; n++) {
var y = (n * this.height / this.numGridLines) + this.y;
context.beginPath();
context.moveTo(this.x, y);
context.lineTo(this.x + this.width, y);
context.stroke();
}
context.restore();
};
context.save() saves the current state of the context (strokeStyle, lineWidth, etc...) then your code will change those values. At the end of your code you call context.restore() which will restore the previous values that your code has changed.
This way you don't need to manually restore everything you changed and your code will not affect other code on the page that has previously modified these values.
You don't. context.save and context.restore are often used for efficient texture translation and rotation, hence show up in many examples.
Save stores your position, angle and various other canvas states. Then you can move to the position/angle you want to draw your image. Restore can then snap your co-ord grid back to the save point. Much easier than rotating points in space mathematically, and the only way to rotate images i know of with canvas 2d context mode.
If your doing simple drawing of boxes, lines or unrotated images then don't bother.
For a personal project, I'm tyring to make a timer application (for controlling Poker blind schedules). I know there are several solutions already on the market, but for reasons which are too lengthy to go into here, we need a bespoke system. Although the output template of the system will ultimately be definable by the end user, we would like to include a widget which shows a circle that gets animated as the time counts down. Here's an illustration of a working example, showing the yellow circle and what we'd like to achieve (or something similar, anyway):
My question is, how would one code the animation as shown below using either jQuery or raw HTML5 / CSS3 animations? This is for a web application using jQuery, so there are no other library options I can use.
Advanced thanks!
If you can use HTML5, canvas is probably your best bet. Mozilla has some decent tutorials on drawing arcs. This should be enough to get you started.
var canvas = document.getElementById('canvasid'),
width = canvas.width,
height = canvas.height,
ctx = canvas.getContext('2d');
function drawTimer(deg) {
var x = width / 2, // center x
y = height / 2, // center y
radius = 100,
startAngle = 0,
endAngle = deg * (Math.PI/180),
counterClockwise = true;
ctx.clearRect(0, 0, height, width);
ctx.save();
ctx.fillStyle = '#fe6';
// Set circle orientation
ctx.translate(x, y);
ctx.rotate(-90 * Math.PI/180);
ctx.beginPath();
ctx.arc(0, 0, radius, startAngle, endAngle, counterClockwise);
ctx.lineTo(0, 0);
ctx.fill();
}
setInterval(function() {
// Determine the amount of time elapsed; converted to degrees
var deg = (elapsedTime / totalTime) * 360;
drawTimer(deg);
}, 1000);
You can achieve this with CSS3 and jQuery.
Check out my example here http://blakek.us/css3-pie-graph-timer-with-jquery/ which with slight modification you could make the timer look how you want it.
In HTML5 you can draw in a canvas.
For example:
// Create the yellow face
context.strokeStyle = "#000000";
context.fillStyle = "#FFFF00";
context.beginPath();
context.arc(100,100,50,0,Math.PI*2,true);
context.closePath();
context.stroke();
context.fill();
Link
You should really check out Processing!
Especially Processing.js. There have been some interesting things made with it for iPhone
First solution i can think of is html5 canvas implementation. From the example above it becomes clear we're talking mobile, so what support does canvas get around mobile browsers i can't tell. developer.mozilla.org provides sufficient documentation. Using canvas to achieve such count down should be pretty simple task. Good luck.
HTML5 Canvas arc command (MDN) is probably what you're looking for. Just decrease the end angle over time to have your timer decrease.