首先的话如果你玩过之前的原版的马里奥,马里奥会吃蘑菇变大,在那种墙壁跟地面只有一个小的马里奥的位置,如果吃蘑菇变大是不会卡死在哪里,并且可以被挤出。如图
如果你是使用这个godot引擎自带的那个物理功能,改变碰撞体积的时候你就会发现马里奥会卡在墙壁里面,所以这个功能只能自己实现,我的实现比较的简单,复杂的暂时没想到,我使用Rect2来作为碰撞的盒子。给每个需要检测碰撞的对象加上Rect2,到时调用intersects来判断是否有碰撞,这些都是godot自带的功能。以下是基本属性
#游戏中所有物体的基本类
var debug=false
var rect=Rect2(Vector2.ZERO,Vector2.ZERO)
#var visible=true #是否可见
var isCollide=true #是否碰撞
var type=constants.empty #类型
var gravity=0 #重力
var xVel=0 #x轴速度
var yVel=0 #y轴速度
var offsetX=0
var offsetY=0
var collisionShow=false #测试的时候显示是否碰撞
物体的运动主要是马里奥和敌人之类的运动,马里奥的运动有加速度,这个分为x轴和y轴的方向,y轴就是重力,y轴速度需要设置最大速递。那么改变速度就是在每帧的时候,改变速度的值,如果这个值是不断变化的那就是变速运动,如果是不变的就是匀速运动,以下是马里奥走路时的代码,就是按键时改变速度的大小,左边xVel为负,右边为正。
func walk(delta):
if xVel>0 || xVel<0:
ani.speed_scale=1+abs(xVel)/constants.marioAniSpeed
if Input.is_action_pressed("ui_action"):
acceleration=constants.runAcceleration
maxXVel=constants.marioRunMaxSpeed
if fire&&allowShoot:
shootFireball(false)
allowShoot=false
else:
acceleration=constants.acceleration
maxXVel=constants.marioWalkMaxSpeed
allowShoot=true
#跳跃
if Input.is_action_pressed("ui_jump"):
yVel=-constants.marioJumpSpeed
gravity=constants.marioJumpGravity
status=constants.jump
playJumpSound()
# print('walk jump')
return
if Input.is_action_pressed("ui_down") &&big:
startCrouch()
return
elif isCrouch and big:
rect=Rect2(Vector2(-11,-30),Vector2(22,60))
position.y-=14
ani.position.y=0
isCrouch=false
if Input.is_action_pressed("ui_left"):
if xVel>0: #反方向
animation("slide")
acceleration=constants.slideFriction
else:
acceleration=constants.acceleration
dir=constants.left
animation('walk')
if xVel>-maxXVel:
xVel-=acceleration*delta
elif Input.is_action_pressed("ui_right"):
if xVel<0:
animation("slide")
acceleration=constants.slideFriction
else:
dir=constants.right
acceleration=constants.acceleration
animation('walk')
if xVel<maxXVel:
xVel+=acceleration*delta
else:
if dir==constants.right:
if xVel>0:
xVel-=acceleration*delta
animation("walk")
else:
ani.speed_scale=1
status=constants.stand
else:
if xVel<0:
xVel+=acceleration*delta
animation("walk")
else:
ani.speed_scale=1
status=constants.stand
position.x+=xVel*delta
# position.y+=yVel*delta
if !isOnFloor:
ani.stop()
status=constants.fall
pass
具体所有的物体的移动基本上都是这样,可以在代码中发现。那么很重套的一点就是碰撞后,需要对一些物体的位置进行重新调整,这个东西比较的麻烦,我参考一篇文章, developer.ibm.com/technologie… 勉强的找到了解决方案,但是还是不完善。碰撞的时候就是要判断到底是左右的碰撞还是上下的碰撞,这样的话才能决定到时是调整x轴还是y轴。
具体看下map场景里面update的函数。只有调整了位置后,这个物理世界的功能才能是正常的运行下去。其他具体想到在补充。 参考资料:developer.ibm.com/technologie…