How to put text on a certain path/route?

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Post Reply
AdventureFan
Prole
Posts: 14
Joined: Wed Jul 24, 2013 7:03 am

How to put text on a certain path/route?

Post by AdventureFan »

First of all, greetings to all who read.
Secondly, I hope I'm posting in the right forum. It wasn't totally clear in which of the forum sections to post my question.

I'm only just starting to learn Love2D. It's absolutely amazing how quick you can get started with a game project using Löve.

I managed to create a program that just makes some text move. However, I would like it to move on a certain path.
I guess I could do it by incorporating some more "if-then" statements inside love.update, but what I would really like to be able to do, is have a table holding all the coordinates and then the game uses that table to move the text around.

I don't know how to go about this though, so if anyone could give me some pointers/tips, I'd greatly appreciate it.

Here is my code so far (if my code can be better somehow, I'd like to know too):

Code: Select all

function love.load()
	
	love.graphics.setBackgroundColor(0,0,0, 255)
	love.graphics.setColor(255,255,255, 255)
	specialEffectText = {}
	specialEffectText.textValue="Hello there!"
	specialEffectText.x = 0
	specialEffectText.y = 0
	specialEffectText.speed = 80

end

function love.update(dt)		
	
	if specialEffectText.x < 600 then
		specialEffectText.x = specialEffectText.x + specialEffectText.speed*dt
	
	elseif specialEffectText.x > 600 then
		specialEffectText.x = 600	
	end 		
end

function love.draw()	
	
	love.graphics.print(specialEffectText.textValue, specialEffectText.x, specialEffectText.y)
	-- love.graphics.print(specialEffectText.x, 200, 400)

end
My first idea was to do something like this:

Code: Select all

specialEffectText.path = {}
specialEffectText.path.x = {200, 400, 600}
specialEffectText.path.y = {100, 200, 300}
The idea being:
1. if specialEffectText.path.x > 200 then stop horizontal movement and start vertical movement
2. if specialEffectText.path.y > 100 then stop vertical movement and start horizontal movement
3. if specialEffectText.path.x > 400 then stop horizontal movement and start vertical movement
4. if specialEffectText.path.y > 200 then stop vertical movement and start horizontal movement
5. if specialEffectText.path.x > 600 then stop ALL movement

Then I would somehow need to check when the x and y values have been reached.
User avatar
Plu
Inner party member
Posts: 722
Joined: Fri Mar 15, 2013 9:36 pm

Re: How to put text on a certain path/route?

Post by Plu »

I'll break it down into steps, and you should try to implement them yourself (you learn much more that way!)

Step 1: make table(s) holding the required path information
Step 2: remove the first entry from the table(s) and store them as GoalX, GoalY
Step 3: move the text towards GoalX and GoalY by comparing them to your current location and then adding/removing speed * dt from the coordinates
Step 4: check if you're within 2 pixels of GoalX and GoalY (due to dt you will never exactly reach the goal)
Step 5: If you are, check if there's still entries left in the path table(s)
Step 6: If there are, return to Step 2
Step 7: If there are not; do whatever else you want the text to do when it's done floating about.

If you need more help, just ask :)
AdventureFan
Prole
Posts: 14
Joined: Wed Jul 24, 2013 7:03 am

Re: How to put text on a certain path/route?

Post by AdventureFan »

Plu wrote:I'll break it down into steps, and you should try to implement them yourself (you learn much more that way!)

Step 1: make table(s) holding the required path information
Step 2: remove the first entry from the table(s) and store them as GoalX, GoalY
Step 3: move the text towards GoalX and GoalY by comparing them to your current location and then adding/removing speed * dt from the coordinates
Step 4: check if you're within 2 pixels of GoalX and GoalY (due to dt you will never exactly reach the goal)
Step 5: If you are, check if there's still entries left in the path table(s)
Step 6: If there are, return to Step 2
Step 7: If there are not; do whatever else you want the text to do when it's done floating about.

If you need more help, just ask :)
Thanks, that's exactly the kind of help I wanted. I'll try it out and if at a certain point I'm dead stuck, I'll post here.
AdventureFan
Prole
Posts: 14
Joined: Wed Jul 24, 2013 7:03 am

Re: How to put text on a certain path/route?

Post by AdventureFan »

Okay, so I had a go at this and came up with the code below:
- first I created some "pseudo code" for myself (sort of like you did in your reply to me at the end of your post)
- then I looked up the commands I would be needing (Google, Love2D documentation)
- then I started programming, block by block. Once I got a block to work without errors, I moved on to the next block

It's probably not much, but at least it is a start.

What I'm happy with:
- it actually (sort of) works!
- I can change the values in specialEffectText.path.x and specialEffectText.path.y to create a "path" like I wanted

What I'm not happy with:
- The text moves too fast. I tried 'lowering' the speed by dividing or subtracting from "dt", but that usually made the program "freeze"
- I would like the text to run horizontally first, then vertically, then horizontally again, then vertically, ... and NOT simultaneous like it is now

Here is the code I came up with so far:

Code: Select all

function love.load()
	
	love.graphics.setBackgroundColor(0,0,0, 255)
	love.graphics.setColor(255,255,255, 255)
	specialEffectText = {}
	specialEffectText.textValue="Hello there!"
	specialEffectText.x = 0
	specialEffectText.y = 0
	specialEffectText.speed = 10
	
	specialEffectText.path = {}
	specialEffectText.path.x = { 200, 300, 400, 600 }
	specialEffectText.path.y = { 100, 250, 350, 400, 450, 500, 550 }

end

function love.update(dt)		
	
	-- run while table specialEffectText.path.x is not empty

 	if next(specialEffectText.path.x) ~= nil then
 		goalX = specialEffectText.path.x[1]
 		goalX = goalX - 2
 		table.remove(specialEffectText.path.x, 1)

 		goalY = specialEffectText.path.y[1]
 		goalY = goalY - 2
 		table.remove(specialEffectText.path.y, 1)
 	
 		while specialEffectText.x < goalX do
 			specialEffectText.x = specialEffectText.x + specialEffectText.speed*dt
 		end 		
 	end

 	-- run while table specialEffectText.path.y is not empty
 	if next(specialEffectText.path.y) ~= nil then
 		goalY = specialEffectText.path.y[1]
 		table.remove(specialEffectText.path.y, 1) 		
 		
 		while specialEffectText.y < goalY do
 			specialEffectText.y = specialEffectText.y + specialEffectText.speed*dt
 		end 		
 	end
	
end

function love.draw()	
	love.graphics.print(specialEffectText.textValue, specialEffectText.x, specialEffectText.y)
	love.graphics.print(specialEffectText.x, 200, 400)
	love.graphics.print(specialEffectText.y, 200, 500)
end

User avatar
Plu
Inner party member
Posts: 722
Joined: Fri Mar 15, 2013 9:36 pm

Re: How to put text on a certain path/route?

Post by Plu »

Rather than solving the horizontal/vertical in your programming, why not just define your path that way? If you use this path:

Code: Select all

100,100
500,100
500,300
200,300
200,600
your text will also move horizontal/vertical. Not everything needs to be fixed in code.

Also, you're trapping your update function in a while loop. Nothing can be drawn to the screen as long as update is working, so you can't change the location of something in a while-loop; only the last frame will ever be drawn. You have to make a change to the coordinates once and then end the function so that the updated value van be drawn to the screen.
AdventureFan
Prole
Posts: 14
Joined: Wed Jul 24, 2013 7:03 am

Re: How to put text on a certain path/route?

Post by AdventureFan »

I took another shot at this.

I feel more comfortable with the solution now, seems cleaner somehow. However I'm still not 100% happy with the behavior: I'm still not able to make it go horizontal-vertical-horizontal-vertical should I wish to.

Perhaps I could instead make one big table with coordinates and another table with "direction" instructions (horizontal/vertical/diagonal)?

Also, seems I cannot put a "0" (zero) value as the first item in the path arrays, or my statements will do nothing.
I thought "nil" meant "empty table", but I guess "0" (zero) also equals "nil" in lua?


Code: Select all

function love.load()
love.graphics.setBackgroundColor(0, 0, 0, 255)
love.graphics.setColor(255,255,255, 255)

movingText = {}

-- text value for the moving text
movingText.value = "Look at me move!"

-- X and Y values for the moving text
movingText.x = 0
movingText.y = 0

-- movement speed for the text
movingText.speed = 100

-- path/coordinates which the text has to follow
movingText.path = {}
movingText.path.x = {100, 200, 400}
movingText.path.y = {100, 100, 100}
end

function love.update(dt)  
    
    -- get the GoalX coordinate from the path table (the position where the text has to move to)
    goalX = movingText.path.x[1]

    -- move the text closer to the goalX coordinate
    if movingText.path.x[1] ~= nil and movingText.x < goalX then 
      movingText.x = movingText.x+movingText.speed*dt
    
    -- if the text has reached the goalX coordinate, remove the item from the table with X coordinates
    elseif movingText.path.x[1] ~= nil and movingText.x > goalX then 
     table.remove(movingText.path.x, 1)    
    end

    -- get the GoalY coordinate from the path table (the position where the text has to move to)
    goalY = movingText.path.y[1]

    -- move the text closer to the goalY coordinate
    if movingText.path.y[1] ~= nil and movingText.y < goalY then 
    movingText.y = movingText.y+movingText.speed*dt
  
    -- if the text has reached the goalY coordinate, remove the item from the table with Y coordinates
    elseif movingText.path.y[1] ~= nil and movingText.y > goalY then 
    table.remove(movingText.path.y, 1)      
    end

end

function love.draw()
love.graphics.print(movingText.value, movingText.x, movingText.y)
end
User avatar
DaedalusYoung
Party member
Posts: 413
Joined: Sun Jul 14, 2013 8:04 pm

Re: How to put text on a certain path/route?

Post by DaedalusYoung »

No, zero does not equal nil. Nil is a type of its own, and simply means the variable (or table or function or any of the other types) does not exist. It evaluates to boolean false, 0 should evaluate to boolean true.

So a line like

Code: Select all

if movingText.path.y[1] ~= nil and movingText.y < goalY then ...
would be the same as

Code: Select all

if movingText.path.y[1]  and movingText.y < goalY then
(Because ~= nil is the same as true)
AdventureFan
Prole
Posts: 14
Joined: Wed Jul 24, 2013 7:03 am

Re: How to put text on a certain path/route?

Post by AdventureFan »

Other attempt, this time using functions. I'm actually really happy with this one, it does exactly what I want and I think there are much less "wasteful" instructions in there like in the previous code examples.

Somehow I could not "import" the "dt" value directly in my functions. But I created a variable containing the value of "dt" and that seems to work.
Also, if I set the speed too high, it only performs the first horizontal movement. What gives?

Code: Select all

function love.load()
love.graphics.setBackgroundColor(0, 0, 0, 255)
love.graphics.setColor(255,255,255, 255)

movingText = {}

-- text value for the moving text
movingText.value = "Look at me move!"

-- X and Y values for the moving text
movingText.x = 0
movingText.y = 0

-- movement speed for the text
movingText.speed = 100

-- path/coordinates which the text has to follow
movingText.path = {}
movingText.path.x = {100, 200, 400, 500}
movingText.path.y = {100, 200, 300, 500}

-- direction of the text; 1 = horizontal, 2 = vertical, 3 = diagonal
movingText.path.direction= {2,1,2,3}

    function moveRight(goalX, speedModifier)
        if movingText.x < goalX then
          movingText.x = movingText.x + movingText.speed*speedModifier    
        
        elseif movingText.x > goalX then
            table.remove(movingText.path.x, 1)
            table.remove(movingText.path.direction, 1)
        end

    end

    function moveDown(goalY, speedModifier)
        if movingText.y < goalY then
            movingText.y = movingText.y + movingText.speed*speedModifier
        
        elseif movingText.y > goalY then
            table.remove(movingText.path.y, 1)
            table.remove(movingText.path.direction, 1)
        end
    end

end

function love.update(dt)      
speedModifier = dt    

    if movingText.path.direction[1] then
        if movingText.path.direction[1]==1 then
            moveRight(movingText.path.x[1], speedModifier)
        
        elseif movingText.path.direction[1]==2 then
            moveDown(movingText.path.y[1], speedModifier)    
        
        elseif movingText.path.direction[1]==3 then
            moveRight(movingText.path.x[1], speedModifier)
            moveDown(movingText.path.y[1], speedModifier)
        end   
    end    

end

function love.draw()
love.graphics.print(movingText.value, movingText.x, movingText.y)
end
User avatar
Eamonn
Party member
Posts: 550
Joined: Sat May 04, 2013 1:29 pm
Location: Ireland

Re: How to put text on a certain path/route?

Post by Eamonn »

Check out tween.lua. It seems be be what your looking for. Tweening is awesome(fade in's, fade out's, etc). It should be up to date(the example does not have a .lua after the require in the readme.md example, which leads me to believe it is in date).

Just thought I'd throw my hat into the ring and help you out :)
"In those quiet moments, you come into my mind" - Liam Reilly
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 1 guest