]> git.seodisparate.com - LD55/commitdiff
Work
authorStephen Seo <seo.disparate@gmail.com>
Sun, 14 Apr 2024 08:24:30 +0000 (17:24 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Sun, 14 Apr 2024 08:24:30 +0000 (17:24 +0900)
Some more work towards implementing battle.

Added summoning mini-game for summoning.

17 files changed:
MainLogic.gd
audio/LD55_sfx_cancel.mp3 [new file with mode: 0644]
audio/LD55_sfx_cancel.mp3.import [new file with mode: 0644]
audio/LD55_sfx_confirm.mp3 [new file with mode: 0644]
audio/LD55_sfx_confirm.mp3.import [new file with mode: 0644]
audio/LD55_sfx_hammer_hit.mp3 [new file with mode: 0644]
audio/LD55_sfx_hammer_hit.mp3.import [new file with mode: 0644]
audio/LD55_sfx_select.mp3 [new file with mode: 0644]
audio/LD55_sfx_select.mp3.import [new file with mode: 0644]
audio/LD55_sfx_sword_hit.mp3 [new file with mode: 0644]
audio/LD55_sfx_sword_hit.mp3.import [new file with mode: 0644]
gander_schwartz.gd
gimp/summon_arrow.png [new file with mode: 0644]
gimp/summon_arrow.png.import [new file with mode: 0644]
main_scene.tscn
summoning.gd [new file with mode: 0644]
summoning.tscn [new file with mode: 0644]

index bd6155c79228db63af45db40a3d4d7fa9193deeb..d05ab498974a4150257c74de883d470ed9111248 100644 (file)
@@ -9,6 +9,10 @@ extends Node2D
 @onready var earth_diamond = $EarthDiamond
 
 @onready var music_player = $MusicPlayer
+@onready var sfx_player = $SFXPlayer
+var sfx_select
+var sfx_confirm
+var sfx_cancel
 
 @onready var camera = $Camera2D
 
@@ -56,8 +60,12 @@ enum StateT {
        Dungeon_Entrance_Battle,
 }
 
-enum BattleMenu {
+enum BattleState {
        MainMenu,
+       SummonMenu,
+       SummonSword,
+       SummonHammer,
+       EnemyAttack,
 }
 
 static var state_dict = {}
@@ -93,6 +101,9 @@ func _ready():
                        viewport_size = get_viewport().size
                        state_dict["battle_refresh_gui"] = true
                )
+               sfx_select = load("res://audio/LD55_sfx_select.mp3")
+               sfx_confirm = load("res://audio/LD55_sfx_confirm.mp3")
+               sfx_cancel = load("res://audio/LD55_sfx_cancel.mp3")
 
 func update_text(text, next_state):
        if state_dict["timer"] > text_speed:
@@ -216,10 +227,24 @@ func _process(delta):
                                tween_scene.tween_callback(func():
                                        gander.auto_control_action = "facing_left"
                                        state_dict["state"] = StateT.Dungeon_Entrance_Battle
-                                       state_dict["battle_state"] = BattleMenu.MainMenu
+                                       state_dict["battle_state"] = BattleState.MainMenu
                                        state_dict["battle_menu_setup"] = false
                                        state_dict["battle_refresh_gui"] = false
                                        state_dict["battle_item"] = null
+                                       var indicator_arrow = Sprite2D.new()
+                                       indicator_arrow.texture = load("res://gimp/arrow.png")
+                                       indicator_arrow.position.x = (indicator_arrow.get_rect().size.x - viewport_size.x) / 2.0
+                                       indicator_arrow.position.y = (viewport_size.y - indicator_arrow.get_rect().size.y) / 2.0
+                                       camera.add_child(indicator_arrow)
+                                       indicator_arrow.set_owner(camera)
+                                       tween_text = get_tree().create_tween()
+                                       tween_text.set_parallel()
+                                       tween_text.tween_property(indicator_arrow, "scale", Vector2(20.0, 20.0), 1.5)
+                                       tween_text.tween_property(indicator_arrow, "self_modulate", Color(1, 1, 1, 0), 1.5)
+                                       tween_text.set_parallel(false)
+                                       tween_text.tween_callback(func():
+                                               camera.remove_child(indicator_arrow)
+                                       )
                                )
                StateT.Dungeon_Entrance_Battle:
                        camera_to_target(delta, level_cached_pos + Vector2(0.0, 500.0))
@@ -381,7 +406,7 @@ func camera_to_target(delta, vec2):
 
 func setup_battle_menu():
        match state_dict["battle_state"]:
-               BattleMenu.MainMenu:
+               BattleState.MainMenu:
                        if not state_dict["battle_menu_setup"] or state_dict["battle_refresh_gui"]:
                                state_dict["battle_menu_setup"] = true
                                state_dict["battle_refresh_gui"] = false
@@ -392,6 +417,7 @@ func setup_battle_menu():
                                        battle_arrow.texture = load("res://gimp/arrow.png")
                                        camera.add_child(battle_arrow, true)
                                        battle_arrow.set_owner(camera)
+                               battle_arrow.self_modulate = Color(1, 1, 1, 1)
                                var battle_menu_item_0 = camera.find_child("BattleMenuItem0")
                                if battle_menu_item_0 == null:
                                        battle_menu_item_0 = Label.new()
@@ -426,8 +452,76 @@ func setup_battle_menu():
                                        battle_menu_item_1.position.y = battle_arrow.position.y + arrow_rect.size.y
                                        state_dict["battle_selection"] = 0
                                        state_dict["battle_options"] = ["attack", "summon"]
+               BattleState.SummonMenu:
+                       if not state_dict["battle_menu_setup"] or state_dict["battle_refresh_gui"]:
+                               state_dict["battle_menu_setup"] = true
+                               state_dict["battle_refresh_gui"] = false
+                               var battle_arrow = camera.find_child("BattleArrow")
+                               var battle_menu_item_0 = camera.find_child("BattleMenuItem0")
+                               var battle_menu_item_1 = camera.find_child("BattleMenuItem1")
+                               battle_arrow.self_modulate = Color(1, 1, 1, 1)
+                               battle_menu_item_0.text = "Summon Sword"
+                               battle_menu_item_1.text = "Summon Hammer"
+                               var arrow_rect = battle_arrow.get_rect()
+                               battle_arrow.position.x = (arrow_rect.size.x - viewport_size.x) / 2.0
+                               battle_arrow.position.y = (viewport_size.y - arrow_rect.size.y * 3.0) / 2.0
+                               battle_menu_item_0.position.x = arrow_rect.size.x - viewport_size.x / 2.0
+                               battle_menu_item_0.position.y = battle_arrow.position.y
+                               battle_menu_item_1.position.x = arrow_rect.size.x - viewport_size.x / 2.0
+                               battle_menu_item_1.position.y = battle_arrow.position.y + arrow_rect.size.y
+                               state_dict["battle_selection"] = 0
+                               state_dict["battle_options"] = ["summon_sword", "summon_hammer"]
+               BattleState.SummonSword:
+                       var summon_node = find_child("SummonAttempt")
+                       if summon_node.success_count >= summon_node.MAX_SUCCESS:
+                               camera.remove_child(summon_node)
+                               var summon_item = find_child("SummonItem")
+                               if summon_item == null:
+                                       summon_item = Sprite2D.new()
+                                       summon_item.texture = load("res://gimp/sword.png")
+                                       summon_item.set_name(&"SummonItem")
+                                       gander.add_child(summon_item, true)
+                                       summon_item.set_owner(gander)
+                               else:
+                                       summon_item.texture = load("res://gimp/sword.png")
+                               gander.summon_item = summon_item
+                               state_dict["battle_state"] = BattleState.EnemyAttack
+                       elif summon_node.error_count >= summon_node.MAX_ERRORS:
+                               tween_scene = get_tree().create_tween()
+                               tween_scene.tween_method(func(c): for i in range(8): summon_node.summon_arrows_arr[i].self_modulate = c, Color(1.0, 0.0, 0.0), Color(1.0, 0.0, 0.0, 0.0), 1.0)
+                               tween_scene.tween_callback(func(): camera.remove_child(summon_node))
+                               state_dict["battle_state"] = BattleState.EnemyAttack
+               BattleState.SummonHammer:
+                       var summon_node = find_child("SummonAttempt")
+                       if summon_node.success_count >= summon_node.MAX_SUCCESS:
+                               camera.remove_child(summon_node)
+                               var summon_item = find_child("SummonItem")
+                               if summon_item == null:
+                                       summon_item = Sprite2D.new()
+                                       summon_item.texture = load("res://gimp/hammer.png")
+                                       summon_item.set_name(&"SummonItem")
+                                       gander.add_child(summon_item, true)
+                                       summon_item.set_owner(gander)
+                               else:
+                                       summon_item.texture = load("res://gimp/hammer.png")
+                               gander.summon_item = summon_item
+                               state_dict["battle_state"] = BattleState.EnemyAttack
+                       elif summon_node.error_count >= summon_node.MAX_ERRORS:
+                               tween_scene = get_tree().create_tween()
+                               tween_scene.tween_method(func(c): for i in range(8): summon_node.summon_arrows_arr[i].self_modulate = c, Color(1.0, 0.0, 0.0), Color(1.0, 0.0, 0.0, 0.0), 1.0)
+                               tween_scene.tween_callback(func(): camera.remove_child(summon_node))
+                               state_dict["battle_state"] = BattleState.EnemyAttack
+               BattleState.EnemyAttack:
+                       var battle_arrow = camera.find_child("BattleArrow")
+                       var battle_menu_item_0 = camera.find_child("BattleMenuItem0")
+                       var battle_menu_item_1 = camera.find_child("BattleMenuItem1")
+                       battle_arrow.self_modulate = Color(1, 1, 1, 0)
+                       battle_menu_item_0.text = ""
+                       battle_menu_item_1.text = ""
 
 func handle_battle_input(event: InputEvent):
+       if state_dict["battle_state"] == BattleState.SummonSword or state_dict["battle_state"] == BattleState.SummonHammer:
+               return
        if event.is_pressed():
                if event.is_action("Down"):
                        state_dict["battle_selection"] += 1
@@ -439,9 +533,77 @@ func handle_battle_input(event: InputEvent):
                        if state_dict["battle_selection"] < 0:
                                state_dict["battle_selection"] = state_dict["battle_options"].size() - 1
                        battle_arrow_positioning()
+               elif event.is_action("Confirm"):
+                       handle_battle_action(state_dict["battle_options"][state_dict["battle_selection"]])
+               elif event.is_action("Cancel"):
+                       handle_battle_action("cancel")
+
+func handle_battle_action(action):
+       match action:
+               "attack":
+                       sfx_player.stream = sfx_confirm
+                       sfx_player.play()
+               "summon":
+                       state_dict["battle_state"] = BattleState.SummonMenu
+                       state_dict["battle_menu_setup"] = false
+                       sfx_player.stream = sfx_confirm
+                       sfx_player.play()
+               "summon_sword":
+                       #var summon_item = find_child("SummonItem")
+                       #if summon_item == null:
+                               #summon_item = Sprite2D.new()
+                               #summon_item.texture = load("res://gimp/sword.png")
+                               #summon_item.set_name(&"SummonItem")
+                               #gander.add_child(summon_item, true)
+                               #summon_item.set_owner(gander)
+                       #else:
+                               #summon_item.texture = load("res://gimp/sword.png")
+                       #gander.summon_item = summon_item
+                       #state_dict["battle_state"] = BattleState.EnemyAttack
+                       #state_dict["battle_menu_setup"] = false
+                       state_dict["battle_state"] = BattleState.SummonSword
+                       state_dict["battle_menu_setup"] = false
+                       var summon_scene = load("res://summoning.tscn")
+                       var summon_node = summon_scene.instantiate()
+                       summon_node.set_name(&"SummonAttempt")
+                       camera.add_child(summon_node, true)
+                       summon_node.set_owner(camera)
+                       sfx_player.stream = sfx_confirm
+                       sfx_player.play()
+               "summon_hammer":
+                       #var summon_item = find_child("SummonItem")
+                       #if summon_item == null:
+                               #summon_item = Sprite2D.new()
+                               #summon_item.texture = load("res://gimp/hammer.png")
+                               #summon_item.set_name(&"SummonItem")
+                               #gander.add_child(summon_item, true)
+                               #summon_item.set_owner(gander)
+                       #else:
+                               #summon_item.texture = load("res://gimp/hammer.png")
+                       #gander.summon_item = summon_item
+                       #state_dict["battle_state"] = BattleState.EnemyAttack
+                       #state_dict["battle_menu_setup"] = false
+                       state_dict["battle_state"] = BattleState.SummonHammer
+                       state_dict["battle_menu_setup"] = false
+                       var summon_scene = load("res://summoning.tscn")
+                       var summon_node = summon_scene.instantiate()
+                       summon_node.set_name(&"SummonAttempt")
+                       camera.add_child(summon_node, true)
+                       summon_node.set_owner(camera)
+                       sfx_player.stream = sfx_confirm
+                       sfx_player.play()
+               "cancel":
+                       state_dict["battle_state"] = BattleState.MainMenu
+                       state_dict["battle_menu_setup"] = false
+                       sfx_player.stream = sfx_cancel
+                       sfx_player.play()
+               _:
+                       pass
 
 func battle_arrow_positioning():
        var battle_arrow: Sprite2D = camera.find_child("BattleArrow")
        if battle_arrow != null:
                var arrow_rect = battle_arrow.get_rect()
                battle_arrow.position.y = (viewport_size.y + arrow_rect.size.y) / 2.0 - (arrow_rect.size.y * (state_dict["battle_options"].size() - state_dict["battle_selection"]))
+               sfx_player.stream = sfx_select
+               sfx_player.play()
diff --git a/audio/LD55_sfx_cancel.mp3 b/audio/LD55_sfx_cancel.mp3
new file mode 100644 (file)
index 0000000..ee5ddbe
Binary files /dev/null and b/audio/LD55_sfx_cancel.mp3 differ
diff --git a/audio/LD55_sfx_cancel.mp3.import b/audio/LD55_sfx_cancel.mp3.import
new file mode 100644 (file)
index 0000000..d59ebcc
--- /dev/null
@@ -0,0 +1,19 @@
+[remap]
+
+importer="mp3"
+type="AudioStreamMP3"
+uid="uid://bwu8jqdfa78j"
+path="res://.godot/imported/LD55_sfx_cancel.mp3-cadc5a46716d397037e2593cd887cdee.mp3str"
+
+[deps]
+
+source_file="res://audio/LD55_sfx_cancel.mp3"
+dest_files=["res://.godot/imported/LD55_sfx_cancel.mp3-cadc5a46716d397037e2593cd887cdee.mp3str"]
+
+[params]
+
+loop=false
+loop_offset=0
+bpm=0
+beat_count=0
+bar_beats=4
diff --git a/audio/LD55_sfx_confirm.mp3 b/audio/LD55_sfx_confirm.mp3
new file mode 100644 (file)
index 0000000..3f95d49
Binary files /dev/null and b/audio/LD55_sfx_confirm.mp3 differ
diff --git a/audio/LD55_sfx_confirm.mp3.import b/audio/LD55_sfx_confirm.mp3.import
new file mode 100644 (file)
index 0000000..2dc4b51
--- /dev/null
@@ -0,0 +1,19 @@
+[remap]
+
+importer="mp3"
+type="AudioStreamMP3"
+uid="uid://d0ekb3bk74p26"
+path="res://.godot/imported/LD55_sfx_confirm.mp3-f5943f8e9f465983820ed67c99df309e.mp3str"
+
+[deps]
+
+source_file="res://audio/LD55_sfx_confirm.mp3"
+dest_files=["res://.godot/imported/LD55_sfx_confirm.mp3-f5943f8e9f465983820ed67c99df309e.mp3str"]
+
+[params]
+
+loop=false
+loop_offset=0
+bpm=0
+beat_count=0
+bar_beats=4
diff --git a/audio/LD55_sfx_hammer_hit.mp3 b/audio/LD55_sfx_hammer_hit.mp3
new file mode 100644 (file)
index 0000000..d86a79f
Binary files /dev/null and b/audio/LD55_sfx_hammer_hit.mp3 differ
diff --git a/audio/LD55_sfx_hammer_hit.mp3.import b/audio/LD55_sfx_hammer_hit.mp3.import
new file mode 100644 (file)
index 0000000..6f54a42
--- /dev/null
@@ -0,0 +1,19 @@
+[remap]
+
+importer="mp3"
+type="AudioStreamMP3"
+uid="uid://clxh0pmhvavne"
+path="res://.godot/imported/LD55_sfx_hammer_hit.mp3-3164a70ab500317d475c03a94852df6f.mp3str"
+
+[deps]
+
+source_file="res://audio/LD55_sfx_hammer_hit.mp3"
+dest_files=["res://.godot/imported/LD55_sfx_hammer_hit.mp3-3164a70ab500317d475c03a94852df6f.mp3str"]
+
+[params]
+
+loop=false
+loop_offset=0
+bpm=0
+beat_count=0
+bar_beats=4
diff --git a/audio/LD55_sfx_select.mp3 b/audio/LD55_sfx_select.mp3
new file mode 100644 (file)
index 0000000..15917e1
Binary files /dev/null and b/audio/LD55_sfx_select.mp3 differ
diff --git a/audio/LD55_sfx_select.mp3.import b/audio/LD55_sfx_select.mp3.import
new file mode 100644 (file)
index 0000000..696d771
--- /dev/null
@@ -0,0 +1,19 @@
+[remap]
+
+importer="mp3"
+type="AudioStreamMP3"
+uid="uid://d1q1gfvi1i8po"
+path="res://.godot/imported/LD55_sfx_select.mp3-fd7a087b2218aec4761b872fc6130921.mp3str"
+
+[deps]
+
+source_file="res://audio/LD55_sfx_select.mp3"
+dest_files=["res://.godot/imported/LD55_sfx_select.mp3-fd7a087b2218aec4761b872fc6130921.mp3str"]
+
+[params]
+
+loop=false
+loop_offset=0
+bpm=0
+beat_count=0
+bar_beats=4
diff --git a/audio/LD55_sfx_sword_hit.mp3 b/audio/LD55_sfx_sword_hit.mp3
new file mode 100644 (file)
index 0000000..d34925b
Binary files /dev/null and b/audio/LD55_sfx_sword_hit.mp3 differ
diff --git a/audio/LD55_sfx_sword_hit.mp3.import b/audio/LD55_sfx_sword_hit.mp3.import
new file mode 100644 (file)
index 0000000..21d4051
--- /dev/null
@@ -0,0 +1,19 @@
+[remap]
+
+importer="mp3"
+type="AudioStreamMP3"
+uid="uid://c2tvj7l0latop"
+path="res://.godot/imported/LD55_sfx_sword_hit.mp3-d10764d82f6cd1f6e91970f219d44ea5.mp3str"
+
+[deps]
+
+source_file="res://audio/LD55_sfx_sword_hit.mp3"
+dest_files=["res://.godot/imported/LD55_sfx_sword_hit.mp3-d10764d82f6cd1f6e91970f219d44ea5.mp3str"]
+
+[params]
+
+loop=false
+loop_offset=0
+bpm=0
+beat_count=0
+bar_beats=4
index 9e557fdcb2da4c8e725fabed4f367da1b2df6eba..55a22c1bdfb4734f876c56eb4930957bfaa967f1 100644 (file)
@@ -15,8 +15,19 @@ var last_collided_id = null
 
 @onready var animated = $AnimatedSprite2D
 
+var summon_item = null
+var summon_item_angle = 0.0
+
 const SPEED = 150.0
 const ANIM_DEADZONE = 0.3
+const SUMMON_ITEM_DIST = 100.0
+const SUMMON_ITEM_Y_OFFSET = -30.0
+
+func _process(delta):
+       summon_item_angle += delta
+       if summon_item != null:
+               summon_item.position.x = cos(summon_item_angle) * SUMMON_ITEM_DIST
+               summon_item.position.y = sin(summon_item_angle) * SUMMON_ITEM_DIST + SUMMON_ITEM_Y_OFFSET
 
 func _physics_process(delta):
        var vec2 = Vector2()
diff --git a/gimp/summon_arrow.png b/gimp/summon_arrow.png
new file mode 100644 (file)
index 0000000..b13be2d
Binary files /dev/null and b/gimp/summon_arrow.png differ
diff --git a/gimp/summon_arrow.png.import b/gimp/summon_arrow.png.import
new file mode 100644 (file)
index 0000000..922d7bb
--- /dev/null
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dvyxj067n812g"
+path="res://.godot/imported/summon_arrow.png-8be3d4d199ac77e639f7001be6b20b00.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://gimp/summon_arrow.png"
+dest_files=["res://.godot/imported/summon_arrow.png-8be3d4d199ac77e639f7001be6b20b00.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
index 5408bf4e5caa58c0c9993b03dfb79dcd0656d5bc..a7f00f41a9166dc02512e1f25d71f680d60eef33 100644 (file)
@@ -1,4 +1,4 @@
-[gd_scene load_steps=8 format=3 uid="uid://ch52ervf073wd"]
+[gd_scene load_steps=7 format=3 uid="uid://ch52ervf073wd"]
 
 [ext_resource type="Script" path="res://MainLogic.gd" id="1_43no1"]
 [ext_resource type="Texture2D" uid="uid://varqu7luxowf" path="res://gimp/earth_diamond.png" id="2_hlcsm"]
@@ -6,7 +6,6 @@
 [ext_resource type="Texture2D" uid="uid://djwgnisoid4co" path="res://gimp/water_diamond.png" id="4_u6w6s"]
 [ext_resource type="Texture2D" uid="uid://d2mxjcl50laoa" path="res://gimp/wind_diamond.png" id="5_3irym"]
 [ext_resource type="AudioStream" uid="uid://2epey2fmmtb2" path="res://audio/LD55_0.mp3" id="6_3kpot"]
-[ext_resource type="Texture2D" uid="uid://bemf77dxebgw1" path="res://gimp/sword.png" id="7_v3xw4"]
 
 [node name="Node2D" type="Node2D"]
 script = ExtResource("1_43no1")
@@ -46,6 +45,4 @@ texture = ExtResource("5_3irym")
 [node name="MusicPlayer" type="AudioStreamPlayer" parent="."]
 stream = ExtResource("6_3kpot")
 
-[node name="Sword" type="Sprite2D" parent="."]
-position = Vector2(-669, 382)
-texture = ExtResource("7_v3xw4")
+[node name="SFXPlayer" type="AudioStreamPlayer" parent="."]
diff --git a/summoning.gd b/summoning.gd
new file mode 100644 (file)
index 0000000..8f43e2b
--- /dev/null
@@ -0,0 +1,123 @@
+extends Node2D
+
+enum Direction {
+       LEFT,
+       RIGHT,
+       UP,
+       DOWN,
+}
+
+@onready var ar_one = $SummonArrow
+@onready var ar_two = $SummonArrow2
+@onready var ar_three = $SummonArrow3
+@onready var ar_four = $SummonArrow4
+@onready var ar_five = $SummonArrow5
+@onready var ar_six = $SummonArrow6
+@onready var ar_seven = $SummonArrow7
+@onready var ar_eight = $SummonArrow8
+
+@onready var timer_box = $TimerBox
+const TIMER_BOX_WIDTH = 380.0
+
+var summon_arrows_arr = []
+
+var arrow_directions = []
+
+const MAX_ERRORS = 3
+const MAX_SUCCESS = 8
+var error_count = 0
+var success_count = 0
+
+const TIMER_AMOUNT = 5.0
+var timer = 0.0
+
+func int_to_dir(i):
+       match i:
+               0:
+                       return Direction.LEFT
+               1:
+                       return Direction.RIGHT
+               2:
+                       return Direction.UP
+               3:
+                       return Direction.DOWN
+               _:
+                       return Direction.DOWN
+
+func dir_to_angle(d: Direction):
+       match d:
+               Direction.LEFT:
+                       return 0.0
+               Direction.RIGHT:
+                       return PI
+               Direction.UP:
+                       return PI / 2.0
+               Direction.DOWN:
+                       return PI * 3.0 / 2.0
+
+func _ready():
+       summon_arrows_arr.append(ar_one)
+       summon_arrows_arr.append(ar_two)
+       summon_arrows_arr.append(ar_three)
+       summon_arrows_arr.append(ar_four)
+       summon_arrows_arr.append(ar_five)
+       summon_arrows_arr.append(ar_six)
+       summon_arrows_arr.append(ar_seven)
+       summon_arrows_arr.append(ar_eight)
+       var rng = RandomNumberGenerator.new()
+       for i in range(8):
+               arrow_directions.append(int_to_dir(rng.randi_range(0, 3)))
+               summon_arrows_arr[i].rotation = dir_to_angle(arrow_directions[i])
+
+
+# Called every frame. 'delta' is the elapsed time since the previous frame.
+func _process(delta):
+       timer += delta
+       if timer >= TIMER_AMOUNT:
+               timer = 0.0
+               if success_count < MAX_SUCCESS and error_count < MAX_ERRORS:
+                       on_summon_error()
+       if success_count < MAX_SUCCESS and error_count < MAX_ERRORS:
+               var interp_amount = (TIMER_AMOUNT - timer) / TIMER_AMOUNT
+               timer_box.scale.x = interp_amount * TIMER_BOX_WIDTH
+               timer_box.self_modulate = Color((1.0 - interp_amount), interp_amount, 0.0)
+
+func _unhandled_input(event):
+       if error_count >= MAX_ERRORS or success_count >= MAX_SUCCESS:
+               return
+       if event.is_pressed():
+               if event.is_action("Left"):
+                       if arrow_directions[success_count] == Direction.LEFT:
+                               on_summon_success(success_count)
+                       else:
+                               on_summon_error()
+               elif event.is_action("Right"):
+                       if arrow_directions[success_count] == Direction.RIGHT:
+                               on_summon_success(success_count)
+                       else:
+                               on_summon_error()
+               elif event.is_action("Up"):
+                       if arrow_directions[success_count] == Direction.UP:
+                               on_summon_success(success_count)
+                       else:
+                               on_summon_error()
+               elif event.is_action("Down"):
+                       if arrow_directions[success_count] == Direction.DOWN:
+                               on_summon_success(success_count)
+                       else:
+                               on_summon_error()
+                               
+func on_summon_success(idx):
+       summon_arrows_arr[idx].self_modulate = Color(0.0, 1.0, 0.0)
+       success_count += 1
+
+func on_summon_error():
+       timer = 0.0
+       success_count = 0
+       error_count += 1
+       if error_count >= MAX_ERRORS:
+               for i in range(8):
+                       summon_arrows_arr[i].self_modulate = Color(1.0, 0.0, 0.0)
+       else:
+               for i in range(8):
+                       summon_arrows_arr[i].self_modulate = Color(1.0, 1.0, 1.0)
diff --git a/summoning.tscn b/summoning.tscn
new file mode 100644 (file)
index 0000000..b99bb48
--- /dev/null
@@ -0,0 +1,54 @@
+[gd_scene load_steps=4 format=3 uid="uid://b7tummdg08cfc"]
+
+[ext_resource type="Script" path="res://summoning.gd" id="1_qh1sn"]
+[ext_resource type="Texture2D" uid="uid://dvyxj067n812g" path="res://gimp/summon_arrow.png" id="2_io4qw"]
+
+[sub_resource type="CanvasTexture" id="CanvasTexture_oraey"]
+
+[node name="Node2D" type="Node2D"]
+script = ExtResource("1_qh1sn")
+
+[node name="SummonArrow" type="Sprite2D" parent="."]
+position = Vector2(-136, -56)
+texture = ExtResource("2_io4qw")
+
+[node name="SummonArrow2" type="Sprite2D" parent="."]
+position = Vector2(-46, -56)
+texture = ExtResource("2_io4qw")
+
+[node name="SummonArrow3" type="Sprite2D" parent="."]
+position = Vector2(47, -55)
+texture = ExtResource("2_io4qw")
+
+[node name="SummonArrow4" type="Sprite2D" parent="."]
+position = Vector2(143, -56)
+texture = ExtResource("2_io4qw")
+
+[node name="SummonArrow5" type="Sprite2D" parent="."]
+position = Vector2(-144, 57)
+texture = ExtResource("2_io4qw")
+
+[node name="SummonArrow6" type="Sprite2D" parent="."]
+position = Vector2(-49, 56)
+texture = ExtResource("2_io4qw")
+
+[node name="SummonArrow7" type="Sprite2D" parent="."]
+position = Vector2(47, 57)
+texture = ExtResource("2_io4qw")
+
+[node name="SummonArrow8" type="Sprite2D" parent="."]
+position = Vector2(136, 58)
+texture = ExtResource("2_io4qw")
+
+[node name="Label" type="Label" parent="."]
+offset_left = -187.0
+offset_top = -140.0
+offset_right = 188.0
+offset_bottom = -100.0
+theme_override_font_sizes/font_size = 24
+text = "Press the directions to summon!"
+
+[node name="TimerBox" type="Sprite2D" parent="."]
+position = Vector2(0, 135)
+scale = Vector2(380, 50)
+texture = SubResource("CanvasTexture_oraey")