繁体   English   中英

如何在JavaScript中使用setInterval循环时让Sprite停止移动

[英]How to get a sprite to stop moving while using a setInterval loop in JavaScript

我正在尝试使用由模因制作的精灵为我的朋友制作游戏。 我决定使用一个无限循环来有效地运行我的代码,但是我不确定如何使用keyup事件侦听器阻止小精灵移动,因为当我按箭头键时,小精灵将永远移动。 我该如何解决? 另外,当我按住键时,如何使子画面移动,而不是在解决主要问题后单独按下它? (注意:精灵转换不是问题,我想先降低运动速度。)

 // setting up basic canvas const cvs = document.getElementById("canvas"); const ctx = cvs.getContext('2d'); // defining images and sources for each one let petscop = new Image(); petscop.src = "https://raw.githubusercontent.com/swedishF1sh/PETSCOP2p/master/petscop-fromside-1.png.png"; let petscop2 = new Image(); petscop2.src = "https://raw.githubusercontent.com/swedishF1sh/PETSCOP2p/master/petscop-fromside-2.png.png"; let petscop3 = new Image(); petscop3.src = "https://raw.githubusercontent.com/swedishF1sh/PETSCOP2p/master/petscop-fromside-3.png.png"; let background1 = new Image(); background1.src = "https://raw.githubusercontent.com/swedishF1sh/PETSCOP2p/master/petscop-background.png" // setting up the direction variable let d; document.addEventListener("keydown", direction); function direction(event) { let key = event.keyCode; if (key == 37) { d = "RIGHT"; } else if (key == 38) { d = "DOWN"; } else if (key == 39) { d = "LEFT"; } else if (key == 40) { d = "UP"; } } // length & width of one box, in half. (regular as 32) let halfbox = 16; // organizing the frames for the current character let currentframe = petscop; let frames = { front: petscop, frontblink: petscop2, back: petscop3 } let petscopsize = { height: petscop.height, width: petscop.width } // setting up the character position let characterpos = { x: halfbox*13, y: halfbox*10, } // setting up the main function which the game will run on. function draw() { currentframe.width = petscop.width; currentframe.height = petscop.height; ctx.drawImage(background1, 0, 0); ctx.drawImage(currentframe, characterpos.x, characterpos.y); if (d == "LEFT") { characterpos.x += halfbox; currentframe = petscop; } else if (d == "UP") { characterpos.y += halfbox; currentframe = petscop; } else if (d == "RIGHT") { characterpos.x -= halfbox; currentframe = petscop; } else if (d == "DOWN") { characterpos.y -= halfbox; currentframe = petscop3; } } setInterval(draw, 50); 
 #canvas { border: 5px; background-color: white; } .canvas-container { margin-left: 25%; } body { background-color: rgb(255, 255, 255); // gray: 40, 68, 68 // white: 255, 255, 255 } 
 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>repl.it</title> <link href="style.css" rel="stylesheet" type="text/css" /> </head> <body> <div class="canvas-container"> <canvas id="canvas" height="512" width="862"></canvas> </div> <script src="script.js"></script> </body> </html> 

我希望当我停止按住键时最终结果将停止移动。

代替setInterval(draw, 50); 使用var loop = setInterval(draw, 50); 然后,当您希望它停止时,使用clearInterval(loop);

document.addEventListener("keyup", () => d = null);

放开按钮,应立即禁用移动。

这两个答案似乎并没有太大帮助。

动画循环

您认为无限循环是处理游戏动画的最佳方法是正确的。

但是,请勿使用setInverval ,而应使用requestAnimationFrame创建游戏循环。

您有50ms的间隔,即20fps(每秒帧数)。 requestAnimationFrame将尝试以60fps的速度运行,您无法更改。 但是,您可以每3帧跳过2帧以获得20fps。

该代码段显示了使用requestAnimationFrame和可调帧率的基本游戏循环。

const frameRate = 20; // only works for frame rates 60,30,20,15,12,10,6,5,4,3,2,1 per second
var frameCount = 0; // counts requested frames @60fps

requestAnimationFrame(gameLoop); // this will start the game loop
function gameLoop(time) { // time is passed to this function by requestAnimationFrame
    if ((frameCount++) % (60 / frameRate)) {
        draw(); // calls your game code
    }

    // Request the next frame
    requestAnimationFrame(gameLoop);
}

键盘

要处理键盘输入,您需要同时监听按键按下和按键按下事件。

流畅的代码段是一个简单的键盘状态管理器,用于维护您感兴趣的键的状态。

您可以在KeyboardEvent.code找到键码。

const keys = {  // Name of keys code you want to use
    ArrowUp: false,  // set to off at start
    ArrowDown: false,
    ArrowLeft: false,
    ArrowRight: false,
};
// the event listener
function keyEvent(event) {
    if (keys[event.code] !== undefined) { // is this a key we are using?
        keys[event.code] = event.type === "keydown"; // set true if down false if up
        event.preventDefault(); // stops default action (eg scrolling page)
    }
}
// Add the key events to the window object (window is the default object 
// so dont need to name it)
addEventListener("keyup", keyEvent);
addEventListener("keydown", keyEvent);

现在,您只需更改游戏代码即可仅在按键按下时移动角色。

顺便说一句,最好先移动精灵然后绘制精灵,而不是先绘制再移动。 这减少了用户输入和视觉反馈之间的延迟。

function draw() {
    ctx.drawImage(background1, 0, 0);
    currentframe = petscop;

    if (keys.ArrowLeft) {
       characterpos.x += halfbox;
    }
    if (keys.ArrowRight) {
       characterpos.x -= halfbox;
    }
    if (keys.ArrowUp) {
       characterpos.y += halfbox;
    }
    if (keys.ArrowDown) {
       characterpos.y -= halfbox;
       currentframe = petscop3;
    }
    ctx.drawImage(currentframe, characterpos.x, characterpos.y);
 }

该片段将所有内容组合在一起。

我认为您的键映射是从前到后的,我把它保留了下来是因为您的代码似乎暗示着左移右移,上移向下等等。

我还更改了图像的加载方式,并更改了作为字符的对象。

希望它能有所帮助,并且不要迟到(我刚刚注意到问题日期)。

 const frameRate = 20; // only rates 60,30,20,15,12,10,6,5,4,3,2,1 per second var frameCount = 0; const cvs = document.getElementById("canvas"); const ctx = cvs.getContext('2d'); ctx.fillStyle = "#09F"; ctx.textAlign = "center"; ctx.fillText("loading...", cvs.width / 2, cvs.height / 2); const imgLocation = "https://raw.githubusercontent.com/swedishF1sh/PETSCOP2p/master/petscop-"; const images = { forward: "fromside-1.png.png", backward: "fromside-3.png.png", blink: "fromside-2.png.png", background: "background.png", }; function loadImages(imageList, onAllLoaded) { var count = 0; for(const name of Object.keys(imageList)) { const img = new Image; count ++; img.src = imgLocation + imageList[name]; img.onload = () => { imageList[name] = img; img.onload = null; count --; if (count === 0 && onAllLoaded) { onAllLoaded() } } } } // loads images and start main loop when all loaded loadImages(images,() =>requestAnimationFrame(gameLoop)); const keys = { // codes @ https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code ArrowUp: false, ArrowDown: false, ArrowLeft: false, ArrowRight: false, }; function keyEvent(event) { if (keys[event.code] !== undefined) { keys[event.code] = event.type === "keydown"; event.preventDefault(); } } addEventListener("keyup", keyEvent); addEventListener("keydown", keyEvent); focus(); // for SO snippet to get keyboard events without clicking first const halfbox = 16; const blinkOdds = 1/100; // odds of blinking. 1/100 @ 20fps average blink time is 5 seconds const character = { x: halfbox * 13, y: halfbox * 10, image: null, draw() { ctx.drawImage(this.image, this.x, this.y); }, move() { this.image = Math.random() < blinkOdds ? images.blink : images.forward; if (keys.ArrowLeft) { this.x += halfbox; } if (keys.ArrowRight) { this.x -= halfbox; } if (keys.ArrowUp) { this.y += halfbox; } if (keys.ArrowDown) { this.y -= halfbox; this.image = images.backward; } }, } function draw() { ctx.drawImage(images.background, 0, 0); character.move(); character.draw(); } function gameLoop(time) { if ((frameCount++) % (60 / frameRate)) { draw(); } requestAnimationFrame(gameLoop); } 
 #canvas { border: 5px; background-color: white; } .canvas-container { margin-left: 25%; } body { background-color: rgb(255, 255, 255); } 
 <div class="canvas-container"> <canvas id="canvas" height="512" width="862"></canvas> </div> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM