多次启动和停止同一时间间隔

问题描述 投票:1回答:2

我第一次尝试游戏角色的移动。我已经成功制作了一个按钮,当按下按钮时角色可以移动,释放按钮时角色可以停止。我的问题是,这只能工作一次。如果我第二次按下按钮,角色将不再前进。我检查了控制台是否有错误,但没有任何错误。这是我的代码:

var sonic = document.getElementById('sonic');
var left = 0
var forward;
var add;
sonic.style.position = "absolute";

function move() {
  forward = setInterval(forward, 10);
  add = setInterval(add, 10);
}

function add() {
  left = left + 10;
}

function forward() {
  sonic.style.left = left;
}

function stop() {
  clearInterval(forward);
  clearInterval(add);
}
<button onmousedown="move()" onmouseup="stop()">Move Forward</button>
<br>
<br>
<img width="150px" id="sonic" src="https://www.sccpre.cat/mypng/full/338-3383227_sonic-running-png-sonic-1-sonic-sprite.png" />

我希望角色可以在用户按住按钮时移动,而不仅仅是一次。

javascript intervals
2个回答
1
投票
  • 而不是使用多个setInterval,而是使用单个window.requestAnimationFrame()
  • [开按钮(或键)操作keys对象,以跟踪按下了什么键
  • keysController()函数内部,将按下的键(如果存在)转换为在pos(甚至以后在x)轴上的y(位置)变换。
  • move()函数内部,编写用于移动元素的代码。最好使用GPU加速的CSS transform属性。
  • engine循环内部只需调用您的所有函数

const EL = sel => document.querySelector(sel);

const sonic = EL('#sonic');
const left  = EL('#left');
const right = EL('#right');

const keys = {}; // you have buttons, but let's call it keys
const pos  = {x: 0, y: 0} // one day you could control the y axis too

function move() {
  sonic.style.transform = `translate(${pos.x}px, ${pos.y}px)`;
}

function keysController () { // convert pressed keys to position
  if (keys.right) pos.x += 10;
  if (keys.left)  pos.x -= 10;
}

(function engine () {
  keysController();
  move();
  requestAnimationFrame(engine)
}());

left.addEventListener('mousedown',  () => keys.left = true );
left.addEventListener('mouseup',    () => delete keys.left );
right.addEventListener('mousedown', () => keys.right = true );
right.addEventListener('mouseup',   () => delete keys.right );
#sonic {
  width: 150px;
  position: absolute;
}
<button id="left">&larr;</button>
<button id="right">&rarr;</button>
<br>
<br>
<img id="sonic" src="https://imgur.com/mYRJad0.png" />

0
投票

第一个问题是变量名的混淆。间隔索引的名称与函数的名称相同-导致混淆。请参阅下面的我进行了一些区分,每次单击按钮时,它就会向前移动:

<button onmousedown="move()" onmouseup="stop()">Move Forward</button>
<br>
<br>
<img width="150px" id="sonic" src="https://www.sccpre.cat/mypng/full/338-3383227_sonic-running-png-sonic-1-sonic-sprite.png" />
<script>
var sonic = document.getElementById('sonic');
var left = 0
var forwardInt;
var addInt;
sonic.style.position = "absolute";
function move(){
   forwardInt = setInterval(forwardFn, 10);
   addInt = setInterval(addFn, 10);
}
function addFn(){ 
   left = left + 10; 
}
function forwardFn(){
   sonic.style.left = left;
}
function stop(){
   clearInterval(forwardInt);
   clearInterval(addInt);
}
</script>

但是,我仍然认为这并不能完全实现您想要的功能(按住按钮的同时连续移动)。我理解正确吗?

下面我也做了一些调整以实现该目标。我结合了这两个功能,并考虑了窗户的边缘。我还为启动和停止添加了锁定/解锁机制。让小家伙走很有趣!带我回来。

<button onmousedown="move()" onmouseup="stop()">Move Forward</button>
<br>
<br>
<img width="150px" id="sonic" src="https://www.sccpre.cat/mypng/full/338-3383227_sonic-running-png-sonic-1-sonic-sprite.png" />
<script>
var sonic = document.getElementById('sonic');
var left = 0;
var forwardInt;
var addInt;
var lock = false;
sonic.style.position = "absolute";
sonic.style.left=0;
var rect = sonic.getBoundingClientRect();
function move(){
  lock = false;
  forwardInt = setInterval(forwardFn, 10);
}
function forwardFn(){
  if(!lock&&rect.right<window.innerWidth){
    sonic.style.left = rect.left+10;
    rect = sonic.getBoundingClientRect();
  }else{
    clearInterval(forwardInt);
  }
}
function stop(){
  lock = true;
}
</script>
© www.soinside.com 2019 - 2024. All rights reserved.