Attention | Topic was automatically imported from the old Question2Answer platform. | |
Asked By | 2Dfanatic |
Thank you for responding to my previous questionIs there an more efficient way for spawning enemies in a Procedurally generated map ? unlike this .
I got the code for procedural map generation from here recursor. there is explanation there for how the code works as well.
I will share the code so that you guys can get a better understanding of my problem.
Here is the gd script for my map random direction Digger:-
extends Node2D
class_name Digger
var dir:Vector2 = Vector2.ZERO
var pos:Vector2 = Vector2.ZERO
const all_dirs = [Vector2.UP, Vector2.DOWN, Vector2.LEFT, Vector2.RIGHT]
const left_right = [Vector2.LEFT, Vector2.RIGHT]
const up_down = [Vector2.UP, Vector2.DOWN]
#percentage chance to keep current direction
var keep_dir : float
var die_chance : float
var is_dead := false
var die_if_all_floor := false
var die_if_tile_is_floor := false
var can_backtrack := false
var map:Map
func _init(map_info:Map, init_pos:Vector2, continue_dir_prob:float = 0.3, chance_to_die:float = 0.005, initial_dir: Vector2 = Vector2.ZERO):
map = map_info
keep_dir = clamp(continue_dir_prob, 0, 1)
die_chance = clamp(chance_to_die, 0, 1)
pos = init_pos
if initial_dir == Vector2.ZERO:
rand_dir()
else:
dir = initial_dir
func move():
if is_dead:
return
pos += dir
if randf() <= die_chance:
is_dead = true
_pick_dir()
func dig(dig_tile:int = 0):
if die_if_tile_is_floor && map.get_cell(pos.x, pos.y) == dig_tile:
is_dead = true
elif not map.set_cell(pos.x, pos.y, dig_tile):
is_dead = true
elif die_if_all_floor && is_all_adjacent(dig_tile):
is_dead = true
func _pick_dir():
if randf() > keep_dir:
var new_dir = dir
while new_dir == dir:
rand_dir()
func is_all_adjacent(tile_id:int = 0):
return get_cell(pos + Vector2.UP) == tile_id && \
get_cell(pos + Vector2.DOWN) == tile_id && \
get_cell(pos + Vector2.LEFT) == tile_id && \
get_cell(pos + Vector2.RIGHT) == tile_id
func get_cell(cell_pos:Vector2):
return map.tiles.get_cell(cell_pos.x, cell_pos.y)
func rand_dir():
if can_backtrack || dir == Vector2.ZERO:
dir = all_dirs[randi() % all_dirs.size()]
else:
if dir.x == 0:
dir = left_right[randi() % left_right.size()]
else:
dir = up_down[randi() % up_down.size()]
Here is the gd script for my Map looks like :-
extends Node2D
class_name Map
var tiles1: TileMap
var tiles2: TileMap
var tiles3: TileMap
var size: Vector2 setget ,get_size
#how much border should there be at the edge (digger will not dig past this)
var border : Vector2
func get_size():
return size
func _init(tmap1:TileMap, tmap2:TileMap, tmap3:TileMap, map_size:Vector2, borderSize:Vector2 = Vector2.ZERO):
tiles1 = tmap1
tiles2 = tmap2
tiles3 = tmap3
size = map_size
border = borderSize
func clear():
tiles1.clear()
tiles2.clear()
tiles3.clear()
func world_center():
return tiles1.map_to_world(size / 2.0)
func center_coord():
return size / 2
func set_cell(x:int, y:int, tile:int):
if _is_valid(x,y):
tiles1.set_cell(x,y,tile)
tiles2.set_cell(x,y,tile)
tiles3.set_cell(x,y,tile)
return true
else:
return false
func get_cell(x:int, y:int):
return tiles1.get_cell(x,y)
return tiles2.get_cell(x,y)
return tiles3.get_cell(x,y)
func _is_valid(x:int, y:int):
return x >= border.x && x < size.x - border.x \
&& y >= border.y && y < size.y - border.y
func fill(tile:int):
for y in size.y:
for x in size.x:
tiles1.set_cell(x, y, tile)
tiles2.set_cell(x, y, tile)
tiles3.set_cell(x, y, tile)
func update_bitmask_all():
tiles1.update_bitmask_region(Vector2.ZERO, size)
tiles2.update_bitmask_region(Vector2.ZERO, size)
tiles3.update_bitmask_region(Vector2.ZERO, size)
func get_percent_tile(tile:int):
var t = tiles1.get_used_cells_by_id(tile).size()
return t / (size.x * size.y)
Here is the gd script of the Main file:-
extends Control
const FLOOR = -1
const WALL = 0
const gridSize = Vector2(160,80)
const gridSize_floor = Vector2(80,50)
var diggers = []
onready var tilemapo = $Mapo
onready var tilemapi = $Mapi
onready var tilemapj = $Mapj
var tile
var map: Map
func _ready():
load_game()
func load_game():
randomize()
map = Map.new(tilemapo, tilemapi, tilemapj, gridSize, Vector2(1,1))
gen_map()
$Player.position = map.world_center() + Vector2.ONE * 16
set_process(true)
func dig_map(digTile:int = FLOOR):
while diggers.size() > 0:
for i in range(diggers.size() - 1, -1, -1):
diggers[i].dig(digTile)
diggers[i].move()
if diggers[i].is_dead:
diggers.remove(i)
func _process(delta):
if Input.is_action_just_pressed("ui_accept"):
get_tree().reload_current_scene()
_ready()
elif Input.is_action_just_pressed("ui_cancel"):
get_tree().quit()
func gen_map():
map.clear()
map.fill(WALL)
#diggers.append(Digger.new(map, map.center_coord(), 0.25, .0003))
#diggers.append(Digger.new(map, Vector2.ZERO, 0.35, .0005))
diggers.append(Digger.new(map, map.center_coord(), 0.55, .01, Vector2.LEFT))
diggers.append(Digger.new(map, map.center_coord() + Vector2.RIGHT, 0.55, .01, Vector2.RIGHT))
diggers.append(Digger.new(map, map.center_coord() + Vector2.UP, 0.55, .01, Vector2.UP))
diggers.append(Digger.new(map, map.center_coord() + Vector2.DOWN, 0.55, .01, Vector2.DOWN))
dig_map(FLOOR)
map.update_bitmask_all()
In order to efficiently spawn enemies i have to record, every single position or cell the digger moves on, and then add enemies inside the recorded cell positions during spawning.
My question is how to append every single Vector2 position the digger has dug into an array, So that the array can be later used to spawn enemies in those vector2 positions.
Can i use tile id to spawn enemies as well ? if so how ?.
Explanation for Digger.gd :-
Variables dir is the direction the digger has to dig
Variable pos is the position of the digger
The const all_dirs ,left_right ,up_down are used in rand_dir() at the bottom to pick the direction the digger is going to move
keep_dir is percentage chance to keep current direction
die_chance is percentage chance the digger will terminate itself.
can_backtrack is used in rand_dir() function as a condition if for the digger to backtrack
_init is used to initialized all the value to the above variables
move() and dig(dig_tile:int = 0) is used in dig_map(digTile:int = FLOOR) function in the Main Gd script
is_all_adjacent(tile_id:int = 0) gets the Vector2 positions of the cells adjacent to the diggers