[英]How to move image on canvas using arrow keys in javascript
I've tried a few different ways that I have seen on here, but I can't quite get my image to move. 我尝试了几种不同的方法,但是我不能完全理解我的形象。 Whenever I try adapting code for arrow key presses, it just seems to make my canvas shrink and my player model (spaceperson) disappear.
每当我尝试调整箭头键按下的代码时,它似乎只会让我的画布缩小,而我的玩家模型(太空人)也会消失。
here is the "drawing board" I keep returning to, and what I have so far. 这是我继续回归的“绘图板”,以及我到目前为止所拥有的内容。
// Get the canvas and context
var canvas = document.getElementById("space");
var ctx = canvas.getContext("2d");
canvas.width = 1920;
canvas.height = 700;
// Create the image object
var spaceperson = new Image();
// Add onload event handler
spaceperson.onload = function () {
// Done loading, now we can use the image
ctx.drawImage(spaceperson, 280, 300);
};
// artwork by Harrison Marley (using make8bitart.com)
spaceperson.src = "http://i.imgur.com/Eh9Dpq2.png";`
I am quite new to javascript, and I am just trying to work out how I can move the specperson image using arrow keys. 我是javascript的新手,我只想弄清楚如何使用箭头键移动specperson图像。 I was trying to make a class for space person to access their x,y values, but I can't seem to draw the image without using
.onload
我试图为
.onload
制作一个类来访问他们的x,y值,但我似乎无法在不使用.onload
情况下绘制图像。
Here's some slightly modified code from a game I was noodling around with a while back. 这里有一些略微修改过的代码来自我一段时间后面的游戏。 If you want to see more code, check out the complete JS on GitHub .
如果您想查看更多代码,请查看GitHub上的完整JS 。 The game is incomplete but you should gather some helpful clues as to how to move an image around the canvas.
游戏不完整但你应该收集一些有用的线索,了解如何在画布周围移动图像。
var spaceperson = {
speed: 256,
other_stuff: ''
},
keysDown = [],
update,
main;
addEventListener("keydown", function (e) {
keysDown[e.keyCode] = true;
}, false);
update = function (modifier) {
if (38 in keysDown && spaceperson.y > 0) { // UP
spaceperson.y -= spaceperson.speed * modifier;
}
if (40 in keysDown && spaceperson.y < CANVAS_HEIGHT - SPACEPERSON_HEIGHT) { // DOWN
spaceperson.y += spaceperson.speed * modifier;
}
if (37 in keysDown && spaceperson.x > 0) { // LEFT
spaceperson.x -= spaceperson.speed * modifier;
}
if (39 in keysDown && spaceperson.x < CANVAS_WIDTH - SPACEPERSON_WIDTH) { // RIGHT
spaceperson.x += spaceperson.speed * modifier;
}
}
I'm not sure but i think this can help. 我不确定,但我认为这可以提供帮助。
// Get the canvas and context var canvas = document.getElementById("space"); var ctx = canvas.getContext("2d"); canvas.width = 1920; canvas.height = 700; var x = 280; var y = 300; // Create the image object var spaceperson = new Image(); spaceperson.addEventListener("keypress", press); // Add onload event handler spaceperson.onload = function () { // Done loading, now we can use the image ctx.drawImage(spaceperson, x, y); }; function press(event) { if(event.keyCode == 37) {//LEFT x = x - 1; } else if(event.keyCode == 38) {//UP y = y - 1; } else if(event.keyCode ==39) {//RIGHT x = x + 1; } else if(event.keyCode == 40) {//DOWN y = y + 1; } draw(); } function draw(){ ctx.drawImage(spaceperson,x,y); } // artwork by Harrison Marley (using make8bitart.com) spaceperson.src = "http://i.imgur.com/Eh9Dpq2.png";
here a more complete example: 这里有一个更完整的例子:
//just a utility
function image(url, callback){
var img = new Image();
if(typeof callback === "function"){
img.onload = function(){
//just to ensure that the callback is executed async
setTimeout(function(){ callback(img, url) }, 0)
}
}
img.src = url;
return img;
}
//a utility to keep a value constrained between a min and a max
function clamp(v, min, max){
return v > min? v < max? v: max: min;
}
//returns a function that can be called with a keyCode or one of the known aliases
//and returns true||false wether the button is down
var isKeyDown = (function(aliases){
for(var i=256, keyDown=Array(i); i--; )keyDown[i]=false;
var handler = function(e){
keyDown[e.keyCode] = e.type === "keydown";
e.preventDefault(); //scrolling; if you have to suppress it
};
addEventListener("keydown", handler, false);
addEventListener("keyup", handler, false);
return function(key){
return(true === keyDown[ key in aliases? aliases[ key ]: key ])
}
})({
//some aliases, to be extended
up: 38,
down: 40,
left: 37,
right: 39
});
// Get the canvas and context
var canvas = document.getElementById("space");
canvas.width = 1920;
canvas.height = 700;
var ctx = canvas.getContext("2d");
//the acutal image is just a little-part of what defines your figue
var spaceperson = {
image: image("//i.imgur.com/Eh9Dpq2.png", function(img){
spaceperson.width = img.naturalWidth;
spaceperson.height = img.naturalHeight;
//start the rendering by calling update
update();
}),
//position
x: 60, y: 310,
width: 0, height: 0,
speed: 200 // 200px/s
};
var lastCall = 0; //to calculate the (real) time between two update-calls
//the render-fucntion
function update(){
//taking account for (sometimes changing) framerates
var now = Date.now(), time = lastCall|0 && (now-lastCall)/1000;
lastCall = now;
requestAnimationFrame(update);
var sp = spaceperson,
speed = sp.speed;
//checking the pressed buttons and calculates the direction
//two opposite buttons cancel out each other, like left and right
var dx = (isKeyDown('right') - isKeyDown('left')) * time,
dy = (isKeyDown('down') - isKeyDown('up')) * time;
//fix the speed for diagonals
if(dx && dy) speed *= 0.7071067811865475; // * 1 / Math.sqrt(2)
if(dx) { //there is some movement on the x-axes
sp.x = clamp(
//calculate the new x-Position
//currentPos + direction * speed
sp.x + dx * sp.speed,
//restraining the result to the bounds of the map
0, canvas.width - sp.width
);
}
//same for y
if(dy) sp.y = clamp(sp.y + dy * sp.speed, 0, canvas.height - sp.height);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(sp.image, sp.x, sp.y);
}
Edit: 编辑:
A quick question (I hope);
一个简单的问题(我希望); if I was to later add other objects, would I check for collisions in update()?
如果我以后添加其他对象,我会检查update()中的冲突吗?
This is still just a very basic example. 这仍然只是一个非常基本的例子。 The main purpose of the
update()
-function should be to work as the main event-loop. update()
-function的主要目的应该是作为主事件循环。 To trigger all Events that have to happen each frame in the order they have to happen. 触发必须按顺序发生的所有事件必须发生的事件。
var lastCall = 0;
function update(){
//I always want a next frame
requestAnimationFrame(update);
//handle timing
var now = Date.now(),
//time since the last call in seconds
//cause usually it's easier for us to think in
//tems like 50px/s than 0.05px/ms or 0.8333px/frame
time = lastCall|0 && (now-lastCall) / 1000;
lastCall = now;
movePlayer(time);
moveEnemies(time);
moveBullets(time);
collisionDetection();
render();
}
function render(){
ctx.clear(0, 0, canvas.width, canvas.height);
drawBackground(ctx);
for(var i=0; i<enemies.length; ++i)
enemies[i].render(ctx);
player.render(ctx);
}
Not saying that you have to implement all these functions now, but to give you an idea of a possible structure. 并不是说你现在必须实现所有这些功能,而是要让你了解一个可能的结构。 Don't be scared to break big tasks (functions) up into subtasks.
不要害怕将大任务(功能)分解为子任务。
And it might make sense to give each enemy a move()
-function so you can implement different movement-patterns per enemy, or you say that the pattern is (and will be) all the same for each enemy, parameterized at the best, then you can handle that in a loop. 给每个敌人一个
move()
函数可能是有意义的,这样你就可以为每个敌人实现不同的运动模式,或者你说每个敌人的模式都是(并且将会)完全相同,参数化最好,然后你可以在循环中处理它。
Same thing for rendering, as I'm showing in the last part of code. 渲染也是一样,正如我在代码的最后部分所示。
I found a solution! 我找到了解决方案!
// Get the canvas and context
var canvas = document.getElementById("space");
var ctx = canvas.getContext("2d");
canvas.width = 1920;
canvas.height = 700;
var xPos = 60;
var yPos = 310;
// Create the image object
var spaceperson = new Image();
// Add onload event handler
spaceperson.onload = function () {
// Done loading, now we can use the image
ctx.drawImage(spaceperson, xPos, yPos);
};
function move(e){
if(e.keyCode==39){
xPos+=10;
}
if(e.keyCode==37){
xPos-=10;
}
if(e.keyCode==38){
yPos-=10;
}
if(e.keyCode==40){
yPos+=10;
}
canvas.width=canvas.width;
ctx.drawImage(spaceperson, xPos, yPos);
}
document.onkeydown = move;
// artwork by Harrison Marley
spaceperson.src = "http://i.imgur.com/Eh9Dpq2.png";
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.