Mob movement

So I’m trying to get some objects to follow where I touch and I have something working, but they all go to the same point and look like one object. I want them to move more like a mob, not overlapping each other. This is what I have so far:


--# Main
-- Targeted Motion

displayMode(FULLSCREEN)
function setup()
    objects = {}
    table.insert(objects, {WIDTH/2, HEIGHT/2, 10})
    table.insert(objects, {WIDTH, HEIGHT, 10})
    table.insert(objects, {0, HEIGHT, 10})
    table.insert(objects, {WIDTH, 0, 10})
    table.insert(objects, {0, 0, 10})
    
    target = vec2(WIDTH/2, HEIGHT/2)
end

function draw()
    background(142, 88, 38, 255)
    
    strokeWidth(5)
    line(0,0, WIDTH,HEIGHT)
    line(0,HEIGHT, WIDTH,0)
    
    for i,v in ipairs(objects) do
        move = target - vec2(v[1], v[2])
        if move:len() > v[3] then
            move = move:normalize() * v[3]
        end
        v[1] = v[1] + move.x
        v[2] = v[2] + move.y

        sprite("Cargo Bot:Codea Icon", v[1], v[2], 50)
    end
end

function touched(touch)
    target = vec2(touch.x, touch.y)
end

What you need to do is compare the x,y position of all the objects and don’t update their positions if they’re within a set minimum distance of each other.

Maybe this can be of interest?

http://twolivesleft.com/Codea/Talk/discussion/2222/swarm-of-ships#Item_3

Perhaps Google flocking, this is a very simple algorithm for what you want

@JakAttak Not sure what you’re going to use the mob for, but here is a simple version that might work for you.


--# Main
-- Targeted Motion

displayMode(FULLSCREEN)
function setup()
    size=20
    objects = {}   
    for z=1,20 do
        a=physics.body(CIRCLE,size)
        a.x=math.random(WIDTH)
        a.y=math.random(HEIGHT)
        a.gravityScale=0
        table.insert(objects,a)
    end
    target = vec2(WIDTH/2, HEIGHT/2)
end

function draw()
    background(142, 88, 38, 255)
    strokeWidth(5)
    line(0,0, WIDTH,HEIGHT)
    line(0,HEIGHT, WIDTH,0)
    for i,v in ipairs(objects) do
        move= target - vec2(v.x, v.y)   
        if move:len() > 10 then
            move = move:normalize() * 10
        end
        v.x = v.x + move.x
        v.y = v.y + move.y
        sprite("Cargo Bot:Codea Icon", v.x, v.y, 20)
    end
end

function touched(touch)
    target = vec2(touch.x, touch.y)
end

@dave1707, I’m working on a little game where a horde of people follows you around. Thanks for that! Does simply making them physics bodies stop the, from being able to run into each other?

The physics bodies repell each other. You can adjust the distance they stay from each other by changing the value of size. If you change the value in the for loop from 20 to 100, it looks like they’re attacking whatever is in the center.

Awesome. Thanks!

@dave1707 that’s a great effect. Cheers

@JakAttak Very good idea
http://youtu.be/_mH6pPwdwB0

@JakAttak I modified the code again to show 2 mobs. The 1st mob sits in the center of the screen. The 2nd mob can be moved around depending on where you tap the screen. Kind of interesting watching the mob move around the stationary one.


--# Main
-- Targeted Motion

displayMode(FULLSCREEN)
function setup()
    size=30
    size1=30
    objects = {}   
    for z=1,30 do
        a=physics.body(CIRCLE,size)
        a.x=math.random(WIDTH)
        a.y=math.random(HEIGHT)
        a.gravityScale=0
        table.insert(objects,a)
    end
    objects1 = {}   
    for z=1,15 do
        a=physics.body(CIRCLE,size1)
        a.x=math.random(WIDTH)
        a.y=math.random(HEIGHT)
        a.gravityScale=0
        table.insert(objects1,a)
    end
    target = vec2(WIDTH/2, HEIGHT/2)
    target1 = vec2(WIDTH/2, 100)
end

function draw()
    background(142, 88, 38, 255)
    strokeWidth(5)
    line(0,0, WIDTH,HEIGHT)
    line(0,HEIGHT, WIDTH,0)
    for i,v in ipairs(objects) do
        move= target - vec2(v.x, v.y)   
        if move:len() > 10 then
            move = move:normalize() * 10
        end
        v.x = v.x + move.x
        v.y = v.y + move.y
        sprite("Planet Cute:Tree Short", v.x, v.y, 20)
    end
    for i,v in ipairs(objects1) do
        move= target1 - vec2(v.x, v.y)   
        if move:len() > 10 then
            move = move:normalize() * 10
        end
        v.x = v.x + move.x
        v.y = v.y + move.y
        sprite("Planet Cute:Character Pink Girl", v.x, v.y, 20)
    end
end

function touched(touch)
    target1 = vec2(touch.x, touch.y)
end

Here’s another example of 4 mobs. Just tap the screen when the mobs are in their area.


--# Main
-- Targeted Motion

displayMode(FULLSCREEN)
function setup()
    size=25
    ob=0
    objects1 = {}
    objects2 = {}
    objects3 = {}
    objects4 = {}    
    for z=1,120 do
        a=physics.body(CIRCLE,size)
        a.x=math.random(WIDTH)
        a.y=math.random(HEIGHT)
        a.gravityScale=0
        ob=(ob+1)%4
        if ob==0 then
            table.insert(objects1,a)
        elseif ob==1 then
            table.insert(objects2,a)
        elseif ob==2 then
            table.insert(objects3,a)
        elseif ob==3 then
            table.insert(objects4,a)
        end
    end    
    target1 = vec2(WIDTH/2, HEIGHT-150)
    target2 = vec2(WIDTH/2, 150)
    target3 = vec2(150,HEIGHT/2)
    target4 = vec2(WIDTH-150,HEIGHT/2)
end

function draw()
    background(142, 88, 38, 255)
    strokeWidth(5)
    line(0,0, WIDTH,HEIGHT)
    line(0,HEIGHT, WIDTH,0)
    drawMob(objects1,target1,"Planet Cute:Character Boy")
    drawMob(objects2,target2,"Planet Cute:Character Cat Girl")
    drawMob(objects3,target3,"Planet Cute:Character Horn Girl")
    drawMob(objects4,target4,"Planet Cute:Character Pink Girl")
end

function drawMob(obj,tar,spr)
    for i,v in ipairs(obj) do
        move= tar - vec2(v.x, v.y)   
        if move:len() > 10 then
            move = move:normalize() * 10
        end
        v.x = v.x + move.x
        v.y = v.y + move.y
        sprite(spr, v.x, v.y, 20)
    end
end

function touched(touch)
    if touch.state==BEGAN then
        xx=target1
        target1 = target2
        target2=xx
        xx=target3
        target3=target4
        target4=xx
    end
end