JS Canvas: lineTo() - javascript

I am new to Javascript!
How do I assign a variable to the current xy coordinates, so I can use relative positions to draw lines? Trying to do etch-a-sketch with keyboard. Up, down, left, right arrow keys... with JS, CSS, and HTML.
Thanks!
window.addEventListener("keydown", keyd);
function keyd(event) {
var etchMain = document.getElementById('etchMain');
var etchContext = etchMain.getContext('2d');
var key = event.keyCode;
**var etchContextPositionX;
var etchContextPositionY;**
if (key == 37) {
// left arrow
if (etchMain.toDataURL() == document.getElementById('blank').toDataURL()) {
etchContext.beginPath();
etchContext.moveTo(etchMain.width / 2, etchMain.height / 2);
// arrow specific drawing goes here
}
else {
}
}
if (key == 38) {
// up arrow
if (etchMain.toDataURL() == document.getElementById('blank').toDataURL()) {
etchContext.beginPath();
etchContext.moveTo(etchMain.width / 2, etchMain.height / 2);
// arrow specific drawing goes here
}
else {
}
}
if (key == 39) {
// right arrow
if (etchMain.toDataURL() == document.getElementById('blank').toDataURL()) {
etchContext.beginPath();
etchContext.moveTo(etchMain.width / 2, etchMain.height / 2);
// arrow specific drawing goes here
}
else {
}
}
if (key == 39) {
// down arrow
if (etchMain.toDataURL() == document.getElementById('blank').toDataURL()) {
etchContext.beginPath();
etchContext.moveTo(etchMain.width / 2, etchMain.height / 2);
// arrow specific drawing goes here
}
else {
}
}
}
function clearCanvas() {
var etchMain = document.getElementById('etchMain');
var etchContext = etchMain.getContext('2d');
etchContext.clearRect(0, 0, etchMain.width, etchMain.height);
}

i implemented a really basic idea of what you're talking about just because it sounded kind of fun. hit run snippet, then click on the canvas box to give that frame focus. the event handler will prevent window scrolling and instead use the arrow inputs to increment or decrement x and y and draw from there or you can hit space bar to clear the canvas!
the bit of design you were missing was storing x and y outside of the event handler and using the difference between the previous state of x and y to draw your canvas lines:
var pos = {
x: 50,
y: 50,
}
var etchMain = document.getElementById('etchMain');
var etchContext = etchMain.getContext('2d');
window.addEventListener('keydown', function(e) {
e.preventDefault();
if(e.keyCode === 32) {
clearCanvas();
} else {
etchContext.beginPath();
etchContext.moveTo(pos.x, pos.y);
switch (e.keyCode) {
//left arrow
case 37:
pos.x--;
break;
//up arrow
case 38:
pos.y--;
break;
//right arrow
case 39:
pos.x++;
break;
//down arrow
case 40:
pos.y++;
break;
default:
break;
}
etchContext.lineTo(pos.x, pos.y);
etchContext.stroke();
}
});
function clearCanvas() {
etchContext.clearRect(0, 0, etchMain.width, etchMain.height);
}
#etchMain {
border: 1px solid black;
}
<canvas id="etchMain" height="100" width="100" />

Related

How to make a character pursue the player's character in a JS / canvas game?

I'm just starting to code a simple JS game using canvas, but i don't have any ideas of how the main mechanic would work: it's an endless game, where the player must run from the monster and enter a door before the monster reaches him.
So, i have the canvas and the player moving, but i still didn't started the monster mechanics. I think that would be to update every monster's frame with the x/y player's position, right?
Code that i wrote so far:
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
canvas.width = 600;
canvas.height = 600;
document.body.appendChild(canvas);
const survivor = {
x: 25,
y: 25,
moveUp: function() { this.y -= 25 },
moveDown: function() { this.y += 25 },
moveLeft: function() { this.x -= 25 },
moveRight: function() { this.x += 25 },
}
function draw(survivor) {
const img = new Image();
img.onload = () => {
ctx.drawImage(img, survivor.x, survivor.y, 50, 50);
}
img.src = "/images/survivor-move_knife_0.png";
}
document.addEventListener('keydown', e => {
switch (e.keyCode) {
case 38:
survivor.moveUp();
console.log('up: ', survivor);
break;
case 40:
survivor.moveDown();
console.log('down: ', survivor);
break;
case 37:
survivor.moveLeft();
console.log('left: ', survivor);
break;
case 39:
survivor.moveRight();
console.log('right: ', survivor);
break;
}
updateCanvas();
})
function updateCanvas() {
ctx.clearRect(0,0,1500,1700);
draw(survivor);
}
updateCanvas()
}
There are several ways to do this.
Given the code you posted, a simple (but not very efficient) way would be to use setInterval() to run your monster's logic.
A very simple logic could work like this (pseudo code):
if ( monster.canMoveLeft() && player.x < monster.x ) {
monster.moveLeft()
} else if ( monster.canMoveRight() && player.x > monster.x ) {
monster.moveRight()
} else if ( monster.canMoveUp() && player.y < monster.y ) {
monster.moveUp()
} else if ( monster.canMoveDown() && player.y > monster.y ) {
monster.moveDown()
} else {
// no good choice
// either continue moving in the same direction, or choose a random
// direction if that's not possible
//
// This means you need to keep track of the monster's last direction
}
You could also check the distance on the horizontal and vertical axis to determine which direction to go first.
List item

Moving an image inside a canvas using arrow keys

I have a canvas where we can move a shape with arrow keys.
However, I want an image to move instead of a shape and I can't work it out.
Any help?
As of now, the image appears but I can't move it.
I tried many things on the internet but they didn't work. The id for the image is image.
This is my current code:
car = {
image : img,
//jumping: true,
x:180, // center of the canvas
x_velocity:0,
y: 160,
y_velocity:0,
};
controller = {
left: false,
right: false,
up: false,
down: false,
keyListener:function(event) {
var key_state = (event.type == "keydown")?true:false;
switch(event.keyCode) {
case 37:// left key
controller.left = key_state;
break;
case 38:// up key
controller.up = key_state;
break;
case 39:// right key
controller.right = key_state;
break;
case 40: //down key
controller.down = key_state;
}
}
};
loop = function() {
if (controller.up) {
car.image.y_velocity -= 0.5;
}
if (controller.left) {
car.image.x_velocity -= 0.5;
}
if (controller.right) {
car.image.x_velocity += 0.5;
}
if (controller.down) {
car.image.y_velocity += 0.5;
}
car.image.x += car.image.x_velocity;
car.image.y += car.image.y_velocity;
car.image.x_velocity *= 0.9;// friction
car.image.y_velocity *= 0.9;
// if car.image is going off the left of the screen
if (car.image.x < -32) {
car.image.x = 1190;
// if car.image goes past right boundary
} else if (car.image.x > 1190) {
car.image.x = -32;
// if car.image goes past lower boundary
} else if (car.image.y > 790) {
car.image.y = 0;
// if car.image goes past upper boundary
} else if (car.image.y < -32) {
car.image.y = 790;
}
context.drawImage(car.image, car.x, car.y);
// call update when the browser is ready to draw again
window.requestAnimationFrame(loop);
};
window.addEventListener("keydown", controller.keyListener) //press down and it moves
window.addEventListener("keyup", controller.keyListener); //lift finger and it stops
window.requestAnimationFrame(loop);
This is the code when the shape was moving:
rectangle = {
height:20,
width:20,
x:180, // location # center of the canvas
x_velocity:0,
y: 160,
y_velocity:0,
};
controller = {
left: false,
right: false,
up: false,
down: false,
keyListener:function(event) {
var key_state = (event.type == "keydown")?true:false;
switch(event.keyCode) {
case 37:// left key
controller.left = key_state;
break;
case 38:// up key
controller.up = key_state;
break;
case 39:// right key
controller.right = key_state;
break;
case 40: //down key
controller.down = key_state;
}
}
};
loop = function() {
if (controller.up) {
rectangle.y_velocity -= 0.5;
}
if (controller.left) {
rectangle.x_velocity -= 0.5;
}
if (controller.right) {
rectangle.x_velocity += 0.5;
}
if (controller.down) {
rectangle.y_velocity += 0.5;
}
rectangle.x += rectangle.x_velocity;
rectangle.y += rectangle.y_velocity;
rectangle.x_velocity *= 0.9;// friction
rectangle.y_velocity *= 0.9;// friction
// if rectangle is going off the left of the screen
if (rectangle.x < -32) {
rectangle.x = 1190;
// if rectangle goes past right boundary
} else if (rectangle.x > 1190) {
rectangle.x = -32;
// if rectangle goes past lower boundary
} else if (rectangle.y > 790) {
rectangle.y = 0;
// if rectangle goes past upper boundary
} else if (rectangle.y < -32) {
rectangle.y = 790;
}
context.fillRect(0, 0, 1200, 800);// x, y, width, height
context.fillStyle = "white";// hex for red
context.beginPath();
context.rect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
context.fill();
// call update when the browser is ready to draw again
window.requestAnimationFrame(loop);
};
window.addEventListener("keydown", controller.keyListener) //press down and it moves
window.addEventListener("keyup", controller.keyListener); //lift finger and it stops
window.requestAnimationFrame(loop);

A more concise way to loop a function on keypress in a case?

What am I trying to accomplish?
I'm trying to get the TrumpHead to continue moving until another key is pressed moving it in a different direction, like in the game snake. The only thing I can think of it making a bunch of cases with functions filled with cases in each? Any ideas welcome and help needed, new to javascript.
My code
var width = 1000, height = 1000; //Width and Height of Canvas
var cvs = document.getElementById('Snake'); //cvs is representing Canvas
var ctx = cvs.getContext('2d'); //ctx is context represented in 2 dimentions.
cvs.width = window.innerWidth; //setting the canvas width to be the width above.
cvs.height = window.innerHeight; //setting the canvas height to be the height above.
var img = new Image();
img.src = 'snakeHead.png';
var TrumpHead = canvasImage(100, 100, img);
window.addEventListener('keydown',this.checkOn,false);
//window.addEventListener('keyUp',this.checkOff,false);
function canvasImage(x, y, img) {
this.image = img;
this.x = x;
this.y = y;
this.width = img.width;
this.height = img.height;
return this;
}
function checkOn(e) {
//var pos = getTrumpPos();
//var x = pos [0];
//var y = pos [1];
//alert(e.keyCode);
switch (e.keyCode) {
case 37://left
if (TrumpHead.x == cvs.width) { //this is just alerting you lose if
you go off the canvas
alert("You Lose");
} else if (TrumpHead.x < 0) {
alert("You Lose");
} else {
LeftDirection ();
console.log("Pressed Left");
console.log(x,y);
}
break;
case 38: //up key
if (TrumpHead.y < 0) {
alert("You Lose");
} else if (TrumpHead.y > cvs.height) {
alert("You Lose");
} else {
console.log("Pressed Up");
UpDirection();
console.log(x,y);
}
break;
case 39: //right
if (TrumpHead.x > cvs.width) {
alert("You Lose");
} else if (TrumpHead.x < 0) {
alert("You Lose");
} else{
console.log("Pressed Right");
console.log(x,y);
RightDirection();
}
break;
case 40: //down
if (TrumpHead.y < 0) {
alert("You Lose");
} else if (TrumpHead.y > cvs.height) {
alert("You Lose");
} else{
console.log("Pressed Down");
console.log(x,y);
DownDirection(); //this is a function defined in the movementFunctions section.
}
break;
// default: alert(e.keyCode); //Everything else
}
}
function gameLoop()
{
// change position based on speed
checkOn();
setTimeout("gameLoop()",10);
}
function LeftDirection ()
{
TrumpHead.x = TrumpHead.x - 50;
ctx.clearRect(0,0,cvs.width,cvs.height); //clears the gamescreen
ctx.drawImage(TrumpHead.image, TrumpHead.x, TrumpHead.y, 50, 50);
//Puts Trump down.
}
function RightDirection ()
{
TrumpHead.x = TrumpHead.x + 50;
ctx.clearRect(0,0,cvs.width,cvs.height);
ctx.drawImage(TrumpHead.image, TrumpHead.x, TrumpHead.y, 50, 50);
}
function UpDirection ()
{
TrumpHead.y = TrumpHead.y - 50;
ctx.clearRect(0,0,cvs.width,cvs.height);
ctx.drawImage(TrumpHead.image, TrumpHead.x, TrumpHead.y, 50, 50);
}
function DownDirection () {
TrumpHead.y = TrumpHead.y + 50;
ctx.clearRect(0,0,cvs.width,cvs.height);
ctx.drawImage(TrumpHead.image, TrumpHead.x, TrumpHead.y, 50, 50);
}
You need two loops: one for input, and one for actually drawing on the display. You can use browser events to check for key input (shown here with the up and left arrow keys, and set state based off of which keys were pressed. Then you can use this in your update loop. Here's an example:
var movingLeft = false, movingUp = false;
document.body.onkeydown(function(e) {
switch(e.keyCode) {
case 38:
movingUp = true;
movingLeft = false;
break;
case 37:
movingLeft = true;
movingUp = false;
break;
}
});
// and a loop:
function loop() {
if (movingLeft) {
updateDisplayByLeftIncrement(); //update display how you want
else if(movingUp) {
updateDisplayByUpIncrement(); //update display how you want
} //...and so on for all the movements
}
//and then you can use setInterval() to loop with a delay between iterations
setInterval(loop, timeOut);
You need to break the program execution into at least two loops/pumps.
1) An input loop,
2) An update loop
If you don't then your scene update will be at the mercy of your user input or vis-a-vis.
Good luck!

bizzare putImageData action

Here is my code :
var ctx = document.getElementById("map").getContext("2d");
var ZeroX = 0;
var ZeroY = 0;
ctx.beginPath();
ctx.fillRect(100, 200, 100, 50); //Drawed a black rectangle
function moveMap(evt) {
var key = evt.keyCode || evt.which;
if (key == 38) { //UP
moveDirect(0, 20, false);
}
else if (key == 40) { //DOWN
moveDirect(0, 20, true);
}
else if (key == 39) { //RIGHT
moveDirect(20, 0, true);
}
else if (key == 37) { //LEFT
moveDirect(20, 0, false);
}
}
function moveDirect(X, Y, minus) {
if (minus == false) {
ZeroX -= X;
ZeroY -= Y;
}
else {
ZeroX += X;
ZeroY = Y;
}
var lol = ctx.getImageData(ZeroX, ZeroY, 3000, 3000);
ctx.clearRect(ZeroX, ZeroY, 3000, 3000);
ctx.putImageData(lol, 0, 0);
}
<body onkeypress="moveMap(event)">
<canvas id="map" width="500" height="500">Map </canvas>
</body>
If you run this snippet and click on one of the arrows on the keyboard, you'll see that the rectangle moves in the opposite
direction because I wanted to make like the screen was a camera in a
game. That's done on purpose
But if after you clicked on the arrow's oppsite (Up = Down, Left = Right,
etc), you will see that you must click two times to make it move in
the other direction. Try this with other arrows, still the same.
And if you press the same arrow many times, it's gap travelled becomes
bigger and bigger, but logically it must the same.
I want it to respond directly, not on two clicks and that the gap is always the same. Please explain in your answer why this is happennings. Thaks beforehand!

How to move object with keyboard in javascript

When I move the object, it's slow and doesn't move in diagonal, only up, down, right and left.
How can I fix this, is this a good way to start or should I do it otherwise?
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
canvas.width = 600;
canvas.height = 600;
var object = {
height: 40,
width: 40,
x: 10,
y: 10,
color: "#FF0000"
}
document.addEventListener('keydown', function(event) {
//left
if(event.keyCode == 37) {
object.x -= 1;
}
//top
else if(event.keyCode == 38) {
object.y -= 1;
}
//right
else if(event.keyCode == 39) {
object.x += 1;
}
//bottom
else if(event.keyCode == 40) {
object.y += 1;
}
});
function renderCanvas(){
ctx.fillStyle = "#000000";
ctx.fillRect(0, 0, 600, 600);
}
function renderObject(){
ctx.fillStyle = "#FF0000";
ctx.fillRect(object.x, object.y, object.width, object.height);
}
function run(){
renderCanvas();
renderObject();
}
setInterval(run, 10);
Here's a jsfiddle
I'm kind of a newbie in javascript and I really need help on this ;)
Use flags or an object with flags that is updated when keys are pressed and released:
var Keys = {
up: false,
down: false,
left: false,
right: false
};
Then update in key events:
window.onkeydown = function(e) {
var kc = e.keyCode;
e.preventDefault();
if (kc === 37) Keys.left = true; // only one key per event
else if (kc === 38) Keys.up = true; // so check exclusively
else if (kc === 39) Keys.right = true;
else if (kc === 40) Keys.down = true;
};
window.onkeyup = function(e) {
var kc = e.keyCode;
e.preventDefault();
if (kc === 37) Keys.left = false;
else if (kc === 38) Keys.up = false;
else if (kc === 39) Keys.right = false;
else if (kc === 40) Keys.down = false;
};
This will now allow you to check keys that are pressed at the same time (if you want to move continuously you need to check status of the key object in a loop or else you will get a repeat delay):
if (Keys.up) {
dy+=3;
}
else if (Keys.down) { // both up and down does not work so check excl.
dy-=3;
}
if (Keys.left) {
dx+=3;
}
else if (Keys.right) {
dx-=3;
}
FIDDLE
Flags, yes, but 2 is plenty: dx and dy:
http://jsfiddle.net/rudiedirkx/paw4X/1/
var dx = 0, dy = 0;
var speed = 100; // px per second
var activeKey = 0;
document.addEventListener('keydown', function(e) {
if (activeKey == e.keyCode) return;
activeKey = e.keyCode;
//left
if (e.keyCode == 37) {
console.log('start moving LEFT');
dx = -1;
}
//top
else if (e.keyCode == 38) {
console.log('start moving UP');
dy = -1;
}
//right
else if (e.keyCode == 39) {
console.log('start moving RIGHT');
dx = 1;
}
//bottom
else if (e.keyCode == 40) {
console.log('start moving DOWN');
dy = 1;
}
});
document.addEventListener('keyup', function(e) {
switch (e.keyCode) {
case 37: // left
case 39: // right
console.log('stop moving HOR');
dx = 0;
break;
case 38: // up
case 40: // down
console.log('stop moving VER');
dy = 0;
break;
}
activeKey = 0;
});
function fun(){
renderCanvas();
object.x += dx / 60 * speed;
object.y += dy / 60 * speed;
renderObject();
requestAnimationFrame(fun);
}
requestAnimationFrame(fun);
The ugly activeKey part is necessary, because some keyboards repeat the keydown event every X ms until the key is released.
var object = {
height: 40,
width: 40,
x: 10,
y: 10,
color: "#FF0000"
}
You seem to have forgotten a semicolon. Let me show you:
var object = {
height: 40,
width: 40,
x: 10,
y: 10,
color: "#FF0000"
};
How about using the number-pad keys?
These number keys are already marked with the up/down/left/right arrowkeys so using 1,3,7,9 for diagonal moves would be understandable and convenient for the user.
To speed up your movement, you can add more than 1 pixel with each keystroke.
To move diagonally, you'll want to change both the object.x and object.y values simultaneously.
// move 4 pixels with each key
var distance=4;
// for example, move diagonally up & left
object.x-=distance;
object.y-=distance;
Here's example code and a Demo: http://jsfiddle.net/m1erickson/RnJLZ/
<!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 distance=4;
var object = {
height: 40,
width: 40,
x: 10,
y: 10,
color: "#FF0000"
}
renderObject();
document.body.onkeydown=function(event){
switch(event.keyCode){
case 97: // 1
object.x-=distance;
object.y+=distance;
break;
case 98: // 2
object.x+=0;
object.y+=distance;
break;
case 99: // 3
object.x+=distance;
object.y+=distance;
break;
case 100: // 4
object.x-=distance;
object.y+=0;
break;
case 101: // 5
object.x+=0;
object.y+=0;
break;
case 102: // 6
object.x+=distance;
object.y+=0;
break;
case 103: // 7
object.x-=distance;
object.y-=distance;
break;
case 104: // 8
object.x+=0;
object.y-=distance;
break;
case 105: // 9
object.x+=distance;
object.y-=distance;
break;
}
renderObject();
}
function renderObject(){
if(ctx.fillStyle!=object.color.toLowerCase()){
console.log(ctx.fillStyle,object.color);
ctx.fillStyle=object.color;
}
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillRect(object.x,object.y,object.width,object.height);
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
I tried and it looks like you had to set flags. I came up with this: http://jsfiddle.net/medda86/y6WU9/
html
<div class="pic"></div>
css
html,body{
width:100%;
height:100%;
margin:0px;}
.pic{
position:absolute;
margin-left:100px;
margin-top:100px;
width:100px;
height:100px;
background-color:#ccc;}
jquery
// MOVE OBJECT DIAGONALLY
$(document).ready(function(){
var movementSpeed = 10;
var intervalSpeed = 60;
var runAnimation = false;
var animationSpeed = 10;
var leftMarginLimit = parseInt($('.pic').parent().css('width')) - parseInt($('.pic').css('width'));
var topMarginLimit = parseInt($('.pic').parent().css('height')) - parseInt($('.pic').css('height'));
var leftMargin = parseInt($('.pic').css('margin-left'));
var topMargin = parseInt($('.pic').css('margin-top'));
var animationComplete = true;
// flags
var left = false;
var right = false;
var up = false;
var down = false;
$(document).keyup(function(key) {
if (key.which == 37){left = false;}
if (key.which == 39){right = false;}
if (key.which == 38){up = false;}
if (key.which == 40){down = false;}
});
$(document).keydown(function(key) {
if (key.which == 37){left = true;}
if (key.which == 39){right = true;}
if (key.which == 38){up = true;}
if (key.which == 40){down = true;}
});
setInterval(runMovement,intervalSpeed);
function runMovement() {
if (animationComplete){
// LEFT
if (left){
leftMargin -=movementSpeed;
if (leftMargin < 0){leftMargin = 0;}
if (leftMargin > leftMarginLimit){leftMargin = leftMarginLimit;}
}
// RIGHT
if (right){
leftMargin +=movementSpeed;
if (leftMargin < 0){leftMargin = 0;}
if (leftMargin > leftMarginLimit){leftMargin = leftMarginLimit;}
}
// UP
if (up){
topMargin -=movementSpeed;
if (topMargin < 0){topMargin = 0;}
if (topMargin > topMarginLimit){topMargin = topMarginLimit;}
}
// DOWN
if (down){
topMargin +=movementSpeed;
if (topMargin < 0){topMargin = 0;}
if (topMargin > topMarginLimit){topMargin = topMarginLimit;}
}
// ANIMATION?
if (runAnimation){
animationComplete = false;
$('.pic').animate({'margin-left': leftMargin+'px','margin-top': topMargin+'px'},animationSpeed,function(){
animationComplete = true;
});
}
else{
$('.pic').css({'margin-left': leftMargin+'px','margin-top': topMargin+'px'});
}
}
}
});
You can change theese settings, like how fast to move object and if you wanna run the animation, and set the animationspeed. Also you cna set the interval here.. game speed :P
var movementSpeed = 10;
var intervalSpeed = 60;
var runAnimation = false;
var animationSpeed = 10;
EDIT: I had to add the setinterval, got a bit buggy the other way with keydown and keyup. Now you can move all around more smoothly :)

Categories