diff --git a/game/game.gd b/game/game.gd index 854db54..8e97e61 100644 --- a/game/game.gd +++ b/game/game.gd @@ -9,6 +9,7 @@ extends Node func _ready() -> void: pause_screen.hide() game_over_screen.hide() + world_generator.generate(randi()) func _input(event: InputEvent) -> void: diff --git a/game/game.tscn b/game/game.tscn index 6f13272..9aa5103 100644 --- a/game/game.tscn +++ b/game/game.tscn @@ -4,7 +4,7 @@ [ext_resource type="PackedScene" uid="uid://d34nh3lc1gpb" path="res://menu/pause_screen.tscn" id="2_h7iqs"] [ext_resource type="PackedScene" uid="uid://dgc0087kvarx6" path="res://game/passage.tscn" id="3_4fuuu"] [ext_resource type="PackedScene" uid="uid://duxm8n62j2qt6" path="res://menu/game_over_screen.tscn" id="4_4fuuu"] -[ext_resource type="Script" uid="uid://b7e3xk14le68j" path="res://game/world/generators/world_generator.gd" id="5_dxrkv"] +[ext_resource type="PackedScene" uid="uid://ggf76ayl53bb" path="res://game/world/generators/world_generator.tscn" id="5_dxrkv"] [node name="Game" type="Node2D"] script = ExtResource("1_l1rk1") @@ -27,9 +27,7 @@ offset_top = 172.0 offset_right = 320.0 offset_bottom = 172.0 -[node name="WorldGenerator" type="Node" parent="."] -script = ExtResource("5_dxrkv") -metadata/_custom_type_script = "uid://b7e3xk14le68j" +[node name="WorldGenerator" parent="." instance=ExtResource("5_dxrkv")] [connection signal="player_died" from="Passage" to="." method="_on_passage_player_died"] [connection signal="continue_game" from="PauseScreen" to="." method="_on_pause_screen_continue_game"] diff --git a/game/world/data/area_data.gd b/game/world/data/area_data.gd index a08d22f..1d644d4 100644 --- a/game/world/data/area_data.gd +++ b/game/world/data/area_data.gd @@ -2,9 +2,7 @@ class_name AreaData extends Resource -@export var first_stage : StageData -@export var last_stage : StageData -@export var inner_stages : Array[StageData] = [] +@export var stages : Array[StageData] = [] @export var passages : Array[PassageData] = [] @export var seed_value : int = 0 diff --git a/game/world/generators/area_generator.gd b/game/world/generators/area_generator.gd index 4065560..181bb30 100644 --- a/game/world/generators/area_generator.gd +++ b/game/world/generators/area_generator.gd @@ -6,55 +6,50 @@ extends Node @onready var passage_generator : PassageGenerator = $PassageGenerator -const INNER_STAGE_COUNT = 3 +const STAGE_COUNT = 9 + +const EXTRA_PASSAGE_CHANCE = 20 + + +var local_seed_rng : RandomNumberGenerator = RandomNumberGenerator.new() +var stage_seed_rng : RandomNumberGenerator = RandomNumberGenerator.new() +var passage_seed_rng : RandomNumberGenerator = RandomNumberGenerator.new() +var passage_chance_rng : RandomNumberGenerator = RandomNumberGenerator.new() +var passage_direction_rng : RandomNumberGenerator = RandomNumberGenerator.new() func generate(seed_value: int) -> AreaData: - var rng := RandomNumberGenerator.new() - rng.seed = seed_value + local_seed_rng.seed = seed_value + stage_seed_rng.seed = local_seed_rng.randi() + passage_seed_rng.seed = local_seed_rng.randi() + passage_chance_rng.seed = local_seed_rng.randi() + passage_direction_rng.seed = local_seed_rng.randi() var data : AreaData = AreaData.new() data.seed_value = seed_value - _fill_stages(rng, data) - _fill_passages(rng, data) + _fill_stages(data) + _fill_passages(data) return data -func _fill_stages(rng: RandomNumberGenerator, data : AreaData) -> void: - _fill_first_stage(rng, data) - _fill_last_stage(rng, data) - _fill_inner_stages(rng, data) +func _fill_stages(data : AreaData) -> void: + for i in range(STAGE_COUNT): + var is_endpoint := i == 0 or i == STAGE_COUNT - 1 + var seed_value := stage_seed_rng.randi() + var stage := stage_generator.generate(seed_value, is_endpoint) + data.stages.append(stage) -func _fill_first_stage(rng: RandomNumberGenerator, data : AreaData) -> void: - var stage := _get_stage(rng, true) - data.first_stage = stage - - -func _fill_last_stage(rng: RandomNumberGenerator, data : AreaData) -> void: - var stage := _get_stage(rng, true) - data.last_stage = stage - - -func _fill_inner_stages(rng: RandomNumberGenerator, data : AreaData) -> void: - for i in INNER_STAGE_COUNT: - var stage := _get_stage(rng) - data.inner_stages.append(stage) - - -func _fill_passages(rng: RandomNumberGenerator, data : AreaData) -> void: - var all_stages : Array[StageData] = [data.first_stage] + data.inner_stages + [data.last_stage] - - for i in range(all_stages.size() - 1): - var first_stage := all_stages[i] - var second_stage := all_stages[i + 1] - _fill_passages_for_pair(rng, data, first_stage, second_stage) +func _fill_passages(data : AreaData) -> void: + for i in range(data.stages.size() - 1): + var first_stage := data.stages[i] + var second_stage := data.stages[i + 1] + _fill_passages_for_pair(data, first_stage, second_stage) func _fill_passages_for_pair( - rng: RandomNumberGenerator, data : AreaData, first_stage: StageData, second_stage: StageData @@ -62,32 +57,82 @@ func _fill_passages_for_pair( var first_size := first_stage.sectors.size() var second_size := second_stage.sectors.size() - if first_size == second_size: - match first_size: - 1: - pass - 2: - pass - 3: - pass + if first_size < second_size: + var is_flipped := false + _fill_passages_for_unequal_pair(data, first_stage.sectors, second_stage.sectors, is_flipped) + elif first_size > second_size: + var is_flipped := true + _fill_passages_for_unequal_pair(data, second_stage.sectors, first_stage.sectors, is_flipped) else: - var lesser_stage := first_stage if first_size < second_size else second_stage - var greater_stage := first_stage if first_size > second_size else second_stage - var lesser_size := lesser_stage.sectors.size() - var greater_size := greater_stage.sectors.size() - - match lesser_size: - 1: - match greater_size: - 2: - pass - 3: - pass - 2: - pass + _fill_passages_for_equal_pair(data, first_stage.sectors, second_stage.sectors) -func _get_stage(rng: RandomNumberGenerator, is_endpoint: bool = false) -> StageData: - var seed_value := rng.randi() - var stage := stage_generator.generate(seed_value, is_endpoint) - return stage +func _fill_passages_for_equal_pair( + data : AreaData, + first_sectors: Array[SectorData], + second_sectors: Array[SectorData] +) -> void: + var size := first_sectors.size() + + for i in range(size): + _connect_sectors(data, first_sectors[i], second_sectors[i]) + + for i in range(size - 1): + if _extra_passage_needed(): + var is_passage_fliped := _is_extra_passage_flipped() + var from := i if is_passage_fliped else i + 1 + var to := i + 1 if is_passage_fliped else i + _connect_sectors(data, first_sectors[from], second_sectors[to]) + + +func _fill_passages_for_unequal_pair( + data : AreaData, + lesser_sectors: Array[SectorData], + greater_sectors: Array[SectorData], + is_sectors_flipped: bool +) -> void: + var lesser_size := lesser_sectors.size() + var greater_size := greater_sectors.size() + + match lesser_size: + 1: + for i in range(greater_size): + _connect_sectors(data, lesser_sectors[0], greater_sectors[i], is_sectors_flipped) + 2: + _connect_sectors(data, lesser_sectors[0], greater_sectors[0], is_sectors_flipped) + _connect_sectors(data, lesser_sectors[1], greater_sectors[2], is_sectors_flipped) + if _extra_passage_needed(): + _connect_sectors(data, lesser_sectors[0], greater_sectors[1], is_sectors_flipped) + _connect_sectors(data, lesser_sectors[1], greater_sectors[1], is_sectors_flipped) + else: + var from := 0 if _is_extra_passage_flipped() else 1 + _connect_sectors(data, lesser_sectors[from], greater_sectors[1], is_sectors_flipped) + + +func _extra_passage_needed() -> bool: + return passage_chance_rng.randi_range(1, 100) <= EXTRA_PASSAGE_CHANCE + + +func _is_extra_passage_flipped() -> bool: + return passage_direction_rng.randi_range(0, 1) == 0 + + +func _connect_sectors( + data : AreaData, + first_sector: SectorData, + second_sector: SectorData, + is_flipped: bool = false +) -> void: + var seed_value := passage_seed_rng.randi() + var passage := passage_generator.generate(seed_value) + + var previous_sector := second_sector if is_flipped else first_sector + var next_sector := first_sector if is_flipped else second_sector + + passage.previous_sector = previous_sector + passage.next_sector = next_sector + + previous_sector.next_passages.append(passage) + next_sector.previous_passages.append(passage) + + data.passages.append(passage) diff --git a/game/world/generators/passage_generator.gd b/game/world/generators/passage_generator.gd new file mode 100644 index 0000000..5af0bf4 --- /dev/null +++ b/game/world/generators/passage_generator.gd @@ -0,0 +1,16 @@ +class_name PassageGenerator +extends Node + + +var local_seed_rng : RandomNumberGenerator = RandomNumberGenerator.new() + + +func generate(seed_value: int) -> PassageData: + local_seed_rng.seed = seed_value + + var data : PassageData = PassageData.new() + data.seed_value = seed_value + + + + return data diff --git a/game/world/generators/passage_generator.gd.uid b/game/world/generators/passage_generator.gd.uid new file mode 100644 index 0000000..3cf9c58 --- /dev/null +++ b/game/world/generators/passage_generator.gd.uid @@ -0,0 +1 @@ +uid://bi5vt3ikxya8d diff --git a/game/world/generators/passage_generator.tscn b/game/world/generators/passage_generator.tscn new file mode 100644 index 0000000..69ce99a --- /dev/null +++ b/game/world/generators/passage_generator.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://cfcpr07j58cvx"] + +[ext_resource type="Script" uid="uid://bi5vt3ikxya8d" path="res://game/world/generators/passage_generator.gd" id="1_3arab"] + +[node name="PassageGenerator" type="Node"] +script = ExtResource("1_3arab") diff --git a/game/world/generators/sector_generator.gd b/game/world/generators/sector_generator.gd new file mode 100644 index 0000000..75b9621 --- /dev/null +++ b/game/world/generators/sector_generator.gd @@ -0,0 +1,16 @@ +class_name SectorGenerator +extends Node + + +var local_seed_rng : RandomNumberGenerator = RandomNumberGenerator.new() + + +func generate(seed_value: int) -> SectorData: + local_seed_rng.seed = seed_value + + var data : SectorData = SectorData.new() + data.seed_value = seed_value + + + + return data diff --git a/game/world/generators/sector_generator.gd.uid b/game/world/generators/sector_generator.gd.uid new file mode 100644 index 0000000..8a489b3 --- /dev/null +++ b/game/world/generators/sector_generator.gd.uid @@ -0,0 +1 @@ +uid://de386hpwwum7o diff --git a/game/world/generators/sector_generator.tscn b/game/world/generators/sector_generator.tscn new file mode 100644 index 0000000..6fc6306 --- /dev/null +++ b/game/world/generators/sector_generator.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://bh1v37wol5ktj"] + +[ext_resource type="Script" uid="uid://de386hpwwum7o" path="res://game/world/generators/sector_generator.gd" id="1_trjpu"] + +[node name="SectorGenerator" type="Node"] +script = ExtResource("1_trjpu") diff --git a/game/world/generators/stage_generator.gd b/game/world/generators/stage_generator.gd new file mode 100644 index 0000000..d7c8904 --- /dev/null +++ b/game/world/generators/stage_generator.gd @@ -0,0 +1,54 @@ +class_name StageGenerator +extends Node + + +const CHANSES_BY_SECTOR_COUNT : Dictionary[int, int] = { + 1: 25, + 2: 60, + 3: 15 +} + + +@onready var sector_generator : SectorGenerator = $SectorGenerator + + +var local_seed_rng : RandomNumberGenerator = RandomNumberGenerator.new() +var sector_seed_rng : RandomNumberGenerator = RandomNumberGenerator.new() +var sector_count_rng : RandomNumberGenerator = RandomNumberGenerator.new() + + +func generate(seed_value: int, is_endpoint: bool = false) -> StageData: + local_seed_rng.seed = seed_value + sector_seed_rng.seed = local_seed_rng.randi() + sector_count_rng.seed = local_seed_rng.randi() + + var data : StageData = StageData.new() + data.seed_value = seed_value + + _fill_sectors(data, is_endpoint) + + return data + + +func _fill_sectors(data : StageData, is_endpoint: bool = false) -> void: + var sector_count := 1 if is_endpoint else _get_sector_count() + for i in sector_count: + var seed_value := sector_seed_rng.randi() + var sector := sector_generator.generate(seed_value) + data.sectors.append(sector) + + +func _get_sector_count() -> int: + var total_chance := 0 + for count in CHANSES_BY_SECTOR_COUNT: + total_chance += CHANSES_BY_SECTOR_COUNT[count] + + var threshold := sector_count_rng.randi_range(1, total_chance) + + var cumulative := 0 + for count in CHANSES_BY_SECTOR_COUNT: + cumulative += CHANSES_BY_SECTOR_COUNT[count] + if threshold <= cumulative: + return count + + return 1 diff --git a/game/world/generators/stage_generator.gd.uid b/game/world/generators/stage_generator.gd.uid new file mode 100644 index 0000000..a58d10e --- /dev/null +++ b/game/world/generators/stage_generator.gd.uid @@ -0,0 +1 @@ +uid://jn0w7kgstq1j diff --git a/game/world/generators/stage_generator.tscn b/game/world/generators/stage_generator.tscn new file mode 100644 index 0000000..f795616 --- /dev/null +++ b/game/world/generators/stage_generator.tscn @@ -0,0 +1,9 @@ +[gd_scene load_steps=3 format=3 uid="uid://bn4r4f3str55v"] + +[ext_resource type="Script" uid="uid://jn0w7kgstq1j" path="res://game/world/generators/stage_generator.gd" id="1_7pxno"] +[ext_resource type="PackedScene" uid="uid://bh1v37wol5ktj" path="res://game/world/generators/sector_generator.tscn" id="2_etmdi"] + +[node name="StageGenerator" type="Node"] +script = ExtResource("1_7pxno") + +[node name="SectorGenerator" parent="." instance=ExtResource("2_etmdi")] diff --git a/game/world/generators/world_generator.gd b/game/world/generators/world_generator.gd index 59e6e19..9b665b6 100644 --- a/game/world/generators/world_generator.gd +++ b/game/world/generators/world_generator.gd @@ -8,20 +8,24 @@ extends Node const AREA_COUNT = 3 +var local_seed_rng : RandomNumberGenerator = RandomNumberGenerator.new() +var area_seed_rng : RandomNumberGenerator = RandomNumberGenerator.new() + + func generate(seed_value: int) -> WorldData: - var rng := RandomNumberGenerator.new() - rng.seed = seed_value + local_seed_rng.seed = seed_value + area_seed_rng.seed = local_seed_rng.randi() var data : WorldData = WorldData.new() data.seed_value = seed_value - _fill_areas(rng, data) + _fill_areas(data) return data -func _fill_areas(rng: RandomNumberGenerator, data : WorldData) -> void: +func _fill_areas(data : WorldData) -> void: for i in AREA_COUNT: - var seed_value := rng.randi() + var seed_value := area_seed_rng.randi() var area := area_generator.generate(seed_value) data.areas.append(area)