我想了解戈多引擎的游戏开发。我试着制作一个类似于游戏导弹的移动游戏:

现在我有一个有效的操纵杆。我得到的值是一个规范化的Vector2
var joystick_value = joystick.get_value()但是我不知道如何根据操纵杆值改变飞机的速度。加上设置一些限制的平面可以旋转多少(或最大角度)。
(飞机是KinematicBody2D)
有什么想法吗?
发布于 2021-05-20 13:51:58
速度
如果我们谈论的是KinematicBody2D和velocity,那么我们谈论的是这样的脚本--无论是给予还是接受:
extends KinematicBody2D
var velocity:Vector2 = Vector2.ZERO # pixels/second
func _physics_process(_delta:float) -> void:
move_and_slide(velocity)也许您最好使用speed和direction,而不是velocity。我们也可以这样做:
extends KinematicBody2D
var speed:float = 0 # pixels/second
var direction:Vector2 = Vector2.UP # pixels
func _physics_process(_delta:float) -> void:
var velocity = direction.normalized() * speed
move_and_slide(velocity)如果我们想要一个angle而不是direction向量呢?当然:
extends KinematicBody2D
var speed:float = 0 # pixels/second
var angle:float = 0 # radians
func _physics_process(_delta:float) -> void:
var velocity = Vector2.RIGHT.rotated(angle) * speed
move_and_slide(velocity)旋转
由于我们将进行转向,我们想要旋转的KinematicBody2D根据它的速度。
当然,我们可以从一个angle中得到一个旋转velocity。
extends KinematicBody2D
var velocity:Vector2 = Vector2.ZERO # pixels/second
func _physics_process(_delta:float) -> void:
rotation = velocity.angle()
move_and_slide(velocity)类似地,对于direction向量,或者如果您有angle,您可以直接使用它。
操舵
对于转向,我们将保持速度和变化的角度。所以我们想要我上面展示的speed和angle版本。当然,在轮换时:
extends KinematicBody2D
var speed:float = 0 # pixels/second
var angle:float = 0 # radians
func _physics_process(_delta:float) -> void:
rotation = angle
var velocity = Vector2.RIGHT.rotated(angle) * speed
move_and_slide(velocity)现在我们将有一个来自用户输入的target_angle。就你而言,这意味着:
var target_angle = joystick.get_value().angle()注意,我们不知道旋转的方向是什么。执行target_angle - angle不起作用,因为反过来旋转可能会更短。因此,我们将这样做:
var angle_difference = wrapf(target_angle - angle, -PI, PI)wrapf是做什么的?它将值“包装”到一个范围。例如,wrapf(11, 0, 10)是1,因为它通过1遍历了10,而1 + 0是1。wrapf(4, 5, 10)是9,因为它低于1的5,10 - 1是9。希望这是合理的。
我们是在从-PI到PI的范围内,所以它给出的角度差的方向,是较短的旋转。
我们还需要angular_speed。也就是说,每个时间单位的角度变化有多大(单位是角度/时间)。注意,这与角度的变化不一样(单位是角度)。要进行转换,我们乘以上次以来所用的时间:
var delta_angle = angular_speed * delta啊,实际上,我们需要在angle_difference的方向上。因此,它的sign
var delta_angle = angular_speed * delta * sign(angle_difference)我们不想过分。因此,如果delta_angle的绝对值大于angle_difference,则需要将delta_angle设置为angle_difference
var angle_difference = wrapf(target_angle - angle, -PI, PI)
var delta_angle= angular_speed * delta * sign(angle_difference)
if abs(delta_angle) > abs(angle_difference):
delta_angle = angle_difference我们可以在那里保存到abs的一个电话:
var angle_difference = wrapf(target_angle - angle, -PI, PI)
var delta_angle_abs = angular_speed * delta
var delta_angle = delta_angle_abs * sign(angle_difference)
if delta_angle_abs > abs(angle_difference):
delta_angle = angle_difference把它们放在一起:
extends KinematicBody2D
var speed:float = 0 # pixels/second
var angle:float = 0 # radians
var angular_speed:float = 0 # radians/second
func _physics_process(delta:float) -> void:
var target_angle = joystick.get_value().angle()
var angle_difference = wrapf(target_angle - angle, -PI, PI)
var delta_angle_abs = angular_speed * delta
var delta_angle = delta_angle_abs * sign(angle_difference)
if delta_angle_abs > abs(angle_difference):
delta_angle = angle_difference
angle += delta_angle
rotation = angle
var velocity = Vector2.RIGHT.rotated(angle) * speed
move_and_slide(velocity)最后,一些重构,包括但不限于将代码块提取到另一个函数:
extends KinematicBody2D
var speed:float = 0 # pixels/second
var angle:float = 0 # radians
var angular_speed:float = 0 # radians/second
func _physics_process(delta:float) -> void:
var target_angle = joystick.get_value().angle()
angle = apply_rotation_speed(angle, target_angle, angular_speed, delta)
rotation = angle
var velocity = Vector2.RIGHT.rotated(angle) * speed
move_and_slide(velocity)
static func apply_rotation_speed(from:float, to:float, angle_speed:float, delta:float) -> float:
var diff = wrapf(to - from, -PI, PI)
var angle_delta = angle_speed * delta
if angle_delta > abs(diff):
return to
return from + angle_delta * sign(diff)下面是一个具有角加速度的版本:
extends KinematicBody2D
var speed:float = 0 # pixels/second
var angle:float = 0 # radians
var angular_speed:float = 0 # radians/second
var angular_acceleration:float = 0 # radians/second^2
func _physics_process(delta:float) -> void:
var target_angle = joystick.get_value().angle()
if angle == target_angle:
angular_speed = 0
else:
angular_speed += angular_acceleration * delta
angle = apply_rotation_speed(angle, target_angle, angular_speed, delta)
rotation = angle
var velocity = Vector2.RIGHT.rotated(angle) * speed
move_and_slide(velocity)
static func apply_rotation_speed(from:float, to:float, angle_speed:float, delta:float) -> float:
var diff = wrapf(to - from, -PI, PI)
var angle_delta = angle_speed * delta
if angle_delta > abs(diff):
return to
return from + angle_delta * sign(diff)还有有角度放松的闪亮版本:
extends KinematicBody2D
var speed = 10
var angle:float = 0
var angular_speed:float = 0
export(float, EASE) var angular_easing:float = 1
func _physics_process(delta:float) -> void:
var target_angle = (get_viewport().get_mouse_position() - position).angle()
angle = apply_rotation_easing(angle, target_angle, angular_easing, delta)
rotation = angle
var velocity = Vector2.RIGHT.rotated(angle) * speed
move_and_slide(velocity)
static func apply_rotation_easing(from:float, to:float, easing:float, delta:float) -> float:
var diff = wrapf(to - from, -PI, PI)
var diff_norm = abs(diff)
var angle_speed = ease(diff_norm / PI, easing)
var angle_delta = angle_speed * delta
if angle_delta > diff_norm:
return to
return from + angle_delta * sign(diff)将angular_easing设置为0到1之间的某个值,使其在接近目标角度时开始旋转和减速时加速。值为0时,它不会旋转。其值为1,它以恒定的速度旋转。见https://docs.godotengine.org/en/3.1/classes/class_@gdscript.html#class-gdscript-method-ease。
我测试了这个答案中的代码(使用一些非零值),这是用于鼠标控制的:
var target_angle = (get_viewport().get_mouse_position() - position).angle()它起作用了。
https://stackoverflow.com/questions/67620139
复制相似问题