Javascript 如何根据增量时间计算跳跃?

Javascript 如何根据增量时间计算跳跃?,javascript,math,canvas,physics,Javascript,Math,Canvas,Physics,我正在尝试用JavaScript制作一个小游戏(没有引擎),我想摆脱基于帧的动画 我成功地为水平运动添加了增量时间(以60或144fps的速度运行良好) 但是我不能让它与跳跃一起工作,高度(或力量)并不总是一样的,我不知道为什么 我已经尝试过(但仍然有完全相同的问题): 在update()结束时传递增量时间:x+=Math.round(dx*dt) 将Date.now()更改为performance.now() 不舍入DeltaY 锁定跳跃高度 我做了一个简单的例子,有两种跳跃类型,高度锁定

我正在尝试用JavaScript制作一个小游戏(没有引擎),我想摆脱基于帧的动画

我成功地为水平运动添加了增量时间(以60或144fps的速度运行良好)

但是我不能让它与跳跃一起工作,高度(或力量)并不总是一样的,我不知道为什么

我已经尝试过(但仍然有完全相同的问题):

  • update()
    结束时传递增量时间:
    x+=Math.round(dx*dt)
  • Date.now()
    更改为
    performance.now()
  • 不舍入
    DeltaY
  • 锁定跳跃高度
我做了一个简单的例子,有两种跳跃类型,高度锁定跳跃和正常跳跃(IDK怎么称呼它)。两者都有同样的问题

const canvas=document.getElementById('canvas'),
ctx=canvas.getContext('2d'),
canvas2=document.getElementById('canvas2'),
ctx2=canvas2.getContext('2d');
//职业选手------------------------
班级演员{
构造器(颜色、ctx、j){
这个.c=ctx
这个。w=20
这个。h=40
this.x=canvas.width/2-this.w/2
this.y=canvas.height/2-this.h/2
这个颜色
//三角洲
这是0.dy=0
//运动
这个重力=25/1000
此值为0.maxSpeed=600/1000
//跳高锁
this.jumpType=(j)?'capedJump':'normalJump'
此参数为0.jumpHeight=-50
//布尔人
this.isOnFloor=false
}
//正常跳跃
法线跳跃(最大值){
如果(!this.isOnFloor)返回
this.dy=-max
this.isOnFloor=false
}
//跳转锁(锁定的最大高度)
capedJump(最大值){
const jh=此高度;
如果(jh>=0)返回
此值为0.dy+=-max/15
如果(jh-this.dy>=0){
this.dy=(jh-this.dy)+jh
此值为0.jumpHeight=0
}否则{
this.jumpHeight+=-this.dy
}
}
更新(dt){
const max=此.maxSpeed*dt,
重力=这个。重力*dt;
//跳跃
此[此.跳线类型](最大值)
//重力
这个.dy+=重力
//上下碰撞(画布边框)
常数y=this.y+this.dy,
h=y+this.h;
如果(y=画布高度){
this.y=canvas.height-this.h
这是0.dy=0
this.isOnFloor=true
此参数为0.jumpHeight=-50
}
//更新Y
this.y+=Math.round(this.dy)
}
画(){
const ctx=this.c
ctx.fillStyle=this.color
ctx.fillRect(this.x,this.y,this.w,this.h)
}
}
const Player=新演员('brown',ctx,false)
const Player2=新演员('blue',ctx2,true)
//生动活泼-----------------------------
设lastRender=0
让currender=Date.now()
函数animate(){
//设置增量时间
lastRender=currender
currender=Date.now()
设dt=currender-lastRender
//画布#1(左)
clearRect(0,0,canvas.width,canvas.height)
背景(ctx)
播放器更新(dt)
Player.draw()
//画布#2(右)
ctx2.clearRect(0,0,canvas2.width,canvas2.height)
背景(ctx2)
Player2.更新(dt)
Player2.draw()
window.requestAnimationFrame(动画)
}
制作动画()
//事件侦听器-----------------------
window.addEventListener('keydown',(e)=>{
e、 预防默认值()
如果(Player.keys.hasOwnProperty(e.code))Player.keys[e.code]=true
})
window.addEventListener('keyup',(e)=>{
e、 预防默认值()
if(Player.keys.hasOwnProperty(e.code))Player.keys[e.code]=false
})
//只是一个用来画背景的函数,这里没什么可看的
功能背景(c){
常量线号=数学地板(画布高度/10)
c、 fillStyle='灰色'
for(设i=0;i
div{
显示:内联块;
字体系列:Arial;
}
帆布{
边框:1px纯黑;
}
跨度{
显示:块;
颜色:灰色;
文本对齐:居中;
}

正常的
锁定

以下是我将如何重构代码:

  • 不要对速度和位置都使用
    dy
    (你似乎正在这样做)。将其重命名为vy,并将其纯粹用作垂直速度

  • isOnFloor
    移动到一个功能,这样我们就可以随时检查与地板的碰撞情况

  • 将跳转功能与实际移动更新分离。只要让他们设置垂直速度,如果球员在地板上

  • 根据移动方向分别执行顶部/底部碰撞检查

  • 不要绕过德尔泰,它会弄乱一些小动作

这些变化到位后,运动行为正确且稳定:

const canvas1=document.getElementById('canvas1'),
ctx1=canvas1.getContext('2d'),
canvas2=document.getElementById('canvas2'),
ctx2=canvas2.getContext('2d');
//全球物理变量
恒重力=0.0015;
常数MAXSPEED=0.6;
常数最大高度=95;
//职业选手------------------------
班级演员{
建造商(C、W、H、J){
//世界大小
this.worldW=W;
this.worldH=H;
//尺寸和颜色
这是w=20;
这个h=40;
这个颜色=C;
//速度
这是0.vy=0;
//位置
this.x=W/2-this.W/2;
this.y=H/2-this.H/2;
//跳高锁
这个参数=J;
此值为0.jumpHeight=0;
}
//将isOnFloor()移动到函数
isOnFloor(){
返回this.y>=this.worldH-this.h;
}
//正常跳跃
normalJump(){
如果(!this.isOnFloor())返回;
this.vy=-MAXSPEED;
}
//跳转锁(锁定的最大高度)
上限跳跃(最大值){
如果(!this.isOnFloor())返回;
this.vy=-MAXSPEED;
此参数为.jumpHeight=max;
}
更新(dt){
//跳跃
如果(本条第1款)
此.cappedJump(最大高度);
其他的
这个.normalJump();
//重力
这.vy+=重力*dt;
这个.y+=这个.vy*dt;