Best Practice for Player-Spawn-Points

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?

Have a nice weekend!

1 Like

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)?

1 Like

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.


My code:

-- 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.

2 Likes

Thanks for your answer!

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

Bildschirmfoto 2024-04-29 um 21.33.24