# Duane's Dungeon - a rogue-like game # Copyright (C) 2023 Duane Robertson # dungeon.gd - the dungeon map # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . extends TileMap class_name Dungeon var astar:AStarGrid2D var bounds:Rect2i var game:Node2D var is_dungeon = true var grid_position:Vector2i = Vector2i(5, 5) var level := 0 var map_off := Vector2(5, 5) var open_spaces:Array = [ ] var open_spaces_dic:Dictionary = { } var param:Dictionary var player # ?? var terr_map:Dictionary var terr_name:Dictionary var tile_size:Vector2i # Called when the node enters the scene tree for the first time. func _ready(): game = get_node('/root/Game') var mm = MapMaker.new() add_child(mm) tile_size = tile_set.tile_size # mm.build(7414521855) mm.build() astar = AStarGrid2D.new() astar.region = bounds astar.update() for y in bounds.size.y: for x in bounds.size.x: var v = Vector2i(x, y) + bounds.position if not terr_map[get_tile(v)].walkable: astar.set_point_solid(v, true) texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST visible = true func add_player(): player = Player.new() player.map = self add_child(player) player.place(get_open_space()) #################################### for i in 200: var species = Creature.species_names.pick_random() var cr = Creature.species_classes[species].new() add_child(cr) assert(cr.map) assert(cr.faction) cr.place(get_open_space()) #################################### return player func entity_at(pos:Vector2i): for ent in get_tree().get_nodes_in_group('entities'): if ent.grid_position == pos: return ent return func get_open_space(ibound := bounds) -> Vector2i: var all = (ibound == bounds) var bound := bounds.intersection(ibound) var spaces = open_spaces var p := Vector2i.ZERO ########################################### if not all: spaces = [ ] for y in range(bound.position.y, bound.end.y + 1): for x in range(bound.position.x, bound.end.x + 1): var v = Vector2i(x, y) if open_spaces_dic.get(v): spaces.append(v) spaces.shuffle() ########################################### for i in len(spaces) + 1: if i == len(spaces): G.error('no open space left') break p = spaces.pop_front() if entity_at(p): spaces.push_back(p) else: break return p func get_tile(pos:Vector2i): return terr_name.get(get_cell_atlas_coords(0, pos)) func make_mini_map(preview:=false): G.stopwatch() var trec := TextureRect.new() trec.size = bounds.size var sz = bounds.size + Vector2i.ONE * 2 var img := Image.create(sz.x, sz.y, false, Image.FORMAT_RGBA8) for y in range(-1, bounds.size.y + 1): for x in range(-1, bounds.size.x + 1): var v := Vector2i(x, y) + bounds.position if (not preview) and v == player.grid_position: img.set_pixel(x+1, y+1, Color.WHITE) # elif preview or known_loc(v): elif true: var col # if map_items.get_tile(v) == ITEM_CHEST: # col = Color(COLOR_WOOD_LIGHT) # elif map_items.get_tile(v) == ITEM_STAIR_DOWN \ # or map_items.get_tile(v) == ITEM_STAIR_UP: # col = Color('c000c0') # else: if true: var ter = get_tile(v) # print(terr_map[ter].minimap_color) col = Color(terr_map[ter].minimap_color) img.set_pixel(x+1, y+1, col) else: img.set_pixel(x+1, y+1, Color.BLACK) var tex := ImageTexture.create_from_image(img) trec.texture = tex trec.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST trec.name = 'MiniMap' G.stopwatch('minimap time', true) return trec func remove_entity(ent:Entity): # if entity_map.get(ent.grid_position): # entity_map.erase(ent.grid_position) # entity_ids.erase(ent.uid) if not ent.get('is_player'): ent.visible = false astar.set_point_weight_scale(ent.grid_position, 1.0) ent.queue_free() return true func set_tile(pos:Vector2i, tile:String): set_cell(0, pos, 0, terr_map[tile].atlas_coords) var ttt = 0 var tts = 0 # 295ms, 273ms, 276ms func turn(game_turn:int) -> void: tts += 1 G.debug('dungeon turn') var t = Time.get_ticks_msec() var smt = 0 get_tree().call_group('creatures', 'turn') for ent in get_tree().get_nodes_in_group('creatures'): if ent.smt: smt += 1 var t2 = Time.get_ticks_msec() - t ttt += t2 G.debug('all entity turns: %dms' % [t2]) G.debug(' average: %dms' % [ttt / tts]) G.debug('successful move_towards: %d' % [smt]) ####################################################### var d = {} for ent in get_tree().get_nodes_in_group('creatures'): if d.has(ent.grid_position): G.error('colocated mobs') d[ent.grid_position] = true ####################################################### # var bound:Rect2 = G.player.act_rect # bound = bound.clip(bounds) # var circ:float = CIRCLE_SPAWN * bound.get_area() / 10000.0 # while randf() < circ: # circ -= 1 # spawn_circle(bound) # handle_items(bound) # for c in get_entities(): # c.visible = unshaded(c.grid_position) or G.DEBUG # for c in get_entities(): # if not c.is_player: # c.acted = false # for c in get_entities(): # if not c.is_player: # c.turn(game_turn) get_tree().call_group('creatures', 'release_if_dead') # status.turn(game_turn) # for c in get_entities(): # c.visible = unshaded(c.grid_position) or G.DEBUG