Movement of Sprite Help

I’m trying to get to grasp with movements of sprites. Iv followed tutorials and searched for similar help but nothing relates to what I want to do . Im very new to codea and code itself so go easy on me :slight_smile:

I have provided two diagrams below. The Gem represents the train at position A. I want the train to move to the next available position (position E) by tapping position E.

Once at position E, i want to tap position D so the train moves down.

Any help would be appreciated

Try this. Tap anywhere on the screen and the dot will go there and stop. There are ways using vec2() to make it better.


displayMode(FULLSCREEN)

function setup()
    hx=0
    hy=0
    dx=0
    dy=0
    x=WIDTH/2
    y=HEIGHT/2
end

function draw()
    background(40, 40, 50)
    fill(255)
    if math.abs(x-hx)>5 or math.abs(y-hy)>5 then
        x=x+dx
        y=y+dy
    end
    ellipse(x,y,20)
end

function touched(t)
    if t.state==BEGAN then
        hx=t.x
        hy=t.y
        dx=(hx-x)/100
        dy=(hy-y)/100
    end
end

Just had a look thanks, although Is it possible to do it though so the train can only move within the track and only move to the touch points (the little grey blobs I placed on track)

Code can be added so that the touch points are only the points you allow. Also, if the train is at one point, only certain points can be valid touch points. For instance, if the train is at A, only points E or C are valid.

@thebugel I added a little more code to the original post. See if this is more helpful. Tap the points you want the train (large dot) to move to.

EDIT: Previous code replaced with this code.


displayMode(FULLSCREEN)

function setup()
    setDest()
    setValidDest()
    speed=2
    x=100
    y=600
    arrived=true
    at=5
end

function draw()
    background(40, 40, 50)
    drawTracks()
    fill(255)    
    -- draw the destination points
    for a,b in pairs(dest) do
        ellipse(b.x,b.y,10)
    end   
    -- check if train arrived at destination
    if not arrived then
        v1=vec2(currDest.x,currDest.y)
        d=v1:dist(vec2(x,y))
        if d>3 then -- train hasn't arrived yet
            x=x+dx
            y=y+dy
        else
            x=currDest.x    -- train arrived, set exact dest x,y position
            y=currDest.y
            arrived=true
        end
    end    
    -- draw train (large dot)
    ellipse(x,y,20)
end

function touched(t)
    if t.state==BEGAN and arrived then
        v1=vec2(t.x,t.y)
        -- is touched point a valid destination
        for a,b in pairs(valid[at]) do
            d=v1:dist(vec2(b.x,b.y))
            if d<20 then
                -- valid destination
                currDest=vec2(b.x,b.y)
                -- get dest table offset of destination
                for c,d in pairs(dest) do
                    if d.x==b.x and d.y==b.y then
                        at=c     -- dest table offset
                        break
                    end
                end
                -- determine new speed and direction of train
                v1=vec2(x,y)
                d=v1:dist(vec2(b.x,b.y))
                dx=(b.x-x)/d*speed
                dy=(b.y-y)/d*speed
                arrived=false
                break
            end
        end
    end
end

function drawTracks()
    stroke(255)
    strokeWidth(3)
    line(100,600,500,600)
    line(300,400,300,800)
end

function setDest()    -- table of the destination points
    dest={}
    table.insert(dest,vec2(300,400))
    table.insert(dest,vec2(300,600))
    table.insert(dest,vec2(300,800))
    table.insert(dest,vec2(500,600)) 
    table.insert(dest,vec2(100,600))  
end

function setValidDest()    -- valid destinations for each dest point
    valid={ 
        {vec2(300,600),vec2(300,800)},
        {vec2(300,400),vec2(300,800),vec2(500,600),vec2(100,600)},
        {vec2(300,400),vec2(300,600)},
        {vec2(300,600),vec2(100,600)},
        {vec2(300,600),vec2(500,600)}
          }
end

@thebugel consider loading your sprites first with readimage(key,width,height) in your code your loading the same image a number of times :slight_smile: with read image you can load it once and reuse the image as many times as you like with the sprite function.

function setup()
track1 = readimage("Documents:track") -- load image
end

function draw()

sprite(track1,0,100) --draw 

sprite(track1,0,200)

end

@thebugel I modified my code above. It’s a little smaller and hopefully easier to understand.

excellent, much appreciated @dave1707 i will give it bash at playing around with it, finding that’s the best way to learn. is it the last part of that code that determines the gps position of the touch points?

This is also a newbie question but would all this info be on a separate tab to the page im currently editing the layout? (tracks and background). im pretty clueless about what you need different tabs for…

also cheers to @XanDDemoX i knew there would be an easier way…

@thebugel The table “dest” holds the x,y positions of where you want the train to go ( the stations? ). The table “setValidDest” holds the x,y positions of the valid destinations from a certain point. The two tables are linked 1 to 1. The 1st entry of setValidDest (2 vec2’s) holds the positions that can be reached if the train is at the 1st entry of the dest table. The 2nd entry of setValidDest holds (4 vec2’s) that can be reached from the 2nd entry of the dest table. The 2nd entry of the dest table is the center of the cross, so 4 points can be reached from it. The remaining entries are the same things. You can use tabs or you can skip them, it mainly up to you. If the program is large, you can put similar code into tabs just so you’re not trying to edit large chunks of code. Tabs also make finding what you want to edit easier. If the tab name fits the functions of the the code that’s in it, then you know which tab to edit when you want to make a change. There is nothing that says you have to or not have to use tabs.

Once again thanks @dave1707.

One more question though if you don’t mind, iv had a good couple of hours playing with this code and trying to figure out what everything does…

Iv been trying to add an extra station at 100,400 (south west position) But having no luck. iv nearly got there (we’l in my mind but probably not) but I’m hoping you can put me out of my misery.

Could you possibly add the code to the existing one you posted and highlight your changes to accommodate the extra station. My attempt is below…

Here are the changes I tried

First I changed at=6 (I’m gathering this is the number of stations)

Then at the bottom I put

function setDest() – table of the destination points
dest={}
table.insert(dest,vec2(300,400))
table.insert(dest,vec2(300,600))
table.insert(dest,vec2(300,800))
table.insert(dest,vec2(500,600))
table.insert(dest,vec2(100,600))
table.insert(dest,vec2(100,400)) --my added line
end

function setValidDest() – valid destinations for each dest point
valid={
{vec2(300,600),vec2(300,800)},
{vec2(300,400),vec2(300,800),vec2(500,600),vec2(100,600)},
{vec2(300,400),vec2(300,600)},
{vec2(300,600),vec2(100,600)},
{vec2(300,600),vec2(500,600)},
{vec2(100,400),vec2(300,400)},–my added line

The result was the ellipse moved from west to south west but only once and I had to make this movement first before I could do west to centre. I had no idea how to add the line.

Thanks

@thebugel I’m sorry, I never specified what “at” was. “at” holds the offset into the dest table of where the train is at. The train starts out at 100,600 which is the 5th offset into the dest table. As the train moves from point to point, the value of “at” will change to where it’s at. You didn’t say how the train would get to the new point 100,400, so I have it set up so that the train can only get to 100,400 from 100,600. I added a line in drawTracks to show that line. The code in drawTracks is for show only. It doesn’t influence how the train moves. New code was added to the dest table to plot the new location 100,400. Since I said the train can only get to 100,400 from 100,600, I looked in the dest table for 100,600. It’s the 5th entry, so in the setValidDest table, in the 5th entry I added vec2(100,400) so that from 100,600 the train can go to 300,600 and 500,600 and 100,400. Since the train can now get to 100,400, it has to get back to 100,600. Since 100,400 is the 6th entry in dest, I had to add a 6th entry in setValidDest to allow 100,600 as a valid destination when the train is at 100,400. It sound more confusing than it is, but once you understand how the dest and setValidDest work together, it’s easy.

EDIT: Sorry again. It looks like you were getting to 100,400 from 300,400. I guess I’ll let you make those changes.


function drawTracks()
    stroke(255)
    strokeWidth(3)
    line(100,600,500,600)
    line(300,400,300,800)
    line(100,600,100,400)    -- new line of code
end

function setDest()    -- table of the destination points
    dest={}
    table.insert(dest,vec2(300,400))
    table.insert(dest,vec2(300,600))
    table.insert(dest,vec2(300,800))
    table.insert(dest,vec2(500,600)) 
    table.insert(dest,vec2(100,600))  
    table.insert(dest,vec2(100,400))  -- new line of code
end

function setValidDest()    -- valid destinations for each dest point
    valid={ 
        {vec2(300,600),vec2(300,800)},
        {vec2(300,400),vec2(300,800),vec2(500,600),vec2(100,600)},
        {vec2(300,400),vec2(300,600)},
        {vec2(300,600),vec2(100,600)},
        {vec2(300,600),vec2(500,600),vec2(100,400)}, -- new code added
        {vec2(100,600)}    -- new line of code
          }
end

Thanks again, I think im getting there now @dave1707.

I attempted to get the elipse from 100,400 to 300,400 which i successfully did by adding vec2(300,400)} to the end of the last code you sent.

this change allowed the elipse to move from 100,400 to 300,400 however it didnt allow it to return back to 100,400

what am i missing? once i have this answer i think iv cracked it. thanks

**edit iv figured it by re-reading your previous comment

i added vec2(100,400)} to the end of line one in the setvalidDest.

thank you again for your help…i should be ok from here on (fingers crossed).

@dave1707 - way to go, code machine! B-)

@thebugel I hate to do this to you, but I re-wrote the above program and eliminated the “valid” table. The “dest” table now contains all the information needed. Also, the drawTracks function now draws the lines between the points, the individual line commands don’t need to be entered. I don’t know if you can use the drawTracks function since your original example has track sprites that you draw. I’ll explain the “dest” table, hopefully it’s now easier. The 1st entry of each line is the x,y position of each train station. That was the original “dest” table information. The 2nd thru … entry of each line are the x,y positions of the train stations that can reached from the 1st entry. So the 2nd thru … entry are the x,y values that were in the “valid” table. So you can use either program you’re comfortable with.

EDIT: I modified the program again to allow points to be beyond the edge of the screen. The screen can be scrolled in all directions to follow the train or move to a point off screen to tap it.


displayMode(FULLSCREEN)

function setup()
    setDest()
    speed=2
    x=100
    y=600
    arrived=true
    at=5
    mx=0
    my=0
end

function draw()
    background(40, 40, 50)
    fill(255)   
    -- draw the destination points
    translate(mx,my)
    drawTracks()
    for a,b in pairs(dest) do
        ellipse(b[1].x,b[1].y,10)
    end   
    -- check if train arrived at destination
    if not arrived then
        v1=vec2(currDest.x,currDest.y)
        d=v1:dist(vec2(x,y))
        if d>3 then -- train hasn't arrived yet
            x=x+dx
            y=y+dy
        else
            x=currDest.x    -- train arrived, set exact dest x,y position
            y=currDest.y
            arrived=true
        end
    end    
    -- draw train (large dot)
    ellipse(x,y,20)
end

function touched(t)
    if t.state==MOVING then
        mx=mx+t.deltaX
        my=my+t.deltaY
    end
    if t.state==BEGAN and arrived then
        v1=vec2(t.x-mx,t.y-my)
        -- is touched point a valid destination
        for a,b in pairs(dest[at]) do
            d=v1:dist(vec2(b.x,b.y))
            if d<20 then
                -- valid destination
                currDest=vec2(b.x,b.y)
                -- get dest table offset of destination
                for c,d in pairs(dest) do
                    if d[1].x==b.x and d[1].y==b.y then
                        at=c     -- dest table offset
                        break
                    end
                end
                -- determine new speed and direction of train
                v1=vec2(x,y)
                d=v1:dist(vec2(b.x,b.y))
                dx=(b.x-x)/d*speed
                dy=(b.y-y)/d*speed
                arrived=false
                break
            end
        end
    end
end

function drawTracks()
    stroke(255)
    strokeWidth(3)
    for z=1,#dest do
        for s=2,#dest[z] do
            line(dest[z][1].x,dest[z][1].y,dest[z][s].x,dest[z][s].y)
        end
    end
end

function setDest()    -- table of the destination points
    dest = {
    {vec2(300,400),vec2(300,600),vec2(300,800),vec2(1700,400)},
    {vec2(300,600),vec2(300,400),vec2(300,800),vec2(500,600),vec2(100,600)},
    {vec2(300,800),vec2(300,400),vec2(300,600),vec2(1700,1200)},
    {vec2(500,600),vec2(300,600),vec2(100,600)},
    {vec2(100,600),vec2(300,600),vec2(500,600)},
    {vec2(1700,400),vec2(300,400),vec2(1700,1200),vec2(1000,600)},
    {vec2(1700,1200),vec2(1700,400),vec2(300,800),vec2(1000,600)},
    {vec2(1000,600),vec2(1700,1200),vec2(1700,400)}
           }
end

@thebugel I modified the program above to allow for off screen points and scrolling. See the EDIT above.

Once again thank you, I’d just got my head round the first way of doing things but this way seems simpler…

Thanks for the scroller that will come in useful.

I don’t want you to tell me the direct answer because I I feel I’m pestering and you’d end up writing the whole game but could you point me in the right direction of where I can find how to tick each station wen visited and also adding a 24 hour clock, I.e all stations must be visited within a time period during the day.

Thanks again dave

@thebugel You can initialize another table the size of “dest” with false, then every time the train stops at a station, use the value of “at” as the offset and set that entry in the table to true. You can loop thru the table and when all entries are true, every station was visited. I’m not sure how you want to do the clock, but you could use ElapsedTime. They have to visit each station in the time you allow. Also, I have the code modified so that if you tap a station far away from the train ( it’s off screen), the screen will scroll so the moving train is kept in view. Let me know if you want it, or if you want to try that yourself.

@dave1707 Yes please, further down line I would like to scroll as for now it’s just going to be one screen. As a newbie to code and codea I’m trying to avoid making layout too complicated. I would like the code though for future ref if you don’t mind.

Where abouts in the code layout would I write the ‘dest’ table’ for visited stations and insert the elapse time code, (your guess was good, stations can only be visit within diff time periods). one thing I’m not familiar with is the layout of the code, I know where to draw, that’s about it. one things for sure I know a hell of a lot more since this time last week.

Going to have a look tonight at what you said and play around with it, thanks again.

@thebugel Here’s the updated code. The screen scrolls to keep the moving train in view. I added a table to check if all stations were stopped at. I added a timer to see how long it takes to stop at all the stations. So you can try adding the changes on your own or see how they were done here. The program layout got changed also, I put more of the code in seperate functions.


displayMode(FULLSCREEN)

function setup()
    at=5
    setDest()
    setAtDest()
    totalTime=0
    startTimer=false
    arrived=true
    speed=2
    x=100
    y=600
    mx=0
    my=0
end

function draw()
    background(40, 40, 50)
    showTime()
    translate(mx,my)
    drawTracks()
    drawStations()
    drawTrain()
    checkArrived()
    checkAllStations()
end

function touched(t)
    if done and t.tapCount==2 then    -- restart
        restart()
    end
    if t.state==MOVING and arrived then    -- scroll screen
        mx=mx+t.deltaX
        my=my+t.deltaY
    end
    if t.state==BEGAN and arrived then
        startTimer=true
        ms=5    -- set move screen speed at 5 pixels for off screen speed
        v1=vec2(t.x-mx,t.y-my)
        -- is touched point a valid destination
        for a,b in pairs(dest[at]) do
            d=v1:dist(vec2(b.x,b.y))
            if d<20 then
                -- valid destination
                currDest=vec2(b.x,b.y)
                -- get dest table offset of destination
                for c,d in pairs(dest) do
                    if d[1].x==b.x and d[1].y==b.y then
                        at=c     -- dest table offset
                        break
                    end
                end
                -- determine new speed and direction of train
                v1=vec2(x,y)
                d=v1:dist(vec2(b.x,b.y))
                dx=(b.x-x)/d*speed
                dy=(b.y-y)/d*speed
                arrived=false
                break
            end
        end
    end
end

function setDest()    -- table of the destination points
    dest = {
    {vec2(300,400),vec2(300,600),vec2(300,800),vec2(1700,400)},
    {vec2(300,600),vec2(300,400),vec2(300,800),vec2(500,600),vec2(100,600)},
    {vec2(300,800),vec2(300,400),vec2(300,600),vec2(1700,1200)},
    {vec2(500,600),vec2(300,600),vec2(100,600)},
    {vec2(100,600),vec2(300,600),vec2(500,600)},
    {vec2(1700,400),vec2(300,400),vec2(1700,1200),vec2(1000,600)},
    {vec2(1700,1200),vec2(1700,400),vec2(300,800),vec2(1000,600)},
    {vec2(1000,600),vec2(1700,1200),vec2(1700,400)}
           }
end

function drawTracks()
    stroke(255)
    strokeWidth(3)
    for z=1,#dest do
        for s=2,#dest[z] do
            line(dest[z][1].x,dest[z][1].y,dest[z][s].x,dest[z][s].y)
        end
    end
end

function drawTrain()
    fill(255)
    ellipse(x,y,20)
end

function drawStations()
    for a,b in pairs(dest) do
        fill(255)
        strokeWidth(0)
        if atDest[a]==true then
            fill(0, 255, 0, 255)
            ellipse(b[1].x,b[1].y,40)
        else
            ellipse(b[1].x,b[1].y,20)
        end
    end 
end  

function checkArrived()
    -- check if train arrived at destination
    if not arrived then
        v1=vec2(currDest.x,currDest.y)
        d=v1:dist(vec2(x,y))
        if d>3 then -- train hasn't arrived yet
            x=x+dx
            y=y+dy
            -- check if on screen train is at the edges
            if x+mx>50 and x+mx<WIDTH-50 and y+my>50 and y+my<HEIGHT-50 then
                ms=3    -- set move screen speed to 3 pixels
            end
            -- move screen to put or keep the train in view
            if x+mx<50 then
                mx=mx+ms
            end
            if x+mx>WIDTH-50 then
                mx=mx-ms
            end
            if y+my<50 then
                my=my+ms
            end
            if y+my>HEIGHT-50 then
                my=my-ms
            end
        else
            x=currDest.x    -- train arrived, set exact dest x,y position
            y=currDest.y
            arrived=true
            atDest[at]=true
        end
    end    
end

function setAtDest()  
    atDest={}     
    for z=1,#dest do
        atDest[z]=false
    end
    atDest[at]=true
end

function checkAllStations()
    done=true
    for z=1,#atDest do
        if atDest[z]==false then
            done=false
        end
    end
end

function showTime()
    fill(255)
    if not startTimer then
        et=ElapsedTime
    end
    if not done then
        totalTime=string.format("%0.2f",ElapsedTime-et)
    else
        text("All stations reached in",WIDTH/2,HEIGHT-50)  
        text("Double tap screen to restart",WIDTH/2,HEIGHT-160)
    end
    text(totalTime.."  seconds",WIDTH/2,HEIGHT-90)
end

@dave1707 I’m realy impressed, and once again thanks.

Can you give me any advise on how to learn all this stuff? I am comfortable with the first template you sent me…is that the best way to learn by editing templates?is there any websites you can recommend where you can find Different scripts?

About the timer…How do I edit the timer so it starts at a certain time or day rather than at 0 and runs continous and then ends at a certain time…I.e trains start at 05:00 and run until 23:00, if all check points are not reached by 23:00 then level failed. Each hr will be 60 seconds long.

I promise this will be the last time I bug you :slight_smile: