Moving actor towards certain location

Hi all!

Is it possible to make an actor head toward a certain location?

Like in the code below, can the red ellipses be made to move toward the blue dot? I’m lost as to where to start with something like this.

I imagine that I will need to use some trigonometry to figure out the angle that the ellipses need to move?

Any tips would be greatly appreciated!


displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)
function setup()
    
end

function draw()
    background(0, 0, 0, 255)
    fill(0, 0, 255, 255)
    ellipse(WIDTH/1.5,HEIGHT/1.5,128)
    fill(255,0,0,255)
    ellipse(WIDTH/5,HEIGHT/4,64)
    ellipse(WIDTH/5,HEIGHT/1.2,64)
    
end

Awesome! A lot easier than I expected it to be!

Thanks for the help!

How about this?


displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)
function setup()
    p1 = {x=WIDTH/5,y=HEIGHT/4}
    p2 = {x=WIDTH/5,y=HEIGHT/1.2}
    tween(1,p1,{x=WIDTH/1.5,y=HEIGHT/1.5})
    tween(1,p2,{x=WIDTH/1.5,y=HEIGHT/1.5})
end

function draw()
    background(0, 0, 0, 255)
    fill(0, 0, 255, 255)
    ellipse(WIDTH/1.5,HEIGHT/1.5,128)
    fill(255,0,0,255)
    ellipse(p1.x,p1.y,64)
    ellipse(p2.x,p2.y,64)

end

@Crumble Here’s another version.

EDIT: Tap the screen where you want the circle to go.


displayMode(FULLSCREEN)

function setup()
    x=WIDTH/2
    y=HEIGHT/2
    nx,ny=x,y
end

function draw()
    background(40, 40, 50)
    fill(255)
    ellipse(x,y,20)
    ellipse(nx,ny,5)
    x=x+(nx-x)/20
    y=y+(ny-y)/20
end

function touched(t)
    if t.state==BEGAN then
        nx=t.x
        ny=t.y
    end
end

Stuck on the next step…

Trying to get the ellipses (stars now) to spawn randomly off screen and then head toward the blue ellipse.

I can’t figure out how to tie the tween into the random sprite spawning…

p1 is the one that I am messing with.



displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)
function setup()
    ball=readImage("Planet Cute:Star")
    p1 = {x=a.x,y=a.y}
    p2 = {x=WIDTH/5,y=HEIGHT/1.2}
    tween(2,p1,{x=WIDTH/1.5,y=HEIGHT/2})
    tween(2,p2,{x=WIDTH/1.5,y=HEIGHT/2})
    spawnLoc={vec2(-64,128),vec2(-64,256),vec2(-64,384),vec2(-64,512),vec2(-64,640)}
    ellipses={}
    timer=0
    spawnFreq=1
end

function spawn()
    local random=math.random(1,5)
    table.insert(ellipses,spawnLoc[random])
end

function draw()
    background(0, 0, 0, 255)
    fill(0, 0, 255, 255)
    ellipse(WIDTH/1.5,HEIGHT/2,128)
    sprite(ball,ellipses[a].x,ellipses[a].y,64,64)
    timer=timer+DeltaTime
    if timer>spawnFreq then
        spawn()
        timer=0
    end
    
    sprite(ball,p2.x,p2.y,64)
end

@dave1707

That is some interesting code, need to wrap my head around that. Not sure if I should use Tweens or the type of code you posted now for what I’m trying to accomplish.

I’m pretty much just trying to randomly spawn sprites all around the outside of the screen, and have them all head toward a designated spot. The Tweens are throwing me off, maybe I’ll try to figure how to use your way.

@Crumble - if you’re prepared to do some reading, this is a very good explanation of how to program “steering” behaviours.

http://natureofcode.com/book/chapter-6-autonomous-agents/

The language is not Codea but Processing, but it is very, very similar. The whole book is a great read.

@Crumble Not exactly sure what you’re doing, but here’s some code to spawn something off the screen and it moves to the center of the screen. It the spawns another from a random spot.

EDIT: Modified the spawn function.


displayMode(FULLSCREEN)

function setup()
    w=WIDTH/2
    h=HEIGHT/2
    spawn()
end

function draw()
    background(40, 40, 50)
    fill(255)
    ellipse(x,y,20)
    x=x-dx/100
    y=y-dy/100
    if math.abs(x-w+y-h)<1 then
        spawn()
    end
end

function spawn()
    v=math.random(4)
    if v==1 then
        x=math.random(WIDTH,2*WIDTH)
        y=math.random(HEIGHT)
    end
    if v==2 then
        x=math.random(WIDTH)
        y=math.random(HEIGHT,2*HEIGHT)
    end
    if v==3 then
        x=math.random(-WIDTH,0)
        y=math.random(HEIGHT)
    end
    if v==4 then
        x=math.random(WIDTH)
        y=math.random(-HEIGHT,0)
    end
    dx=x-w
    dy=y-h
end

@dave1707

That is essentially what I’m trying to do, but I need each ellipse that is randomly spawned to be stored in a table so I can destroy them with touch. What I am trying to do is have ellipses spawning and going toward the stationary blue ellipse, and you have to touch the ellipses to destroy them before they touch the blue ellipse. Just a random simple game to try to learn a little more about programming.

I have the ellipses randomly spawning, and stored in a table. However I can’t for the life of me figure out how to get those stored [a].x and [a].y values to be changed to cause the ellipses to move. I have tried Tweens but it isn’t working, and have also tried the way in your first example. Both ways keep giving errors for the a.x and a.y values when I try to change their x and y locations every frame.

I have tried doing [a].x=[a].x+(x-[a].x)/20 but it gives an error.

Have also tried tween(1,ellipses,{x=WIDTH/1.2, y=HEIGHT/2}) but is also gives an error.

I’m surely using both of the above codes wrong, not sure how I’m supposed to set them up.

The working code I have so far is:

Edit: I have the ellipses (stars) spawning on screen for now just so I could see that the random spawn was working.



displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)
function setup()
    ball=readImage("Planet Cute:Star")
    x=WIDTH/1.2
    y=HEIGHT/2
    spawnLoc={vec2(64,128),vec2(64,256),vec2(64,384),vec2(64,512),vec2(64,640)}
    ellipses={}
    timer=0
    spawnFreq=1
end

function spawn()
    local random=math.random(1,5)
    table.insert(ellipses,spawnLoc[random])
end

function draw()
    background(0, 0, 0, 255)
    fill(0, 0, 255, 255)
    ellipse(x,y,128)
    for a,b in ipairs(ellipses) do
        sprite(ball,ellipses[a].x,ellipses[a].y,64,64)
        
    end
    timer=timer+DeltaTime
    if timer>spawnFreq then
        spawn()
        timer=0
    end
end

@Crumble - rather than moving 1/20 of the difference each time (which means you’ll never reach the destination, I suggest you move at a constant speed (maybe different for each ball).

So suppose you set the speed like this when you spawn

--set speed as a random fraction between 2 and 4
--see note underneath about spawnLoc
table.insert(ellipses,{
    loc=vec2(spawnLoc[random].x,spawnLoc[random].y),
    speed=math.random()*2+2
})

then in draw

for a,b in ipairs(ellipses) do
        local d=b.loc:dist(vec2(x,y)) --calculate distance to (x,y) 
        if d>0 then --apply speed limit, 
            d=math.min(1,b.speed/d) --calc fraction of distance to move
            b.loc.x=b.loc.x+(x-b.loc.x)*d
            b.loc.y=b.loc.y+(y-b.loc.y)*d 
       end
       sprite(ball,b.loc.x,b.loc.y,64,64)   
end

First, you should not set the random location to spawnLoc[random], because you may think you are making a new copy of spawnLoc[random], but what you are actually doing is pointing at the original item. Then, when you change your ball’s position, it will change the x,y position of the spawnLoc item you started with.

I think of it as though Codea variables have small pockets that can only fit a string or a number. So if you say b=a, when a is a string or number, then you will be making a new copy of a, and if you change b afterwards, a will not change.

But if a is anything but a string or number, such as a table, a vec2 etc, then when you say b=a, what gets put in b is the memory address of a, not a copy of a, and if you change b, you will also change a, because they are the same thing. So you’ll see I have copied the x and y values from spawnLoc separately, and because they are just numbers, they will be copied, so changes to our ball position won’t affect the original spawnLoc values.

Second, if you want the balls to move at constant speed, calculate the distance to the target, divide it by the speed of the ball (with maximum of 1), to get the fraction of the distance that can be moved. Apply this fraction to the x and y differences.

@Crumble - I knew I’d written about the spawnLoc type of problem somewhere, see if this makes sense

http://coolcodea.wordpress.com/2013/06/14/84-tables-and-pointers/

@Ignatz

Awesome that works great!

Few questions so I can learn from this.

The a,b part still confuses me, what is a and b referring to? I understand that they are pointers, but by default when you create a table, what are a and b pointing to?

Also, when you insert loc=vec2(spawnLoc[random].x, spawnLoc[random].y) into the table, that is creating the b.loc.x and b.loc.y variables that you use later?

And finally, when you use b.loc:dist(vec2(x,y)) it is doing the distance between 2 points calculation (c^2=((x2-x1)^2+(y2-y1)^2)?

Thanks for all of the help! Sorry I’m so full of questions.

Thanks to you too @dave1707

a gives you the position in the table (you were using it correctly) and b gives you the object. so i could have said ellipses[a] instead of b.

yes, when I spawn, I make a copy of the x and y values from whichever spawnLoc item I chose, and this is used for the ball position.

And dist gives distance between two vecs. Have a look at the built in docs for more vec functions.

Awesome, thanks much for the info! Learned a lot in this thread!

@Crumble I added a few more lines of code to what I show above. Try to tap the incoming objects moving towards the middle of the screen. You can adjust the amount of incoming objects by decreasing the “delay” value. You can adjust how close you have to touch to the incoming objects by changing the “dist” value. The smaller the dist value, the closer you have to touch to them.


displayMode(FULLSCREEN)

function setup()
    tab={}
    w,h=WIDTH/2,HEIGHT/2
    count=999
    delay=60
    dist=50
end

function draw()
    background(40, 40, 50)
    count=count+1
    if count>delay then
        count=0
        spawn()
    end
    sprite("Tyrian Remastered:Eye Mecha",w,h)
    for a,b in pairs(tab) do
        sprite("Tyrian Remastered:Mine Spiked Huge",b.x,b.y)
        b.x=b.x-b.z/100
        b.y=b.y-b.w/100
        if math.abs(b.x-w+b.y-h)<1 then
            table.remove(tab,a)
            sprite("Tyrian Remastered:Explosion Huge",w,h,100)
        end
    end
end

function spawn()
    v=math.random(4)
    if v==1 then
        x=math.random(WIDTH,2*WIDTH)
        y=math.random(HEIGHT)
    end
    if v==2 then
        x=math.random(WIDTH)
        y=math.random(HEIGHT,2*HEIGHT)
    end
    if v==3 then
        x=math.random(-WIDTH,0)
        y=math.random(HEIGHT)
    end
    if v==4 then
        x=math.random(WIDTH)
        y=math.random(-HEIGHT,0)
    end
    table.insert(tab,vec4(x,y,x-w,y-h))
end

function touched(t)
    if t.state==BEGAN then
        v1=vec2(t.x,t.y)
        for a,b in pairs(tab) do
            d=v1:dist(vec2(b.x,b.y))
            if d<dist then
                table.remove(tab,a)
            end
        end
    end
end