PirateTreasureHunt/scenes/Island.gd

245 lines
6.8 KiB
GDScript

extends Node2D
var tiles = {}
var offset_world = Vector2.ZERO
var center_coord = Vector2.ZERO
var center_world_coord = Vector2.ZERO
var rect_local = Rect2()
var rect_world = Rect2()
var radius_world = 0.0
var is_active = false
var landing_site_local_coord = null
var landing_site_world = null
var obstacles_local_coords = {}
var treasure_local_coords = null
var highlight_treasure = false
var prerender_texture = null
var render_sprite = null
# Called when the node enters the scene tree for the first time.
func _init():
render_sprite = Sprite.new()
add_child(render_sprite)
func set_tile(coord: Vector2, value: String):
if HexTileDrawer.TileTypeFromString[value] == HexTileDrawer.TileType.None:
if coord in tiles.keys():
tiles.erase(coord)
else:
tiles[coord] = value
update()
func set_offset_world(value: Vector2):
offset_world = value
rect_world.position = rect_local.position + value
rect_world.size = rect_local.size
func clear_island():
tiles = {}
update()
func generate_random_walk (length):
var cur_hex_coord = Vector2(0,0)
var i = length
while (i >= 0):
var cur_world_pos = Globals.HexToWorld(cur_hex_coord)
tiles[cur_world_pos] = "Sand"
var neighbours = Globals.HexGrid.get_hex_at(cur_hex_coord).get_all_adjacent()
var exists = true
for j in range (len(neighbours)):
neighbours[j] = neighbours[j].axial_coords
var rand_idx = randi() % 6
cur_hex_coord = cur_hex_coord + neighbours[rand_idx]
i = i - 1
func extrude_island():
var old_tiles = tiles
tiles = {}
for tile in old_tiles:
var hex_coord = Globals.WorldToHex(tile)
tiles[tile] = "Sand"
var neighbours = Globals.HexGrid.get_hex_at(hex_coord).get_all_adjacent()
for cell in neighbours:
var world_coord = Globals.HexToWorld(hex_coord + cell.axial_coords)
tiles[world_coord] = "Sand"
func mark_grass():
var old_tiles = tiles
tiles = {}
for tile in old_tiles:
var hex_coord = Globals.WorldToHex(tile)
var neighbours = Globals.HexGrid.get_hex_at(hex_coord).get_all_adjacent()
var is_center_cell = true
for cell in neighbours:
var world_coord = Globals.HexToWorld(hex_coord + cell.axial_coords)
if not world_coord in old_tiles.keys():
is_center_cell = false
if is_center_cell:
tiles[tile] = "Grass"
else:
tiles[tile] = "Sand"
func generate():
var size = 62
generate_random_walk(size)
extrude_island()
mark_grass()
calc_bbox()
update()
func calc_bbox():
var coord_min = Vector2.ONE * 10000
var coord_max = Vector2.ONE * -10000
var coords = tiles.keys()
for coord in coords:
var local_coords = (coord)
if local_coords.x < coord_min.x:
coord_min.x = local_coords.x
if local_coords.y < coord_min.y:
coord_min.y = local_coords.y
if local_coords.x > coord_max.x:
coord_max.x = local_coords.x
if local_coords.y > coord_max.y:
coord_max.y = local_coords.y
var hex_half_size = Vector2 (Globals.hex_size * 0.5, Globals.hex_size * sqrt(3) * 0.25)
rect_local = Rect2(coord_min - hex_half_size, coord_max - coord_min + hex_half_size * 2)
center_world_coord = Globals.HexToWorld(Globals.WorldToHex(coord_min + 0.5 * (coord_max - coord_min)))
center_coord = Globals.WorldToHex(center_world_coord)
print ("center coord: " + str(center_coord))
radius_world = max(rect_local.size.x, rect_local.size.y) * 0.5
# brute force the bbox tiles
obstacles_local_coords = {}
var dx = Globals.hex_size * 0.5
var dy = Globals.hex_size * 0.5
var n_tiles_x = (rect_local.size.x + Globals.hex_size * 2) / dx
var n_tiles_y = (rect_local.size.y + Globals.hex_size * 2) / dy
for r in range (n_tiles_y):
for c in range (n_tiles_x):
var point_hex_local = Globals.WorldToHexCenter(Vector2(rect_local.position.x+ c * dx, rect_local.position.y + r * dy) - Vector2.ONE * Globals.hex_size * 0.5)
if not obstacles_local_coords.has(point_hex_local) and not tiles.has(point_hex_local):
obstacles_local_coords[point_hex_local] = "#bb44aa"
func save_island(path: String):
var island_save_data = File.new()
island_save_data.open(path, File.WRITE)
island_save_data.store_line (to_json(tiles))
island_save_data.close()
func load_island(path: String):
var island_save_data = File.new()
if !island_save_data.file_exists(path):
clear_island()
return
island_save_data.open(path, File.READ)
var data = parse_json(island_save_data.get_line())
island_save_data.close()
var data_keys = data.keys()
tiles = {}
var coord_regex = RegEx.new()
coord_regex.compile("\\((?<tile_x>-?\\d+(.?\\d+)?), (?<tile_y>-?\\d+(.?\\d+)?)\\)")
var reg_test_result = coord_regex.search("(0, 0)")
assert(reg_test_result)
reg_test_result = coord_regex.search("(123.124, 552.0)")
assert(reg_test_result)
for k in data_keys:
var coords = Vector2.ZERO
var regresult = coord_regex.search(k)
if regresult:
# print(regresult.get_string("tile_x"), " - ", regresult.get_string("tile_y"))
coords = Vector2(float(regresult.get_string("tile_x")), float(regresult.get_string("tile_y")))
tiles[coords] = data[k]
name = path
calc_bbox()
update()
func check_overlap(other):
var rect_world = calc_rect_world()
var rect_world_other = other.calc_rect_world()
return rect_world.intersects(rect_world_other)
func get_tile_by_world_coord(world_coord: Vector2):
var local_coord = get_local_coord_by_world_coord(world_coord)
if local_coord in tiles.keys():
return tiles[local_coord]
return null
func is_point_on_treasure_site(world_coord: Vector2):
var local_coord = get_local_coord_by_world_coord(world_coord)
return treasure_local_coords != null and local_coord == treasure_local_coords
func is_point_on_landing_site(world_coord: Vector2):
return (Globals.WorldToHex(world_coord) - Globals.WorldToHex(landing_site_world)).length_squared() < 1
func get_local_coord_by_world_coord(world_coord: Vector2):
return Globals.WorldToHexCenter(world_coord - offset_world)
func calc_rect_world():
var rect_world = Rect2(rect_local)
rect_world.position = transform.origin + rect_world.position + offset_world
return rect_world
func draw_bsphere():
var transform = get_transform()
draw_set_transform(transform.origin + offset_world, transform.get_rotation(), transform.get_scale())
draw_circle(center_world_coord, radius_world, Color("#80000033"))
draw_circle(center_world_coord, 10, Color.red)
func _draw():
var transform = get_transform()
for coord in tiles.keys():
draw_set_transform (coord + offset_world, 0, Vector2.ONE)
draw_polygon(HexTileDrawer.HexPoints, HexTileDrawer.get_tile_color(tiles[coord]))
if highlight_treasure and treasure_local_coords:
draw_set_transform (treasure_local_coords + offset_world, 0, Vector2.ONE)
draw_polygon(HexTileDrawer.HexPoints, HexTileDrawer.create_color_array("#922"))
if Globals.draw_island_bbox:
# draw_set_transform(transform.origin, transform.get_rotation(), transform.get_scale())
draw_rect(rect_world, Color.red, false)