commit 51fb7f81d3065a6b1dcb9ad5ed8c0e8e8a226b2d
Author: Daniel Lehmann <3004405@stud.hs-mannheim.de>
Date: Wed Mar 27 18:02:45 2024 +0100
v.0 TicTacToe vorlage
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..8ad74f7
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+# Normalize EOL for all files that Git considers text files.
+* text=auto eol=lf
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4709183
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+# Godot 4+ specific ignores
+.godot/
diff --git a/assets/sprites.png b/assets/sprites.png
new file mode 100644
index 0000000..ebbfc16
Binary files /dev/null and b/assets/sprites.png differ
diff --git a/assets/sprites.png.import b/assets/sprites.png.import
new file mode 100644
index 0000000..73a5193
--- /dev/null
+++ b/assets/sprites.png.import
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://do2vfb2cj7fk"
+path="res://.godot/imported/sprites.png-bb36f92a96c2b9ad48a8528dbf01963e.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/sprites.png"
+dest_files=["res://.godot/imported/sprites.png-bb36f92a96c2b9ad48a8528dbf01963e.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
diff --git a/assets/sprites.svg b/assets/sprites.svg
new file mode 100644
index 0000000..048f98c
--- /dev/null
+++ b/assets/sprites.svg
@@ -0,0 +1,451 @@
+
+
+
+
diff --git a/assets/sprites.svg.import b/assets/sprites.svg.import
new file mode 100644
index 0000000..4f334bc
--- /dev/null
+++ b/assets/sprites.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://ddkkkb6k0j8pl"
+path="res://.godot/imported/sprites.svg-3de0a23bb576a309499d2855bd837d3b.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/sprites.svg"
+dest_files=["res://.godot/imported/sprites.svg-3de0a23bb576a309499d2855bd837d3b.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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/board/board.gd b/board/board.gd
new file mode 100644
index 0000000..267fa49
--- /dev/null
+++ b/board/board.gd
@@ -0,0 +1,65 @@
+extends TileMap
+
+class_name Board
+
+var tile_by_name := {}
+var layer_by_name := {}
+
+@export var state_layer: String = "States"
+@export var board_layer: String = "Board"
+@export var state_name: String = "Name"
+@export var empty_state: String = "Empty"
+var off_limits: String = ""
+@export var active: bool = true
+
+
+func _ready():
+ print("Initializing board...")
+ _index_atlas_coordinates_by_name()
+ _index_layers_by_name()
+ $Highlight.size = tile_set.tile_size
+ print("Tiles: ", ", ".join(tile_by_name.keys()))
+
+
+func get_state(grid_pos: Vector2) -> String:
+ var state_tile_data: TileData = self.get_cell_tile_data(layer_by_name[state_layer], grid_pos)
+ var board_tile_data: TileData = self.get_cell_tile_data(layer_by_name[board_layer], grid_pos)
+ if not board_tile_data:
+ return off_limits
+ if not state_tile_data or not state_tile_data.get_custom_data(state_name):
+ return empty_state
+ return state_tile_data.get_custom_data(state_name)
+
+func set_state(grid_pos: Vector2, state: String) -> bool:
+ if get_state(grid_pos) != empty_state:
+ return false
+ self.set_cell(layer_by_name[state_layer], grid_pos, tile_by_name[state]["source_id"], tile_by_name[state]["atlas_coords"])
+ return true
+
+func global_to_map(global_pos: Vector2) -> Vector2:
+ return self.local_to_map(self.to_local(global_pos))
+
+func gridpos_at_mouse() -> Vector2:
+ return global_to_map(get_viewport().get_mouse_position())
+
+func reset() -> void:
+ for cell in get_used_cells(layer_by_name[state_layer]):
+ set_cell(layer_by_name[state_layer], cell, -1)
+
+func _index_atlas_coordinates_by_name():
+ var tileset = self.tile_set
+ for source_index in range(tileset.get_source_count()):
+ var source_id = tileset.get_source_id(source_index)
+ var atlas:TileSetAtlasSource = tileset.get_source(source_id)
+ for tile_index in range(atlas.get_tiles_count()):
+ var atlas_coords = atlas.get_tile_id(tile_index)
+ var tile_data : TileData = atlas.get_tile_data(atlas_coords, 0)
+ if tile_data and tile_data.get_custom_data(state_name):
+ tile_by_name[tile_data.get_custom_data(state_name)] = {
+ "source_id": source_id,
+ "atlas_coords": atlas_coords
+ }
+
+func _index_layers_by_name():
+ for i in range(get_layers_count()):
+ layer_by_name[get_layer_name(i)] = i
diff --git a/board/board.tscn b/board/board.tscn
new file mode 100644
index 0000000..4d13652
--- /dev/null
+++ b/board/board.tscn
@@ -0,0 +1,70 @@
+[gd_scene load_steps=6 format=3 uid="uid://dvlk7imglgpms"]
+
+[ext_resource type="Texture2D" uid="uid://do2vfb2cj7fk" path="res://assets/sprites.png" id="1_lagx3"]
+[ext_resource type="Script" path="res://board/board.gd" id="2_vjb6q"]
+[ext_resource type="Script" path="res://board/highlight.gd" id="3_m02pi"]
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_cta1l"]
+resource_name = "sprites"
+texture = ExtResource("1_lagx3")
+texture_region_size = Vector2i(100, 100)
+0:0/0 = 0
+0:0/0/custom_data_0 = "Blue1"
+1:0/0 = 0
+1:0/0/custom_data_0 = "Blue2"
+2:0/0 = 0
+2:0/0/custom_data_0 = "Red1"
+3:0/0 = 0
+3:0/0/custom_data_0 = "Red2"
+0:1/0 = 0
+0:1/0/custom_data_0 = "Circle"
+1:1/0 = 0
+1:1/0/custom_data_0 = "Square"
+2:1/0 = 0
+2:1/0/custom_data_0 = "Triangle"
+3:1/0 = 0
+3:1/0/custom_data_0 = "Cross"
+0:2/0 = 0
+0:2/0/custom_data_0 = "Circle2"
+1:2/0 = 0
+1:2/0/custom_data_0 = "Square2"
+2:2/0 = 0
+2:2/0/custom_data_0 = "Triangle2"
+3:2/0 = 0
+3:2/0/custom_data_0 = "Cross2"
+0:3/0 = 0
+0:3/0/custom_data_0 = "D1"
+1:3/0 = 0
+1:3/0/custom_data_0 = "D2"
+2:3/0 = 0
+2:3/0/custom_data_0 = "D3"
+3:3/0 = 0
+3:3/0/custom_data_0 = "D4"
+0:4/0 = 0
+0:4/0/custom_data_0 = "White"
+1:4/0 = 0
+1:4/0/custom_data_0 = "D5"
+2:4/0 = 0
+2:4/0/custom_data_0 = "D6"
+3:4/0 = 0
+3:4/0/custom_data_0 = "Grey"
+
+[sub_resource type="TileSet" id="TileSet_exrha"]
+tile_size = Vector2i(100, 100)
+custom_data_layer_0/name = "Name"
+custom_data_layer_0/type = 4
+sources/1 = SubResource("TileSetAtlasSource_cta1l")
+
+[node name="Board" type="TileMap"]
+texture_filter = 1
+tile_set = SubResource("TileSet_exrha")
+rendering_quadrant_size = 100
+format = 2
+layer_0/name = "Board"
+layer_0/tile_data = PackedInt32Array(65537, 1, 0, 131073, 1, 0, 131074, 1, 0, 0, 1, 0, 65536, 1, 0, 131072, 1, 0, 1, 1, 0, 2, 1, 0, 65538, 1, 0)
+layer_1/name = "States"
+layer_1/tile_data = PackedInt32Array()
+script = ExtResource("2_vjb6q")
+
+[node name="Highlight" type="Node2D" parent="."]
+script = ExtResource("3_m02pi")
diff --git a/board/highlight.gd b/board/highlight.gd
new file mode 100644
index 0000000..9dea4f6
--- /dev/null
+++ b/board/highlight.gd
@@ -0,0 +1,22 @@
+extends Node2D
+
+@export var size := Vector2(16,16):
+ set(value):
+ size = value
+ queue_redraw()
+
+@onready var board := get_parent() as Board
+
+
+func _draw():
+ draw_rect(Rect2(0,0,size.x,size.y), Color(1,0,0,0.7), false, 2)
+
+
+func _process(_delta):
+ var grid_pos = board.global_to_map(get_viewport().get_mouse_position())
+ var state = board.get_state(grid_pos)
+ if state == board.empty_state and board.active:
+ position = board.map_to_local(grid_pos) - size / 2
+ show()
+ else:
+ hide()
diff --git a/game.gd b/game.gd
new file mode 100644
index 0000000..73e2190
--- /dev/null
+++ b/game.gd
@@ -0,0 +1,65 @@
+extends Node2D
+
+var current_player: int = 0
+var player_states := ["Circle", "Cross"]
+var won := ""
+
+@onready var board := $Board as Board
+@onready var nextPlayer := $GUI/NextPlayer as Sprite2D
+@onready var wonPlayer := $GUI/WonPlayer as Sprite2D
+
+# Called when the node enters the scene tree for the first time.
+func _ready():
+ current_player = 0
+ board.reset()
+ won = ""
+ wonPlayer.hide()
+ nextPlayer.region_rect.position.x = current_player * 300
+ nextPlayer.show()
+ board.active = true
+
+
+# Called every frame. 'delta' is the elapsed time since the previous frame.
+func _process(_delta):
+ if won == "":
+ if Input.is_action_just_pressed("Click"):
+ var grid_pos = board.gridpos_at_mouse()
+ if board.get_state(grid_pos) == board.empty_state:
+ if board.set_state(grid_pos, player_states[current_player]):
+ won = _check_win()
+ if won=="":
+ current_player = 1 - current_player
+ nextPlayer.region_rect.position.x = current_player * 300
+ else:
+ print("Winner: ", won)
+ wonPlayer.region_rect.position.x = player_states.find(won) * 300
+ wonPlayer.show()
+ nextPlayer.hide()
+ board.active = false
+
+func _on_restart_button_pressed():
+ _ready()
+
+
+var _checks = [
+ [Vector2i(-1,0), Vector2i(1,0)],
+ [Vector2i(0,-1), Vector2i(0,1)],
+ [Vector2i(-1,-1), Vector2i(1,1)],
+ [Vector2i(-1,1), Vector2i(1,-1)],
+]
+
+func _check_win() -> String:
+ for cell in board.get_used_cells(board.layer_by_name[board.state_layer]):
+ var state = board.get_state(cell)
+ for check in _checks:
+ var same = true
+ for neighbour in check:
+ if board.get_state(cell + neighbour) != state:
+ same = false
+ continue
+ if same:
+ return state
+ return ""
+
+
+
diff --git a/game.tscn b/game.tscn
new file mode 100644
index 0000000..21073b3
--- /dev/null
+++ b/game.tscn
@@ -0,0 +1,64 @@
+[gd_scene load_steps=4 format=3 uid="uid://dmahmxghpm47w"]
+
+[ext_resource type="Script" path="res://game.gd" id="1_g1ie7"]
+[ext_resource type="PackedScene" uid="uid://dvlk7imglgpms" path="res://board/board.tscn" id="1_ym80r"]
+[ext_resource type="Texture2D" uid="uid://do2vfb2cj7fk" path="res://assets/sprites.png" id="3_0333r"]
+
+[node name="Game" type="Node2D"]
+script = ExtResource("1_g1ie7")
+
+[node name="Board" parent="." instance=ExtResource("1_ym80r")]
+position = Vector2(420, 222)
+
+[node name="GUI" type="Node2D" parent="."]
+
+[node name="Title" type="Label" parent="GUI"]
+offset_left = 28.0
+offset_top = 31.0
+offset_right = 718.0
+offset_bottom = 103.0
+theme_override_font_sizes/font_size = 32
+text = "Tic Tac Toe Rapid Prototyper"
+
+[node name="NextPlayer" type="Sprite2D" parent="GUI"]
+position = Vector2(690, 59)
+scale = Vector2(0.5, 0.5)
+texture = ExtResource("3_0333r")
+region_enabled = true
+region_rect = Rect2(0, 100, 100, 100)
+
+[node name="NextPlayerLabel" type="Label" parent="GUI"]
+offset_left = 602.0
+offset_top = 47.0
+offset_right = 644.0
+offset_bottom = 73.0
+size_flags_horizontal = 4
+text = "Next:"
+metadata/_edit_use_anchors_ = true
+
+[node name="WonPlayer" type="Sprite2D" parent="GUI"]
+visible = false
+position = Vector2(891, 58)
+scale = Vector2(0.5, 0.5)
+texture = ExtResource("3_0333r")
+region_enabled = true
+region_rect = Rect2(0, 100, 100, 100)
+
+[node name="WonPlayerLabel" type="Label" parent="GUI"]
+offset_left = 807.0
+offset_top = 47.0
+offset_right = 849.0
+offset_bottom = 73.0
+size_flags_horizontal = 4
+text = "Won:"
+metadata/_edit_use_anchors_ = true
+
+[node name="RestartButton" type="Button" parent="GUI"]
+offset_left = 983.0
+offset_top = 44.0
+offset_right = 1086.0
+offset_bottom = 75.0
+text = "Restart"
+metadata/_edit_use_anchors_ = true
+
+[connection signal="pressed" from="GUI/RestartButton" to="." method="_on_restart_button_pressed"]
diff --git a/icon.svg b/icon.svg
new file mode 100644
index 0000000..afd6a84
--- /dev/null
+++ b/icon.svg
@@ -0,0 +1,75 @@
+
+
diff --git a/icon.svg.import b/icon.svg.import
new file mode 100644
index 0000000..16de692
--- /dev/null
+++ b/icon.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://cqc52ufiirdtv"
+path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://icon.svg"
+dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/project.godot b/project.godot
new file mode 100644
index 0000000..c7a99ff
--- /dev/null
+++ b/project.godot
@@ -0,0 +1,31 @@
+; 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=5
+
+[application]
+
+config/name="Tic Tac Toe"
+run/main_scene="res://game.tscn"
+config/features=PackedStringArray("4.2", "GL Compatibility")
+config/icon="res://icon.svg"
+
+[input]
+
+Click={
+"deadzone": 0.5,
+"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null)
+]
+}
+
+[rendering]
+
+textures/canvas_textures/default_texture_filter=0
+renderer/rendering_method="gl_compatibility"
+renderer/rendering_method.mobile="gl_compatibility"
+environment/defaults/default_clear_color=Color(0.203922, 0.203922, 0.203922, 1)