A long shot but I thought I'd ask

Hi dyson,

i’m trying to use particle candy with mte for firing at sprites.  I can get my player shooting properly, but I can’t seem to get any collision detection working.

No code errors – I just dont get any collisions, is this because my fire is ‘outside’ the mte engine?

Any ideas greatly appreciated, Greg

I Create my particle:

Particles.CreateParticleType (“Shots”,
        {
        imagePath         = “torpedo.png”,
        imageWidth        = 32,
        imageHeight       = 32,
        velocityStart     = 500,    
–    velocityChange = 1,
        fadeInSpeed       = 1.5,    – PER SECOND
        rotationChange = 1000,
        autoOrientation   = false,    – ROTATE TO MOVEMENT DIRECTION
        killOutsideScreen = true,    
        lifeTime          = 2000,  
        alphaStart        = 1.00,    
        blendMode         = “add”,
        sounds            = torpedo,
        
        } )
        Particles.PhysicsMaterial = { density = 0.75, friction = 0.5, bounce = 0, radius=16 }
        Particles.PhysicsProperties ={ isFixedRotation = false, isSleepingAllowed = false, name=“photon” }      

I add my emitter to my player:

    Particles.CreateEmitter(“E1”, player.x, player.y, 0, false, true)
    Particles.AttachParticleType(“E1”, “Shots”, 1, 5000,2000)
    Particles.StartEmitter(“E1”)

I add a listener to my enemy:

physics.addBody( object, “static”,  { density = 3.0, friction = 1.0, bounce = 0.1 } , {radius=400, isSensor = true})
        object.collision = onenemyCollision
        object:addEventListener( “collision”, object )

My collision listener:

function onenemyCollision(self,event)

    if event.phase==“began” then
            collisiontype = event.other.id
            print ("Collision detected: "… collisiontype)
    end
    
end    
 

I don’t have experience with ParticleCandy, but it looks like you’re assigning onenemyCollision as an event listener before onenemyCollision exists. Try moving your onenemyCollision function above the physics.addBody call for your enemy. 

I think that particle candy uses general physics tranisitons which are outside the mte scope.  So the two don’t currently work together… too bad!

This sort of thing seems to come up a lot. Calls to the physics library through MTE and outside in Corona SDK go to the same place. Some of my samples use mte.physics.*, but this is exactly identical to calling physics.* directly. Only one physics simulation is running, you’re just calling it indirectly in the first case, passing through MTE to get there. The concept of scope doesn’t really apply here.

As an example, try adding the following code to the bottom of main.lua in the Platformer - Angled PHYSICS sample project:

local mapObj = mte.getMapObj() local newBall = display.newCircle(mapObj[3], 1650, 600, 32) physics.addBody(newBall, {radius = 32})

As you can see, the circle happily collides with those objects created by and held in MTE. 

Thats great to hear, but for example , if I fire a slow moving weapon with transition.to and then I touch scroll, will the weapon stay in tune with my touch scroll, or will it follow its transition.to path?

(That’s what I though mte.movespriteto did… wrapped a sprite within the scope of the tile engine)

Lets say you created a sprite and you neither inserted it into any group nor used addSprite on it. That display object will be placed on Corona’s Stage. If you place the sprite in the top left corner of the screen and use transition.to to send it to the bottom right corner of the screen, it will move from one corner to the other whether MTE’s map is in motion or not. No matter what you do with MTE’s camera, that sprite will always move from the top left to the bottom right corner of your screen. This is because MTE does not move the Stage. 

Now imagine that you created a sprite and used addSprite to put it on the map. What’s happened is that MTE has moved the sprite from the Stage into another Group. Groups, like the Stage, have their own internal coordinate system. In most cases the coordinate system will match that of the Stage when you first create the Group. If you use transition.to to send the sprite from one corner of the screen to another it will do so just like before- but only if MTE’s camera isn’t moving. If the camera moves, for example because of touch scroll, the sprite’s path will remain synchronized with the MAP, not the screen. It is still doing exactly what you told it to do; it’s moving from it’s current position to a new position, but those positions are relative to the Group containing the sprite, and the group is in motion too.

Adding a sprite to MTE, or placing it directly on one of MTE’s group objects, doesn’t wrap the sprite in the tile engine’s scope so much as give the engine access to the sprite so that it can manipulate the sprite. A display object can have many references all pointing to the same object, all in the scopes of different functions and libraries. 

Are you adding your player and enemy sprite’s to the map? I’m sure we can get Particle Candy working, we just have to figure out where the problem’s hiding.

thanks for the clarification!  Yes I am adding all sprites to the map, except for the torpedo that I am firing.  If you remember, my map is in a container

local mapObj = mte.getMapObj()
    newGroup1 = display.newContainer(display.contentWidth *.6, display.contentHeight*.88)
    newGroup1.x =display.contentWidth / 3.5
    newGroup1.y = display.contentHeight / 2.2
    newGroup1:insert(mapObj)

When if fire the torpedo to the right, it goes out and past the container, as particle candy is using the display as its extents.

So yes, as per your explanation, the particles / emitter  have to be added to the mte group.

This is where the add to mte needs to happen:

  Particles.CreateEmitter(“E1”, player.x, player.y, 0, false, true)
  Particles.AttachParticleType(“E1”, “Shots”, 1, 5000,2000)

  Particles.StartEmitter(“E1”)

Ah, alright, according to Particle Candy documentation the emitters are actually display objects, which means you can add them to the Map like any other. You can retrieve an emitter by calling GetEmitter(name). Try doing one of the following before you call Particles.StartEmitter(“E1”):

local setup = {levelPosX = player.x, levelPosY = player.y, layer = 1} mte.addSprite(Particles.GetEmitter("E1"), setup)

Or

local mapObj = mte.getMapObj() local layer = 1 mapObj[layer]:insert(Particles.GetEmitter("E1"))

Hi Dyson,

I’ll give it a try.

Mike had this to say:

usually, particles are not meant to be used as game objects. They’re meant
to be used as “volatile” objects to create visual effects. If you need to access
an individual particle’s properties, you can loop through the particles and
access each one individually –see “sample…”.

This allows you to retrieve a particles position, scale, rotation etc.
However, you should NOT remove this particle manually or move to another parent
–just let the particle engine handle this.

Particles.CreateEmitter(“E1”, screenW*0.1, screenH*0.5, 90, true, true)

Sample…

    – DEFINE PARTICLE TYPE PROPERTIES
    Particles.CreateParticleType (“Arrow”,
        {
        imagePath         = “gfx_particles/arrow.png”,
        imageWidth        = 32,        – PARTICLE IMAGE WIDTH  (newImageRect)
        imageHeight       = 32,        – PARTICLE IMAGE HEIGHT (newImageRect)
        velocityStart     = 300,    – PIXELS PER SECOND
        autoOrientation   = true,    – ROTATE TO MOVEMENT DIRECTION
        killOutsideScreen = true,    – KILL PARTICLES WHEN OFF-SCREEN
        lifeTime          = 4000,    – MAX. LIFETIME OF A PARTICLE
        alphaStart        = 0,        – PARTICLE START ALPHA
        fadeInSpeed       = 1.0,    – PER SECOND
        fadeOutSpeed      = -1.0,    – PER SECOND
        fadeOutDelay      = 1000,    – TIME TO BEGIN FADE-OUT AFTER SPAWN
        } )

    – FEED EMITTERS (EMITTER NAME, PARTICLE TYPE NAME, EMISSION RATE, DURATION, DELAY)
    Particles.AttachParticleType(“E1”, “Arrow”, 4, 99999,0)

    – TRIGGER THE EMITTERS
    Particles.StartEmitter(“E1”)

local numParticles = Particles.GetMaxParticles()
    for i = 1, numParticles do
        local Particle = Particles.GetParticle(i)
        if Particle ~= nil then
            – Particle.x            – GET PARTICLE’S X-COORDINATE
            – Particle.y            – GET PARTICLE’S Y-COORDINATE
            – Particle.xScale        – GET PARTICLE’S X-SCALE
            – Particle.yScale        – GET PARTICLE’S Y-SCALE
            – Particle.alpha        – GET PARTICLE’S ALPHA
            – Particle.xSpeed        – GET PARTICLE’S X-SPEED (NON PHYSICS)
            – Particle.ySpeed        – GET PARTICLE’S Y-SPEED (NON PHYSICS)
            – Particle.killTime        – GET OR SET PARTICLE’S KILL TIME (IF SMALLER THAN CURR. TIME, PARTICLE WILL BE REMOVED)
            – Particle.emitterName        – GET EMITTER’S NAME
            – Particle.isPhysicsParticle      – IS PHYSICS PARTICLE?
            – Particle.PType.name        – GET PARTICLE TYPE’S NAME
        end
    end

We aren’t manipulated the particles here, just the emitter. According to their docs the particles will automatically spawn into the parent of the emitter. Once we get the emitter into the layer group the rest should fall into line without additional input.

Good call, it works!!!  Mike from particle candy also confirmed it:

, ok, so you want to add emitters to the tile maps, not individual particles.
Yes, you can place emitters within any display group, the particles are then
drawn within that group. Using the correct physics setup for your particle
types, you can also make them interact with any other physics items.

I don’t have experience with ParticleCandy, but it looks like you’re assigning onenemyCollision as an event listener before onenemyCollision exists. Try moving your onenemyCollision function above the physics.addBody call for your enemy. 

I think that particle candy uses general physics tranisitons which are outside the mte scope.  So the two don’t currently work together… too bad!

This sort of thing seems to come up a lot. Calls to the physics library through MTE and outside in Corona SDK go to the same place. Some of my samples use mte.physics.*, but this is exactly identical to calling physics.* directly. Only one physics simulation is running, you’re just calling it indirectly in the first case, passing through MTE to get there. The concept of scope doesn’t really apply here.

As an example, try adding the following code to the bottom of main.lua in the Platformer - Angled PHYSICS sample project:

local mapObj = mte.getMapObj() local newBall = display.newCircle(mapObj[3], 1650, 600, 32) physics.addBody(newBall, {radius = 32})

As you can see, the circle happily collides with those objects created by and held in MTE. 

Thats great to hear, but for example , if I fire a slow moving weapon with transition.to and then I touch scroll, will the weapon stay in tune with my touch scroll, or will it follow its transition.to path?

(That’s what I though mte.movespriteto did… wrapped a sprite within the scope of the tile engine)

Lets say you created a sprite and you neither inserted it into any group nor used addSprite on it. That display object will be placed on Corona’s Stage. If you place the sprite in the top left corner of the screen and use transition.to to send it to the bottom right corner of the screen, it will move from one corner to the other whether MTE’s map is in motion or not. No matter what you do with MTE’s camera, that sprite will always move from the top left to the bottom right corner of your screen. This is because MTE does not move the Stage. 

Now imagine that you created a sprite and used addSprite to put it on the map. What’s happened is that MTE has moved the sprite from the Stage into another Group. Groups, like the Stage, have their own internal coordinate system. In most cases the coordinate system will match that of the Stage when you first create the Group. If you use transition.to to send the sprite from one corner of the screen to another it will do so just like before- but only if MTE’s camera isn’t moving. If the camera moves, for example because of touch scroll, the sprite’s path will remain synchronized with the MAP, not the screen. It is still doing exactly what you told it to do; it’s moving from it’s current position to a new position, but those positions are relative to the Group containing the sprite, and the group is in motion too.

Adding a sprite to MTE, or placing it directly on one of MTE’s group objects, doesn’t wrap the sprite in the tile engine’s scope so much as give the engine access to the sprite so that it can manipulate the sprite. A display object can have many references all pointing to the same object, all in the scopes of different functions and libraries. 

Are you adding your player and enemy sprite’s to the map? I’m sure we can get Particle Candy working, we just have to figure out where the problem’s hiding.

thanks for the clarification!  Yes I am adding all sprites to the map, except for the torpedo that I am firing.  If you remember, my map is in a container

local mapObj = mte.getMapObj()
    newGroup1 = display.newContainer(display.contentWidth *.6, display.contentHeight*.88)
    newGroup1.x =display.contentWidth / 3.5
    newGroup1.y = display.contentHeight / 2.2
    newGroup1:insert(mapObj)

When if fire the torpedo to the right, it goes out and past the container, as particle candy is using the display as its extents.

So yes, as per your explanation, the particles / emitter  have to be added to the mte group.

This is where the add to mte needs to happen:

  Particles.CreateEmitter(“E1”, player.x, player.y, 0, false, true)
  Particles.AttachParticleType(“E1”, “Shots”, 1, 5000,2000)

  Particles.StartEmitter(“E1”)

Ah, alright, according to Particle Candy documentation the emitters are actually display objects, which means you can add them to the Map like any other. You can retrieve an emitter by calling GetEmitter(name). Try doing one of the following before you call Particles.StartEmitter(“E1”):

local setup = {levelPosX = player.x, levelPosY = player.y, layer = 1} mte.addSprite(Particles.GetEmitter("E1"), setup)

Or

local mapObj = mte.getMapObj() local layer = 1 mapObj[layer]:insert(Particles.GetEmitter("E1"))

Hi Dyson,

I’ll give it a try.

Mike had this to say:

usually, particles are not meant to be used as game objects. They’re meant
to be used as “volatile” objects to create visual effects. If you need to access
an individual particle’s properties, you can loop through the particles and
access each one individually –see “sample…”.

This allows you to retrieve a particles position, scale, rotation etc.
However, you should NOT remove this particle manually or move to another parent
–just let the particle engine handle this.

Particles.CreateEmitter(“E1”, screenW*0.1, screenH*0.5, 90, true, true)

Sample…

    – DEFINE PARTICLE TYPE PROPERTIES
    Particles.CreateParticleType (“Arrow”,
        {
        imagePath         = “gfx_particles/arrow.png”,
        imageWidth        = 32,        – PARTICLE IMAGE WIDTH  (newImageRect)
        imageHeight       = 32,        – PARTICLE IMAGE HEIGHT (newImageRect)
        velocityStart     = 300,    – PIXELS PER SECOND
        autoOrientation   = true,    – ROTATE TO MOVEMENT DIRECTION
        killOutsideScreen = true,    – KILL PARTICLES WHEN OFF-SCREEN
        lifeTime          = 4000,    – MAX. LIFETIME OF A PARTICLE
        alphaStart        = 0,        – PARTICLE START ALPHA
        fadeInSpeed       = 1.0,    – PER SECOND
        fadeOutSpeed      = -1.0,    – PER SECOND
        fadeOutDelay      = 1000,    – TIME TO BEGIN FADE-OUT AFTER SPAWN
        } )

    – FEED EMITTERS (EMITTER NAME, PARTICLE TYPE NAME, EMISSION RATE, DURATION, DELAY)
    Particles.AttachParticleType(“E1”, “Arrow”, 4, 99999,0)

    – TRIGGER THE EMITTERS
    Particles.StartEmitter(“E1”)

local numParticles = Particles.GetMaxParticles()
    for i = 1, numParticles do
        local Particle = Particles.GetParticle(i)
        if Particle ~= nil then
            – Particle.x            – GET PARTICLE’S X-COORDINATE
            – Particle.y            – GET PARTICLE’S Y-COORDINATE
            – Particle.xScale        – GET PARTICLE’S X-SCALE
            – Particle.yScale        – GET PARTICLE’S Y-SCALE
            – Particle.alpha        – GET PARTICLE’S ALPHA
            – Particle.xSpeed        – GET PARTICLE’S X-SPEED (NON PHYSICS)
            – Particle.ySpeed        – GET PARTICLE’S Y-SPEED (NON PHYSICS)
            – Particle.killTime        – GET OR SET PARTICLE’S KILL TIME (IF SMALLER THAN CURR. TIME, PARTICLE WILL BE REMOVED)
            – Particle.emitterName        – GET EMITTER’S NAME
            – Particle.isPhysicsParticle      – IS PHYSICS PARTICLE?
            – Particle.PType.name        – GET PARTICLE TYPE’S NAME
        end
    end

We aren’t manipulated the particles here, just the emitter. According to their docs the particles will automatically spawn into the parent of the emitter. Once we get the emitter into the layer group the rest should fall into line without additional input.