This repository has been archived on 2020-09-30. You can view files and clone it, but cannot push or open issues or pull requests.
odyssey-old/Scenes/Map.gd
2020-09-16 01:23:45 +02:00

283 lines
8.3 KiB
GDScript

tool
extends Node2D
class_name GameMap
var debug_areas := false
var ship_direction := 0
var ship_speed := 0
var current_ship_position := Vector2.ZERO
var current_ship_subpos := Vector2.ZERO
var current_ship_target = Vector2.ZERO
var current_ship_direction := 0.0
var current_ship_speed := 0.0
var deepspace_mat: ShaderMaterial = null
var warp_state := false
puppet var pup_ship_position := Vector2.ZERO
puppet var pup_ship_subpos := Vector2.ZERO
puppet var pup_ship_target := Vector2.ZERO
puppet var pup_ship_direction := 0.0
puppet var pup_ship_speed := 0.0
const MAX_ACCELERATION := 0.03
const MAX_STEERING := 0.06
const EPSILON := 1e-3
const SCROLL_MULTIPLIER := 1e4
const ENGINE_MULTIPLIER := 5000
const NO_SPEED_THRESHOLD := 0.01
const ProbeElectricity := preload("res://Actors/Systems/Electricity/ElectricProbe.tscn")
onready var tilemaps := [ $tiles/base, $tiles/cables, $tiles/floor, $tiles/walls ]
onready var pois := $pois
export var unlit := false setget set_unlit
onready var darkness := $darkness
export var shadow_intensity := 0.2
func _ready():
if Engine.editor_hint:
return
set_unlit(true)
if not is_network_master():
return
# Run autotile conversions and generate occlusions
$tiles/walls.run_conversions()
# Electricity setup
make_electric_probes($tiles/cables, "Wire")
# Set engines to expected power level
set_engine_strength(current_ship_speed)
deepspace_mat = $deepspace.material as ShaderMaterial
func _process(delta: float):
if Engine.editor_hint:
return
var engines := get_engine_count()
var max_speed := get_max_speed()
# Ease ship speed/direction changes
if abs(current_ship_direction) > PI*2:
current_ship_direction -= PI*2 * sign(current_ship_direction)
var direction_delta := ship_direction - current_ship_direction
if direction_delta < 0:
direction_delta += PI*2
if direction_delta > PI:
direction_delta -= PI*2
if abs(direction_delta) < 1e-3:
current_ship_direction = ship_direction
else:
# Avoid stuttering by not turning until there's enough reason to
if abs(direction_delta) > 0.1:
current_ship_direction += MAX_STEERING * engines * delta * sign(direction_delta)
var speed_delta := ship_speed - current_ship_speed
if abs(speed_delta) < EPSILON:
current_ship_speed = ship_speed
else:
current_ship_speed += MAX_ACCELERATION * max_speed * delta * sign(speed_delta)
set_engine_strength(current_ship_speed * ENGINE_MULTIPLIER)
deepspace_mat.set_shader_param("scroll_speed", current_ship_speed * 5000)
func _physics_process(delta):
if Engine.editor_hint:
return
if is_network_master():
var adj_position := current_ship_position+current_ship_subpos
if current_ship_target != null:
var distance := adj_position.distance_to(current_ship_target)
if distance > NO_SPEED_THRESHOLD:
ship_direction = current_ship_target.angle_to_point(adj_position)
var max_speed := get_max_speed()
if max_speed > 0:
var deceleration_time = current_ship_speed / (MAX_ACCELERATION * max_speed)
if current_ship_speed * deceleration_time < distance:
ship_speed = max_speed
else:
ship_speed = 0.0
else:
ship_speed = 0.0
rset("pup_ship_direction", ship_direction)
rset("pup_ship_speed", ship_speed)
else:
ship_speed = 0.0
rset("pup_ship_speed", ship_speed)
if current_ship_speed > EPSILON:
var pos_delta: Vector2 = (Vector2.RIGHT * current_ship_speed * delta).rotated(current_ship_direction)
current_ship_subpos += pos_delta
if current_ship_subpos.x >= 1.0:
var int_part := floor(current_ship_subpos.x)
current_ship_position.x += int_part
current_ship_subpos.x -= int_part
if current_ship_subpos.y >= 1.0:
var int_part := floor(current_ship_subpos.y)
current_ship_position.y += int_part
current_ship_subpos.y -= int_part
rset("pup_ship_position", current_ship_position)
rset("pup_ship_subpos", current_ship_subpos)
if not warp_state and current_ship_speed > 0.05:
# Engage FTL
rpc("warp_enter")
elif warp_state and current_ship_speed < 0.02:
# Diseangage FTL
rpc("warp_exit")
else:
ship_speed = 0.0
rset("pup_ship_speed", ship_speed)
else:
ship_direction = pup_ship_direction
ship_speed = pup_ship_speed
current_ship_position = pup_ship_position
current_ship_subpos = pup_ship_subpos
func get_engine_count() -> int:
var working_engines := 0
for child in $engines.get_children():
var engine := child as GameObjectEngine
if engine.force > 0:
working_engines += 1
return working_engines
func get_max_speed() -> float:
var max_speed := 0.0
for child in $engines.get_children():
var engine := child as GameObjectEngine
max_speed += engine.force
return max_speed
# Serialization / Deserialization
func serialize() -> Dictionary:
# Get tilemap data
var tilemapdata := {}
for tilemap in tilemaps:
var data := []
for cell in tilemap.get_used_cells():
data.append([cell, tilemap.get_cellv(cell)])
tilemapdata[tilemap.name] = data
return {
"tilemaps": tilemapdata,
"engines": serialize_children($engines),
"objects": serialize_children($objects),
"lights": serialize_children($lights),
"sockets": serialize_children($sockets),
"pois": serialize_children($pois),
"areas": serialize_children($areas),
"ship": {
"position": current_ship_position,
"target": current_ship_target,
"set_speed": ship_speed,
"set_direction": ship_direction,
"speed": current_ship_speed,
"direction": current_ship_direction
}
}
func deserialize(data: Dictionary) -> void:
# Create maps
for tilemap in data["tilemaps"]:
var tilemap_node = get_node(tilemap) as TileMap
for tile in data["tilemaps"][tilemap]:
tilemap_node.set_cellv(tile[0], tile[1])
tilemap_node.update_bitmask_region()
tilemap_node.update_dirty_quadrants()
# Create objects
deserialize_children($engines, data["engines"])
deserialize_children($objects, data["objects"])
deserialize_children($lights, data["lights"])
deserialize_children($pois, data["pois"])
deserialize_children($sockets, data["sockets"])
deserialize_children($sockets, data["sockets"])
deserialize_children($areas, data["areas"], true)
# Set ship parameters
current_ship_position = data["ship"]["position"]
current_ship_target = data["ship"]["target"]
ship_speed = data["ship"]["set_speed"]
ship_direction = data["ship"]["set_direction"]
current_ship_speed = data["ship"]["speed"]
current_ship_direction = data["ship"]["direction"]
# Run autotile conversions and generate occlusions
$tiles/walls.run_conversions()
func serialize_children(node: Node) -> Dictionary:
var data := {}
for child in node.get_children():
data[child.name] = {
"filename": child.filename,
"data": child.serialize(),
"transform": child.transform
}
return data
func deserialize_children(node: Node, data: Dictionary, deserialize_first: bool = false) -> void:
for node_name in data:
var node_data := data[node_name] as Dictionary
var node_scene = load(node_data.filename).instance()
node_scene.name = node_name
node_scene.transform = node_data.transform
if deserialize_first:
node_scene.deserialize(node_data.data)
node.add_child(node_scene, true)
if not deserialize_first:
node_scene.deserialize(node_data.data)
# Lighting
func set_unlit(val: bool):
unlit = val
if darkness:
darkness.visible = not val
# Engine related functions
func set_engine_strength(val: float):
# Set energy strength to current speed
for child in $engines.get_children():
if child is GameObjectEngine:
var engine := child as GameObjectEngine
engine.strength = val
remotesync func warp_enter():
$deepspace/AnimationPlayer.play("warp-enter")
warp_state = true
remotesync func warp_exit():
$deepspace/AnimationPlayer.play("warp-exit")
warp_state = false
# Tileset related functions
func make_electric_probes(tilemap: TileMap, tile_name: String):
var tile_id := tilemap.tile_set.find_tile_by_name(tile_name)
for cell in tilemap.get_used_cells_by_id(tile_id):
var coord := tilemap.map_to_world(cell)
var probe := ProbeElectricity.instance()
probe.position = coord
tilemap.add_child(probe)
func get_pois(type_filter, class_filter) -> Array:
var filtered := []
for child in $pois.get_children():
if type_filter != null and child.poitype != type_filter:
continue
if class_filter != null and child.poiclass != class_filter:
continue
filtered.append(child)
return filtered