naveedk
naveedk

Reputation: 161

Make shape keep moving in direction in canvas until changed direction

I have this code, but when I go left, right, up, or down, I can stop. I want to make it so it will keep going instead of me having to keep holding on the buttons. Look at the real version of snake to see what I'm talking about. I have already tried doing a while loop instead of and if statement, but that still didn't work. Please help if you can. Here's my code:

<!DOCTYPE html>
    <html>
    <head>
	    <title>Canvas</title>
    </head>
    <style>
	    #canvas {
		    outline:1px solid #000;
            background-color:black;
	    }
    </style>
    <body>
    <input style="display:none;" id="score" type="text" name="score" value="0">            
    <br>
    <h2 id="h">Score: 0</h2>
    <canvas id="canvas" height="410" width="400"></canvas>
    <script>
	    var box = 32;


	    function reset() {
		    location.reload();
	    }
	    var canvas = document.querySelector("#canvas");
	    var context = canvas.getContext('2d');

	    var xPos = 10;
	    var yPos = 10;
    
        var xPos2 = 90;
	    var yPos2 = 90;
    
        var c = document.getElementById("canvas");
        var ctx = c.getContext("2d");
	    ctx.fillStyle = "#1aff1a";
    	ctx.fillRect(xPos, yPos, 20, 20);
    
        var ctx2 = c.getContext("2d");
	    ctx2.fillStyle = "red";
	    ctx2.fillRect(xPos2, yPos2, 20, 20);

	    var d=0;
	    function move(e){

		

		    if(e.keyCode == 39){
			    d="right";
		    }
		    if(e.keyCode == 37){
			    d="left";
		    }
		    if(e.keyCode == 38){
			    d="up";
		    }
		    if(e.keyCode == 40){
			    d="down";
		    }

		    if(d=="right"){
			    xPos += 10;
		    }
		    if(d=="left"){
			    xPos -= 10;
		    }
		    if(d=="up"){
		    	yPos -= 10;
		    }
		    if(d=="down"){
			    yPos += 10;
		    }

		    if (xPos == xPos2 && yPos == yPos2){
			    score.value += "+";
			    score.value += "1";
			    score.value = eval(score.value);
			    document.getElementById('h').innerHTML="Score: "+score.value;
			    xPos2=Math.floor(Math.random() * 38) * 10;  
			    yPos2=Math.floor(Math.random() * 38) * 10;
		    } 

		    if (xPos < 0 || xPos > 380){
    		    alert('you lost');
    		    alert('your score: '+ score.value)
    		    document.getElementById('canvas').style.display = "none";
    	    }
    	    if (yPos > 390 || yPos < 0){
   			alert('you lost');
   			alert('your score: '+ score.value)
   			document.getElementById('canvas').style.display = "none";
   		    }

		    canvas.width=canvas.width;
		    ctx.fillStyle = "#1aff1a";
		    ctx.fillRect(xPos, yPos, 20, 20);
            ctx2.fillStyle = "red";
		    ctx2.fillRect(xPos2, yPos2 , 20, 20);
	    }
	    function again(){
		    if(d=="right"){
			    xPos += 10;
		    }
		    if(d=="left"){
			    xPos -= 10;
		    }
		    if(d=="up"){
			    yPos -= 10;
		    }
		    if(d=="down"){
			    yPos += 10;
		    }
	    }
	    function win() {
		    if (xPos == xPos2 && yPos == yPos2){
			    alert('you win')
		    } 
	    }
	    function while1(){
		    while(d!="right" && d!="up" && d!="down" && d=="left"){
			    xPos -= 10;
		    }
		    while(d=="right"){
			    xPos += 10;
		    }
		    while(d=="up"){
			    yPos -= 10;
		    }
		    while(d=="down"){
			    yPos += 10;
		    }
	    }
	    function block(){
		    document.getElementById('score').style.display = "block";
	    }
	    while1()
	    document.addEventListener("keydown", move);
    </script>
    <br><button style="width:200px; height:68px;" onclick="reset()">Reset</button>
    </body>
    </html>

Upvotes: 3

Views: 98

Answers (2)

Nikhil Kinkar
Nikhil Kinkar

Reputation: 781

to automate the movement of the green box (snake) you can use requestAnimationFrame, which takes the animation code that you want to iterate.

then you will need to save the previous keyCode, to update the movement direction.

for iterating the animation the code you put in move function need to be moved out in another function iterate which set the requestAnimationFrame, and when the move function is called again we need to cancelAnimationFrame, if you don't cancel animation frame, it will increase the animation frame speed every time move is called. bellow is the updated code that would solve you problem.

var box = 32;

function reset() {
  location.reload();
}
var canvas = document.querySelector("#canvas");
var context = canvas.getContext('2d');
var xPos = 10;
var yPos = 10;

var xPos2 = 10;
var yPos2 = 90;

var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "#1aff1a";
ctx.fillRect(xPos, yPos, 20, 20);

var ctx2 = c.getContext("2d");
ctx2.fillStyle = "red";
ctx2.fillRect(xPos2, yPos2, 20, 20);

var d = 0;
var hit;
var hitKey;
var animate;
var fps = 15;
var now;
var then = Date.now();
var interval = 1000 / fps;
var delta;

function move(e) {
  cancelAnimationFrame(animate);
  hitKey = e.keyCode;
  if (e.keyCode == 39) {
    d = "right";
  }
  if (e.keyCode == 37) {
    d = "left";
  }
  if (e.keyCode == 38) {
    d = "up";
  }
  if (e.keyCode == 40) {
    d = "down";
  }
  again();
  iterate();
}

function iterate() {
  animate = requestAnimationFrame(iterate);
  now = Date.now();
  delta = now - then;

  if (delta > interval) {
    then = now - (delta % interval);
    if (xPos == xPos2 && yPos == yPos2) {
      score.value += "+";
      score.value += "1";
      score.value = eval(score.value);
      document.getElementById('h').innerHTML = "Score: " + score.value;
      xPos2 = Math.floor(Math.random() * 38) * 10;
      yPos2 = Math.floor(Math.random() * 38) * 10;
    }

    if (xPos < 0 || xPos > 380) {
      cancelAnimationFrame(animate);
      alert('you lost');
      alert('your score: ' + score.value)
      document.getElementById('canvas').style.display = "none";
    }
    if (yPos > 390 || yPos < 0) {
      cancelAnimationFrame(animate);
      alert('you lost');
      alert('your score: ' + score.value)
      document.getElementById('canvas').style.display = "none";
    }

    if (hitKey != hit) {
      canvas.width = canvas.width;
      ctx.fillStyle = "#1aff1a";
      ctx.fillRect(xPos, yPos, 20, 20);
      ctx2.fillStyle = "red";
      ctx2.fillRect(xPos2, yPos2, 20, 20);
      again();
    }
  }
}

function again() {
  if (d == "right") {
    xPos += 10;
  }
  if (d == "left") {
    xPos -= 10;
  }
  if (d == "up") {
    yPos -= 10;
  }
  if (d == "down") {
    yPos += 10;
  }
}

function win() {
  if (xPos == xPos2 && yPos == yPos2) {
    alert('you win')
  }
}

function while1() {
  while (d != "right" && d != "up" && d != "down" && d == "left") {
    xPos -= 10;
  }
  while (d == "right") {
    xPos += 10;
  }
  while (d == "up") {
    yPos -= 10;
  }
  while (d == "down") {
    yPos += 10;
  }
}

function block() {
  document.getElementById('score').style.display = "block";
}
while1()
document.onkeypress = function(e) {
  hit = e.keyCode;
}
document.addEventListener("keydown", move);
#canvas {
  outline: 1px solid #000;
  background-color: black;
}
<!DOCTYPE html>
<html>

<body>
  <input style="display:none;" id="score" type="text" name="score" value="0">
  <br>
  <h2 id="h">Score: 0</h2>
  <canvas id="canvas" height="410" width="400"></canvas>
  <br><button style="width:200px; height:68px;" onclick="reset()">Reset</button>
</body>

</html>

you can increase/decrease the speed of movement by changing fps value.

Upvotes: 1

Mathieu Paturel
Mathieu Paturel

Reputation: 4500

The idea is to set a speed variable. When you press a key, you change this speed variable accordingly.

And every frame, with a call requestAnimationFrame, you move the character according to the speed variable.

const canvas = document.querySelector('#canvas')
const context = canvas.getContext('2d')

const width = parseInt(canvas.width)
const height = parseInt(canvas.height)

const size = [10, 10] // the size of our object (a rectangle)
let speed = [0, 0] // the speed in x, and y
let topleft = [0, 0] // the top left corner of our rectangle


function update() {
  context.clearRect(0, 0, width, height)
  context.fillStyle = 'red'
  context.fillRect(topleft[0], topleft[1], size[0], size[1])
  topleft[0] += speed[0]
  topleft[1] += speed[1]
  requestAnimationFrame(update)
}

document.body.addEventListener('keydown', e => {
  if (e.code == 'ArrowLeft') {
    speed[0] -= 1
  } else if (e.code == 'ArrowRight') {
    speed[0] += 1
  } else if (e.code == 'ArrowUp') {
    speed[1] -= 1
  } else if (e.code == 'ArrowDown') {
    speed[1] += 1
  }
  e.preventDefault()
})

update()
canvas {
  border: 1px solid black;
}
<!DOCTYPE html>
<html>

<body>
  <canvas id="canvas" width=640 height=400 />
</body>

</html>

Do you get the idea? We constantly update the canvas, from the speed variable. And we change the speed variable only when the user presses a key.

Upvotes: 0

Related Questions