I am using LibGDX to create an Android game on Eclipse. I created an instance of Image class. I am not sure if I should dispose it. I created it like this;
img = new Image(new Texture("img.png"));
I created a Texture as well but I could not find a way to dispose it. What should I do?
It's very error-prone to be storing your sole reference to a Disposable asset in part of your game's object graph. Use an AssetManager, or at least use one class that keeps track of all your textures and sounds, etc., (but seriously, use AssetManager--it has built-in reference counting). Then only that class has to handle disposing of all Disposables. Your actor can have a reference to a Texture, but it shouldn't hold the only reference, nor be responsible for disposing of the asset.
assetManager.load("img.png", Texture.class);
assetManager.finishLoading();
img = new Image(assetManager.get("img.png", Texture.class));
//...
assetManager.dispose();
Well, it looks like Texture implements disposeable so that would be the native object that needs to be disposed. You can read through this documentation.
You created an Image with an anonymous texture which just means you don't have a name you can reference it with so you can't dispose it. Your Texture asset needs to be referenced somewhere in your code so that you can dispose it at some appropriate time. Usually I would have a static Assets class which handles disposing all assets when needed (when stopping the app). Classes like Image use these assets but they don't have to worry about disposing them. Hope that helps.
Related
I would like an easy approach to preload/cache all of my static image assets so that they can be rendered/served without a delay.
I've seen that there is a precacheImage() call that can be used to pre-load/cache the AssetImage. This needs a context and it is recommended to call this in the didChangeDependencies() override.
Shouldn't there be a way to make this easier and more general? My app uses a total of 1.5 MB of image data (and I've included 2.0x and 3.0x upscaled versions in that number). PNG images that are 50 KB (and no upscaled versions) takes a noticeable amount of time to display, maybe 300-600ms on both emulator and fast devices. These are local assets, not fetched over the network. I find that irritating and I'm frustrated that there isn't a better way to handle this?
I've also seen the tip to use FadeInImage but again - it's not really what I'm looking for.
I'm displaying the image in a stateless widget (a custom button). It's not possible to use precacheImage in a stateless widget afaik. So I'd need to build the Image.asset() in my parent widget, call precacheImage and then pass the image widget to my stateless widget and render it in build - this is cumbersome.
Furthermore, the images will be displayed in different places (different parent widgets). Sometimes the image widgets differ in size between widgets and since size is parameters to Image.asset() I guess I would need to precache each unique size and pass these precached image widgets around. Isn't it possible to tell Flutter to "cache" the data of the PNG so that when the Image.asset is requested it reads the PNG from cache - without having to pass around precached image widgets?
I would like a "precacheAllImageAssets()call or callprecacheImage()` with a string so that each Image.asset() that references that same asset would be cached.
I guess that Flutter internally caches the image widget (including it's size and other properties) as some internal render object that is cached. Thus pre-caching two different sizes of the same image would require two different caches. With that being said - I'd still want a precacheAllImageAssets() call that could at least read the PNG data into memory and just serve it quicker even if would need to do some processing to get the PNG data to an actual widget with a size before it could be rendered. With such a cache I could maybe get a render delay of < 50 ms instead of the current 300-600 ms.
Any idea if this is possible? If not possible - am I missing something obvious or could this be a (likely) future improvement of the Flutter framework?
Here is my similar precacheAllImageAssets(), but you need to list all image path by yourself.
final List _allAsset = [
///tabbar
'images/tabbar/tabar_personal.png',
'images/tabbar/tabar_personal_slt.png',
'images/tabbar/tabar_home.png',
'images/tabbar/tabar_home_slt.png',
'images/...'
'images/...'
}
void main() {
final binding = WidgetsFlutterBinding.ensureInitialized();
binding.addPostFrameCallback((_) async {
BuildContext context = binding.renderViewElement;
if(context != null)
{
for(var asset in _allAsset)
{
precacheImage(AssetImage(asset), context);
}
}
});
}
UPDATE: after some research I've figured out that previous version of my answer was not correct. Here is relevant one (you can see old one in edit history).
You do not need to use same ImageProvider for images to precache. So you can run precacheImage() at init time and then create another image with same path and it is gonna be obtained from cache (if it was not cleared one way on another).
Internally precacheImage() uses ImageProvider.obtainKey() which is pair of (imagePath, scale) as a key to store image in in-memory cache. So as long as you are using same key it does not matter which instance of ImageProvider/Image you are using.
For futher insights you can inspect ImageCache documentation. Specifically, take a look at putIfAbsent() method as it's main caching endpoint. To understand how images generate their key (at which they are stored in ImageCache) try to start with ImageProvider class and then look into it's implementations.
I'm making an isometric city builder using Monogame Extended and Tiled. I've got everything set-up and now i need to somehow access the specific tiles so i can change them at runtime as the user clicks on a tile to build an object. The problem is, i can't seem to find a "map.GetLayer("Layername").GetTile(x,y) or .SetTile(x,y) function or something similar.
Now what i can do is edit the xml(.tmx) file which has a matrix in it that represents the map and it's drawn tiles. The problem with this is that i need to build the map in the content pipeline again after editing for the changes to be displayed. I can't really build at runtime or can i?
Thanks in advance!
Something like this will get you part way there.
var tileLayer = map.GetLayer<TiledMapTileLayer>("layername");
TiledMapTile tile;
if(tileLayer.TryGetTile(x, y, out tile))
{
// do something with tile
}
However, there's only a limited amount of things you can actually do with the tile once you've got it from the map.
There's no such thing as a SetTile method because changing tile data at runtime is not currently supported. This is a limitation of the renderer, which has been optimized for rendering very large maps by building static geometry that can't be changed once it's loaded into the graphics card.
There has been some discussion about building another renderer that would handle dynamic map changes but at this stage nothing like that has been implemented in the library. You could always have a go at implementing a simple renderer yourself, a really basic one is not as hard as you might think.
An alternative approach to dealing with this kind of problem might be to pre-process the map data before giving it to the renderer. The idea would be to effectively separate the layers of the map that are static from those that are dynamic and render the dynamic tiles as normal sprites. Just a thought, I'm not sure about the details of how this might work.
I plan to eventually revisit the Tiled API in the next major version of MonoGame.Extended. Don't hold your breath, these things can take a lot of time, but I am paying attention to the feedback and kinds of problems people are experiencing with the existing API.
Since the map data is stored in a XML (or csv) file which runs through the Content Pipeline you can not change it at runtime.
Anyways, in a city builder you usually do not change existing tiles but you place object on top of existing tiles.
I've been trying for two days to find an alternative to loading an image into my current project. I am using Adobe Flash Professional CS6 as my IDE and Animation program. I would like to be able to display an image in my application. What I am trying to do is have the image display onto the screen, the user enters the PLU associated with the image, and if the PLU is right then they receive a point. I have everything else already to go, but I just can't find an efficient way to deal with loading the image.
Right now I'm using this to accomplish getting my image on the display:
var myDisp:Layer0 = new Layer0();
var bmp:Bitmap = new Bitmap(myDisp);
spDispBox.addChild(bmp);
The above code works just find, but the limitation I can't get around is that I'm going to have to import each image into the library and then consecutively code each part in. I wanted to stick to OOP and streamline this process, I just don't know where I should turn to in order to accomplish my project goal. I'm more than happy to give more information. Thanks in advance, everyone.
July, 26, 2014 - Update: I agree, now, that XML is the way to go. I'm just having a hard time getting the grasp of loading an external XML file. I'm following along, but still not quite getting the idea. I understand about creating a new XML data object, Loader, and URLRequest. It's just loading the picture. I've been able to get output by using trace in the function to see that the XML is loaded, but when I go to add the XML data object to the stage I'm getting a null object reference.
I'm going to try a few more things, I just wanted to update the situation. Thanks again everyone.
it seems like these images are in your FLA library. To simplify your code you can make a singleton class which you can name ImageFactory (factory design pattern) and call that when needing an image which will return a Sprite (lighter than a MovieClip)
spDispBox.addChild( ImageFactory.getImageA() ); // returns a Sprite with your image
and in your ImageFactory
public function getImageA():DisplayObject {
var image:Layer0 = new Layer0(); // image from the FLA library
var holder:Sprite = new Sprite();
holder.addChild( new Bitmap( image ) );
return holder;
}
also recommend using a more descriptive name than Layer0
I'd like to understand the usage of CCAnimationCache.
I have a cache of enemies objects. Each object has two CCAnimations member variables, a standard animation and a special animation. The frames in the animation varies according to the type property of the enemy object.
#interface EnemyEntity : Entity
{
EnemyTypes type;
CCAnimation * animation;
CCAnimationCache * animationCache;
}
As it is often the case that in the screen I do have several instances of the same enemy type I am wondering if I should use a CCAnimationCache instead a CCAnimation member variable.
And if so where should I put the CCAnimationCache instance?
Huh. Don't you read comments in headers?
/** Singleton that manages the Animations.
It saves in a cache the animations. You should use this class if you want to save your animations in a cache.
Before v0.99.5, the recommend way was to save them on the CCSprite. Since v0.99.5, you should use this class instead.
#since v0.99.5
*/
This comment is in the CCAnimationCache.h file. So, this is a cocos2d singleton as others (CCTextureCache, CCSpriteFrameCache). If you want to use it, just call
CCAnimationCache* animationCache = [CCAnimationCache sharedAnimationCache];
How to read and draw image from isolated storage in xna???
I don't know why you would want to do this, but anyways, you would need actually implement System.IO.IsolatedStorage.
http://www.windowsphonegeek.com/tips/All-about-WP7-Isolated-Storage---Read-and-Save-Images
Read up on that, and try to use Texture2D instead of a BitMap image.
I know you can make a new Texture2D from Microsoft's Content Pipeline, but the Texture2D constructors are weird.
You can also try making a Silverlight and XNA Project and see what it does when you have a BitMap within the GraphicsDevice.
I am sorry I am making you try these things cause I am away from my computer right now.
Very unusual request :P
Best of luck,
Robert.