(Runner Tutorial) Disabling the #collisionobject for only the platforms when the character dies

So I have reached the stage to program the character to die on collision with the edge of the platforms with spikes but I didn’t want to use spikes on my own game so what I did was divide the collision objects on each platform into two one for the geometry group and one for the death group but after referencing from the code in the runner tutorial the collision objects get disabled and the character falls through the floor I would just like to disable the collision object for everything but the ground since I’m already working on a tumble animation for when the character dies here is my character script:

    -- gravity pulling the player down in pixel units/sˆ2
    local gravity = -40

    -- take-off speed when jumping in pixel units/s
    local jump_takeoff_speed = 450
    -- prehashing improves performance
    local anim_run = hash("run")
    local anim_fall = hash("fall")
    local anim_frontflip = hash("frontflip")
    local anim_jump = hash("jump")

    function init(self)
    	-- this tells the engine to send input to on_input() in this script
    	msg.post(".", "acquire_input_focus")

    	-- save the starting position
    	self.position = go.get_position()

    	-- keep track of movement vector and if there is ground contact
    	self.velocity = vmath.vector3(0, 0, 0)
    	self.ground_contact = false
    	self.anim = nil
    	self.ceiling_contact = false
    	
    end

    function final(self)
    	-- Return input focus when the object is deleted
    	msg.post(".", "release_input_focus")
    end
    local function play_animation (self, anim)
    	--only play animations which are not already playing
    	if self.anim ~= anim then
    		sprite.play_flipbook("#sprite", anim)
    		--remember which animation is playing
    		self.anim = anim
    	end
    end
    local function update_animations(self)
    	if self.ground_contact then
    		play_animation(self, anim_run)
    else
    	if self.velocity.y > 0 then
    		play_animation(self, anim_frontflip) 
    	else
    		play_animation(self, anim_fall)
    		end
    	end
    end


    function update(self, dt)
    	local gravity = vmath.vector3(0, gravity, 0)

    	if not self.ground_contact then
    		if self.ceiling_contact then
    		-- Apply gravity if there's no ground contact
    		self.velocity = self.velocity + gravity
    	end
    end
    	-- apply velocity to the player character
    	go.set_position(go.get_position() + self.velocity * dt)

    	-- called update_animation(self) to change player animations with state
    	update_animations(self)

    	-- reset volatile state
    	self.correction = vmath.vector3()
    	self.ground_contact = false
    	self.ceiling_contact = true
    end

    local function handle_geometry_contact(self, normal, distance)
    	-- project the correction vector onto the contact normal
    	-- (the correction vector is the 0-vector for the first contact point)
    	local proj = vmath.dot(self.correction, normal)
    	-- calculate the compensation we need to make for this contact point
    	local comp = (distance - proj) * normal
    	-- add it to the correction vector
    	self.correction = self.correction + comp
    	-- apply the compensation to the player character
    	go.set_position(go.get_position() + comp)
    	-- check if the normal points enough up to consider the player standing on the ground
    	-- (0.7 is roughly equal to 45 degrees deviation from pure vertical direction)
    	if normal.y > 0.7 then
    		self.ground_contact = true
    	end
    	if normal.y < 0.7 then
    		self.ceiling_contact = true
    	end
    	-- project the velocity onto the normal
    	proj = vmath.dot(self.velocity, normal)
    	-- if the projection is negative, it means that some of the velocity points towards the contact point
    	if proj < 0 then
    		-- remove that component in that case
    		self.velocity = self.velocity - proj * normal
    	end
    end

    function on_message(self, message_id, message, sender)
    	if message_id == hash("reset") then
    		self.velocity = vmath.vector3(0, 0, 0)
    		self.correction = vmath.vector3()
    		self.ground_contact = false
    		self.anim= nil
    		go.set(".", euler.z, 0)
    		go.set_position(self.position)
    		msg.post("#collisionobject", "enable")

    	elseif message_id == hash("contact_point_response") then
    		-- check if we received a contact point message. One message for each contact point
    		if message.group == hash("death") then
    			--die and restart
    			msg.post("#collisionobject", "disable")
    			go.animate(".", "euler.z", go.PLAYBACK_ONCE_FORWARD, 160, go.EASING_LINEAR, 0.7)
    		go.animate(".", "position.y", go.PLAYBACK_ONCE_FORWARD, go.get_position().y - 200, go.EASING_INSINE, 0.5, 0.2,
    		function()
    			msg.post("#", "reset")
    		end) 
    		if message.group == hash("geometry") then
    			handle_geometry_contact(self, message.normal, message.distance)
    			if message_id == hash("set_speed") then -- <1>
    				self.speed = message.speed -- <2>
    			end
    		end
    	end
    end


    local function jump(self)
    	-- enable "if self.ground_contact then" to allow jumps from ground
    		-- set take-off speed
    		self.velocity.y = jump_takeoff_speed
    end
    	local function abort_jump(self)
    	-- cut the jump short if we are still going up
    	if self.velocity.y > 0 then
    		-- scale down the upwards speed
    		self.velocity.y = self.velocity.y * 0.5
    		end
    	end
    function on_input(self, action_id, action)
    	if action_id == hash("jump") or action_id == hash("touch") then
    		if action.pressed then
    			jump(self) 
    		elseif action.released then
    			abort_jump(self)
    		end
    	end
    end

This is the way to disable a component. In this case it is the component with id collisionobject on the player. But in your case I’d probably skip disabling collision components. I’d start by setting a different collision group on the ground (instead of geometry I’d call it ground). Next I’d expand what you do in the elseif where you check for contact_point_response:

When the player dies I’d set a flag:

self.dead = true

And I would ignore further collisions with death and geometry but still react to collisions with ground. Something like this:

elseif message_id == hash("contact_point_response") then
	-- ignore further collisions with "death" if already dead
	if not self.dead and message.group == hash("death") then
		--die and restart
		self.dead = true
		go.animate(".", "euler.z", go.PLAYBACK_ONCE_FORWARD, 160, go.EASING_LINEAR, 0.7)
		go.animate(".", "position.y", go.PLAYBACK_ONCE_FORWARD, go.get_position().y - 200, go.EASING_INSINE, 0.5, 0.2, function()
			msg.post("#", "reset")
		end) 
	-- ignore collisions with "geometry" if dead
	elseif not self.dead and message.group == hash("geometry") then
		handle_geometry_contact(self, message.normal, message.distance)
		if message_id == hash("set_speed") then
			self.speed = message.speed
		end
	-- always check for collisions with "ground"
	elseif message.group == hash("ground") then
		handle_geometry_contact(self, message.normal, message.distance)
		if message_id == hash("set_speed") then
			self.speed = message.speed
		end
	end
end

i did this and now the character doesn’t respond to touch or jump commands

It’s hard to say what’s wrong. My guess is that you haven’t set up the player to collide with the new group “ground”.

Use print debugging and add print() statements inside the elseif message_id == hash("contact_point_response") then and see what happens.

Or set a breakpoint and use the debugger.

Thanks, i did this and ended up redoing the “function on_message” and it works fine now

3 Likes