– bump –
— post updated —
:ph34r:
Quick fix for the mine timer:
[lua]
– mine is your mine you just layed
mine.explodeTimer=timer.performWithDelay(1500, mine.explode) – Or whatever you call the explode function
– On collision with an enemy
function mine:collision(event)
if event.other.isEnemy then
if mine.explodeTimer then timer.cancel(mine.explodeTimer) end
end
end
[/lua]
Obviously I haven’t seen your code, but it sounds like the issue is using one timer for multiple events. If you make the timer a property of each mine, it should work.
- C
Thanks for the suggestion, Caleb.
Unfortunately it didn’t work. I think it’s because of how I have my function setup.
If you want to take a look, here is a textDoc with just the code relating to the PTmine: link
– Fyi Any object that doesn’t have local preceding it, has a forward declaration at the top of my code –
The way I have the function setup is how I setup most of my functions that deal with collision 'n such e.g. my bullet function/s, IGmine, radar, etc…
-Saer
I think where you’re doing your explode timer is on line #43… Correct 吗?
So if you make that a member of your PTmine (instead of having one local timer), everything should be terrifically fabulously lovely (or something around that).
- Caleb
Actually it is on line #156
It is calling the ExplodeMine function after three seconds, which at the moment just plays an animation and removes the mine.
What’s the timer on line #43 in the code you linked to?
- C
Here is the revised code: link
When the user taps the PTMBtn and if no collisions are detected within three seconds the mine being placed, the ExplodeMine function (lines #20 - 48) is called.
When I comment-out all the lines (In the ExplodeMine function) with the exception of the lines that play the explosion animation and the line that removes the mine, I get an error when the second mine explodes (again due to the timer defaulting to the most recently laid mine)
**"File: … Projects/DoodleTanks/LevelHelper/Nodes/LHSprite.lua
Line: 214
Bad argument #-2 to ‘originalCoronaRemoveSelf’ (Proxy expected, got nil)"**
In the past when I’ve had errors like this, it’s generally a scope issue… though in this case I don’t know what that would be.
If I try it with all the code in the function, I get this error:
**"File: …/Desktop/Application Projects/DoodleTanks/level1.lua
Line: 440
Bad argument #1 to ‘newCircle’ (number expected, got nil)"**
(line #440 is line #22 in the document you have)
On a similar note, I’ve successfully (lol I think so anyway) been able to incorporate a type of ‘blast-wave’ when my mine explodes.
Basically I’m just drawing a dynamic radial-sensor right after the mine explodes and then checking for collisions. I need to refine it a bit, but it seems to be what I need.
As far as I can tell, you’ve only got one PTmine object. If you were to add them to a table, that would most likely do it. You could also just make them local (I’d also make your blast wave local so you can have more than one) and make sure to remove them.
[lua]
– In your onPTMBtnRelease()
local PTmine = (build PTmine)
PTmines:insert(PTmine) – Just so you can clear them all if need be
[/lua]
- Caleb
Slightly updated code: link
I discovered something interesting - when I comment-out the line in the ExplodeMine fuction that removes the PTmine, it no longer prints an error… which would make sense since it is trying to position the PTmineBW circle at the location of an object that has, at this point, been removed.
In this short video, you’ll see how the second mine triggers two explosions - one for the first mine and the second obviously for the second instance of the timer.
Also, it’s interesting how only one explosion is played when I destroy the first mine before the second explodes. And another thing worth noting is how it throws an error when I go to destroy the second mine, before it explodes.
And btw, both the PTmine and the PTmineBW have a forward declaration at the top of my code:
[lua]
local PTmine
local PTmineBW
[/lua]
They are also both being added the main display-group.
I’ll continue to mess around with it, and hope I figure it out.
Ok, so I think I’ll just give a few pointers/tips rather than go through all the code…
- Not so many local objects
Tables are the power of Lua. Literally. Keeping objects in a table not only keeps your code clean, but it also makes it easier to find things. If you know all of your tanks are in a table named “tanks” then you don’t have to do something both for enemyB01 and enemyB02 - you can just iterate through the “tanks” table and you know you’re getting each enemy. Likewise for a lot of your other things - keeping them in a table is the way to go.
- Give each object an overall “type” (or something to that effect) value.
Instead of giving each object a “class” value (that apparently maps to their exact object) I’d opt for a “type” or “title” or something - “enemy” for the enemy tanks, “mine” for mines, etc. Then you can check against one value -
[lua]
if event.other.type == “enemy” then
– We know it’s an enemy; explode!
end
[/lua]
- Nil out your objects after removing them
Stops memory leaks.
[lua]
– Yes
display.remove(myObject)
myObject = nil
– No
display.remove(myObject)
[/lua]
Anyhow, good luck!
- Caleb
Yeah, the reason I didn’t use a table for enemy-tanks is because each tank is made up of two parts - the base and turret.
The base and turret of say the first tank are both added to a specific displayGroup and are given a .class of Etank01, so that way if I shoot a bullet and it hits the turret portion of the enemy-tank it knows it hit Etank01 and therefore calls a function that removes not just the turret but the corresponding displayGroup.
If I were to just assign each enemy-tank object a .class of “enemy”, everytime a bullet would hit just the turret portion of a tank it would only remove the event.other.class which means you’d have a tank-body roaming around without a turret… believe me, I’ve tried.
and btw, I give all my objects a designated .class and check for that class in my various collision functions:
[lua]
if event.other.class == “Etank01”
then
– display.remove(Etank01)
end
[/lua]
As far as ‘nil-ing’ out objects, I used to do that whenever I’d remove an object, but then I was reading how it’s not really necessary since everything is purged when the scene changes. I guess I’ll go back to that and nil everything.
Thanks for taking the time to help me out, Caleb. I’ll figure it out.
I fixed your problem of turret vs. body (not the exact problem, but a similar one - tower vs. sensor) by making each tank a display group and adding each component to it.
As for .class or .type and such, why not both? A .class for the object referencing itself, and a .type for checking whether to attack or not. (just an idea; you don’t have to do that if you don’t wish to )
I make sure to nil out my objects so that I can be absolutely sure no memory leaks occur - why risk it?
- C
Yes, that is what I do…
Unless I’m not following you, why would I need to give an object a .class and .objType reference?
I just define a new display-group for each tank:
local Etank01 = display.newGroup()
local Etank02 = display.newGroup()
etc…
I assign a class to each object:
Ebase01 = loader:spriteWithUniqueName(“Ebase01”)
Ebase01.class = "Etank01"
Eturret01 = loader:spriteWithUniqueName(“Eturret01”)
Eturret01.class = "Etank01"
and then add the components to their corresponding group:
Etank01:insert ( Ebase01 )
Etank01:insert ( Eturret01 )
etc…
Other than becoming quite tedious when there is a high number of enemy-tanks… 21 for example ;), It seems to work without any problems.
Yeah, true. I’ll go back and nil out my objects as well.
Thanks again.
-Saer
Like you said, having a lot of tanks gets tedious. Here’s what I meant by using tables:
[lua]
local tanks = {}
local function buildTank()
local tank = display.newGroup()
tank.body = [build tank body]
tank.turret = [build tank turret]
tank:insert(tank.body)
tank:insert(tank.turret)
– Etc.
table.insert(tanks, tank)
end
[/lua]
.class and .type - It would just be easier for reference - you can check if event.other.type == “enemy” instead of if event.other.class == “Etank01” or event.other.class == “Etank02” or event.other.class == “Etank03” or such when more tanks exist.
- Caleb
Okay, that helps.
Just to clarify though, does “tank.body = [build tank body]” mean the same as tankBody = display.newImage or in my case loading it from SpriteHelper, loader:spriteWithUniqueName(“tankBody”)?
This is the first time I’ve seen that form of syntax.
Ahh, I see what you’re saying…
Though how would it know, depending on what object is hit first, which turret/base to remove in addition to the object the bullet collided with? Since they all have a .type of “enemy” I can’t see how it would distinguish what objects to remove.
What I’m trying to say is “bullet hit a turret. Remove the turret and the corresponding base.” or vice versa.
From my understanding you can’t add a .class or .type to a displayGroup. If you could then I would just add the Ebase/Eturret01 to Tank1 = display.newGroup() and then assign the group an objectType - Tank1.class = “Enemy”.
In doing so I could just check if the bullet has collided with an object that has a class of “Enemy” and if so just remove even.other.class (which would be the entire Tank1 display-group)
If I could do that, then I could just create multiple display-groups for each tank and give all the groups a .class / .type of “Enemy”…
Can I achieve this via using a table?
Sorry, but other than the code in some of the libraries/modules I am utilizing, I personally have not constructed one table… I know, sad. <_<
I did that bracket-enclosed **[build tank body] and [build tank turret] **to mean however you build your body/turret, do it there. That’s not valid syntax - that’s just to show where you create your objects and add values and such to them
For knowing what object to remove when a turret/body is hit, I’d use index pointers - the body has an index and the turret has an index that both point to the location of the tank object inside the tanks table.
[lua]
table.insert(tanks, tank)
local location = table.indexOf(tanks, tank) – Where is the index of “tank” in the “tanks” table?
tank.body.tankLocation = location
tank.turret.tankLocation = location
[/lua]
Then, when a collision occurs, you can find the associated tank by this:
[lua]
local location = event.other.tankLocation
local otherTank = tanks[location]
[/lua]
You can actually add any property you want to anything as long as the “anything” is a table. The .class or .type or .somethingOrOther is called a key, and it just points to where the value is - saying tank.randomThingy = 110 basically means “store 110 at the location ‘randomThingy’”. My terminology probably isn’t correct, but it gets the point across
You definitely need to get into tables… They’re really awesome (and useful!).
Okay, I figured that’s what the brackets meant. As far as the “tank.body” , what is the " ." for? Is that a way of identifying ‘body’ as a subset of the display-group tank? At first I thought it was a different form of tank:insert( body ), but then I saw tank:insert( tank.body ) in addition to the first declaration - tank.body = object
From the little bit of reading I’ve done on Tables, would the following make sense/be correct?
[lua]
local Etanks = {
{ tank1.body = loader:spriteWithUniqueName(“Ebase01”), tank1.turret = loader:spriteWithUniqueName(“Eturret01”) },
{ tank2.body = loader:spriteWithUniqueName(“Ebase02”), tank2.turret = loader:spriteWithUniqueName(“Eturret02”) }
– Etc…
}
– I assume this would either mean both the base and turret have the value of Etanks[1]
– or they are just two different values that can be accessed in the first… iteration? in the table.
– If it indeed does mean they both are considered to be [1] then I’d think when I check for collisions
– I can just cycle through the table and if the bullet hit Etanks[1]
– it would remove everything defined as the [1] in Etanks{} …?
[/lua]
Sorry if this is way off from the method you’ve been explaining. :mellow:
You should really get into tables… A quick Google search reveals a couple of links that seem to be good:
http://lua-users.org/wiki/TablesTutorial
http://www.phailed.me/2011/02/learn-lua-the-hard-way-tables/
And as a side note, all display objects are tables. When you do something like…
[lua]
myImage.x = 750
[/lua]
You’re assigning 750 to the “x” value of myImage. Corona in turn translates that into a change in position.
- C
Alright, I’ll take a look at the links.
Thanks for helping me out and offering some advice.
-Saer
No problem
- C