Revamping of the docs organisation for a more coherent TOC

Only the pages were moved so far and some empty ones created,
the up-to-date toctrees come in the next commit.
This commit is contained in:
Julian Murgia
2017-03-29 13:59:20 +02:00
committed by Rémi Verschelde
parent b632022426
commit b408bdb918
149 changed files with 2 additions and 379 deletions

View File

@@ -1,10 +0,0 @@
2D tutorials
============
.. toctree::
:maxdepth: 2
:name: toc-2d-tutorials
_2d_graphics
_2d_gui
_2d_physics

View File

@@ -1,14 +0,0 @@
Graphics
========
.. toctree::
:maxdepth: 1
:name: toc-2d-graphics
canvas_layers
viewport_and_canvas_transforms
custom_drawing_in_2d
screen-reading_shaders
particle_systems_2d
cutout_animation
using_tilemaps

View File

@@ -1,10 +0,0 @@
Graphical user interface (GUI)
==============================
.. toctree::
:maxdepth: 1
:name: toc-2d-gui
size_and_anchors
gui_skinning
custom_gui_controls

View File

@@ -1,10 +0,0 @@
Physics
=======
.. toctree::
:maxdepth: 1
:name: toc-2d-physics
physics_introduction
kinematic_character_2d
../ray-casting

View File

@@ -1,76 +0,0 @@
.. _doc_canvas_layers:
Canvas layers
=============
Viewport and Canvas items
-------------------------
Regular 2D nodes, such as :ref:`Node2D <class_Node2D>` or
:ref:`Control <class_Control>` both inherit from
:ref:`CanvasItem <class_CanvasItem>`, which is the base for all 2D
nodes. CanvasItems can be arranged in trees and they will inherit
their transform. This means that when moving the parent, the children
will be moved too.
These nodes are placed as direct or indirect children to a
:ref:`Viewport <class_Viewport>`, and will be displayed through it.
Viewport has a property "canvas_transform"
:ref:`Viewport.set_canvas_transform() <class_Viewport_set_canvas_transform>`,
which allows to transform all the CanvasItem hierarchy by a custom
:ref:`Matrix32 <class_Matrix32>` transform. Nodes such as
:ref:`Camera2D <class_Camera2D>`, work by changing that transform.
Changing the canvas transform is useful because it is a lot more
efficient than moving the root canvas item (and hence the whole scene).
Canvas transform is a simple matrix that offsets the whole 2D drawing,
so it's the most efficient way to do scrolling.
Not enough...
-------------
But this is not enough. There are often situations where the game or
application may not want *everything* transformed by the canvas
transform. Examples of this are:
- **Parallax Backgrounds**: Backgrounds that move slower than the rest
of the stage.
- **HUD**: Head's up display, or user interface. If the world moves,
the life counter, score, etc. must stay static.
- **Transitions**: Effects used for transitions (fades, blends) may
also want it to remain at a fixed location.
How can these problems be solved in a single scene tree?
CanvasLayers
------------
The answer is :ref:`CanvasLayer <class_CanvasLayer>`,
which is a node that adds a separate 2D rendering layer for all its
children and grand-children. Viewport children will draw by default at
layer "0", while a CanvasLayer will draw at any numeric layer. Layers
with a greater number will be drawn above those with a smaller number.
CanvasLayers also have their own transform, and do not depend of the
transform of other layers. This allows the UI to be fixed in-place,
while the world moves.
An example of this is creating a parallax background. This can be done
with a CanvasLayer at layer "-1". The screen with the points, life
counter and pause button can also be created at layer "1".
Here's a diagram of how it looks:
.. image:: /img/canvaslayers.png
CanvasLayers are independent of tree order, and they only depend on
their layer number, so they can be instantiated when needed.
Performance
-----------
Even though there shouldn't be any performance limitation, it is not
advised to use excessive amount of layers to arrange drawing order of
nodes. The most optimal way will always be arranging them by tree order.
2d nodes also have a property for controlling their drawing order
(see :ref:`Node2D.set_z() <class_Node2D_set_z>`).

View File

@@ -1,256 +0,0 @@
.. _doc_custom_drawing_in_2d:
Custom drawing in 2D
====================
Why?
----
Godot has nodes to draw sprites, polygons, particles, and all sorts of
stuff. For most cases this is enough, but not always. Before crying in fear,
angst, and rage because a node to draw that-specific-something does not exist... it would
be good to know that it is possible to easily make any 2D node (be it
:ref:`Control <class_Control>` or :ref:`Node2D <class_Node2D>`
based) draw custom commands. It is *really* easy to do it too.
But...
------
Custom drawing manually in a node is *really* useful. Here are some
examples why:
- Drawing shapes or logic that is not handled by nodes (example: making
a node that draws a circle, an image with trails, a special kind of
animated polygon, etc).
- Visualizations that are not that compatible with nodes: (example: a
tetris board). The tetris example uses a custom draw function to draw
the blocks.
- Managing drawing logic of a large amount of simple objects (in the
hundreds of thousands). Using a thousand nodes is probably not nearly
as efficient as drawing, but a thousand of draw calls are cheap.
Check the "Shower of Bullets" demo as example.
- Making a custom UI control. There are plenty of controls available,
but it's easy to run into the need to make a new, custom one.
OK, how?
--------
Add a script to any :ref:`CanvasItem <class_CanvasItem>`
derived node, like :ref:`Control <class_Control>` or
:ref:`Node2D <class_Node2D>`. Override the _draw() function.
::
extends Node2D
func _draw():
#your draw commands here
pass
Draw commands are described in the :ref:`CanvasItem <class_CanvasItem>`
class reference. There are plenty of them.
Updating
--------
The _draw() function is only called once, and then the draw commands
are cached and remembered, so further calls are unnecessary.
If re-drawing is required because a state or something else changed,
simply call :ref:`CanvasItem.update() <class_CanvasItem_update>`
in that same node and a new _draw() call will happen.
Here is a little more complex example. A texture variable that will be
redrawn if modified:
::
extends Node2D
export var texture setget _set_texture
func _set_texture(value):
#if the texture variable is modified externally,
#this callback is called.
texture=value #texture was changed
update() #update the node
func _draw():
draw_texture(texture,Vector2())
In some cases, it may be desired to draw every frame. For this, just
call update() from the _process() callback, like this:
::
extends Node2D
func _draw():
#your draw commands here
pass
func _process(delta):
update()
func _ready():
set_process(true)
An example: drawing circular arcs
----------------------------------
We will now use the custom drawing functionality of the Godot Engine to draw something that Godot doesn't provide functions for. As an example, Godot provides a draw_circle() function that draws a whole circle. However, what about drawing a portion of a circle? You will have to code a function to perform this, and draw it yourself.
Arc function
^^^^^^^^^^^^
An arc is defined by its support circle parameters, that is: the center position, and the radius. And the arc itself is then defined by the angle it starts from, and the angle it stops at. These are the 4 parameters we have to provide to our drawing. We'll also provide the color value so we can draw the arc in different colors if we wish.
Basically, drawing a shape on screen requires it to be decomposed into a certain number of points linked one to the following one. As you can imagine, the more points your shape is made of, the smoother it will appear, but the heavier it will be in terms of processing cost. In general, if your shape is huge (or in 3D, close to the camera), it will require more points to be drawn without showing angular-looking. On the contrary, if you shape is small (or in 3D, far from the camera), you may reduce its number of points to save processing costs. This is called *Level of Detail (LoD)*. In our example, we will simply use a fixed number of points, no matter the radius.
::
func draw_circle_arc( center, radius, angle_from, angle_to, color ):
var nb_points = 32
var points_arc = Vector2Array()
for i in range(nb_points+1):
var angle_point = angle_from + i*(angle_to-angle_from)/nb_points - 90
var point = center + Vector2( cos(deg2rad(angle_point)), sin(deg2rad(angle_point)) ) * radius
points_arc.push_back( point )
for indexPoint in range(nb_points):
draw_line(points_arc[indexPoint], points_arc[indexPoint+1], color)
Remember the number of points our shape has to be decomposed into? We fixed this number in the nb_points variable to a value of 32. Then, we initialize an empty Vector2Array, which is simply an array of Vector2.
Next step consists in computing the actual positions of these 32 points that compose arc. This is done in the first for-loop: we iterate over the number of points we want to compute the positions, plus one to include the last point. We first determine the angle of each point, between the starting and ending angles.
The reason why each angle is reduced of 90° is that we will compute 2D positions out of each angle using trigonometry (you know, cosine and sine stuff...). However, to be simple, cos() and sin() use radians, not degrees. The angle of 0° (0 radian) starts at 3 o'clock, although we want to start counting at 0 o'clock. So, we just reduce each angle of 90° in order to start counting from 0'clock.
The actual position of a point located on a circle at angle 'angle' (in radians) is given by Vector2(cos(angle), sin(angle)). Since cos() and sin() return values between -1 and 1, the position is located on a circle of radius 1. To have this position on our support circle, which has a radius of 'radius', we simply need to multiply the position by 'radius'. Finally, we need to position our support circle at the 'center' position, which is performed by adding it to our Vector2 value. Finally, we insert the point in the Vector2Array which was previously defined.
Now, we need to actually draw our points. As you can imagine, we will not simply draw our 32 points: we need to draw everything that is between each of them. We could have computed every point ourselves using the previous method, and draw it one by one, but this it too complicated and inefficient (except if explicitly needed). So, we simply draw lines between each pair of points. Unless the radius of our support circle is very big, the length of each line between a pair of points will never be long enough to see them. If this happens, we simply would need to increase the number of points.
Draw the arc on screen
^^^^^^^^^^^^^^^^^^^^^^
We now have a function that draws stuff on screen: it is time to call it in the _draw() function.
::
func _draw():
var center = Vector2(200,200)
var radius = 80
var angle_from = 75
var angle_to = 195
var color = Color(1.0, 0.0, 0.0)
draw_circle_arc( center, radius, angle_from, angle_to, color )
Result:
.. image:: /img/result_drawarc.png
Arc polygon function
^^^^^^^^^^^^^^^^^^^^
We can take this a step further and write a function that draws the plain portion of the disc defined by the arc, not only its shape. The method is exactly the same a previously, except that we draw a polygon instead of lines:
::
func draw_circle_arc_poly( center, radius, angle_from, angle_to, color ):
var nb_points = 32
var points_arc = Vector2Array()
points_arc.push_back(center)
var colors = ColorArray([color])
for i in range(nb_points+1):
var angle_point = angle_from + i*(angle_to-angle_from)/nb_points - 90
points_arc.push_back(center + Vector2( cos( deg2rad(angle_point) ), sin( deg2rad(angle_point) ) ) * radius)
draw_polygon(points_arc, colors)
.. image:: /img/result_drawarc_poly.png
Dynamic custom drawing
^^^^^^^^^^^^^^^^^^^^^^
Alright, we are now able to draw custom stuff on screen. However, it is very static: let's make this shape turn around the center. The solution to do this is simply to change the angle_from and angle_to values over time. For our example, we will simply increment them by 50. This increment value has to remain constant, else the rotation speed will change accordingly.
First, we have to make both angle_from and angle_to variables global at the top of our script. Also note that you can store them in other nodes and access them using get_node().
::
extends Node2D
var rotation_ang = 50
var angle_from = 75
var angle_to = 195
We make these values change in the _process(delta) function. To activate this function, we need to call set_process(true) in the _ready() function.
We also increment our angle_from and angle_to values here. However, we must not forget to wrap() the resulting values between 0 and 360°! That is, if the angle is 361°, then it is actually 1°. If you don't wrap these values, the script will work correctly but angles values will grow bigger and bigger over time, until they reach the maximum integer value Godot can manage (2^31 - 1). When this happens, Godot may crash or produce unexpected behavior. Since Godot doesn't provide a wrap() function, we'll create it here, as it is relatively simple.
Finally, we must not forget to call the update() function, which automatically calls _draw(). This way, you can control when you want to refresh the frame.
::
func _ready():
set_process(true)
func wrap(value, min_val, max_val):
var f1 = value - min_val
var f2 = max_val - min_val
return fmod(f1, f2) + min_val
func _process(delta):
angle_from += rotation_ang
angle_to += rotation_ang
# we only wrap angles if both of them are bigger than 360
if (angle_from > 360 && angle_to > 360):
angle_from = wrap(angle_from, 0, 360)
angle_to = wrap(angle_to, 0, 360)
update()
Also, don't forget to modify the _draw() function to make use of these variables:
::
func _draw():
var center = Vector2(200,200)
var radius = 80
var color = Color(1.0, 0.0, 0.0)
draw_circle_arc( center, radius, angle_from, angle_to, color )
Let's run!
It works, but the arc is rotating insanely fast! What's wrong?
The reason is that your GPU is actually displaying the frames as fast as he can. We need to "normalize" the drawing by this speed. To achieve, we have to make use of the 'delta' parameter of the _process() function. 'delta' contains the time elapsed between the two last rendered frames. It is generally small (about 0.0003 seconds, but this depends on your hardware). So, using 'delta' to control your drawing ensures your program to run at the same speed on every hardware.
In our case, we simply need to multiply our 'rotation_ang' variable by 'delta' in the _process() function. This way, our 2 angles will be increased by a much smaller value, which directly depends on the rendering speed.
::
func _process(delta):
angle_from += rotation_ang * delta
angle_to += rotation_ang * delta
# we only wrap angles if both of them are bigger than 360
if (angle_from > 360 && angle_to > 360):
angle_from = wrap(angle_from, 0, 360)
angle_to = wrap(angle_to, 0, 360)
update()
Let's run again! This time, the rotation displays fine!
Tools
-----
Drawing your own nodes might also be desired while running them in the
editor, to use as preview or visualization of some feature or
behavior.
Remember to just use the "tool" keyword at the top of the script
(check the :ref:`doc_gdscript` reference if you forgot what this does).

View File

@@ -1,143 +0,0 @@
.. _doc_custom_gui_controls:
Custom GUI controls
===================
So many controls...
-------------------
Yet there are never enough. Creating your own custom controls that act
just the way you want them is an obsession of almost every GUI
programmer. Godot provides plenty of them, but they may not work exactly
the way you want. Before contacting the developers with a pull-request
to support diagonal scrollbars, at least it will be good to know how to
create these controls easily from script.
Drawing
-------
For drawing, it is recommended to check the :ref:`doc_custom_drawing_in_2d` tutorial.
The same applies. Some functions are worth mentioning due to their
usefulness when drawing, so they will be detailed next:
Checking control size
~~~~~~~~~~~~~~~~~~~~~
Unlike 2D nodes, "size" is very important with controls, as it helps to
organize them in proper layouts. For this, the
:ref:`Control.get_size() <class_Control_get_size>`
method is provided. Checking it during _draw() is vital to ensure
everything is kept in-bounds.
Checking focus
~~~~~~~~~~~~~~
Some controls (such as buttons or text editors) might provide input
focus for keyboard or joypad input. Examples of this are entering text
or pressing a button. This is controlled with the
:ref:`Control.set_focus_mode() <class_Control_set_focus_mode>`
function. When drawing, and if the control supports input focus, it is
always desired to show some sort of indicator (highight, box, etc) to
indicate that this is the currently focused control. To check for this
status, the :ref:`Control.has_focus() <class_Control_has_focus>`
exists. Example
::
func _draw():
if (has_focus()):
draw_selected()
else:
draw_normal()
Sizing
------
As mentioned before, size is very important to controls. This allows
them to lay out properly, when set into grids, containers, or anchored.
Controls most of the time provide a *minimum size* to help to properly
lay them out. For example, if controls are placed vertically on top of
each other using a :ref:`VBoxContainer <class_VBoxContainer>`,
the minimum size will make sure your custom control is not squished by
the other controls in the container.
To provide this callback, just override
:ref:`Control.get_minimum_size() <class_Control_get_minimum_size>`,
for example:
::
func get_minimum_size():
return Vector2(30,30)
Or alternatively, set it via function:
::
func _ready():
set_custom_minimum_size( Vector2(30,30) )
Input
-----
Controls provide a few helpers to make managing input events much easier
than regular nodes.
Input events
~~~~~~~~~~~~
There are a few tutorials about input before this one, but it's worth
mentioning that controls have a special input method that only works
when:
- The mouse pointer is over the control.
- The button was pressed over this control (control always
captures input until button is released)
- Control provides keyboard/joypad focus via
:ref:`Control.set_focus_mode() <class_Control_set_focus_mode>`.
This function is
:ref:`Control._input_event() <class_Control__input_event>`.
Simply override it in your control. No processing needs to be set.
::
extends Control
func _input_event(ev):
if (ev.type==InputEvent.MOUSE_BUTTON and ev.button_index==BUTTON_LEFT and ev.pressed):
print("Left mouse button was pressed!")
For more information about events themselves, check the :ref:`doc_inputevent`
tutorial.
Notifications
~~~~~~~~~~~~~
Controls also have many useful notifications for which no callback
exists, but can be checked with the _notification callback:
::
func _notification(what):
if (what==NOTIFICATION_MOUSE_ENTER):
pass # mouse entered the area of this control
elif (what==NOTIFICATION_MOUSE_EXIT):
pass # mouse exited the area of this control
elif (what==NOTIFICATION_FOCUS_ENTER):
pass # control gained focus
elif (what==NOTIFICATION_FOCUS_EXIT):
pass # control lost focus
elif (what==NOTIFICATION_THEME_CHANGED):
pass # theme used to draw the control changed
# update and redraw is recommended if using a theme
elif (what==NOTIFICATION_VISIBILITY_CHANGED):
pass # control became visible/invisible
# check new status with is_visible()
elif (what==NOTIFICATION_RESIZED):
pass # control changed size, check new size
# with get_size()
elif (what==NOTIFICATION_MODAL_CLOSED):
pass # for modal popups, notification
# that the popup was closed

View File

@@ -1,355 +0,0 @@
.. _doc_cutout_animation:
Cutout animation
================
What is it?
~~~~~~~~~~~
Cut-out is a technique of animating in 2D where pieces of paper (or
similar material) are cut in special shapes and laid one over the other.
The papers are animated and photographed, frame by frame using a stop
motion technique (more info
`here <http://en.wikipedia.org/wiki/Cutout_animation>`__).
With the advent of the digital age, this technique became possible using
computers, which resulted in an increased amount of animation TV shows
using digital Cut-out. Notable examples are `South
Park <http://en.wikipedia.org/wiki/South_Park>`__ or `Jake and the Never
Land
Pirates <http://en.wikipedia.org/wiki/Jake_and_the_Never_Land_Pirates>`__
.
In video games, this technique also become very popular. Examples of
this are `Paper
Mario <http://en.wikipedia.org/wiki/Super_Paper_Mario>`__ or `Rayman
Origins <http://en.wikipedia.org/wiki/Rayman_Origins>`__ .
Cutout in Godot
~~~~~~~~~~~~~~~
Godot provides a few tools for working with these kind of assets, but
its overall design makes it ideal for the workflow. The reason is that,
unlike other tools meant for this, Godot has the following advantages:
- **The animation system is fully integrated with the engine**: This
means, animations can control much more than just motion of objects,
such as textures, sprite sizes, pivots, opacity, color modulation,
etc. Everything can be animated and blended.
- **Mix with Traditional**: AnimatedSprite allows traditional animation
to be mixed, very useful for complex objects, such as shape of hands
and foot, changing facial expression, etc.
- **Custom Shaped Elements**: Can be created with
:ref:`Polygon2D <class_Polygon2D>`
allowing the mixing of UV animation, deformations, etc.
- **Particle Systems**: Can also be mixed with the traditional
animation hierarchy, useful for magic effects, jetpacks, etc.
- **Custom Colliders**: Set colliders and influence areas in different
parts of the skeletons, great for bosses, fighting games, etc.
- **Animation Tree**: Allows complex combinations and blendings of
several animations, the same way it works in 3D.
And much more!
Making of GBot!
~~~~~~~~~~~~~~~
For this tutorial, we will use as demo content the pieces of the
`GBot <https://www.youtube.com/watch?v=S13FrWuBMx4&list=UUckpus81gNin1aV8WSffRKw>`__
character, created by Andreas Esau.
.. image:: /img/tuto_cutout_walk.gif
Get your assets: :download:`gbot_resources.zip </files/gbot_resources.zip>`.
Setting up the rig
~~~~~~~~~~~~~~~~~~
Create an empty Node2D as root of the scene, we will work under it:
.. image:: /img/tuto_cutout1.png
OK, the first node of the model that we will create will be the hip.
Generally, both in 2D and 3D, the hip is the root of the skeleton. This
makes it easier to animate:
.. image:: /img/tuto_cutout2.png
Next will be the torso. The torso needs to be a child of the hip, so
create a child sprite and load the torso, later accommodate it properly:
.. image:: /img/tuto_cutout3.png
This looks good. Let's see if our hierarchy works as a skeleton by
rotating the torso:
.. image:: /img/tutovec_torso1.gif
Ouch, that doesn't look good! The rotation pivot is wrong, this means
it needs to be adjusted.
This small little cross in the middle of the
:ref:`Sprite <class_Sprite>` is
the rotation pivot:
.. image:: /img/tuto_cutout4.png
Adjusting the pivot
~~~~~~~~~~~~~~~~~~~
The pivot can be adjusted by changing the *offset* property in the
Sprite:
.. image:: /img/tuto_cutout5.png
However, there is a way to do it more *visually*. While hovering over the
desired pivot point, simply press the "v" key to move the pivot there for the
selected Sprite. Alternately, there is a tool in the tool bar that has a
similar function.
.. image:: /img/tutovec_torso2.gif
Now it looks good! Let's continue adding body pieces, starting by the
right arm. Make sure to put the sprites in hierarchy, so their rotations
and translations are relative to the parent:
.. image:: /img/tuto_cutout6.png
This seems easy, so continue with the left arm. The rest should be
simple! Or maybe not:
.. image:: /img/tuto_cutout7.png
Right. Remember your tutorials, Luke. In 2D, parent nodes appear below
children nodes. Well, this sucks. It seems Godot does not support cutout
rigs after all. Come back next year, maybe for 3.0.. no wait. Just
Kidding! It works just fine.
But how can this problem be solved? We want the left arm to appear behind
the hip and the torso. For this, we can move the nodes behind the hip
(note that you can bypass this by setting the Node2D Z property, but then you
won't learn about all this!):
.. image:: /img/tuto_cutout8.png
But then, we lose the hierarchy layout, which allows to control the
skeleton like.. a skeleton. Is there any hope?.. Of Course!
RemoteTransform2D node
~~~~~~~~~~~~~~~~~~~~~~
Godot provides a special node, :ref:`RemoteTransform2D <class_RemoteTransform2D>`.
This node will transform nodes that are sitting somewhere else in the
hierarchy, by applying the transform to the remote nodes.
This enables to have a visibility order independent from the
hierarchy.
Simply create two more nodes as children from torso, remote_arm_l and
remote_hand_l and link them to the actual sprites:
.. image:: /img/tuto_cutout9.png
Moving the remote transform nodes will move the sprites, allowing you to
easily animate and pose the character:
.. image:: /img/tutovec_torso4.gif
Completing the skeleton
~~~~~~~~~~~~~~~~~~~~~~~
Complete the skeleton by following the same steps for the rest of the
parts. The resulting scene should look similar to this:
.. image:: /img/tuto_cutout10.png
The resulting rig will be easy to animate. By selecting the nodes and
rotating them you can animate forward kinematics (FK) efficiently.
For simple objects and rigs this is fine, however the following problems
are common:
- Selecting sprites can become difficult for complex rigs, and the
scene tree ends being used due to the difficulty of clicking over the
proper sprite.
- Inverse Kinematics is often desired for extremities.
To solve these problems, Godot supports a simple method of skeletons.
Skeletons
~~~~~~~~~
Godot doesn't actually support *true* Skeketons, but it does feature a
helper to create "bones" between nodes. This is enough for most cases,
but the way it works is not completely obvious.
As an example, let's turn the right arm into a skeleton. To create
skeletons, a chain of nodes must be selected from top to bottom:
.. image:: /img/tuto_cutout11.png
Then, the option to create a skeleton is located at Edit > Make Bones:
.. image:: /img/tuto_cutout12.png
This will add bones covering the arm, but the result is not quite what
is expected.
.. image:: /img/tuto_cutout13.png
It looks like the bones are shifted up in the hierarchy. The hand
connects to the arm, and the arm to the body. So the question is:
- Why does the hand lack a bone?
- Why does the arm connect to the body?
This might seem strange at first, but will make sense later on. In
traditional skeleton systems, bones have a position, an orientation and
a length. In Godot, bones are mostly helpers so they connect the current
node with the parent. Because of this, **toggling a node as a bone will
just connect it to the parent**.
So, with this knowledge. Let's do the same again so we have an actual,
useful skeleton.
The first step is creating an endpoint node. Any kind of node will do,
but :ref:`Position2D <class_Position2D>` is preferred because it's
visible in the editor. The endpoint node will ensure that the last bone
has orientation.
.. image:: /img/tuto_cutout14.png
Now select the whole chain, from the endpoint to the arm and create
bones:
.. image:: /img/tuto_cutout15.png
The result resembles a skeleton a lot more, and now the arm and forearm
can be selected and animated.
Finally, create endpoints in all meaningful extremities and connect the
whole skeleton with bones up to the hip:
.. image:: /img/tuto_cutout16.png
Finally! the whole skeleton is rigged! On close look, it is noticeable
that there is a second set of endpoints in the hands. This will make
sense soon.
Now that a whole skeleton is rigged, the next step is setting up the IK
chains. IK chains allow for more natural control of extremities.
IK chains
~~~~~~~~~
IK chains are a powerful animation tool. Imagine you want to pose a character's foot in a specific position on the ground. Without IK chains, each motion of the foot would require rotating and positioning several other bones. This would be quite complex and lead to imprecise results.
What if we could move the foot and let the rest of the leg self-adjust?
This type of posing is called IK (Inverse Kinematic).
To create an IK chain, simply select a chain of bones from endpoint to
the base for the chain. For example, to create an IK chain for the right
leg, select the following:
.. image:: /img/tuto_cutout17.png
Then enable this chain for IK. Go to Edit > Make IK Chain.
.. image:: /img/tuto_cutout18.png
As a result, the base of the chain will turn *Yellow*.
.. image:: /img/tuto_cutout19.png
Once the IK chain is set-up, simply grab any of the bones in the
extremity, any child or grand-child of the base of the chain and try to
grab it and move it. Result will be pleasant, satisfaction warranted!
.. image:: /img/tutovec_torso5.gif
Animation
~~~~~~~~~
The following section will be a collection of tips for creating
animation for your rigs. If unsure about how the animation system in
Godot works, refresh it by checking again the :ref:`doc_animations`.
2D animation
------------
When doing animation in 2D, a helper will be present in the top menu.
This helper only appears when the animation editor window is opened:
.. image:: /img/tuto_cutout20.png
The key button will insert location/rotation/scale keyframes to the
selected objects or bones. This depends on the mask enabled. Green items
will insert keys while red ones will not, so modify the key insertion
mask to your preference.
Rest pose
~~~~~~~~~
These kind of rigs do not have a "rest" pose, so it's recommended to
create a reference rest pose in one of the animations.
Simply do the following steps:
1. Make sure the rig is in "rest" (not doing any specific pose).
2. Create a new animation, rename it to "rest".
3. Select all nodes (box selection should work fine).
4. Select "loc" and "rot" on the top menu.
5. Push the key button. Keys will be inserted for everything, creating
a default pose.
.. image:: /img/tuto_cutout21.png
Rotation
~~~~~~~~
Animating these models means only modifying the rotation of the nodes.
Location and scale are rarely used, with the only exception of moving
the entire rig from the hip (which is the root node).
As a result, when inserting keys, only the "rot" button needs to be
pressed most of the time:
.. image:: /img/tuto_cutout22.png
This will avoid the creation of extra animation tracks for the position
that will remain unused.
Keyframing IK
~~~~~~~~~~~~~
When editing IK chains, is is not necessary to select the whole chain to
add keyframes. Selecting the endpoint of the chain and inserting a
keyframe will automatically insert keyframes until the chain base too.
This makes the task of animating extremities much simpler.
Moving sprites above and behind others.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RemoteTransform2D works in most cases, but sometimes it is really
necessary to have a node above and below others during an animation. To
aid on this the "Behind Parent" property exists on any Node2D:
.. image:: /img/tuto_cutout23.png
Batch setting transition curves
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When creating really complex animations and inserting lots of keyframes,
editing the individual keyframe curves for each can become an endless
task. For this, the Animation Editor has a small menu where changing all
the curves is easy. Just select every single keyframe and (generally)
apply the "Out-In" transition curve to smooth the animation:
.. image:: /img/tuto_cutout24.png

View File

@@ -1,161 +0,0 @@
.. _doc_gui_skinning:
GUI skinning
============
Oh beautiful GUI!
-----------------
This tutorial is about advanced skinning of an user interface. Most
games generally don't need this, as they end up just relying on
:ref:`Label <class_Label>`, :ref:`TextureFrame <class_TextureFrame>`,
:ref:`TextureButton <class_TextureButton>` and
:ref:`TextureProgress <class_TextureProgress>`.
However, many types of games often need complex user interfaces, like
MMOs, traditional RPGs, Simulators, Strategy, etc. These kind of
interfaces are also common in some games that include editors to create
content, or interfaces for network connectivity.
Godot user interface uses these kind of controls with the default theme,
but they can be skinned to resemble pretty much any kind of user
interface.
Theme
-----
The GUI is skinned through the :ref:`Theme <class_Theme>`
resource. Theme contains all the information required to change the
entire visual styling of all controls. Theme options are named, so it's
not obvious which name changes what (specialy from code), but several
tools are provided. The ultimate place to look at what each theme option
is for each control, which will always be more up to date than any
documentation is the file `scene/resources/default_theme/default_theme.cpp
<https://github.com/godotengine/godot/blob/master/scene/resources/default_theme/default_theme.cpp>`__.
The rest of this document will explain the different tools used to
customize the theme.
A Theme can be applied to any control in the scene. As a result, all
children and grand-children controls will use that same theme too
(unless another theme is specified further down the tree). If a value is
not found in a theme, it will be searched in themes higher up in the
hierarchy towards the root. If nothing was found, the default theme is
used. This system allows for flexible overriding of themes in complex
user interfaces.
Theme options
-------------
Each kind of option in a theme can be:
- **An integer constant**: A single numerical constant. Generally used
to define spacing between compoments or alignment.
- **A Color**: A single color, with or without transparency. Colors are
usually applied to fonts and icons.
- **A Texture**: A single image. Textures are not often used, but when
they are they represent handles to pick or icons in a complex control
(such as file dialog).
- **A Font**: Every control that uses text can be assigned the fonts
used to draw strings.
- **A StyleBox**: Stylebox is a resource that defines how to draw a
panel in varying sizes (more information on them later).
Every option is associated to:
- A name (the name of the option)
- A Control (the name of the control)
An example usage:
::
var t = Theme.new()
t.set_color("font_color","Label",Color(1.0,1.0,1.0))
var l = Label.new()
l.set_theme(t)
In the example above, a new theme is created. The "font_color" option
is changed and then applied to a label. As a result, the label (and all
children and grand children labels) will use that color.
It is possible to override those options without using the theme
directly and only for a specific control by using the override API in
:ref:`Control.add_color_override() <class_Control_add_color_override>`:
::
var l = Label.new()
l.add_color_override("font_color",Color(1.0,1.0,1.0))
In the inline help of Godot (in the script tab) you can check which theme options
are overrideable, or check the :ref:`Control <class_Control>` class reference.
Customizing a control
---------------------
If only a few controls need to be skinned, it is often not necessary to
create a new theme. Controls offer their theme options as special kinds
of properties. If checked, overriding will take place:
.. image:: /img/themecheck.png
As can be see in the image above, theme options have little check-boxes.
If checked, they can be used to override the value of the theme just for
that control.
Creating a theme
----------------
The simplest way to create a theme is to edit a theme resource. Create a
Theme from the resource menu, the editor will appear immediately.
Following to this, save it (to, as example, mytheme.thm):
.. image:: /img/themecheck.png
This will create an empty theme that can later be loaded and assigned to
controls.
Example: theming a button
--------------------------
Take some assets (:download:`skin_assets.zip </files/skin_assets.zip>`),
go to the "theme" menu and select "Add Class Item":
.. image:: /img/themeci.png
A menu will appear promting the type of control to create. Select
"Button":
.. image:: /img/themeci2.png
Immediately, all button theme options will appear in the property
editor, where they can be edited:
.. image:: /img/themeci3.png
Select the "normal" stylebox and create a new "StyleBoxTexture", then
edit it. A texture stylebox basically contains a texture and the size of
the margins that will not stretch when the texture is stretched. This is
called "3x3" stretching:
.. image:: /img/sb1.png
Repeat the steps and add the other assets. There is no hover or disabled
image in the example files, so use the same stylebox as in normal. Set
the supplied font as the button font and change the font color to black.
Soon, your button will look different and retro:
.. image:: /img/sb2.png
Save this theme to the .thm file. Go to the 2D editor and create a few
buttons:
.. image:: /img/skinbuttons1.png
Now, go to the root node of the scene and locate the "theme" property,
replace it by the theme that was just created. It should look like this:
.. image:: /img/skinbuttons2.png
Congratulations! You have created a reusable GUI Theme!

View File

@@ -1,249 +0,0 @@
.. _doc_kinematic_character_2d:
Kinematic Character (2D)
========================
Introduction
~~~~~~~~~~~~
Yes, the name sounds strange. "Kinematic Character". What is that?
The reason is that when physics engines came out, they were called
"Dynamics" engines (because they dealt mainly with collision
responses). Many attempts were made to create a character controller
using the dynamics engines but it wasn't as easy as it seems. Godot
has one of the best implementations of dynamic character controller
you can find (as it can be seen in the 2d/platformer demo), but using
it requieres a considerable level of skill and understanding of
physics engines (or a lot of patience with trial and error).
Some physics engines such as Havok seem to swear by dynamic character
controllers as the best alternative, while others (PhysX) would rather
promote the Kinematic one.
So, what is really the difference?:
- A **dynamic character controller** uses a rigid body with infinite
inertial tensor. Basically, it's a rigid body that can't rotate.
Physics engines always let objects collide, then solve their
collisions all together. This makes dynamic character controllers
able to interact with other physics objects seamlessly (as seen in
the platformer demo), however these interactions are not always
predictable. Collisions also can take more than one frame to be
solved, so a few collisions may seem to displace a tiny bit. Those
problems can be fixed, but require a certain amount of skill.
- A **kinematic character controller** is assumed to always begin in a
non-colliding state, and will always move to a non colliding state.
If it starts in a colliding state, it will try to free itself (like
rigid bodies do) but this is the exception, not the rule. This makes
their control and motion a lot more predictable and easier to
program. However, as a downside, they can't directly interact with
other physics objects (unless done by hand in code).
This short tutorial will focus on the kinematic character controller.
Basically, the oldschool way of handling collisions (which is not
necessarily simpler under the hood, but well hidden and presented as a
nice and simple API).
Fixed process
~~~~~~~~~~~~~
To manage the logic of a kinematic body or character, it is always
advised to use fixed process, which is called the same amount of times
per second, always. This makes physics and motion calculation work in a
more predictable way than using regular process, which might have spikes
or lose precision if the frame rate is too high or too low.
::
extends KinematicBody2D
func _fixed_process(delta):
pass
func _ready():
set_fixed_process(true)
Scene setup
~~~~~~~~~~~
To have something to test, here's the scene (from the tilemap tutorial):
:download:`kbscene.zip </files/kbscene.zip>`. We'll be creating a new scene
for the character. Use the robot sprite and create a scene like this:
.. image:: /img/kbscene.png
Let's add a circular collision shape to the collision body, create a new
CircleShape2D in the shape property of CollisionShape2D. Set the radius
to 30:
.. image:: /img/kbradius.png
**Note: As mentioned before in the physics tutorial, the physics engine
can't handle scale on most types of shapes (only collision polygons,
planes and segments work), so always change the parameters (such as
radius) of the shape instead of scaling it. The same is also true for
the kinematic/rigid/static bodies themselves, as their scale affect the
shape scale.**
Now create a script for the character, the one used as an example
above should work as a base.
Finally, instance that character scene in the tilemap, and make the
map scene the main one, so it runs when pressing play.
.. image:: /img/kbinstance.png
Moving the Kinematic character
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Go back to the character scene, and open the script, the magic begins
now! Kinematic body will do nothing by default, but it has a really
useful function called :ref:`KinematicBody2D.move() <class_KinematicBody2D_move>`.
This function takes a :ref:`Vector2 <class_Vector2>` as
an argument, and tries to apply that motion to the kinematic body. If a
collision happens, it stops right at the moment of the collision.
So, let's move our sprite downwards until it hits the floor:
::
extends KinematicBody2D
func _fixed_process(delta):
move( Vector2(0,1) ) #move down 1 pixel per physics frame
func _ready():
set_fixed_process(true)
The result is that the character will move, but stop right when
hitting the floor. Pretty cool, huh?
The next step will be adding gravity to the mix, this way it behaves a
little more like an actual game character:
::
extends KinematicBody2D
const GRAVITY = 200.0
var velocity = Vector2()
func _fixed_process(delta):
velocity.y += delta * GRAVITY
var motion = velocity * delta
move( motion )
func _ready():
set_fixed_process(true)
Now the character falls smoothly. Let's make it walk to the sides, left
and right when touching the directional keys. Remember that the values
being used (for speed at least) is pixels/second.
This adds simple walking support by pressing left and right:
::
extends KinematicBody2D
const GRAVITY = 200.0
const WALK_SPEED = 200
var velocity = Vector2()
func _fixed_process(delta):
velocity.y += delta * GRAVITY
if (Input.is_action_pressed("ui_left")):
velocity.x = -WALK_SPEED
elif (Input.is_action_pressed("ui_right")):
velocity.x = WALK_SPEED
else:
velocity.x = 0
var motion = velocity * delta
move(motion)
func _ready():
set_fixed_process(true)
And give it a try.
Problem?
~~~~~~~~
And... it doesn't work very well. If you go to the left against a wall,
it gets stuck unless you release the arrow key. Once it is on the floor,
it also gets stuck and it won't walk. What is going on??
The answer is, what it seems like it should be simple, it isn't that
simple in reality. If the motion can't be completed, the character will
stop moving. It's as simple as that. This diagram should illustrate
better what is going on:
.. image:: /img/motion_diagram.png
Basically, the desired motion vector will never complete because it hits
the floor and the wall too early in the motion trajectory and that makes
it stop there. Remember that even though the character is on the floor,
the gravity is always turning the motion vector downwards.
Solution!
~~~~~~~~~
The solution? This situation is solved by "sliding" by the collision
normal. KinematicBody2D provides two useful functions:
- :ref:`KinematicBody2D.is_colliding() <class_KinematicBody2D_is_colliding>`
- :ref:`KinematicBody2D.get_collision_normal() <class_KinematicBody2D_get_collision_normal>`
So what we want to do is this:
.. image:: /img/motion_reflect.png
When colliding, the function ``move()`` returns the "remainder" of the
motion vector. That means, if the motion vector is 40 pixels, but
collision happened at 10 pixels, the same vector but 30 pixels long is
returned.
The correct way to solve the motion is, then, to slide by the normal
this way:
::
func _fixed_process(delta):
velocity.y += delta * GRAVITY
if (Input.is_action_pressed("ui_left")):
velocity.x = - WALK_SPEED
elif (Input.is_action_pressed("ui_right")):
velocity.x = WALK_SPEED
else:
velocity.x = 0
var motion = velocity * delta
motion = move(motion)
if (is_colliding()):
var n = get_collision_normal()
motion = n.slide(motion)
velocity = n.slide(velocity)
move(motion)
func _ready():
set_fixed_process(true)
Note that not only the motion has been modified but also the velocity.
This makes sense as it helps keep the new direction too.
The normal can also be used to detect that the character is on floor, by
checking the angle. If the normal points up (or at least, within a
certain threshold), the character can be determined to be there.
A more complete demo can be found in the demo zip distributed with the
engine, or in the
https://github.com/godotengine/godot-demo-projects/tree/master/2d/kinematic_char.

View File

@@ -1,260 +0,0 @@
.. _doc_particle_systems_2d:
Particle Systems (2D)
=====================
Intro
-----
A simple (but flexible enough for most uses) particle system is
provided. Particle systems are used to simulate complex physical effects
such as sparks, fire, magic particles, smoke, mist, magic, etc.
The idea is that a "particle" is emitted at a fixed interval and with a
fixed lifetime. During his lifetime, every particle will have the same
base behavior. What makes every particle different and provides a more
organic look is the "randomness" associated to each parameter. In
essence, creating a particle system means setting base physics
parameters and then adding randomness to them.
Particles2D
~~~~~~~~~~~
Particle systems are added to the scene via the
:ref:`Particles2D <class_Particles2D>`
node. They are enabled by default and start emitting white points
downwards (as affected by the gravity). This provides a reasonable
starting point to start adapting it to our needs.
.. image:: /img/particles1.png
Texture
~~~~~~~
A particle system uses a single texture (in the future this might be
extended to animated textures via spritesheet). The texture is set via
the relevant texture property:
.. image:: /img/particles2.png
Physics variables
-----------------
Before taking a look at the global parameters for the particle system,
let's first see what happens when the physics variables are tweaked.
Direction
---------
This is the base angle at which particles emit. Default is 0 (down):
.. image:: /img/paranim1.gif
Changing it will change the emissor direction, but gravity will still
affect them:
.. image:: /img/paranim2.gif
This parameter is useful because, by rotating the node, gravity will
also be rotated. Changing direction keeps them separate.
Spread
------
Spread is the angle at which particles will randomly be emitted.
Increasing the spread will increase the angle. A spread of 180 will emit
in all directions.
.. image:: /img/paranim3.gif
Linear velocity
---------------
Linear velocity is the speed at which particles will be emitted (in
pixels/sec). Speed might later be modified by gravity or other
accelerations (as described further below).
.. image:: /img/paranim4.gif
Spin velocity
-------------
Spin velocity is the speed at which particles turn around their center
(in degrees/sec).
.. image:: /img/paranim5.gif
Orbit velocity
--------------
Orbit velocity is used to make particles turn around their center.
.. image:: /img/paranim6.gif
Gravity direction & strength
----------------------------
Gravity can be modified as in direction and strength. Gravity affects
every particle currently alive.
.. image:: /img/paranim7.gif
Radial acceleration
-------------------
If this acceleration is positive, particles are accelerated away from
the center. If negative, they are absorbed towards it.
.. image:: /img/paranim8.gif
Tangential acceleration
-----------------------
This acceleration will use the tangent vector to the center. Combining
with radial acceleration can do nice effects.
.. image:: /img/paranim9.gif
Damping
-------
Damping applies friction to the particles, forcing them to stop. It is
specially useful for sparks or explosions, which usually begin with a
high linear velocity and then stop as they fade.
.. image:: /img/paranim10.gif
Initial angle
-------------
Determines the initial angle of the particle (in degress). This parameter
is mostly useful randomized.
.. image:: /img/paranim11.gif
Initial & final size
--------------------
Determines the initial and final scales of the particle.
.. image:: /img/paranim12.gif
Color phases
------------
Particles can use up to 4 color phases. Each color phase can include
transparency.
Phases must provide an offset value from 0 to 1, and always in
ascending order. For example, a color will begin at offset 0 and end
in offset 1, but 4 colors might use different offsets, such as 0, 0.2,
0.8 and 1.0 for the different phases:
.. image:: /img/particlecolorphases.png
Will result in:
.. image:: /img/paranim13.gif
Global parameters
-----------------
These parameters affect the behavior of the entire system.
Lifetime
--------
The time in seconds that every particle will stay alive. When lifetime
ends, a new particle is created to replace it.
Lifetime: 0.5
.. image:: /img/paranim14.gif
Lifetime: 4.0
.. image:: /img/paranim15.gif
Timescale
---------
It happens often that the effect achieved is perfect, except too fast or
too slow. Timescale helps adjust the overall speed.
Timescale everything 2x:
.. image:: /img/paranim16.gif
Preprocess
----------
Particle systems begin with 0 particles emitted, then start emitting.
This can be an inconvenience when just loading a scene and systems like
a torch, mist, etc begin emitting the moment you enter. Preprocess is
used to let the system process a given amount of seconds before it is
actually shown the first time.
Emit timeout
------------
This variable will switch emission off after given amount of seconds
being on. When zero, itś disabled.
Offset
------
Allows to move the emission center away from the center
Half extents
------------
Makes the center (by default 1 pixel) wider, to the size in pixels
desired. Particles will emit randomly inside this area.
.. image:: /img/paranim17.gif
It is also possible to set an emission mask by using this value. Check
the "Particles" menu on the 2D scene editor viewport and select your
favorite texture. Opaque pixels will be used as potential emission
location, while transparent ones will be ignored:
.. image:: /img/paranim19.gif
Local space
-----------
By default this option is on, and it means that the space that particles
are emitted to is contained within the node. If the node is moved, all
particles are moved with it:
.. image:: /img/paranim20.gif
If disabled, particles will emit to global space, meaning that if the
node is moved, the emissor is moved too:
.. image:: /img/paranim21.gif
Explosiveness
-------------
If lifetime is 1 and there are 10 particles, it means every particle
will be emitted every 0.1 seconds. The explosiveness parameter changes
this, and forces particles to be emitted all together. Ranges are:
- 0: Emit all particles together.
- 1: Emit particles at equal interval.
Values in the middle are also allowed. This feature is useful for
creating explosions or sudden bursts of particles:
.. image:: /img/paranim18.gif
Randomness
----------
All physics parameters can be randomized. Random variables go from 0 to
1. the formula to randomize a parameter is:
::
initial_value = param_value + param_value*randomness

View File

@@ -1,441 +0,0 @@
.. _doc_physics_introduction:
Physics introduction
====================
Our world is made of tangible matter. In our world, a piano can't go
through a wall when going into a house. It needs to use the door. Video
games are often like the the real world and Pac-Man can't go through the
walls of his maze (although he can teleport from the left to the right
side of the screen and back).
Anyway, moving sprites around is nice but one day they have to collide
properly, so let's get to the point.
Shapes
------
The base collidable object in Godot's 2D world is a
:ref:`Shape2D <class_Shape2D>`.
There are many types of shapes, all of them inherit this base class:
- :ref:`CircleShape2D <class_CircleShape2D>`
- :ref:`RectangleShape2D <class_RectangleShape2D>`
- :ref:`CapsuleShape2D <class_CapsuleShape2D>`
- :ref:`ConvexPolygonShape2D <class_ConvexPolygonShape2D>`
- :ref:`ConcavePolygonShape2D <class_ConcavePolygonShape2D>`
- etc. (there are others check the class list).
Shapes are of type
:ref:`Resource <class_Resource>`,
but they can be created via code easily. For example:
::
# Create a circle
var c = CircleShape2D.new()
c.set_radius(20)
# Create a box
var b = RectangleShape2D.new()
b.set_extents(Vector2(20,10))
The main use for shapes is checking collision/intersection and getting
resolution information. Shapes are mostly convex, (except the
concavepolygon one, which is just a list of segments to check collision
against). This collision check is done easily with the built-in
functions like:
::
# Check if there is a collision between two shapes, each with a transform
if b.collide(b_xform, a, a_xform):
print("OMG Collision!")
Godot will return correct collision and collision info from the
different calls to the Shape2D api. Collision between all shapes and
transforms can be done this way, or even obtaining contact information,
motion casting, etc.
Transforming shapes
~~~~~~~~~~~~~~~~~~~
As seen before in the collide functions, 2D shapes in Godot can be
transformed by using a regular :ref:`Matrix32 <class_Matrix32>`
transform, meaning the functions can check for collisions while the
shapes are scaled, moved and
rotated. The only limitation to this is that shapes with curved sections
(such as circle and capsule) can only be scaled uniformly. This means
that circle or capsule shapes scaled in the form of an ellipse **will
not work properly**. This is a limitation on the collision algorithm
used (SAT), so make sure that your circle and capsule shapes are always
scaled uniformly!
.. image:: /img/shape_rules.png
When problems begin
-------------------
Even though this sounds good, reality is that collision detection alone
is usually not enough in most scenarios. Many problems start arising as
long as the development of the game is in progress:
Too many combinations!
~~~~~~~~~~~~~~~~~~~~~~
Games have several dozens, hundreds, thousands! of objects that can
collide and be collided. The typical approach is to test everything
against everything in two for loops like this:
::
for i in colliders:
for j in colliders:
if (i.collides(j)):
do_collision_code()
But this scales really bad. Let's imagine there are only 100 objects in
the game. This means that 100\*100=10000 collisions will need to be
tested each frame. This is a lot!
Visual aid
~~~~~~~~~~
Most of the time, creating a shape via code is not enough. We need to
visually place it over a sprite, draw a collision polygon, etc. It is
obvious that we need nodes to create the proper collision shapes in a
scene.
Collision resolution
~~~~~~~~~~~~~~~~~~~~
Imagine we solved the collision issue, we can tell easily and quickly
which shapes overlap. If many of them are dynamic objects that move
around, or move according to newtonian physics, solving a collision of
multiple objects can be really difficult code-wise.
Introducing... Godot's physics engine!
--------------------------------------
To solve all these problems, Godot has a physics and collision engine
that is well integrated into the scene system, yet it allows different
levels and layers of functionality. The built-in physics engine can be
used for:
- Simple Collision Detection: See :ref:`Shape2D <class_Shape2D>`
API.
- Scene Kinematics: Handle shapes, collisions, broadphase, etc as
nodes. See :ref:`Area2D <class_Area2D>`.
- Scene Physics: Rigid bodies and constraints as nodes. See
:ref:`RigidBody2D <class_RigidBody2D>`, and the joint nodes.
Units of measure
~~~~~~~~~~~~~~~~
It is often a problem when integrating a 2D physics engine to a game
that such engines are optimized to work using meters as unit of measure.
Godot uses a built-in custom 2D physics engine that is designed to
function properly in pixels, so all units and default values used for
stabilization are tuned for this, making development more
straightforward.
CollisionObject2D
-----------------
:ref:`CollisionObject2D <class_CollisionObject2D>`
is the (virtual) base node for everything that can be collided in 2D.
Area2D, StaticBody2D, KinematicBody2D and RigidBody2D all inherit from
it. This node contains a list of shapes (Shape2D) and a relative
transform. This means that all collisionable objects in Godot can use
multiple shapes at different transforms (offset/scale/rotation). Just
remember that, as mentioned before, **non-uniform scale will not work
for circle and capsule shapes**.
.. image:: /img/collision_inheritance.png
A CollisionObject2D comes in different flavors: StaticBody2D, RigidBody2D,
KinematicBody2D and Area2D. However, before we dig into them, let's have
a look how to define the shape of a collision object.
There are two special nodes for that.
CollisionShape2D
~~~~~~~~~~~~~~~~
This node is a helper node, which must be created as a direct child of a
CollisionObject2D-derived node: :ref:`Area2D <class_Area2D>`,
:ref:`StaticBody2D <class_StaticBody2D>`, :ref:`KinematicBody2D <class_KinematicBody2D>`,
:ref:`RigidBody2D <class_RigidBody2D>`.
The purpose of a CollisionShape2D instance is to add collision shapes to
its parent class. Multiple children of type CollisionShape2D can be added to a
CollisionObject2D-derived object with the effect that the parent will
simply get more collision shapes. When a CollisionShape2D is edited (or added, moved,
deleted) the list of shapes in the parent node is updated.
At run time, though, this node does not exist and it can't be accessed with
``get_node()``. This is because it is a helper node only for editing the collision shapes.
To access the shapes created at runtime, use the CollisionObject2D API directly.
As an example, here's the scene from the platformer, containing an
Area2D (named 'coin') having two children: a CollisionShape2D (named 'collision')
and a sprite (called 'sprite'):
.. image:: /img/area2dcoin.png
CollisionPolygon2D
~~~~~~~~~~~~~~~~~~
This one is similar to CollisionShape2D, except that instead of
assigning a shape, a polygon can be edited (drawn by the user) to
determine the shape. The polygon can be convex or concave, it doesn't
matter.
Here is another scene involving a CollisionPolygon2D: A StaticBody2D has
been added as a child of a sprite so that the collision object moves together
with the sprite. In turn, the CollisionPolygon is a child of StaticBody2D, meaning it
adds collision shapes to it.
.. image:: /img/spritewithcollision.png
The CollisionPolygon2D will decompose the user-defined polygon into conves shapes
convex shapes (shapes can only be convex, remember?) before adding them to
the CollisionObject2D. The following image shows such a decomposition:
.. image:: /img/decomposed.png
Triggers
~~~~~~~~
A CollisionShape2D or CollisionPolygon2D can be set as a trigger by setting
the boolean flag with the same name. When
used in a RigidBody2D or KinematicBody2D, "trigger" shapes take part
in collision detection but are unaffected by physics (they don't block
movement etc).
Defining a collision shape as a trigger is mostly useful in two situations:
- Collisions for a specific shape shall be disabled.
- An Area2D shall send ``body_enter`` and ``body_exit`` signals when the
trigger shape enters it (useful in several situations).
StaticBody2D
~~~~~~~~~~~~
The simplest node in the physics engine is the :ref:`StaticBody2D <class_StaticBody2D>`.
This node takes part in collision detection. However, it does not move or rotate
after a collision, so physics do not influence them. The node is static.
Other nodes can collide against it and will be influenced accordingly.
The platformer example uses StaticBody2D objects for the floors and walls.
These are the static parts of a level and shall stay right where they
are even if the player jumps onto them.
KinematicBody2D
~~~~~~~~~~~~~~~
Similar to StaticBody2D, objects of type :ref:`KinematicBody2D <class_KinematicBody2D>`
are not affected by physics (although they take part in collision detection, of course).
However, KinematicBody2D are not static but can be moved via code or an animation.
They have two main uses:
- **Simulated Motion**: When these bodies are moved manually, either
from code or from an :ref:`AnimationPlayer <class_AnimationPlayer>`
(with process mode set to fixed!), the physics will automatically
compute an estimate of their linear and angular velocity. This makes
them very useful for moving platforms or other
AnimationPlayer-controlled objects (like a door, a bridge that opens,
etc). As an example, the 2d/platformer demo uses them for moving
platforms.
- **Kinematic Characters**: KinematicBody2D also has an API for moving
objects (the ``move()`` function) while performing collision tests. This
makes them really useful to implement characters that collide against
a world, but that don't require advanced physics. There is a tutorial
about it :ref:`doc_kinematic_character_2d`.
RigidBody2D
~~~~~~~~~~~
This type of body simulates Newtonian physics. It has mass, friction,
bounce, and the (0,0) coordinates simulate the center of mass. When real
physics are needed, :ref:`RigidBody2D <class_RigidBody2D>`
is the node to use. The motion of this body is affected by gravity
and/or other bodies.
Rigid bodies are usually active all the time, but when they end up in
resting position and don't move for a while, they are put to sleep until
something else wakes them up. This saves an enormous amount of CPU.
RigidBody2D nodes update their transform constantly, as it is generated
by the simulation from a position, linear velocity and angular velocity.
As a result, [STRIKEOUT:this node can't be scaled]. Scaling the children
nodes should work fine though.
A RigidBody2D has a ``Mode`` flag to change its behavior (something
which is very common in games). It can behave like a rigid body,
a character (a rigid body without the ability to rotate so that it is
always upright), a kinematic body or a static body. This flag can be
changed dynamically according to the current situation. For example,
an enemy frozen by an ice beam becomes a static body.
The best way to interact with a RigidBody2D is during the force
integration callback by overriding the function
::
func _integrate_forces(state):
[use state to change the object]
The "state" parameter is of type :ref:`Physics2DDirectBodyState <class_Physics2DDirectBodyState>`.
Please do not use the state object outside the callback as it will
result in an error.
During the evaluation of the aforementioned function, the physics engine
synchronizes state with the scene and allows full modification of the
object's parameters. Since physics may run in its own thread, parameter
changes outside that callback will not take place until the next frame.
Contact reporting
-----------------
In general, RigidBody2D will not keep track of the contacts, because
this can require a huge amount of memory if thousands of rigid bodies
are in the scene. To get contacts reported, simply increase the amount
of the "contacts reported" property from zero to a meaningful value
(depending on how many you are expecting to get). The contacts can be
later obtained via the
:ref:`Physics2DDirectBodyState.get_contact_count() <class_Physics2DDirectBodyState_get_contact_count>`
and related functions.
Contact monitoring via signals is also available (signals similar to the
ones in Area2D, described below) via a boolean property.
Area2D
~~~~~~
Areas in Godot physics have three main roles:
1. Override the space parameters for objects entering them (ie.
gravity, gravity direction, gravity type, density, etc).
2. Monitor when rigid or kinematic bodies enter or exit the area.
3. Monitor other areas (this is the simplest way to get overlap test)
The second function is the most common. For it to work, the "monitoring"
property must be enabled (it is by default). There are two types of
signals emitted by this node:
::
# Simple, high level notification
body_enter(body:PhysicsBody2D)
body_exit(body:PhysicsBody2D)
area_enter(area:Area2D)
area_exit(body:Area2D)
# Low level shape-based notification
# Notifies which shape specifically in both the body and area are in contact
body_enter_shape(body_id:int,body:PhysicsBody2D,body_shape_index:int,area_shape_index:idx)
body_exit_shape(body_id:int,body:PhysicsBody2D,body_shape_index:int,area_shape_index:idx)
area_enter_shape(area_id:int,area:Area2D,area_shape_index:int,self_shape_index:idx)
area_exit_shape(area_id:int,area:Area2D,area_shape_index:int,self_shape_index:idx)
By default, areas also receive mouse/touchscreen input, providing a
lower-level way than controls to implement this kind of input in a game.
Bodies support this but it's disabled by default.
In case of overlap, who receives collision information?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Remember that not every combination of two bodies can "report" contacts.
Static bodies are passive and will not report contacts when hit.
Kinematic Bodies will report contacts but only against Rigid/Character
bodies. Area2D will report overlap (not detailed contacts) with bodies
and with other areas. The following table should make it more visual:
+-------------------+-------------+-----------------+-----------------+---------------+--------+
| **Type** | *RigidBody* | *CharacterBody* | *KinematicBody* | *StaticBody* | *Area* |
+===================+=============+=================+=================+===============+========+
| **RigidBody** | Both | Both | Both | Rigidbody | Area |
+-------------------+-------------+-----------------+-----------------+---------------+--------+
| **CharacterBody** | Both | Both | Both | CharacterBody | Area |
+-------------------+-------------+-----------------+-----------------+---------------+--------+
| **KinematicBody** | Both | Both | None | None | Area |
+-------------------+-------------+-----------------+-----------------+---------------+--------+
| **StaticBody** | RigidBody | CharacterBody | None | None | None |
+-------------------+-------------+-----------------+-----------------+---------------+--------+
| **Area** | Area | Area | Area | None | Both |
+-------------------+-------------+-----------------+-----------------+---------------+--------+
Physics global variables
------------------------
A few global variables can be tweaked in the project settings for
adjusting how 2D physics works:
.. image:: /img/physics2d_options.png
Leaving them alone is best (except for the gravity, that needs to be
adjusted in most games), but there is one specific parameter that might
need tweaking which is the "cell_size". Godot 2D physics engine used by
default a space hashing algorithm that divides space in cells to compute
close collision pairs more efficiently.
If a game uses several colliders that are really small and occupy a
small portion of the screen, it might be necessary to shrink that value
(always to a power of 2) to improve efficiency. Likewise if a game uses
few large colliders that span a huge map (of several screens of size),
increasing that value a bit might help save resources.
Fixed process callback
----------------------
The physics engine may spawn multiple threads to improve performance, so
it can use up to a full frame to process physics. Because of this, when
accessing physics variables such as position, linear velocity, etc. they
might not be representative of what is going on in the current frame.
To solve this, Godot has a fixed process callback, which is like process
but it's called once per physics frame (by default 60 times per second).
During this time, the physics engine is in *synchronization* state and
can be accessed directly and without delays.
To enable a fixed process callback, use the ``set_fixed_process()``
function, example:
::
extends KinematicBody2D
func _fixed_process(delta):
move(direction * delta)
func _ready():
set_fixed_process(true)
Casting rays and motion queries
-------------------------------
It is very often desired to "explore" the world around from our code.
Throwing rays is the most common way to do it. The simplest way to do
this is by using the RayCast2D node, which will throw a ray every frame
and record the intersection.
At the moment there isn't a high level API for this, so the physics
server must be used directly. For this, the
:ref:`Physics2DDirectspaceState <class_Physics2DDirectspaceState>`
class must be used. To obtain it, the following steps must be taken:
1. It must be used inside the ``_fixed_process()`` callback, or at
``_integrate_forces()``
2. The 2D RIDs for the space and physics server must be obtained.
The following code should work:
::
func _fixed_process(delta):
var space = get_world_2d().get_space()
var space_state = Physics2DServer.space_get_direct_state(space)
Enjoy doing space queries!

View File

@@ -1,109 +0,0 @@
.. _doc_screen-reading_shaders:
Screen-reading shaders
======================
Introduction
~~~~~~~~~~~~
Very often it is desired to make a shader that reads from the same
screen it's writing to. 3D APIs such as OpenGL or DirectX make this very
difficult because of internal hardware limitations. GPUs are extremely
parallel, so reading and writing causes all sort of cache and coherency
problems. As a result, not even the most modern hardware supports this
properly.
The workaround is to make a copy of the screen, or a part of the screen,
to a back-buffer and then read from it while drawing. Godot provides a
few tools that makes this process easy!
TexScreen shader instruction
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Godot :ref:`doc_shading_language` has a special instruction, "texscreen", it takes as
parameter the UV of the screen and returns a vec3 RGB with the color. A
special built-in varying: SCREEN_UV can be used to obtain the UV for
the current fragment. As a result, this simple 2D fragment shader:
::
COLOR=vec4( texscreen(SCREEN_UV), 1.0 );
results in an invisible object, because it just shows what lies behind.
The same shader using the visual editor looks like this:
.. image:: /img/texscreen_visual_shader.png
TexScreen example
~~~~~~~~~~~~~~~~~
Texscreen instruction can be used for a lot of things. There is a
special demo for *Screen Space Shaders*, that you can download to see
and learn. One example is a simple shader to adjust brightness, contrast
and saturation:
::
uniform float brightness = 1.0;
uniform float contrast = 1.0;
uniform float saturation = 1.0;
vec3 c = texscreen(SCREEN_UV);
c.rgb = mix(vec3(0.0), c.rgb, brightness);
c.rgb = mix(vec3(0.5), c.rgb, contrast);
c.rgb = mix(vec3(dot(vec3(1.0), c.rgb)*0.33333), c.rgb, saturation);
COLOR.rgb = c;
Behind the scenes
~~~~~~~~~~~~~~~~~
While this seems magical, it's not. The Texscreen instruction, when
first found in a node that is about to be drawn, does a full-screen
copy to a back-buffer. Subsequent nodes that use texscreen() in
shaders will not have the screen copied for them, because this ends up
being very inefficient.
As a result, if shaders that use texscreen() overlap, the second one
will not use the result of the first one, resulting in unexpected
visuals:
.. image:: /img/texscreen_demo1.png
In the above image, the second sphere (top right) is using the same
source for texscreen() as the first one below, so the first one
"disappears", or is not visible.
To correct this, a
:ref:`BackBufferCopy <class_BackBufferCopy>`
node can be instanced between both spheres. BackBufferCopy can work by
either specifying a screen region or the whole screen:
.. image:: /img/texscreen_bbc.png
With correct back-buffer copying, the two spheres blend correctly:
.. image:: /img/texscreen_demo2.png
Back-buffer logic
~~~~~~~~~~~~~~~~~
So, to make it clearer, here's how the backbuffer copying logic works in
Godot:
- If a node uses the texscreen(), the entire screen is copied to the
back buffer before drawing that node. This only happens the first
time, subsequent nodes do not trigger this.
- If a BackBufferCopy node was processed before the situation in the
point above (even if texscreen() was not used), this behavior
described in the point above does not happen. In other words,
automatic copying of the entire screen only happens if texscreen() is
used in a node for the first time and no BackBufferCopy node (not
disabled) was found before in tree-order.
- BackBufferCopy can copy either the entire screen or a region. If set
to only a region (not the whole screen) and your shader uses pixels
not in the region copied, the result of that read is undefined
(most likely garbage from previous frames). In other words, it's
possible to use BackBufferCopy to copy back a region of the screen
and then use texscreen() on a different region. Avoid this behavior!

View File

@@ -1,42 +0,0 @@
.. _doc_size_and_anchors:
Size and anchors
----------------
If a game was to be always run in the same device and at the same
resolution, positioning controls would be a simple matter of setting the
position and size of each one of them. Unfortunately, it is rarely the
case.
Only TVs nowadays have a standard resolution and aspect ratio.
Everything else, from computer monitors to tablets, portable consoles
and mobile phones have different resolutions and aspect ratios.
There are several ways to handle this, but for now let's just imagine
that the screen resolution has changed and the controls need to be
re-positioned. Some will need to follow the bottom of the screen, others
the top of the screen, or maybe the right or left margins.
.. image:: /img/anchors.png
This is done by editing the *margin* properties of controls. Each
control has four margins: left, right, bottom and top. By default all of
them represent a distance in pixels relative to the top-left corner of
the parent control or (in case there is no parent control) the viewport.
.. image:: /img/margin.png
When horizontal (left,right) and/or vertical (top,bottom) anchors are
changed to END, the margin values become relative to the bottom-right
corner of the parent control or viewport.
.. image:: /img/marginend.png
Here the control is set to expand its bottom-right corner with that of
the parent, so when re-sizing the parent, the control will always cover
it, leaving a 20 pixel margin:
.. image:: /img/marginaround.png
Finally, there is also a ratio option, where 0 means left, 1 means right
and anything in between is interpolated.

View File

@@ -1,165 +0,0 @@
.. _doc_using_tilemaps:
Using tilemaps
~~~~~~~~~~~~~~
Introduction
------------
Tilemaps are a simple and quick way to make 2D game levels. Basically,
you start with bunch of reference tiles (or pieces) that can be put in a
grid, as many times each as desired:
.. image:: /img/tilemap.png
Collisions can also be added to the tiles, allowing for both 2D side
scrolling and top down games.
Making a tileset
----------------
To begin, a tileset needs to be made. Here are some tiles for it.
They are all in the same image because artists will often prefer this.
Having them as separate images also works.
.. image:: /img/tileset.png
Create a new project and move the above png image into the directory.
We will be creating a :ref:`TileSet <class_TileSet>`
resource. While this resource exports properties, it's pretty difficult
to get complex data into it and maintain it. Here is what it would look like to
manually edit the resource:
.. image:: /img/tileset_edit_resource.png
There's enough properties to get by, and with some effort editing this
way can work, but the easiest way to edit and maintain a tileset is exporting
it from a specially-crafted scene!
TileSet scene
-------------
Create a new scene with a regular node or node2d as root. For each tile,
add a sprite as a child. Since tiles here are 50x50, enabling snap might be
a good idea.
If more than one tile is present in the source image, make sure to use
the region property of the sprite to adjust which part of the texture is being
used.
Finally, make sure to name your sprite node correctly, this will ensure
that, in subsequent edits to the tileset (for example, if added
collision, changed the region, etc), the tile will still be **identified
correctly and updated**. This name should be unique.
Sounds like a lot of requirements, so here's a screenshot that shows
where everything of relevance is:
.. image:: /img/tile_example.png
Continue adding all the tiles, adjusting the offsets if needed (if you have
multiple tiles in a single source image). Again, remember that their names must
be unique.
.. image:: /img/tile_example2.png
Collision
---------
To add collision to a tile, create a StaticBody2D child for each sprite.
This is a static collision node. Then, as a child of the StaticBody2D,
create a CollisionShape2D or CollisionPolygon. The latter is recommended
because it is easier to edit:
.. image:: /img/tile_example3.png
Finally, edit the polygon, this will give the tile a collision.
**Remember to use snap!**. Using snap will make sure collision polygons
are aligned properly, allowing a character to walk seamlessly from tile
to tile. Also **do not scale or move** the collision and/or collision
polygon nodes. leave them at offset 0,0, with scale 1,1 and rotation 0
respect to the parent sprite.
.. image:: /img/tile_example4.png
Keep adding collisions to tiles until we are done. Note that BG is just
a background, so it should not have a collision.
.. image:: /img/tile_example5.png
OK! We're done! Remember to save this scene for future edit, call it
"tileset_edit.scn" or something like that.
Exporting a TileSet
-------------------
With the scene created and opened in the editor, next step will be to
create a tileset. Use Scene > Convert To > Tile Set from the Scene Menu:
.. image:: /img/tileset_export.png
Then choose a filename, like "mytiles.res". Make sure the "Merge With
Existing" option is toggled on. This way, every time the tileset
resource file is overwritten, existing tiles are merged and updated
(they are referenced by their unique name, so again, **name your tiles
properly**).
.. image:: /img/tileset_merge.png
Using the TileSet in a TileMap
------------------------------
Create a new scene, use any node or node2d as root, then create a
:ref:`TileMap <class_TileMap>` as
a child.
.. image:: /img/tilemap_scene.png
Go to the tileset property of this node and assign the one created in
previous steps:
.. image:: /img/tileset_property.png
Also set the cell size to '50', since that is the size used by the
tiles. Quadrant size is a tuning value, which means that the engine will
draw and cull the tilemap in blocks of 16x16 tiles. This value is
usually fine and does not need to be changed, but can be used to tune
performance in specific cases (if you know what you are doing).
Painting your world
-------------------
With all set, make sure the TileMap node is selected. A red grid will
appear on screen, allowing to paint on it with the selected tile on the
left palette.
.. image:: /img/tile_example6.png
To avoid moving and selecting the tilemap node accidentally (something
common given it's a huge node), it is recommended that you lock it,
using the lock button:
.. image:: /img/tile_lock.png
Offset and scaling artifacts
----------------------------
When using a single texture for all the tiles, scaling the tileset (or
even moving to a non pixel-aligned location) will most likely result in
filtering artifacts like this:
.. image:: /img/tileset_filter.png
This can't be avoided, as it is the way the hardware bilinear filter
works. So, to avoid this situation, there are a few workarounds, try the
ones that look better for you:
- Use a single image for each tile, this will remove all artifacts but
can be more cumbersome to implement, so try the options below first.
- Disable filtering for either the tileset texture or the entire image
loader (see the :ref:`doc_managing_image_files` asset pipeline tutorial).
- Enable pixel snap (set: "Scene > Project Settings >
Display/use_2d_pixel_snap" to true).
- Viewport Scaling can often help with shrinking the map (see the
:ref:`doc_viewports` tutorial).

View File

@@ -1,99 +0,0 @@
.. _doc_viewport_and_canvas_transforms:
Viewport and canvas transforms
==============================
Introduction
------------
This tutorial is created after a topic that is a little dark for most
users, and explains all the 2D transforms going on for nodes from the
moment they draw their content locally to the time they are drawn into
the screen.
Canvas transform
----------------
As mentioned in the previous tutorial, :ref:`doc_canvas_layers`, every
CanvasItem node (remember that Node2D and Control based nodes use
CanvasItem as their common root) will reside in a *Canvas Layer*. Every
canvas layer has a transform (translation, rotation, scale, etc.) that
can be accessed as a :ref:`Matrix32 <class_Matrix32>`.
Also covered in the previous tutorial, nodes are drawn by default in Layer 0,
in the built-in canvas. To put nodes in a different layer, a :ref:`CanvasLayer
<class_CanvasLayer>` node can be used.
Global canvas transform
-----------------------
Viewports also have a Global Canvas transform (also a
:ref:`Matrix32 <class_Matrix32>`). This is the master transform and
affects all individual *Canvas Layer* transforms. Generally this
transform is not of much use, but is used in the CanvasItem Editor
in Godot's editor.
Stretch transform
-----------------
Finally, viewports have a *Stretch Transform*, which is used when
resizing or stretching the screen. This transform is used internally (as
described in :ref:`doc_multiple_resolutions`), but can also be manually set
on each viewport.
Input events received in the :ref:`MainLoop._input_event() <class_MainLoop__input_event>`
callback are multiplied by this transform, but lack the ones above. To
convert InputEvent coordinates to local CanvasItem coordinates, the
:ref:`CanvasItem.make_input_local() <class_CanvasItem_make_input_local>`
function was added for convenience.
Transform order
---------------
For a coordinate in CanvasItem local properties to become an actual
screen coordinate, the following chain of transforms must be applied:
.. image:: /img/viewport_transforms2.png
Transform functions
-------------------
Obtaining each transform can be achieved with the following functions:
+----------------------------------+--------------------------------------------------------------------------------------+
| Type | Transform |
+==================================+======================================================================================+
| CanvasItem | :ref:`CanvasItem.get_global_transform() <class_CanvasItem_get_global_transform>` |
+----------------------------------+--------------------------------------------------------------------------------------+
| CanvasLayer | :ref:`CanvasItem.get_canvas_transform() <class_CanvasItem_get_canvas_transform>` |
+----------------------------------+--------------------------------------------------------------------------------------+
| CanvasLayer+GlobalCanvas+Stretch | :ref:`CanvasItem.get_viewport_transform() <class_CanvasItem_get_viewport_transform>` |
+----------------------------------+--------------------------------------------------------------------------------------+
Finally then, to convert a CanvasItem local coordinates to screen
coordinates, just multiply in the following order:
::
var screen_coord = get_viewport_transform() * ( get_global_transform() * local_pos )
Keep in mind, however, that it is generally not desired to work with
screen coordinates. The recommended approach is to simply work in Canvas
coordinates (``CanvasItem.get_global_transform()``), to allow automatic
screen resolution resizing to work properly.
Feeding custom input events
---------------------------
It is often desired to feed custom input events to the scene tree. With
the above knowledge, to correctly do this, it must be done the following
way:
::
var local_pos = Vector2(10,20) # local to Control/Node2D
var ie = InputEvent()
ie.type = InputEvent.MOUSE_BUTTON
ie.button_index = BUTTON_LEFT
ie.pos = get_viewport_transform() * (get_global_transform() * local_pos)
get_tree().input_event(ie)