So what you're doing is making a TileSet whose tile types represent game objects, while your levels have a TileMap using this TileSet where you draw the game object tiles on. Then when the level loads this game object TileMap is used to load the real game objects and set their positions.
One drawback is having to update the game object TileSet everytime I add a new game object or modify a game object's appearance. I also plan on having multi-tile game objects (e.g. a dragon that's 2x2 tiles) and I'm not sure if a TileSet can support such a tile type.
Meanwhile, I've recently tried making a "tile object" editor plugin. There's a main tile object script with tile position properties that update its true position, and an editor plugin to handle its positioning in the editor.
# tile_object.gd
tool
extends Node2D
# Base size of tiles in pixels
export(Vector2) var tile_size = Vector2(16, 16) setget set_tile_size
# Dimensions of object in tiles
export(Vector2) var tile_dimensions = Vector2(1, 1) setget set_tile_dimensions
# Position of object in tiles
# Origin is top-left
export(Vector2) var tile_pos = Vector2(0, 0) setget set_tile_pos
func _ready():
if get_parent() is TileMap:
set_tile_size(get_parent().cell_size)
var tile = position / tile_size
set_tile_pos(Vector2(round(tile.x), round(tile.y)))
func set_tile_size(value):
tile_size = value
_update_position()
if Engine.editor_hint:
update()
func set_tile_dimensions(value):
tile_dimensions = value
if Engine.editor_hint:
update()
func set_tile_pos(value):
tile_pos = value
_update_position()
func _update_position():
position = tile_pos * tile_size
func _draw():
if Engine.editor_hint:
var rect = Rect2(Vector2(), tile_dimensions * tile_size)
draw_rect(rect, Color(1, 0, 1), false)
# tile_object_plugin.gd
tool
extends EditorPlugin
const TileObject = preload("res://addons/tile_object/tile_object.gd")
var _current = null
func _enter_tree():
add_custom_type("TileObject", "Node2D", TileObject, preload("res://addons/tile_object/tile_object_icon.png"))
func _exit_tree():
remove_custom_type("TileObject")
func handles(object):
return object is TileObject
func edit(object):
if _current != object:
_current = object
func make_visible(visible):
if not visible:
_current = null
func clear():
_current = null
func forward_canvas_gui_input(event):
if _current != null:
if (event is InputEventMouseButton) and (not event.pressed):
assert(_current is TileObject)
var origin_tile = _current.position / _current.tile_size
_current.tile_pos = Vector2(round(origin_tile.x), round(origin_tile.y))
Drawbacks are:
Update's to a TileObject's tile_pos
property caused by dragging doesn't appear in the inspector until I deselect and reselect the TileObject.
Creating a node that subclasses TileObject is awkward. I add a TileObject as a root node, clear its script, and make a new script where I have to make sure I select the plugin script "tile_object.gd" as the parent. Not the type "TileObject", but the actual script inside the addon folder.