Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Основы создания 2D персонажа в Godot. Часть 2: компилирование образцов, немножко о GDScript, движение и анимация героя

Anna | 15.06.2014 | нет комментариев
В предыдущей статье мы разглядели азы создания нового плана в Godot. И с этими поверхностными умениями дозволено разве что посмотреть demo-версии игр.

Во 2-й части на повестке дня у нас:
1) Экспорт готового плана в бинарные файлы для выбранной архитектуры.
2) Новые анимации. Параметры персонажа.
3) Управление.
3) GDScript. Добродушно пожаловать в подлинный кодинг!
4) Импорт простейших Tilesets.
5) Бонус: разбор устройства простейших задников.

Ну и как традиционно, много картинок!

Компиляция….?

В прошлой статье я упоминал что авторы не предусматривали бинарники для linux x86. На время написания статьи бинарные файлы всё ещё были не готовы. Но экспортировать готовые планы, demo либо легко тесты теснее хотелось. Но что делать, если нет Образцов экспорта? Верно! Скомпилировать их самому!

Переходим в директорию с начальными файлами и компилируем

cd ./godot

Средства отладки:

scons bin/godot target=release_debug tools=no

Позже удачной компиляции переименовываем свежеполученный файл в linux_x11_32_debug

Сам образец экспорта:

scons bin/godot_rel target=release tools=no

Переименовываем в linux_x11_32_release

Запаковываем в zip-архив.

find ./* -name "linux_x11_32_*" -exec zip ./linux_x11_32_templates.zip "{}"  

Скармливаем архив Godot. Вуаля, сейчас дозволено экспортировать план для ОС GNU/Linux всякий разрядности.

Да даже под ОС и разрядности, чудесные от Вашей. Бинарные файлы для Windows без задач сумел завести в wine, основное не позабыть снять либо поставить галочку 64bits, и отключить debugging, если не необходим.

Подробнее про настройки экспорта дозволено почитать на сайте плана на английском языке. Если будет актуально и востребовано, дозволено будет подумать о русской локализации статей и создания русскоязычной wiki по Godot.

Анимация бега и прыжков

В прошлом уроке я предварительно подготовил текстурку со спрайтами бега и прыжка нашего Капитана. Следственно я думаю сделать две анимации jumping и run не составит труда. Я думаю это не сложно будет сделать. Скажу лишь параметры:

run:
Len(s): 0.9
Step(s): 0.1
Looping: yes

jumping:
Len(s): 1
Step(s): 0.1
Animation: хожую на Mario Bros'
var JUMP_VELOCITY=460    #скорость прыжка
var STOP_JUMP_FORCE=900.0    #сила торможения прыжка

var MAX_FLOOR_AIRBORNE_TIME = 0.15    #Время касания, позже которого теснее прыгнуть невозможно. То-есть время, в течении которого дозволено сделать 2-й прыжок. Не меняйте, если не хотите "двойных" либо безмерных прыжков.

var airborne_time=1e20  #время в воздухе

var floor_h_velocity=0.0 

Начинаем функцию integrate_forces. Вот что пронеё сказано в Help:
Измените функцию, Дабы применять свою физику взаимодействий. Ну отлично, этим и займёмся.
PS не знаю как комментировать код дальше. Следственно легко оставлю его так:

Пишем функцию взаимодействия

func _integrate_forces(s):

	var lv = s.get_linear_velocity()
	var step = s.get_step()

	var new_anim=anim
	var new_siding_left=siding_left
Получаем управление

	var move_left = Input.is_action_pressed("move_left")
	var move_right = Input.is_action_pressed("move_right")
	var jump = Input.is_action_pressed("jump")

#Замедление по оси x (торможение)
	lv.x-=floor_h_velocity
	floor_h_velocity=0.0
Поиск земли (проверяем контакт текстуры с полом)

	var found_floor=false
	var floor_index=-1

	for x in range(s.get_contact_count()):

		var ci = s.get_contact_local_normal(x)
		if (ci.dot(Vector2(0,-1))>0.6):
			found_floor=true
			floor_index=x

	if (found_floor):
		airborne_time=0.0 
	else:
		airborne_time =step #время, проведенное в воздухе

	var on_floor = airborne_time < MAX_FLOOR_AIRBORNE_TIME
Процесс прыжка

	if (jumping):
		if (lv.y>0):
#Завершаем прыжок если он завершен (достигли наивысшей точки прыжка)
			jumping=false
		elif (not jump):
			stopping_jump=true

		if (stopping_jump):
			lv.y =STOP_JUMP_FORCE*step
Движение персонажа на земле

	if (on_floor):

		if (move_left and not move_right):
			if (lv.x > -WALK_MAX_VELOCITY):
				lv.x-=WALK_ACCEL*step			
		elif (move_right and not move_left):
			if (lv.x < WALK_MAX_VELOCITY):
				lv.x =WALK_ACCEL*step
		else:
			var xv = abs(lv.x)
			xv-=WALK_DEACCEL*step
			if (xv<0):
				xv=0
			lv.x=sign(lv.x)*xv

		#Проверка прыжка
		if (not jumping and jump):
			lv.y=-JUMP_VELOCITY
			jumping=true
			stopping_jump=false

		#Проверка перемещения и смена анимации

		if (lv.x < 0 and move_left):
			new_siding_left=true
		elif (lv.x > 0 and move_right):
			new_siding_left=false
		if (jumping):
			new_anim="jumping"	
		elif (abs(lv.x)<0.1):
			new_anim="idle"
		else:
			new_anim="run"
Движение персонажа в воздухе

	else:

		if (move_left and not move_right):
			if (lv.x > -WALK_MAX_VELOCITY):
				lv.x-=AIR_ACCEL*step			
		elif (move_right and not move_left):
			if (lv.x < WALK_MAX_VELOCITY):
				lv.x =AIR_ACCEL*step
		else:
			var xv = abs(lv.x)
			xv-=AIR_DEACCEL*step
			if (xv<0):
				xv=0
			lv.x=sign(lv.x)*xv

		if (lv.y<0):
			new_anim="jumping"
		else:
			new_anim="falling"

Перемещение персонажа

	if (new_siding_left!=siding_left):
		if (new_siding_left):
			get_node("sprite").set_scale( Vector2(-1,1) )
		else:
			get_node("sprite").set_scale( Vector2(1,1) )

		siding_left=new_siding_left

Смена анимации

	if (new_anim!=anim):
		anim=new_anim
		get_node("anim").play(anim)

Использование скорости перемещения на земле

	if (found_floor):
		floor_h_velocity=s.get_contact_collider_velocity_at_pos(floor_index).x
		lv.x =floor_h_velocity

Использование гравитации на это всё бесчинство

	lv =s.get_total_gravity()*step
	s.set_linear_velocity(lv)

Блин, это был ужас.

Сейчас всё совместно без комментариев:

extends RigidBody2D

var anim=""
var siding_left=false
var jumping=false
var stopping_jump=false

var WALK_ACCEL = 300.0
var WALK_DEACCEL= 300.0
var WALK_MAX_VELOCITY= 400.0
var GRAVITY = 900.0
var AIR_ACCEL = 300.0
var AIR_DEACCEL= 300.0
var JUMP_VELOCITY=460
var STOP_JUMP_FORCE=200.0

var MAX_FLOOR_AIRBORNE_TIME = 0.15
var airborne_time=1e20
var floor_h_velocity=0.0

func _integrate_forces(s):

	var lv = s.get_linear_velocity()
	var step = s.get_step()

	var new_anim=anim
	var new_siding_left=siding_left

	var move_left = Input.is_action_pressed("move_left")
	var move_right = Input.is_action_pressed("move_right")
	var jump = Input.is_action_pressed("jump")

	lv.x-=floor_h_velocity
	floor_h_velocity=0.0

	var found_floor=false
	var floor_index=-1

	for x in range(s.get_contact_count()):

		var ci = s.get_contact_local_normal(x)
		if (ci.dot(Vector2(0,-1))>0.6):
			found_floor=true
			floor_index=x

	if (found_floor):
		airborne_time=0.0 
	else:
		airborne_time =step

	var on_floor = airborne_time < MAX_FLOOR_AIRBORNE_TIME

	if (jumping):
		if (lv.y>0):
			jumping=false
		elif (not jump):
			stopping_jump=true

		if (stopping_jump):
			lv.y =STOP_JUMP_FORCE*step

	if (on_floor):

		if (move_left and not move_right):
			if (lv.x > -WALK_MAX_VELOCITY):
				lv.x-=WALK_ACCEL*step			
		elif (move_right and not move_left):
			if (lv.x < WALK_MAX_VELOCITY):
				lv.x =WALK_ACCEL*step
		else:
			var xv = abs(lv.x)
			xv-=WALK_DEACCEL*step
			if (xv<0):
				xv=0
			lv.x=sign(lv.x)*xv

		if (not jumping and jump):
			lv.y=-JUMP_VELOCITY
			jumping=true
			stopping_jump=false

		if (lv.x < 0 and move_left):
			new_siding_left=true
		elif (lv.x > 0 and move_right):
			new_siding_left=false
		if (jumping):
			new_anim="jumping"	
		elif (abs(lv.x)<0.1):
			new_anim="idle"
		else:
			new_anim="run"

	else:

		if (move_left and not move_right):
			if (lv.x > -WALK_MAX_VELOCITY):
				lv.x-=AIR_ACCEL*step			
		elif (move_right and not move_left):
			if (lv.x < WALK_MAX_VELOCITY):
				lv.x =AIR_ACCEL*step
		else:
			var xv = abs(lv.x)
			xv-=AIR_DEACCEL*step
			if (xv<0):
				xv=0
			lv.x=sign(lv.x)*xv

		if (lv.y<0):
			new_anim="jumping"
		else:
			new_anim="falling"

	if (new_siding_left!=siding_left):
		if (new_siding_left):
			get_node("sprite").set_scale( Vector2(-1,1) )
		else:
			get_node("sprite").set_scale( Vector2(1,1) )

		siding_left=new_siding_left

	if (new_anim!=anim):
		anim=new_anim
		get_node("anim").play(anim)

	if (found_floor):
		floor_h_velocity=s.get_contact_collider_velocity_at_pos(floor_index).x
		lv.x =floor_h_velocity

	lv =s.get_total_gravity()*step
	s.set_linear_velocity(lv)

PS Дабы заработала гравитация, нужно поставить галочку в Scene -> Project Settings -> Physics2D -> Default Gravity

Импорт TileSets

Рассказать детально про tileset я в данный раз не поспеваю. Могу лишь предложить свою готовую сцену (из моего плана) либо Вам сделать свою из TileSet. Скачать сет дозволено по ссылке ниже, позже чего добавить в план Node TileMap. В настройках к ней нужно добавить готовый TileSet ( TileSet -> Load -> tileset.xml ). Примитивный пол/землю нарисовать сумеете. Как рисовать ярусы, TileSets я детально расскажу в дальнейшем уроке.

Бонус! Добавление задников!

Создаём новую сцену. Добавляем в неё «Node» ParallaxBackground. Называем её parallax_bg и сберегаем как parallax_bg.xml.
К ней создаём ParallaxLayer 4 штуки. Называем их sky, clouds, mount_1, mount_2. Соответственно небосвод, облака, и горы.
Разрешение нашей игры 800×600 (Посмотрите в настройках Scene -> Project Settings -> Display). Следственно ставим всякой «Ноде» параметр Mirroring 800,0 — зеркалирование по оси Y. Поменяйте параметры Scale у «Нод» clouds, mount_1, mount_2 на 0.1,1; 0.2,1 и 0.4,1 соответственно.

К Node sky добавляем спрайт самого неба. Свой я теснее нарисовал предварительно. А вы можете скачать всё по ссылкам ниже.
На рабочей области возникло сразу 2 полоски. Переносим на рабочую область изображения, масштабируем. Видим что изменяя основной спрайт меняется и его зеркальное отражение.

К Node clouds добавляем облачка. Думаю дозволено будет продублировать всякий из 3-х Дабы в результате было 6, mirror дублирует ещё раз, итого у нас будет даже 12 облаков!

Сейчас к Node mount_1 и mount_2 добавим горы. Но слой mount_2 поднимем выше mount_1.

Сберегаем сцену. Открываем stage.xml. И к нашему Stage добавляем через «плюсик» сцену с задниками.

И как традиционно малое видео геймплея:

Маленький FAQ (Будет пополняться):

  • Если персонаж не двигается — проверьте добавили и верно ли добавили клавиши управления
  • Задачи с анимацией — верно ли добавили анимацию. Проверьте looping анимаций idle, run и falling.
  • Персонаж проваливается в пол/проходит через стены, потолки — увеличьте треугольник CollisionPolygon2D.
  • Персонаж Отчасти в текстурах/выше них — поработайте со стрелкой CollisionShape2D

Скачать:

Спасибо, если осилили и дочитали до конца. В случае недочётов пишите в личку. Спасибо, увидимся!

 Источник: programmingmaster.ru
Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB