AndEngine add single image multiple time in different size - android

I am new in AndEngine. I am using following code to display an image of a ball.
private ITextureRegion mBallTextureRegion;
private Sprite ball1;
#Override
public void onCreateResources() {
ITexture ball = new BitmapTexture(this.getTextureManager(),
new IInputStreamOpener() {
#Override
public InputStream open() throws IOException {
return getAssets().open("gfx/ball.png");
}
});
this.mBallTextureRegion = TextureRegionFactory.extractFromTexture(ring1);
....................
....................
}
#Override
protected Scene onCreateScene() {
final Scene scene = new Scene();
scene.attachChild(backgroundSprite);
...........
ball1 = new Sprite(192, 63, this.mBallTextureRegion, getVertexBufferObjectManager());
scene.attachChild(ball1);
..............
...........
}
Now, depending on the game level I want to add multiple ball of different size in the scene. Is it possible to add ITextureRegion mBallTextureRegion multiple time in different size(using different magnifying it)? If it is, then how? Please help me this sample code.

if you want to resize a Sprite,AnimatedSprite,Text,etc...
//the original image x2, 2f because the parameter is float
youSprite.setScale(2f);
if you use a texture region in more sprites:
Sprite youSprite;
//set deepCopy() in you texture to optimized memory
youSprite= new Sprite(0,0,youTexture.deepCopy(),mEnginge.getVertexTextureManager());
and if you want generate random position of each ball use "Random" variable.
best regards.

Related

Android Libgdx memory leak on creating Actors

I've created an Android application to show about a hundred point objects using Libgdx modelBuilder. It works fine and models are rendered without any problem, but I needed to add a marker for every point model. To do that I've extended from Actor and in this class, I've created two textures representing the marker in normal and the selected mode when the user clicked the objects. The following is the LabelActor class which has been instantiated for each point model.
public class LabelActor extends Actor {
Texture texture;
Texture selectedTexture;
Sprite sprite;
private Vector3 distVector = new Vector3();
public LabelActor( String markerColor){
String path = "markers/point_marker_" + markerColor + ".png"";
String selected_path = "markers/point_marker_select.png";
texture = new Texture(Gdx.files.internal(path));
selectedTexture = new Texture(Gdx.files.internal(selected_path));
sprite = new Sprite(texture);
setBounds(sprite.getX(), sprite.getY(), sprite.getWidth(), sprite.getHeight());
}
#Override
protected void positionChanged() {
sprite.setPosition(getX(),getY());
super.positionChanged();
}
#Override
public void draw(Batch batch, float parentAlpha) {
if (selected){
batch.draw(selectedTexture, getX()-sprite.getWidth()/2, getY());
} else {
batch.draw(texture, getX()-sprite.getWidth()/2, getY());
}
}
}
The problem will be arisen on using the marker for these objects which causes a huge amount of memory usage. Loading a sphere model for each point objects takes about 14M of graphics memory but loading texture markers take 500M of memory on the device. I've used png icons located in the asset folders to create my textures but not using a Libgdx atlas. Is there any chance to create markers for this number of point objects to consume a little amount of memory?
Below is the image representing the view of the markers and point models.
Edit 1:
I've used AssetManager to load textures and create HashMap of them in the main screen then pass an array of two textures to each LabelActor class as Retron advised, but the memory is still overloaded.
public class LabelActor extends Actor {
Texture texture;
Texture selectedTexture;
Sprite sprite;
private Vector3 distVector = new Vector3();
public LabelActor(Texture[] textures){
texture = textures[0];
selectedTexture = textures[1];
sprite = new Sprite(texture);
setBounds(sprite.getX(), sprite.getY(), sprite.getWidth(), sprite.getHeight());
}
#Override
protected void positionChanged() {
sprite.setPosition(getX(),getY());
super.positionChanged();
}
#Override
public void draw(Batch batch, float parentAlpha) {
if (selected){
batch.draw(selectedTexture, getX()-sprite.getWidth()/2, getY());
infoWindow.draw(batch, parentAlpha);
} else {
batch.draw(texture, getX()-sprite.getWidth()/2, getY());
}
}
}
Part of main screen to load textures using AssetManager:
#Override
public void create() {
...
environment = new Environment();
environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1.0f));
pointLight = new PointLight().set(0.8f, 0.8f, 0.8f, 2f, 0f, 0f, 500f);
environment.add(pointLight);
assetManager = new AssetManager();
textureTitleList = new ArrayList<>();
for (FileHandle f: Gdx.files.internal("markers").list()){
assetManager.load("markers/" + f.name(), Texture.class);
textureTitleList.add(f.name());
}
}
private void loadModel() {
textureMap = new HashMap<>();
for (String fName: textureTitleList){
textureMap.put(fName, assetManager.get("markers/" + fName, Texture.class));
}
}
#Override
public void render() {
if (!isLoaded && assetManager.update()) {
loadModel();
isLoaded = true;
}
...
}
You must use AssetManager and load ONE texture from asset, not create new texture for every new actor.

9patch looks pixeled when setSize is called too many times

I have a sprite that is supposed to act like a loadbar. I have tried this by using an example image that has been created like a 9patch-type (http://cdn.dibbus.com/wp-content/uploads/2011/03/btn_black.9.png). It seems okay in the start, but as the width of the sprite increases the sprite starts to look pixeled. Anyone know what the problem could be, or have any solution? The code is shown below.
public Sprite loaded;
public void init()
{
atlas = new TextureAtlas(Gdx.files.
internal("data/misc/menu_button.pack"));
loaded = atlas.createSprite("loadbar");
loaded.setPosition((Misc.WIDTH/2) - unloaded.getWidth()/2,
Misc.HEIGTH - unloaded.getHeight());
}
public void draw_load_bar() //render function
{
if(loaded.getWidth() < 600)
{
loaded.setSize(loaded.getWidth()+ 0.5f, loaded.getHeight());
}
loaded.draw(batch);
}
Dont use a Sprite to stretch it. I'd recommend a real Ninepatch from libgdx for it.
public NinePatch loaded;
private float posX, posY, width, height;
public void init()
{
loaded = new NinePatch(the Texture here,10, 10, 10, 10); //bounds outside
//set right pos here...
}
public void draw_load_bar(SpriteBatch batch) //render function
{
if(loaded.getWidth() < 600)
{
//update the size of it here (guess pos is static)
width++;
}
//need to parse the batch and the right sizes.
loaded.draw(batch, posx, posy, width, height);
}
after that you can handle it like a Sprite or Texture but it does stratch right without issues. If you want to the full Picture to be Stretched simply do net set any bounds at the creation new NinePatch(texture, 0,0,0,0)

Sprite example from AndEngine's example project, looks pixelated when imported to my own project

I'm trying out AndEngine (GLES2) in the last couple of days.
I'm having a problem with the SpriteExample from the Examples project.
In the SpriteExample in the example project the face_box.png sprite looks nice and sharp.
However when I copy the same code and the face_box.png file to my own separate project, the sprite looks pixelated.
Since the code is just the same I guess the problem is with some configuration settings, however I could not figure it out.
I'm running on Galaxy S2 with ICS.
Does anyone have any idea on what might cause the problem?
This is the code if anyone wondered -
public class AndEngineMapActivity extends SimpleBaseGameActivity implements OnClickListener {
// ===========================================================
// Constants
// ===========================================================
private static final int CAMERA_WIDTH = 800;
private static final int CAMERA_HEIGHT = 480;
// ===========================================================
// Fields
// ===========================================================
private ITexture mTexture;
private ITextureRegion mFaceTextureRegion;
// ===========================================================
// Constructors
// ===========================================================
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
#Override
public EngineOptions onCreateEngineOptions() {
final Camera camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_SENSOR, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera);
}
#Override
public void onCreateResources() {
try {
this.mTexture = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
#Override
public InputStream open() throws IOException {
return getAssets().open("gfx/face_box.png");
}
});
this.mTexture.load();
this.mFaceTextureRegion = TextureRegionFactory.extractFromTexture(this.mTexture);
} catch (IOException e) {
Debug.e(e);
}
}
#Override
public Scene onCreateScene() {
this.mEngine.registerUpdateHandler(new FPSLogger());
final Scene scene = new Scene();
scene.setBackground(new Background(0.09804f, 0.6274f, 0.8784f));
/* Calculate the coordinates for the face, so its centered on the camera. */
final float centerX = (CAMERA_WIDTH - this.mFaceTextureRegion.getWidth()) / 2;
final float centerY = (CAMERA_HEIGHT - this.mFaceTextureRegion.getHeight()) / 2;
/* Create the face and add it to the scene. */
final Sprite face = new Sprite(centerX, centerY, this.mFaceTextureRegion, this.getVertexBufferObjectManager());
scene.attachChild(face);
return scene;
}
#Override
public void onClick(final ButtonSprite pButtonSprite, final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(AndEngineMapActivity.this, "Clicked", Toast.LENGTH_LONG).show();
}
});
}
// ===========================================================
// Methods
// ===========================================================
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}
**Update: ** Following to JoenEye's advice I tried loading the texture differently with
#Override
public void onCreateResources() {
try {
this.mTexture = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
#Override
public InputStream open() throws IOException {
return getAssets().open("gfx/face_box.png");
}
}, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
this.mTexture.load();
this.mFaceTextureRegion = TextureRegionFactory.extractFromTexture(this.mTexture);
} catch (IOException e) {
Debug.e(e);
}
}
The results have improved and the smiley face picture looks a bit better, but it's still not as sharp as in the Example's project.
****Another Update: ****
These are the images of the results I get.
-
This is the one from the original example project (best result)
This is the one from my project without the TextureOptions.BILINEAR_PREMULTIPLYALPHA
This is the one from my project with the TextureOptions.BILINEAR_PREMULTIPLYALPHA (current result
By the way way - Interesting result, once I created another empty project with only this class in it and it worked flawlessly and looked good.
So I guess it must be some kind of a configuration problem with my own project.
I'd be glad to get any more ideas!
Thanks!
I'll guess that the difference between the example project and the one with the bad result is either the subpixel location of the sprite or it being stretched/skewed slightly. Are you careful to draw the sprite exactly on a pixel boundry?
The issue is when a fragment is drawn, if the fragment is not perfectly lined up with the texture it is sampling, then it must generate a color that is not exactly what is in the texture. For example if you have a 10x10 pixel texture, and you draw it at screen coordinates (0.5, 0.5), then each pixel either needs to just pick the nearest texel (NEAREST sampling), or blend together nearby texels (LINEAR or BILINEAR sampling). NEAREST can have rounding problems here if two texels are equal distances from the sample point (which might explain the slightly ugly image in the first bad result). If you use LINEAR sampling, then it just blends together the nearest texels, which may give the slightly blurred image you see in the second result.
So to remedy this for small images with tiny features, you want to always make sure to draw the image so that it lines up exactly with a pixel boundry. Can you check if you are doing this in your application?
For more information I would do some google searches for 'pixel perfect sampling/rendering`, which will give you more information.
EDIT, I also noticed this, which may explain:
final float centerX = (CAMERA_WIDTH - this.mFaceTextureRegion.getWidth()) / 2;
final float centerY = (CAMERA_HEIGHT - this.mFaceTextureRegion.getHeight()) / 2;
You're doing integer division here, which could cause you to get the value of 'center' off by a half pixel if the image width/height is an odd number. Then when you pass this value to AndEngine your center is incorrect by a half pixel, explaining the subpixel problems.
Try using the standard way of loading images unless the method you use is necessary for some reason.
mTexture = new BitmapTexture(1024, 512, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
BitmapTextureRegionFactory.createFromAsset(mTexture, this, "face_box.png", 0, 0);
You will probably end up using buildable textures that place the images on the texture automatically, but this could help you determine where the problem is.
Eventually I decided to just open up a new project and move all my code to the new project.
It works.
I know it's a bad solution, but it solved the problem.
If I'll ever come up with this problem again, and find a real solution, I would update it in here.

AndEngine scene load resources

Help me please, wat's wrong in my code? On device shown black background.
public void onLoadResources()
{
this.mTexture = new Texture(1024, 1024);
this.mTextureRegion = TextureRegionFactory.createFromAsset(this.mTexture, this, "gfx/bgr.png",0,0);
this.getEngine().getTextureManager().loadTexture(this.mTexture);
}
#Override
public Scene onLoadScene()
{
final Scene scene = new Scene(1);
backLayer=new Sprite(0,0,this.mTextureRegion);
scene.getTopLayer().addEntity(backLayer);
return scene;
}
I have a few fixes for you:
Don't use the constructor Scene(int), its deprecated. Use Scene() instead.
By your sprite's name, I guess it is your scene background? If this is your intention, you should use this: scene.setBackground(new SpriteBackground(backLayer));, instead of scene.getTopLayer().addEntity(backLayer);.
Lastly, I didn't see the method createFromAsset in TextureRegionFactory. Maybe you should update your AndEngine classes? And try this instead, might work:
BitmapTextureAtlas textureAtlas = new BitmapTextureAtlas(1024, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
this.mTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(textureAtlas, this, "bgr.png", 0, 0);

Only want one sprite to animate, instead they all do. Andengine

I'm creating an android app using Andengine. One part of the app requires users to select a few sprites from a group of sprites on the screen, which causes the selected sprites to turn a different color (ie, moving to the next tile). I declared them all as animated sprites and I'm using the same texture for each one. The problem is that once I select a sprite, every sprite moves to the next tile, not just the one I selected. How do I make just the one sprite change?
Here's where I setup the textures and whatnot:
private Texture mGreenTextureAtlas;
private TiledTextureRegion mGreenBallFaceTextureRegion;
#Override
public void onLoadResources() {
/* Textures. */
...
this.mGreenTextureAtlas = new Texture(32, 32, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
...
TextureRegionFactory.setAssetBasePath("gfx/");
/* TextureRegions. */
...
this.mGreenBallFaceTextureRegion = TextureRegionFactory.createTiledFromAsset(this.mGreenTextureAtlas, this, "green_ball.png", 0, 16, 2, 1); // 64x32
this.mEngine.getTextureManager().loadTextures(this.mCueTextureAtlas, this.mGreenTextureAtlas , this.mBackgroundTexture, this.mPocketTexture);
}
Here's where I actually create the sprites and apply the textures:
face = new AnimatedSprite(pX, pY, this.mGreenBallFaceTextureRegion);
body = PhysicsFactory.createCircleBody(this.mPhysicsWorld, face, BodyType.DynamicBody, FIXTURE_DEF);
encapsed = new Encapsulator(body, face, Encapsulator.AVOID_BALL, mFaceCount);
ballsList.add(encapsed);
I encapsulate each sprite, it's body, and some other data into an object that I made, and then add that object into an ArrayList.
Here is the onTouch event handler.
#Override
public boolean onAreaTouched( final TouchEvent pSceneTouchEvent, final ITouchArea pTouchArea,final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
if(pSceneTouchEvent.isActionDown()) {
final AnimatedSprite face = (AnimatedSprite) pTouchArea;
for(int i=0; i<ballsList.size(); i++)
{
if(face.equals(ballsList.get(i).animatedFace))
{
ballsList.get(i).toggleType(face);
System.out.println("Ball " + ballsList.get(i).id + " is now " + ballsList.get(i).type);
}
}
return true;
}
return false;
}
Finally, here is the toggleType method in the Encapsulator class that's responsible for moving to the next tile:
public void toggleType(AnimatedSprite face)
{
if(this.type == AVOID_BALL)
{
this.type = HIT_BALL;
face.nextTile();
}
else if(this.type == HIT_BALL)
{
this.type = AVOID_BALL;
face.setCurrentTileIndex(0);
}
}
Sorry if this is a bit long-winded. Any help is appreciated.
I did some more googling and came across a solution. I had to use the textureregion.clone() method when creating the sprites. I found the solution at this link:
http://www.andengine.org/forums/development/two-sprites-sharing-the-same-tiledtextureregion-t4339.html

Categories

Resources