Hey everyone, is there a ‘best practice’ solution for determining the player’s spawn position? The situation is as follows: I have a large overworld and various houses that I switch to via proxy. Now each ‘level’ must have an entry spawnpoint. The overworld also has several spawn points. I think my problem is something very common… How do you solve it?
Sure, it is a common problem, and there’s probably hundreds of different solutions. But each solution depends on many game specific factors, so it’s hard to give general advice.
You only mention “large overworld with houses”. Can the spawn point be random? If not, why? What are the constraints you have? Does it have to be close to something else? If so what? Or perhaps the spawn point can’t be close to something (an enemy spawn point, or the level exit)?
That’s right, sorry, I should probably have explained it in more detail. The player’s spawn points are always fixed points in the world/levels. There can be several spawn points. However, a fixed spawn point is always used. When you start the game, you arrive at the start spawn point. If you walk into a house, you enter the ‘House-Inside-Spawn Point’. When you leave the house, you are placed in the overworld at the ‘House outside spawn point’. I have attached two screenshots.
-- From the Player (collision):
if message.group == hash("portal") then
msg.post(message.other_id, "level_change")
end
--In my Level (for example Overworld):
if message_id == hash("level_change") then
msg.post("game:/levels", "level_house")
end
-- In my handle_levels.script:
if message_id == hash("level_overworld") then
constants.set_level_id("overworld")
msg.post("levels#house", "unload")
msg.post("levels#overworld", "load")
elseif message_id == hash("level_ house") then
constants.set_level_id("house")
msg.post("levels#overworld", "unload")
msg.post("levels#house", "load")
elseif message_id == hash("proxy_loaded") then
msg.post(sender, "enable")
end
Given your scenario, I would simply store the url of the spawn point I would wish to exit to.
E.g. if you’re in the caves, with multiple exits, I would associate each exit with a url (or other type of ID) to figure out where to move the player to once the collection proxy is loaded.
Can I then use a game object as a ‘spawn point’, or is that rather unusual?
I haven’t quite understood the ‘associate’ thing yet.
I’ve tried writing down my thoughts as code, it all still feels a bit static, but maybe that’s still a good solution for me:
--Player.script
if message.group == hash("portal") then
msg.post(message.other_id, "level_change")
end
--Map Script (e.g. from the house):
function on_message(self, message_id, message, sender)
if message_id == hash("level_change") then
msg.post("game:/levels", "level_overworld", {spawnpoint = "sp_came_from_house"})
end
end
--Level_handler.script:
function on_message(self, message_id, message,sender)
if message_id == hash("level_overworld") then
msg.post("levels#osteria", "unload")
msg.post("levels#overworld", "load")
msg.post("/common/player", "set_position", {spawnpoint = message.spawnpointurl})
elseif message_id == hash("level_osteria") then
msg.post("levels#overworld", "unload")
msg.post("levels#osteria", "load")
msg.post("/common/player", "set_position", {spawnpoint = message.spawnpointurl})
elseif message_id == hash("proxy_loaded") then
msg.post(sender, "enable")
end
end
-- Player
if message.group == hash("set_position") then
local spawnposition = go.get_position(message.spawnpoint)
go.set_position(spawnposition)
end
Okay, I think I have a solution. For all those who are facing a similar problem:
In my level handler I set the current level_id and which spawn_point (object name) should be taken. I pass this as a message to the player. I then use the spawn (game) object ID to get the position and then set the player to the same position.
Level Handler:
function init(self)
-- Input Focus muss durchgereicht werden
msg.post(".", "acquire_input_focus")
msg.post("levels#overworld", "load")
constants.set_level_id("overworld")
spawn_point = "sp_game_entry"
end
function final(self)
msg.post(".", "release_input_focus")
end
function on_message(self, message_id, message,sender)
if message_id == hash("level_overworld") then
constants.set_level_id("overworld")
spawn_point = "sp_osteria_out"
msg.post("levels#osteria", "unload")
msg.post("levels#overworld", "load")
elseif message_id == hash("level_osteria") then
constants.set_level_id("osteria")
spawn_point = "sp_osteria_in"
msg.post("levels#overworld", "unload")
msg.post("levels#osteria", "load")
elseif message_id == hash("proxy_loaded") then
msg.post(sender, "init")
msg.post(sender, "enable")
msg.post(constants.LEVEL_ID..":/common/player", "set_spawn_position", {spawn_point = spawn_point})
end
end
Player:
if message_id == hash("set_spawn_position") then
set_spawn_position(self, message.spawn_point)
end
local function set_spawn_position(self, spawn_point)
local sp_path = constants.LEVEL_ID..":/"..spawn_point
local sp_position = go.get_position(sp_path)
-- Setze Player Position
go.set_position(sp_position)
end