calling Remove on a sprite

So I think I’m missing something here, but I’m calling remove on a sprite and then telling the compositor to draw but it appears that the sprite I just removed is still being drawn by the compositor. What are the standard steps for removing a sprite from the screen? Thanks!

I’m wondering, are you calling compositor.drawall() and calling swapbuffers() or finish() at the end of each iteration?

  • Joel

Yes..so in pseudo code

sprite = compositor.newsprite
compositor.draw
screen.swapbuffers
sprite.remove
compositor.draw
screen.swapbuffers

I will still see what the original sprite drew.

also to note, I have other sprites still in the compositor if that makes a difference.

try drawall() instead of draw() ?

  • Joel

Hmmm…no reply yet. So…

How about:

Are you regenerating the entire frame each time? You should either clear the screen and draw, or fill it with a background bitmap and then draw. The “old” sprite shouldn’t be there. If it still is…maybe the remove failed?

Here’s a little example of removing a sprite. Mind you, I’m not invalidating the underlying region and bitmap here, which you might need to do if you run out of video memory, but I don’t think that is an issue with the way I’m doing this:

https://www.box.com/shared/jbetbkjcus4iyw25uejb

sub main()

l=listdir("pkg:/images")
regarray=[]
for each item in l
bmp=createobject("robitmap","pkg:/images/"+item)
reg=createobject("roregion",bmp,0,0,bmp.getwidth(),bmp.getheight())
regarray.push(reg)
end for

screen=createobject("roscreen",true)
compositor=createobject("rocompositor")
compositor.setdrawto(screen,&h000000FF)
timer=createobject("rotimespan")
timer.mark()
i=0
spr=compositor.newsprite(100+rnd(300),100+rnd(300),regarray[0])
while true
screen.clear(&h000000FF)
if timer.totalseconds() > 5 then
i=i+1
if i > regarray.count()-1 then i=0
	spr.remove()
	spr=compositor.newsprite(100+rnd(300),100+rnd(300),regarray[i])
	timer.mark()
end if
compositor.drawall()
screen.swapbuffers()
end while

end sub
 

RokuJoel,

Thanks for the response. Turns out I was calling draw() on the compositor at the wrong time which was causing artifacts. Removing that and enforcing a drawall call made it work properly.

Hi everyone,

I’m currently trying to create an app which has a vast list of items represented by sprites (about 1000). In order to avoid video memory depletion I keep only 6 sprites drawn on the screen at a time. When scrolling the list, the last item (from those 6 drawn) is deleted and the next item is drawn and so on. I delete the sprites using sprite.remove() method and then assigning the sprite an invalid value (and also invalidate the related region and bitmap) but it still seems that after scrolling about 400 items the memory gets depleted.

“RokuJoel” wrote:
Mind you, I’m not invalidating the underlying region and bitmap here, which you might need to do if you run out of video memory, but I don’t think that is an issue with the way I’m doing this

Here is how I invalidate the sprite and the related region and bitmap:


purgeSprite: function(sprite as Object) as Void

	if type(sprite) = "roSprite"
		
		' Get the region and bitmap of the sprite
		region = sprite.getRegion()
		bitmap = region.getBitmap()
		
		' Remove the sprite and invalidate it
		sprite.remove()
		sprite = invalid
		
		' Invalidate the region and bitmap
		region = invalid
		bitmap = invalid
	
		print "| Sprite purged!"
	end if
	
	' After exiting this method, the memory that the sprite used
	' (altogether with the bitmap and region) should be removed.

end function

Could you please tell me why the memory still gets depleted?

look at what your doing. Creating a local variable to reference other objects then setting the local variable back to invalid does not remove the original bitmap.
l_b = createobject(“roBitmap”, …)
l_a = l_b
Two references
L_a = invalid
One reference
Has no effect on l_b. It still exists

You’re right. That slipped away. But still, why after removing the sprite the memory gets depleted? Do I also have to delete the entry from the sprites array (spritesArray.delete(spriteIndex))?

If you look at the code above, your arrays persist for the entire application since they are defined in main. The regions that you push on to the array hold a reference to their bitmap. This means the bitmaps created there also persist ( continue to be referenced ). You would need to set those top-level references to invalid to get rid of the bitmap in memory. You should use a telnet session at your device IP, port 8080. Issue the command r2d2_bitmaps (ignore the initial command not found message and reissue the command) this shows all the bitmaps in memory and how much memory is being used. This way you can be sure you have gotten rid of all references

And by the way, the sprite = Invalid is also just another reference passed into the function. You are only setting the argument sprite to invalid. So you need to review and understand how references work.

“NewManLiving” wrote:
If you look at the code above, your arrays persist for the entire application since they are defined in main. The regions that you push on to the array hold a reference to their bitmap. This means the bitmaps created there also persist ( continue to be referenced )

I only store the sprites in a global array. The bitmap and region used for creating a sprite are local variables of a function so they should be “garbage collected” after exiting the function (exits after drawing a new item on screen). Only the six visible sprites should be held in memory and the others should have invalid value. To better understand, I call something like m.globals.spriteArray[spriteIndex].remove() and m.globals.spriteArray[spriteIndex] = invalid with each list scroll for the first sprite to be deleted and create a new roSprite for the last item that will become visible. There are only six items in the array that are of type “roSprite” and the rest are invalid at each given time. The problem is that after scrolling about 400 items the memory still gets depleted.

“NewManLiving” wrote:
And by the way, the sprite = Invalid is also just another reference passed into the function. You are only setting the argument sprite to invalid. So you need to review and understand how references work.

Sorry for the confusion with references. I did that by mistake, beeing to desperate to free memory :)). I get how references work in Roku.

It’s best to post all your current code. Apparently it has changed from your beginning post.
Looking at everything it will be easier to tell where there is a reference leak

When dealing with the 2d it’s best to get a telnet like puttytel set it up like I said and view it as you scroll to see how bitmaps are released

“NewManLiving” wrote:

It’s best to post all your current code. Apparently it has changed from your beginning post.
Looking at everything it will be easier to tell where there is a reference leak.

NewManLiving, I am different guy from the one that started the tread. The problem is that the code is huge about 1200 lines of code only for the part with the list (it’s a vast MVC structured app) and that’s why I’ve explained briefly what i have done. If you consider what I have written so far too confusing then don’t bother too much because, anyway, I greatly appreaciate that you took some your time to help.

It’s not a matter of confusion. There is nothing confusing about it. Looking at the code you/someone initially submitted along with the function that removes the sprites shows a number of errors related to references even if they were out of “desperation”. I was curious if you had changed the code somewhat since then. Your problem still suggests a reference leak. Requesting the code was just to examine what you had changed not because I thought it was confusing. My own libraries contain thousands of lines of code. I hope you find your problem