change image in display.newImageRect

I draw an image to screen like this:

local im

im =  display.newImageRect( … )

is it possible to somehow change the image to another image in code… haven’t found a way to do it.

No, you would need to remove the old image and create a new one

Graphics 2.0 is supposed to give us a way to do this from what I have read.  Can anyone confirm this?

Thanks, Greg

Hi Greg,

I’m not sure which mention your citing, do you have a link? Technically you could change the “fill” on an object to change its image, but I don’t believe there’s a way in 2.0 to simply change the source image… although, I suppose changing the fill is pretty much the same thing, as long as you do it properly. :slight_smile:

Brent

Hi Brent,

Here’s the reference (I really hope this works, I have to swap images on the fly as well!)   (If a player doesn’t have a ball they look normal, if they get a pass they become a ball icon)

It comes from this topic: http://forums.coronalabs.com/topic/33446-swapping-image-for-image-or-sprite/


completed
 · 
AdminDavid Rangel
(COO, Corona Labs)

responded

 · 
Oct 10, 2013
 

This is now taken care by a new “fill” property to shape objects in our new graphic engine.

See: http://coronalabs.com/blog/2013/10/08/graphics-2-0-public-beta/

This will be covered in our graphics 2.0 release (currently in Developer Preview).

For us to support an image swap feature, we have to read both files and create textures for them and have them in memory.  

You can do this in several different ways:

If you want both images around and not have to keep reloading them:

  1. You can hold the two images in memory and using lsVisible, swap which one is visible, drawing the image in the same place.

  2. Use a sprite and pick which frame you want to show.

If you don’t care about the first image after loading the second one:

  1. delete the first one, create the second one

  2. You can write a function to do this for you (this is untested, just making it up off the top of my head)

swapImage = function(oldImage, imageFile, width, height)

     local newImage = display.newImageRect(imageFile, width, height)

     newImage.x = oldImage.x

     newImage.y = oldImage.y

     oldImage:removeSelf()

     oldImage = nil

     return newImage

end

or something like that.  Tuck it away in your utility belt.  You might want to grab oldImage’s parent and insert newImage into oldImage’s parent to support groups.

Now with Graphics 2.0, you can have a rectangle of some sort (newRect, newImageRect, etc) and use its fill property to fill it with an image.  The trick is that the rect needs to be the size of the image or it will distort the image when it fills the rect, but you can just change the fill and the image will change. 

Rob

Thanks for the excellent reply Rob,  there is an extra complication in what I am doing, I am calling a spawn function that attaches a table to an image.    I am trying to preserve the values and the states saved in the ‘team’ table while swapping the image from without a ball to with a ball. If I do a display.remove(obj) I lose all of the data and position in the table.  That’s why I was hoping for a ‘.fill’ property to save the day.  Then again my logic might be off on how this should be done.

local temp = spawn({
            image=playerimage,

            objTable=team,

            itemx =   startingx,
            itemy =  display.contentHeight/2,
            itemvisible = visible,    
        })

function spawn(params)
    local object = display.newImage(playerImage,params.image)
    object.objTable = params.objTable
    object.index = #object.objTable + 1
    object.myName = object.index
    object.objTable[object.index] = object
    object.width = iwidth
    object.height = iwidth
    object.x = params.itemx
    object.y = params.itemy
    object:addEventListener( “touch”, onTouch )        
    object:addEventListener( “tap”, onTap )        
    object.isVisible = params.itemvisible
    return object
end

Greg

Just as an FYI, you can’t use “spawn” for your table and “spawn” for your function.  The names need to be unique.

We used to have a library called movieClip() that people used for this exact purpose.  It stored a table of images in a single display object and had methods to play the various frames.  You could use it to toggle images on or off.  When we redid the sprite and imageSheet functions we got rid of movieClip in favor of using sprites for this.

You could do a similar thing, have your spawn function actually return a display.newGroup() that has all of the image you need stacked on top of each other with only one visible and give your self a showFrame() function you attach to the group that would make everything else invisible and show only the active frame.

Hi Rob,

Thanks for the reply.  I don’t think I want to stack 32 images x 10 players and move them around just because of overhead.

–> If I do a table(index):removeSelf()  does that keep the table data so that if I did a table(index) = display.newimage() it would re-link the new image to my table?

or do I have it backwards, that the table is linked to the image and destroying the image unbinds the table?

If your image has 32 states, I would think sprites would be the way to go, if nothing else from a memory conservation stance.

Rob

Hi Rob,  I was able to get it working by doing the following, it seems to work ok for swapping two images, any thoughts?:

local function onTap( event )
    if event.target then
        t=event.target
        playerwithfocus = t.index
        print ("player “… playerwithfocus … " was tapped”)
        if placeflag == true then

– save player info and then remove image from table

            tempw = team[t.index].width
            temph = team[t.index].height
            tempx = team[t.index].x
            tempy = team[t.index].y
            team[t.index]:removeSelf()

– add other image back into table at correct index                     
            local object = display.newImage(playerImage,showimage)
            object.objTable = team
            object.index = t.index
            object.myName = object.index
            object.objTable[object.index] = object
            object.width = tempw            --team[t.index].width
            object.height = temph             – team[t.index].height
            object.x = tempx                        --team[t.index].x
            object.y = tempy                        --team[t.index].y
            object:addEventListener( “touch”, onTouch )        
            object:addEventListener( “tap”, onTap )

        end
    end
    return true
end

No, you would need to remove the old image and create a new one

Graphics 2.0 is supposed to give us a way to do this from what I have read.  Can anyone confirm this?

Thanks, Greg

Hi Greg,

I’m not sure which mention your citing, do you have a link? Technically you could change the “fill” on an object to change its image, but I don’t believe there’s a way in 2.0 to simply change the source image… although, I suppose changing the fill is pretty much the same thing, as long as you do it properly. :slight_smile:

Brent

Hi Brent,

Here’s the reference (I really hope this works, I have to swap images on the fly as well!)   (If a player doesn’t have a ball they look normal, if they get a pass they become a ball icon)

It comes from this topic: http://forums.coronalabs.com/topic/33446-swapping-image-for-image-or-sprite/


completed
 · 
AdminDavid Rangel
(COO, Corona Labs)

responded

 · 
Oct 10, 2013
 

This is now taken care by a new “fill” property to shape objects in our new graphic engine.

See: http://coronalabs.com/blog/2013/10/08/graphics-2-0-public-beta/

This will be covered in our graphics 2.0 release (currently in Developer Preview).

For us to support an image swap feature, we have to read both files and create textures for them and have them in memory.  

You can do this in several different ways:

If you want both images around and not have to keep reloading them:

  1. You can hold the two images in memory and using lsVisible, swap which one is visible, drawing the image in the same place.

  2. Use a sprite and pick which frame you want to show.

If you don’t care about the first image after loading the second one:

  1. delete the first one, create the second one

  2. You can write a function to do this for you (this is untested, just making it up off the top of my head)

swapImage = function(oldImage, imageFile, width, height)

     local newImage = display.newImageRect(imageFile, width, height)

     newImage.x = oldImage.x

     newImage.y = oldImage.y

     oldImage:removeSelf()

     oldImage = nil

     return newImage

end

or something like that.  Tuck it away in your utility belt.  You might want to grab oldImage’s parent and insert newImage into oldImage’s parent to support groups.

Now with Graphics 2.0, you can have a rectangle of some sort (newRect, newImageRect, etc) and use its fill property to fill it with an image.  The trick is that the rect needs to be the size of the image or it will distort the image when it fills the rect, but you can just change the fill and the image will change. 

Rob

Thanks for the excellent reply Rob,  there is an extra complication in what I am doing, I am calling a spawn function that attaches a table to an image.    I am trying to preserve the values and the states saved in the ‘team’ table while swapping the image from without a ball to with a ball. If I do a display.remove(obj) I lose all of the data and position in the table.  That’s why I was hoping for a ‘.fill’ property to save the day.  Then again my logic might be off on how this should be done.

local temp = spawn({
            image=playerimage,

            objTable=team,

            itemx =   startingx,
            itemy =  display.contentHeight/2,
            itemvisible = visible,    
        })

function spawn(params)
    local object = display.newImage(playerImage,params.image)
    object.objTable = params.objTable
    object.index = #object.objTable + 1
    object.myName = object.index
    object.objTable[object.index] = object
    object.width = iwidth
    object.height = iwidth
    object.x = params.itemx
    object.y = params.itemy
    object:addEventListener( “touch”, onTouch )        
    object:addEventListener( “tap”, onTap )        
    object.isVisible = params.itemvisible
    return object
end

Greg

Just as an FYI, you can’t use “spawn” for your table and “spawn” for your function.  The names need to be unique.

We used to have a library called movieClip() that people used for this exact purpose.  It stored a table of images in a single display object and had methods to play the various frames.  You could use it to toggle images on or off.  When we redid the sprite and imageSheet functions we got rid of movieClip in favor of using sprites for this.

You could do a similar thing, have your spawn function actually return a display.newGroup() that has all of the image you need stacked on top of each other with only one visible and give your self a showFrame() function you attach to the group that would make everything else invisible and show only the active frame.

Hi Rob,

Thanks for the reply.  I don’t think I want to stack 32 images x 10 players and move them around just because of overhead.

–> If I do a table(index):removeSelf()  does that keep the table data so that if I did a table(index) = display.newimage() it would re-link the new image to my table?

or do I have it backwards, that the table is linked to the image and destroying the image unbinds the table?

If your image has 32 states, I would think sprites would be the way to go, if nothing else from a memory conservation stance.

Rob