I want to automatically define incrementing variable names.
So instead of this:
$Var1 = 'This is variable one :P'
$Var2 = 'This is variable two :P'
I'd like this (pseudo code):
For $i = 1 to UBound($People)-1
**$var[$i]** = GUICtrlCreateCheckbox($var[$i], 24, $y, 200, 17)
$y = $y + 25
Next
Does anyone know how?
The code should make as many checkboxes as defined in an array and every checkbox should have its own variable.
You're looking for the Assign function!
Check out this example:
For $i = 1 To 5
Assign('var' & $i, $i);
Next
Then you can access these variables with:
MsgBox(4096, "My dynamic variables", $var1)
MsgBox(4096, "My dynamic variables", $var3)
MsgBox(4096, "My dynamic variables", $var5)
Obviously, var2 and var3 can be utilised too :)
Edit: For clarity, what you would have been doing, if you had done it properly, was storing those values in an array - which is the best method for this kind of thing.
so instead of this:
$Var1 = 'This is variable one :P'
$Var2 = 'This is variable two :P'
I'd like this (pseudo code):
For $i = 1 to UBound($People)-1
**$var[$i]** = GUICtrlCreateCheckbox($var[$i], 24, $y, 200, 17)
$y = $y + 25
Next
Does anyone know how this could be done?
As per Documentation - Intro - Arrays:
An Array is a variable containing a series of data elements. Each element in this variable can be accessed by an index number which relates to the position of the element within the Array - in AutoIt the first element of an Array is always element [0]. Arrays elements are stored in a defined order and can be sorted.
Dynamic checkbox creation example, assigning multiple checkbox-control identifiers to a single array (untested, no error-checking):
#include <GUIConstantsEx.au3>
Global Const $g_iBoxStartX = 25
Global Const $g_iBoxStartY = 25
Global Const $g_iBoxWidth = 100
Global Const $g_iBoxHeight = 15
Global Const $g_iBoxSpace = 0
Global Const $g_iBoxAmount = Random(2, 20, 1)
Global Const $g_iBoxTextEx = $g_iBoxAmount -1
Global Const $g_sBoxTextEx = 'Your text here.'
Global Const $g_iWindDelay = 50
Global Const $g_iWinWidth = $g_iBoxWidth * 2
Global Const $g_iWinHeight = ($g_iBoxStartY * 2) + ($g_iBoxHeight * $g_iBoxAmount) + ($g_iBoxSpace * $g_iBoxAmount)
Global Const $g_sWinTitle = 'Example'
Global $g_hGUI
Global $g_aID
Main()
Func Main()
$g_hGUI = GUICreate($g_sWinTitle, $g_iWinWidth, $g_iWinHeight)
$g_aID = GUICtrlCreateCheckboxMulti($g_iBoxStartX, $g_iBoxStartY, $g_iBoxWidth, $g_iBoxHeight, $g_iBoxSpace, $g_iBoxAmount)
GUICtrlSetData($g_aID[$g_iBoxTextEx], $g_sBoxTextEx)
GUISetState(#SW_SHOW, $g_hGUI)
While Not (GUIGetMsg() = $GUI_EVENT_CLOSE)
Sleep($g_iWindDelay)
WEnd
Exit
EndFunc
Func GUICtrlCreateCheckboxMulti(Const $iStartX, Const $iStartY, Const $iWidth, Const $iHeight, Const $iSpace, Const $iAmount, Const $sTextTpl = 'Checkbox #%s')
Local $iYPosCur = 0
Local $sTextCur = ''
Local $aID[$iAmount]
For $i1 = 0 To $iAmount -1
$iYPosCur = $iStartY + ($iHeight * $i1) + ($iSpace * $i1)
$sTextCur = StringFormat($sTextTpl, $i1 +1)
$aID[$i1] = GUICtrlCreateCheckbox($sTextCur, $iStartX, $iYPosCur, $iWidth, $iHeight)
Next
Return $aID
EndFunc
GUICtrlCreateCheckboxMulti() demonstrates
array declaration ($aID[$iAmount])
assignment of array elements in a For...To...Step...Next -loop ($aID[$i1] = ...).
Main() demonstrates selection of an individual element (changing its text using GUICtrlSetData()).
Adjust constants as required ($g_iBoxAmount etc.).
Related
I am trying to store the numpy.ndarrays defined as x_c, y_c, and z_c for every iteration of the loop:
for z_value in np.arange(0, 5, 1):
ms.set_current_mesh(0)
planeoffset : float = z_value
ms.compute_planar_section(planeaxis = 'Z Axis', planeoffset = planeoffset)
m = ms.current_mesh()
matrix_name = m.vertex_matrix()
x_c = matrix_name[:,0]
y_c = matrix_name[:,1]
z_c = matrix_name[:,2]
I would like to be able to recall the three arrays at any z_value, preferably with reference to the z_value i.e x_c # z_value = 2 or similar.
Thanks for any help!
p.s very new to coding, so please go easy on me.
You have to store each array in an external variable, for example a dictionary
x_c={}
y_c={}
z_c={}
for z_value in np.arange(0, 5, 1):
ms.set_current_mesh(0)
planeoffset = float(z_value)
ms.compute_planar_section(planeaxis = 'Z Axis', planeoffset = planeoffset)
m = ms.current_mesh()
m.compact()
print(m.vertex_number(), "vertices in Planar Section Z =", planeoffset)
matrix_name = m.vertex_matrix()
x_c[planeoffset] = matrix_name[:,0]
y_c[planeoffset] = matrix_name[:,1]
z_c[planeoffset] = matrix_name[:,2]
Please, ensure you call m.compact() before accessing the vertex_matrix or you will get a MissingCompactnessException error. Please, note that it is not the same to store anything in x_c[2] or in x_c[2.0], so choose if your index has to be integers o floats and keep the same type (in this example, they are floats).
Later, you can recall values like this:
print("X Values with z=2.0")
print(x_c[2.0])
How would I go about compiling values from a table using a string?
i.e.
NumberDef = {
[1] = 1,
[2] = 2,
[3] = 3
}
TextDef = {
["a"] = 1,
["b"] = 2,
["c"] = 3
}
If I was for example to request "1ABC3", how would I get it to output 1 1 2 3 3?
Greatly appreciate any response.
Try this:
s="1ABC3z9"
t=s:gsub(".",function (x)
local y=tonumber(x)
if y~=nil then
y=NumberDef[y]
else
y=TextDef[x:lower()]
end
return (y or x).." "
end)
print(t)
This may be simplified if you combine the two tables into one.
You can access values in a lua array like so:
TableName["IndexNameOrNumber"]
Using your example:
NumberDef = {
[1] = 1,
[2] = 2,
[3] = 3
}
TextDef = {
["a"] = 1,
["b"] = 2,
["c"] = 3
}
print(NumberDef[2])--Will print 2
print(TextDef["c"])--will print 3
If you wish to access all values of a Lua array you can loop through all values like so (similarly to a foreach in c#):
for i,v in next, TextDef do
print(i, v)
end
--Output:
--c 3
--a 1
--b 2
So to answer your request, you would request those values like so:
print(NumberDef[1], TextDef["a"], TextDef["b"], TextDef["c"], NumberDef[3])--Will print 1 1 2 3 3
One more point, if you're interested in concatenating lua string this can be accomplished like so:
string1 = string2 .. string3
Example:
local StringValue1 = "I"
local StringValue2 = "Love"
local StringValue3 = StringValue1 .. " " .. StringValue2 .. " Memes!"
print(StringValue3) -- Will print "I Love Memes!"
UPDATE
I whipped up a quick example code you could use to handle what you're looking for. This will go through the inputted string and check each of the two tables if the value you requested exists. If it does it will add it onto a string value and print at the end the final product.
local StringInput = "1abc3" -- Your request to find
local CombineString = "" --To combine the request
NumberDef = {
[1] = 1,
[2] = 2,
[3] = 3
}
TextDef = {
["a"] = 1,
["b"] = 2,
["c"] = 3
}
for i=1, #StringInput do --Foreach character in the string inputted do this
local CurrentCharacter = StringInput:sub(i,i); --get the current character from the loop position
local Num = tonumber(CurrentCharacter)--If possible convert to number
if TextDef[CurrentCharacter] then--if it exists in text def array then combine it
CombineString = CombineString .. TextDef[CurrentCharacter]
end
if NumberDef[Num] then --if it exists in number def array then combine it
CombineString = CombineString .. NumberDef[Num]
end
end
print("Combined: ", CombineString) --print the final product.
I try to split a string into a multidimensional array, but it is not working the way I want. I just split a string to some arrays where one 2 dimensional array should represent a table. I can see the array using _ArrayDisplay() but I cannot work with the array elements itself. The Line:
For $j = 1 To $aTable1Row[$i][0]
reports "incorrect number of subscripts". But if I do:
MsgBox(1, "TEST", UBound($aTable1Row[$i]))
it shows this array has 8 elements. So they are there but I somehow cannot access them. Full source code:
#include <Array.au3>
$string = "az#1:y#2:x#3:w#4:v#5:u#6:t#7-bz#1:y#2:x#3:w#4:v#5:u#6:t#7-cz#1:y#2:x#3:w#4:v#5:u#6:t#7"
$aTable1 = StringSplit($string, '-',1)
_ArrayDisplay($aTable1)
;3
;az#1:y#2:x#3:w#4:v#5:u#6:t#7
;bz#1:y#2:x#3:w#4:v#5:u#6:t#7
;cz#1:y#2:x#3:w#4:v#5:u#6:t#7
Local $aTable1Row[$aTable1[0]+1]
$aTable1Row[0] = $aTable1[0]
For $i = 1 To $aTable1Row[0]
$aTable1Row[$i] = StringSplit($aTable1[$i], ':',1)
_ArrayDisplay($aTable1Row[$i])
;7
;az#1
;y#2
;x#3
;w#4
;v#5
;u#6
;t#7
;do stuff
For $j = 1 To $aTable1Row[$i][0]
$aTable1Row[$i][$j] = StringTrimLeft(($aTable1Row[$i])[$j], StringInStr(($aTable1Row[$i])[$j], '#'))
Next
Next
… this array has 8 elements.
That For -loop addresses a 1 dimensional array as if it were a 2 dimensional one, hence the Array variable has incorrect number of subscripts or subscript dimension range exceeded. -error.
Declare a 2 dimensional array first. Example (no error-checking):
#include <StringConstants.au3>
#include <Array.au3>
Global Const $g_sString = 'az#1:y#2:x#3:w#4:v#5:u#6:t#7-bz#1:y#2:x#3:w#4:v#5:u#6:t#7-cz#1:y#2:x#3:w#4:v#5:u#6:t#7'
Global Const $g_sDelimRow = '-'
Global Const $g_sDelimCol = ':'
Global Const $g_aArray2D = StringSplitToArray2D($g_sString, $g_sDelimRow, $g_sDelimCol)
_ArrayDisplay($g_aArray2D, #ScriptName)
Func StringSplitToArray2D(Const $sString, Const $sDelimiterRow, Const $sDelimiterCol)
Local $aArray1DRows = StringSplit($sString, $sDelimiterRow, $STR_ENTIRESPLIT)
Local $aArray1DCols = StringSplit($aArray1DRows[1], $sDelimiterCol, $STR_ENTIRESPLIT)
Local $aArray2D[ $aArray1DRows[0] + 1 ][ $aArray1DCols[0] + 1 ]
For $i1 = 1 To $aArray1DRows[0]
$aArray1DCols = StringSplit($aArray1DRows[$i1], $sDelimiterCol, $STR_ENTIRESPLIT)
For $i2 = 1 To $aArray1DCols[0]
$aArray2D[$i1][$i2] = $aArray1DCols[$i2]
Next
Next
Return $aArray2D
EndFunc
Consider _FileReadToArray() if stored as text/CSV file. Related.
#include <StringConstants.au3>
#include <Array.au3>
Global Const $g_sString = 'az#1:y#2:x#3:w#4:v#5:u#6:t#7-bz#1:y#2:x#3:w#4:v#5:u#6:t#7-cz#1:y#2:x#3:w#4:v#5:u#6:t#7'
Global Const $g_sDelimRow = '-'
Global Const $g_sDelimCol = ':'
Global Const $g_aArray2D = StringSplit2D($g_sString, $g_sDelimCol, $g_sDelimRow)
_ArrayDisplay($g_aArray2D, #ScriptName)
Func StringSplit2D($sMatches = "Hola-2-5-50-50-100-100|Hola-6-200-200-100-100", Const $sDelim_Item = "-", Const $sDelim_Row = "|")
Local $iValDim_1, $iValDim_2 = 0, $iColCount
Local $aSplit_1 = StringSplit($sMatches, $sDelim_Row, $STR_NOCOUNT + $STR_ENTIRESPLIT)
$iValDim_1 = UBound($aSplit_1, $UBOUND_ROWS)
Local $aTmp[$iValDim_1][0], $aSplit_2
For $i = 0 To $iValDim_1 - 1
$aSplit_2 = StringSplit($aSplit_1[$i], $sDelim_Item, $STR_NOCOUNT + $STR_ENTIRESPLIT)
$iColCount = UBound($aSplit_2)
If $iColCount > $iValDim_2 Then
$iValDim_2 = $iColCount
ReDim $aTmp[$iValDim_1][$iValDim_2]
EndIf
For $j = 0 To $iColCount - 1
$aTmp[$i][$j] = $aSplit_2[$j]
Next
Next
Return $aTmp
EndFunc ;==>StringSplit2D
It is a very stable function and it was used in massive projects, tested millions of times.
Result
I'm getting a very irritating error whenever I do anything like this with arrays. I have code that sets up the array in the love.load() function:
function iceToolsInit()
objectArray = {} --for object handling
objectArrayLocation = 0
end
and then code that allows for the creation of an object. It basically grabs all of the info about said object and plugs it into an array.
function createObject(x, y, renderimage) --used in the load function
--objectArray is set up in the init function
objectArrayLocation = objectArrayLocation + 1
objectArray[objectArrayLocation] = {}
objectArray[objectArrayLocation]["X"] = x
objectArray[objectArrayLocation]["Y"] = y
objectArray[objectArrayLocation]["renderimage"] =
love.graphics.newImage(renderimage)
end
After this, an update function reads through the objectArray and renders the images accordingly:
function refreshObjects() --made for the update function
arrayLength = #objectArray
arraySearch = 0
while arraySearch <= arrayLength do
arraySearch = arraySearch + 1
renderX = objectArray[arraySearch]["X"]
renderY = objectArray[arraySearch]["Y"]
renderimage = objectArray[arraySearch]["renderimage"]
if movingLeft == true then --rotation for rightfacing images
renderRotation = 120
else
renderRotation = 0
end
love.graphics.draw(renderimage, renderX, renderY, renderRotation)
end
end
I of course clipped some unneeded code (just extra parameters in the array such as width and height) but you get the gist. When I set up this code to make one object and render it, I get this error:
attempt to index '?' (a nil value)
the line it points to is this line:
renderX = objectArray[arraySearch]["X"]
Does anyone know what's wrong here, and how I could prevent it in the future? I really need help with this.
It's off-by-one error:
arraySearch = 0
while arraySearch <= arrayLength do
arraySearch = arraySearch + 1
You run through the loop arrayLength+1 number of times, going through indexes 1..arrayLength+1. You want to go through the loop only arrayLength number of times with indexes 1..arrayLength. The solution is to change the condition to arraySearch < arrayLength.
Another (more Lua-ly way) is to write this as:
for arraySearch = 1, #objectArray do
Even more Lua-ly way is to use ipairs and table.field reference instead of (table["field"]):
function refreshObjects()
for _, el in ipairs(objectArray) do
love.graphics.draw(el.renderimage, el.X, el.Y, movingLeft and 120 or 0)
end
end
objectArray and movingLeft should probably be passed as parameters...
I will try to as concise as possible with my issue.
Firstly, files are:
block.lua
base.lua
main.lua
In block.lua I create a block, add collision detection and a cleanup code.
In base.lua I create a base made up of 4 columns and 10 rows. 40 blocks in total.
In main.lua I create 4 bases made from the base.class.
All is working fine once the game begins.
I remove the bases and call them again on level 2.
They create themselves ok BUT
when the enemy is destroyed once again, and the bases are to be rebuilt, I get an:
array index 1 is beyond array bounds:1..1
-- all the way up to--
array index 800 is beyond array bounds:1..159
it will then create the bases and continue until the enemys are destroyed and do the same again starting at :
array index 800 is beyond array bounds:1..159
-- all the way up to--
array index 4000 is beyond array bounds:1..159
The terminal points me at block.lua line 23
blockGroup:insert(blockNum,self.block)
Now I cant see anything wrong in the class, I have looked and googled for hours but all to no avail.
I would really appreciate a helping hand to guide me here please.
I have tried rewriting the "cleanup" etc but no joy.
I left a few commented out bits in there and removed some of the irrelevant stuff.
I post below the relevant code:
--MAIN.LUA--
function gameOver()
Runtime:removeEventListener("enterFrame", onEnterFrame)
Runtime:removeEventListener("enterFrame", movePlayer)
layers:removeSelf()
layers = nil
enemyCount = 0
for i = 1,#allEnemys do
timer.cancel(allEnemys[i].clock)
Runtime:removeEventListener( "enterFrame", allEnemys[i] )
display.remove(allEnemys[i].image)
allEnemys[i].image=nil
end
allEnemys=nil
cleanupBlocks()
end
----------------------------------------------------------------------
-- LEVEL UP --
----------------------------------------------------------------------
function levelUp(level)
enemyCount = 0
local enemys = require("modules.enemy")
if allEnemys ~= nil then
for i = 1,#allEnemys do
timer.cancel(allEnemys[i].clock)
Runtime:removeEventListener( "enterFrame", allEnemys[i] )
display.remove(allEnemys[i].image)
allEnemys[i].image=nil
end
end
allEnemys=nil
cleanupBlocks()
levels()
end
----------------------------------------------------------------------
-- LEVELS --
----------------------------------------------------------------------
function levels(level)
function createInvader(x, y, row)
for j = 1, 2 do
for i = 1, 2 do
if allEnemys == nil then
allEnemys = {}
else
enemysCount=#allEnemys
end
allEnemys[#allEnemys + 1] = enemys:new()
allEnemys[#allEnemys ]:init(i * 60, j * 70 + 70,j)
allEnemys[#allEnemys ]:start()
end
end
end
createInvader()
--[[function createBases1()
local base = require("modules.base")
for i = 1, 4 do
base:new()
base:init(i * 180 - 130, 850)
end
end ]]--
createBases()
end
--BLOCK.LUA--
local block = {}
local block_mt = { __index = block}
local scene = scene
local blockGroup = display.newGroup()
local blockNum = 0
function block:new() -- constructor
local group = {}
return setmetatable( group, block_mt )
end
function block:init(xloc,yloc) --initializer
-- Create attributes
self.block = display.newRect( xloc,yloc,10,10)
self.block:setFillColor ( 2, 255, 14 )
blockNum = blockNum + 1
blockGroup:insert(blockNum,self.block)
local blockCollisionFilter = { categoryBits = 128, maskBits = 387}
physics.addBody( self.block, "static", {filter = blockCollisionFilter})
self.count = 1
end
function cleanupBlocks()
--[[ print(blockNum, blockGroup.numChildren)
for i=1,blockGroup.numChildren do
blockGroup[1]:removeSelf()
blockGroup[1] = nil
end ]]--
print(blockNum, blockGroup.numChildren)
while blockGroup.numChildren>0 do
display.remove(blockGroup[1])
blockGroup[1]=nil
end
end
function block:start()
--- Create Listeneres
self.block:addEventListener( "collision", self )
scene:addEventListener('base_block_event', self)
end
return block
--BASE.LUA--
local base = {}
local base_mt = { __index = base}
local scene = scene
local block = require("modules.block")
function base:new() -- constructor
local group = {}
return setmetatable( group, base_mt )
end
function base:init(xloc, yloc) --initializer
-- Create attributes
local base
for j = 1, 4 do
for i = 1, 10 do
base = block:new()
base:init(xloc+i * 10,yloc+j * 10)
base:start()
end
end
end
return base
I see you use
blockNum = blockNum + 1
blockGroup:insert(blockNum,self.block)
Try to use
blockGroup:insert(self.block)
just to see if you still get that error.