Crabs first version
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
extends Node2D
|
||||
class_name Crab
|
||||
|
||||
signal crab_hit(stimulus: Dictionary)
|
||||
|
||||
@onready var animation_player: = $AnimationPlayer
|
||||
@onready var label: = $Label
|
||||
@onready var button: = $Button
|
||||
|
||||
var stimulus: Dictionary
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
set_button_active(false)
|
||||
|
||||
|
||||
func set_button_active(active: bool) -> void:
|
||||
button.disabled = not active
|
||||
|
||||
|
||||
func set_stimulus(p_stimulus: Dictionary) -> void:
|
||||
stimulus = p_stimulus
|
||||
|
||||
label.text = stimulus["label"]
|
||||
|
||||
|
||||
func _on_button_pressed() -> void:
|
||||
emit_signal("crab_hit", stimulus)
|
||||
animation_player.play("hit")
|
||||
|
||||
|
||||
func _on_animation_player_animation_finished(animation_name: StringName) -> void:
|
||||
var idles: = ["idle1", "idle2"]
|
||||
if animation_name in idles:
|
||||
var r: = randi() % idles.size()
|
||||
animation_player.play(idles[r])
|
||||
if animation_name == "hit":
|
||||
animation_player.play("hurt")
|
||||
@@ -0,0 +1,148 @@
|
||||
[gd_scene load_steps=16 format=3 uid="uid://bwe3fp0vkpufb"]
|
||||
|
||||
[ext_resource type="Script" path="res://sources/minigames/crabs/crab/crab.gd" id="1_5hgg8"]
|
||||
[ext_resource type="Texture2D" uid="uid://c36217nu30yh3" path="res://resources/minigames/crabs/graphic/crab_spritesheet.png" id="2_yu4q0"]
|
||||
[ext_resource type="FontFile" uid="uid://b2l4jfylc1v41" path="res://resources/fonts/DidactGothic-Regular.ttf" id="3_dei0e"]
|
||||
|
||||
[sub_resource type="Animation" id="Animation_lftfb"]
|
||||
length = 0.001
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("Crab:frame")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 1,
|
||||
"values": [0]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_b2qjc"]
|
||||
resource_name = "hit"
|
||||
length = 0.4
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("Crab:frame")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.1, 0.2, 0.3),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1),
|
||||
"update": 1,
|
||||
"values": [18, 19, 20, 21]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_aahhw"]
|
||||
resource_name = "hurt"
|
||||
length = 0.6
|
||||
loop_mode = 1
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("Crab:frame")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
|
||||
"update": 1,
|
||||
"values": [12, 13, 14, 15, 16, 17]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_5butr"]
|
||||
resource_name = "idle1"
|
||||
length = 0.6
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("Crab:frame")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
|
||||
"update": 1,
|
||||
"values": [0, 1, 2, 3, 4, 5]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_0cnq1"]
|
||||
resource_name = "idle2"
|
||||
length = 0.6
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("Crab:frame")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
|
||||
"update": 1,
|
||||
"values": [6, 7, 8, 9, 10, 11]
|
||||
}
|
||||
|
||||
[sub_resource type="AnimationLibrary" id="AnimationLibrary_ifo73"]
|
||||
_data = {
|
||||
"RESET": SubResource("Animation_lftfb"),
|
||||
"hit": SubResource("Animation_b2qjc"),
|
||||
"hurt": SubResource("Animation_aahhw"),
|
||||
"idle1": SubResource("Animation_5butr"),
|
||||
"idle2": SubResource("Animation_0cnq1")
|
||||
}
|
||||
|
||||
[sub_resource type="LabelSettings" id="LabelSettings_lys05"]
|
||||
font = ExtResource("3_dei0e")
|
||||
font_size = 42
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_tnp5x"]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_g8ffa"]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_fwwak"]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_tdur1"]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_1h5my"]
|
||||
|
||||
[node name="Crab" type="Node2D"]
|
||||
script = ExtResource("1_5hgg8")
|
||||
|
||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
||||
autoplay = "idle1"
|
||||
libraries = {
|
||||
"": SubResource("AnimationLibrary_ifo73")
|
||||
}
|
||||
|
||||
[node name="Crab" type="Sprite2D" parent="."]
|
||||
light_mask = 1024
|
||||
visibility_layer = 1024
|
||||
texture = ExtResource("2_yu4q0")
|
||||
offset = Vector2(-5, -8)
|
||||
hframes = 6
|
||||
vframes = 4
|
||||
|
||||
[node name="Label" type="Label" parent="."]
|
||||
offset_left = -56.0
|
||||
offset_top = -33.0
|
||||
offset_right = 55.0
|
||||
offset_bottom = 52.0
|
||||
label_settings = SubResource("LabelSettings_lys05")
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="Button" type="Button" parent="."]
|
||||
offset_left = -56.0
|
||||
offset_top = -33.0
|
||||
offset_right = 55.0
|
||||
offset_bottom = 52.0
|
||||
theme_override_styles/normal = SubResource("StyleBoxEmpty_tnp5x")
|
||||
theme_override_styles/hover = SubResource("StyleBoxEmpty_g8ffa")
|
||||
theme_override_styles/pressed = SubResource("StyleBoxEmpty_fwwak")
|
||||
theme_override_styles/disabled = SubResource("StyleBoxEmpty_tdur1")
|
||||
theme_override_styles/focus = SubResource("StyleBoxEmpty_1h5my")
|
||||
|
||||
[connection signal="animation_finished" from="AnimationPlayer" to="." method="_on_animation_player_animation_finished"]
|
||||
[connection signal="pressed" from="Button" to="." method="_on_button_pressed"]
|
||||
@@ -0,0 +1,143 @@
|
||||
extends Minigame
|
||||
|
||||
@export var difficulty: = 1
|
||||
|
||||
const hole_class: = preload("res://sources/minigames/crabs/hole/hole.tscn")
|
||||
const difficulty_settings: = {
|
||||
0: {"crab_rows": [2, 1]},
|
||||
1 : {"crab_rows": [3, 2]},
|
||||
2 : {"crab_rows": [4, 3]},
|
||||
3 : {"crab_rows": [4, 3, 2]},
|
||||
4 : {"crab_rows": [4, 3, 4]},
|
||||
}
|
||||
|
||||
@onready var top_left: = $GameRoot/TopLeft
|
||||
@onready var bottom_right: = $GameRoot/BottomRight
|
||||
|
||||
var holes: = []
|
||||
|
||||
|
||||
# ------------ Initialisation ------------
|
||||
|
||||
# Find and set the parameters of the minigame, like the number of lives or the victory conditions.
|
||||
func _setup_minigame() -> void:
|
||||
super._setup_minigame()
|
||||
|
||||
# Progression management
|
||||
max_progression = 10
|
||||
current_progression = 0
|
||||
|
||||
var max_difficulty: = 0
|
||||
for d in difficulty_settings.keys():
|
||||
if d > max_difficulty:
|
||||
max_difficulty = d
|
||||
|
||||
if difficulty > max_difficulty:
|
||||
difficulty = max_difficulty
|
||||
|
||||
var settings: Dictionary = difficulty_settings[difficulty]
|
||||
for i in range(settings["crab_rows"].size()):
|
||||
var fi: = float(i + 1.0) / float(settings["crab_rows"].size() + 1.0)
|
||||
var y: float = (1.0 - fi) * top_left.position.y + fi * bottom_right.position.y
|
||||
for j in range(settings["crab_rows"][i]):
|
||||
var fj: = float(j + 1.0) / float(settings["crab_rows"][i] + 1.0)
|
||||
var x: float = fj * top_left.position.x + (1.0 - fj) * bottom_right.position.x
|
||||
|
||||
var hole: = hole_class.instantiate()
|
||||
game_root.add_child(hole)
|
||||
hole.position = Vector2(x, y)
|
||||
|
||||
hole.connect("stimulus_hit", _on_hole_stimulus_hit)
|
||||
hole.connect("crab_despawned", _on_hole_crab_despawned)
|
||||
|
||||
holes.append(hole)
|
||||
|
||||
|
||||
# Find the stimuli and distractions of the minigame.
|
||||
func _find_stimuli_and_distractions() -> void:
|
||||
# TODO: fake stimuli and distractor for testing
|
||||
# Replace in the future by a proper research
|
||||
stimuli = [{"label": "a", "sound": ""}]
|
||||
distractions = [
|
||||
{"label": "e", "sound": ""},
|
||||
{"label": "u", "sound": ""},
|
||||
{"label": "o", "sound": ""},
|
||||
]
|
||||
|
||||
|
||||
# Launch the minigame
|
||||
func _start() -> void:
|
||||
super._start()
|
||||
|
||||
_on_hole_timer_timeout(stimuli[0])
|
||||
|
||||
for i in range(3 * holes.size() / 4):
|
||||
_on_hole_crab_despawned(distractions[randi() % distractions.size()])
|
||||
|
||||
await get_tree().create_timer(0.1).timeout
|
||||
|
||||
|
||||
# ------------ Crabs ------------
|
||||
|
||||
|
||||
func _on_hole_stimulus_hit(stimulus: Dictionary) -> void:
|
||||
if stimulus in stimuli:
|
||||
current_progression += 1
|
||||
else:
|
||||
current_lives -= 1
|
||||
|
||||
|
||||
func _on_hole_timer_timeout(stimulus: Dictionary) -> void:
|
||||
var holes_range: = range(holes.size())
|
||||
holes_range.shuffle()
|
||||
|
||||
var hole_found: = false
|
||||
while not hole_found:
|
||||
for i in holes_range:
|
||||
if not holes[i].crab_spawned:
|
||||
holes[i].spawn_crab(stimulus)
|
||||
hole_found = true
|
||||
|
||||
break
|
||||
|
||||
if not hole_found:
|
||||
await get_tree().create_timer(randf_range(0.1, 0.5)).timeout
|
||||
|
||||
|
||||
func _on_hole_crab_despawned(stimulus: Dictionary) -> void:
|
||||
await get_tree().create_timer(randf_range(0.1, 2.0)).timeout
|
||||
|
||||
_on_hole_timer_timeout(stimulus)
|
||||
|
||||
|
||||
# ------------ Logs ------------
|
||||
|
||||
|
||||
func _save_logs() -> void:
|
||||
LessonLogger.save_logs(logs, GameGlobals.teacher_id, GameGlobals.user_id, minigame_name, lesson, Time.get_time_string_from_system())
|
||||
|
||||
_reset_logs()
|
||||
|
||||
|
||||
func _reset_logs() -> void:
|
||||
logs = {}
|
||||
|
||||
|
||||
# ------------ UI ------------
|
||||
|
||||
# Callbacks
|
||||
|
||||
func _go_back_to_the_garden() -> void:
|
||||
return
|
||||
|
||||
|
||||
func _play_stimulus() -> void:
|
||||
return
|
||||
|
||||
|
||||
func _pause_game() -> void:
|
||||
get_tree().paused = not get_tree().paused
|
||||
|
||||
|
||||
func _play_kalulu() -> void:
|
||||
return
|
||||
@@ -0,0 +1,32 @@
|
||||
[gd_scene load_steps=8 format=3 uid="uid://c8ntt5r3fjeh"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://8awe4usnucyv" path="res://sources/minigames/base/base_minigame.tscn" id="1_lbq56"]
|
||||
[ext_resource type="Script" path="res://sources/minigames/crabs/crabs_minigame.gd" id="2_gierf"]
|
||||
[ext_resource type="Texture2D" uid="uid://bt7u67errbjls" path="res://resources/minigames/crabs/graphic/gauge_icon_crab_empty.png" id="3_s5o38"]
|
||||
[ext_resource type="AudioStream" uid="uid://4qo683e8atp4" path="res://resources/minigames/crabs/audio/kalulu/kalulu_help_crabs_language.mp3" id="3_vtu3m"]
|
||||
[ext_resource type="Texture2D" uid="uid://cq5wwf7y1msh7" path="res://resources/minigames/crabs/graphic/gauge_icon_crab_full.png" id="4_a1dm5"]
|
||||
[ext_resource type="AudioStream" uid="uid://cmp7vupeq11ic" path="res://resources/minigames/crabs/audio/kalulu/kalulu_end_crabs_all.mp3" id="4_eh4op"]
|
||||
[ext_resource type="Texture2D" uid="uid://5bx8ugh178j1" path="res://resources/minigames/crabs/graphic/background.png" id="5_0ps1r"]
|
||||
|
||||
[node name="Crabs" instance=ExtResource("1_lbq56")]
|
||||
script = ExtResource("2_gierf")
|
||||
difficulty = 4
|
||||
minigame_name = "Crabs"
|
||||
start_kalulu_speech = ExtResource("3_vtu3m")
|
||||
win_kalulu_speech = ExtResource("4_eh4op")
|
||||
|
||||
[node name="MinigameUI" parent="." index="0"]
|
||||
empty_progression_icon = ExtResource("3_s5o38")
|
||||
full_progression_icon = ExtResource("4_a1dm5")
|
||||
|
||||
[node name="Background" type="Sprite2D" parent="GameRoot" index="0"]
|
||||
position = Vector2(1280, 900)
|
||||
scale = Vector2(2, 2)
|
||||
texture = ExtResource("5_0ps1r")
|
||||
metadata/_edit_lock_ = true
|
||||
|
||||
[node name="TopLeft" type="Node2D" parent="GameRoot" index="1"]
|
||||
position = Vector2(544, 631)
|
||||
|
||||
[node name="BottomRight" type="Node2D" parent="GameRoot" index="2"]
|
||||
position = Vector2(2310, 1675)
|
||||
@@ -0,0 +1,83 @@
|
||||
extends Node2D
|
||||
class_name CrabHole
|
||||
|
||||
signal stimulus_hit(stimulus: Dictionary)
|
||||
signal crab_despawned(stimulus: Dictionary)
|
||||
|
||||
const crab_class: = preload("res://sources/minigames/crabs/crab/crab.tscn")
|
||||
|
||||
@onready var hole_back: = $HoleBack
|
||||
@onready var hole_front: = $HoleFront
|
||||
@onready var mask: = $Mask
|
||||
@onready var timer: = $Timer
|
||||
@onready var crab_audio_stream_player: = $CrabAudioStreamPlayer2D
|
||||
|
||||
var crab: Crab
|
||||
var crab_hit: = false
|
||||
var crab_spawned: = false
|
||||
|
||||
|
||||
func spawn_crab(stimulus: Dictionary) -> void:
|
||||
crab_spawned = true
|
||||
|
||||
crab = crab_class.instantiate()
|
||||
mask.add_child(crab)
|
||||
|
||||
crab.connect("crab_hit", _crab_hit)
|
||||
|
||||
crab.position = Vector2(0, 200)
|
||||
crab.set_stimulus(stimulus)
|
||||
|
||||
crab_audio_stream_player.start_playing()
|
||||
|
||||
var first_tween: = create_tween()
|
||||
first_tween.tween_property(crab, "position", Vector2(0.0, 100.0), randf_range(0.25, 2.0))
|
||||
await first_tween.finished
|
||||
first_tween.kill()
|
||||
|
||||
crab_audio_stream_player.stop_playing()
|
||||
|
||||
timer.start(randf_range(0.25, 1.5))
|
||||
await timer.timeout
|
||||
|
||||
crab_audio_stream_player.start_playing()
|
||||
|
||||
var second_tween: = create_tween()
|
||||
second_tween.tween_property(crab, "position", Vector2(0.0, -50.0), 0.25)
|
||||
await second_tween.finished
|
||||
second_tween.kill()
|
||||
|
||||
crab_audio_stream_player.stop_playing()
|
||||
|
||||
crab_hit = false
|
||||
crab.set_button_active(true)
|
||||
|
||||
timer.start(randf_range(1.0, 2.5))
|
||||
await timer.timeout
|
||||
|
||||
crab.set_button_active(false)
|
||||
|
||||
var final_tween: = create_tween()
|
||||
if crab_hit:
|
||||
final_tween.tween_property(crab, "position", Vector2(0.0, -200.0), 0.5)
|
||||
final_tween.parallel().tween_property(crab, "rotation_degrees", 540.0, 0.5)
|
||||
else:
|
||||
crab_audio_stream_player.start_playing()
|
||||
final_tween.tween_property(crab, "position", Vector2(0.0, 200.0), 0.25)
|
||||
await final_tween.finished
|
||||
|
||||
crab_audio_stream_player.stop_playing()
|
||||
|
||||
crab.queue_free()
|
||||
|
||||
crab_spawned = false
|
||||
|
||||
emit_signal("crab_despawned", stimulus)
|
||||
|
||||
|
||||
func _crab_hit(stimulus: Dictionary) -> void:
|
||||
crab_hit = true
|
||||
crab.set_button_active(false)
|
||||
if not timer.is_stopped():
|
||||
timer.start(0.4)
|
||||
emit_signal("stimulus_hit", stimulus)
|
||||
@@ -0,0 +1,35 @@
|
||||
[gd_scene load_steps=7 format=3 uid="uid://byq160dxpb3rl"]
|
||||
|
||||
[ext_resource type="Script" path="res://sources/minigames/crabs/hole/hole.gd" id="1_05s8c"]
|
||||
[ext_resource type="Texture2D" uid="uid://tfigqbebxmal" path="res://resources/minigames/crabs/graphic/hole_back.png" id="2_f44i6"]
|
||||
[ext_resource type="Texture2D" uid="uid://7nrlmc7opox1" path="res://resources/minigames/crabs/graphic/hole_mask.png" id="3_ehfgm"]
|
||||
[ext_resource type="Texture2D" uid="uid://jl4sirrpr1l1" path="res://icon.svg" id="4_5yovx"]
|
||||
[ext_resource type="Texture2D" uid="uid://cwebei83ml5vs" path="res://resources/minigames/crabs/graphic/hole_front.png" id="5_mhdld"]
|
||||
[ext_resource type="Script" path="res://sources/minigames/crabs/hole/hole_audio_stream_player_2d.gd" id="6_2rg3s"]
|
||||
|
||||
[node name="Hole" type="Node2D"]
|
||||
position = Vector2(947, 568)
|
||||
script = ExtResource("1_05s8c")
|
||||
|
||||
[node name="HoleBack" type="Sprite2D" parent="."]
|
||||
texture = ExtResource("2_f44i6")
|
||||
|
||||
[node name="Mask" type="Sprite2D" parent="."]
|
||||
clip_children = 1
|
||||
position = Vector2(0, -51)
|
||||
texture = ExtResource("3_ehfgm")
|
||||
|
||||
[node name="IconToHideTheMask" type="Sprite2D" parent="Mask"]
|
||||
position = Vector2(-1, 263)
|
||||
texture = ExtResource("4_5yovx")
|
||||
|
||||
[node name="HoleFront" type="Sprite2D" parent="."]
|
||||
position = Vector2(0, 2)
|
||||
texture = ExtResource("5_mhdld")
|
||||
|
||||
[node name="Timer" type="Timer" parent="."]
|
||||
|
||||
[node name="CrabAudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."]
|
||||
script = ExtResource("6_2rg3s")
|
||||
|
||||
[connection signal="finished" from="CrabAudioStreamPlayer2D" to="CrabAudioStreamPlayer2D" method="_on_finished"]
|
||||
@@ -0,0 +1,34 @@
|
||||
extends AudioStreamPlayer2D
|
||||
|
||||
const crab_sound_list: = [
|
||||
preload("res://resources/minigames/crabs/audio/sfx/crab_random_1.mp3"),
|
||||
preload("res://resources/minigames/crabs/audio/sfx/crab_random_1.mp3"),
|
||||
preload("res://resources/minigames/crabs/audio/sfx/crab_random_1.mp3"),
|
||||
preload("res://resources/minigames/crabs/audio/sfx/crab_random_1.mp3"),
|
||||
preload("res://resources/minigames/crabs/audio/sfx/crab_random_1.mp3"),
|
||||
preload("res://resources/minigames/crabs/audio/sfx/crab_random_1.mp3"),
|
||||
preload("res://resources/minigames/crabs/audio/sfx/crab_random_1.mp3"),
|
||||
preload("res://resources/minigames/crabs/audio/sfx/crab_random_1.mp3"),
|
||||
preload("res://resources/minigames/crabs/audio/sfx/crab_random_1.mp3"),
|
||||
preload("res://resources/minigames/crabs/audio/sfx/crab_random_1.mp3"),
|
||||
preload("res://resources/minigames/crabs/audio/sfx/crab_random_1.mp3"),
|
||||
preload("res://resources/minigames/crabs/audio/sfx/crab_random_1.mp3"),
|
||||
preload("res://resources/minigames/crabs/audio/sfx/crab_random_1.mp3"),
|
||||
]
|
||||
|
||||
var should_play: = false
|
||||
|
||||
|
||||
func start_playing() -> void:
|
||||
should_play = true
|
||||
_on_finished()
|
||||
|
||||
|
||||
func stop_playing() -> void:
|
||||
should_play = false
|
||||
|
||||
|
||||
func _on_finished() -> void:
|
||||
if should_play:
|
||||
stream = crab_sound_list[randi() % crab_sound_list.size()]
|
||||
playing = true
|
||||
Reference in New Issue
Block a user