Swap an image?

Hi,
I’m doing a Breakout clone and when it hits one of the dark-grey bricks I want the brick to still be alive (i.e. not be remove, still have it’s body etc.) but only change color (i.e. picture) from one picture to another but I can’t seem to get it to work.
 
Here is a for loop generating all the bricks and it works fine:

local brick = display.newImage(findBrick(brickTable[j][i]))

                brick.x = (i * brickWidth) - brickWidth - 22

                brick.y = j * brickHeight - 6

                brick.name = “brick”

                brick.value = brickTable[j][i]

                brick.i = i

                brick.j = j

                – Create physic body for each brick

                physics.addBody(brick, “static”, {density = 1, friction = 0, bounce = 0})

                – Add each brick to display group

                bricks.insert(bricks, brick)

The problem is during the collision event, the dark-grey bricks have value 11:

if event.other.value == 11 then

            local i = event.other.i

            local j = event.other.j

            – event.other:removeSelf()

            – event.other = nil

            

            local brick = display.newImage(“10.png”)

            brick.x = (i * brickWidth) - brickWidth - 22

            brick.y = j * brickHeight - 6

            brick.name = “brick”

            brick.value = 10

            brick.i = i

            brick.j = j

            – Create physic body for each brick

            --physics.addBody(brick, “static”, {density = 1, friction = 0, bounce = 0})

            – Add each brick to table

            bricks.insert(bricks, brick)

        else

            event.other:removeSelf()

            event.other = nil

            bricks.numChildren = bricks.numChildren - 1

        end

Must I remove the previous picture or can I just overwrite the current image and keep all the remaing values?

Thanks in advance!

Best regards,

Tomas

Check out ImageSheets - essentially you’ll just reference a new frame in the ImageSheet.

The way you’re currently trying would have to remove/recreate the image - which is VERY expensive at runtime.

Hi,

thanks for the answer but I still don’t get it, I still need a reference to the actual brick, right?

So this change won’t work:

        if event.other.value == 2 then

            event.other = display.newImage(imagesheet, 4)

            

        else

            event.other:removeSelf()

            event.other = nil

            bricks.numChildren = bricks.numChildren - 1

        end

How should I refer to the actual object in question? I mean the actual brick is created during runtime together with it’s name for the ball event listener to act on but I can’t see how I can have a reference to the actual brick so I can change the image.

I have now created an imageSheet and loads the images from.

Thanks again for your help

Best regards,

Tomas

You could just apply a tint to the block when it’s hit if all you want is a different color. Whit the block being gray it would change color nicely

Hi,

RIght now I’m working on colors but the idea is to make some nice images in the sprite later on.

Best regards,

Tomas

Are your single hit bricks removing ok. From code above it looks like your overwriting each prev. Brick new one

Hi Jstrahan,

Yepp, all the other bricks are being removed ok, except for the one where I am trying to change picture, which is correct.

Best regards,

Tomas

Doing like this I can create a new image on the same position:

    if event.other.name == “brick” then

        vy = vy * -1

        if event.other.value == 2 then

            local j = event.other.j

            local i = event.other.i

            local x = event.other.x

            local y = event.other.y

            

            event.other:removeSelf()

            event.other = nil

            brickImageTable[j][i] = display.newImage(imageSheet,4, x, y)

            

        else

            event.other:removeSelf()

            event.other = nil

            bricks.numChildren = bricks.numChildren - 1

        end

    end

but that image doesn’t have a body of it’s own so the ball go straights through it. I just wants to know how I reference to the existing bricks så that I can change the image of a currenct brick and still keep the body.

If anybody can help me with this it would be great!

Best regards,

Tomas

Or if I in the “collision” function tries do remove the old image and create a new image with a new physics body it complains as well:

            physics.addBody(brick, “static”, {density = 1, friction = 0, bounce = 0})

            brickImageTable[j][i] = brick

ERROR: physics.addBody() cannot be called when the world is locked and in the mi

ddle of number crunching, such as during a collision event.

To swap image sounds like such a simple thing to do so probably I’m doing something wrong but can’t find out what it is. Haven’t no one here changed a picture in LUA?

Best regards,

Tomas

Have you tried the pistCollision event

Hi, unfortunately it seems to be the same error:

ERROR: physics.addBody() cannot be called when the world is locked and in the mi

ddle of number crunching, such as during a collision event.

This is my removeBrick function:

function removeBrick(event)

    if event.name == “postCollision” then

        if event.other.value == 2 then

                local j = event.other.j

                local i = event.other.i

                local x = event.other.x

                local y = event.other.y

                local brick = display.newImage(imageSheet, 4, x, y)

                physics.addBody(brick, “static”, {density = 1, friction = 0, bounce = 0})

                brickImageTable[j][i] = brick

                

                event.other:removeSelf()

                event.other = nil

        end

    end

    if event.name == “collision” then

        if event.other.name == “brick” and ball.x + ball.width * 0.5 < event.other.x + event.other.width * 0.5 then

            vx = -vx

        elseif event.other.name == “brick” and ball.x + ball.width * 0.5 >= event.other.x + event.other.width * 0.5  then

            vx = vx

        end

        

        if event.other.name == “brick” then

            vy = vy * -1

            if event.other.value == 2 then

                – Do nothing

                

            else

                event.other:removeSelf()

                event.other = nil

                bricks.numChildren = bricks.numChildren - 1

            end

        end

    end

    

    lastBounce = “brick”

end

My events:

        ball:addEventListener(“collision”, removeBrick)

        ball:addEventListener(“postCollision”, removeBrick)

How the bricks, it’s images and bodies are created:

function level1()

    brickTable = {}

    – Each index in the table represents a row

    – Each number within that row represents a brick value

    – The bricksTable must be full, even if it’s corresponding value is an empty brick

    brickTable[1] = {}

    brickTable[1][1] = 3

    brickTable[1][2] = 3

    brickTable[1][3] = 3

    brickTable[1][4] = 3

    brickTable[1][5] = 6

    brickTable[1][6] = 5

    brickTable[1][7] = 5

    brickTable[1][8] = 5

    brickTable[1][9] = 4

    brickTable[1][10] = 6

    brickTable[1][11] = 2

    brickTable[1][12] = 1

    

    

    – I och J bak och fram men fungerar!

    for j=1, rows do

        brickImageTable[j] = {}

        brickPhysicsTable[j] = {}

        for i=1, cols do

            if brickTable[j][i] ~= 0 then

                local brick = display.newImage(imageSheet, brickTable[j][i])

                brick.x = (i * brickWidth) - brickWidth - 22

                brick.y = j * brickHeight - 6

                brick.name = “brick”

                brick.value = brickTable[j][i]

                brick.j = j

                brick.i = i

                – Create physic body for each brick

                local p = physics.addBody(brick, “static”, {density = 1, friction = 0, bounce = 0})

                – add current image to a table so we can change the reference to it later

                brickImageTable[j][i] = brick

                brickPhysicsTable[j][i] = p

                – Add each brick to table

                bricks.insert(bricks, brickImageTable[j][i])

            end

        end

    end

end

I don’t understand how it can be so hard to change an image. Thanks for all the help, I been stuck on this for I don’t know how long but I’m sure it is some easy fix somewhere that I have missed.

Best regards,

Tomas

Check out ImageSheets - essentially you’ll just reference a new frame in the ImageSheet.

The way you’re currently trying would have to remove/recreate the image - which is VERY expensive at runtime.

Hi,

thanks for the answer but I still don’t get it, I still need a reference to the actual brick, right?

So this change won’t work:

        if event.other.value == 2 then

            event.other = display.newImage(imagesheet, 4)

            

        else

            event.other:removeSelf()

            event.other = nil

            bricks.numChildren = bricks.numChildren - 1

        end

How should I refer to the actual object in question? I mean the actual brick is created during runtime together with it’s name for the ball event listener to act on but I can’t see how I can have a reference to the actual brick so I can change the image.

I have now created an imageSheet and loads the images from.

Thanks again for your help

Best regards,

Tomas

You could just apply a tint to the block when it’s hit if all you want is a different color. Whit the block being gray it would change color nicely

Hi,

RIght now I’m working on colors but the idea is to make some nice images in the sprite later on.

Best regards,

Tomas

Are your single hit bricks removing ok. From code above it looks like your overwriting each prev. Brick new one

Hi Jstrahan,

Yepp, all the other bricks are being removed ok, except for the one where I am trying to change picture, which is correct.

Best regards,

Tomas

Doing like this I can create a new image on the same position:

    if event.other.name == “brick” then

        vy = vy * -1

        if event.other.value == 2 then

            local j = event.other.j

            local i = event.other.i

            local x = event.other.x

            local y = event.other.y

            

            event.other:removeSelf()

            event.other = nil

            brickImageTable[j][i] = display.newImage(imageSheet,4, x, y)

            

        else

            event.other:removeSelf()

            event.other = nil

            bricks.numChildren = bricks.numChildren - 1

        end

    end

but that image doesn’t have a body of it’s own so the ball go straights through it. I just wants to know how I reference to the existing bricks så that I can change the image of a currenct brick and still keep the body.

If anybody can help me with this it would be great!

Best regards,

Tomas

Or if I in the “collision” function tries do remove the old image and create a new image with a new physics body it complains as well:

            physics.addBody(brick, “static”, {density = 1, friction = 0, bounce = 0})

            brickImageTable[j][i] = brick

ERROR: physics.addBody() cannot be called when the world is locked and in the mi

ddle of number crunching, such as during a collision event.

To swap image sounds like such a simple thing to do so probably I’m doing something wrong but can’t find out what it is. Haven’t no one here changed a picture in LUA?

Best regards,

Tomas

Have you tried the pistCollision event