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.
Related
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)
I am working on a game using love2d and i haven't quite programmed in lua. Not sure on technical wording so i'll post my code and explain what i'm trying to do:
item = {}
item.stat = {}
player.x = 100
player.y = 100
--
item[0].stat.damage = 10
What i'm trying to do is make an inventory system and an item database. I want to be able to make the item database with the code above so i could add an item like so:
item[1].stat.damage = 10
item[1].stat.speed = 10
item[2].stat.damage = 20
item[2].stat.speed = 5
--
player.inventory[0] = item[1]
player.inventory[1] = item[2]
can someone tell me what coding principle this may so i can research it? I basically want to make a matrix that i can access like above while having the convenience of named arrays instead of saying item[1,"damage"] = 10
Edit:
I realise now i can do item.stat.damage[1] = 10 but i have to setup an array for each one, is there an easier way?
Simply use tables:
player = {}
player.x = 100
print(player.x) -- prints 100
Note that player.x is simply syntactic sugar for player["x"], so the following lines are equivalent:
print(player.x) -- prints 100
print(player["x"]) -- also prints 100
With that in mind, you could construct your game data like this for example:
item = {}
item[1] = {}
item[1].stat = {}
item[1].stat.damage = 10
item[1].stat.speed = 10
item[2] = {}
item[2].stat = {}
item[2].stat.damage = 20
item[2].stat.speed = 5
player = {}
player.x = 100
player.y = 100
player.inventory = {}
player.inventory[1] = item[1]
player.inventory[2] = item[2]
print(player.inventory[2].stat.damage) -- prints 20
print(player["inventory"][2]["stat"]["damage"]) -- equivalent, also prints 20
It is probably a good idea to define functions that create items or players and automatically set all the required fields.
Eventually, you may want to use actual classes and objects (for example, if you want to define methods on your objects).
EDIT:
Here is the example from above with functions create_item, create_player to create items or players. I've used named parameters for these functions so one doesn't have to remember the order of the function parameters (note the curly braces when calling the functions).
function create_item(arg)
local item = {}
item.stat = {}
item.stat.damage = arg.damage
item.stat.speed = arg.speed
return item
end
function create_player(arg)
local player = {}
player.x = arg.x
player.y = arg.y
player.inventory = {}
return player
end
item = {}
item[1] = create_item{damage=10, speed=10}
item[2] = create_item{damage=20, speed=5}
player = create_player{x=100, y=100}
player.inventory[1] = item[1]
player.inventory[2] = item[2]
print(player.inventory[2].stat.damage) -- prints 20
print(player["inventory"][2]["stat"]["damage"]) -- equivalent, also prints 20
You can always shorten your code:
item = {
stat = {},
[0] = { stat = { damage = 10 } },
[1] = { stat = { damage = 10, speed = 10 } },
[2] = { stat = { damage = 20, speed = 5 } },
}
player = { x = 100, y = 100, inventory = { [0] = item[1], [1] = item[2] } }
You can access that code in matrix way like
function item:getstat(index, param)
return self[index] and self[index].stat and self[index].stat[param];
end
function item:setstat(index, param, value)
local t1 = self[index]
if (t1 == nil) then
t1 = {}
self[index] = t1
end
local t2 = t1.stat
if (t2 == nil) then
t2 = {}
t1.stat = t2
end
t2[param] = value
end
print(item:getstat(0, "damage"))
item:setstat(1, "speed", 20)
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.
What is the best way to remove all spawned coins when the game is over?
Here is the code that spawns the coins:
screenGroup = self.view
coin = {}
coinspawn = function()
i = display.newSprite( imageSheet1, sequenceData1 )
i.x = display.contentWidth
i.y = math.random(0, display.contentHeight-50)
i:play()
i.collided = true
i.name = "coin"
physics.addBody(i, "dynamic",
{density=.1, bounce=0.1, friction=.2, shape= shape2 ,filter=playerCollisionFilter }
)
--player.gravityScale = 0.5
coinIntro = transition.to(i,{time=2500, x=display.contentWidth - display.contentWidth -500 ,onComplete=jetReady , transition=easing.OutExpo } ) --
coin[#coin+1] = i
end
tmrcoin = timer.performWithDelay( 1000, coinspawn, 0 )
First you would remove all coins from the display. Then you would clear the coin table:
for i=1,#coin do
coin[i]:removeSelf()
end
coin = {} -- forget all coins
Assuming coin table is the only other place you store your coins, this will do it.
Note that you can't use coin[i]=nil in the loop after removeSelf: as soon as table has holes, the # operator is basically unusable. You can't use table.remove either, because i gets incremented every time, so you'll miss items (try, you'll see). Same issue with pairs: you can't edit a table while iterating through it. You could however do this:
local numCoins = #coin
for i=1,numCoins do
coin[i]:removeSelf()
coin[i]=nil
end
-- now coin is {}
The only reason I can think of to nil N items instead of letting the gc take care of it with one table = {} statement is if you have more than one reference to your coin table (which I would rename to coins, BTW, for clarity).
I am new to game development and I am trying to create a simply GUI framework for my current project. I am currently using the Director Class 1.4 for my scene management. I have got my project o change scenes, but now I want to create a pop up window. I just want the pop up window to show up over the current scene I'm on. Below is the code for my main.lua and menu.lua (my initial scene). If anyone could help me out, I would really appreciate it. Please try to be as specific as possible, because I am very new to Corona and programming in general.
main.lua
_W = display.contentWidth
_H = display.contentHeight
local director = require ("director");
local mainGroup = display.newGroup();
local function main()
mainGroup:insert(director.directorView);
director:changeScene("menu");
return true;
end
main();
menu.lua
module(..., package.seeall)
function new()
local localGroup = display.newGroup();
local bg = display.newImage("Images/background1.PNG");
local myText = display.newText("Merchant", 0, 0, native.systemFont, 24)
myText:setTextColor(255, 255, 255)
myText:setReferencePoint(display.CenterReferencePoint);
myText.x = _W/2; myText.y = _H/2;
local hero_btn = display.newImage("Images/weaponcraft.PNG", 25, 25);
hero_btn:setReferencePoint(display.BottomLeftReferencePoint);
hero_btn.x = 252; hero_btn.y = 475;
hero_btn.scene = "heroMain";
local craft_btn = display.newImage("Images/smithing.PNG", 25, 25);
craft_btn:setReferencePoint(display.BottomLeftReferencePoint);
craft_btn.x = 7; craft_btn.y = 475;
craft_btn.scene = "craftMain";
local inventory_btn = display.newImage("Images/inventory1.png");
inventory_btn:setReferencePoint(display.CenterReferencePoint);
inventory_btn.x = _W/2; inventory_btn.y = 430;
--inventory_btn.scene = "inventory";
function changeScene(e)
if(e.phase == "ended") then
director:changeScene(e.target.scene);
end
end
localGroup:insert(bg);
localGroup:insert(hero_btn);
localGroup:insert(craft_btn);
hero_btn:addEventListener("touch", changeScene);
craft_btn:addEventListener("touch", changeScene);
return localGroup;
end
You can use the native.showAlert function. This shows a popup dialog box.
Something like this:
local function onComplete( event )
local action = event.action
if "clicked" == event.action then
if 1 == event.index then
end
end
local alert = native.showAlert( "You are in scene1!", "Congratulations!", { "OK" }, onComplete )
This show a dialog box with a "You are in scene1!" title, "Congratulations!" subtitle, and a "OK" button that closes the dialog box when you click(or tap) it.
Put these code in the front of your scene, and change the native.showAlert properties to the words you want.
You can create your custom pop up and can handle it by your own I am putting the sample code.
--function to create a dialog to be shown on the game over
local function gameOverAlertScreen()
--Display item used in the popup screen
local alertBox , restartBtn, levelBtn, soundOnOffSwitch, quitOnOffSwitch, imageSheetSoundOnOff, imageSheetQuitOnOff
--initial constans used for positioning the display items
local startTX = -400
local startTY = halfH
local btnInitailY = halfH -50
local btnMargin = 10
--cancel the game pausse timer
if(gameTimer_main) then
timer.cancel(gameTimer_main)
gameTimer_main = nil
end
local optionSoundSheet =
{
-- The params below are required
width = 51,height = 51,numFrames = 2,-- The params below are optional; used for dynamic resolution support
sheetContentWidth = 102, -- width of original 1x size of entire sheet
sheetContentHeight = 51 -- height of original 1x size of entire sheet
}
local optionQuitSheet =
{
-- The params below are required
width = 51,height = 51,numFrames = 2,-- The params below are optional; used for dynamic resolution support
sheetContentWidth = 102, -- width of original 1x size of entire sheet
sheetContentHeight = 51 -- height of original 1x size of entire sheet
}
isFirstTime=true
--pauseScreen()
dialog=true
alertBox = display.newImage("image/popup_dialog.png")
alertBox.x = halfW; alertBox.y = halfH
alertBox:setReferencePoint(display.CenterReferencePoint)
--creating the restart button fot the popup dialog
restartBtn = widget.newButton{
defaultFile="image/replay_btn.png",overFile = "image/replay_btn_hover.png",
isEnable=true,onRelease = onReplayBtnGameOverRelease -- event listener function
}
restartBtn.x = halfW
restartBtn.y = btnInitailY
--creating the level button
levelBtn = widget.newButton{
defaultFile="image/menu.png",overFile = "image/menu_hover.png",
isEnable=true, onRelease = onLevelBtnGameOverRelease -- event listener function
}
levelBtn.x = halfW
levelBtn.y = restartBtn.y + restartBtn.height + btnMargin
--creating the sound on off switch
imageSheetSoundOnOff = graphics.newImageSheet( "image/sound.png", optionSoundSheet )
soundOnOffSwitch = widget.newSwitch
{
left = screenW * 0.18,top = screenH * 0.73, style = "checkbox", sheet = imageSheetSoundOnOff,
initialSwitchState = soundOn,frameOff = "2",frameOn = "1",onRelease = onSoundButtonClicked, onPress = onSoundButtonClicked,
}
--creating the quit on off switch
imageSheetQuitOnOff = graphics.newImageSheet( "image/vibration.png", optionQuitSheet )
quitOnOffSwitch = widget.newSwitch
{
left = screenW * 0.7,top = screenH * 0.735,style = "checkbox",sheet = imageSheetQuitOnOff,onPress = onViberationButtonClicked,
initialSwitchState = vibrationOn,frameOff = "2",frameOn = "1",
}
--soundOnOffSwitch:setState({ isOn = soundOn })
--quitOnOffSwitch:setState({ isOn = vibrationOn})
--create/position logo/title image on upper-half of the screen
local titleLogo = display.newImageRect( "image/gameover.png",144,30)
titleLogo:setReferencePoint( display.CenterReferencePoint )
titleLogo.x = halfW
titleLogo.y = btnInitailY - 65
if popupGameOverGroup == nil then
popupGameOverGroup = display.newGroup()
end
-- inserting the buttons and the alert dialog to the popup group
popupGameOverGroup:insert(alertBox)
popupGameOverGroup:insert(restartBtn)
popupGameOverGroup:insert(levelBtn)
popupGameOverGroup:insert(soundOnOffSwitch)
popupGameOverGroup:insert(quitOnOffSwitch)
popupGameOverGroup:insert(titleLogo)
transition.from(popupGameOverGroup, {time =1000,x=startTX,y=titleLogo.y,xScale = 1, yScale = 1,
transition = easing.inOutExpo})
localGroup:insert(popupGameOverGroup)
showAdd()
end