Ball pass through collision object ground

Hi, I am practicing to a game. I have a ball and a ground. Both of them have collisionobject kinematicly, i made it kinematic because they are moving. Anyway, I make the ball jump and when it touches ground it should stop. However, sometimes it stops instantly and sometimes it passes through the ground. Here an example video and the code block that I wrote. Waiting for your help. Thanks.

local gravity = -70
local jump_takeoff_speed = 1500

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

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

function final(self)
	msg.post(".", "release_input_focus") 
end

function update(self, dt)
	local gravity = vmath.vector3(0, gravity, 0)
	if not self.ground_contact then
		self.velocity = self.velocity + gravity
		go.set_position(go.get_position() + self.velocity * dt)
	end
	if self.is_jumping then
		go.set_position(go.get_position() + self.velocity * dt)
	end
	self.ground_contact = false
	self.is_jumping = false
end

function on_message(self, message_id, message, sender)
	if message_id == hash("collision_response") then
		self.ground_contact = true
	end
end

local function jump(self)
	-- only allow jump from ground
	if self.ground_contact then
		self.velocity.y = jump_takeoff_speed
		self.is_jumping = true
	end
end

local function abort_jump(self)
	-- cut the jump short if we are still going up
	if self.velocity.y > 0 then
		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

In the platformer tutorial there’s a little script to handle kinematic collisions. As long as you don’t use tilemaps you’ll be alright.

local msg_contact_point_response = hash("contact_point_response")
local group_obstacle = hash("obstacle")

function handle_obstacle_contact(self, normal, distance)
	local proj = vmath.dot(self.correction, normal)
	local comp = (distance - proj) * normal
	self.correction = self.correction + comp
	go.set_position(go.get_position() + comp)

	if normal.y > 0.7 then
		self.ground_contact = true
	end

	proj = vmath.dot(self.velocity, normal)
	if proj < 0 then
		self.velocity = self.velocity - proj * normal
	end
end

function on_message(self, message_id, message, sender)
	if message_id == msg_contact_point_response then
		if message.group == group_obstacle then
			handle_obstacle_contact(self, message.normal, message.distance)
		end
	end
end

Kinematic means that you have to deal with collisions in code. Dynamic means that the physics engine solves collisions for you. See https://www.defold.com/manuals/physics/

I solve the problem little bit but not completely… Still have problems like jumping between grounds. I have multiple grounds and the ball can jump to others. Not everytime but sometimes still goes down level of the ground. I used this script. Also, when the ball comes end of the ground (left or right side) instantly drops so it means that player can not jump limit of the grounds. I do not know that if I explained the problem clearly. Any idea?

	if message_id == hash("contact_point_response") and not self.is_fixed then
		-- Fixing level problems
		local y_fix = vmath.vector3(0, message.normal.y, 0)
		local newpos = go.get_position() + y_fix * message.distance
		go.set_position(newpos)
		--
	end

if you print your self.velocity.y you will see that the y coordinate keeps decreasing which is why your ball keeps sinking.

1 Like