Making a cubic ease-in-out curve dynamically switch its goal position - lua

Using, Lua, I've made a function to cubically (easing in/"accelerating", then easing out/"decelerating" afterwards) interpolate from one number to another; SimpleSpline takes a number between 0-1 (the time the animation's been going, easiest put), and SimpleSplineBetween does the same, but keeps it in between two given minimum/maximum values.
function SimpleSpline( v )
local vSquared = v*v
return (3 * vSquared - 2 * vSquared * v)
end
function SimpleSplineBetween( mins, maxs, v )
local fraction = SimpleSpline( v )
return (maxs * fraction + mins * (1 - fraction))
end
It all works fine. However, I've run into a bit of an issue. I'd like this to be a bit more dynamic. For example, assume my "mins" is 0.5, and my "maxs" is 1, then I have a variable for time that I pass as V; we'll say it's 0.5, so our current interpolation value is 0.75. Now, let's also assume that suddenly, "maxs" is jerked up to 0.25, so now, we have a new goal to reach.
My current approach to handling situations like the above is to reset our "time" variable and change "mins" to our current value; in the above case 0.75, etc. However, this produces a very noticable "stop" or "freeze" in the animation, because it is being entirely reset.
My question is, how can I make this dynamic without that stop? I'd like it to transition smoothly from moving to one goal number to another.

local Start_New_Spline, Calculate_Point_on_Spline, Recalculate_Old_Spline
do
local current_spline_params
local function Start_New_Spline(froms, tos)
current_spline_params = {d=0, froms=froms, h=tos-froms, last_v=0}
end
local function Calculate_Point_on_Spline(v) -- v = 0...1
v = v < 0 and 0 or v > 1 and 1 or v
local d = current_spline_params.d
local h = current_spline_params.h
local froms = current_spline_params.froms
current_spline_params.last_v = v
return (((d-2*h)*v+3*h-2*d)*v+d)*v+froms
end
local function Recalculate_Old_Spline(new_tos)
local d = current_spline_params.d
local v = current_spline_params.last_v
local h = current_spline_params.h
local froms = current_spline_params.froms
froms = (((d-2*h)*v+3*h-2*d)*v+d)*v+froms
d = ((3*d-6*h)*v+6*h-4*d)*v+d
current_spline_params = {d=d, froms=froms, h=new_tos-froms, last_v=0}
end
end
Usage example according to your values:
Start_New_Spline(0.5, 1) -- "mins" is 0.5, "maxs" is 1
local inside_spline = true
while inside_spline do
local goal_has_changed = false
for time = 0, 1, 0.015625 do -- time = 0...1
-- It's time to draw next frame
goal_has_changed = set to true when goal is changed
if goal_has_changed then
-- time == 0.5 -> s == 0.75, suddenly "maxs" is jerked up to 0.25
Recalculate_Old_Spline(0.25) -- 0.25 is the new goal
-- after recalculation, "time" must be started again from zero
break -- exiting this loop
end
local s = Calculate_Point_on_Spline(time) -- s = mins...maxs
Draw_something_at_position(s)
wait()
end
if not goal_has_changed then
inside_spline = false
end
end

Related

How can I change color depending on health?

I want to know how to edit my script below to make the color lower or higher depending on the health amount instead of a set amount in the script. Everything works currently, i'm just trying to edit the script to do what I said above.
local parts = script.Parent.Parent:WaitForChild("Collectables"):GetChildren()
for i, v in pairs(parts) do
if v:IsA("Part") then
if v:WaitForChild("ClickDetector") then
if v:FindFirstChild("Values") then
local Values = v:FindFirstChild("Values")
Values.Red.Value = 0
Values.Green.Value = 255
Values.Blue.Value = 0
Values.Health.Value = 100
Values.Change.Value = true
v.SurfaceGui.TextLabel.Text = 100
Values.Color.Value = Color3.fromRGB(Values.Red.Value,Values.Green.Value,Values.Blue.Value)
v.SurfaceGui.TextLabel.TextColor3 = Values.Color.Value
v.ClickDetector.MouseClick:Connect(function()
if Values.Health.Value > 5 then
Values.Health.Value -= 5
else
v:Destroy()
end
if v:FindFirstChild("SurfaceGui") then
v.SurfaceGui.TextLabel.Text = v.SurfaceGui.TextLabel.Text - 5
if Values.Change.Value == true then
if Values.Red.Value < 250 then
Values.Red.Value += 50
elseif Values.Red.Value == 250 then
Values.Red.Value += 5
elseif Values.Red.Value == 255 and Values.Green.Value > 5 then
Values.Green.Value -= 50
elseif Values.Green.Value == 5 then
Values.Green.Value -= 5
Values.Change.Value = false
end
Values.Color.Value = Color3.fromRGB(Values.Red.Value,Values.Green.Value,Values.Blue.Value)
v.SurfaceGui.TextLabel.TextColor3 = Values.Color.Value
end
end
end)
end
end
end
end
Rather than use your stepwise function for calculating the color, a more simple way to handle this might be to define the colors you want ahead of time or simplify it down to ranges of colors based on health. Like,
if it's between 100 - 60, the color is green.
if it's between 60 - 30, it's yellow.
if it's less than 30, it is red.
And to make the color react to the health, I would set up a series of dependencies using the Changed signal on your NumberValue objects.
The ClickDetector's only job is to modify the health of the block. But when the health changes, the color values change. And when the color values change, the text color changes too.
First off, delete the R, G, and B NumberValues, you can set the text color without them.
local DEFAULT_HEALTH = 100
local HEALTH_PER_CLICK = 5
-- colors are sorted by health in descending order, add more as desired
local COLORS = {
{ health = 60, color = Color3.fromRGB( 0, 255, 0)}, -- green
{ health = 30, color = Color3.fromRGB(255, 255, 0)}, -- yellow
{ health = 0, color = Color3.fromRGB(255, 0, 0)}, -- red
}
local function observeHealthChanges(values, textLabel)
-- whenever the health changes, update the text and the text color
local health = values.Health
health.Changed:Connect(function(newValue)
textLabel.Text = tostring(newValue)
-- set the color based on the health by looping through the colors to find the right ones
for i, colorData in ipairs(COLORS) do
local colorRange = colorData.health
local healthColor = colorData.color
if newValue > colorRange then
textLabel.TextColor3 = healthColor
break
end
end
end)
end
local function observeClicks(part, values, detector)
local health = values.Health
-- listen for clicks to reduce the health
detector.MouseClick:Connect(function()
if health.Value > HEALTH_PER_CLICK then
health.Value -= HEALTH_PER_CLICK
else
part:Destroy()
end
end)
end
local parts = script.Parent.Parent:WaitForChild("Collectables"):GetChildren()
for _, v in ipairs(parts) do
-- escape if the object isn't a part
if v:IsA("Part") then
-- escape if the part doesn't have Values, a ClickDetector, and a SurfaceGui
local Values = v.Values
local Detector = v.ClickDetector
local Gui = v.SurfaceGui
if Values and Detector and Gui then
-- register the change listeners
local textLabel = v.SurfaceGui.TextLabel
observeHealthChanges(Values, textLabel)
observeClicks(v, Values, Detector)
-- set the health and all the rest will follow
Values.Health.Value = DEFAULT_HEALTH
end
end
end

Attempt to index field (a nil value), for an Object

I have a problem with trying to add things to a LOVE2D version of Match-3. (From the CS50 course)
I added a function swapTiles() into my Board class and made a class object called self.board in a Class called PlayState. Then when I try to access the new function, it says this error:
Error
src/states/PlayState.lua:155: attempt to index field 'board' (a nil value)
I'll provide my Board and PlayState class below:
Board: (keep in mind the new function is literally in the code)
Board = Class{}
function Board:init(x, y, level) -- Added "level" as an integer for the block variations.
self.x = x
self.y = y
self.matches = {}
self.level = level
self:initializeTiles()
end
function Board:swapTiles(tile1, tile2)
-- swap grid positions of tiles
local tempX = tile1.gridX
local tempY = tile1.gridY
tile1.gridX = tile2.gridX
tile1.gridY = tile2.gridY
tile2.gridX = tempX
tile2.gridY = tempY
-- swap tiles in the tiles table
self.tiles[tile1.gridY][tile1.gridX] = tile1
self.tiles[tile2.gridY][tile2.gridX] = tile2
end
function Board:initializeTiles()
self.tiles = {}
-- There should only be two shiny tiles.
for tileY = 1, 8 do
-- empty table that will serve as a new row
table.insert(self.tiles, {})
for tileX = 1, 8 do
self.isPowerup = false
if math.random(1, 25) == 4 then
self.isPowerup = true
end
-- create a new tile at X,Y with a random color and variety
table.insert(self.tiles[tileY], Tile(tileX, tileY, math.random(18), math.min(8, math.random(1, self.level)), self.isPowerup))
end
end
while self:calculateMatches() do
-- recursively initialize if matches were returned so we always have
-- a matchless board on start
self:initializeTiles()
end
end
--[[
Goes left to right, top to bottom in the board, calculating matches by counting consecutive
tiles of the same color. Doesn't need to check the last tile in every row or column if the
last two haven't been a match.
]]
function Board:calculateMatches()
local matches = {}
-- how many of the same color blocks in a row we've found
local matchNum = 1
-- horizontal matches first
for y = 1, 8 do
local colorToMatch = self.tiles[y][1].color
matchNum = 1
-- every horizontal tile
for x = 2, 8 do
-- if this is the same color as the one we're trying to match...
if self.tiles[y][x].color == colorToMatch then
matchNum = matchNum + 1
else
-- set this as the new color we want to watch for
colorToMatch = self.tiles[y][x].color
-- if we have a match of 3 or more up to now, add it to our matches table
if matchNum >= 3 then
local match = {}
-- go backwards from here by matchNum
for x2 = x - 1, x - matchNum, -1 do
-- add each tile to the match that's in that match
table.insert(match, self.tiles[y][x2])
-- Shiny Check
if self.tiles[y][x2].isShiny == true then
for i = 1, 8 do
table.insert(match, self.tiles[y][i])
end
end
end
-- add this match to our total matches table
table.insert(matches, match)
end
-- don't need to check last two if they won't be in a match
if x >= 7 then
break
end
matchNum = 1
end
end
-- account for the last row ending with a match
if matchNum >= 3 then
local match = {}
-- go backwards from end of last row by matchNum
for x = 8, 8 - matchNum + 1, -1 do
table.insert(match, self.tiles[y][x])
end
table.insert(matches, match)
end
end
-- vertical matches
for x = 1, 8 do
local colorToMatch = self.tiles[1][x].color
matchNum = 1
-- every vertical tile
for y = 2, 8 do
if self.tiles[y][x].color == colorToMatch then
matchNum = matchNum + 1
else
colorToMatch = self.tiles[y][x].color
if matchNum >= 3 then
local match = {}
for y2 = y - 1, y - matchNum, -1 do
table.insert(match, self.tiles[y2][x])
if self.tiles[y2][x].isShiny == true then
for i = 1, 8 do
table.insert(match, self.tiles[i][x])
end
end
end
table.insert(matches, match)
end
matchNum = 1
-- don't need to check last two if they won't be in a match
if y >= 7 then
break
end
end
end
-- account for the last column ending with a match
if matchNum >= 3 then
local match = {}
-- go backwards from end of last row by matchNum
for y = 8, 8 - matchNum, -1 do
table.insert(match, self.tiles[y][x])
end
table.insert(matches, match)
end
end
-- store matches for later reference
self.matches = matches
-- return matches table if > 0, else just return false
return #self.matches > 0 and self.matches or false
end
--[[
Remove the matches from the Board by just setting the Tile slots within
them to nil, then setting self.matches to nil.
]]
function Board:removeMatches()
for k, match in pairs(self.matches) do
for k, tile in pairs(match) do
self.tiles[tile.gridY][tile.gridX] = nil
end
end
self.matches = nil
end
--[[
Shifts down all of the tiles that now have spaces below them, then returns a table that
contains tweening information for these new tiles.
]]
function Board:getFallingTiles()
-- tween table, with tiles as keys and their x and y as the to values
local tweens = {}
-- for each column, go up tile by tile till we hit a space
for x = 1, 8 do
local space = false
local spaceY = 0
local y = 8
while y >= 1 do
-- if our last tile was a space...
local tile = self.tiles[y][x]
if space then
-- if the current tile is *not* a space, bring this down to the lowest space
if tile then
-- put the tile in the correct spot in the board and fix its grid positions
self.tiles[spaceY][x] = tile
tile.gridY = spaceY
-- set its prior position to nil
self.tiles[y][x] = nil
-- tween the Y position to 32 x its grid position
tweens[tile] = {
y = (tile.gridY - 1) * 32
}
-- set space back to 0, set Y to spaceY so we start back from here again
space = false
y = spaceY
spaceY = 0
end
elseif tile == nil then
space = true
if spaceY == 0 then
spaceY = y
end
end
y = y - 1
end
end
-- create replacement tiles at the top of the screen
for x = 1, 8 do
for y = 8, 1, -1 do
local tile = self.tiles[y][x]
-- if the tile is nil, we need to add a new one
if not tile then
local tile = Tile(x, y, math.random(18), math.random(1, self.level))
tile.y = -32
self.tiles[y][x] = tile
tweens[tile] = {
y = (tile.gridY - 1) * 32
}
end
end
end
return tweens
end
function Board:getNewTiles()
return {}
end
function Board:testForMatches()
for y = 1, 8 do
for x = 1, 8 do
-- Test for left swap
if x > 1 then
end
end
end
end
function Board:render()
for y = 1, #self.tiles do
for x = 1, #self.tiles[1] do
self.tiles[y][x]:render(self.x, self.y)
end
end
end
Here's my PlayState: (look for PlayState:swapTiles(), keep in mind that the self.board is being used several times for and works fine, except when i try calling self.board:swapTiles().)
PlayState = Class{__includes = BaseState}
function PlayState:init()
-- start our transition alpha at full, so we fade in
self.transitionAlpha = 255
-- position in the grid which we're highlighting
self.boardHighlightX = 0
self.boardHighlightY = 0
-- timer used to switch the highlight rect's color
self.rectHighlighted = false
-- flag to show whether we're able to process input (not swapping or clearing)
self.canInput = true
-- tile we're currently highlighting (preparing to swap)
self.highlightedTile = nil
self.score = 0
self.timer = 60
-- set our Timer class to turn cursor highlight on and off
Timer.every(0.5, function()
self.rectHighlighted = not self.rectHighlighted
end)
-- subtract 1 from timer every second
Timer.every(1, function()
self.timer = self.timer - 1
-- play warning sound on timer if we get low
if self.timer <= 5 then
gSounds['clock']:play()
end
end)
end
function PlayState:enter(params)
-- grab level # from the params we're passed
self.level = params.level
-- spawn a board and place it toward the right
self.board = params.board or Board(VIRTUAL_WIDTH - 272, 16)
-- grab score from params if it was passed
self.score = params.score or 0
-- score we have to reach to get to the next level
self.scoreGoal = self.level * 1.25 * 1000
end
function PlayState:update(dt)
if love.keyboard.wasPressed('escape') then
love.event.quit()
end
-- go back to start if time runs out
if self.timer <= 0 then
-- clear timers from prior PlayStates
Timer.clear()
gSounds['game-over']:play()
gStateMachine:change('game-over', {
score = self.score
})
end
-- go to next level if we surpass score goal
if self.score >= self.scoreGoal then
-- clear timers from prior PlayStates
-- always clear before you change state, else next state's timers
-- will also clear!
Timer.clear()
gSounds['next-level']:play()
-- change to begin game state with new level (incremented)
gStateMachine:change('begin-game', {
level = self.level + 1,
score = self.score
})
end
if self.canInput then
-- move cursor around based on bounds of grid, playing sounds
if love.keyboard.wasPressed('up') then
self.boardHighlightY = math.max(0, self.boardHighlightY - 1)
gSounds['select']:play()
elseif love.keyboard.wasPressed('down') then
self.boardHighlightY = math.min(7, self.boardHighlightY + 1)
gSounds['select']:play()
elseif love.keyboard.wasPressed('left') then
self.boardHighlightX = math.max(0, self.boardHighlightX - 1)
gSounds['select']:play()
elseif love.keyboard.wasPressed('right') then
self.boardHighlightX = math.min(7, self.boardHighlightX + 1)
gSounds['select']:play()
end
-- if we've pressed enter, to select or deselect a tile...
if love.keyboard.wasPressed('enter') or love.keyboard.wasPressed('return') then
-- if same tile as currently highlighted, deselect
local x = self.boardHighlightX + 1
local y = self.boardHighlightY + 1
-- if nothing is highlighted, highlight current tile
if not self.highlightedTile then
self.highlightedTile = self.board.tiles[y][x]
-- if we select the position already highlighted, remove highlight
elseif self.highlightedTile == self.board.tiles[y][x] then
self.highlightedTile = nil
-- if the difference between X and Y combined of this highlighted tile
-- vs the previous is not equal to 1, also remove highlight
elseif math.abs(self.highlightedTile.gridX - x) + math.abs(self.highlightedTile.gridY - y) > 1 then
gSounds['error']:play()
self.highlightedTile = nil
else
self:swapTiles(self.highlightedTile, self.board.tiles[y][x], true)
end
end
end
Timer.update(dt)
end
function PlayState:swapTiles(tile1, tile2, swapBackAtNoMatch)
local tile1 = tile1
local tile2 = tile2
local swapBackAtNoMatch = swapBackAtNoMatch
self.board:swapTiles(tile1, tile2) -- Causes the nil error.
if swapBackAtNoMatch then
-- tween coordinates between two swapping tiles
Timer.tween(0.1, {
[tile1] = {x = tile2.x, y = tile2.y},
[tile2] = {x = tile1.x, y = tile1.y}
})
-- once they've swapped, tween falling blocks
:finish(function ()
local matches = self.board:calculateMatches()
if matches then
self.calculateMatches(matches)
else
-- swap back if there's no match
self.swapTiles(tile1, tile2, false)
gSounds['error']:play()
end
end)
else
-- tween coordinates between the two so they swap
Timer.tween(0.1, {
[tile1] = {x = tile2.x, y = tile2.y},
[tile2] = {x = tile1.x, y = tile1.y}})
end
end
--[[
Calculates whether any matches were found on the board and tweens the needed
tiles to their new destinations if so. Also removes tiles from the board that
have matched and replaces them with new randomized tiles, deferring most of this
to the Board class.
]]
function PlayState:calculateMatches()
self.highlightedTile = nil
-- if we have any matches, remove them and tween the falling blocks that result
local matches = self.board:calculateMatches()
if matches then
gSounds['match']:stop()
gSounds['match']:play()
-- add score for each match
for k, match in pairs(matches) do
local varietyPoints = 0 -- We'll keep track of the bonus variety points here
-- We'll use vareity to calculate points for each tile within a match
for j, tiles in pairs(match) do
varietyPoints = varietyPoints + tiles.variety * 25
end
self.score = self.score + (#match * 50) + varietyPoints
-- Also add one second times the number of match to the timer
self.timer = self.timer + #match * 1
end
-- remove any tiles that matched from the board, making empty spaces
self.board:removeMatches()
-- gets a table with tween values for tiles that should now fall
local tilesToFall = self.board:getFallingTiles()
-- first, tween the falling tiles over 0.25s
Timer.tween(0.25, tilesToFall):finish(function()
local newTiles = self.board:getNewTiles()
-- then, tween new tiles that spawn from the ceiling over 0.25s to fill in
-- the new upper gaps that exist
Timer.tween(0.25, newTiles):finish(function()
-- recursively call function in case new matches have been created
-- as a result of falling blocks once new blocks have finished falling
self:calculateMatches()
end)
end)
-- if no matches, we can continue playing
else
self.canInput = true
end
end
Honestly doesn't make much sense. Please help!
function PlayState:swapTiles(tile1, tile2, swapBackAtNoMatch) end
is syntactic sugar for
PlayState.swaptiles = function(self, tile1, tile2, swapBackAtNoMatch) end
That's the reason why you can work with self inside that function.
A function defined like that needs to be called using the colon operator as well to make this work. Or you explicitly provide the table as first parameter.
Hence in your call self.swapTiles(tile1, tile2, false)
self is going to be tile1
tile1.board is nil so self.board is nil in this function call which causes the error
You have to call self:swapTiles(tile1, tile2, false) or self.swapTiles(self, tile1, tile2, false)
Please make sure you fully understand the colon syntax.

ROBLOX - Trying to get my desired effect?

sorry about the vague title, I have no idea on how to explain what I'm trying to do.
I'm trying to replicate a "choosing"(?) effect from a ROBLOX game shown here
I've gotten to basically the exact same thing, except for one problem. It always stops on the same part every time (the top). Posting here is my current last resort (the scripting subforum on roblox is incredibly inactive)
for i = 1, 3 do
for _, ll in pairs(P:GetChildren()) do
lastbcolor = ll.BrickColor
ll.BrickColor = BrickColor.Yellow()
wait(t)
ll.BrickColor = lastbcolor
lastpicked = ll
print(t)
t=t+0.2 -- to slow down
end
end
math.randomseed(os.time())
local t = P:GetChildren()
local N = #t -- number of menu items
local K = 1
for R = 20 + math.random(N), 1, -1 do
ll = t[K]
local lastbcolor = ll.BrickColor
ll.BrickColor = BrickColor.Yellow()
wait( R^-.7*.7 )
ll.BrickColor = lastbcolor
K = K % N + 1
end
ll = t[K]
-- blink
for R = 1, 5 do
local lastbcolor = ll.BrickColor
ll.BrickColor = BrickColor.Yellow()
wait( .3 )
ll.BrickColor = lastbcolor
wait( .3 )
end

C-Frame Sliding Door in Roblox Studio Script

With the current complexity of scripting, and my abilities, i have hit a dead end with working out how to create a sliding door in the Popular MMO, "Roblox".
I have analyzed the script automatically, and manually, and have not found any errors.
Here it is below:
local Part = workspace.Part
local newPos = Part.Position + Vector3.new(-61.866, 8.551, -97.181)
local Time = 5
local Increment = 0.5
local Debounce = false
local Diff = newPos - Part.Position
local Mag = Diff.magnitude
local Direction = CFrame.new(Part.Position, newPos).lookVector
function MovePart()
if Debounce then return end
Debounce = true
for n = 0, Mag, Increment do
Part.CFrame = Part.CFrame + (Direction * Increment)
wait( (Time/Mag) * Increment )
end
Debounce = false
end
workspace.Button.ClickDetector.MouseClick:connect(MovePart)
When i have inserted a Button with a Clickdetector inside, and tried to click the button, no results have been shown- not even an error! I am stuck, and require assistance. It would be much appreciated.
Hmmm, works for me.
Is it already at (-61.866, 8.551, -97.181)?
Is there another "Part" or "Button"?
Is it not anchored and something in the way?
Alternate solution:
Put the button, part, and the following script together in a model.
local Part = script.Parent.Part
local Button = script.Parent.Button
Part.Anchored = true
local Direction = Part.CFrame.lookVector
local Mag = Part.Size.Z
local Time = 5
local Increment = 0.5 -- Smaller will make smoother 'movement'
local Debounce = false
function MovePart()
if Debounce then return end
Debounce = true
for n = 0, Mag, Increment do
Part.CFrame = Part.CFrame + (Direction * Increment)
wait(Time/(Mag * Increment))
end
for n = 0, Mag, Increment do
Part.CFrame = Part.CFrame + (Direction * -Increment) -- so that it moves back
wait(Time/(Mag * Increment))
end
Debounce = false
end
clickD = Button.ClickDetector or Instance.new("ClickDetector",Button)
clickD.MouseClick:connect(MovePart)
Hope that helps.
all you have to do is place a part in the workspace, rename it "Button" and insert a clickDetector into the part.

Generate and manipulate a table of "complex" objects in CoronaSDK

I'm trying to generate 40 circles with text and I want to be able to use them and handle them later.
According to several post I found here and on corona forums, I'm doing it well but, in all the examples, is only with one "display" object... not with several so I'm not sure if it's possible or maybe it needs something different.
After some introduction... here the code:
function _.spawn(params)
local orb = display.newCircle( display.contentWidth/2, display.contentHeight/2, 40 ) -- creates the orb shape
orb.orbTable = params.orbTable --assign the internal table
orb.index = #orb.orbTable + 1 -- takes control of the index
orb.orbTable[orb.index] = orb -- assign a orb to the internal table
orb:setFillColor( unpack(params.color) ) -- change the color according to the rules above
orb.x = params.x -- control the X position of the orb
orb.y = params.y --control the Y position of the orb
orb.alpha = 1 -- borns with alpha = 0
orb.value = params.value -- assign the internal value of the orb (1-10)
--local orbText = display.newText( orb.value, orb.x+2, orb.y-5, "Aniron", 40 ) -- generates the value on the ball
--orbText.orbTable = params.orbTable
--orbText.index = #orbText.orbTable + 1
--orbText.orbTable[orbText.index] = orbText
--orbText:setFillColor( 0,0,0 )
--orbText.alpha = 1
--The objects group
orb.group = params.group or nil
--If the function call has a parameter named group then insert it into the specified group
orb.group:insert(orb)
--orb.group:insert(orbText)
--Insert the object into the table at the specified index
orb.orbTable[orb.index] = orb
return orb -- returns the orb to have control of it
end
The function to generate all the objects I need is:
function _.generateDeck()
for i = 1, 40 do -- loop to generate the 40 orbs
internalValue = internalValue + 1 -- counter to assigns the right values
if (internalValue > 10) then -- if the internal value is more than 10 starts again (only 1-10)
internalValue = 1
end
if (i >= 1 and i <= 10) then -- assign RED color to the first 10 orbs
completeDeck[i] = _.spawn({color = {196/255,138/255,105/255}, group = orbsGroup, x = 100, y = display.contentHeight / 2, value = internalValue, orbTable = completeDeck})
elseif (i >= 11 and i <= 20) then -- assigns YELLOW color to the next 10 orbs
completeDeck[i] = _.spawn({color = {229/255,214/255,142/255}, group = orbsGroup, x = 100, y = display.contentHeight / 2, value = internalValue, orbTable = completeDeck})
elseif (i >= 11 and i <= 30) then -- assigns BLUE color to the next 10 orbs
completeDeck[i] = _.spawn({color = {157/255,195/255,212/255}, group = orbsGroup, x = 100, y = display.contentHeight / 2, value = internalValue, orbTable = completeDeck})
elseif (i >= 11 and i <= 40) then -- assigns GREEN color to the next 10 balls
completeDeck[i] = _.spawn({color = {175/255,181/255,68/255}, group = orbsGroup, x = 100, y = display.contentHeight / 2, value = internalValue, orbTable = completeDeck})
end
end
end
After calling the function, it generates the circles correctly and I can read the value:
for i = 1, #completeDeck do
print("Complete Deck Value ("..i.."): "..completeDeck[i].value)
end
But if I uncomment the lines regarding the newText (orbText) then I'm not able to read the values... (value is a nil value)
I guess I need to create a displayGroup with the objects I want inside (circle and text), then "spawn" it, modifying the values? In that case... how can I refer to the object inside the displayGroup?
I think I'm mixing different concepts.
In Lua, objects are tables and to create an object composed of existing objects, we create a table with and add the objects to it as values. The code below creates an objects with orb and orbText which can be accessed by object.orb or object.orbText
function _.spawn(params)
local orb = display.newCircle(display.contentWidth/2, display.contentHeight/2, 40) -- creates the orb shape
orb:setFillColor(unpack(params.color))
orb.x = params.x
orb.y = params.y
orb.alpha = 1
local orbText = display.newText(param.value, param.x + 2, param.y - 5, "Aniron", 40)
orbText:setFillColor(0, 0, 0)
orbText.alpha = 1
-- create an object with orb and orbText as values
local object = {orb = orb, orbText = orbText}
-- add more values to the object
object.value = params.value
object.index = #params.orbTable + 1
params.orbTable[object.index] = object
return object
end
Now to use the object:
for i, object in ipairs(completeDeck) do
print(object.value)
end

Resources