Hello,
I don't want to spam the forum with topics but I am in need of assistance. I'm trying to find examples of a script/function that would allow me to have a number of 'enemies' chase the player around a fixed area/room, basically flocking to wherever the player has moved to. I suppose a bit like they do in Geometry Wars. Can anyone point me in the right direction here?
I'm running through the tutorials but can't really find anything that will help me with this, the closest being the Hamster Ball example but obviously that is designed to enact player control rather than NPC movement. I haven't used LUA for 4 years or so and I've basically forgotten everything!
Any help appreciated.
NPC chasing the player
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
- nevon
- Commander of the Circuloids
- Posts: 938
- Joined: Thu Feb 14, 2008 8:25 pm
- Location: Stockholm, Sweden
- Contact:
Re: NPC chasing the player
I'm on my phone, so I'm not gonna give you any example code, but the easiest way to solve it is to simply get the vector between the player and each enemy, and then move the enemy along that vector. Of course you'd have to calculate a new vector each time, as long as the player is moving. This simple approach does not take into account any obstacles or walls. For that, you'd have to take a look at pathfinding algorithms.
- Taehl
- Dreaming in associative arrays
- Posts: 1025
- Joined: Mon Jan 11, 2010 5:07 am
- Location: CA, USA
- Contact:
Re: NPC chasing the player
A couple functions you may want to use:
Then you could do something like this:
Code: Select all
-- Returns the distance between two points.
function math.dist(x1,y1, x2,y2) return ((x2-x1)^2+(y2-y1)^2)^0.5 end
-- Returns the angle between two points
function math.getAngle(x1,y1, x2,y2) return math.atan2(x2-x1, y2-y1) end
-- Averages angles.
function math.averageAngles(...)
local x,y = 0,0
for i=1,select('#',...) do local a= select(i,...) x, y = x+math.cos(a), y+math.sin(a) end
return math.atan2(y, x)
end
Code: Select all
function love.update(dt)
for k,v in ipairs(NPCs) do
local a = math.getAngle(v.x, v.y, player.x, player.y)
v.x = v.x + math.cos(a) * v.speed * dt
v.y = v.y + math.sin(a) * v.speed * dt
end
end
Earliest Love2D supporter who can't Love anymore. Let me disable pixel shaders if I don't use them, dammit!
Lenovo Thinkpad X60 Tablet, built like a tank. But not fancy enough for Love2D 0.10.0+.
Lenovo Thinkpad X60 Tablet, built like a tank. But not fancy enough for Love2D 0.10.0+.
Re: NPC chasing the player
Or you could do it with vectors to avoid trigonometric funtions. Like nevon suggested:Taehl wrote:Then you could do something like this:Code: Select all
stuff
Code: Select all
for _,enemy in ipairs(NPCs) do
-- direction is the vector from the enemy to the player
local direction_x = player.x - enemy.x
local direction_y = player.y - enemy.y
local distance = math.sqrt(direction_x * direction_x + direction_y * direction_y)
if dist ~= 0 then -- avoid division by zero
enemy.x = enemy.x + direction_x / distance * enemy.speed * dt
enemy.y = enemy.y + direction_y / distance * enemy.speed * dt
end
end
Code: Select all
for _,enemy in ipairs(NPCs) do
local direction = player.pos - enemy.pos
enemy.pos = enemy.pos + direction:normalized() * enemy.speed * dt
end
- Taehl
- Dreaming in associative arrays
- Posts: 1025
- Joined: Mon Jan 11, 2010 5:07 am
- Location: CA, USA
- Contact:
Re: NPC chasing the player
Vrld, wouldn't that let enemies move twice as fast diagonally than they could horizontally or vertically?
Earliest Love2D supporter who can't Love anymore. Let me disable pixel shaders if I don't use them, dammit!
Lenovo Thinkpad X60 Tablet, built like a tank. But not fancy enough for Love2D 0.10.0+.
Lenovo Thinkpad X60 Tablet, built like a tank. But not fancy enough for Love2D 0.10.0+.
-
- Prole
- Posts: 9
- Joined: Wed Feb 09, 2011 4:40 pm
Re: NPC chasing the player
Thanks alot guys, I appreciate the help.
- Taehl
- Dreaming in associative arrays
- Posts: 1025
- Joined: Mon Jan 11, 2010 5:07 am
- Location: CA, USA
- Contact:
Re: NPC chasing the player
That vector stuff sounds neat. Would it be faster than using trig?
Also to test my understanding, this would correctly normalize a list of numbers, yes?
For instance, math.normalize(2,4,10) returns 0.125, 0.25, 0.625. Also, is there a better way to return a vararg expression than my loadstring hack?
Also to test my understanding, this would correctly normalize a list of numbers, yes?
Code: Select all
function math.normalize(...)
local n, m, s = select('#',...), 0, "return "
for i=1, n do m = m + select(i,...) end
for i=1, n-1 do s = s..select(i,...)/m.."," end
return loadstring(s..select(n,...)/m)()
end
Earliest Love2D supporter who can't Love anymore. Let me disable pixel shaders if I don't use them, dammit!
Lenovo Thinkpad X60 Tablet, built like a tank. But not fancy enough for Love2D 0.10.0+.
Lenovo Thinkpad X60 Tablet, built like a tank. But not fancy enough for Love2D 0.10.0+.
- bartbes
- Sex machine
- Posts: 4946
- Joined: Fri Aug 29, 2008 10:35 am
- Location: The Netherlands
- Contact:
Re: NPC chasing the player
A table + unpack? This loadstring stuff is unreadable.
- Robin
- The Omniscient
- Posts: 6506
- Joined: Fri Feb 20, 2009 4:29 pm
- Location: The Netherlands
- Contact:
Re: NPC chasing the player
A challenge!
Untested.
Code: Select all
function math.sum(...)
if select('#', ...) == 0 then
return 0
end
return (...) + math.sum(select(2, ...))
end
function math.normalize(...)
local total = math.sum(...)
local t = {...}
for i = 1, #t do
t[i] = t[i]/total
end
return unpack(t)
end
Help us help you: attach a .love.
Who is online
Users browsing this forum: Bing [Bot] and 9 guests