Initial commit

In this commit I add a human character, a traveler that can move around
a tiny world made of a single screen so far. :)

Materials used so far:
 * 'HeartBeast' video lesons: https://goo.gl/3DtqPn
 * The very informative and rich documentation of Godot itself!

For the Gamepad I used wonderful addon by fiaful:
https://github.com/fiaful/Gamepad

The beautiful arts are from "Open Pixel Project":
https://openpixelproject.itch.io
This commit is contained in:
Martin Dimitrov 2018-10-26 16:06:27 +03:00
commit 8689a4732a
119 changed files with 4479 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
.import/

17
addons/Gamepad/Gamepad.gd Normal file
View file

@ -0,0 +1,17 @@
tool
extends EditorPlugin
func _enter_tree():
# 120 - 80 - 70 (colora)
add_custom_type("GamepadContainer", "Control", preload("GamepadContainer.gd"), preload("icons/container.png"))
add_custom_type("GamepadArea", "Control", preload("GamepadArea.gd"), preload("icons/area.png"))
add_custom_type("GamepadStick", "Control", preload("GamepadStick.gd"), preload("icons/stick.png"))
add_custom_type("GamepadPaddle", "Control", preload("GamepadPaddle.gd"), preload("icons/paddle.png"))
add_custom_type("GamepadButton", "Control", preload("GamepadButton.gd"), preload("icons/button.png"))
func _exit_tree():
remove_custom_type("GamepadContainer")
remove_custom_type("GamepadArea")
remove_custom_type("GamepadStick")
remove_custom_type("GamepadPaddle")
remove_custom_type("GamepadButton")

View file

@ -0,0 +1,99 @@
###[ INFO ]######################################################################################################
# Component: GamepadArea
# Author: Francesco Iafulli (fiaful)
# E-mail: fiaful@hotmail.com
# Version: 1.0
# Last modify: 2018-07-20
# What is this:
# E' un nodo facoltativo. Le sue funzioni sono 2 (una esclude l'altra):
# - consentire agli elementi del gamepad di essere visualizzati solo quando lo schermo viene toccato e nel punto
# in cui viene toccato, ed essere invisibili il restante tempo
# - raggruppare oggetti sempre visibili del gamepad in modo da poter essere disabilitati in maniera cumulativa
# Requirements:
# - il parent di questo nodo deve essere di tipo GamepadContainer, altrimenti gli eventi non verranno intercettati
# - l'area di questo oggetto deve essere estesa a tutta la zona che si desidera avere sesibile per la visualizzazione
# dell'oggetto del gamepad in maniera dinamica -oppure- deve essere estesa in modo da poter contenere tutti
# gli oggetti che si desidera abilitare/disabilitare contemporaneamente
# - dovrà essere contenuto un solo oggetto se questo deve essere visualizzato in maniera dinamica, altrimenti
# tutti gli oggetti che si desirea abilitare/disabilitare contemporaneamente dovranno essere qui contenuti
# To do:
# - gestire una eventuale visualizzazione dell'area al tocco qualora lo si desideri
# Changelog:
#
#
###[ BEGIN ]#####################################################################################################
extends Control
###[ CONSTS ]####################################################################################################
# è utilizzato per discriminare se questo nodo è un'area (viene controllata la presenza di questa costante, se c'è il nodo
# è di tipo GamepadArea, altrimenti no
const is_area = true
###[ EXPORTED VARIABLES ]########################################################################################
# indica se l'intera area (e gli oggetti in essa contenuti) devono essere disabilitati (se true, nessuno degli oggetti
# contenuti riceverà i tocchi dell'utente)
export var disabled = false
# questa proprietà contiene il nome dell'oggetto (che viene restituito nell'oggetto finger)
export var gamepad_type = "AREA 0"
###[ METHODS ]###################################################################################################
# dal GamepadContainer viene richiamato questo metodo se l'utente tocca quest'area
func handle_down_event(event, finger):
# se l'oggetto è disabilitato esco, non propagando l'evento agli oggetti contenuti
if disabled:
return
# altrimenti per ogni oggetto contenuto
for child in get_children():
# se l'oggetto è un oggetto del gamepad
if child.has_method("handle_down_event"):
# aggiorno l'oggetto associato all'istanza corrente di finger
finger.set_finger(finger.index, child, finger.position)
# quindi chiedo all'oggetto contenuto di gestire l'evento
child.handle_down_event(event, finger)
func handle_up_event(event, finger):
# se l'oggetto è disabilitato esco, non propagando l'evento agli oggetti contenuti
if disabled:
return
# altrimenti per ogni oggetto contenuto
for child in get_children():
# se l'oggetto è un oggetto del gamepad
if child.has_method("handle_up_event"):
# aggiorno l'oggetto associato all'istanza corrente di finger
finger.set_finger(finger.index, child, finger.position)
# quindi chiedo all'oggetto contenuto di gestire l'evento
child.handle_up_event(event, finger)
func handle_move_event(event, finger):
# se l'oggetto è disabilitato esco, non propagando l'evento agli oggetti contenuti
if disabled:
return
# altrimenti per ogni oggetto contenuto
for child in get_children():
# se l'oggetto è un oggetto del gamepad
if child.has_method("handle_move_event"):
# aggiorno l'oggetto associato all'istanza corrente di finger
finger.set_finger(finger.index, child, finger.position)
# quindi chiedo all'oggetto contenuto di gestire l'evento
child.handle_move_event(event, finger)
func handle_input(event):
# questo evento viene richiamato dal container in caso di eventi da tastiera
for child in get_children():
# pertanto propago l'evento a tutti i figli
if child.has_method("handle_input"):
# che sono in grado di gestirlo
child.handle_input(event)
###[ END ]#######################################################################################################

View file

@ -0,0 +1,295 @@
###[ INFO ]######################################################################################################
# Component: GamepadButton
# Author: Francesco Iafulli (fiaful)
# E-mail: fiaful@hotmail.com
# Version: 1.0
# Last modify: 2018-07-20
# What is this:
# E' l'oggetto che consente di gestire i pulsanti del gamepad
# Possono essere aggiunti nel contenitore quanti button si desideri
# Requirements:
# - il parent di questo nodo deve essere di tipo GamepadArea se si desidera utilizzare la proprietà show_dinamically
# per far apparire il button dinamicamente alla posizione della pressione del dito sullo schermo. Il suo parent
# può essere di tipo GamepadContainer se il button è sempre visibile sullo schermo in una posizione fissa.
# - deve comunque essere contenuto (direttamente o indirettamente) in un nodo di tipo GamepadContainer, altrimenti
# non funzionerà
# - la texture del button deve essere quadrata altrimenti si verificheranno problemi di visualizzazione
# a runtime (vedere le immagini di esempio nella cartella assets/Gamepad)
# - se il button deve essere sempre visibile in una posizione fissa, è necessario valorizzare questa posizione nella
# proprietà static_position.
# Changelog:
#
#
###[ BEGIN ]#####################################################################################################
tool
extends Control
###[ INTERNAL OBJECTS ]##########################################################################################
# mantiene l'aspetto del button
onready var button = $ButtonFace
# gestisce l'autofire del button
onready var timer = $AutofireTimer
# gestisce visualizzazione/nascondimento del button
onready var fader = $ShowHideAnimation
###[ EXPORTED VARIABLES ]########################################################################################
# indica se il button deve essere disabilitato (se true, il button non riceverà i tocchi dell'utente e il suo aspetto
# verrà mutato visualizzando la texture_disabled se impostata)
export var disabled = false setget _set_disabled
# indica se il button deve essere staticamente sempre visualizzato (false) o se questo deve apparire nascosto e
# mostrarsi (true) quando l'utente tocca la sua area (in questo caso deve essere contenuto in un oggetto di tipo
# GamepadArea)
export var show_dynamically = false setget _set_show_dynamically
# questa proprietà contiene il nome dell'oggetto (che viene restituito nell'oggetto finger)
export var gamepad_type = "BUTTON 0"
# texture del button nello stato rilasciato
export(Texture) var texture_normal setget _set_texture_normal, _get_texture_normal
# texture del button nello stato premuto
export(Texture) var texture_pressed setget _set_texture_pressed, _get_texture_pressed
# texture del button nello stato disabilitato
export(Texture) var texture_disabled setget _set_texture_disabled, _get_texture_disabled
# contiene la reale posizione del button
export var static_position = Vector2(0, 0)
# indica l'intervallo di tempo tra un fire e l'altro quando il button rimane premuto
# se vale 0, l'utente dovrà rilasciare e premere nuovamente il button per emettere un nuovo segnale di fire
export var autofire_delay = 0.0
# per utilizzare uniformemente gli oggetti anche in presenza di tastiera, consento di associare
# direttamente un input map per premere il button
export var simulate_action = "ui_select"
###[ SIGNALS ]###################################################################################################
# viene emesso quando il button è premuto (una sola volta)
signal down(sender)
# viene emesso quando il button è rilasciato (una sola volta)
signal up(sender)
# viene emesso quando il pulsante è premuto ed agli intervalli dell'autofire
signal fire(sender)
###[ PRIVATE AND PUBLIC VARIABLES ]##############################################################################
# centro del button (ovvero della sua texture)
var center_point = Vector2(0,0)
# i dati del tocco (in modo che possano essere recuperati negli eventi)
var finger_data = null
# indica lo stato de button (se premuto - true - o rilasciato - false)
var is_pressed = false
# indica se sto simulando il button con la tastiera oppure no
var simulation = false
# mantiene lo stato della visualizzazione dinamica
var shown = true
###[ METHODS ]###################################################################################################
# costruisce l'albero dei nodi necessari all'oggetto prendendoli dal template
func _init():
# se non sono già stati caricati
if get_child_count() > 0: return
# carico e istanzio il template
var gamepad_button_template = load("res://addons/Gamepad/GamepadButtonTemplate.tscn").instance()
# quindi se ci sono oggetti nel template (ovviamente si)
if gamepad_button_template.get_child_count() > 0:
# prendo ogni oggetto nel template
for child in gamepad_button_template.get_children():
# se l'oggetto è il timer
if child is Timer:
# ne creo il duplicato
var tmr = child.duplicate()
# lo aggiungo al mio nodo
add_child(tmr)
# connetto il suo segnale timeout allo script
tmr.connect("timeout", self, "_on_AutofireTimer_timeout")
else:
# aggiungo un duplicato al mio nodo
add_child(child.duplicate())
func _ready():
# se l'oggetto deve essere visualizzato dinamicamente (ovvero solo quando l'utente tocca lo schermo) lo nascondo
if show_dynamically:
_hide_button()
# imposto la sua posizione statica (non ha senso se visualizzato dinamicamente in quanto la sua posizione
# varierà in base al tocco dell'utente)
rect_position = static_position
# ricavo i restanti valori che mi serviranno più avanti per fare i calcoli
center_point = self.rect_size / 2
# emula il button tramite tastiera
func handle_input(event):
# verifica quale tasto è stato premuto
simulation = false
# se il tasto premuto corrisponde a quello indicato
if simulate_action and Input.is_action_pressed(simulate_action):
simulation = true
# e il button non era precedentemente premuto
if !is_pressed:
# inizializzo la posizione del'oggetto
var ev = InputEventScreenTouch.new()
ev.position = get_parent().rect_global_position + static_position + center_point
# simulo la pressione del dito sul button
handle_down_event(ev, null)
else:
# mentre se il tasto corrispondente non è premuto e il button lo era,
if is_pressed:
# simulo il rilascio del dito dal button
handle_up_event(null, null)
# l'utente ha toccato lo schermo in corrispondenza del button o dell'area che contiene il button
func handle_down_event(event, finger):
# se il button è disabilitato esco senza fare nulla (prima però resetto i dati interni)
if disabled:
is_pressed = false
button.pressed = false
return
# altrimenti imposto i dati del tocco in modo che possano essere recuperati da fuori
finger_data = finger
# se il button deve essere visualizzato dinamicamente vuol dire che in questo momento non è visibile e quindi lo mostro
if show_dynamically:
_show_button(event)
# comunico che il button è stato premuto
emit_signal("down", self)
# quindi gestisco il fire (e l'autofire)
fire()
# l'utente ha sollevato il dito con cui aveva toccato il button o la sua area
func handle_up_event(event, finger):
# se il button è disabilitato esco senza fare nulla (prima però resetto i dati interni)
if disabled:
is_pressed = false
button.pressed = false
return
# altrimenti imposto i dati del tocco in modo che possano essere recuperati da fuori
finger_data = finger
# se il button deve essere visualizzato dinamicamente vuol dire che in questo momento è visibile e quindi lo nascondo
if show_dynamically:
_hide_button()
# gestisco la fine del fire (e dell'autofire)
fire_stop()
# comunico che il button è stato rilasciato
emit_signal("up", self)
# l'utente ha spostato il dito con cui aveva toccato il button o la sua area
func handle_move_event(event, finger):
# non faccio nulla
pass
# if disabled: return
func _on_AutofireTimer_timeout():
# il timer dell'autofire, semplicemente emette segnali fire all'intervallo stabilito, continuamente
emit_signal("fire", self)
# gestione del fire (può essere richiamata anche esternamente)
func fire():
if disabled:
# proprio perchè questa funzione può essere richiamata anche esternamente,
# se il button è disabilitato esco senza fare nulla (prima però resetto i dati interni)
is_pressed = false
button.pressed = false
return
# imposto lo stato di premuto
button.pressed = true
is_pressed = true
# emetto il segnale fire
emit_signal("fire", self)
# e se l'autofire è impostato (ovvero se il suo delay è > 0)
if autofire_delay > 0:
# avvio il timer per l'autofire
timer.wait_time = autofire_delay
timer.start()
# gestione della fine del fire (può essere richiamata anche esternamente)
func fire_stop():
# resetto lo stato interno
button.pressed = false
is_pressed = false
# se il timer dell'autofire era partito, lo arresto
timer.stop()
# mostra il button
func _show_button(event):
# se event è diverso dal null (nel caso in l'utente tocca il button o la sua area) calcolo la posizione
# in base a quella passata nell'evento
if shown: return
shown = true
if event:
rect_global_position = event.position - center_point
else:
# altrimenti la posizione del button è quella statica impostata in static_position
rect_position = static_position
# avvio l'animazione di visualizzazione
if fader:
fader.stop()
fader.play("fade_in", -1, 10)
# nasconde il button
func _hide_button():
if !shown: return
shown = false
# avvia l'animazione di nascondimento
if fader:
fader.stop()
fader.play("fade_out", -1, 10)
###[ SETTER/GETTER ]#############################################################################################
func _get_texture_normal():
return $ButtonFace.texture_normal
func _set_texture_normal(value):
# if !has_node("ButtonFace"): return
$ButtonFace.texture_normal = value
func _get_texture_pressed():
return $ButtonFace.texture_pressed
func _set_texture_pressed(value):
# if !has_node("ButtonFace"): return
$ButtonFace.texture_pressed = value
func _get_texture_disabled():
return $ButtonFace.texture_disabled
func _set_texture_disabled(value):
# if !has_node("ButtonFace"): return
$ButtonFace.texture_disabled = value
func _set_disabled(value):
disabled = value
# if !has_node("ButtonFace"): return
$ButtonFace.disabled = value
func _set_show_dynamically(value):
show_dynamically = value
# se sono nell'editor non faccio nulla (altrimenti mi verrebbe nascosto l'oggetto anche dall'editor)
if Engine.editor_hint: return
if value:
_hide_button()
else:
_show_button(null)
###[ END ]#######################################################################################################

View file

@ -0,0 +1,101 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://assets/Gamepad/big_circle.png" type="Texture" id=1]
[ext_resource path="res://assets/Gamepad/small_circle.png" type="Texture" id=2]
[sub_resource type="Animation" id=1]
resource_name = "fade_in"
length = 1.0
loop = false
step = 0.2
tracks/0/type = "value"
tracks/0/path = NodePath("ButtonFace:modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 1 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Color( 1, 1, 1, 0 ), Color( 1, 1, 1, 1 ) ]
}
[sub_resource type="Animation" id=2]
resource_name = "fade_out"
length = 1.0
loop = false
step = 0.1
tracks/0/type = "value"
tracks/0/path = NodePath("ButtonFace:modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 1 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ]
}
[node name="GamepadButtonTemplate" type="Control" index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 192.0
margin_bottom = 192.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
_sections_unfolded = [ "Hint", "Rect", "Size Flags" ]
[node name="ButtonFace" type="TextureButton" parent="." index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 1.0
anchor_bottom = 1.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
toggle_mode = true
action_mode = 0
enabled_focus_mode = 2
shortcut = null
group = null
texture_normal = ExtResource( 1 )
texture_pressed = ExtResource( 2 )
expand = true
_sections_unfolded = [ "Size Flags", "Textures", "Visibility" ]
[node name="AutofireTimer" type="Timer" parent="." index="1"]
process_mode = 1
wait_time = 1.0
one_shot = false
autostart = false
[node name="ShowHideAnimation" type="AnimationPlayer" parent="." index="2"]
root_node = NodePath("..")
autoplay = ""
playback_process_mode = 1
playback_default_blend_time = 0.0
playback_speed = 1.0
anims/fade_in = SubResource( 1 )
anims/fade_out = SubResource( 2 )
blend_times = [ ]

View file

@ -0,0 +1,163 @@
###[ INFO ]######################################################################################################
# Component: GamepadContainer
# Author: Francesco Iafulli (fiaful)
# E-mail: fiaful@hotmail.com
# Version: 1.0
# Last modify: 2018-07-20
# What is this:
# E' il nodo che andrà a contenere tutti gli oggetti che costruiranno il gamepad.
# Di fatto, è l'oggetto che cattura l'input multitouch sullo schermo, legando ogni touch ad uno specifico oggetto
# del gamepad.
# Requirements:
# - l'area di questo oggetto deve essere estesa a tutta la zone che si vuole rendere sensibile al tocco
# - tutti gli oggetti appartenenti al gamepad dovranno essere contenuti in questo oggetto
# To do:
# - gestire lo scroll sugli assi x e y
# - gestire lo swipe sugli assi x e y
# - gestire lo zoom-in e zoom-out (pinch in/out)
# Changelog:
#
#
###[ BEGIN ]#####################################################################################################
extends Control
###[ EXPORTED VARIABLES ]########################################################################################
# indica se l'intero gamepad deve essere disabilitato (se true, nessuno degli oggetti contenuti riceverà i tocchi
# dell'utente
export var disabled = false
###[ SIGNALS ]###################################################################################################
# viene emesso quando avviene un qualsiasi tocco (in caso di più tocchi simultanei, viene emesso per ogni tocco)
signal finger_down(finger_data)
# viene emesso quando qualsiasi tocco ha fine (in caso di fine di più tocchi simultanei, viene emesso per ogni tocco)
signal finger_up(finger_data)
# viene emesso quando qualsiasi dito si muove sullo schermo (in caso di movimento di più dita, viene emesso per ogni dito)
signal finger_move(finger_data)
# Nota: finger_data è un oggetto, di tipo finger, che mantiene le informazioni su cosa è accaduto.
# la classe Finger è definita in fondo a questo file
###[ PRIVATE AND PUBLIC VARIABLES ]##############################################################################
# mantiene un elenco (in forma di dizionario dove la chiave è l'indice del tocco) di tutti i tocchi attualmente attivi
var fingers = {}
###[ METHODS ]###################################################################################################
func _input(event):
# se il contenitore è disabilitato, non faccio nulla
if disabled:
return
# se l'evento è un tocco premuto
if event is InputEventScreenTouch:
if event.is_pressed():
# creo, se non esistente (altrimenti l'aggiorna), una nuova voce Finger nel dizionario
fingers[event.index] = Finger.new()
# impostandone i dati di base (indice, l'oggetto su cui è avvenuto il tocco, la posizione del tocco)
fingers[event.index].set_finger(event.index, _find_object_by_position(event), event.position)
# emetto il segnale del tocco avvenuto
emit_signal("finger_down", fingers[event.index])
# se il dito ha premuto lo schermo su un oggetto del gamepad, propago l'evento a quell'oggetto
if fingers[event.index].object:
fingers[event.index].object.handle_down_event(event, fingers[event.index])
else:
# mentre se l'evento è un tocco rilasciato ed era stato memorizzato
if fingers.has(event.index):
# imposto le informazioni sul dito dicendo che non è più premuto
fingers[event.index].pressed = false
# ed emetto il segnale di dito rilasciato, passando tutte le informazioni raccolte finora
emit_signal("finger_up", fingers[event.index])
# se il dito era premuto su un oggetto del gamepad, comunico a quell'oggetto che il dito è stato sollevato
if fingers[event.index].object:
fingers[event.index].object.handle_up_event(event, fingers[event.index])
# dunque pulisco le informazioni del dito dal dizionario in modo che possano essere reinserire se necessario
fingers[event.index].reset_finger()
fingers.erase(event.index)
# se invece l'evento è un trascinamento del dito
if event is InputEventScreenDrag:
# controllo di avere le informazioni per quel dito e, se ce l'ho,
if fingers.has(event.index):
# aggiorno le informazioni sulla posizione
fingers[event.index].position = event.position
# ed emetto il segnale di spostamento del dito
emit_signal("finger_move", fingers[event.index])
# quindi se al dito era associato un oggetto del gamepad, comunico lo spostamento a quell'oggetto
if fingers[event.index].object:
fingers[event.index].object.handle_move_event(event, fingers[event.index])
# se l'evento è un'azione della tastiera (pressione o rilascio di tasti)
if event is InputEventKey:
# propago l'evento
for child in get_children():
# a tutti i figli di tipo gamepad
if "gamepad_type" in child:
child.handle_input(event)
# questa funzione verifica se alle date coordinate (estratte dall'evento), è presente un oggetto del gamepad.
# se è presente, lo ritorna, altrimenti restituisce null
func _find_object_by_position(event):
for child in get_children():
if "gamepad_type" in child and child.get_global_rect().has_point(event.position):
return child
return null
###[ THE FINGER CLASS ]##########################################################################################
class Finger:
# What is this
# Questa classe è un contenitore di dati per le informazioni del dito
###[ PRIVATE AND PUBLIC VARIABLES ]##############################################################################
# contiene l'indice del tocco,
var index = -1
# il tipo dell'oggetto su cui il tocco è avvenuto (UNKNOWN è se il tocco non ha sotto di sè oggetti del gamepad)
# il suo valore è dato dalla proprietà gamepad_type dell'oggetto del gamepad su cui è avvenuto il tocco
var type = "UNKNOWN"
# se il dito è premuso sullo schermo oppure no
var pressed = false
# la posizione del tocco
var position = Vector2()
# l'oggetto collegato al dito
var object = null
###[ METHODS ]###################################################################################################
func set_finger(_index, _object, _position, _type=""):
index = _index
type = _type if _type else _object.gamepad_type if _object else "UNKNOWN"
pressed = true
position = _position
object = _object
func reset_finger():
index = -1
type = "UNKNOWN"
pressed = false
position.x = -1
position.y = -1
object = null
func to_string():
var d = {
"index": index,
"type": type,
"pressed": pressed,
"position": position,
"object": object
}
return str(d)
###[ END ]#######################################################################################################

View file

@ -0,0 +1,408 @@
###[ INFO ]######################################################################################################
# Component: GamepadPaddle
# Author: Francesco Iafulli (fiaful)
# E-mail: fiaful@hotmail.com
# Version: 1.0
# Last modify: 2018-07-20
# What is this:
# E' l'oggetto che consente di gestire paddle virtuali analogici (la paddle è un controller che ruota su se stesso,
# come ad esempio il volante di una automobile).
# Possono essere aggiunti nel contenitore quanti paddle si desideri (generalmente 1 o 2)
# Requirements:
# - il parent di questo nodo deve essere di tipo GamepadArea se si desidera utilizzare la proprietà show_dinamically
# per far apparire la paddle dinamicamente alla posizione della pressione del dito sullo schermo. Il suo parent
# può essere di tipo GamepadContainer se la paddle è sempre visibile sullo schermo ad una posizione fissa.
# - deve comunque essere contenuto (direttamente o indirettamente) in un nodo di tipo GamepadContainer, altrimenti
# non funzionerà
# - la texture di sfondo della paddle deve essere quadrata altrimenti si verificheranno problemi di visualizzazione
# a runtime (vedere le immagini di esempio nella cartella assets/Gamepad)
# - se la paddle deve essere sempre visibile in una posizione fissa, è necessario valorizzare questa posizione nella
# proprietà static_position.
# Changelog:
#
#
###[ BEGIN ]#####################################################################################################
tool
extends Control
###[ CONSTS ]####################################################################################################
# contiene un valore per definire un angolo non valido
const INVALID_ANGLE = -99
###[ INTERNAL OBJECTS ]##########################################################################################
# texture di sfondo della paddle
onready var bg = $PaddleBackground
# texture del centro della paddle
onready var paddle = $Paddle
# animazione di visualizzazione/nascondimento della paddle
onready var fader = $ShowHideAnimation
onready var timer = $Timer
###[ EXPORTED VARIABLES ]########################################################################################
# indica se la paddle deve essere disabilitata (se true, la paddle non riceverà i tocchi dell'utente)
export var disabled = false
# indica se la paddle deve essere staticamente sempre visualizzata (false) o se questa deve apparire nascosta e
# mostrarsi (true) quando l'utente tocca la sua area (in questo caso deve essere contenuta in un oggetto di tipo
# GamepadArea)
export var show_dynamically = false setget _set_show_dynamically
# questa proprietà contiene il nome dell'oggetto (che viene restituito nell'oggetto finger)
export var gamepad_type = "PADDLE 0"
# texture di sfondo della paddle
export(Texture) var background_texture setget _set_bg_texture, _get_bg_texture
# texture del centro della paddle
export(Texture) var paddle_texture setget _set_texture, _get_texture
# scala della texture del centro della paddle (la dimensione dello sfondo è data dal rect_size dell'oggetto,
# quindi per impostare la dimensione del centro della paddle si usa questa proprietà)
export(Vector2) var paddle_scale setget _set_scale, _get_scale
# contiene la reale posizione della paddle
export var static_position = Vector2(0, 0)
# questa proprietà indica la forza minima da imporre alla paddle per iniziare a considerare validi
# i valori (es. con un valore = 0.5, la paddle inizierà a ruotare solo se l'utente toccherà l'oggetto
# su oltre la metà della distanza tra il centro della paddle ed il bordo)
export var valid_threshold = 0.2
# se impostato a true, il rilascio della paddle resetterà i valori e la posizione della paddle, mentre
# se impostato a false, al rilascio i valori e la posizione resteranno gli ultimi validi
export var reset_on_release = true
# impone un limite inferiore alla rotazione della paddle (limite inferiore e superiore possono essere invertiti)
export var low_limit = 0
# impone un limite alto alla rotazione della paddle (limite inferiore e superiore possono essere invertiti)
export var high_limit = 0
# per utilizzare uniformemente gli oggetti anche in presenza di tastiera, consento di associare
# direttamente degli input map per ruotare la paddle in senso antiorario e orario
export var simulate_counter_clockwise = "ui_left"
export var simulate_clockwise = "ui_right"
# in caso di simulazione con la tastiera, indica lo step di incremento/decremento dell'angolo
export var simulation_increment = 0.05
# in caso di simulazione con la tastiera, indica la velocità di incremento/decremento dell'angolo
export var simulation_delay = 0.01
###[ PRIVATE AND PUBLIC VARIABLES ]##############################################################################
# centro della paddle (ovvero dello sfondo della paddle)
var center_point = Vector2(0,0)
# forza calcolata dal centro della paddle (serve per calcolare l'angolo)
var current_force = Vector2(0,0)
# metà della dimensione dello sfondo della paddle
var half_size = Vector2()
# area del rettangolo costituito da metà delle dimensioni dello sfondo
var squared_half_size_length = 0
# indica se l'angolo di rotazione della paddle si trova all'interno o all'esterno dei limiti imposti
var into_limits = false
# i dati del tocco (in modo che possano essere recuperati negli eventi)
var finger_data = null
# angolo di rotazione della paddle
var angle = -1
# indica se sto ruotando la paddle con i tasti della tastiera oppure no
var simulation = false
# ultimo angolo calcolato (serve per emettere i segnali solo se l'angolo corrente è diverso da quello precedente)
var last_angle = INVALID_ANGLE
# mantiene lo stato della visualizzazione dinamica
var shown = true
# indica la direzione di rotazione nel caso di simulazione con la tastiera
var direction = 0
###[ SIGNALS ]###################################################################################################
# viene emesso quando la paddle ruota, restituendo l'angolo di rotazione e l'oggetto paddle stesso (in modo da
# poter recuperare altre informazioni (qualsiasi proprietà dell'oggetto)
signal angle_changed(current_angle, sender)
# viene emesso quando l'utente rilascia il dito dalla paddle (l'angolo sarà sempre invalido, pertanto è inutile
# passare il sender)
signal paddle_released
###[ METHODS ]###################################################################################################
# costruisce l'albero dei nodi necessari all'oggetto prendendoli dal template
func _init():
# se non sono già stati caricati
if get_child_count() > 0: return
# carico e istanzio il template
var gamepad_paddle_template = load("res://addons/Gamepad/GamepadPaddleTemplate.tscn").instance()
# quindi se ci sono oggetti nel template (ovviamente si)
if gamepad_paddle_template.get_child_count() > 0:
# prendo ogni oggetto nel template
for child in gamepad_paddle_template.get_children():
# se l'oggetto è il timer
if child is Timer:
# ne creo il duplicato
var tmr = child.duplicate()
# lo aggiungo al mio nodo
add_child(tmr)
tmr.wait_time = simulation_delay
# connetto il suo segnale timeout allo script
tmr.connect("timeout", self, "_on_timer_timeout")
else:
# aggiungo un duplicato al mio nodo
add_child(child.duplicate())
func _ready():
# se l'oggetto deve essere visualizzato dinamicamente (ovvero solo quando l'utente tocca lo schermo) lo nascondo
if show_dynamically:
_hide_paddle()
# imposto la sua posizione statica (non ha senso se visualizzato dinamicamente in quanto la sua posizione
# varierà in base al tocco dell'utente)
rect_position = static_position
# ricavo i restanti valori che mi serviranno più avanti per fare i calcoli
half_size = bg.rect_size / 2
center_point = half_size
paddle.position = half_size
squared_half_size_length = half_size.x * half_size.y
# emula la paddle tramite i tasti
func handle_input(event):
if event is InputEventKey:
if !((simulate_counter_clockwise and event.is_action(simulate_counter_clockwise)) or \
(simulate_clockwise and event.is_action(simulate_clockwise))): return
else:
return
# verifica quale tasto è stato premuto
var cnt = simulate_counter_clockwise and Input.is_action_pressed(simulate_counter_clockwise)
var clk = simulate_clockwise and Input.is_action_pressed(simulate_clockwise)
simulation = false
# se nessuna delle 2 direzioni è premuta, azzero l'angolo e sollevo l'evento di rilascio
if !cnt and !clk:
# fermo il timer che si occupa di far ruotare la paddle
timer.stop()
handle_up_event(null, null)
else:
# imposto la direzione di rotazione
if cnt:
clk = false
direction = -simulation_increment
elif clk:
cnt = false
direction = simulation_increment
# ed avvio il timer che si occuperà di far ruotare la paddle
timer.start()
func _on_timer_timeout():
# inizializza la posizione del'oggetto
var ev = InputEventScreenTouch.new()
ev.position = get_parent().rect_global_position + static_position + half_size
simulation = true
# incrementa/decrementa l'angolo
angle += direction
# se l'angolo è diverso dal precedente
if angle != last_angle:
last_angle = angle
# simulo la rotazione della paddle
handle_down_event(ev, null)
# l'utente ha toccato lo schermo in corrispondenza della paddle o dell'area che contiene la paddle
func handle_down_event(event, finger):
# se la paddle è disabilitata esco senza fare nulla (prima però resetto i dati interni)
if disabled:
reset()
return
# altrimenti imposto i dati del tocco in modo che possano essere recuperati da fuori
finger_data = finger
# se la paddle deve essere visualizzata dinamicamente vuol dire che in questo momento non è visibile e quindi la mostro
if show_dynamically:
_show_paddle(event)
# se il tocco è avvenuto nella zona dello sfondo della paddle
if simulation or bg.get_global_rect().has_point(event.position):
# calcolo la forza e l'angolo, aggiorno la rotazione della paddle ed emetto il segnale
calculate(event)
else:
# altrimenti resetto tutti i dati e esco
reset()
# l'utente ha sollevato il dito con cui aveva toccato la paddle o la sua area
func handle_up_event(event, finger):
# se la paddle è disabilitata esco senza fare nulla (prima però resetto i dati interni)
if disabled:
reset()
return
# altrimenti imposto i dati del tocco in modo che possano essere recuperati da fuori
finger_data = finger
# se la paddle deve essere visualizzata dinamicamente vuol dire che in questo momento è visibile e quindi la nascondo
if show_dynamically:
_hide_paddle()
# resetto i dati interni
reset()
# quindi emetto il segnale per comunicare che la paddle è stata rilasciata
emit_signal("paddle_released")
# l'utente ha spostato il dito con cui aveva toccato la paddle o la sua area
func handle_move_event(event, finger):
# se la paddle è disabilitata esco senza fare nulla (prima però resetto i dati interni)
if disabled:
reset()
return
# altrimenti imposto i dati del tocco in modo che possano essere recuperati da fuori
finger_data = finger
# calcolo la forza, l'angolo, aggiorno la rotazione della paddle ed emetto il segnale
calculate(event)
# calcolo la forza, l'angolo, aggiorno la rotazione della paddle ed emetto il segnale
func calculate(event):
# ricalcolo la posizione dell'evento in modo che lo 0,0 coincida con lo 0,0 dell'oggetto
if !simulation:
var pos = event.position - rect_global_position
calculate_force(pos)
update_paddle_pos()
emit()
func calculate_force(pos):
# print ("pos: ", pos, " - center_point: ", center_point, " - half_size: ", half_size)
# calcolo la forza in relazione alla posizione del mouse e il centro della paddle, e la normalizzo
current_force.x = (pos.x - center_point.x) / half_size.x
current_force.y = (pos.y - center_point.y) / half_size.y
if current_force.length_squared() > 1:
current_force = current_force / current_force.length()
# quindi se la forza è minore della soglia di validità, resituisco 0,0 (per comunicare che
# non è stato effettuato uno spostamento valido del centro della paddle)
if (current_force.length() < valid_threshold):
current_force = Vector2(0,0)
# aggiorno la rotazione della paddle in modo che graficamente sia coerente
func update_paddle_pos():
var new_angle
if !simulation:
var x = center_point.x + half_size.x * current_force.x
var y = center_point.y + half_size.y * current_force.y
new_angle = Vector2(x, y).angle_to_point(center_point)
else:
new_angle = angle
# quindi verifico che il nuovo angolo sia nei limiti
into_limits = false
var deg_angle = rad2deg(new_angle) + 180
# print ([deg_angle, low_limit, high_limit])
# se low_limit e high_limit sono uguali non devo imporre limiti, ovvero sono sempre nei limiti
if low_limit != high_limit:
if low_limit > high_limit:
if deg_angle <= high_limit:
into_limits = true
if deg_angle >= low_limit:
if deg_angle >= high_limit:
into_limits = true
else:
if deg_angle <= high_limit and deg_angle >= low_limit:
into_limits = true
else:
into_limits = true
# se sono nei limiti, imposto il nuovo angolo ed aggiorno la rotazione della paddle
if into_limits:
angle = new_angle
paddle.rotation = angle
# solo se reset_on_release = true (vedi commento) effettuo un reset dei dati interni,
# imposto l'angolo della paddle ad un valore invalido e ne aggiorno graficamente la rotazione
func reset():
if !reset_on_release: return
calculate_force(center_point)
update_paddle_pos()
angle = INVALID_ANGLE
last_angle = angle
# emit()
# emette il segnale per comunicare il cambiamento dell'angolo della paddle
func emit():
if into_limits:
emit_signal("angle_changed", angle, self)
# print (angle / PI * 180)
# print (rad2deg(angle) + 180)
# mostra la paddle
func _show_paddle(event):
# se event è diverso dal null (nel caso in l'utente tocca la paddle o la sua area) calcolo la posizione
# in base a quella passata nell'evento
if shown: return
shown = true
if event:
rect_global_position = event.position - center_point
else:
# altrimenti la posizione della paddle è quella statica impostata in static_position
rect_position = static_position
# avvio l'animazione di visualizzazione
if fader:
reset()
fader.stop()
fader.play("fade_in", -1, 10)
# nasconde la paddle
func _hide_paddle():
if !shown: return
shown = false
# avvia l'animazione di nascondimento
if fader:
fader.stop()
fader.play("fade_out", -1, 10)
###[ SETTER/GETTER ]#############################################################################################
func _get_scale():
return $Paddle.scale
func _set_scale(value):
# if !has_node("Paddle"): return
$Paddle.scale = value
$Paddle.position = $PaddleBackground.rect_size / 2
func _get_bg_texture():
return $PaddleBackground.texture
func _set_bg_texture(value):
# if !has_node("PaddleBackground"): return
$PaddleBackground.texture = value
$Paddle.position = $PaddleBackground.rect_size / 2
func _get_texture():
return $Paddle.texture
func _set_texture(value):
# if !has_node("PaddleBackground"): return
$Paddle.texture = value
$Paddle.position = $PaddleBackground.rect_size / 2
func _set_show_dynamically(value):
show_dynamically = value
# se sono nell'editor non faccio nulla (altrimenti mi verrebbe nascosto l'oggetto anche dall'editor)
if Engine.editor_hint: return
if value:
_hide_paddle()
else:
_show_paddle(null)
###[ END ]#######################################################################################################

View file

@ -0,0 +1,125 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://assets/Gamepad/big_circle.png" type="Texture" id=1]
[ext_resource path="res://assets/Gamepad/small_circle.png" type="Texture" id=2]
[sub_resource type="Animation" id=1]
resource_name = "fade_in"
length = 1.0
loop = false
step = 0.2
tracks/0/type = "value"
tracks/0/path = NodePath("PaddleBackground:modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 1 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Color( 1, 1, 1, 0 ), Color( 1, 1, 1, 1 ) ]
}
tracks/1/type = "value"
tracks/1/path = NodePath("Paddle:modulate")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/keys = {
"times": PoolRealArray( 0, 1 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Color( 1, 1, 1, 0 ), Color( 1, 1, 1, 1 ) ]
}
[sub_resource type="Animation" id=2]
resource_name = "fade_out"
length = 1.0
loop = false
step = 0.1
tracks/0/type = "value"
tracks/0/path = NodePath("PaddleBackground:modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 1 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ]
}
tracks/1/type = "value"
tracks/1/path = NodePath("Paddle:modulate")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/keys = {
"times": PoolRealArray( 0, 1 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ]
}
[node name="GamepadPaddleTemplate" type="Control" index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 256.0
margin_bottom = 256.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
_sections_unfolded = [ "Rect", "Size Flags" ]
[node name="PaddleBackground" type="TextureRect" parent="." index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 1.0
anchor_bottom = 1.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 1
mouse_default_cursor_shape = 0
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource( 1 )
expand = true
stretch_mode = 0
_sections_unfolded = [ "Size Flags", "Visibility" ]
[node name="Paddle" type="Sprite" parent="." index="1"]
position = Vector2( 128, 128 )
texture = ExtResource( 2 )
_sections_unfolded = [ "Transform", "Visibility" ]
[node name="ShowHideAnimation" type="AnimationPlayer" parent="." index="2"]
root_node = NodePath("..")
autoplay = ""
playback_process_mode = 1
playback_default_blend_time = 0.0
playback_speed = 1.0
anims/fade_in = SubResource( 1 )
anims/fade_out = SubResource( 2 )
blend_times = [ ]
[node name="Timer" type="Timer" parent="." index="3"]
process_mode = 1
wait_time = 1.0
one_shot = false
autostart = false

View file

@ -0,0 +1,546 @@
###[ INFO ]######################################################################################################
# Component: GamepadStick
# Author: Francesco Iafulli (fiaful)
# E-mail: fiaful@hotmail.com
# Version: 1.0
# Last modify: 2018-07-20
# What is this:
# E' l'oggetto che consente di gestire stick virtuali, analogici o digitali.
# Possono essere aggiunti nel contenitore quanti stick si desideri (generalmente 1 o 2)
# Esistono diversi tipi di stick:
# - analogici:
# restituiscono un vettore 2D forza contenente valori che vanno da 0 a 1 (positivi per le direzioni
# destra e basso, e negativi per le direzioni sinistra e alto) dipendenti dalla distanza dello stick
# dal suo centro.
# Stick analogici sono:
# - ANALOG (consentono qualsiasi direzione)
# - LEFT/RIGHT (consentono lo spostamento solo in orizzontale - l'asse y avrà sempre valore 0)
# - UP/DOWN (consentono lo spostamento solo in verticale - l'asse x avrà sempre valore 0)
#
# - digitali:
# restituiscono un vettore 2D digitale, ovvero i valori di x e y possono valere solo 0, 1, e -1
# a seconda della direzione (positivi per le direzioni destra e basso, e negativi per le direzioni
# sinistra e alto).
# Stick digitali sono:
# - DIGITAL 8 (consente lo spostamento dello stick nelle 8 direzioni digitali (su, giù, sinistra,
# destra, e relative diagonali)
# - DIGITAL 4 PLUS (consente lo spostamento nelle sole 4 direzioni principali disposte cardinalmente
# (su, giù, destra, e sinistra)
# - DIGITAL 4 X (consente lo spostamento nelle 4 direzioni diagonali (alto-sinistra, alto-destra,
# basso-sinistra, e basso destra)
# - DIGITAL 4 ISO (è come il DIGITAL 4 X ma consente di modificare alcuni parametri particolari per
# visualizzare lo stick in maniera isometrica)
#
# La direzione corrente, nel caso di stick digitali, viene restituita anche in una lista di nome direction in cui
# è possibile verificare se una data direzione è presente (es.: if sender.UP in sender.direction: )
#
# Nota: è possibile tramutare gli analogici LEFT/RIGHT e UP/DOWN in digitali impostando la proprietà step = 1
# Requirements:
# - il parent di questo nodo deve essere di tipo GamepadArea se si desidera utilizzare la proprietà show_dinamically
# per far apparire lo stick dinamicamente alla posizione della pressione del dito sullo schermo. Il suo parent
# può essere di tipo GamepadContainer se lo stick è sempre visibile sullo schermo ad una posizione fissa.
# - deve comunque essere contenuto (direttamente o indirettamente) in un nodo di tipo GamepadContainer, altrimenti
# non funzionerà
# - la texture di sfondo dello stick deve essere comunque quadrata (width == height), anche nel caso di LEFT/RIGHT,
# UD/DOWN, o DIGITAL 4 ISO, altrimenti si verificheranno problemi di visualizzazione a runtime (vedere le
# immagini di esempio nella cartella assets/Gamepad)
# - se lo stick deve essere sempre visibile in una posizione fissa, è necessario valorizzare questa posizione nella
# proprietà static_position.
# To do:
# - inserire un flag per invertire l'asse y
# - provare a gestire l'analogico da tastiera come nella paddle
# Changelog:
#
#
###[ BEGIN ]#####################################################################################################
tool
extends Control
###[ CONSTS ]####################################################################################################
# contiene un valore per definire un angolo non valido
const INVALID_ANGLE = -99
###[ ENUMS ]#####################################################################################################
# consente di specificare che tipo di stick si intende gestire
enum STICK_TYPE { _ANALOG, _DIGITAL_8, _DIGITAL_4_PLUS, _DIGITAL_4_X, _DIGITAL_4_ISO, _LEFT_RIGHT, _UP_DOWN }
# contiene le quattro direzioni fondamentali, utilizzato per valorizzare la lista delle direzioni digitali direction
enum DIGITAL_DIRECTIONS { UP, LEFT, DOWN, RIGHT }
###[ INTERNAL OBJECTS ]##########################################################################################
# texture di sfondo dello stick
onready var bg = $StickBackground
# texture del centro dello stick
onready var stick = $Stick
# animazione di visualizzazione/nascondimento dello stick
onready var fader = $ShowHideAnimation
###[ EXPORTED VARIABLES ]########################################################################################
# indica se lo stick deve essere disabilitato (se true, lo stick non riceverà i tocchi dell'utente)
export var disabled = false
# indica se lo stick deve essere staticamente sempre visualizzato (false) o se questo deve apparire nascosto e
# mostrarsi (true) quando l'utente tocca la sua area (in questo caso deve essere contenuto in un oggetto di tipo
# GamepadArea)
export var show_dynamically = false setget _set_show_dynamically
# questa proprietà contiene il nome dell'oggetto (che viene restituito nell'oggetto finger)
export var gamepad_type = "STICK 0"
# indica il tipo dello stick (fare riferimento alla documentazione in alto e all'enum STICK_TYPE)
export(STICK_TYPE) var stick_type = STICK_TYPE._ANALOG
# texture di sfondo dello stick
export(Texture) var background_texture setget _set_bg_texture, _get_bg_texture
# texture del centro dello stick
export(Texture) var stick_texture setget _set_texture, _get_texture
# scala della texture del centro dello stick (la dimensione dello sfondo è data dal rect_size dell'oggetto,
# quindi per impostare la dimensione del centro dello stick si usa questa proprietà)
export(Vector2) var stick_scale setget _set_scale, _get_scale
# contiene la reale posizione dello stick
export var static_position = Vector2(0, 0)
# indica se il centro dello stick deve essere nascosto (true) o meno se esso si trova al centro dell'oggetto
# (ovvero se la sua forza = 0)
export var hide_stick_on_stop = false
# questa proprietà è da utilizzarsi solo se lo stick è di tipo DIGITAL 4 ISO e serve ad indicare di quanti
# pixel deve essere spostato il centro dello stick se si trova nelle posizioni diagonali alte
export var adjust_iso = 0
# questa proprietà indica la forza minima da imporre al centro dello stick per iniziare a considerare validi
# i valori (es. con un valore = 0.5, il centro dello stick non si sposterà fino a quando non sarà raggiunto
# almeno la metà della distanza tra il centro dello stick ed il bordo)
export var valid_threshold = 0.2
# consente di restituire i valori analogici arrotondati per step
# (es.: con un valore = 0.25, lo stick restituirà come forze i soli valori 0, 0.25, 0.5, 0.75, 1)
export var step = 0.0
# per utilizzare uniformemente gli oggetti anche in presenza di tastiera, consento di associare
# direttamente degli input map alle direzioni
# Attenzione: la simulazione non funzionerà correttamente con stick analogici
export var simulate_up = "ui_up"
export var simulate_left = "ui_left"
export var simulate_down = "ui_down"
export var simulate_right = "ui_right"
###[ PRIVATE AND PUBLIC VARIABLES ]##############################################################################
# centro dello stick (ovvero dello sfondo dello stick)
var center_point = Vector2(0,0)
# ultima forza calcolata (serve per emettere i segnali solo se la forza corrente è diversa da quella precedente)
var last_force = Vector2(0,0)
# forza calcolata dal centro dello stick (oppure i valori digitali nel caso di stick digitali)
var current_force = Vector2(0,0)
# metà della dimensione dello sfondo dello stick
var half_size = Vector2()
# metà della dimensione del centro dello stick
var half_stick = Vector2()
# posizione del centro dello stick
var stick_pos = Vector2()
# area del rettangolo costituito da metà delle dimensioni dello sfondo
var squared_half_size_length = 0
# i dati del tocco (in modo che possano essere recuperati negli eventi)
var finger_data = null
# angolo tra la posizione del centro dello stick e l'asse x
var angle = -1
# lista delle direzioni digitali in cui si trova lo stick
var direction = []
# indica se sto simulando lo stick con i tasti della tastiera oppure no
var simulation = false
# mantiene lo stato della visualizzazione dinamica
var shown = true
###[ SIGNALS ]###################################################################################################
# viene emesso quando lo stick si muove, restituendo il vettore della forza (se analogico altrimento valori 0, 1,
# -1 se digitale) e l'oggetto stick stesso (in modo da poter recuperare altre informazioni come l'angolo, le
# direzioni, i dati del tocco, o qualsiasi altra proprietà dell'oggetto)
signal gamepad_force_changed(current_force, sender)
# viene emesso quando l'utente rilascia il dito dallo stick (la forza sarà sempre 0, l'angolo sarà sempre invalido,
# e la lista delle direzioni sarà sempre vuota, pertanto è inutile passare il sender)
signal gamepad_stick_released
###[ METHODS ]###################################################################################################
# costruisce l'albero dei nodi necessari all'oggetto prendendoli dal template
func _init():
# se non sono già stati caricati
if get_child_count() > 0: return
# carico e istanzio il template
var gamepad_stick_template = load("res://addons/Gamepad/GamepadStickTemplate.tscn").instance()
# quindi se ci sono oggetti nel template (ovviamente si)
if gamepad_stick_template.get_child_count() > 0:
# prendo ogni oggetto nel template
for child in gamepad_stick_template.get_children():
# e ne aggiungo un duplicato al mio nodo
add_child(child.duplicate())
func _ready():
# se l'oggetto deve essere visualizzato dinamicamente (ovvero solo quando l'utente tocca lo schermo) lo nascondo
if show_dynamically:
_hide_stick()
# imposto la sua posizione statica (non ha senso se visualizzato dinamicamente in quanto la sua posizione
# varierà in base al tocco dell'utente)
rect_position = static_position
# ricavo i restanti valori che mi serviranno più avanti per fare i calcoli
half_size = bg.rect_size / 2
center_point = half_size
stick.position = half_size
half_stick = (stick.texture.get_size() * stick.scale) / 2
squared_half_size_length = half_size.x * half_size.y
# emula lo stick tramite i tasti
func handle_input(event):
if event is InputEventKey:
if !((simulate_up and event.is_action(simulate_up)) or \
(simulate_down and event.is_action(simulate_down)) or \
(simulate_left and event.is_action(simulate_left)) or \
(simulate_right and event.is_action(simulate_right))): return
else:
return
var ev
# verifica quale tasto è stato premuto
var up = simulate_up and Input.is_action_pressed(simulate_up)
var down = simulate_down and Input.is_action_pressed(simulate_down)
var left = simulate_left and Input.is_action_pressed(simulate_left)
var right = simulate_right and Input.is_action_pressed(simulate_right)
simulation = false
# se nessuna delle 4 direzioni è premuta, azzero la forza così che verrà sollevato l'evento di rilascio
if !up and !down and !left and !right:
current_force = Vector2(0, 0)
else:
# se almeno una delle 4 direzioni è premuta, inizializza la posizione del'oggetto
ev = InputEventScreenTouch.new()
ev.position = get_parent().rect_global_position + static_position + half_size
simulation = true
# se lo stick è di qualsiasi tipo tranne un DIGITAL 4 diagonale
if stick_type != STICK_TYPE._DIGITAL_4_X and stick_type != STICK_TYPE._DIGITAL_4_ISO:
# imposto la forza al valore digitale corrispondente ai tasti premuti
current_force.x = -1 if left else 1 if right else 0
current_force.y = -1 if up else 1 if down else 0
else:
# altrimenti, se lo stick è di tipo DIGITAL 4 diagonale, decido io la forza in base al tasto premuto
if up:
down = false; left = false; right = false
current_force = Vector2(-1, -1)
elif left:
down = false; up = false; right = false
current_force = Vector2(-1, 1)
elif down:
up = false; left = false; right = false
current_force = Vector2(1, 1)
elif right:
down = false; left = false; up = false
current_force = Vector2(1, -1)
# se la forza è diversa da 0
if current_force.x != 0 or current_force.y != 0:
# ed è diversa dalla precedente
if last_force.x != current_force.x or last_force.y != current_force.y:
# simulo la pressione del dito sullo stick
handle_down_event(ev, null)
else:
# mentre se la forza è 0 ma la precedente non lo era,
if last_force.x != 0 or last_force.y != 0:
# simulo il rilascio del dito dallo stick
handle_up_event(ev, null)
# l'utente ha toccato lo schermo in corrispondenza dello stick o dell'area che contiene lo stick
func handle_down_event(event, finger):
# se lo stick è disabilitato esco senza fare nulla (prima però resetto i dati interni)
if disabled:
reset()
return
# altrimenti imposto i dati del tocco in modo che possano essere recuperati da fuori
finger_data = finger
# se lo stick deve essere visualizzato dinamicamente vuol dire che in questo momento non è visibile e quindi lo mostro
if show_dynamically:
_show_stick(event)
# se il tocco è avvenuto nella zona dello sfondo dello stick
if simulation or bg.get_global_rect().has_point(event.position):
# calcolo la forza, aggiorno la posizione del centro dello stick ed emetto il segnale
calculate(event)
else:
# altrimenti resetto tutti i dati e esco
reset()
# l'utente ha sollevato il dito con cui aveva toccato lo stick o la sua area
func handle_up_event(event, finger):
# se lo stick è disabilitato esco senza fare nulla (prima però resetto i dati interni)
if disabled:
reset()
return
# altrimenti imposto i dati del tocco in modo che possano essere recuperati da fuori
finger_data = finger
# se lo stick deve essere visualizzato dinamicamente vuol dire che in questo momento è visibile e quindi lo nascondo
if show_dynamically:
_hide_stick()
# resetto i dati interni
reset()
# quindi emetto il segnale per comunicare che lo stick è stato rilasciato
emit_signal("gamepad_stick_released")
# l'utente ha spostato il dito con cui aveva toccato lo stick o la sua area
func handle_move_event(event, finger):
# se lo stick è disabilitato esco senza fare nulla (prima però resetto i dati interni)
if disabled:
reset()
return
# altrimenti imposto i dati del tocco in modo che possano essere recuperati da fuori
finger_data = finger
# calcolo la forza, aggiorno la posizione del centro dello stick ed emetto il segnale
calculate(event)
# calcolo la forza, aggiorno la posizione del centro dello stick ed emetto il segnale
func calculate(event):
# ricalcolo la posizione dell'evento in modo che lo 0,0 coincida con lo 0,0 dell'oggetto
var pos = event.position - rect_global_position
calculate_force(pos)
update_stick_pos()
emit()
func calculate_force(pos):
# print ("pos: ", pos, " - center_point: ", center_point, " - half_size: ", half_size)
if !simulation:
# calcolo la forza in relazione alla posizione del mouse e il centro dello stick, e la normalizzo
current_force.x = (pos.x - center_point.x) / half_size.x
current_force.y = (pos.y - center_point.y) / half_size.y
if current_force.length_squared() > 1:
current_force = current_force / current_force.length()
# quindi se la forza è minore della soglia di validità, resituisco 0,0 (per comunicare che
# non è stato effettuato uno spostamento valido del centro dello stick)
if (current_force.length() < valid_threshold):
current_force = Vector2(0,0)
# effettuo aggiustamenti vari alla forza in baso a che tipo di stick sto gestendo
select_force()
# aggiorno la posizione del centro dello stick in modo che graficamente sia coerente
func update_stick_pos():
stick_pos.x = center_point.x + half_size.x * current_force.x
stick_pos.y = center_point.y + half_size.y * current_force.y
# questa funzione serve solo se lo stick è di tipo DIGITAL 4 ISO
adjust_stick_pos()
stick.position = Vector2(stick_pos)
# calcolo anche l'angolo tra la posizione dello stick e l'asse x
angle = stick.position.angle_to_point(center_point)
# infine gestisco la visualizzazione o meno del centro dello stick se deve essere
# gestita in base al valore di hide_stick_on_stop (vedi commento)
if hide_stick_on_stop and current_force.x == 0 and current_force.y == 0:
stick.hide()
else:
stick.show()
# effettuo un reset dei dati interni, ovvero faccio si che la forza sia impostata a 0,
# il centro dello stick torni graficamente al centro, e sia impostato un angolo invalido
func reset():
# calculate_force(center_point)
current_force = Vector2(0,0)
last_force = Vector2(0,0)
update_stick_pos()
angle = INVALID_ANGLE
# emit()
# emette il segnale per comunicare il cambiamento della forza dello stick
func emit():
if current_force.x != last_force.x or current_force.y != last_force.y:
# solo se la forza corrente è diversa da quella precedente
last_force = Vector2(current_force.x, current_force.y)
emit_signal("gamepad_force_changed", current_force, self)
# se lo stick è di tipo DIGITAL 4 ISO, e la posizione del centro dello stick capita in una
# diagonale alta, viene aggiustata graficamente la posizione
func adjust_stick_pos():
if stick_type != STICK_TYPE._ANALOG and stick_type != null:
if stick_type == STICK_TYPE._DIGITAL_4_ISO and adjust_iso != 0 and current_force.y == -1:
if stick_pos.x < half_stick.x + adjust_iso:
stick_pos.x = half_stick.x + adjust_iso
elif stick_pos.x > rect_size.x - half_stick.x - adjust_iso:
stick_pos.x = rect_size.x - half_stick.x - adjust_iso
else:
if stick_pos.x < half_stick.x:
stick_pos.x = half_stick.x
elif stick_pos.x > rect_size.x - half_stick.x:
stick_pos.x = rect_size.x - half_stick.x
if stick_pos.y < half_stick.y:
stick_pos.y = half_stick.y
elif stick_pos.y > rect_size.y - half_stick.y:
stick_pos.y = rect_size.y - half_stick.y
# qui la forza viene adattata in base al tipo di stick che sto gestendo
func select_force():
match stick_type:
STICK_TYPE._DIGITAL_8:
# la forza viene semplicemente convertita in digitale
to_digital()
STICK_TYPE._DIGITAL_4_PLUS:
# il minore dei due assi viene azzerato in modo che possano
# essere restituite solo forze cardinali
if abs(current_force.x) > abs(current_force.y):
current_force.y = 0
else:
current_force.x = 0
# quindi la forza viene convertita in digitale
to_digital()
STICK_TYPE._DIGITAL_4_X, STICK_TYPE._DIGITAL_4_ISO:
# salvo la forza analogica prima di convertirla in digitale
# in modo da poter capire effettivamente dove si trova il
# centro dello stick
var curr = Vector2(current_force.x, current_force.y)
# converto la forza in digitale
to_digital()
# determino quindi in quale diagonale mi trovo
if abs(current_force.x) == 1:
if curr.y > 0.35:
current_force.y = 1
else:
current_force.y = -1
else:
if abs(current_force.y) == 1:
if curr.x > 0.35:
current_force.x = 1
else:
current_force.x = -1
STICK_TYPE._LEFT_RIGHT:
# azzero l'asse y
current_force.y = 0
# quindi, essendo un controllo analogico, lo sottopondo allo step
to_steps()
STICK_TYPE._UP_DOWN:
# azzero l'asse x
current_force.x = 0
# quindi, essendo un controllo analogico, lo sottopondo allo step
to_steps()
_:
# ANALOG
# essendo un controllo analogico, lo sottopondo allo step
to_steps()
# popolo la lista delle direzioni in base ai valori digitali ottenuti
direction = []
if current_force.x < 0:
direction.append(DIGITAL_DIRECTIONS.LEFT)
elif current_force.x > 0:
direction.append(DIGITAL_DIRECTIONS.RIGHT)
if current_force.y < 0:
direction.append(DIGITAL_DIRECTIONS.UP)
elif current_force.y > 0:
direction.append(DIGITAL_DIRECTIONS.DOWN)
func to_steps():
# se lo step vale 0 (o meno) non applico lo step ed esco
if step <= 0:
return
# se lo step vale 1 (o più) converto direttamente in digitale ed esco
if step >= 1:
to_digital()
return
# altrimenti applico lo step
var modx = int(current_force.x / step) * step if abs(current_force.x) < 0.99 else 1 * sign(current_force.x)
var mody = int(current_force.y / step) * step if abs(current_force.y) < 0.99 else 1 * sign(current_force.y)
current_force = Vector2(modx, mody)
# digitalizza la forza corrente
func to_digital():
current_force = current_force.normalized()
current_force.x = stepify(current_force.x, 1)
current_force.y = stepify(current_force.y, 1)
# mostra lo stick
func _show_stick(event):
# se event è diverso dal null (nel caso in l'utente tocca lo stick o la sua area) calcolo la posizione
# in base a quella passata nell'evento
if shown: return
shown = true
if event:
rect_global_position = event.position - center_point
else:
# altrimenti la posizione dello stick è quella statica impostata in static_position
rect_position = static_position
# avvio l'animazione di visualizzazione
if fader:
if !simulation: reset()
fader.stop()
fader.play("fade_in", -1, 10)
# nasconde lo stick
func _hide_stick():
if !shown: return
shown = false
# avvia l'animazione di nascondimento
if fader:
fader.stop()
fader.play("fade_out", -1, 10)
###[ SETTER/GETTER ]#############################################################################################
func _get_scale():
# if !has_node("Stick"): return Vector2(1.0, 1.0)
return $Stick.scale
func _set_scale(value):
# if !has_node("Stick"): return
$Stick.scale = value
$Stick.position = $StickBackground.rect_size / 2
func _get_bg_texture():
# if !has_node("StickBackground"): return null
return $StickBackground.texture
func _set_bg_texture(value):
# if !has_node("StickBackground"): return
$StickBackground.texture = value
$Stick.position = $StickBackground.rect_size / 2
func _get_texture():
# if !has_node("Stick"): return null
return $Stick.texture
func _set_texture(value):
# if !has_node("Stick"): return
$Stick.texture = value
$Stick.position = $StickBackground.rect_size / 2
func _set_show_dynamically(value):
show_dynamically = value
# se sono nell'editor non faccio nulla (altrimenti mi verrebbe nascosto l'oggetto anche dall'editor)
if Engine.editor_hint: return
if value:
_hide_stick()
else:
_show_stick(null)
###[ END ]#######################################################################################################

View file

@ -0,0 +1,118 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://assets/Gamepad/big_circle.png" type="Texture" id=1]
[ext_resource path="res://assets/Gamepad/small_circle.png" type="Texture" id=2]
[sub_resource type="Animation" id=1]
resource_name = "fade_in"
length = 1.0
loop = false
step = 0.2
tracks/0/type = "value"
tracks/0/path = NodePath("StickBackground:modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 1 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Color( 1, 1, 1, 0 ), Color( 1, 1, 1, 1 ) ]
}
tracks/1/type = "value"
tracks/1/path = NodePath("Stick:modulate")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/keys = {
"times": PoolRealArray( 0, 1 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Color( 1, 1, 1, 0 ), Color( 1, 1, 1, 1 ) ]
}
[sub_resource type="Animation" id=2]
resource_name = "fade_out"
length = 1.0
loop = false
step = 0.1
tracks/0/type = "value"
tracks/0/path = NodePath("StickBackground:modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 1 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ]
}
tracks/1/type = "value"
tracks/1/path = NodePath("Stick:modulate")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/keys = {
"times": PoolRealArray( 0, 1 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ]
}
[node name="GamepadStickTemplate" type="Control" index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 256.0
margin_bottom = 256.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
_sections_unfolded = [ "Rect", "Size Flags" ]
[node name="StickBackground" type="TextureRect" parent="." index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 1.0
anchor_bottom = 1.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 1
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
texture = ExtResource( 1 )
expand = true
stretch_mode = 0
_sections_unfolded = [ "Size Flags", "Visibility" ]
[node name="Stick" type="Sprite" parent="." index="1"]
position = Vector2( 128, 128 )
texture = ExtResource( 2 )
_sections_unfolded = [ "Transform", "Visibility" ]
[node name="ShowHideAnimation" type="AnimationPlayer" parent="." index="2"]
root_node = NodePath("..")
autoplay = ""
playback_process_mode = 1
playback_default_blend_time = 0.0
playback_speed = 1.0
anims/fade_in = SubResource( 1 )
anims/fade_out = SubResource( 2 )
blend_times = [ ]

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 B

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/area.png-839064d7f6486da3f1f42829fe5ff350.stex"
[deps]
source_file="res://addons/Gamepad/icons/area.png"
dest_files=[ "res://.import/area.png-839064d7f6486da3f1f42829fe5ff350.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 727 B

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/button.png-53cd5d056500b25527df0b9c633f2443.stex"
[deps]
source_file="res://addons/Gamepad/icons/button.png"
dest_files=[ "res://.import/button.png-53cd5d056500b25527df0b9c633f2443.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 B

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/container.png-6fa1028c51fbe41a2e5a9a472482d80a.stex"
[deps]
source_file="res://addons/Gamepad/icons/container.png"
dest_files=[ "res://.import/container.png-6fa1028c51fbe41a2e5a9a472482d80a.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 615 B

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/paddle.png-59514a14dc6761beb00e68c904d8fdeb.stex"
[deps]
source_file="res://addons/Gamepad/icons/paddle.png"
dest_files=[ "res://.import/paddle.png-59514a14dc6761beb00e68c904d8fdeb.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/stick.png-f1f1d9614c54b68a216944c6dd22f794.stex"
[deps]
source_file="res://addons/Gamepad/icons/stick.png"
dest_files=[ "res://.import/stick.png-f1f1d9614c54b68a216944c6dd22f794.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -0,0 +1,7 @@
[plugin]
name="Gamepad"
description="Adds touch gamepad controls for mobile applications"
author="Francesco Iafulli"
version="1.0"
script="Gamepad.gd"

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/big_circle.png-133d03445796653ac801f6dce35e2739.stex"
[deps]
source_file="res://assets/Gamepad/big_circle.png"
dest_files=[ "res://.import/big_circle.png-133d03445796653ac801f6dce35e2739.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

BIN
assets/Gamepad/button_a.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/button_a.png-3425d7a5fbc3dfc0a8035eb514d85043.stex"
[deps]
source_file="res://assets/Gamepad/button_a.png"
dest_files=[ "res://.import/button_a.png-3425d7a5fbc3dfc0a8035eb514d85043.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

BIN
assets/Gamepad/button_b.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/button_b.png-126d00e733ca708d9f00355fb34510f6.stex"
[deps]
source_file="res://assets/Gamepad/button_b.png"
dest_files=[ "res://.import/button_b.png-126d00e733ca708d9f00355fb34510f6.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/button_fire.png-a3d807fe20812fbcde99caf0c4dd4553.stex"
[deps]
source_file="res://assets/Gamepad/button_fire.png"
dest_files=[ "res://.import/button_fire.png-a3d807fe20812fbcde99caf0c4dd4553.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

BIN
assets/Gamepad/button_l.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/button_l.png-005713f15e95ca68e459f9814ff0334e.stex"
[deps]
source_file="res://assets/Gamepad/button_l.png"
dest_files=[ "res://.import/button_l.png-005713f15e95ca68e459f9814ff0334e.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

BIN
assets/Gamepad/button_r.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/button_r.png-7b69b467b84da136e20c628e4594a14b.stex"
[deps]
source_file="res://assets/Gamepad/button_r.png"
dest_files=[ "res://.import/button_r.png-7b69b467b84da136e20c628e4594a14b.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/button_target.png-2baafc8011e910bd60bdd7618cee8b74.stex"
[deps]
source_file="res://assets/Gamepad/button_target.png"
dest_files=[ "res://.import/button_target.png-2baafc8011e910bd60bdd7618cee8b74.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

BIN
assets/Gamepad/button_x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/button_x.png-ca13c48418dcd2a2cf82fd985ae9fe5b.stex"
[deps]
source_file="res://assets/Gamepad/button_x.png"
dest_files=[ "res://.import/button_x.png-ca13c48418dcd2a2cf82fd985ae9fe5b.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

BIN
assets/Gamepad/button_y.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/button_y.png-7ff07289434f8350718c3aaa7cc2412d.stex"
[deps]
source_file="res://assets/Gamepad/button_y.png"
dest_files=[ "res://.import/button_y.png-7ff07289434f8350718c3aaa7cc2412d.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/cross_dark.png-309abb32126b3e8341efbb2f05560805.stex"
[deps]
source_file="res://assets/Gamepad/cross_dark.png"
dest_files=[ "res://.import/cross_dark.png-309abb32126b3e8341efbb2f05560805.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/cross_light.png-da14eb1bb7ceb770cd3460d9616bd9d7.stex"
[deps]
source_file="res://assets/Gamepad/cross_light.png"
dest_files=[ "res://.import/cross_light.png-da14eb1bb7ceb770cd3460d9616bd9d7.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/cursor_dark.png-1b46b2c8cde337e0c2b3d16428ce7d4c.stex"
[deps]
source_file="res://assets/Gamepad/cursor_dark.png"
dest_files=[ "res://.import/cursor_dark.png-1b46b2c8cde337e0c2b3d16428ce7d4c.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/cursor_light.png-68fa5bda91a6da44255f09bfc83b5c7c.stex"
[deps]
source_file="res://assets/Gamepad/cursor_light.png"
dest_files=[ "res://.import/cursor_light.png-68fa5bda91a6da44255f09bfc83b5c7c.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/diagonal_dark.png-f84908cf6a4f75f6cf1849b19bafba26.stex"
[deps]
source_file="res://assets/Gamepad/diagonal_dark.png"
dest_files=[ "res://.import/diagonal_dark.png-f84908cf6a4f75f6cf1849b19bafba26.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/diagonal_int_dark.png-5f97c51c3c6125e1c44aca983ca326ef.stex"
[deps]
source_file="res://assets/Gamepad/diagonal_int_dark.png"
dest_files=[ "res://.import/diagonal_int_dark.png-5f97c51c3c6125e1c44aca983ca326ef.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 809 B

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/diagonal_int_light.png-cc157c17e49280d4956545af8a5e3d36.stex"
[deps]
source_file="res://assets/Gamepad/diagonal_int_light.png"
dest_files=[ "res://.import/diagonal_int_light.png-cc157c17e49280d4956545af8a5e3d36.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/diagonal_light.png-46bca542db63d1263474a3c51a4e716c.stex"
[deps]
source_file="res://assets/Gamepad/diagonal_light.png"
dest_files=[ "res://.import/diagonal_light.png-46bca542db63d1263474a3c51a4e716c.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/left_right_dark.png-ecafbcd1394c471262560c7d3f30b204.stex"
[deps]
source_file="res://assets/Gamepad/left_right_dark.png"
dest_files=[ "res://.import/left_right_dark.png-ecafbcd1394c471262560c7d3f30b204.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/left_right_light.png-997df9a152863ba659ae2db2d3127d1a.stex"
[deps]
source_file="res://assets/Gamepad/left_right_light.png"
dest_files=[ "res://.import/left_right_light.png-997df9a152863ba659ae2db2d3127d1a.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/omni_dark.png-c2c424cfec7053d41d67b22c27529ee0.stex"
[deps]
source_file="res://assets/Gamepad/omni_dark.png"
dest_files=[ "res://.import/omni_dark.png-c2c424cfec7053d41d67b22c27529ee0.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/omni_int_dark.png-871036fd0dcaeafb8ead63d9ae7bca86.stex"
[deps]
source_file="res://assets/Gamepad/omni_int_dark.png"
dest_files=[ "res://.import/omni_int_dark.png-871036fd0dcaeafb8ead63d9ae7bca86.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/omni_int_light.png-b29f657562a3524e3d0bca76cddcaeeb.stex"
[deps]
source_file="res://assets/Gamepad/omni_int_light.png"
dest_files=[ "res://.import/omni_int_light.png-b29f657562a3524e3d0bca76cddcaeeb.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/omni_light.png-9f8bbd8a6d35d648f266d2b186633764.stex"
[deps]
source_file="res://assets/Gamepad/omni_light.png"
dest_files=[ "res://.import/omni_light.png-9f8bbd8a6d35d648f266d2b186633764.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/omni_square_dark.png-d225c4fae15b4c1cdb018f845344bc57.stex"
[deps]
source_file="res://assets/Gamepad/omni_square_dark.png"
dest_files=[ "res://.import/omni_square_dark.png-d225c4fae15b4c1cdb018f845344bc57.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/omni_square_int_dark.png-e32d7d162dbb803947e8c5f580f24cb1.stex"
[deps]
source_file="res://assets/Gamepad/omni_square_int_dark.png"
dest_files=[ "res://.import/omni_square_int_dark.png-e32d7d162dbb803947e8c5f580f24cb1.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/omni_square_int_light.png-1c9b638196c3a0ec99bd4edcf6938779.stex"
[deps]
source_file="res://assets/Gamepad/omni_square_int_light.png"
dest_files=[ "res://.import/omni_square_int_light.png-1c9b638196c3a0ec99bd4edcf6938779.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/omni_square_light.png-a81ead77f97f3089dffdefb5b69acaa5.stex"
[deps]
source_file="res://assets/Gamepad/omni_square_light.png"
dest_files=[ "res://.import/omni_square_light.png-a81ead77f97f3089dffdefb5b69acaa5.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/paddle_dark.png-ff76cc51d0c2f8d02ca93579ce2effba.stex"
[deps]
source_file="res://assets/Gamepad/paddle_dark.png"
dest_files=[ "res://.import/paddle_dark.png-ff76cc51d0c2f8d02ca93579ce2effba.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/paddle_light.png-68bc3bd76f7f29fd851c29cccf13f361.stex"
[deps]
source_file="res://assets/Gamepad/paddle_light.png"
dest_files=[ "res://.import/paddle_light.png-68bc3bd76f7f29fd851c29cccf13f361.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 834 B

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/small_circle.png-136001dcb41744d5a052513c95052c98.stex"
[deps]
source_file="res://assets/Gamepad/small_circle.png"
dest_files=[ "res://.import/small_circle.png-136001dcb41744d5a052513c95052c98.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/up_down_dark.png-7d220233a78e0d477d10e5afebcf5f3b.stex"
[deps]
source_file="res://assets/Gamepad/up_down_dark.png"
dest_files=[ "res://.import/up_down_dark.png-7d220233a78e0d477d10e5afebcf5f3b.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/up_down_light.png-b168b374670f061c4cba35a8b8c61c2a.stex"
[deps]
source_file="res://assets/Gamepad/up_down_light.png"
dest_files=[ "res://.import/up_down_light.png-b168b374670f061c4cba35a8b8c61c2a.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -0,0 +1,63 @@
extends KinematicBody2D
const UPRIGHT = Vector2(0, -1)
const GRAVITY = 20
const MAX_SPEED = 200
const ACCELERATION = 50
const JUMP_HEIGHT = -550
var motion = Vector2()
var touch_pos = Vector2()
var screen_bounds = Vector2()
enum DIGITAL_DIRECTIONS { UP, LEFT, DOWN, RIGHT, RELEASED }
var active_direction = DIGITAL_DIRECTIONS.RELEASED
var jump_pressed = false
func _ready():
screen_bounds = get_viewport().get_visible_rect().size
func _physics_process(delta):
motion.y += GRAVITY
var friction = false
if Input.is_action_pressed("ui_right") or active_direction == DIGITAL_DIRECTIONS.RIGHT:
motion.x = min(motion.x + ACCELERATION, MAX_SPEED)
$Sprite.flip_h = false
$Sprite.play("Run")
elif Input.is_action_pressed("ui_left") or active_direction == DIGITAL_DIRECTIONS.LEFT:
motion.x = max(motion.x - ACCELERATION, -MAX_SPEED)
$Sprite.flip_h = true
$Sprite.play("Run")
else:
$Sprite.play("Idle")
friction = true
if is_on_floor():
if Input.is_action_just_pressed("ui_up") or jump_pressed:
motion.y = JUMP_HEIGHT
if friction == true:
motion.x = lerp(motion.x, 0, 0.2)
else:
if motion.y < 0:
$Sprite.play("Jump")
else:
$Sprite.play("Fall")
if friction == true:
motion.x = lerp(motion.x, 0, 0.05)
motion = move_and_slide(motion, UPRIGHT)
func gamepad_force_changed(current_force, sender):
print ("Gamepad force: ", current_force, ", direction: ", sender.direction)
if sender.direction.size() > 0:
active_direction = sender.direction[0]
else:
active_direction = DIGITAL_DIRECTIONS.RELEASED
func gamepad_stick_released():
active_direction = DIGITAL_DIRECTIONS.RELEASED
func A_GamepadButton_up(sender):
jump_pressed = false
func A_GamepadButton_down(sender):
jump_pressed = true

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/Idle0.png-afe017ad7ad0d90b5a0140896d6c9932.stex"
[deps]
source_file="res://characters/player/sprite/Idle0.png"
dest_files=[ "res://.import/Idle0.png-afe017ad7ad0d90b5a0140896d6c9932.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 883 B

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/Jump0.png-1031ca0b01bb60a449a0b5aa1293e57b.stex"
[deps]
source_file="res://characters/player/sprite/Jump0.png"
dest_files=[ "res://.import/Jump0.png-1031ca0b01bb60a449a0b5aa1293e57b.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 807 B

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/Jump1.png-4dcf5efccf390af8d32013b538a4b3d5.stex"
[deps]
source_file="res://characters/player/sprite/Jump1.png"
dest_files=[ "res://.import/Jump1.png-4dcf5efccf390af8d32013b538a4b3d5.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 794 B

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/Jump3.png-90ebffddf0dbb59d0163b1d95dc16442.stex"
[deps]
source_file="res://characters/player/sprite/Jump3.png"
dest_files=[ "res://.import/Jump3.png-90ebffddf0dbb59d0163b1d95dc16442.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 B

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/Jump4.png-0eb245ee330545001e2a3d898d1f49f0.stex"
[deps]
source_file="res://characters/player/sprite/Jump4.png"
dest_files=[ "res://.import/Jump4.png-0eb245ee330545001e2a3d898d1f49f0.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 867 B

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/Run0.png-6c9753af7d0b2baf39cd2c0db6fb1ec8.stex"
[deps]
source_file="res://characters/player/sprite/Run0.png"
dest_files=[ "res://.import/Run0.png-6c9753af7d0b2baf39cd2c0db6fb1ec8.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 792 B

View file

@ -0,0 +1,29 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/Run1.png-0f17afe42ce1632133d8f7622d9318b9.stex"
[deps]
source_file="res://characters/player/sprite/Run1.png"
dest_files=[ "res://.import/Run1.png-0f17afe42ce1632133d8f7622d9318b9.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

Some files were not shown because too many files have changed in this diff Show more