-rw-r--r--.gitattributes2
-rw-r--r--.gitignore8
-rw-r--r--InputHandler.tscn11
-rw-r--r--LICENSE21
-rw-r--r--README.md2
-rw-r--r--World.gd54
-rw-r--r--World.tscn27
-rw-r--r--default_env.tres7
-rw-r--r--dot.pngbin0 -> 198 bytes
-rw-r--r--dot.png.import35
-rw-r--r--dots/YellowDot.gd1
-rw-r--r--dots/dot.gd50
-rw-r--r--dots/dot_extras/dotcollider.gd7
-rw-r--r--dots/dot_extras/dotcollider.tscn15
-rw-r--r--dots/dot_extras/dotray.tscn7
-rw-r--r--dots/dot_extras/dotsprite.gd4
-rw-r--r--dots/dot_extras/dotsprite.tscn14
-rw-r--r--dots/dot_template.tscn14
-rw-r--r--dots/reddot.gd5
-rw-r--r--dots/reddot.tscn6
-rw-r--r--dots/yellowdot.tscn6
-rw-r--r--entity_tracker.gd7
-rw-r--r--events.gd7
-rw-r--r--global_vars.gd12
-rw-r--r--icon.pngbin0 -> 3305 bytes
-rw-r--r--icon.png.import35
-rw-r--r--input_handler.gd44
-rw-r--r--project.godot90
-rw-r--r--utils.gd8
29 files changed, 499 insertions, 0 deletions
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..dfe0770
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+# Auto detect text files and perform LF normalization
+* text=auto
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ba45ca4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+
+# Godot-specific ignores
+.import/
+export.cfg
+export_presets.cfg
+
+# Mono-specific ignores
+.mono/
diff --git a/InputHandler.tscn b/InputHandler.tscn
new file mode 100644
index 0000000..2b48ba8
--- /dev/null
+++ b/InputHandler.tscn
@@ -0,0 +1,11 @@
+[gd_scene load_steps=2 format=2]
+
+[ext_resource path="res://input_handler.gd" type="Script" id=1]
+
+[node name="InputHandler" type="CanvasLayer"]
+script = ExtResource( 1 )
+
+[node name="Line2D" type="Line2D" parent="."]
+default_color = Color( 0, 0, 0, 0 )
+end_cap_mode = 2
+antialiased = true
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..9a9763e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2022 bendn
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..bda9ca6
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# two_dots
+
diff --git a/World.gd b/World.gd
new file mode 100644
index 0000000..1f1ce1f
--- /dev/null
+++ b/World.gd
@@ -0,0 +1,54 @@
+extends Node2D
+
+const dots_path = "res://dots/"
+
+onready var dots_holder = $Dots
+
+var counted_done = 0
+
+var h = GlobalVars.height
+var w = GlobalVars.width
+
+var dots = {
+ "yellowdot" : load(dots_path + "yellowdot.tscn"),
+ "reddot" : load(dots_path + "reddot.tscn")
+}
+
+func _ready():
+ spawn_dots(dots)
+ Events.connect("done_moving", self, "_on_dot_done_moving")
+ Events.connect("dots_done_moving", self, "_dots_done_moving")
+
+func spawn_dots(library : Dictionary):
+ var lib_size = library.keys().size()
+ var lib_keys = library.keys()
+ for wi in w:
+ for hi in h:
+ var current_row_item
+ if GlobalVars.turns_used != 0: # if its the first turn, the arrays will be empty, and i dont want to pad them with " "
+ current_row_item = EntityTracker.rows[hi][wi]
+ if current_row_item != 0:
+ continue
+ var new_dot = choose_random_dot(lib_size, lib_keys, library)
+ EntityTracker.rows[hi].append(new_dot)
+ dots_holder.add_child(new_dot)
+ var offset = Vector2(GlobalVars.size.x * wi, GlobalVars.size.y * hi)
+ var new_pos = ($Corners/Position2D.global_position + offset).snapped(GlobalVars.size)
+ new_dot.global_position = new_pos
+ Events.emit_signal("level_initialized")
+
+func choose_random_dot(lib_size, lib_keys, library) -> Array:
+ randomize()
+ var rand_number = randi() % lib_size
+ var lib_key = lib_keys[rand_number]
+ var new_dot = library[lib_key].instance()
+ return new_dot
+
+func _on_dot_done_moving():
+ counted_done += 1
+ if counted_done >= (w * h):
+ Events.emit_signal("dots_done_moving")
+ GlobalVars.state = GlobalVars.states.player_turn
+
+func _dots_done_moving():
+ pass
diff --git a/World.tscn b/World.tscn
new file mode 100644
index 0000000..d68cf7a
--- /dev/null
+++ b/World.tscn
@@ -0,0 +1,27 @@
+[gd_scene load_steps=3 format=2]
+
+[ext_resource path="res://World.gd" type="Script" id=1]
+
+[sub_resource type="RectangleShape2D" id=1]
+extents = Vector2( 350, 35 )
+
+[node name="World" type="Node2D"]
+script = ExtResource( 1 )
+
+[node name="Corners" type="Node2D" parent="."]
+
+[node name="Position2D" type="Position2D" parent="Corners"]
+position = Vector2( 70, 140 )
+
+[node name="Position2D3" type="Position2D" parent="Corners"]
+position = Vector2( 630, 770 )
+
+[node name="Dots" type="Node2D" parent="."]
+
+[node name="Bottom" type="StaticBody2D" parent="."]
+collision_layer = 2
+collision_mask = 0
+
+[node name="CollisionShape2D" type="CollisionShape2D" parent="Bottom"]
+position = Vector2( 350, 805 )
+shape = SubResource( 1 )
diff --git a/default_env.tres b/default_env.tres
new file mode 100644
index 0000000..20207a4
--- /dev/null
+++ b/default_env.tres
@@ -0,0 +1,7 @@
+[gd_resource type="Environment" load_steps=2 format=2]
+
+[sub_resource type="ProceduralSky" id=1]
+
+[resource]
+background_mode = 2
+background_sky = SubResource( 1 )
diff --git a/dot.png b/dot.png
new file mode 100644
index 0000000..2304c20
--- /dev/null
+++ b/dot.png
Binary files differ
diff --git a/dot.png.import b/dot.png.import
new file mode 100644
index 0000000..4b147f0
--- /dev/null
+++ b/dot.png.import
@@ -0,0 +1,35 @@
+[remap]
+
+importer="texture"
+type="StreamTexture"
+path="res://.import/dot.png-c009b1c4c85719f89f80768b0ad78763.stex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://dot.png"
+dest_files=[ "res://.import/dot.png-c009b1c4c85719f89f80768b0ad78763.stex" ]
+
+[params]
+
+compress/mode=0
+compress/lossy_quality=0.7
+compress/hdr_mode=0
+compress/bptc_ldr=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
+process/invert_color=false
+process/normal_map_invert_y=false
+stream=false
+size_limit=0
+detect_3d=false
+svg/scale=1.0
diff --git a/dots/YellowDot.gd b/dots/YellowDot.gd
new file mode 100644
index 0000000..a5b88f0
--- /dev/null
+++ b/dots/YellowDot.gd
@@ -0,0 +1 @@
+extends dot
diff --git a/dots/dot.gd b/dots/dot.gd
new file mode 100644
index 0000000..d7b915e
--- /dev/null
+++ b/dots/dot.gd
@@ -0,0 +1,50 @@
+extends KinematicBody2D
+class_name dot
+
+var dotCollider = preload("res://dots/dot_extras/dotcollider.tscn" )
+
+onready var dotcollider : CollisionShape2D
+onready var ray : RayCast2D
+
+var tween = Tween.new()
+
+export(Color) var color
+export(GlobalVars.type) var dot_type
+
+func _ready():
+ Events.connect("level_initialized", self, "move")
+ Events.connect("turn_over", self, "move")
+ add_child(tween)
+ var new_dotcollider = dotCollider.instance()
+ add_child(new_dotcollider)
+ dotcollider = new_dotcollider
+ ray = dotcollider.get_ray()
+ dotcollider.move_ray($dotsprite/pos.global_position)
+ $dotsprite.change_color(color)
+
+func move():
+ if ! GlobalVars.state == GlobalVars.states.level_turn:
+ return
+ var go_to = extend_ray_until_collides()
+ tween.interpolate_property(self, "global_position",
+ global_position, go_to, 2,
+ Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
+ tween.start()
+ Events.emit_signal("done_moving")
+
+func extend_ray_until_collides() -> Vector2:
+ for i in get_viewport_rect().size.y:
+ if not ray.is_colliding():
+ ray.cast_to.y += 1
+ ray.force_raycast_update()
+ var size = ray.cast_to.y
+ print(ray.get_collider())
+ ray.cast_to = Vector2.ZERO
+ return Vector2(global_position.x, global_position.y + size)
+
+func turn_off_collision():
+ dotcollider.disabled = true
+
+func _on_dot_input(viewport, event : InputEvent, shape_idx):
+ InputHandler._pressed(event, self)
+
diff --git a/dots/dot_extras/dotcollider.gd b/dots/dot_extras/dotcollider.gd
new file mode 100644
index 0000000..bd3c227
--- /dev/null
+++ b/dots/dot_extras/dotcollider.gd
@@ -0,0 +1,7 @@
+extends CollisionShape2D
+
+func move_ray(position):
+ $dotray.global_position = position
+
+func get_ray():
+ return $dotray
diff --git a/dots/dot_extras/dotcollider.tscn b/dots/dot_extras/dotcollider.tscn
new file mode 100644
index 0000000..0ef1a53
--- /dev/null
+++ b/dots/dot_extras/dotcollider.tscn
@@ -0,0 +1,15 @@
+[gd_scene load_steps=4 format=2]
+
+[ext_resource path="res://dots/dot_extras/dotray.tscn" type="PackedScene" id=1]
+[ext_resource path="res://dots/dot_extras/dotcollider.gd" type="Script" id=2]
+
+[sub_resource type="RectangleShape2D" id=1]
+extents = Vector2( 30, 30 )
+
+[node name="dotcollider" type="CollisionShape2D"]
+position = Vector2( 30, 30 )
+shape = SubResource( 1 )
+script = ExtResource( 2 )
+
+[node name="dotray" parent="." instance=ExtResource( 1 )]
+position = Vector2( 0, 32 )
diff --git a/dots/dot_extras/dotray.tscn b/dots/dot_extras/dotray.tscn
new file mode 100644
index 0000000..9a95b1d
--- /dev/null
+++ b/dots/dot_extras/dotray.tscn
@@ -0,0 +1,7 @@
+[gd_scene format=2]
+
+[node name="dotray" type="RayCast2D"]
+position = Vector2( 30, 60 )
+enabled = true
+cast_to = Vector2( 0, 0 )
+collision_mask = 2
diff --git a/dots/dot_extras/dotsprite.gd b/dots/dot_extras/dotsprite.gd
new file mode 100644
index 0000000..d77e17e
--- /dev/null
+++ b/dots/dot_extras/dotsprite.gd
@@ -0,0 +1,4 @@
+extends Sprite
+
+func change_color(color : Color):
+ self_modulate = color
diff --git a/dots/dot_extras/dotsprite.tscn b/dots/dot_extras/dotsprite.tscn
new file mode 100644
index 0000000..c3cfebb
--- /dev/null
+++ b/dots/dot_extras/dotsprite.tscn
@@ -0,0 +1,14 @@
+[gd_scene load_steps=3 format=2]
+
+[ext_resource path="res://dot.png" type="Texture" id=1]
+[ext_resource path="res://dots/dot_extras/dotsprite.gd" type="Script" id=2]
+
+[node name="dotsprite" type="Sprite"]
+texture = ExtResource( 1 )
+centered = false
+script = ExtResource( 2 )
+
+[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
+
+[node name="pos" type="Position2D" parent="."]
+position = Vector2( 30, 59 )
diff --git a/dots/dot_template.tscn b/dots/dot_template.tscn
new file mode 100644
index 0000000..5902e02
--- /dev/null
+++ b/dots/dot_template.tscn
@@ -0,0 +1,14 @@
+[gd_scene load_steps=3 format=2]
+
+[ext_resource path="res://dots/dot.gd" type="Script" id=1]
+[ext_resource path="res://dots/dot_extras/dotsprite.tscn" type="PackedScene" id=2]
+
+[node name="dot_template" type="KinematicBody2D"]
+collision_layer = 2
+collision_mask = 0
+input_pickable = true
+script = ExtResource( 1 )
+
+[node name="dotsprite" parent="." instance=ExtResource( 2 )]
+
+[connection signal="input_event" from="." to="." method="_on_dot_input"]
diff --git a/dots/reddot.gd b/dots/reddot.gd
new file mode 100644
index 0000000..05c5a2c
--- /dev/null
+++ b/dots/reddot.gd
@@ -0,0 +1,5 @@
+extends "res://dots/dot.gd"
+
+
+func _ready():
+ pass
diff --git a/dots/reddot.tscn b/dots/reddot.tscn
new file mode 100644
index 0000000..46826f3
--- /dev/null
+++ b/dots/reddot.tscn
@@ -0,0 +1,6 @@
+[gd_scene load_steps=2 format=2]
+
+[ext_resource path="res://dots/dot_template.tscn" type="PackedScene" id=1]
+
+[node name="reddot" instance=ExtResource( 1 )]
+color = Color( 1, 0.407843, 0.407843, 1 )
diff --git a/dots/yellowdot.tscn b/dots/yellowdot.tscn
new file mode 100644
index 0000000..9f7549a
--- /dev/null
+++ b/dots/yellowdot.tscn
@@ -0,0 +1,6 @@
+[gd_scene load_steps=2 format=2]
+
+[ext_resource path="res://dots/dot_template.tscn" type="PackedScene" id=1]
+
+[node name="yellowdot" instance=ExtResource( 1 )]
+color = Color( 1, 0.831373, 0.25098, 1 )
diff --git a/entity_tracker.gd b/entity_tracker.gd
new file mode 100644
index 0000000..717c764
--- /dev/null
+++ b/entity_tracker.gd
@@ -0,0 +1,7 @@
+extends Node
+
+var rows = []
+
+func _ready():
+ for w in GlobalVars.width:
+ rows.append([])
diff --git a/events.gd b/events.gd
new file mode 100644
index 0000000..ca85260
--- /dev/null
+++ b/events.gd
@@ -0,0 +1,7 @@
+extends Node
+
+# warning-ignore-all:unused_signal
+signal level_initialized
+signal turn_over
+signal done_moving
+signal dots_done_moving
diff --git a/global_vars.gd b/global_vars.gd
new file mode 100644
index 0000000..5847804
--- /dev/null
+++ b/global_vars.gd
@@ -0,0 +1,12 @@
+extends Node
+
+const size = Vector2(70, 70)
+enum type {normal, unnormal}
+enum states {player_turn, level_turn}
+
+var turns_used = 0
+var state = states.level_turn
+
+
+const height = 8
+const width = 8
diff --git a/icon.png b/icon.png
new file mode 100644
index 0000000..c98fbb6
--- /dev/null
+++ b/icon.png
Binary files differ
diff --git a/icon.png.import b/icon.png.import
new file mode 100644
index 0000000..a4c02e6
--- /dev/null
+++ b/icon.png.import
@@ -0,0 +1,35 @@
+[remap]
+
+importer="texture"
+type="StreamTexture"
+path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://icon.png"
+dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ]
+
+[params]
+
+compress/mode=0
+compress/lossy_quality=0.7
+compress/hdr_mode=0
+compress/bptc_ldr=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
+process/invert_color=false
+process/normal_map_invert_y=false
+stream=false
+size_limit=0
+detect_3d=true
+svg/scale=1.0
diff --git a/input_handler.gd b/input_handler.gd
new file mode 100644
index 0000000..b0f64c2
--- /dev/null
+++ b/input_handler.gd
@@ -0,0 +1,44 @@
+extends CanvasLayer
+
+var pressed = false setget set_pressed
+
+var nodes_with_points = []
+
+onready var line = $Line2D
+
+func _pressed(event : InputEvent, node : dot):
+ if not GlobalVars.state == GlobalVars.states.player_turn:
+ return
+ if line.get_point_count() > 0:
+ if node.color == line.default_color:
+ if not node in nodes_with_points:
+# line.remove_point(line.get_point_count() - 1) # remove the last points
+ set_physics_process(false)
+ yield(get_tree(), "idle_frame")
+ line.add_point(node.position + GlobalVars.size / 2)
+ nodes_with_points.append(node)
+ set_physics_process(true)
+ elif event.is_action("click") and event.is_pressed():
+ pressed = true
+ line.clear_points()
+ nodes_with_points.clear()
+ nodes_with_points.append(node)
+ line.add_point(node.position + GlobalVars.size / 2) # add a point in the center of the dot
+ line.add_point(line.get_global_mouse_position())
+ line.default_color = node.color
+
+func _physics_process(delta):
+ if line.get_point_count() > 0:
+ if Input.is_action_pressed("click") and pressed == true:
+ line.remove_point(line.get_point_count() - 1)
+ line.add_point(line.get_global_mouse_position())
+ elif line.get_point_count() > 2:
+ line.clear_points()
+ else:
+ line.clear_points()
+ nodes_with_points.clear()
+ pressed = false
+
+func set_pressed(new_pressed):
+ pressed = new_pressed
+ set_physics_process(pressed)
diff --git a/project.godot b/project.godot
new file mode 100644
index 0000000..3bfe32f
--- /dev/null
+++ b/project.godot
@@ -0,0 +1,90 @@
+; Engine configuration file.
+; It's best edited using the editor UI and not directly,
+; since the parameters that go here are not all obvious.
+;
+; Format:
+; [section] ; section goes between []
+; param=value ; assign values to parameters
+
+config_version=4
+
+_global_script_classes=[ {
+"base": "KinematicBody2D",
+"class": "dot",
+"language": "GDScript",
+"path": "res://dots/dot.gd"
+} ]
+_global_script_class_icons={
+"dot": ""
+}
+
+[application]
+
+config/name="two_dots"
+run/main_scene="res://World.tscn"
+config/icon="res://icon.png"
+
+[autoload]
+
+GlobalVars="*res://global_vars.gd"
+Utils="*res://utils.gd"
+Events="*res://events.gd"
+EntityTracker="*res://entity_tracker.gd"
+InputHandler="*res://InputHandler.tscn"
+
+[debug]
+
+gdscript/warnings/return_value_discarded=false
+
+[display]
+
+window/size/width=700
+window/size/height=910
+window/stretch/mode="2d"
+
+[importer_defaults]
+
+texture={
+"compress/bptc_ldr": 0,
+"compress/hdr_mode": 0,
+"compress/lossy_quality": 0.7,
+"compress/mode": 0,
+"compress/normal_map": 0,
+"detect_3d": false,
+"flags/anisotropic": false,
+"flags/filter": true,
+"flags/mipmaps": false,
+"flags/repeat": 0,
+"flags/srgb": 2,
+"process/HDR_as_SRGB": false,
+"process/fix_alpha_border": true,
+"process/invert_color": false,
+"process/normal_map_invert_y": false,
+"process/premult_alpha": false,
+"size_limit": 0,
+"stream": false,
+"svg/scale": 1.0
+}
+
+[input]
+
+click={
+"deadzone": 0.5,
+"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":1,"pressed":false,"doubleclick":false,"script":null)
+ ]
+}
+
+[layer_names]
+
+2d_physics/layer_2="dots"
+
+[physics]
+
+common/enable_pause_aware_picking=true
+
+[rendering]
+
+quality/driver/driver_name="GLES2"
+vram_compression/import_etc=true
+vram_compression/import_etc2=false
+environment/default_environment="res://default_env.tres"
diff --git a/utils.gd b/utils.gd
new file mode 100644
index 0000000..9140d1a
--- /dev/null
+++ b/utils.gd
@@ -0,0 +1,8 @@
+extends Node
+
+func instance_scene_on_main(scene, position):
+ var main = get_tree().current_scene
+ var instance = scene.instance()
+ main.add_child(instance)
+ instance.global_position = position
+ return instance