Добро пожаловать в официальную документацию Godot Engine — бесплатного движка с открытым исходным кодом для 2D- и 3D-игр, управляемого сообществом! Если вы впервые знакомитесь с этой документацией, мы рекомендуем вам прочитать страницу введения , чтобы получить общее представление о том, что может предложить эта документация.
Оглавление внизу и на боковой панели позволит вам легко получить доступ к документации по интересующей вас теме.Вы также можете использовать функцию поиска в левом верхнем углу.
Вы также можете загрузить копию в формате HTML для чтения в автономном режиме (обновляется каждый понедельник). index.html
верхнего уровня в веб-браузере.
Note
Godot Engine-это проект с открытым исходным кодом,разработанный сообществом добровольцев.Команда разработчиков документации всегда может воспользоваться вашими отзывами и помощью для улучшения учебников и справочников по классам.Если вы чего-то не понимаете или не можете найти в документации то,что ищете,помогите нам сделать документацию лучше,сообщив нам об этом!
Отправьте запрос или запрос на включение в репозиторий GitHub , помогите нам перевести документацию на ваш язык или поговорите с нами на канале #documentation
в чате участников Godot !
Основная документация сайта разбита на следующие разделы:
General
- About
Getting started
- Introduction
- Шаг за шагом
- Ваша первая 2D-игра
- Ваша первая 3D-игра
Tutorials
- 2D
- 3D
- Animation
- Assets pipeline
- Audio
- Best practices
- Editor manual
- Export
- Internationalization
- Inputs
- Ввод и вывод (ввод/вывод)
- Math
- Navigation
- Networking
- Optimization
- Physics
- Platform-specific
- Plugins
- Rendering
- Scripting
- Shaders
- Пользовательский интерфейс (UI)
- XR (AR/VR)
Development
- Compiling
- Engine development
- Editor development
- Форматы файлов Godot
Community
- Contributing
- Asset Library
- Community channels
- Учебники и ресурсы
Class reference
- Godot API
Godot
3.5
-
@GDScript
-
1
-
2
-
3
-
4
-
5
- …
-
818
-
Next
Godot Beginner’s Guide
Project Manager
The first thing you see when opening Godot is the project manager.
You have a list of projects being managed by Godot (including a «favorite» star button to pin projects)
and several buttons for managing projects. To add an existing project,
use the “Scan” feature to search a folder (and its sub-folders) for all projects it can find.
Godot 2.1
projects can’t import into Godot 3.0
without converting the project.
Godot 2.1
has a converter but it may not work well.
Godot 3.0
projects should work in 3.1
, but 3.1
files won’t work in 3.0
.
To create a new project, you need an empty folder. Once you have your folder then click OK. Now «Edit» (load/open) your project.
You can also run your projects from the project manager without launching the editor («Run» feature).
File System
Godot refers to your project folder as «res://» and contains your static game files used to compile your export.
Godot also has another special address prefix «user://» for dynamic data.
Essentially the user directory «user://» is for game saves or generated map data caching.
If you download add-ons from the Godot asset library, they should go to «res://addons/» folder in your project. Organize your project files using folders.
One folder for graphics, one for sounds, one for scripts, whatever makes sense to you.
Godot converts resource files (like images) into its own format, which you can see in the “res://.import” folder.
Resources can be re-imported from the editor by selecting your file in the file browser.
Your import preferences are saved per file in a *.import file (my_image.png.import
for example)
Objects
Node
objects are the main object type you will work with in the editor.
Each scene is built out of nodes and saved to a file (TSCN or “text-scene”).
You can include scenes into other scenes and update them later (Inherit Scene).
You can build up your game parts (player, level, enemy, enemy spawner) and combine them in different ways.
Inside a Node
you have properties and functions.
They also have signals for calling functions when an event happens.
Functions control game logic by editing properties or calling engine functions.
Objects (a Node is a Reference which is an Object) inherit all the properties and functions of their parent object.
Node2D
has all the info and tools available in
Node
,
because Node2D
is a child of Node
.
A common example for signals is when using a Timer
node.
The «timeout» signal calls a function when the timer is up.
You can define a signal in your script, then call emit_signal
when the signal’s event happens.
Signals are fast, but you have to choose where to call emit_signal
.
Example: Using a timer.
extends Node onready var my_timer = Timer.new() func _ready(): my_timer.wait_time = 0.5 my_timer.connect( “timeout”, self, “_timer_done” ) #connect signal self.add_child( my_timer ) my_timer.start() func _timer_done(): print(“Timer finished.”) #print to console output (seen in editor)
Example: Creating a signal.
extends Node2D signal got_hurt (damage) onready var hitpoints = 10 setget set_hitpoints func set_hitpoints( new_hp ): var diff = new_hp - hitpoints if diff < 0: emit_signal("got_hurt", diff) hitpoints = new_hp
SceneTree
Making a game in Godot begins with creating a scene. Inside a scene you assemble Nodes,
and each scene begins with exactly one Node (of your choosing). Each node can have many children (as many as you want).
This creates what we call a “tree” of nodes, and thus the name SceneTree
.
When making a 2D scene your top node should be a Node2D
or child of
Node2D
.
When making a 3D scene start with a Spatial
type node.
Control
nodes (user interface widgets) are 2D
but work different from Node2D
objects.
The two work best when separated (you can separate with a CanvasLayer
as child node).
You can use 2D nodes in your 3D scene but they should be at the bottom of your node list (so they draw on top).
When you run your game you start with running a scene.
It runs inside the SceneTree
object,
which holds the node tree of your scene. Any GDScript attached to your scene can access the
SceneTree
by calling get_tree()
.
In 2D: the engine draws sprites to screen in order.
The Sprite node at the top of the SceneTree is drawn first, and at the end of the node tree Sprites are drawn last.
Background sprites go at the top of the list of nodes in your Godot editor. UI nodes (Control) go below Node2D objects.
Sometimes you want sprites to switch order, to change which is drawn on top.
If you want to order them based on their position.y value,
then make them children (y_sort_node.add_child()
) of a YSort
node.
You can access nodes belonging to a group from the SceneTree.
Use the code get_tree().get_nodes_in_group("enemies")
to get all nodes in group «enemies».
-
2D objects use X and Y positioning:
- X positive (+) is right; negative (-) is left.
- Y positive is down; negative is up.
-
3D objects use X, Y, and Z positioning:
- X and Z form the floor plane. (Left, right, forward, backwards)
- Y positive is up; negative is down.
GDScript
GDscript is Godot’s default coding language.
You save it to a text file ending with .gd or save it built-in to any
Node
object.
The script has to start with extends Node
or replace «Node» with the type you’ll attach the script to.
Leaving out «extends» is the same as extends Reference
which is a data type you don’t add to the
SceneTree
.
Link: @GDScript Built-in Functions
Native Code
GDScript is great, but it isn’t 100% the fastest option. When you need extra speed, you can use C++ as a Native module.
For 2D, GDScript can manage running the whole game. For 3D you might need C++ for your dynamic world building code (or whatever intensive code you’re making).
The benefits gained from using GDScript should outweigh the minor speed loss.
Signals and groups are tools to help you build efficient scenes.
Physics
The physics engine nodes are:
-
StaticBody
— Non-moving solid physical obstacle. -
RigidBody
— Moving physical object. Managed by engine. -
KinematicBody
— Moving physical object. Managed by you the coder. -
Area
— Non-obstacle. Detects overlap with other physics bodies or areas. -
VehicleBody
— Simulate a moving vehicle with wheels. Includes drive and steering wheel functionality. -
RayCast
— Check along a directed line for any physics object; fast and effective check.
VehicleBody
is only available in 3D. Godot 3.1 will also include a PhysicalBone
physics object for 3D.
Physics objects need to have a CollisionShape
(or CollisionPolygon
) as a child node.
This tells the engine how big and what shape the object is.
All physics objects have collision layers and collision masks.
The collision layer represents which layer(s) the object is on.
The mask represents which layers the object collides with.
So an object with layer 1 and mask 2 will collide with objects on layer 2,
but not layer 1 (so no collision with other instances).
Note that you only need KinematicBody
to move objects that collide.
Otherwise you can change the position/translation property to move the object.
For smooth movement you can use a Tween
to control the transition.
For the next code you need to define the “move_left” and “move_right” actions.
The «Input Map» is in project settings. You also need some StaticBody2D
nodes to collide with.
Example: Move a side-scroll platform character using action inputs.
extends KinematicBody2D const GRAVITY = Vector2(0,98) const SPEED = 500 onready var direction = Vector2(0,0) func _process(delta): if Input.is_action_pressed(“move_right”): direction.x = 1 elif Input.is_action_pressed(“move_left”): direction.x = -1 else: direction.x = 0 func _physics_process(delta): move_and_slide( (direction * SPEED) + GRAVITY )
NOTE: When using KinematicBody’s move_and_collide
function, you should multiply the argument by delta
When using move_and_slide
you should NOT multiply by ‘delta’ because the ‘slide’ functions manage this automatically.
Link: More physics info.
Node2D
When building a 2D scene you use Node2D
objects.
There are many nodes based on Node2D
such as
Camera2D
, RigidBody2D
, etc.
To display an image you’ll use a Sprite
or an
AnimatedSprite
node.
A Sprite
accepts one image at a time.
An AnimatedSprite
has a series of animation tracks that can each hold many images.
You can control the view of your scene using a Camera2D
.
For 2D tiled games you might want to enable “Pixel Snap” from your project settings.
Example: Object movement without using physics.
extends Sprite const SPEED = 200 onready var direction = 0 func _input(event): if event is InputEventKey: if event.pressed: match event.scancode: KEY_LEFT: direction = -1 KEY_RIGHT: direction = 1 else: match event.scancode: KEY_LEFT, KEY_RIGHT: direction = 0 func _process(delta): position.x += direction * SPEED * delta
Link: InputEvent
Here I defined a constant (can’t change value) called SPEED.
I used the “onready” keyword to initialize the variable when the Node becomes “ready”.
For input, make sure the InputEvent
is an InputEventKey
(so I know I can call event.scancode
or event.pressed
).
Then, if pressed I set the direction, or else set the direction variable to zero.
In _process
I move the X position of the ‘Sprite’ based on the direction they want to go (1 or -1) multiplied by SPEED and delta
.
The Sprite
inherits position
from Node2D
. The delta
variable is a number for how much time passed between engine calls to _process
. Multiply this by your speed so that movement is consistent with time itself. This makes movement consistent between different computers too.
The same in 3D (Spatial
nodes) uses the translation
property instead of position
.
Control
Control
nodes are for dynamic user interfaces.
They don’t interact with Node2D
objects by default. You can still access info from both, and relate them yourself. A Control
has rect_position
and a Node2D
has position
. If you need a Sprite
or something equal for your Control
nodes, try a TextureRect
. Most Control
nodes also support displaying an image icon next to text (or instead of text). Control
nodes are good at stealing mouse focus. You can change mouse event behavior from the inspector.
Tilemap
You can build your game world out of a Tilemap
(2D) or a Gridmap
(3D).
You can also write your own level creation/management nodes.
Tilemap
and Gridmap
each use a compiled Tileset (2D) or MeshLibrary (3D) to build their tiles.
A tileset (or meshlib) only contains some types of data.
These include Sprite
(Mesh
),collision shape, and navigation mesh.
Creating a Tileset
-
Link: Old Method (also applies to MeshLibrary (3D))
-
Link (youtube video): New Method
Linear Algebra
Linear algebra is where Vectors and Matrices (matrix) come from.
It lets us do complex things fast and simple.
This is good for realtime computing, and thus good for video games.
Having knowledge of vectors and how they work is usually enough for a 2D game,
but you might want to learn about matrices when working with 3D.
Vectors can have 2 or more components, but for games we’re only interested in 2-component and 3-component vectors.
Godot provides us with Vector2
and Vector3
integrated data types.
There are also the Transform2D
and Transform
objects.
Call the xform
function to transform your vectors according to your Transform
.
Link: Godot Math Docs
Всем привет!
Давненько от меня не было слышно никаких новостей, тем более и повод соответствующий, наконец-таки поделится своими наработками по Godot, и уже аж версии 3!
В этом вводном материале мы рассмотрим сам редактор, базовые элементы и немного затронем скрипты.
Скачать редактор можно как с официального сайта, так и установив через клиент Steam (кому как удобнее).
Я буду использовать версию из Steam, так как она позволяет одновременно работать как с версией 3, так и запускать версию 2.1. Забегая вперёд скажу, что в третьей версии очень многое поменялось, некоторая логика, вызовы в скриптах и т.д. Но обо всём по порядку.
После запуска Godot, вы увидите окошко со списком доступных проектов. Их можно как запустить сразу, нажав кнопку «Запустить», так и открыть в редакторе, соответственно кнопка «Редактировать».
Примеры проектов можно скачать с сайта Godot. Однако сразу обращу ваше внимание, что проекты, написанные под Godot 2.1 с большей долей вероятности не заработают из отличия в скриптах. Поэтому, при скачивании, обратите внимание на версию.
После того как вы скачали и распаковали архив в какую-нибудь папку на диске, её нужно подключить к редактору. Нажимаем кнопку «Импорт», указываем путь, и нажимаем «Импортировать и Редактировать», после чего наши демо-проекты появятся в списке доступных.
Так же демо-проекты можно посмотреть, выбрав вкладку «Шаблоны». Выбираем заинтересовавший нас проект, например, «2D Particles Demo». Нажимаем на название, и во вновь открывшемся окне устанавливаем (кнопка «Установить»).
По сути можно сразу посмотреть проект в действии, кнопкой «Запустить». Однако может быть ситуация, как с «2D Particles Demo», когда для просмотра нужно его сначала всё-так открыть в редакторе для импорта некоторых компонентов.
Думаю, с демо-примерами вы разберётесь самостоятельно, а мы создадим новый проект, нажав соответствующую кнопку. В вновь открывшемся окне у нас спросят название проекта и где мы хотим его разместить (пустая папка).
Несмотря на то, что редактор Godot русифицирован, я всё же рекомендую задавать имена файлов латинскими буквами, дабы избежать проблем в будущем и не ломать голову почему у меня вылетают непонятные ошибки или вовсе не грузится, например, картинка.
После создания проекта, у нас откроется сам редактор. Он состоит из нескольких блоков: Блок «Файловая система» — здесь располагаются блок навигации (дерево папок) и собственно все файлы нашего проекта; Блок «Сцена» — это структура (дерево) всех наших элементов на текущей сцене; Блок «Инспектор» — позволяет редактировать свойства и параметры выбранного элемента в дереве блока «Сцена».
Ещё есть блоки «Импорт» и «Узел», но мы пока рассматривать их не будем.
По центру расположен сам редактор, в зависимости от того что мы хотим редактировать он может отображать 2D-сцену, 3D-сцену, редактор скриптов, а также список доступных модулей (плагинов для самого Godot) — «AssetLib». Переключаются разделы нажатием на соответствующие надписи в верхней части.
В нижней части редактора есть ещё один блок, который по умолчанию скрыт, и открывается только при возникновении каких-либо ошибок или отладке. Он состоит из четырёх вкладок: «Вывод» — различная информация самого редактора, в том числе ошибки; «Отладчик» — используется для отладки скриптов; «Аудио» и «Анимация» мы пока рассматривать не будем.
Для того, чтобы скрыть это блок опять, достаточно нажать ещё раз на название раздела («Вывод», «Отладчик», «Аудио» или «Анимация»).
Но вернёмся к редактору, по своей сути все элементы Godot это сцены, их можно сохранять, изменять тип, встраивать в другие сцены и т.д. Мы будем работать с 2D-сценами и использовать соответствующие для них типы элементов.
Сначала создадим простой компонент, который будет у нас в будущем игроком. Для этого в блоке «Сцена» нажимаем плюс и во вновь открывшемся окошке ищем тип «KinematicBody2D» с иконкой в виде человечка. Его можно сразу найти задав фильтр в строке поиска или найти открыв дерево со списком компонентов: Node → CanvasItem → Node2D → CollisionObject2D → PhysicsBody2D → KinematicBody2D. После чего нажимаем кнопку «Создать».
По своей сути мы могли бы выбрать и обычный элемент «Node2D», но у «KinematicBody2D» есть ряд свойств, которые нам понадобятся в будущем.
После добавления элемента на сцену, рядом с названием появится желтый восклицательный знак, нажав на пиктограмму которого мы получим предупреждение:
Дело в том, что для того что бы наш игрок смог взаимодействовать с пространством у него должна быть задана область взаимодействия, ну и заодно нужно задать внешний вид игрока.
Для начала переименуем наш компонент «KinematicBody2D» в «player». В последствии это имя будет использовано при отображении элементов на игровой сцене. (Для этого достаточно кликнуть на названии и откроется поле для ввода нового имени).
Теперь необходимо добавить компонент, отвечающий за область взаимодействия или если быть точнее область обнаружения столкновений (Collision). Если у нас простой элемент или мы не хотим заморачиваться с высокой точностью, то подойдёт «CollisionShape2D». Если же у вас сложный, многогранный объект, то можно выбрать «CollisionPolygon2D».
Я не буду усложнять материал, поэтому просто добавим компонент «CollisionShape2D». Выбираем наш элемент «player», нажимаем плюс и выбираем: Node → CanvasItem → Node2D → CollisionShape2D.
И вновь получаем предупреждение с желтым восклицательным знаком:
Дело в том, что компонент мы добавили, а сама область так и не задана. Но прежде чем мы её добавим, нам понадобится ещё один элемент — Sprite. Это будет внешний вид нашего персонажа.
Выбираем узел «player», нажимаем плюс и добавляем: Node → CanvasItem → Node2D → Sprite:
Как видите, в разделе «Недавние», появились наши ранее добавленные элементы. Гораздо быстрее, нежели искать однотипные элементы каждый раз.
Теперь переключимся в блок «Файловая система», и нажав правую кнопку мыши на «res://» выберем пункт «Новая папка». В открывшемся окне введём название «images», здесь будут изображения, которые мы будет использовать в дальнейшем:
Откроем эту папку в проводнике (правая кнопка мыши на «images» и пункт «Просмотреть в проводнике». Теперь сюда нужно скопировать картинку для нашего игрока в формате PNG.
Хочу обратить ваше внимание, что PhotoShop очень любит «пихать» в файлы системную информацию, и в частности задавать не совсем корректный «Color profile». Из-за чего Godot начнёт ругаться на некорректный формат «sRGB profile»:
В принципе вы конечно можете игнорировать данное сообщение, но я всё рекомендую очистить весь лишний «мусор». Сделать это можно, например, с помощью программы «XnView MP». Для этого на нашей картинке нажимаем правую кнопку мыши и в открывшемся меню выбираем «Пакетная обработка»:
На вкладке действия нажимаем «Добавить действие» → Изображение → Удаление метаданных. Отмечаем все чекбоксы (галочки) и нажимаем преобразовать:
После чего редактор Godot успокоится и перестанет ругаться на некорректный профиль. Честно сказать я не знаю с чем это связано, ибо такая же ситуация была и с версией 2.1. Возможно в будущем я разберусь подробнее с этим моментом.
Но вернёмся в наш редактор и убедимся, что изображение нашего игрока находится на месте. Теперь это изображение нужно добавить к компоненту Sprite. Для этого выберем этот элемент в разделе «Сцена», и переключим своё внимание на раздел «Инспектор». В данный момент нас интересует свойство «Texture». Изначально там указано значение . Нас интересует «Новый ImageTexture». Можно выбрать его из меню, а можно сразу перетащить нашу картинку из блока «Файловая система» и отпустить над свойством «Texture»:
После чего увидим, что в главном окне редактора у нашего «player» появилась форма в виде нашей картинки:
Сразу хочу обратить ваше внимание вот на какой момент. Если вы планируете использовать графику в стиле pixeart, то вам вполне вероятно понадобится отключить сглаживание. В противном случае ваша картинка будет «мутная».
Для этого, в блоке «Инспектор», выбираем нашу текстуру, и в открывшемся меню выбираем пункт «Редактировать»:
В разделе «Flags» снимаем все чекбоксы (галочки) и убеждаемся, что грани нашего кубика больше не сглаживаются.
Для того, чтобы не повторять эту процедуру каждый раз, откроем блок «Импорт», снимем чекбокс (галочку) напротив «Flags». Затем нажимаем на «Предустановка..» и выбираем «Установить по умолчанию для ‘Texture’»:
Теперь при импорте новых картинок редактор не будет выставлять флаги.
Вернёмся к блоку «Сцена» и добавим наконец область взаимодействия. Для этого выберем наш компонент «CollisionShape2D» и блоке «Инспектор» зададим свойство «Shape» в виде «Новый RectangleShape2D»:
Просто квадратная область. Поскольку изображение нашего игрока всего 32 на 32 точки, то область задать будет несколько проблематично:
Но можно с помощью колеса мыши приблизить изображение и выставить область таким образом, чтобы она покрывала весь спрайт персонажа:
Можно пойти несколько другим способом и не мучатся, тягая мышкой точки. Открываем в блоке «Инспектор» раздел «Transform» и задаём свойство Scale:
Честно сказу в редакторе Godot очень много непонятных моментов, например, почему свойство именно scale (масштаб), а ни, например, просто дать возможность указать точный размер области. Или глобальная область первичного объекта (в данном случае «player») она равна 64 на 64 точки и изменить её нельзя, даже если у нас спрайт размером меньше. Честно скажу это весьма неудобно в некоторых случаях. А на англоязычных форумах предлагают модифицировать основные классы прямо внутри Godot и задавать там размер. К сожалению, с ходу у меня это не получилось сделать.
Но вернёмся к нашему игроку. По сути базовые настройки завершены, и мы можем сохранить нашу сцену уже как компонент «player». Для этого в блоке «Файловая система» создадим ещё одну папку и назовём её «elements». Теперь в главном меню редактора выберем «Сцена» → «Сохранить сцену как…» и выбрав нашу папку «elements» сохраним файл «player.tscn»:
Теперь нам нужно создать главную игровую сцену. Для этого в том же главном меню «Сцена» выбираем пункт «Новая сцена». В блоке «Сцена» нажимаем плюс и выбираем компоненту «Node»:
По сути это базовый компонент, прародитель всех остальных и нам от него ничего не потребуется (пока). Единственное, что переименуем его в «gamescene». Теперь нам на игровую сцену нам нужно добавить нашего игрока. Для этого кликнем на «gamescene» и затем нажмём на пиктограмму в виде звена цепи (рядом с плюсом) и во вновь открывшемся окне выберем: «elements → player.tscn».
Как не трудно догадаться звено цепи прикрепляет к сцене элемент в виде нашего игрока. Причём если мы потом захотим что-либо изменить в «player», то этим изменения так же отобразятся на игровой сцене. Это очень удобно, так как таких элементов может быть очень много на сцене и отдельно редактировать каждый из компонентов очень утомительно.
Компонент «player» можно спокойно перемещать мышкой в нужное место, но мы пойдём немного дальше и включим сетку и сделаем перемещение дискретное. Для этого в основном блоке редактора нажмём обзор и включим «Показать сетку». По сути её можно в любой момент включать/отключать с помощь горячих клавиш — G:
Теперь настроим размер ячеек кратное нашему игроку. Для этого нажмём на пиктограмму в виде трёх вертикальных точек и выберем пункт «Настроить привязку…»:
И укажем размер ячеек 32 на 32:
Теперь надо активировать привязку нажав на пиктограмму в виде магнита:
Так же можно переключать это режим с помощью горячей клавиши — S.
Как мы видим на скриншоте выше наш игрок попадает на пересечение ячеек и это не есть совсем хорошо:
Для того что бы наш персонаж был чётко посредине ячейки, откроем его на редактирование нажав на пиктограмму в виде «Хлопушки-нумератора»:
Теперь изменим свойства позиционирования в блоке «Инспектор», сначала для Srpite:
В подразделе «Offset» снимаем чекбокс (галочку) рядом со свойством «Centered».
Затем у элемента «CollisionShape2D» в подразделе «Position» задаём смещение (16, 16) на половину размера нашего спрайта:
Сохраняем сцену (Ctrl+S) с «player.tscn» и переключаемся на нашу игровую сцену:
Проверяем, что наш персонаж точно по середине ячейки, хоть и общий контур больше (64×64) и сохраним игровую сцену. Создадим ещё одну папку «scenes» в «res://» и сохраним туда «gamescene.tscn».
Теперь самое время проверить всю нашу конструкцию в действии. Для этого выберем в верхнем меню справа нажмём кнопку «play» или горячую клавишу — «F5».
Редактор сообщит, что не выбрана главная сцена и предложит её указать. Нажимаем «Выделение» и выбираем «gamescene.tscn»:
После чего откроется окно с игрой, и мы увидим наш квадратик с персонажем.
Теперь попробуем задать управление с помощью клавиатуры и рассмотрим базовые элементы скриптов. Сначала нам нужно задать сами клавиши.
Для этого откроем в главном меню: «Проект» → «Параметры проекта». Во вновь открывшемся окне на закладке «Список действий» мы увидим большой список. Можно использовать уже готовые элементы списка, но мы создадим четыре своих: «player_up», «player_down», «player_left», «player_right». Вставляем поочерёдно названия и нажимаем кнопку «Добавить»:
Это будут четыре события, по каждой стороне перемещения. Теперь надо задать условия, при котором будет происходить сработка события. Нажимаем плюс и выбираем «кнопка», после чего откроется окошко и нам предложат нажать кнопку на клавиатуре. По такому же принципу можно задать кнопку у геймпада или мыши:
Я буду нажимать кнопки управления курсором, но вы можете назначить их по своему усмотрению, например, WASD. В результате чего должна получится такая вот картина:
Теперь создадим ещё одну папку в разделе «res://» для скриптов — «scripts». После чего открываем на редактирование нашу сцену «player.tscn». Выбираем главный узел «player» и нажимаем пиктограмму в виде свитка с зелёным плюсиком или же можно нажать правую кнопку на узле «player» и выбрать «Прикрепить скрипт»:
Во вновь открывшемся окне оставляем все настройки по умолчанию, и изменим лишь наш путь к расположению скрипта, дабы не делать в будущем свалку:
После нажатия кнопки «Создать» откроется редактор с нашим скриптом, с шаблоном по умолчанию. Несколько слов о самом редакторе:
- В области 1 находятся открытые скрипты проекта, в данный момент он один — player.gd;
- В области 2 находится список функций данного скрипта. На этапе создания она тоже одна это _ready();
- В области 3 (начало скрипта) указан класс на базе которого основан данный скрипт. В данном примере это KinematicBody2D. У каждого класса свой функционал и надо быть внимательным.
- В области 4 перечисляются локальные переменные доступные внутри этого скрипта. Несмотря на то, что тип переменной не указан явно (var), они типизированы и для того, чтобы склеить строку и число, придётся привести к одному типу. Например “lives: “ + String(10);
- Далее в области 5 и 6 следуют функции. У зарезервированных функций имена начинаются со знака подчёркивания. В выше указанном примере функция _ready() вызывается 1 раз когда элемент добавляется на сцену, или проще говоря инициализируется. Если функция пустая, для того чтобы не было ошибки вставляется «заглушка» в виде вызова pass. Функция _process вызывается каждый фрейм (кадр), но только если предварительно была разрешена командой set_process(true) в функции _ready(). Причём при каждом вызове функции _process в переменной delta будет некое число (прирост) с момента предыдущего вызова. Это значение можно использовать как таймер для каких-либо действий в будущем;
Проведём небольшой эксперимент. Разрешим вызов set_process(true), а в функции _process добавим вывод в консоль отладки значение delta в консоль:
Теперь после запуска проекта (F5) мы получим кучу быстро сменяющихся цифр:
Ура! Всё работает! Но нам нужно добавить управление нашим кубиком. Сразу скажу, что приведённый метод не очень хорош, но как базовая демонстрация вполне сгодится. В моих проектах используется более корректный опрос, но он несколько сложен, а мне бы не хотелось перегружать и так достаточно большую статью. Итак, для того, чтобы сработал наш опрос кнопок необходимо на этапе инициализации добавить несколько переменных:
var direction = Vector2()
var speed = 0
const MAX_SPEED = 400
var velocity = Vector2()
- direction — это двумерный вектор направления в какую сторону будет двигаться наш персонаж: (-1,0) влево, (1,0) вправо, (0,-1) вверх, (0,1) вниз. Возможны комбинации, например, для движения по горизонтали вверх и влево (-1,-1);
- speed — текущая скорость перемещения нашего персонажа, изначально равно 0 (он стоит);
- MAX_SPEED — константа, максимальная скорость с которой будет двигаться персонаж;
- velocity — ещё одни двумерный вектор, в нём хранится текущее направление движения с учётом скорости;
Теперь опишем функционал в _process:
Инициализируем(сбрасываем) направление движения (0,0):
direction = Vector2()
Теперь опрашиваем события для кнопок влево/вправо:
if Input.is_action_pressed("player_left"):
direction.x = -1
elif Input.is_action_pressed("player_right"):
direction.x = 1
Если одна из них нажата задаём горизонтальное направление.
Повторяем эту же процедуру для вертикального движения:
if Input.is_action_pressed("player_up"):
direction.y = -1
elif Input.is_action_pressed("player_down"):
direction.y = 1
Если вектор движения задан (не равен 0,0), то выставляем максимальную скорость движения, в противном случае она равна нулю:
if direction != Vector2():
speed = MAX_SPEED
else:
speed = 0
Теперь рассчитываем движение с учётом направления и скорости:
velocity = speed * direction.normalized()
Ну и далее собственно заставляем двигаться сам объект:
move_and_slide (velocity)
В результате чего у нас должна получится вот такая картинка:
А после запуска наш квадратик гоняется по экрану с помощью клавиш курсора.
На этом собственно всё. Не хочу сильно перегружать вводную часть. В следующий раз мы рассмотрим столкновения и более подробно поговорим о GDScript.
Удачи в ваших начинания, а готовый проект можно скачать по ссылке.
Уроки создания игр — SKANERSOFT
канал на YouTube
1
Введение в разработку
00:00 Краткий анонс того, что будет происходить в видео. Нарезка моментов.
00:20 Введение и выбор темы для проекта. Для выбора темы используется генератор случайных фраз, который выдал тему про шампунь. Сеттинг определяется следующим образом: главный герой находится в некоем альтернативном мире (предположительно, это его сон), в котором ему предстоит отстреливаться от монстров с грязными волосами шампунем (ох уж этот генератор случайностей).
02:40 Моделирование объектов окружения, оружия и врагов. Для моделирования используется программа Blender 3D версии 2.8, используются простые модели без текстур, оформленные материалами с плотной заливкой.
2
Создание игрового уровня
6:20 Перемещаемся в игровой движок Godot Engine, создаём новый проект. Для проекта определяем рендер OpenGL ES 2.0 для большей совместимости. Также такой проект удобно портировать для WEB.
6:46 Поскольку игра подразумевает переход между уровнями, рассмотрим шаблон проектирования, при котором данную возможность довольно просто реализовать. Данный подход не требует навыков проектирования и моделирования ситуаций. Попутно создаём структуру папок и необходимый набор базовых сцен. Определяем синглтон (глобальный объект), подключаем его к проекту, а также конфигурируем его.
8:30 Программируем загрузку уровня.
9:00 Переносим объекты, смоделированные в Blender, в игровой проект. Для экспорта используется формат glTF 2.0, который поддерживается как движком, так и пакетом моделирования.
9:25 На основе моделей создаём игровые объекты, настраиваем материалы, пока без поведения. Также масштабируем все объекты так, чтобы они имели нормальный размер относительно игрока и друг друга, пропорции сохраняем. Расставляем объекты, получая приблизительный вид будущего уровня для игры.
11:24 Добавляем объект Environment, отвечающий за окружение. Настраиваем боковое освещение и убираем скайбоксы. Настраиваем Glow эффект для игрового мира. Создаём объекты, отвечающие за освещение, настраиваем тени.
3
Создание персонажа
13:50 Теперь необходимо создать объект игрока, отвечающий за взаимодействие с игровым миром. Этим объектом будет управлять человек за компьютером или телефоном (планшетом). Объект состоит из капсюля и камеры — идеальное сочетание объектов для игр от первого лица. Для камеры используем стандартную «интерполированную камеру», которая будет вращаться плавно, создавая приятный эффект.
16:35 Модифицируем комнату, в которой происходит действие.
17:30 Программируем поведение игрока. Управление осуществляется мышью и клавиатурой. Соответственно, необходимо обработать поступающие команды. Godot позволяет сделать это очень просто.
21:00 Настраиваем перемещение по миру при помощи клавиш, задействуя стандартный механизм действий движка. Клавиши настраиваются через настройки проекта. В коде проверяем только срабатывание действий.
25:37 Обрабатываем клавишу паузы и условия выходы из игры. Также обрабатываем мышь и скрываем её в игровом процессе, отображаем только в меню паузы или при выходе в меню.
26:40 Включаем тени от источников света и настраиваем их отображение.
4
Создание вражеских персонажей
27:43 Переходим ко вражескому объекту. Говорим о локальных осях, настраиваем материалы объекта. Добавляем поведение объекту: враги будут двигаться к игроку, пока не приблизятся на удобное расстояние, постоянно выстреливая изо рта светящимися шарами, убивающими игрока. При приближении игрока они должны отъезжать от него, чтобы сохранять нужное расстояние.
31:50 Программируем объект, генерирующий вражеские объекты. Этот объект будет порождать их на уровне, пока не будет уничтожен сам. Таким образом, чтобы пройти уровень, в первую очередь требуется уничтожить объекты, генерирующие врагов. Полное их уничтожение гарантирует переход на следующий уровень. Враги генерируются по таймеру.
5
Программирование боя
35:37 Добавляем игроку оружие. Это бутылка шампуня. Позиционируем его правильно в камере. Так же добавляем прицел, чтобы игрок мог целиться.
37:39 Теперь надо разработать то, чем бутылка шампунем будет стрелять. Это будет поток из капель, который при движении очень походит на струю. Для организованного движения шариков необходимо задать их поведение. Это делается для каждого шарика. Поток будет имитировать гравитацию и инерцию. Выстрелы происходят по левой кнопке мыши, так что механизм обработки делаем такой же, как и раньше. При прикосновении пуль к чему-либо, целесообразно их уничтожать. Обработаем и это.
46:12 Переходим к обработке пуль и реакции объектов на них. Помимо того, что пули уничтожаются, они должны как-то влиять на то, во что они попадают. Соответственно всё, что нужно, — настроить обработчики у нужных объектов.
47:41 Добавляем возможность стрельбы вражеским объектам. За основу берём настроенный ранее механизм стрельбы для шампуня. Меняем лишь цвет и немного поведения. После этого немного меняем направление стрельбы, чтобы вражеские пули всегда летели в камеру, усиливая эффект устрашения.
50:54 Конфигурируем глобальный объект и некоторые параметры реакции игрока и врагов. Такая калибровка происходит на протяжении первых этапов разработки практически всегда.
52:12 Теперь на 2D слое делаем визуализацию попадания пули в игрока. Делаем это при помощи заполнения экрана красным и плавным исчезанием заливки. Данный эффект помогает идентифицировать попадание, даже когда оно происходит со спины.
6
Программирование технической части
54:05 Переходим к настройке достижения цели уровня. Для этого определяем механизм достижения какого-то числового счёта. При создании врагов мы будем запоминать их количество на уровне, при уничтожении проверять, сколько было убито. Как только убиваем последнего, активируется механизм отпирания двери на следующий уровень. Визуально на двери это отобразится путем смены красного цвета лампы на зелёный.
58:18 Добавляем сцену с паузой. Она реализуется созданием отдельной сцены, которая будет рисоваться поверх игры при нажатии клавиши Escape. При этом вся игра будет становиться на паузу и «замирать». Курсор при постановке на паузу отображается. Также паузу стоит отменять по Escape.
1:00:15 Далее разрабатываем механизм перехода между уровнями. И тут мы возвращаемся к понятию паттерна, про который я говорил в самом начале. Механизм довольно простой: у нас есть одна сцена, которая перезагружает уровни в зависимости от текущего индекса. Для демонстрации моделируется ещё один уровень.
1:03:38 Теперь нужно разграничить слои объектов, чтобы определить, что с чем сталкивается, и что на что реагирует. Это нужно в первую очередь для того, чтобы исключить попадание пуль в самого себя, и чтобы пули не сталкивались с объектами дверей, потому что это просто не нужно. Для настройки слоев в Godot Engine есть специальные маски, расставляя галочки в которых можно добиться нужного эффекта.
1:08:34 Создание уровня с Боссом игры. Моделируем объект, экспортируем и настраиваем его материалы и поведение. Тут всё очень похоже на работу с другими объектами, поэтому многие части дублируют и код, и поведение в целом.
7
Заключение
1:15:26 Бонус — создание механизма, позволяющего оставлять следы от капель шампуня на стенах и полу, и завершение урока.
Итог — создание игры в Godot Engine — процесс намного более увлекательный, чем может показаться на первый взгляд, а кажущиеся сложными вещи выполняются довольно просто и удобно.