Fixing grammar (#425)

Fixed some grammar, as well as some edits to make things clearer.
This commit is contained in:
Ertain
2017-08-01 15:04:52 -05:00
committed by Rémi Verschelde
parent 0228593b2c
commit a5272fc63a
9 changed files with 99 additions and 98 deletions

View File

@@ -8,8 +8,8 @@ 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
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.
@@ -37,7 +37,7 @@ 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.
:ref:`Node2D <class_Node2D>`. Then override the _draw() function.
::
@@ -104,9 +104,9 @@ 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.
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 at which it stops. 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 your 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.
Basically, drawing a shape on screen requires it to be decomposed into a certain number of points, linked from 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 it being angular-looking. On the contrary, if your 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.
::
@@ -124,17 +124,17 @@ Basically, drawing a shape on screen requires it to be decomposed into a certain
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 next step consists of computing the actual positions of these 32 points that compose an arc. This is done in the first for-loop: we iterate over the number of points for which 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 reason why each angle is reduced by 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 by 90° in order to start counting from 0 o'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.
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 drew it one by one. But this is 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.
We now have a function that draws stuff on the screen: it is time to call in the _draw() function.
::
@@ -154,7 +154,7 @@ Result:
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:
We can take this a step further and not only write a function that draws the plain portion of the disc defined by the arc, but also its shape. The method is exactly the same as previously, except that we draw a polygon instead of lines:
::
@@ -190,7 +190,7 @@ First, we have to make both angle_from and angle_to variables global at the top
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.
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 angle 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.
@@ -227,7 +227,7 @@ Also, don't forget to modify the _draw() function to make use of these variables
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 it 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.
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 that your program runs at the same speed on everybody's 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.
@@ -252,5 +252,5 @@ 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
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

@@ -33,8 +33,8 @@ 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
There's enough properties to get by. 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
@@ -48,7 +48,7 @@ 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
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.
@@ -58,9 +58,9 @@ 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.
Continue adding all the tiles, adjusting the offsets if needed (that is, if you have
multiple tiles in a single source image). Again, *remember that their names must
be unique*.
.. image:: /img/tile_example2.png
@@ -68,33 +68,33 @@ 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:
This is a static collision node. Then create a CollisionShape2D or
CollisionPolygon as a child of the StaticBody2D. The CollisionPolygon 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
**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.
polygon nodes. Leave them at offset 0,0, with scale 1,1 and rotation 0
with respect to the parent sprite.
.. image:: /img/tile_example4.png
Keep adding collisions to tiles until we are done. Note that BG is just
Keep adding collisions to the 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.tscn" or something like that.
OK! We're done! Remember to save this scene for future edit. Name 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
With the scene created and opened in the editor, the next step will be to
create a tileset. Use Scene > Convert To > Tile Set from the Scene Menu:
.. image:: /img/tileset_export.png
@@ -110,7 +110,7 @@ properly**).
Using the TileSet in a TileMap
------------------------------
Create a new scene, use any Node or Node2D as root, then create a
Create a new scene, using any node or node2d as root, and then create a
:ref:`TileMap <class_TileMap>` as
a child.
@@ -124,7 +124,7 @@ previous steps:
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
usually fine and does not need to be changed, but can be used to fine tune
performance in specific cases (if you know what you are doing).
Painting your world
@@ -136,8 +136,8 @@ 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,
To avoid accidentally moving and selecting the tilemap node (something
common, given it's a huge node), it is recommended that you lock it,
using the lock button:
.. image:: /img/tile_lock.png
@@ -145,30 +145,31 @@ using the lock button:
You can also flip and rotate sprites in the TileMap editor (note:
flipping the sprite in the TileSet will have no effect). Icons at the
top right of the editor allow flipping and rotating of the currently
selected sprite - you can also use A and S to flip horizontally and
vertically. With a brick pattern like this tutorial uses, flipping the
sprites would create unpleasant discontinuities unless you're flipping
an entire region of bricks, but for some kinds of tiles flipping can
be a convenient and space-saving feature.
selected sprite - you can also use the A and S keys to flip the sprite
horizontally and vertically. With a brick pattern like this tutorial uses,
flipping the sprites would create unpleasant discontinuities unless you're
flipping an entire region of bricks. But for some kinds of tiles, flipping
can be a convenient and space-saving feature.
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:
filtering artifacts like so:
.. 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:
This is unavoidable, as it is the way the hardware bilinear filter
works. So, to avoid this situation, there are a few workarounds. Try the
one that looks 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).
- Use a single image for each tile. This will remove all artifacts, but
can be more cumbersome to implement.

View File

@@ -54,8 +54,8 @@ keyboard/joypad events (see
and :ref:`Control.grab_focus() <class_Control_grab_focus>`).
Mouse motion events are received by the control directly below the mouse
pointer. When a control receives a mouse button pressed event, all
subsequent motion events are received by the pressed control until that
pointer. When a control receives a "mouse button pressed" event, all
subsequent motion events are received by the "pressed" control until that
button is released, even if the pointer moves outside the control
boundary.
@@ -68,10 +68,10 @@ to enqueue the CanvasItem for redraw). If the control is not visible
(yet another CanvasItem property), the control does not receive any
input.
In general though, the programmer does not need to deal with drawing and
In general, though, the programmer does not need to deal with drawing and
input events directly when building UIs (that is more useful when
creating custom controls). Instead, controls emit different kinds of
signals with contextual information for when action occurs. For
signals with contextual information for when an action occurs. For
example, a :ref:`Button <class_Button>` emits
a "pressed" signal when pressed, a :ref:`Slider <class_Slider>` will
emit a "value_changed" when dragged, etc.
@@ -158,7 +158,7 @@ list of elements (for a high score table, for example), which needs a
:ref:`ScrollContainer <class_ScrollContainer>`
and a :ref:`VBoxContainer <class_VBoxContainer>`.
These kind of more advanced controls can be mixed with the regular ones
seamlessly (they are all controls after all).
seamlessly (they are all controls, after all).
Complex UI controls
~~~~~~~~~~~~~~~~~~~

View File

@@ -33,8 +33,8 @@ weird at first, but by the end of this tutorial it should make complete sense.
Instancing, step by step
------------------------
To learn how to do instancing, let's start by downloading a sample project:
:download:`instancing.zip </files/instancing.zip>`.
To learn how to do instancing, let's start with downloading a sample
project: :download:`instancing.zip </files/instancing.zip>`.
Unzip this project anywhere you like. Then, open Godot and add this project to
the project manager using the 'Import' option:
@@ -91,22 +91,21 @@ Cool, huh? This is how instancing works.
Editing instances
-----------------
Select one of the many copies of the balls and go to the property editor. Let's
make it much more bouncy. To do this, look for the Bounce parameter and set it
to 1.0:
Select one of the many copies of the balls and go to the property
editor. Let's make it bounce a lot more, so look for the Bounce
parameter and set it to 1.0:
.. image:: /img/instedit.png
Notice that a grey "revert" button appeared. When this button is present, it
means we modified a property in the instanced scene to override a specific
value that differs from the original scene. Even if that property is modified
in the original scene later, our custom value here will continue to overwrite
it. Pressing the revert button will restore the property to the value that
comes from the original scene.
Grey "revert" button will appear. When
this button is present, it means we modified a property in the
instanced scene to override a specific value in this instance. Even
if that property is modified in the original scene, the custom value
will always overwrite it. Pressing the revert button will restore the
property to the original value that came from the scene.
Conclusion
----------
Instancing seems handy, but there is more to it than meets the eye!
The next part of the tutorial will show how this feature can help you organize
your entire game...
The next part of the instancing tutorial should cover the rest..

View File

@@ -6,7 +6,7 @@ Instancing (continued)
Recap
-----
Instancing has many handy uses. At a glance, it provides:
Instancing has many handy uses. At a glance, with instancing you have:
- The ability to subdivide scenes and make them easier to manage.
- A more flexible alternative to prefabs (and much more powerful given that
@@ -26,7 +26,7 @@ When making games with Godot, the recommended approach is to dismiss most
common design patterns, such as MVC or Entity-Relationship diagrams, and
instead think about your scenes in a more natural way. Start by imagining the
visible elements in your game, the ones that can be named not just by a
programmer but by anyone.
programmer, but by anyone.
For example, here's how a simple shooter game could be imagined:
@@ -44,8 +44,7 @@ A lot of time spent in programming games (or software in general) is on
designing an architecture and fitting game components to that architecture.
Designing based on scenes replaces that approach and makes development much
faster and more straightforward, allowing you to concentrate on the game logic
itself. Because most game components map directly to a scene, using a design
based on scene instantiation means little other architectural code is needed.
itself. Because most game components map directly to a scene, using a design-based on scene instantiation means little other architectural code is needed.
Let's take a look at one more, somewhat more complex, example of an open-world
type game with lots of assets and nested elements:

View File

@@ -20,7 +20,7 @@ savor your magnificent creation.
Making games in Godot feels pretty much the same way. Using the engine
feels like being in a kitchen. In this kitchen, *nodes* are like a
refrigerator full of fresh ingredients to cook with.
refrigerator full of fresh ingredients with which to cook.
There are many types of nodes. Some show images, others play sound,
other nodes display 3D models, etc. There are dozens of them.
@@ -58,6 +58,9 @@ Scenes
.. image:: /img/scene_tree_example.png
Now that the concept of nodes has been defined, the next logical
step is to explain what a Scene is.
A scene is composed of a group of nodes organized hierarchically (in
tree fashion). Furthermore, a scene:
@@ -127,7 +130,7 @@ The node appears in the scene tree editor (box in the top left
corner), and the label properties appear in the Inspector (box on the
right side).
The next step will be to change the "Text" Property of the label, let's
The next step will be to change the "Text" Property of the label. Let's
change it to "Hello, World!":
.. image:: /img/hw.png
@@ -184,7 +187,7 @@ application/main_scene property and click on it to select 'hello.tscn'.
.. image:: /img/main_scene.png
With this change, now when you press the regular Play button (or F5), this
Now, with this change, when you press the regular Play button (or F5), this
scene will run, no matter which scene is actively being edited.
The project settings dialog provides a lot of options that can be saved to a

View File

@@ -20,14 +20,14 @@ tools that try to reduce the amount of code that needs to be written for
specific tasks, to speed up development.
In that sense, Godot has taken some useful design decisions towards that
goal. The first and most important is the scene system. The aim of it is
not obvious at first, but works well later on. That is, to relieve
programmers from the responsibility of architecting code.
goal. The first, and most important, is the scene system. The aim of it is
not obvious at first, but is understandable later on. That is, it relieves
programmers from the responsibility of designing and structuring code.
When designing games using the scene system, the whole project is
fragmented into *complementary* scenes (not individual ones). Scenes
complement each other, instead of being separate. There will be plenty
of examples about this later on, but it's very important to remember it.
complement (i.e. help) each other, instead of being separate. There will be
plenty of examples of this later on, but it's very important to remember it.
For those with a good amount of programming expertise, this means a
different design pattern to MVC. Godot promises efficiency at the
@@ -41,8 +41,8 @@ available engine classes.
GDScript
--------
:ref:`doc_gdscript` is a dynamically typed scripting language to fit
inside Godot. It was designed with the following goals:
:ref:`doc_gdscript` is a dynamically-typed scripting language designed to
fit inside Godot. It was designed with the following goals:
- First and most importantly, making it simple, familiar and as easy to
learn as possible.
@@ -56,7 +56,7 @@ As with most dynamically typed languages, the higher productivity
(code is easier to learn, faster to write, no compilation, etc) is
balanced with a performance penalty. But most critical code is written
in C++ already in the engine (vector ops, physics, math, indexing, etc),
resulting in a more than sufficient performance for most types of
resulting in more than sufficient performance for most types of
games.
In any case, if more performance is required, critical sections can be

View File

@@ -11,7 +11,7 @@ functions, so there is no need to check for writing code that runs all
the time. Additionally, a lot can be done with animation players.
However, it is still a very common case to have a script process on every
frame. There are two types of processing, idle processing and fixed
frame. There are two types of processing: idle processing and fixed
processing.
Idle processing is activated with the
@@ -28,7 +28,7 @@ callback will be called every frame. Example:
# do something...
The delta parameter describes the time elapsed (in seconds, as
floating point) since the previous call to _process().
floating point) since the previous call to "_process()".
Fixed processing is similar, but only needed for synchronization with
the physics engine.
@@ -55,7 +55,7 @@ Groups
Nodes can be added to groups (as many as desired per node). This is a
simple yet useful feature for organizing large scenes. There are two
ways to do this, the first is from the UI, from the Groups button under Node-panel:
ways to do this: the first is from the UI, from the Groups button under the Node panel:
.. image:: /img/groups_in_nodes.PNG
@@ -164,8 +164,8 @@ As mentioned before, it's best to use these functions.
Creating nodes
--------------
To create a node from code, just call the .new() method (like for any
other class based datatype). Example:
To create a node from code, just call the ".new()" method (like for any
other class-based datatype). Example:
::
@@ -174,7 +174,7 @@ other class based datatype). Example:
s = Sprite.new() # create a new sprite!
add_child(s) # add it as a child of this node
To delete a node, be it inside or outside the scene, free() must be
To delete a node, be it inside or outside the scene, "free()" must be
used:
::
@@ -217,7 +217,7 @@ time.
var scene = preload("res://myscene.tscn") # will load when parsing the script
But 'scene' is not yet a node containing subnodes. It's packed in a
But 'scene' is not yet a node for containing subnodes. It's packed in a
special resource called :ref:`PackedScene <class_PackedScene>`.
To create the actual node, the function
:ref:`PackedScene.instance() <class_PackedScene_instance>`
@@ -232,4 +232,4 @@ the active scene:
The advantage of this two-step process is that a packed scene may be
kept loaded and ready to use, so it can be used to create as many
instances as desired. This is especially useful to quickly instance
several enemies, bullets, etc. in the active scene.
several enemies, bullets, etc., in the active scene.

View File

@@ -22,16 +22,16 @@ in your project folder.
Scene setup
~~~~~~~~~~~
For the sake of the old times, the game will be in 640x400 pixels
To pay homage to the olden times, the game will be in 640x400 pixels
resolution. This can be configured in the Project Settings (see
:ref:`doc_scenes_and_nodes-configuring_the_project`) under Scene/Project
:ref:`doc_scenes_and_nodes-configuring_the_project`) under the Scene/Project
settings menu. The default background color should be set to black:
.. image:: /img/clearcolor.png
Create a :ref:`class_Node2D` node for the project root. Node2D is the
base type for the 2D engine. After this, add some sprites
(:ref:`class_Sprite` node) for the left and right paddles, the separator
(:ref:`class_Sprite` node) for the left and right paddles, the separator,
and ball. You can set a custom name for each node, and set the texture
for each sprite in the Inspector.
@@ -60,11 +60,11 @@ Input actions setup
~~~~~~~~~~~~~~~~~~~
Video games can be played using various input methods: Keyboard, Joypad,
Mouse, Touchscreen (multitouch)... Godot is able to use them all.
Mouse, Touchscreen (even multitouch)... Godot is able to use them all.
However, it would be interesting to define the inputs as "Input Actions"
instead of hardware actions that you'd manage separately. This way, any
input method can be used: each of them only require the user to connect
buttons to game actions that you defined.
buttons to game actions that you define.
This is Pong. The only input that matters is for the pads going up and
down.
@@ -76,9 +76,8 @@ this time move to the
In this tab, add 4 actions:
``left_move_up``, ``left_move_down``, ``right_move_up``,
``right_move_down``.
Assign the keys that you desire. A/Z (for the left player) and Up/Down
(for the right player) as keys
should work in most cases.
Assign the keys that you desire. The A/Z keys (for the left player) and
the Up/Down keys (for the right player) should work in most cases.
.. image:: /img/inputmap.png
@@ -168,8 +167,8 @@ our ball move.
Finally, the ``_process()`` function. All the code below is contained by
this function.
We have to init some useful values for computation. The first one is the
ball position (from the node), the second one is the rectangle
We have to initialize some useful values for computation. The first one is the
ball position (from the node),and the second one is the rectangle
(``Rect2``) for each pad. These rectangles will be used for collision
tests between the ball and the pads. Sprites center their textures by
default, so a small adjustment of ``pad_size / 2`` must be added.
@@ -195,7 +194,7 @@ function. That means the ball position will be updated at each new
frame.
Now that the ball has a new position, we need to test if it
collides with anything, that is the window borders and the pads. First,
collides with anything. That is, the window borders and the pads. First,
the floor and the roof:
::
@@ -218,7 +217,7 @@ speed a little.
direction = direction.normalized()
ball_speed *= 1.1
Finally, if the ball went out of the screen, it's game over. That is, we test if
Finally, if the ball moves off of the screen, it's game over. That is, we test if
the X position of the ball is less than 0 or greater than the screen
width. If so, the game restarts:
@@ -268,4 +267,4 @@ corresponding action is triggered. As soon as this happens, we simply
compute a new position for the pad in the desired direction and apply it
to the node.
That's it! A simple Pong was written with a few lines of code.
That's it! A simple Pong game was written with a few lines of code.