Reputation: 1
I've been working on developing a video game and have recently been working on incorporating touchscreen capabilities into the program. However, I noticed that the touch event tends to cause movement in the canvas to freeze.
Here is some code that I wrote up to demonstrate this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<canvas id="cnvs" width="400" height="400"></canvas>
<script>
var canvas, canvasContext;
var x = 0, y = 30;
var incrementor = 1;
window.onload = function() {
canvas = document.getElementById('cnvs');
canvasContext = canvas.getContext('2d');
colorRect(0, 0, canvas.width, canvas.height, 'white');
setInterval(updateAll, 1);
canvas.addEventListener('touchstart', touchStart);
canvas.addEventListener('touchend', touchEnd);
}
function touchStart(e) {
console.log(e);
}
function touchEnd(e) {
console.log(e);
}
function colorRect(p,a,i,n,t) {
canvasContext.fillStyle = t;
canvasContext.fillRect(p,a,i,n);
}
function updateAll() {
moveAll();
drawAll();
}
function moveAll() {
x += incrementor;
if(x > canvas.width - 20 || x < 0) {
incrementor = incrementor * -1;
}
}
function drawAll() {
colorRect(0, 0, canvas.width, canvas.height, 'black');
colorRect(x, y, 20, 20, 'red');
}
</script>
</body>
</html>
Notice that when you touch the canvas using a device with a touchscreen that the program seems to "stutter" a little bit. It's not necessarily that there are errors that appear. In fact, the program runs through without any errors. The only "bug" that appears is that movement on the canvas tends to freeze when the touch event is called.
The main question I have is this: how to I write a program similar to this one that performs the exact same tasks, but without freezing the program in the process? I do not have any experience with jQuery or any other fancy JS plugins, so a way to do it using plain JavaScript would be helpful to my cause.
Upvotes: -3
Views: 62
Reputation: 1146
You're probably having issues with overworking the processor.
JavaScript has a very useful method to achieve better rendering performance, which is the Window
method requestAnimationFrame(updateAll)
. It's like setInterval
but the callback runs once every frame the browser renders its contents.
By convention, browsers render their content at the rate of 60fps, which can or not be configurable.
But your code is using setInterval(updateAll, 1)
which causes your code to render the image a thousand times each second while the browser will render it only 60 times of those. You're rendering the image 940 times more than needed.
Note that this is also basing the measurements in the framerate, which is bad, because if it is bigger (like 120fps), then everything will move faster instead of smoother (the game velocity should remain the same, based on time)...
As this latter issue is not related to the actual question, then I'm leaving that aside.
Also, it looks like logging the touch event is causing the browser to overwork...
Try your code with the snippet below:
var canvas, canvasContext;
var x = 0, y = 30;
var incrementor = 1;
// EDIT: Using this function to adjust the game velocity.
function speed(v) {
incrementor = v;
}
window.onload = function() {
canvas = document.getElementById('cnvs');
canvasContext = canvas.getContext('2d');
colorRect(0, 0, canvas.width, canvas.height, 'white');
canvas.addEventListener('touchstart', touchStart);
canvas.addEventListener('touchend', touchEnd);
// EDIT: Refresh the image with initial data.
updateAll();
}
function touchStart(e) {
// EDIT: Removed the logging.
//console.log(e);
}
function touchEnd(e) {
// EDIT: Removed the logging.
//console.log(e);
}
function colorRect(p,a,i,n,t) {
canvasContext.fillStyle = t;
canvasContext.fillRect(p,a,i,n);
}
function updateAll() {
moveAll();
drawAll();
// EDIT: Refresh the image on the next frame renderization.
requestAnimationFrame(updateAll);
}
function moveAll() {
x += incrementor;
if(x > canvas.width - 20 || x < 0) {
incrementor = incrementor * -1;
}
}
function drawAll() {
colorRect(0, 0, canvas.width, canvas.height, 'black');
colorRect(x, y, 20, 20, 'red');
}
<canvas id="cnvs" width="400" height="400"></canvas>
<div>
<button onclick="speed(1)">Speed 1</button>
<button onclick="speed(5)">Speed 5</button>
<button onclick="speed(10)">Speed 10</button>
</div>
Upvotes: 0