# Duane's Dungeon - a rogue-like game # Copyright (C) 2023 Duane Robertson # state_play.gd - the primary state of play # 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 State class_name StatePlay const MAP_BD = 8 const SAVE_SHOTS = false const WIN_SIZE = Vector2(1280, 720) var eot:bool = true var game_turn := 0 var MAP_SZ = Vector2.ONE * (WIN_SIZE.y - MAP_BD * 2) var SSHOT_DIR = 'screenshots' var SSHOT_FN = 'user://%s/dungeon_shot_%%04d.png' % [SSHOT_DIR] var last_move_time:float var map:Dungeon var map_pos:Vector2 var player:Player var shot_num = 0 var view:ColorRect var mov_vecs = { 'ui_down_left' = Vector2(-1, 1), 'ui_down_right' = Vector2(1, 1), 'ui_down' = Vector2(0, 1), 'ui_left' = Vector2(-1, 0), 'ui_right' = Vector2(1, 0), 'ui_up_left' = Vector2(-1, -1), 'ui_up_right' = Vector2(1, -1), 'ui_up' = Vector2(0, -1), } # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta): if eot: return var d = clampf(120.0 * delta, 1.0, 3.0) var d22 = d * d * 2 var busy := false for ent in get_tree().get_nodes_in_group('creatures'): ent.moving = (ent.position != ent.target_pos) if ent.moving: busy = true ent.position += (ent.target_pos - ent.position).sign() * d if ent.position.distance_squared_to(ent.target_pos) <= d22: ent.position = ent.target_pos ent.moving = false ent.position = ent.position.round() map.position = map.map_off - player.position if not busy: eot = true func _ready(): super() name = 'StatePlay' map_pos = get_parent().map_pos setup_gui() if SAVE_SHOTS: make_shot_dir() player = map.add_player() # player.connect('show_message_hud', game.show_message) # This is better? player.show_message_hud.connect(game.show_message) func input(event): if not eot: return if event is InputEventMouseMotion: return var t1 = Time.get_ticks_msec() var td = t1 - last_move_time if td < 250: return # Convert click on map to vector. if event is InputEventMouseButton and event.pressed: var mapb = view.get_global_rect() if mapb.has_point(event.position): var relp = event.position - mapb.position var sect = (relp * 3.0 / mapb.size).floor() event = sect - Vector2.ONE # Handle ui_events. elif event is InputEventKey: if Input.is_action_pressed('ui_rest'): event = 'rest' elif Input.is_action_pressed('ui_minimap'): event = 'minimap' elif Input.is_action_pressed('ui_repeat'): event = 'pop' else: for dirn in mov_vecs.keys(): if Input.is_action_pressed(dirn): event = mov_vecs[dirn] break if event is InputEvent: return # From here on, the input is an event that takes # a player turn. eot = false if event is Vector2: map.player.move(event) elif event is String and event == 'rest': pass elif event is String and event == 'minimap': stack(StateMinimap) return elif event is String and event == 'pop': stack(StatePopup) return game_turn += 1 map.turn(game_turn) # G.debug('time from last move: %dms' % [t1 - last_move_time]) last_move_time = t1 ############################### if SAVE_SHOTS: var tex = get_tree().get_root().get_texture() var img = tex.get_image() shot_num += 1 img.save_png(SSHOT_FN % [shot_num]) ############################### func make_shot_dir(): var dir = DirAccess.open('user://') if not dir.dir_exists(SSHOT_DIR): dir.make_dir(SSHOT_DIR) func setup_gui(): var vscale = Vector2.ONE * 4 var vsize = MAP_SZ # the map background view = ColorRect.new() view.size = vsize view.position = map_pos view.color = Color.BLACK view.mouse_filter = Control.MOUSE_FILTER_IGNORE view.clip_children = CanvasItem.CLIP_CHILDREN_AND_DRAW # a node to scale the map var cent := Node2D.new() cent.scale = vscale view.add_child(cent) add_child(view) # the game map map = Dungeon.new() cent.add_child(map) var tsize = Vector2(map.tile_size) # used to center the map on the player map.map_off = Vector2(vsize / vscale / 2 - tsize / 2)