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

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.

Related

Why this lua function is modifying tables it shouldn't?

I have this function in my code to load and setup sizes for sprites.
function aux.Sprite:setTexture(renderer,imgPath)
... -- Not important for this question
img = loadImage(renderer,imgPath)
self.texture = img.texture
self.rect.w = img.w
self.rect.h = img.h
end
(loadImage here is the function implemented in C, and is returning the correct values)
Using it should be easy enough
bg = aux.Sprite:new()
bg:setTexture(R, "testfiles/bg.png")
ship = aux.Sprite:new()
ship:setTexture(R, "testfiles/testship.png")
The problem is that after the second call for setTexture the values for the FIRST sprite is changed!
for example
bg = aux.Sprite:new()
bg:setTexture(R, "testfiles/bg.png")
print(bg.rect.w)
ship = aux.Sprite:new()
ship:setTexture(R, "testfiles/testship.png")
print(bg.rect.w)
should return
1920 1920
because I'm printing the width for bg twice
but I'm getting
1920
300
That is, the second setTexture changes the value for "bg" and not only for "ship".
My guess is that self.rect.w = img.w is setting a "pointer", or whatever is called in lua, to img.w and when I use the function later this pointer is updated in all references?
What I'm doing wrong here? Is this the correct lua behavior?
PS: The definition of the Sprite:new function as asked
function aux.Sprite:new(o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
There is nothing in the provided code that actually creates the rect (or aux.Sprite for that matter). I guess this means that is done via something like
aux.Sprite = { rect = {} }
This is a problem because it means all your sprites share the same rect.
aux.Sprite:new() returns a new empty table that has the metatable and its __index set to Sprite. Thus when in setTexture self.rect is searched in this empty table the one from Sprite is returned via __index.
You need to make sure every sprite has its own unique rect.
I don't really know what is the typical Lua object pattern here, but you can eg. have self.rect = { w = img.w, h = img.h } in setTexture or maybe o.rect = {} in new - something that actually sets rect to a new table for this particular sprite.

Getting data from a table

Using Tiled I generated a Lua file which contains a table. So I figured that I'd write a for loop which cycles through the table gets the tile id and checks if collision is true and add collision if it was. But, I've been unable to get the tile id's or check they're properties. But it returned a error saying that I tried to index nil value tileData.
Here is the Map file
return {
version = "1.1",
luaversion = "5.1",
-- more misc. data
tilesets = {
{
name = "Tileset1",
firstgid = 1,
tilewidth = 16,
tileheight = 16,
tiles = {
{
id = 0,
properties = {
["Collision"] = false
}
},
}
}
layers = {
{
type = "tilelayer",
name = "Tile Layer 1"
data = {
-- array of tile id's
}
}
}
}
And here is the for loop I wrote to cycle through the table
require("Protyping")
local map = love.filesystem.load("Protyping.lua")()
local tileset1 = map.tilesets
local tileData = tileset1.tiles
local colision_layer = map.layers[1].data
for y=1,16 do
for x=1,16 do
if tileData[colision_layer[x*y]].properties["Colision"] == true then
world:add("collider "..x*y,x*map.tilewidth, y*tileheight,tilewidth,tileheight)
end
end
end
Try this:
tileset1 = map.tilesets[1]
instead of
tileset1 = map.tilesets
lhf's answer (map.tilesets[1] instead of map.tilesets) fixes the error you were getting, but there are at least two other things you'll need to fix for your code to work.
The first is consistent spelling: you have a Collision property in your map data and a Colision check in your code.
The second thing you'll need to fix is the way that the individual tiles are being referenced. Tiled's layer data is made of 2-dimensional tile data laid out in a 1-dimensional array from left-to-right, starting at the top, so the index numbers look like this:
You would think you could just do x * y to get the index, but if you look closely, you'll see that this doesn't work. Instead, you have to do x + (y - 1) * width.
Or if you use zero-based x and y, it looks like this:
Personally, I prefer 0-based x and y (but as I get more comfortable with Lua, that may change, as Lua has 1-based arrays). If you do go with 0-based x and y, then the formula is x + 1 + y * width.
I happen to have just written a tutorial this morning that goes over the Tiled format and has some helper functions that do exactly this (using the 0-based formula). You may find it helpful: https://github.com/prust/sti-pg-example.
The tutorial uses Simple Tiled Implementation, which is a very nice library for working with Tiled lua files. Since you're trying to do collision, I should mention that STI has a plugins for both the bump collision library and the box2d (physics) collision library.

Background infinite using corona sdk

I'm trying to scroll side a background in corona sdk (infinity background)
I used two images repeated (854x176).
I tried this function:
function mov(self, event)
if self.x < -854 then
self.x = 854
else
self.x = self.x - self.speed
end
end
it's working just fine but the problem that a small white space occurred between repetitions.
Is there a better way to do this?
One way of doing this would be to take advantage of Graphics 2.0 Engine's feature called repeating fills.
Here are the steps:
Set the default texture wrapping mode for x (you could do the same for y too):
display.setDefault("textureWrapX", "mirroredRepeat")
The modes for wrapping are:
"clampToEdge" - (default) clamped fill won't repeat
"repeat" - fill is repeated as if same tiles were placed side by side
"mirroredRepeat" - fill is repeated in a mirrored pattern, each tile being a mirror image of the one next to it
Create a rectangle the size of the background you want to have, eg. full screen
local background = display.newRect(display.contentCenterX, display.contentCenterY, 320, 480)
Fill your display object with your background image
background.fill = {type = "image", filename = "background.jpg"}
Animate it using whatever method fits your app. Below's just one way:
local function animateBackground()
transition.to(background.fill, {time=5000, x=1, delta=true, onComplete=animateBackground})
end
animateBackground()
Here you simply run transition on x property of background.fill object, delta=true indicating that we're rather using changes in x value, not final ending values (see here).
Play with the values for time, x, set delta to false, play with wrapping modes, just to see what effect it has on animation. You might even accidentally discover some cool effect which you might want to use later...
Check this excellent tutorial by Brent Sorrentino, who goes through more details on fills. Additionally, see sample code in CoronaSDK under Graphics-Premium/PatternFill.
Full code:
display.setDefault("textureWrapX", "mirroredRepeat")
local background = display.newRect(display.contentCenterX, display.contentCenterY, 320, 480)
background.fill = {type = "image", filename = "background.jpg" }
local function animateBackground()
transition.to( background.fill, { time=5000, x=1, delta=true, onComplete=animateBackground } )
end
animateBackground()

In corona sdk how can I reference / specify all indexes of a spawned object on the screen?

Hi I've been wondering this for a while and it's causing me lots of problems not knowing more about how to reference / specify all indexes of a spawned enemy on the screen at one time.
Say when my character dies I want all the enemies on the screen at that time to move away from my dead character as the screen fades out. Simply calling 'enemy1' only makes one (the last spawned I think) do as it's told.
Here is my enemy spawn script:
local spawnTable2 = {}
local function spawnEnemy()
enemy1 = display.newSprite( group, sheetE, sequenceData2 )
enemy1.x=math.random(100,1300)
enemy1.y=math.random(360,760)
enemy1.gravityScale = 0
enemy1:play()
enemy1.type="coin"
enemy1.objTable = spawnTable2
enemy1.index = #enemy1.objTable + 1
enemy1.myName = "enemy" .. enemy1.index
physics.addBody( enemy1, "kinematic",{ density = 0, friction = 0, bounce = 1 })
enemy1.isFixedRotation = true
enemy1.type = "enemy1"
enemy1.timer = nil
enemy1.enterFrame = moveEnemy
Runtime:addEventListener("enterFrame",enemy1)
enemy1.objTable[enemy1.index] = enemy1
hudGroup:toFront()
return enemy1
end
To reference all objects, you would need to have two things.
A Counter
Loop
First make a counter:
counter = 0
Every time the funciton is called have a counter:
counter = counter + 1
For tables, you would do something like this:
spawnTable2[counter].x=math.random(100,1300)
Then when you want to remove the object, you would just do this:
display.remove(spawnTable2[counter])
Just keep in mind, everything you do to manipulate that object will have to be inside that function. Good luck and hope this helps.

How do I reference an image that I have created in an table array in Corona (Lua)?

Apologies for the incredibly noob question, but I'm new to Lua, very very rusty at any code, stuck and can't find the solution!
I'm creating a series of random images on screen using:
for count = 1, 6 do
r = math.random ( 1, 5 )
mpart[count] = display.newImage ("mpart" .. r .. ".png")
mpart[count].y = 680
mpart[count].x = x
mpart[count].spawnednew = false
x = x + 170
mpart[count]:addEventListener ("touch", onTouch)
end
How do I know which object is being touched/moved in the function "onTouch", and how do I add a property to it, e.g.
mpart[1].spawnednew == true
Your onTouch function should have an event parameter passed in. The touched image can then be found by in event.target.
Well first off, lins is spot on about how to reference the touched object: the 'event' parameter of the listener function includes the value 'event.target'
As for adding new data to the touched object, that's as simple as 'event.target.moved = true' and now the object has data at object.moved

Resources