簡體   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