Механики для реализации платформера на игровом движке GodotEngine

в 9:39, , рубрики: gdscript, Godot, разработка игр, чисто программирование

Здравствуйте, я разрабатываю на Godot Engine игры примерно 2 года, поэтому решил создать сборник программного кода для реализации базовых механик платформера. Данный сборник рассчитан на новых, в использовании Godot engine, пользователей.

Базовый код

Для того чтобы персонаж подчинялся физике нужно вызвать move_and_slide() в методе _process() или _physics_process().

Во всём последующем коде я буду использовать статическую типизацию.

extends KinematicBody2D
# Пока не ввели поддержку gdscript во вставках кода, придётся обходиться подсветкой python

var velocity: Vector2 = Vector2.ZERO 	# Объявляем переменную ускорения.
					# Нужна чтобы указывать смещение персонажа
					# относительно текущей позиции

func _physics_process(_delta: float) -> void:
	# Ниже будет размещён программный код
	
	
	self.velocity = self.move_and_slide(self.velocity, Vector2(0, -1)) 
	# Перемещает персонажа в направлении указанном в первом аргументе.
	# Второй аргумент - нормаль пола, или же направление вверх.
	# Возвращает новое ускорение с учётом столкновений.

Данного кода будет достаточно чтобы заставить любой объект KinematicBody2D двигаться в зависимости от столкновений c другими объектами, но управлять этим объектом невозможно, тем более в платформерах этот объект по-прежнему не может падать вниз. Для того чтобы объект начал падать, нужно увеличивать значение self.velocity.y на положительное значение. Дело в том, что Godot Engine считает обе координаты из левого верхнего угла в правый нижний в режиме 2D. Для того чтобы объект падал нужно к ускорению прибавлять что-то. Обычно я использую константу GRAVITY, которая задаётся в начале программы. Далее будет представлен код с изменениями для того, чтобы объект падал.

extends KinematicBody2D

const GRAVITY: int = 40
# скорость падения в 40 пискелей будет достаточной, чтобы всё работало как надо


var velocity: Vector2 = Vector2.ZERO 	# Переменная ускорения


func _physics_process(_delta: float) -> void:
	# Ниже вставлять вызовы функций перемещения

	# Ниже можно ничего не трогать
	self.velocity.y += GRAVITY
	# Умножать на _delta не нужно, мы же не используем self.move_and collide
	self.velocity = self.move_and_slide(self.velocity, Vector2(0, -1))
	# И да, объект сам перестанет падать на земле. Здесь не нужно усложнять.

Управление перемещением стоит реализовывать в отдельном методе, чтобы не слишком усложнять 1 метод. Тем более никто не выдержит повторение одного и того же кода в одной статье 33 раза.

Перемещение

Недавно я почерпнул один интересный способ управления персонажем, который стал альтернативой первому освоенному мной способу. Далее я покажу оба способа:

  • Первый, новый для меня способ
  • func move_character() -> void:
    	var direction: float = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left") 
    	# Для определения направления нужно определить разницу между силой нажатия
    	# перемещения вправо(+ по x, от 0 до 1) и влево(- по x, от 0 до 1).
    	# Если вправо = 0, то скорость < 0 и наоборот, а если зажаты влево и
    	# вправо, то направление равно нулю.
    	self.velocity.x = direction * MOVE_SPEED # Умножаем на скорость.
    # вставить const MOVE_SPEED = # Скорость персонажа в пикселях под const GRAVITY
    
  • Второй способ
  • func move_character() -> void: # Гораздо медленнее
    	var direction: float = 0
    	if Input.is_action_pressed("ui_left"):
    		direction = -1
    	elif Input.is_action_pressed("ui_right"):
    		direction = 1
    	else:
    		direction = 0
    	self.velocity.x = direction * MOVE_SPEED
    # вставьте const MOVE_SPEED = #скорость персонажа в пикселях# под const GRAVITY
    

Прыжок

Прыжок реализовывается почти также легко и однозначно, как первый способ перемещения. Для этого нужно создать константу силы прыжка, как скорость перемещения в начале и поставить значение большее чем значение гравитации. Сразу перейдём к программному коду:

func jump() -> void:
	if self.is_on_floor(): # Проверяем, на полу ли игрок.
	# Можно усложнить чтобы ввести двойной, но этот выпуск рассчитан на начинающих
		if Input.is_action_pressed("ui_jump"): # Назначаем в настройках событие
				# нажатия ui_jump и назначаем в него кнопку прыжка.
				# или используем "ui_up"
			self.velocity.y -= JUMP_POWER
# const JUMP_POWER... создаём как и говорил ранее константу силы прыжка около остальных

Осталось только нарисовать карту, добавить коллизии и другое, не относящееся напрямую к основному коду и за игрового персонажа можно будет наконец устроить пробежку по локациям, но об этом всё-таки в другой раз, ведь пока что другие фрагменты кода я не придумал как правильнее объяснить, да и это выходит за пределы темы сообщения.

Автор: Дима Васьков

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js