2D 运动概述

前言

每个初学者都问过“我该如何移动我的游戏角色呢?”根据你正在制作的游戏的风格,可能有特殊的需求,但一般来说,大多数 2D 游戏的运动都基于一组不太多的操作之上。 KinematicBody2D,但这些原则也适用于其他节点类型(Area2D、RigidBody2D)。

场景布置

SpriteCollisionShape2D 两个子节点的 KinematicBody2D 开始. 你可以使用Godot图标(“icon.png”)作为Sprite的纹理或使用其他任何2D图像. 项目 -> 项目设置并选择“键位映射”选项卡。添加以下输入操作(相关详细信息请参阅 InputEvent):

八向移动

在这种情况下, 您希望用户按下四个方向键(上/左/下/右或W / A / S / D)并沿所选方向移动. “8向移动” 意味着游戏角色可以通过同时按下两个键实现斜向移动. 将脚本添加到场景中的KinematicBody2D上, 并添加以下代码: GDScript C#

  1. extends KinematicBody2Dexport (int) var speed = 200var velocity = Vector2()func get_input(): velocity = Vector2() if Input.is_action_pressed("right"): velocity.x += 1 if Input.is_action_pressed("left"): velocity.x -= 1 if Input.is_action_pressed("down"): velocity.y += 1 if Input.is_action_pressed("up"): velocity.y -= 1 velocity = velocity.normalized() * speedfunc _physics_process(delta): get_input() velocity = move_and_slide(velocity)
  1. using Godot;using System;public class Movement : KinematicBody2D{ [Export] public int speed = 200; public Vector2 velocity = new Vector2(); public void GetInput() { velocity = new Vector2(); if (Input.IsActionPressed("right")) velocity.x += 1; if (Input.IsActionPressed("left")) velocity.x -= 1; if (Input.IsActionPressed("down")) velocity.y += 1; if (Input.IsActionPressed("up")) velocity.y -= 1; velocity = velocity.Normalized() * speed; } public override void _PhysicsProcess(float delta) { GetInput(); velocity = MoveAndSlide(velocity); }}

get_input() 函数中, 我们检查四个键盘事件并将它们相加以获得速度向量. 这么做的优点是两个相对的键会彼此抵消, 但是由于两个非相对方向被加在一起, 导致对角线方向移动速度更快. 归一化(normalize) 处理, 就可以防止这种情况, 这意味着我们将速度向量的 长度 设置为 1 , 并乘以所期望的速度. 小技巧 向量数学 看到Godot中向量用法的解释. 注解 场景布置 部分所描述的正确设置了输入操作.

旋转+移动

这种类型的运动有时被称为 “Asteroids式运动”, 因为它类似于经典街机游戏Asteroids的工作方式. 按左/右旋转角色, 而按上/下使得角色在面向的方向上向前或向后. GDScript C#

  1. extends KinematicBody2Dexport (int) var speed = 200export (float) var rotation_speed = 1.5var velocity = Vector2()var rotation_dir = 0func get_input(): rotation_dir = 0 velocity = Vector2() if Input.is_action_pressed("right"): rotation_dir += 1 if Input.is_action_pressed("left"): rotation_dir -= 1 if Input.is_action_pressed("down"): velocity = Vector2(-speed, 0).rotated(rotation) if Input.is_action_pressed("up"): velocity = Vector2(speed, 0).rotated(rotation)func _physics_process(delta): get_input() rotation += rotation_dir * rotation_speed * delta velocity = move_and_slide(velocity)
  1. using Godot;using System;public class Movement : KinematicBody2D{ [Export] public int speed = 200; [Export] public float rotationSpeed = 1.5f; public Vector2 velocity = new Vector2(); public int rotationDir = 0; public void GetInput() { rotationDir = 0; velocity = new Vector2(); if (Input.IsActionPressed("right")) rotationDir += 1; if (Input.IsActionPressed("left")) rotationDir -= 1; if (Input.IsActionPressed("down")) velocity = new Vector2(-speed, 0).Rotated(Rotation); if (Input.IsActionPressed("up")) velocity = new Vector2(speed, 0).Rotated(Rotation); velocity = velocity.Normalized() * speed; } public override void _PhysicsProcess(float delta) { GetInput(); Rotation += rotationDir * rotationSpeed * delta; velocity = MoveAndSlide(velocity); }}

rotation 属性上. Vector2.rotated() 方法, 使它的指向与物体方向相同. rotated() 是一个很有用的向量函数, 你可以在许多情况下使用它, 否则就需要用到三角函数.

旋转+移动(鼠标)

这种运动方式是前一种运动方式的变体. 这次, 方向由鼠标位置而不是键盘设置. 角色将始终 “看向” 鼠标指针. 前进/后退输入保持不变. GDScript C#

  1. extends KinematicBody2Dexport (int) var speed = 200var velocity = Vector2()func get_input(): look_at(get_global_mouse_position()) velocity = Vector2() if Input.is_action_pressed("down"): velocity = Vector2(-speed, 0).rotated(rotation) if Input.is_action_pressed("up"): velocity = Vector2(speed, 0).rotated(rotation)func _physics_process(delta): get_input() velocity = move_and_slide(velocity)
  1. using Godot;using System;public class Movement : KinematicBody2D{ [Export] public int speed = 200; public Vector2 velocity = new Vector2(); public void GetInput() { LookAt(GetGlobalMousePosition()); velocity = new Vector2(); if (Input.IsActionPressed("down")) velocity = new Vector2(-speed, 0).Rotated(Rotation); if (Input.IsActionPressed("up")) velocity = new Vector2(speed, 0).Rotated(Rotation); velocity = velocity.Normalized() * speed; } public override void _PhysicsProcess(float delta) { GetInput(); velocity = MoveAndSlide(velocity); }}

Node2D 中的 look_at() 方法, 使游戏角色朝向给定的位置. 如果没有此函数, 为获得相同的效果, 可能需要像下面这样设置角度: GDScript C#

  1. rotation = get_global_mouse_position().angle_to_point(position)
  1. var rotation = GetGlobalMousePosition().AngleToPoint(Position);

点击并移动

最后一个示例仅使用鼠标来控制角色. 单击屏幕将使游戏角色移动到目标位置. GDScript C#

  1. extends KinematicBody2Dexport (int) var speed = 200var target = Vector2()var velocity = Vector2()func _input(event): if event.is_action_pressed("click"): target = get_global_mouse_position()func _physics_process(delta): velocity = position.direction_to(target) * speed # look_at(target) if position.distance_to(target) > 5: velocity = move_and_slide(velocity)
  1. using Godot;using System;public class Movement : KinematicBody2D{ [Export] public int speed = 200; public Vector2 target = new Vector2(); public Vector2 velocity = new Vector2(); public override void _Input(InputEvent @event) { if (@event.IsActionPressed("click")) { target = GetGlobalMousePosition(); } } public override void _PhysicsProcess(float delta) { velocity = Position.DirectionTo(target) * speed; // LookAt(target); if (Position.DistanceTo(target) > 5) { velocity = MoveAndSlide(velocity); } }}

distance_to() 检查. 如果没有这个检查, 物体在到达目标位置时会 “抖动”, 因为它稍微移过该位置时就会试图向后移动, 只是每次移动步长都会有点远从而导致来回重复移动. rotation 代码可以使物体转向其运动方向. 小技巧 目标 位置可以是任何你想移动到的对象的位置.

总结

你可能觉得这些代码示例可以作为你自己的项目的一个有用的出发点. 请随意使用它们并试验它们, 看看你能做些什么. 2D_movement_demo.zip