How to access the object names when they are created randomly - lua

Random objects are created on the screen with the help of code written below. I want to give these random objects name and access it when user taps a particular object, i am actually creating a game
when user taps on a particular objects, then only that particular object must shoot. Please give any suggestion thanks...
imageHolder = {}
numOfImages = 10
for i=1,numOfImages do
imageHolder[i] = display.newImageRect("myImage.png", 20, 20)
imageHolder[i].name="images"
imageHolder[i].x = math.random(0, display.contentWidth)
imageHolder[i].y = math.random(0, display.contentHeight)
end

you can achieve it by giving each object a unique ID you can refer to my code and if you tap every square it will print the ID you assign to them
imageHolder = {}
numOfImages = 10
local function onTap(event)
local t = event.target
-- t.name is the name you assign to the object
print(t.name)
end
for i=1,numOfImages do
imageHolder[i] = display.newRect(0,0, 20, 20)
imageHolder[i].name="images "..i
imageHolder[i].x = math.random(0, display.contentWidth)
imageHolder[i].y = math.random(0, display.contentHeight)
imageHolder[i]:addEventListener("tap", onTap)
end

Related

Displaying a random object chosen from a table

I'm trying to create a function that would choose one of four objects from a table that would then create it. Essentially what's meant to happen is if objects 1-3 are chosen they would be considered "regular" and the "player" would have to catch them while the fourth object is "special" and would take points away if caught.
here's the table
local objects = {
"object1",
"object2",
"object3",
"object4"
}
this is the code I'm using in place of what I want currently (mostly to make sure everything else in my code is working)
local function spawnObject()
object = display.newImage("images/object1.png")
object.x = math.random(screenLeft+ 30, screenRight-30)
object.y = screenTop-100
object.width = 100
object.height = 100
object.Number = 1
object.type = "regular"
object.score = 5
object.rotation = math.random(-20,20)
physics.addBody(object, "dynamic", {density =1, friction =1, bounce = .5})
end
Start with this...
local function spawnObject()
local objects = {
"object1",
"object2",
"object3",
"object4"
}
object = display.newImage("images/"..objects[math.random(3)]..".png")
object.x = math.random(screenLeft+ 30, screenRight-30)
object.y = screenTop-100
object.width = 100
object.height = 100
object.Number = 1
object.type = "regular"
object.score = 5
object.rotation = math.random(-20,20)
physics.addBody(object, "dynamic", {density =1, friction =1, bounce = .5})
end
...for choosing 1-3.
If you dont like math.random(3) you can do a table.remove(objects,1) 3 times so it is clear the 4th time is the special one.
But then have to be objects global ( outside function and not local ).
...you have to check for.

How to remove a number from a table?

I have no idea why this is not working. I am trying to delete the numbers in the table one by one (the randomCheck picks a number from the table and I want to delete that exact number) when I press the button 'MyButton'
math.randomseed(os.time())
_X = display.contentCenterX
_Y=display.contentCenterY
local numbers = {1,2,3,4,5,6,7,8,9,10}
local randomCheck = numbers[ math.random( #numbers) ]
local text = display.newText(""..randomCheck.."",_X,_Y,"Helvetica",50)
function removeNumber()
for i = 1, 10 do
if(randomCheck == i ) then
table.remove(numbers,i)
text.text = (""..i.."")
end
end
end
myButton = display.newRect(_X,_Y+100,100,80 )
myButton:addEventListener("tap", removeNumber)
In your loop, instead of
if(randomCheck == i)
use
if(randomCheck == numbers[i])
But all of that work is really unnecessary.
Instead of
local randomCheck = numbers[math.random( #numbers)]
use
local randomIndex = math.random(#numbers)
local randomCheck = numbers[randomIndex]
Then you can just
table.remove(numbers, randomIndex)

How can I dynamically retrieve the variable used to initialize an instance?

I'm trying to implement a speed-based turn system for a roguelike. I've set up a Mob class using metamethods, so that assigning the following to a variable will spawn a mob into the map at certain grid coordinates:
function Mob:spawn(x,y,m)
local mob = {}
setmetatable(mob, Mob)
mob.x = x
mob.y = y
mob.is_monster = m
return mob
end
Once that's done, I call the following:
function Mob:roll_call()
who_is_here[self.y][self.x] = self.is_monster
self.turn_counter = self.turn_counter * math.random(0.9, 1.1)
table.insert(allTurnCounters, self.turn_counter)
end
This puts the mob's self.turn_counter into a table. Meanwhile, in another module, I've defined these two functions, the heart of the problem:
function turn.decrement_counters(dt) -- runs in Dungeon.update(dt) and subtracts from allTurnCounters
for i = 1,#allMobsSpawned do
if allTurnCounters[i] <= 0 then
allTurnCounters[i] = 0
turn_active = true
whose_turn = i
return
elseif allTurnCounters[i] > 0 then
allTurnCounters[i] = allTurnCounters[i] - (10 * dt)
end
end
end
function turn.whose_is_it() -- called when an entry in allTurnCounters goes zero
if whose_turn == 1 then -- spots 1 and 2 in the spawn list are only ever for players
player1.my_turn = true -- turns on player 1's keys
elseif whose_turn == 2 then
player2.my_turn = true -- turns on player 2's keys
elseif whose_turn >= 3 then -- above 3 we're in monster territory
end
end
I've decided that the first two instances of Mob to be initialized will always be players 1 and 2, assigned to the variables player1 and player2, respectively. And, as it is, it works fine for passing control back and forth between players! But obviously, that's not enough for a fully-featured game. I need monsters, too.
The allTurnCounters table gets new entries, in order, from every mob that spawns (a class which includes both the players and the monsters, so they can share stats). Here's my question: How can I get Lua to dynamically retrieve the name of the table associated with a given turn_counter/value within that table, and use it to take turn priority, even in the event that I don't know what's been procedurally spawned ahead of time or what place it will occupy in the spawn order?
I have 3 ideas, none of which I'm solid on how to implement. One method would be something like sending the entire instance table to another table, rather than just their turn_counters, and then somehow grabbing a pair of values (the table itself and my_turn within the table), updating my_turn's value directly.
Another method might be to use the environment _G... somehow. I'm still poring over Chapter 14 of PiL trying to adapt it to my purposes, but value = _G[varname] seems to be a powerful bit of code I might be able to use for this. Not sure how, just yet.
My last idea was to maybe write some kind of string-sensing find-replace that can grab some other value in each mob's table and then pop it on the front of my_turn. Like, assigning some value with a known pattern for each mob type, that I can use in a string.find and then a string.gsub, to like... manually make the code line read as intended. Seems inelegant, though.
I had good luck with asking my previous Lua/Love2D question here, so I figured let's toss it out there while I'm thinking!
Here is my suggestion for how you should implement this:
Instead of allTurnCounters[i], give mobs a turn_counter property and use allMobsSpawned[i].turn_counter. Then, delete allTurnCounters.
Instead of storing the mob number in whose_turn, store the mob itself. (Note: when I say "the mob itself", it's short for "a reference to the mob itself")
So instead of
whose_turn = i
you would have:
whose_turn = allMobsSpawned[i]
Now whose_turn holds the mob whose turn it is. You can easily check whose_turn == player1, whose_turn == player2, etc. As a bonus, it doesn't rely on the players being the first mobs any more.
You can access the mob's properties through whose_turn - if whose_turn == player1 is true for example then whose_turn.x accesses the same field as player1.x
Here's a somewhat janky solution that can be made more elegant by incorporating the method from the other answer. This is what I came up with on my own while waiting for an answer.
-- in "Mob.lua" module
function Mob:roll_call()
who_is_here[self.y][self.x] = self.is_monster
self.turn_counter = self.turn_counter * math.random(0.9, 1.1)
table.insert(allMobs, {self.name, self.turn_counter})
if self.is_monster == true then
table.insert(allMonsters, {self.name, self.turn_counter})
end
end
function Mob:move(dx, dy)
who_is_here[self.y][self.x] = nil
self.x, self.y = self.x + dx, self.y + dy
who_is_here[self.y][self.x] = self.is_monster
self.turn_counter = 1 * self.speed
for k,v in ipairs(allMobs) do
if v[1] == self.name then
v[2] = self.turn_counter
end
end
self.my_turn = false -- flags turn is over
turn_active = false -- flags no active turn
end
-- in "turn.lua" module
function turn.decrement_counters(dt)
if turn_active == false then
for k,v in ipairs(allMobs) do
v[2] = v[2] - (10 * dt)
if v[2] < 0 then
v[2] = 0
turn_active = true
whose_turn = v[1]
return
end
end
else turn.whose_is_it()
end
end
function turn.whose_is_it()
if whose_turn == player1.name then
player1.my_turn = true
elseif whose_turn == player2.name then
player2.my_turn = true
elseif whose_turn == ant1.name then
ant1.my_turn = true
end
end
turn.whose_is_it() is the part that will need refining. If I use immibis' method of assigning allMobs[i].turn_counter, that will simplify things considerably and allow for future expansion. This answer only works for player1, player2, and an ant called ant1 in particular.

attempt to call method 'insert' (a nil value) when i restart game

I've added objects to the group so they get deleted and respawn when the game restarts but when the game restarts it gives the following error "attempt to call method 'insert' (a nil value)"
This is my object code:
local function spawnObject()
local objIdx = mRandom(#objects)
objName = objects[objIdx]
object = display.newImage( "images/fruit_" .. objName .. "_100.png" )
object.x = mRandom(screenLeft+30, screenRight-30)
object.y = screenTop
object.rotation = mRandom(-15, 15)
object.id = mRandom(-15,15)
group:insert( object )
if objIdx < 4 then
object.type = "food"
else
object.type = "other"
end
physics.addBody(object, "dynamic",{radius=45 , bounce = bt})
grassfront320w:toFront()
object.collision = objectCollision
object:addEventListener( "collision", object )
end
And for restarting I go to restart scene which I've created and from there I go back to my play scene.
Please help me solve the problem.
Don't add directly to the group view. Make a separate display group for the objects
local objectGroup = display.newGroup()
group:insert(objectGroup)
by doing it this way, you are not obligated to kill out the group when you change scene (if you are using composer or storyboard). It will clear it self in the memory when you change scene.

how do i stop objects from spawning automatic

ok whenever i try to reload the scene the objects from the previous scene dont stop spawning
here is my code, I want to delete all the objects from screen before moving to another screen
local objects = {
"banana",
"grape",
"pineapple",
"bomb",
"watermelon",
}
local function spawnObject()
objIdx = mRandom(#objects)
objName = objects[objIdx]
object = display.newImage( "images/fruit_" .. objName .. "_100.png" )
object.x = mRandom(screenLeft+30, screenRight-30)
object.y = screenTop
object.rotation = mRandom(-15, 15)
object.id = mRandom(-15,15)
if objIdx < 4 then
object.type = "food"
else
object.type = "other"
end
end
Insert your object (from display.newImage) into the scene view / display group.
Then it will get deleted automatically if you change screen.
Other option is to store all objects in a table, and call removeSelf() on each object in the table when you want to delete them.

Resources