Enemy always falling through the level

I’m making an enemy npc and currently coding it to move between 2 walls in the game. I’ve written code that should cause it to hit the floor which is the level and then be in its idle animation (which is set to default). When the game runs there are no errors but everytime the npc falls through the level. Ive attached the enemy code, are there any logic errors in it, or can you help me tack where this error is coming from??


It would be better if you put your code between code fences so that people can easily read it, scroll through it and try it out.
Like so:

1 Like
local move_acceleration = 100
local max_speed = 50
local gravity = -1000
local ground_contact = false
local wall_contcat = false

local msg_contact_point_response = hash("contact_point_response")
local msg_animation_done = hash("animation_done")
local group_obstacle = hash("floor")
local group_wall = hash("walls")
local anim_walk = hash("run")
local anim_idle = hash("idle")
local anim_hit = hash("hit")
local anim_attack = hash("attack")


function init(self)
	self.velocity = vmath.vector3(0,0,0)
	self.movement = 1
	self.anim = nil
	
end

function final(self)
	-- Add finalization code here
	-- Learn more: https://defold.com/manuals/script/
	-- Remove this function if not needed
end

function update(self, dt)
	local target_speed = self.movement * max_speed
	local speed_diff = target_speed * self.velocity.x
	local acceleration = vmath.vector3(0,gravity,0)

	if (speed_diff ~= 0) then
		if (speed_diff < 0) then
			acceleration.x = -move_acceleration
		else
			acceleration.x = move_acceleration
		end
	end

	local dv = acceleration * dt 
	if (math.abs(dv.x) > math.abs(speed_diff)) then
		dv.x = speed_diff
	end

	local v0 = self.velocity
	self.velocity = self.velocity + dv
	local dp = (v0 + self.velocity) * dt
	go.set_position(go.get_position() + dp)

	self.correction = vmath.vector3()
	self.ground_contact = false 
	self.wall_contact = false

end

local 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 fixed_update(self, dt)
	-- This function is called if 'Fixed Update Frequency' is enabled in the Engine section of game.project
	-- Can be coupled with fixed updates of the physics simulation if 'Use Fixed Timestep' is enabled in Physics section of game.project
	-- Add update code here
	-- Learn more: https://defold.com/manuals/script/
	-- Remove this function if not needed
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

function on_input(self, action_id, action)
	-- Add input-handling code here. The game object this script is attached to
	-- must have acquired input focus:
	--
	--    msg.post(".", "acquire_input_focus")
	--
	-- All mapped input bindings will be received. Mouse and touch input will
	-- be received regardless of where on the screen it happened.
	-- Learn more: https://defold.com/manuals/input/
	-- Remove this function if not needed
end

function on_reload(self)
	-- Add reload-handling code here
	-- Learn more: https://defold.com/manuals/hot-reload/
	-- Remove this function if not needed
end
1 Like

Had a quick look and spotted a typo in the message function:
“message_group” should read “message.group”.

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

Does it work now?

3 Likes

Yes it works now, thank you soo much it really is appreciated :))

2 Likes

Devs - help please, I accidently flagged the penultimate post. :flushed: Ah - flag seems to be gone. :grinning:

I now have a problem where the enemy will load in but will not move as it should. Instead it stays in the idle position stationary. When i removed the brackes from the first 2 if statements in the update function the enemy did move but when i ran the game again it went back to staying stationary again. Do you know what the problem may be???

local move_acceleration = 100
local max_speed = 50
local gravity = -1000
local ground_contact = false
local wall_contcat = false

local msg_contact_point_response = hash("contact_point_response")
local msg_animation_done = hash("animation_done")
local group_obstacle = hash("floor")
local group_wall = hash("walls")
local anim_walk = hash("run")
local anim_idle = hash("idle")
local anim_hit = hash("hit")
local anim_attack = hash("attack")


function init(self)
	self.velocity = vmath.vector3(0,0,0)
	self.movement = 1
	self.anim = nil
	
end

function final(self)
	-- Add finalization code here
	-- Learn more: https://defold.com/manuals/script/
	-- Remove this function if not needed
end

function update(self, dt)
	local target_speed = self.movement * max_speed
	local speed_diff = target_speed - self.velocity.x
	local acceleration = vmath.vector3(0, gravity,0)

	if speed_diff ~= 0 then
		if speed_diff < 0 then
			acceleration.x = -move_acceleration
		else
			acceleration.x = move_acceleration
		end
	end

	local dv = acceleration * dt 
	if (math.abs(dv.x) > math.abs(speed_diff)) then
		dv.x = speed_diff
	end

	local v0 = self.velocity
	self.velocity = self.velocity + dv
	local dp = (v0 + self.velocity) * dt
	go.set_position(go.get_position() + dp)

	self.correction = vmath.vector3()
	self.ground_contact = false 
	self.wall_contact = false

end

local 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 fixed_update(self, dt)
	-- This function is called if 'Fixed Update Frequency' is enabled in the Engine section of game.project
	-- Can be coupled with fixed updates of the physics simulation if 'Use Fixed Timestep' is enabled in Physics section of game.project
	-- Add update code here
	-- Learn more: https://defold.com/manuals/script/
	-- Remove this function if not needed
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

function on_input(self, action_id, action)
	-- Add input-handling code here. The game object this script is attached to
	-- must have acquired input focus:
	--
	--    msg.post(".", "acquire_input_focus")
	--
	-- All mapped input bindings will be received. Mouse and touch input will
	-- be received regardless of where on the screen it happened.
	-- Learn more: https://defold.com/manuals/input/
	-- Remove this function if not needed
end

function on_reload(self)
	-- Add reload-handling code here
	-- Learn more: https://defold.com/manuals/hot-reload/
	-- Remove this function if not needed
end

1 Like

As far as I can tell, the code pulls the enemy downwards, but doesn’t move him in the x direction. There is also no code in the input function to move the enemy around. Do I understand you correctly: you would like the enemy to constantly move left or right between walls until he hits a wall and then turns? I think there is code for this somewhere on the forum. I haven’t written such code myself, but can have a look tomorrow if you haven’t got an answer by then.

Edit: found this video - would this help?DEFOLD Game Engine TUTORIAL #02: Implementing the ENEMY MOVEMENT & ANIMATIONS - YouTube

that’s the video i’m using as a guide, and the code i have copied is the code from the video, so i’m not really sure what to do. If you want you can look at the video to see if i’ve missed anything :slight_smile:

Ok - I’ll have a look for you tomorrow if possible. If you like, could you upload your project so I don’t have to reproduce it myself (and maybe spot sth in your setup) - in a pm if you prefer.

I’ve just been messing around with it now, and every now,and again it will move but this seems almost completly random usually every 3 - 8 times i build the game it moves lmao

Interesting - well, sth is amiss. Still, looking at what you have done so far in your project files would help to find the problem. So, it would be great if you could share the project.
I must be off now.
Edit: ah, you just did - great.