Swipe management in a game project on Godot Engine

Greetings to all! Today I would like to talk about how to implement swipe management in a game project for Android on the Godot Engine.

image

My name is Peter, and I am one of the active users of the Godot Engine game engine.
In the Russian-language segment, there is a huge shortage of materials on this tool, which surprises me very much, since it is one of the fastest growing game engines.
Of course, it is in many ways inferior to such engines as Unity, UE, and the like, and you won’t make a AAA class game on it.

However! It is free (full), cross-platform (full), and its weight is about 60 megabytes, as opposed to the same Unity.

The engine runs on most devices, even if the latter are from a very budget line. Also, “out of the box”, it is already Russified, has all the necessary tools on board, does not require additional software, and does not eat up all RAM in running form.

I already saw a couple of articles on Habré on it, and this is very small, since it is so friendly to the developer that it’s a big omission to go past it and not try it.

The topic of this post is the implementation of swipe management (gestures) in an Android project.
In general, the experience of my use of the engine is quite extensive, and if the topic gets a response, I can arrange an entire training course. By this post I want to at least draw your attention to the engine.

As a programming language, you can use, again, out of the box, two options: GDScript and C #. I will use the first one.

The interface of the main editor looks like this:

image

In it you can work simultaneously with 3D, 2D, scripts and in general everything that a developer may require.

The engine uses an approach in which your game is a set of scenes nested into each other. And there may be some confusion, because I use the term “scene” for nodes that are just game scenes (situations, windows, game states (menus, games, etc.)), and for other cases I use the term "Prefab" borrowed from Unity.

Since in this post I will consider a special case, I will not expand on some topics. If something is unclear, there are comments.

So, the main scene for the demonstration, we will have a game.

Its structure looks like this:

image

The root node of the game stores nested inside itself:
- world, - stores level data in it
- - level, - a set of environment objects (blocks, rings, obstacles)
- - player, - player object
- - InterpolatedCamera, - smooth the camera that watches the player
- gui, - interface, will not be involved.

Names to objects and structure are arbitrary and this is only a special case.
Near some objects, you can see icons saying that this object is a prefab (nested scene) and a script can also be added to it.

So, clicking on the “script” icon, we get into the script editor, in fact, the engine’s operating mode simply switches.

image

In this operating mode, you can edit the behavior of objects. Actually, in this case it is a script of the world object, which, when loading an object into the game, sets the camera object (InterpolatedCamera) sets the target for tracking.

extends Spatial

func _ready():
	$InterpolatedCamera.target = '../player/camera' #  , ,         (  ).   player  "camera"   pivot.   .         .

Syntactically, GDScript is similar to Python. You can take a brief training on GDScript in Russian here: GDScript Book

With the world object, it’s clear, it just sets the camera’s tracking target. The next object (already a child of world) is level. Its structure looks like this:

image

In fact, these are simply arranged objects with physical properties that do not have scripts or behavior. In addition to the "cell" objects. These are spinning rings disappearing in contact with the player’s object.

The player object is most interesting right now, which contains the swipe control logic for touch screens.

This prefab looks like this:

image

The root object has a script, which we will get to a little later.
First, consider nested objects.

  • camera, — , , . player.
  • CollisionShape, — . «» . , , . .
  • MeshInstance, — . , . Blender 3D , .
  • Tween, . .

Well, now consider the script itself in the root object. It turns out to be the most voluminous in the whole "game".

image

Well, its description and decoding.


extends KinematicBody #       

#  
const GRAV = 0.5 #   (      Y, ..       ,     )
const SPEED = 2 #  
const SWIPE_SPEED = 30 #       
const JUMP_SPEED = 10 #     

onready var ball = $MeshInstance #        
onready var tween = $Tween #      
var vel = Vector3() #     
var swipe = '' #       


func _ready():
	pass #        ;    


#       (60FPS)  
func _physics_process(delta): # delta -  Delta Time ,  ,    
	vel.y -= GRAV #      (  )
	vel.z = -SPEED #     .   
	ball.rotate_x(-delta * SPEED * 2) #     ,   ""

	if swipe && swipe != 'swiped': #         
		if swipe == 'up' && is_on_floor(): #        ()
			vel.y = JUMP_SPEED #     ,   -  
		elif swipe == 'left' || swipe == 'right': #     
			tween.interpolate_property(self, "translation", #      
				translation, translation+Vector3(-2 if swipe == 'left' else 2,0,0), 0.2, #    ,         X.      . -2  ,  2
				Tween.TRANS_CUBIC, Tween.EASE_IN_OUT) #     "" 
			tween.start() #   
		swipe = 'swiped' #   ,   

	vel = move_and_slide(vel, Vector3.UP) #       ,                  

#       
func _input(e):
	if e is InputEventScreenDrag: # ,       
		if !swipe: #       
			if e.relative.y < -SWIPE_SPEED: #       Y
				swipe = 'up' #     (     )    ( ,          ),     " (UP)"
			elif e.relative.x < -SWIPE_SPEED: #      ,     X.     -  
				swipe = 'left'
			elif e.relative.x > SWIPE_SPEED: #  ,
				swipe = 'right' #  

	elif e is InputEventScreenTouch: #     
		if !e.pressed: #      
			swipe = '' #   

I described each line, I hope, with scripts everything plus or minus is clear.

If in Russian, then when we move our finger across the screen, we register the direction of movement and speed. If the finger moves at the desired speed, we count the swipe. Based on which axis and in which direction the movement was going, we have three options: UP, LEFT, RIGHT.
We write the received value into a variable, which is immediately picked up by the event of updating the state of the object, and performs the necessary actions with it, after which it marks the event as fulfilled and expects the next.

I took not the easiest way to implement a swipe, but it is quite reliable and works in most situations. Of course, it depends on the genre and type of game.

As a result of the work done, we get an example of how easy it is to implement swipe management in literally ten minutes.

In total, it took me about 30 minutes, this is taking into account the creation of models in Blender.

Well, according to tradition ...

Development Video


Source code

All Articles