I can't get ground contact to work

I’m using Defold 1.6.2 (installed on a computer that is not mine). I’ve been following a tutorial by Unfolding Gamedev on YouTube, and I’ve managed to get the gravity to work in my game, but my player continues to fall through the map.

Here is the code if it helps:

local DIRECTION_RIGHT = 1
local DIRECTION_LEFT = -1
local BASE_VELOCITY = 500
local GRAVITY = 100

function init(self)
	msg.post("#", "acquire_input_focus")

	self.velocity = vmath.vector3(0, 0, 0)
	self.ground_contact = false
end

function walk(self)
	self.velocity.x = BASE_VELOCITY * self.direction
end

function flip(direction)
	sprite.set_hflip("#sprite", direction < 0)
end

function animate(action)
	if action.pressed then
		sprite.play_flipbook("#sprite", "run")
	elseif action.released then
		sprite.play_flipbook("#sprite", "idle")
	end
end

local function clamp(v, min, max)
	if v < min then return min
	elseif v > max then return max
	else return v
	end
end

function fixed_update(self, dt)
	--gravity
	self.velocity.y = self.velocity.y - GRAVITY * dt
	self.velocity.y = clamp(self.velocity.y, -2000, 2000)

	if self.ground_contact then
		self.velocity.y = 0
	end
	
	local position = go.get_position()
	position = position + self.velocity * dt
	go.set_position(position)

	self.velocity.x = 0
end

function on_message(self, message_id, message, sender)
	if (message_id == hash("contact_point_response")) 
	and message.other_group == hash("level") then
		self.ground_contact = true
		self.velocity.y = 0
	end
end

function on_input(self, action_id, action)
	animate(action)
	self.direction = (action_id == hash("right")) and DIRECTION_RIGHT or DIRECTION_LEFT
	walk(self)
	flip(self.direction)
end

Are you getting calls to on_message() and pass the conditional checks? You can add a print(“ground contact”) to check, or set a breakpoint using the debugger.

i think the issue is with ground contact in your code might be in the on_message function.

Maybe a silly question but have you added a collsion object to the ground?

Ok, so I actually realised the issue was that the hash for message.other_group needed to be map not level, which fixed the issue, but now that I’ve added this code to my actual game and not the prototype I was working on, the spacebar no longer works and I don’t know why

I fixed that issue as well, I hadn’t gone into the game project to turn on Use Fixed Timestep. Once I did that, the spacebar allowed the player to jump. Now however, the gravity no longer works to allow the player to fall back down without having changed any of the code.

Every time I post here I keep finding solutions to the issue soon after, so I’m going to continue to update here. Part of the issue was that the collision box in the game when I turned on the physics debugging was huge, so the player was constantly in contact with the ground, so self.velocity.y was always being set to 0. Now that I have massively reduced the size of the collision box, the player can fall, but only sometimes, as the debugger thinks that the player is almost constantly in contact with the ground. I do not know how to fix this.

1 Like

Rubber ducking, excellent strategy.

2 Likes

Thank you, I’m glad someone else is appreciating this ¦ )

Ok. So as it stands, the issue there was that I actually had not coded in level collisions, which I have now done by rewatching the videos I was following. However, as it currently stands, I think my code is identical to the code I was following, but the character is falling part-way through the platform it should be landing on (including the literal ground). Can anyone see an issue with this code?

function handle_level_collisions(self, normal, distance)
	--stops player from landing slightly in the platforms or floor
	distance = distance * vmath.length(normal) --normal distance compensation

	if distance > 0 then
		--project accumulated correction onto the penetration vector
		local projection = vmath.project(self.correction, normal * distance)
		if projection < 1 then --exclude overshoot projection
			local compensation = (distance - distance * projection) * normal
			go.set_position(go.get_position() + compensation) --apply instantly
			self.correction = self.correction + compensation
		end
	end
	
	--wall on left or right
	if math.abs(normal.x) > 0 then
		self.velocity.x = 0
	end
	
	--when on the ground
	if normal.y > 0 then
		self.ground_contact = true
		self.velocity.y = 0
	end

	--hitting a platform
	if normal.y < 0 then
		self.velocity.y = 0
	end
end

Hey, I didn’t check your code but after the description of what’s happening, I think it COULD be caused by not setting the right physics scale in the project settings, check out this doc:
https://defold.com/manuals/physics/#units-used-by-the-physics-engine-simulation

What do you mean by not using the right scale?

There’s a setting physics scale in your game.project file. It’s value should be set to a number depending on the size of the collision objects that you’re using in your game. I think it’s fairly well explained in this doc that I linked to (just the section “Units used by the physics engine simulation”).