diff --git a/Set.gd b/Set.gd new file mode 100644 index 0000000..fd9b5c2 --- /dev/null +++ b/Set.gd @@ -0,0 +1,247 @@ +class_name Set extends RefCounted +## A custom implementation of a set data structure in GDScript. +## +## Usage Example: +## [codeblock] +## var mySet = Set.new([1, 2, 3]) +## var otherSet = Set.new([2, 3, 4]) +## +## var differenceSet = mySet.difference(otherSet) +## print(differenceSet.elements()) # Output: [1] +## +## mySet.intersection_update(otherSet) +## print(mySet.elements()) # Output: [2, 3] +## [/codeblock] + + +var _set := {} + +## The constructor initializes the set with elements from the specified object, +## supporting various data types. Unsupported types trigger an assertion error. +func _init(obj: Variant = null) -> void: + match typeof(obj): + TYPE_ARRAY, TYPE_PACKED_BYTE_ARRAY, TYPE_PACKED_COLOR_ARRAY, \ + TYPE_PACKED_FLOAT32_ARRAY, TYPE_PACKED_FLOAT64_ARRAY, \ + TYPE_PACKED_INT32_ARRAY, TYPE_PACKED_INT64_ARRAY, \ + TYPE_PACKED_VECTOR2_ARRAY, TYPE_PACKED_VECTOR3_ARRAY, \ + TYPE_PACKED_STRING_ARRAY: + for element in obj: + add(element) + TYPE_NIL: pass + _: + assert(false, "Type %s unsupported for Set objects" % [typeof(obj)]) + +## Adds an [param element] to the set. +func add(element: Variant) -> void: + _set[element] = 0 + +## Clears all elements from the set. +func clear() -> void: + _set.clear() + +## Creates and returns a new [Set] containing the same elements as the current set. +func duplicate() -> Set: + var new_set := Set.new() + new_set._set = _set.duplicate() + return new_set + +# O(min(|self|, |set|)) +## Returns a new [Set] containing elements that are present in the current set +## but not in the provided [param set]. +func difference(set: Set) -> Set: + if set.hash() == self.hash(): + return Set.new() + var out := self.duplicate() + if set.size() > self.size(): + for element in self.elements(): + if set.has(element): + out.erase(element) + else: + for element in set.elements(): + out.erase(element) + return out + +# O(min(|self|, |set|)) +## Modifies the current [Set] to contain elements present in the current set\ +## but not in the provided [param set]. +func difference_update(set: Set) -> void: + if set.hash() == self.hash(): + self.clear() + return + if set.size() > self.size(): + for element in self.elements(): + if set.has(element): + self.erase(element) + else: + for element in set.elements(): + self.erase(element) + +# O(min(|self|, |set|)) +## Returns a new [Set] containing elements common to both the current set and +## the provided [param set]. +func intersection(set: Set) -> Set: + if set.hash() == self.hash(): + return duplicate() + var out := Set.new() + if set.size() > self.size(): + for element in self.elements(): + if set.has(element): + out.add(element) + else: + for element in set.elements(): + if self.has(element): + out.add(element) + return out + +# O(min(|self|, |set|)) +## Modifies the current set to contain only elements common to both the +## current set and the provided [param set]. +func intersection_update(set: Set) -> void: + if set.hash() == self.hash(): + return + var out := Set.new() + if set.size() > self.size(): + for element in self.elements(): + if set.has(element): + out.add(element) + else: + for element in set.elements(): + if self.has(element): + out.add(element) + self.clear() + self._set = out._set + +# O([1, min(|self|, |set|)]) +## Returns [code]true[/code] if the sets have no elements in common; +## otherwise, returns [code]false[/code]. +func isdisjoint(set: Set) -> bool: + if set.size() > self.size(): + for element in self.elements(): + if set.has(element): + return false + else: + for element in set.elements(): + if self.has(element): + return false + return true + +# O([1, |self|]) +## Returns [code]true[/code] if every element of the current set is present +## in the provided [param set]; otherwise, returns [code]false[/code]. +func issubset(set: Set) -> bool: + if set.size() < self.size(): + return false + else: + for element in self.elements(): + if !set.has(element): + return false + return true + +# O([1, |set|]) +## Returns [code]true[/code] if every element of the provided [param set] +## is present in the current set; otherwise, returns [code]false[/code]. +func issuperset(set: Set) -> bool: + if self.size() < set.size(): + return false + else: + for element in set.elements(): + if !self.has(element): + return false + return true + +# O(|self|) ? +## Removes and returns an arbitrary element from the set. +func pop() -> Variant: + assert(self.size() > 0) + var element = self.elements()[randi() % self.size()] + self.erase(element) + return element + +## Removes the specified [param element] from the set. +func erase(element: Variant) -> void: + _set.erase(element) + +# O(min(|self|, |set|)) +## Returns a new [Set] containing elements that are present in either +## the current set or the provided [param set], but not in both. +func symmetric_difference(set: Set) -> Set: + if set.hash() == self.hash(): + return Set.new() + if set.size() > self.size(): + var out := set.duplicate() + for element in self.elements(): + if set.has(element): + out.remove(element) + return out + else: + var out := self.duplicate() + for element in set.elements(): + if self.has(element): + out.remove(element) + return out + +# O(min(|self|, |set|)) +## Modifies the current set to contain elements that are present in either +## the current set or the provided [param set], but not in both. +func symmetric_difference_update(set: Set) -> void: + if set.size() > self.size(): + var temp := set.duplicate() + for element in self.elements(): + if temp.has(element): + temp.erase(element) + else: + temp.add(element) + self._set = temp._set + else: + for element in set.elements(): + if self.has(element): + self.erase(element) + else: + self.add(element) + +# O(min(|self|, |set|)) +## Returns a new [Set] containing all elements from both the current +## set and the provided [param set]. +func union(set: Set) -> Set: + if set.size() > self.size(): + var out := set.duplicate() + for element in self.elements(): + out.add(element) + return out + else: + var out := self.duplicate() + for element in set.elements(): + out.add(element) + return out + +# O(min(|self|, |set|)) +## Modifies the current set to contain all elements from both the current set +## and the provided [param set]. +func update(set: Set) -> void: + if set.size() > self.size(): + var temp := set.duplicate() + for element in self.elements(): + temp.add(element) + self._dict = temp._dict + else: + var temp := self.duplicate() + for element in set.elements(): + temp.add(element) + self._dict = temp.dict + +## Returns an [Array] containing all elements of the set. +func elements() -> Array: + return _set.keys() + +## Returns [code]true[/code] if the set contains the specified [param element]; +## otherwise, returns [code]false[/code]. +func has(element: Variant) -> bool: + return _set.has(element) + +## Returns the number of elements in the set. +func size() -> int: + return _set.size() + +## Returns a hash value for the set. +func hash() -> int: + return _set.hash() diff --git a/Set.gd.uid b/Set.gd.uid new file mode 100644 index 0000000..7d1c1c2 --- /dev/null +++ b/Set.gd.uid @@ -0,0 +1 @@ +uid://3jpsx0g5sg04 diff --git a/assets/000000.png b/assets/000000.png new file mode 100644 index 0000000..a3d4c45 Binary files /dev/null and b/assets/000000.png differ diff --git a/assets/000000.png.import b/assets/000000.png.import new file mode 100644 index 0000000..0d6f560 --- /dev/null +++ b/assets/000000.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bjq048nw8wfx0" +path="res://.godot/imported/000000.png-162664b104f1a282020c995db036c82d.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/000000.png" +dest_files=["res://.godot/imported/000000.png-162664b104f1a282020c995db036c82d.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +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/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +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/0000FF.png b/assets/0000FF.png new file mode 100644 index 0000000..d90f5ef Binary files /dev/null and b/assets/0000FF.png differ diff --git a/assets/0000FF.png.import b/assets/0000FF.png.import new file mode 100644 index 0000000..b4c34b0 --- /dev/null +++ b/assets/0000FF.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dicgy2r4tfods" +path="res://.godot/imported/0000FF.png-3f6845171ad90fe6c585ec200bc8f017.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/0000FF.png" +dest_files=["res://.godot/imported/0000FF.png-3f6845171ad90fe6c585ec200bc8f017.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +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/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +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/00FF00.png b/assets/00FF00.png new file mode 100644 index 0000000..a2725f7 Binary files /dev/null and b/assets/00FF00.png differ diff --git a/assets/00FF00.png.import b/assets/00FF00.png.import new file mode 100644 index 0000000..e595bb4 --- /dev/null +++ b/assets/00FF00.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bb1o41y5ceeqx" +path="res://.godot/imported/00FF00.png-83ab8a7d931629d22b3867042271f361.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/00FF00.png" +dest_files=["res://.godot/imported/00FF00.png-83ab8a7d931629d22b3867042271f361.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +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/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +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/FF0000.png b/assets/FF0000.png new file mode 100644 index 0000000..8ea4e54 Binary files /dev/null and b/assets/FF0000.png differ diff --git a/assets/FF0000.png.import b/assets/FF0000.png.import new file mode 100644 index 0000000..b8ea5c7 --- /dev/null +++ b/assets/FF0000.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://e6snlurkc6d0" +path="res://.godot/imported/FF0000.png-4337ff1c8f0050e96b3bf6805173b9c7.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/FF0000.png" +dest_files=["res://.godot/imported/FF0000.png-4337ff1c8f0050e96b3bf6805173b9c7.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +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/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +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/atlas.png b/atlas.png new file mode 100644 index 0000000..31533ea Binary files /dev/null and b/atlas.png differ diff --git a/atlas.png.import b/atlas.png.import new file mode 100644 index 0000000..b46d5ac --- /dev/null +++ b/atlas.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://2lkar20jssq5" +path="res://.godot/imported/atlas.png-7b6d701721d40511b9cfca52325841a7.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://atlas.png" +dest_files=["res://.godot/imported/atlas.png-7b6d701721d40511b9cfca52325841a7.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +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/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +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/client.gd b/client.gd index dcf0a66..5ec51bb 100644 --- a/client.gd +++ b/client.gd @@ -11,16 +11,20 @@ var _chunks: Array[Chunk] = [] @onready var wfc: Node = get_node("../Generator") +@onready +var map: TileMapLayer = get_node("../TileMapLayer") + func _ready() -> void: - var ruleset: PackedInt32Array = read_sample_ruleset("sample1.png") + var ruleset: PackedInt32Array = read_sample_ruleset("sample2.png") var samples: Array[PackedInt32Array] = parse_samples_from_ruleset(ruleset) - var c = wfc.generate_chunk_at(0,0,_chunks,samples) + var c: Chunk = wfc.generate_chunk_at(0,0,_chunks,samples) #TODO: build a visual layout for the results #TODO: handle the chunk-edges #print(ruleset) #print(samples) print(c.data) + draw_map_data(c) ## Read the png file, and parse it to a useable ruleset func read_sample_ruleset(filename: String) -> PackedInt32Array: @@ -43,7 +47,8 @@ func parse_samples_from_ruleset(ruleset: PackedInt32Array) -> Array[PackedInt32A const RULESET_WIDTH: int = 8 const RULESET_HEIGHT: int = 8 - var samples: Array[PackedInt32Array] = [] + #using a custom container type + var samples: Set = Set.new() for x in range(1, RULESET_WIDTH-1): for y in range(1, RULESET_HEIGHT-1): @@ -61,6 +66,22 @@ func parse_samples_from_ruleset(ruleset: PackedInt32Array) -> Array[PackedInt32A ruleset[(y +1) * RULESET_WIDTH + (x +1)], ] - samples.append(sample) + samples.add(sample) - return samples + var result: Array[PackedInt32Array] = [] + result.assign(samples.elements()) + return result + +func draw_map_data(chunk: Chunk) -> void: + #hacky + var fix = func(x) -> int: + match x: + 0x000000: return 0 + 0xFF0000: return 1 + 0x00FF00: return 2 + 0x0000FF: return 3 + _: return -1 + + for x in range(Chunk.CHUNK_WIDTH): + for y in range(Chunk.CHUNK_HEIGHT): + map.set_cell(Vector2i(x, y), fix.call(chunk.data[y * Chunk.CHUNK_WIDTH + x]), Vector2i.ZERO) diff --git a/sample2.png b/sample2.png new file mode 100644 index 0000000..ed2261f Binary files /dev/null and b/sample2.png differ diff --git a/sample2.png.import b/sample2.png.import new file mode 100644 index 0000000..495b4c3 --- /dev/null +++ b/sample2.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dnmlsw7rrerri" +path="res://.godot/imported/sample2.png-fea84afe5d2a3cb34a1787a71110f597.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://sample2.png" +dest_files=["res://.godot/imported/sample2.png-fea84afe5d2a3cb34a1787a71110f597.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +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/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +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/scene.tscn b/scene.tscn index 93fc410..5f88a96 100644 --- a/scene.tscn +++ b/scene.tscn @@ -1,7 +1,38 @@ -[gd_scene load_steps=3 format=3 uid="uid://d2g4ooi0x6ebo"] +[gd_scene load_steps=12 format=3 uid="uid://d2g4ooi0x6ebo"] [ext_resource type="Script" uid="uid://bf6phxhnvh0ul" path="res://wfc/generator.gd" id="1_ulcgi"] [ext_resource type="Script" uid="uid://jmttidfcknea" path="res://client.gd" id="2_nxogm"] +[ext_resource type="Texture2D" uid="uid://bjq048nw8wfx0" path="res://assets/000000.png" id="3_y2354"] +[ext_resource type="Texture2D" uid="uid://e6snlurkc6d0" path="res://assets/FF0000.png" id="4_ni31j"] +[ext_resource type="Texture2D" uid="uid://bb1o41y5ceeqx" path="res://assets/00FF00.png" id="5_xlvrw"] +[ext_resource type="Texture2D" uid="uid://dicgy2r4tfods" path="res://assets/0000FF.png" id="6_73fnb"] + +[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_5juve"] +texture = ExtResource("3_y2354") +texture_region_size = Vector2i(32, 32) +0:0/0 = 0 + +[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_fy5k1"] +texture = ExtResource("4_ni31j") +texture_region_size = Vector2i(32, 32) +0:0/0 = 0 + +[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_5c1cw"] +texture = ExtResource("5_xlvrw") +texture_region_size = Vector2i(32, 32) +0:0/0 = 0 + +[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_akxrc"] +texture = ExtResource("6_73fnb") +texture_region_size = Vector2i(32, 32) +0:0/0 = 0 + +[sub_resource type="TileSet" id="TileSet_gu47o"] +tile_size = Vector2i(32, 32) +sources/0 = SubResource("TileSetAtlasSource_5juve") +sources/1 = SubResource("TileSetAtlasSource_fy5k1") +sources/2 = SubResource("TileSetAtlasSource_5c1cw") +sources/3 = SubResource("TileSetAtlasSource_akxrc") [node name="Scene" type="Node2D"] @@ -10,3 +41,6 @@ script = ExtResource("1_ulcgi") [node name="Client" type="Node" parent="."] script = ExtResource("2_nxogm") + +[node name="TileMapLayer" type="TileMapLayer" parent="."] +tile_set = SubResource("TileSet_gu47o")