How to reveal string one letter at a time? - lua

I'm learning from a book, and this is the assignment question i'm working on:
Create an app that asks for the users name and then displays the name down the side of the screen, one letter at a time.
Clarify what i'm trying trying to do: Have users name fade in one at a time vertically. Example: Adam "A" would appear after 1 second , "d" would appear after 3 seconds under the displayed A, "a" would appear after 5 seconds under the displayed d, "m" would appear after 7 seconds under the displayed a. The visuals would have a sort of domino effect.When they appear they would stay displayed on screen.
So far i'm able to get the user's name and display it side ways. Have it fade it in within 2 seconds. I'm stuck on how to get the letters to fade in one letter at a time.
function submit ()
print( "connect" )
userName = userNameField.text
display_userName = display.newText( userName, display.contentWidth-20, display.contentHeight/2 )
display_userName.rotation = 90
display_userName.alpha = 0
userNameField: removeSelf( )
greeting:removeSelf( )
submitButton:removeSelf( )
transition.fadeIn( display_userName, {time = 2000} )
Please let me know if you need to see more of my code.

You can do it in a simple way as below:
local myString = "Adam" -- Create your string
local positionCount = 0 -- initialize a variable to determine letter position
local function displayData()
positionCount = positionCount + 1
if(positionCount<=string.len(myString))then
-- if positionCount is less than or equal to letters in 'myString'
local letter = string.sub(myString, positionCount, positionCount) -- get the current letter
local letterLabel = display.newText(letter,20,20*positionCount,nil,20) -- place the letter
letterLabel.alpha = 0;
-- display the label and update the function after the completion of transition
transition.to(letterLabel,{time=1000,alpha=1,onComplete=displayData})
end
end
displayData()
Keep Coding.................... :)

Here is the code snippet for storing every character in a table.
Initialise a variable:
check =0;
Here splitWord is an table to store each character of string. and variable "yourStringForOneLetter" is your string variable for splitting. "string.sub" will split string into words using for loop.
if(check==wordSize) then
check=1
end
local wordSize = string.len(yourStringForOneLetter)
splitWord = {}
for i=check, check do
splitWord[i] = string.sub(yourStringForOneLetter, i, i)
check= check +1;
end

Related

Am I able to use table.concat as a set of arguments?

I'm using LOVE2D to get used to lua a bit more, and I am trying to call a function to make a circle appear on screen, there's 5 arguments, and I have a table known as 'button' with the required arguments in it. I want to use table.concat to to fill in all the blank arguments but it won't let me. Is there anyway to do this?
function toRGB(r,g,b)
return r/255,g/255,b/255
end
function love.load()
button = {}
button.mode = "fill"
button.x = 0
button.y = 0
button.size = 30
end
function love.draw()
love.graphics.setColor(toRGB(60,60,60))
love.graphics.circle(table.concat(button))
end
table.concat returns a string. That's not what you want.
To get a list of table elements use table.unpack. But this function does only work with tables that have consecutive numeric indices starting from 1.
Also love.graphics.circle accesses its parameters by position, not by name. Hence you have to ensure that the expression list you put into that function has the right order.
So something like:
button = {"fill", 0, 0, 30}
love.graphics.circle(table.unpack(button))
would work.
If you're using other table keys as in your example you'll have to write a function that returns the values in the right order.
In the simplest case
button = {}
button.mode = "fill"
button.x = 0
button.y = 0
button.size = 30
button.unpack = function() return button.mode, button.x, button.y, button.size end
love.graphics.circle(button.unpack())
Or you can do something like this:
function drawCircle(params)
love.graphics.circle(params.mode, params.x, params.y, params.size)
end
drawCircle(button)
There are many other ways to achieve this.

Getting the text of a clicked display group in Corona

To simplify my problem:
I have the following loop:
local arguments =
{
{ text="foo", x=0, y=0, font=native.systemFont, size=32 },
{ text="bar", x=0, y=0, font=native.systemFont, size=32 }
}
for _,item in ipairs( arguments ) do
local text = display.newText( item.text, item.x, item.y, item.font, item.size )
text:setFillColor( 1 ) -- white
text.x = 50 + 50 * i
text.y = 100
i = i + 1
text:addEventListener( "touch", onTouch )
end
The function onTouch is defined previously and it responds by allowing the user to drag the object around the screen.
The function works fine. However, I would like to be able to access the text of the object the user clicks in from within the onTouch function. For example, if a user clicks on text that contains the string "foo", I would be able to access this string and work with it. Is this possible? I am using Corona Starter (the free one) in case that is relevant.
Thanks in advance.
In short:
Yes, it is possible you should simply declare a variable with a string on the object as such:
text.string = "foo"
And then in your onTouch function you can reach it through
event.target.string

Corona SDK display.remove() in lua

this code (lua) gives you a random value from the table "local a" by pressing the text "new". Unfortunately the new random value just appears above the old one. I've tried to remove the old value e.g. with display.remove(mmDis), but it doesn't work.
The second problem is that sometimes I also get back the value "nil" and not only the four entries from the table.
Both things must be easy to solve, but as newbie to lua and working on these small things for almost 4 hours now I just don't get what to change to make it work.
-- references
local mmDis
-- functions
function randomText(event)
display.remove(mmDis)
local a = {"Banana!","Apple!","Potato","Pie"}
com = (a[math.random(0.5,#a)])
local mmDis = display.newText(tostring(com),
display.contentWidth*0.57, display.contentHeight*0.7,
display.contentWidth*0.9, display.contentHeight*0.8, "Calibri", 60)
end
-- menu button
local textnew = display.newText("New", 0, 0, "Calibri", 40)
textnew.x = display.contentWidth*0.2
textnew.y = display.contentHeight*0.9
textnew:addEventListener ("tap", randomText )
It's hard to understand what you are trying to do because when you create textnew you have it in one position and size, while in randomeText() you seem to want to replace that text object with a new one, but you put it at a different pos and size. It appears you want to change the object's text every time you press on tap; in this case, you don't need to replace the text object, you just replace its text.
Also:
you have two "local mmDis", the second one will hide the first, not sure what you're after there
read carefully the docs for math.random
com is already a string so you don't need tostring
Try this code and let me know if this is not what you are after:
local menuTextOptions = {
text = "New",
x = display.contentWidth*0.2,
y = display.contentHeight*0.9,
align = 'left',
font = "Calibri",
fontSize = 40,
}
local textnew = display.newText(menuTextOptions)
-- functions
function randomText(event)
local a = {"Banana!","Apple!","Potato","Pie"}
local com = a[math.random(1,#a)]
textnew.text = com
-- if you want to change position too:
-- textnew.x = display.contentWidth*0.2
-- textnew.y = display.contentHeight*0.9
-- if you want to change size too, but only used for multiline text:
-- textnew.width = display.contentWidth*0.9
-- textnew.height = display.contentHeight*0.8
end
textnew:addEventListener ("tap", randomText )
Sometimes it looks like the button doesn't do anything when you tap but that's because the random number happens to be same as previous, you could put a loop to guard against that. Ig you actually want to change the pos and/or width, then the above code makes it clear where you should do that.
So, that's the basic code (without any extras at the moment :)) how it should be. Big thanks to Scholli!:
local menuTextOptions = {
text = "New",
x = display.contentWidth*0.2,
y = display.contentHeight*0.9,
align = 'left',
font = "Calibri",
fontSize = 40,
}
local textnew = display.newText(menuTextOptions)
local replacement = display.newText(menuTextOptions)
replacement.y = display.contentHeight*0.5
-- functions
function randomText(event)
local a = {"Banana!","Apple!","Potato","Pie"}
local com = a[math.random(1,#a)]
replacement.text = com
end
textnew:addEventListener ("tap", randomText )

How to hide native.newTextField after clicking submit?

I'm trying trying to have users name fade in one letter at a time vertically. Example: Adam "A" would appear after 1 second , "d" would appear after 3 seconds under the displayed A, "a" would appear after 5 seconds under the displayed d, "m" would appear after 7 seconds under the displayed a. The visuals would have a sort of domino effect.When they appear they would stay displayed on screen.
When if I comment out userNameField:removeSelf () then the code works fine. I get the effect I want, but the problem is that I still have the userNamefield showing.
Please let me know if you need to see more code.
local greeting = display.newText( "Greetings, enter your name",0,0,native.systemFont, 20 )
greeting.x = display.contentWidth/2
greeting.y = 100
local submitButton = display.newImage( "submit.png" ,display.contentWidth/2, display.contentHeight - 50 )
local userNameField = native.newTextField( display.contentWidth * 0.5 , 150, 250, 45)
userNameField.inputtype = "defualt"
local incrementor = 0
function showNameLetters()
userNameField:removeSelf( )
if incrementor <= string.len ("userNameField.text") then
incrementor = incrementor + 1
personLetters = string.sub (userNameField.text, incrementor,incrementor)
display_personLetters = display.newText (personLetters, 290,30*incrementor, native.systemFont, 30)
display_personLetters.alpha = 0
transition.to(display_personLetters,{time = 3000, alpha = 1, onComplete = showNameLetters})
end
end
Update:
I've found a solution to my problem, by adding userNameField.isVisible = false in my function.
I've also found something very weird, and wish to have someone explain why this happens. If I add greeting:removeSelf() and submitButton:removeSelf() (I've commented them out in my code below to show you where I put them for testing). I get weird result of only the first letter fading in. If i set greeting.isVisible = false and submitButton.isVisible = false. The code works fine.
I'm so confused why object:removeSelf() wouldn't work. Can someone please clear this up for me.
That is, if I replace the following line:
userNameField:removeSelf( )
with:
userNameField.isVisible = false
then the app works fine. Please suggest me why/ any solution for the question. THanks in advance...
It seems like you're calling the showNameLetters multiple times, this means that you're removing the native text field more than once. Nil it and check for nil before removing it like this:
if userNameField ~= nil then
userNameField:removeSelf()
userNameField = nil
end
It shows that you are using data from userNameField after removing it (in the line below):
personLetters = string.sub (userNameField.text, incrementor,incrementor)
As well as you are calling object:removeSelf() again and again without checking its existance (as mentioned by hades2510). So before removing userNameField, check for it's existance:
if userNameField ~= nil then
userNameField:removeSelf()
userNameField = nil
end
And you won't get userNameField.text while userNameField is nil. So use a temporary variable to hold the previous userNameField.text and get the saved data from that variable when needed.
Extra note: Are you sure, you have to check the length of the text "userNameField.text" in the following line, or the variable userNameField.text? If you have to use the data from the text field, then this will also matter.
if incrementor <= string.len ("userNameField.text") then
........
end
Keep coding....................... :)

Attempt to index global 'player' (a nil value)

I'm getting a (a nil value) error when i try to do this :
player = display.newSprite( imageSheet, "sequenceDataPlayer"..math.random(1, 7) )
Looking at a test print :
print ("sequenceDataPlayer"..math.random(1, 7) )
It prints the data oky 'sequenceDataPlayer1'
What Im i doing wrong here ?
Your print statement is just printing the string "sequenceDataPlayer" concatenated with a random number between 1 and 7.
It took me a little while to figure out how to use sprites in Corona, but here's how I do it. I'll use Player for the variables since that's what you're using.
First I create an options variable to get the frames from my Player.lua file:
optionsPlayer =
{
frames = require("player").frames,
}
Then I create a variable for the image sheet:
playerSheet = graphics.newImageSheet( "player.png", optionsPlayer )
After that, I create a variable to set up the name, the sequence of frames, the time it takes to play, and set how many times it will loop:
spriteOptionsPlayer = { name="Player", start=1, count=10, time=500, loopCount = 1}
Finally, I create the new sprite:
spriteInstancePlayer = display.newSprite( playerSheet, spriteOptionsPlayer )
Once I've done all this, I usually set up the x and y positions, xScale and yScale, and other properties along with adding it to a display group.
Last of all, then I play the sprite somewhere:
spriteInstancePlayer:play()
From what it looks like, you want to have 7 different sprites to choose from. Personally, I would just create seven different sprites using all of the steps above and then put them in a table.
sprites = { spriteInstancePlayer, spriteInstancePlayer2, spriteInstancePlayer3, etc.. }
Then when I wanted to play them, I would set the position and visibility and just do:
r = math,random(1, 7)
sprites[r].x = x position
sprites[r].y = y position
sprites[r].isVisible = true
sprites[r]:play()
Of course, then I would want to set listeners to either completely remove the sprite or set the visibility to false when it's done playing, there's a collision(you'd have to add a physics body and set that all up), or whatever else might happen...
There are probably simpler ways to do it, but that's what I do.
Hope this helps.

Resources