diff --git a/game/world/data/enemy_data.gd b/game/world/data/enemy_data.gd index f68d0a5..a8fcd8a 100644 --- a/game/world/data/enemy_data.gd +++ b/game/world/data/enemy_data.gd @@ -5,3 +5,10 @@ extends Resource @export var seed_value : int = 0 @export var spawn_point : Vector2 +@export var spawn_time : int + +@export var enemy_scene: String + +@export var weapon_id: String + +@export var weapon_count: int diff --git a/game/world/generators/enemy_generator.gd b/game/world/generators/enemy_generator.gd index af2d577..0e8238a 100644 --- a/game/world/generators/enemy_generator.gd +++ b/game/world/generators/enemy_generator.gd @@ -2,15 +2,74 @@ class_name EnemyGenerator extends Node +enum EnemyType { + Small, + Medium, + Large, +} + + +const ENEMY_TYPES : Array[EnemyType] = [ + EnemyType.Small, + EnemyType.Medium, + EnemyType.Large, +] +const ENEMY_CHANCES : Array[int] = [ + 45, + 35, + 20, +] + +const ENEMY_SCENES : Dictionary[EnemyType, String] = { + EnemyType.Small: "res://game/entities/ships/enemies/small/small_enemy_ship.tscn", + EnemyType.Medium: "res://game/entities/ships/enemies/small/medium_enemy_ship.tscn", + EnemyType.Large: "res://game/entities/ships/enemies/small/large_enemy_ship.tscn", +} + +const ENEMY_MAX_WEAPON_COUNT : Dictionary[EnemyType, int] = { + EnemyType.Small: 1, + EnemyType.Medium: 2, + EnemyType.Large: 3, +} + + var local_seed_rng : RandomNumberGenerator = RandomNumberGenerator.new() +var spawn_rng : RandomNumberGenerator = RandomNumberGenerator.new() +var type_rng : RandomNumberGenerator = RandomNumberGenerator.new() +var weapon_rng : RandomNumberGenerator = RandomNumberGenerator.new() func generate(seed_value: int) -> EnemyData: local_seed_rng.seed = seed_value + spawn_rng.seed = local_seed_rng.randi() + type_rng.seed = local_seed_rng.randi() + weapon_rng.seed = local_seed_rng.randi() + + var type := _get_enemy_type() var data : EnemyData = EnemyData.new() data.seed_value = seed_value - + _full_spawn(data) + _full_scene(data, type) + _full_weapon(data, type) return data + + +func _get_enemy_type() -> EnemyType: + var index := type_rng.rand_weighted(ENEMY_CHANCES) + return ENEMY_TYPES[index] + + +func _full_spawn(data: EnemyData) -> void: + data.spawn_point.y = 750 + data.spawn_point.x = spawn_rng.randf_range(0.0, 360.0) + + +func _full_scene(data: EnemyData, type: EnemyType) -> void: + data.enemy_scene = ENEMY_SCENES[type] + + +func _full_weapon(data: EnemyData, type: EnemyType) -> void: + data.weapon_count = randi_range(1, ENEMY_MAX_WEAPON_COUNT[type]) diff --git a/game/world/generators/passage_generator.gd b/game/world/generators/passage_generator.gd index 4df7838..e7740f6 100644 --- a/game/world/generators/passage_generator.gd +++ b/game/world/generators/passage_generator.gd @@ -2,14 +2,27 @@ class_name PassageGenerator extends Node -const ENEMY_COUNT = 10 -const MIN_LENGTH = 250.0 -const MAX_LENGTH = 350.0 +const ENEMY_COUNT_MEAN = 50.0 +const ENEMY_COUNT_DEVIATION = 100.0 + +const LENGTH_MEAN = 300.0 +const LENGTH_DEVIATION = 50.0 + +const SPAWN_START_DELAY = 3 +const SPAWN_END_DELAY = 3 + +const USE_NEXT_WEAPON_CHANCE = 10 var local_seed_rng : RandomNumberGenerator = RandomNumberGenerator.new() -var enemy_seed_rng : RandomNumberGenerator = RandomNumberGenerator.new() +var weapon_ids_rng : RandomNumberGenerator = RandomNumberGenerator.new() var length_rng : RandomNumberGenerator = RandomNumberGenerator.new() +var enemy_seed_rng : RandomNumberGenerator = RandomNumberGenerator.new() +var enemy_count_rng : RandomNumberGenerator = RandomNumberGenerator.new() +var enemy_spawn_time_rng : RandomNumberGenerator = RandomNumberGenerator.new() +var enemy_weapon_rng : RandomNumberGenerator = RandomNumberGenerator.new() + +var weapon_ids : Array[String] @onready var enemy_generator : EnemyGenerator = $EnemyGenerator @@ -17,24 +30,66 @@ var length_rng : RandomNumberGenerator = RandomNumberGenerator.new() func generate(seed_value: int) -> PassageData: local_seed_rng.seed = seed_value - enemy_seed_rng.seed = local_seed_rng.randi() + weapon_ids_rng.seed = local_seed_rng.randi() length_rng.seed = local_seed_rng.randi() + enemy_seed_rng.seed = local_seed_rng.randi() + enemy_count_rng.seed = local_seed_rng.randi() + enemy_spawn_time_rng.seed = local_seed_rng.randi() + enemy_weapon_rng.seed = local_seed_rng.randi() + + weapon_ids = _get_weapon_ids() var data : PassageData = PassageData.new() data.seed_value = seed_value - _fill_enemies(data) _fill_length(data) + _fill_enemies(data) return data -func _fill_enemies(data: PassageData) -> void: - for i in ENEMY_COUNT: - var seed_value := enemy_seed_rng.randi() - var enemy := enemy_generator.generate(seed_value) - data.enemies.append(enemy) +func _get_weapon_ids() -> Array[String]: + var array : Array[String] = AbstractShip.WEAPON_SCENES.keys().duplicate() + + for i in range(array.size() - 1, 0, -1): + var j := weapon_ids_rng.randi_range(0, i) + + var temp := array[i] + array[i] = array[j] + array[j] = temp + + return array func _fill_length(data: PassageData) -> void: - data.length = length_rng.randf_range(MIN_LENGTH, MAX_LENGTH) + data.length = length_rng.randfn(LENGTH_MEAN, LENGTH_DEVIATION) + + +func _fill_enemies(data: PassageData) -> void: + var spawn_end_time := floori(data.length - SPAWN_END_DELAY) + + var enemy_count := roundi(enemy_count_rng.randfn(ENEMY_COUNT_MEAN, ENEMY_COUNT_DEVIATION)) + for i in range(enemy_count): + var seed_value := enemy_seed_rng.randi() + var enemy := enemy_generator.generate(seed_value) + + enemy.spawn_time = enemy_spawn_time_rng.randi_range(SPAWN_START_DELAY, spawn_end_time) + enemy.weapon_id = _get_weapon_id() + + data.enemies.append(enemy) + + var enemy_spawn_time_compare := func(a: EnemyData, b: EnemyData) -> bool: + return a.spawn_time > b.spawn_time + data.enemies.sort_custom(enemy_spawn_time_compare) + + +func _get_weapon_id() -> String: + var index := 0 + + while [index < weapon_ids.size()]: + if enemy_weapon_rng.randi_range(1, 100) <= USE_NEXT_WEAPON_CHANCE: + index += 1 + else: + break + + return weapon_ids[index] diff --git a/game/world/generators/sector_generator.gd b/game/world/generators/sector_generator.gd index c26921e..fadcff9 100644 --- a/game/world/generators/sector_generator.gd +++ b/game/world/generators/sector_generator.gd @@ -1,12 +1,16 @@ class_name SectorGenerator extends Node - -const CHANSES_BY_SECTOR_TYPE : Dictionary[SectorData.SectorType, int] = { - SectorData.SectorType.ShopSector: 40, - SectorData.SectorType.RepairSector: 20, - SectorData.SectorType.DebrisSector: 40, -} +const SECTOR_TYPES : Array[SectorData.SectorType] = [ + SectorData.SectorType.ShopSector, + SectorData.SectorType.RepairSector, + SectorData.SectorType.DebrisSector, +] +const SECTOR_CHANCES : Array[int] = [ + 40, + 20, + 40, +] var local_seed_rng : RandomNumberGenerator = RandomNumberGenerator.new() @@ -26,16 +30,5 @@ func generate(seed_value: int) -> SectorData: func _get_sector_type() -> SectorData.SectorType: - var total_chance := 0 - for type in CHANSES_BY_SECTOR_TYPE: - total_chance += CHANSES_BY_SECTOR_TYPE[type] - - var threshold := sector_type_rng.randi_range(1, total_chance) - - var cumulative := 0 - for type in CHANSES_BY_SECTOR_TYPE: - cumulative += CHANSES_BY_SECTOR_TYPE[type] - if threshold <= cumulative: - return type - - return SectorData.SectorType.DebrisSector + var index := sector_type_rng.rand_weighted(SECTOR_CHANCES) + return SECTOR_TYPES[index] diff --git a/game/world/generators/stage_generator.gd b/game/world/generators/stage_generator.gd index 9f49c40..e582802 100644 --- a/game/world/generators/stage_generator.gd +++ b/game/world/generators/stage_generator.gd @@ -9,11 +9,16 @@ enum StageType { } -const CHANSES_BY_SECTOR_COUNT : Dictionary[int, int] = { - 1: 20, - 2: 30, - 3: 50, -} +const SECTOR_COUNTS : Array[int] = [ + 1, + 2, + 3, +] +const SECTOR_CHANCES : Array[int] = [ + 20, + 30, + 50, +] var local_seed_rng : RandomNumberGenerator = RandomNumberGenerator.new() @@ -52,19 +57,8 @@ func _fill_sectors(data : StageData, type: StageType = StageType.Inner) -> void: 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 + var index := sector_count_rng.rand_weighted(SECTOR_CHANCES) + return SECTOR_COUNTS[index] func _update_neighbors(data : StageData) -> void: