Friday, April 20, 2018

26. enum

We use a root node of Node2D and attach a Panel and Label. Both the Panel and Label take the entire window of 200 by 200.


An enum can be used for defining consecutive integers. They are often used in state management. It makes more sense to check if state == RUNNING rather than state == 0.


This script illustrates use of enum, both unnamed and named versions. The unnamed is same as defining many const statements with consecutive integer values, while the named results in dictionary. The dictionary value can be read as STATE.ST1 or STATE['ST1']



extends Node2D

enum {STATE1, STATE2, STATE3}
enum STATE {ST1, ST2, ST3}
var string

func _ready():
    $Label.set_align(Label.ALIGN_CENTER)
    $Label.set_valign(Label.VALIGN_CENTER)
    string  = 'STATE1 = ' + str(STATE1) + '\n'
    string += 'STATE2 = ' + str(STATE2) + '\n'
    string += 'STATE3 = ' + str(STATE3) + '\n'
    string += 'STATE.ST1 = ' + str(STATE.ST1) + '\n'
    string += 'STATE.ST2 = ' + str(STATE.ST2) + '\n'
    string += 'STATE.ST3 = ' + str(STATE.ST3)
    $Label.set_text(string)

This is the output:


25. AudioStreamPlayer

We use a root Node and attach a script.


We have the child of AudioStreamPlayer and with an audio file set.


This is the script to play the audio when up arrow is pressed.



extends Node
func _process(delta):
    if Input.is_action_just_pressed('ui_up'):
        $AudioStreamPlayer.play()

24. Drawing Regular Polygon

We use a root Node2D and attach a script.


In the script, we draw a polygon of N equal sides, around a center point. As N becomes large, we approach a circle. In the function draw_regular_polygon, we use dictionary col. In the loop we initial or update three keys 'r', 'g', and 'b'. We could have read the elements as col['r'] or col.r, etc.


This is the script to draw the regular polygon:



extends Node2D

func _ready():
    randomize()

func _draw():
    var cen = Vector2(100, 100)
    var rad = 90
    var N = 8
    draw_regular_polygon(cen, rad, N)

func draw_regular_polygon(cen, rad, N):
    if N < 3: return
    var col = {}
    var cols
    var ang
    var x
    var y
    var points = PoolVector2Array()
    var colors = PoolColorArray()
    for i in range(N + 1):
        col['r'] = rand_range(0,1)
        col['g'] = rand_range(0,1)
        col['b'] = rand_range(0,1)
        cols = Color(col.r, col.g, col.b)
        ang = i * (2 * PI / N)
        x = rad * cos(ang)
        y = rad * sin(ang)
        points.append(cen + Vector2(x, y))
        colors.append(cols)
    draw_polygon(points, colors)


The 8-sided polygon is shown below:


23. draw_rect and draw_circle

We use a root Node2D and attach a script.


In the script, we draw a circle and rectangle.


This is the script to draw the 2 shapes:



extends Node2D

func _draw():
    var cen = Vector2(25, 25)
    var rad = 20
    var col = Color(0, 0, 1)
    draw_circle (cen, rad, col)
    col = Color(1, 0, 0)
    var rect = Rect2(Vector2(50, 50),Vector2(50, 50))
    draw_rect(rect, col)


The circle has 25-pixel radius and rectangle has size of 50 by 50 pixel as shown below:


Thursday, April 19, 2018

22. Saving data

We use a root Node and attach a script. We have 2 childs of Node, a Button and a Label.


We can use $ instead of get_node. We can save data by using File methods, such as store_line for saving a string and newline. The save will be done when button is clicked.


This script is attached to the Node.



extends Node

var label
var button
var pos

func _ready():
    label = $Label
    label.rect_position = Vector2(10,10)
    pos = get_viewport().get_mouse_position()
    label.set_text("Pos: " + str(pos))
    button = $Button
    button.rect_position = Vector2(50,50)
    button.set_text('Save')
    set_process_input(true)

func _input(event):
    if event is InputEventMouseButton:
        pos = event.position
        label.set_text("Pos: " + str(pos))

func _on_Button_pressed():
    var file = File.new()
    file.open("res://save_pos.dat", file.WRITE)
    file.store_line(str(pos))
    file.store_line('Another line')
    file.close()


This is a possible content of the file:

(58, 59)
Another line


21. draw_line

We use a root Node2D and attach a script.


In the script, we draw 3 lines using draw_line function of CanvasItem which is in the Node2D hierarchy. We have to use the virutal function _draw() from this class.


This script is attached to the Node2D.



extends Node2D

var from = Vector2(10,10)
var to = Vector2(190,20)
var col = Color(0,0,1)

func _draw():
    draw_line (from, to, col)
    from += Vector2(0, 50)
    to += Vector2(0, 50)
    draw_line (from, to, col, 5)
    from += Vector2(0, 50)
    to += Vector2(0,50)
    draw_line (from, to, col, 5, true)


This is the output showing the 3 lines (first line has width of 1 while second and third line have width of 5).

20. AnimationPlayer

The AnimationPlayer node is used to create any kind of animation.


Usually they will be used to control a sprite (or many sprites), but could be any node or function within a node.


Here we have an AnimationPlayer as the root node and a Sprite as child, which Godot icon texture.


Four keyframes are inserted. We only have one track (for location) as shown:



This shows the complete animation on the 200 by 200 window.


Wednesday, April 18, 2018

19. Particles2D

We have a Particles2D note. We use a texture (blue circle), and set its gravity in -y direction.


We get this output:


18. Parallax

We have 3 scenes: red.tscn, green.tscn, blue.tscn that contain a sprite of 16 by 16 with the color indicated.


In the main scene with root node of Node2D, we have a ParallaxBackground node with 3 ParallaxLayer childs.


This script is attached to the Node2D.



extends Node2D

onready var layer1 = get_node("parallax/layer1")
onready var layer2 = get_node("parallax/layer2")
onready var layer3 = get_node("parallax/layer3")

func _ready():
    var red_scene = load("res://red.tscn")
    var green_scene = load("res://green.tscn")
    var blue_scene = load("res://blue.tscn")
    var red
    var green
    var blue
    for i in range(10):
        red = red_scene.instance()
        red.position = Vector2(20 * i + 10, 10)
        green = green_scene.instance()
        green.position = Vector2(20 * i + 10, 30)
        blue = blue_scene.instance()
        blue.position = Vector2(20 * i + 10, 50)
    layer1.add_child(red)
    layer2.add_child(green)
    layer3.add_child(blue)


func _process(delta):
    layer1.motion_offset.x += 1
    layer2.motion_offset.x += 1.5
    layer3.motion_offset.x += 2


This is the output showing the layers moving at different speeds.


17. CollisionPolygon2D

We add another Area2D node, renamed as walls, and we create a child of CollisionPolygon2D. Should we want a visual wall, we will also want to add a sprite.


In the editor we can click on + at top and add points. Finally we can click on the top to close the collision shape.


We can edit the vertices in the Inspector for more positional control, or even pass them programmatically.


This shows the node structure so far and the collision shape for the wall.


16. Area2D and CollisionShape2D

For detecting collisions we need either physics node or Area2D node.


We use an Area2D node, named player, with 2 childs, a sprite (Godot icon), and Collision2DShape. The shape selected is RectangleShape2D


This shows the node structure for the scene and the collision.