animated sprite from multiple sprite sheets - android

Im new to android dev and using andengine and ive just come across a problem when dealing with a large animation that covers more then 1 sprite sheet. Basically I have a large sprite whose animation runs across 2 sprite sheets. Im trying to find a way to load them successfully. I will show you what I am trying and hopefully some one can either show me the correct way or help me finish it my way.
i start off by creating the 2 texture packs from the xml files.
these are created fine
TexturePackTextureRegionLibrary packer1 = null,packer2 = null;
TexturePack spritesheetTexturePack1 = null,spritesheetTexturePack2 = null;
try {
spritesheetTexturePack1 = new TexturePackLoader(activity.getTextureManager(), "Animation/Jack/")
.loadFromAsset(activity.getAssets(), "Jack_walk1" + ".xml");
spritesheetTexturePack1.loadTexture();
packer1 = spritesheetTexturePack1.getTexturePackTextureRegionLibrary();
} catch (final TexturePackParseException e) {
Debug.e(e);
}
TexturePackerTextureRegion textureRegion = packer1.get(Jack_walk1.LOOP_JACK_WALK_TO_SAFE_AREA_00000_ID);
try {
spritesheetTexturePack2 = new TexturePackLoader(activity.getTextureManager(), "Animation/Jack/")
.loadFromAsset(activity.getAssets(), "Jack_walk2" + ".xml");
spritesheetTexturePack2.loadTexture();
packer2 = spritesheetTexturePack2.getTexturePackTextureRegionLibrary();
} catch (final TexturePackParseException e) {
Debug.e(e);
}
TexturePackerTextureRegion textureRegion2 = packer2.get(Jack_walk1.LOOP_JACK_WALK_TO_SAFE_AREA_00000_ID);
ArrayList<SparseArray> animList = new ArrayList<SparseArray>();
animList.add(packer1.getIDMapping());
animList.add(packer2.getIDMapping());
TiledTextureRegion text1 = TiledTextureRegion.create(textureRegion.getTexture(), (int) textureRegion.getTextureX(), (int) textureRegion.getTextureY(), animList);
I then added this function to the tiledtextureregion to take in a list of arrays that hold the frame information and step through adding them to the itexturregion array
public static TiledTextureRegion create(final ITexture pTexture, final int pTextureX, final int pTextureY, final ArrayList<SparseArray> animList) {
ITextureRegion[] textureRegions = null;
int maxFrame = 0;
for(int i = 0; i < animList.size(); i++){
maxFrame += animList.get(i).size();
}
int currentFrame = 0;
textureRegions = new ITextureRegion[maxFrame];
for(int i = 0 ; i < animList.size(); i++){
SparseArray<? extends ITexturePackTextureRegion> packer = animList.get(i);
for(int j = 0; j < packer.size(); j++) {
if (packer.valueAt(j)!= null){
final int x = (int) packer.valueAt(j).getTextureX();
final int y = (int) packer.valueAt(j).getTextureY();
final int width = packer.valueAt(j).getSourceWidth();
final int height = packer.valueAt(j).getSourceHeight();
final Boolean rotated = packer.valueAt(j).isRotated();
textureRegions[currentFrame] = new TextureRegion(pTexture, x, y, width, height, rotated);
currentFrame++;
}
}
}
return new TiledTextureRegion(pTexture, false, textureRegions);
}
but the line return new TiledTextureRegion(pTexture, false, textureRegions); is expecting 1 texture do retrieve the frames from when creating the tiled region. Any ideas where i should go from here or is there a super easy way to handle this that i have over looked. Thanks for any help

This class is designed to work with a single texture.
If you cannot merge your textures into one (which I think is the case), then you can try to write a new class implementing ITextureRegion that will contain 2 or more TiledTextureRegion objects, and which will have a method to select one of these at will.
You will just have to delegate the remaining methods of ITextureRegion to the selected object.
public class MultipleTextureRegion implements ITextureRegion {
private List<TiledTextureRegion> internal;
private int selected=0;
//...
public void add(TiledTextureRegion region) {
internal.add(region);
}
public void select(int index) {
selected=index;
}
//...
// Delegates all ITextureRegion methods ...
public int getWidth() { return internal.get(selected).getWidth(); }
// And so on...
}

Related

Handling collision in Bullet through the .g3db files

I am developing a simple application using libgdx and the Bullet API. I have completed the basic prototype of this application using shapes but now I want to load the real models in the application. I have used the .g3db file for loading the models through AssetManager
private void doneLoading() {
// TODO Auto-generated method stub
Model model = manager.get("ping1.g3db", Model.class);
int index = 0;
for (int i = 0; i < model.nodes.size; i++) {
String id = model.nodes.get(i).id;
ModelInstance instance = new ModelInstance(model, id);
Node node = instance.getNode(id);
instance.transform.set(node.globalTransform);
//node.translation.set(0, 0, 0);
//node.scale.set(1, 1, 1);
//node.rotation.idt();
instance.calculateTransforms();
if (id.equals("ball4") || id.equals("bat")) {
instance_array.add(instance);
index += 1;
}
if (id.equals("ball4")) {
ball = instance;
Gdx.app.log("Ball Index", " " + index);
instance_map.put("ball", new GameObject.Constructor(model, id, new btSphereShape(0.165f), 1.0f));
createBall();
//ball.transform.setToTranslation(0f, 10f, 0f);
} else if (id.equals("bat")) {
Gdx.app.log("Bat Index", " " + index);
bat = instance;
instance_map.put("bat",new GameObject.Constructor(model, id, new btSphereShape(1.897f), 0.0f));
createBat();
}
}
loading = false;
}
private void createBat() {
// TODO Auto-generated method stub
GameObject object=instance_map.get("bat").construct();
object.body.setCollisionFlags(object.body.getCollisionFlags()|btCollisionObject.CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
instances_gameobject.add(object);
dynamicWorld.addCollisionObject(object.body);
}
private void createBall() {
// TODO Auto-generated method stub
GameObject object=instance_map.get("ball").construct();
Gdx.app.log("Ball", "Ball created");
object.moving=true;
object.body.setWorldTransform(object.transform);
object.body.setCollisionFlags(object.body.getCollisionFlags()|btCollisionObject.CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
instances_gameobject.add(object);
dynamicWorld.addCollisionObject(object.body);
}
Please tell how could I use the custom models for collision detection.
In the ConvexHullTest you can see how you can create a Shape for your CollisionObject from a Mesh.
public static btConvexHullShape createConvexHullShape (final Model model, boolean optimize) {
final Mesh mesh = model.meshes.get(0);
final btConvexHullShape shape = new btConvexHullShape(mesh.getVerticesBuffer(), mesh.getNumVertices(), mesh.getVertexSize());
if (!optimize) return shape;
// now optimize the shape
final btShapeHull hull = new btShapeHull(shape);
hull.buildHull(shape.getMargin());
final btConvexHullShape result = new btConvexHullShape(hull);
// delete the temporary shape
shape.dispose();
hull.dispose();
return result;
}
For me, it helped to "bake" the scales in blender per this post
Scaling a ModelInstance in libgdx 3D and Bullet engine
After doing this, collision shapes worked for me with this method.

Set Image Resource from Enum

I am trying to set an image based on the enum. I did try to do some research on how to do that using this post : How to match int to enum
but wasn't really sure how to actually use it according to my code.
Here's the enum:
public enum ImageValue{
Image1(1,R.drawable.clubs1),
Image2(2,R.drawable.hearts),
Image3(3,R.drawable.diamonds),
Image4(4,R.drawable.spades);
private int imagevalue;
private int image;
private ImageValue(int value, int drawable){
this.imagevalue = value;
this.image = drawable;
}
public int getImageValue(){
return image;
}
}
This is where I am getting the image values and other values:
public void NewDeck() {
deck = new ArrayList<Card>();
for (int i = 0; i < 13; i++) {
value = CardValue.values()[i];
for (int j = 0; j < 4; j++) {
card = new Card(value, Suit.values()[j], ImageValue.values()[j] );
this.deck.add(card);
}
}
Collections.shuffle(deck);
Iterator<Card> cardIterator = deck.iterator();
System.out.println(deck.size());
while (cardIterator.hasNext()) {
aCard = cardIterator.next();
}
System.out.println("One Card Value" + "--" + aCard.getCardValue()
+ " of " + aCard.getSuit()+"--"+"Image Value" +"----" + aCard.getImagevalue());
}
Here's one solution from the post I mentioned:
**coinView.setImageResource(coinArray[x].getImage());**
Now, On click of a button I want to set that random image that's being generated to one of my image views.
Here:
public void onClick(View v) {
randomImage.setImageResource(**Want to put the image here!**);
}
I am a bit new to Enum concept and not sure how exactly to use it.
A little help will be really appreciated..Thank's in advance.

How to reload libgdx unmanaged Texture after OpenGL context loss

I'm downloading images over the network and add them to my libgdx UI as Image actors using this:
Pixmap pm = new Pixmap(data, 0, data.length);
Texture t = new Texture(pm);
TextureRegion tr = new TextureRegion(t,200,300);
TextureRegionDrawable trd = new TextureRegionDrawable(tr);
Image icon = new Image();
icon.setDrawable(trd);
Given this I need some way of reloading the texture data since it is lost when the OpenGL context is lost (e.g. because the screen goes to sleep).
I've tried making my own manager class, adding
DynamicTextureManager.register(t, pm); // Register texture together with the source pixmap
to the above snippet, and in resume() I do:
DynamicTextureManager.reload();
The manager class:
public class DynamicTextureManager {
private static LinkedHashMap<Texture, Pixmap> theMap = new
LinkedHashMap<Texture,Pixmap>();
public static void reload() {
Set<Entry<Texture,Pixmap>> es = theMap.entrySet();
for(Entry<Texture,Pixmap> e : es) {
Texture t = e.getKey();
Pixmap p = e.getValue();
t.draw(p, 0, 0);
}
}
public static void register(Texture t, Pixmap p) {
theMap.put(t, p);
}
}
But this doesn't help - I still end up with the texture being unloaded and white areas instead of the image.
How should this be done? I haven't been able to find any code demonstrating this!
Adding my solution as a reference. I now register the Image object and the Pixmap object with my manager, on reload() the Texture is re-created from the Pixmap and I set the new Texture for the old Image. Works for me, but more elegant solutions are welcome.
import java.util.Map.Entry;
public class DynamicTextureManager {
private static final class MapData {
Pixmap pixmap;
int width;
int height;
}
private static WeakHashMap<Image, MapData> theMap = new WeakHashMap<Image, MapData>();
public static void reload() {
Set<Entry<Image, MapData>> es = theMap.entrySet();
for (Entry<Image, MapData> e : es) {
Image i = e.getKey();
MapData d = e.getValue();
Texture t = new Texture(d.pixmap);
TextureRegion tr;
if(d.width == -1 || d.height == -1) {
tr = new TextureRegion(t);
}
else {
tr = new TextureRegion(t,d.width, d.height);
}
TextureRegionDrawable trd = new TextureRegionDrawable(tr);
i.setDrawable(trd);
}
}
public static void register(Image i, Pixmap p) {
MapData d = new MapData();
d.pixmap = p;
d.width = -1;
d.height = -1;
theMap.put(i, d);
}
public static void register(Image i, Pixmap p, int width, int height) {
MapData d = new MapData();
d.pixmap = p;
d.width = width;
d.height = height;
theMap.put(i, d);
}
}

Trying to set textview

Here is my class it goes in to infinite loop please check where I am going wrong ... I am trying to get id's of image view making it random and then trying to set text view with imageview's description
public class Object {
int ObectIds[];
LinearLayout HUDDisplay;
int HudDisplayText[] = {R.id.HUD_Text_Element1,
R.id.HUD_Text_Element2,
R.id.HUD_Text_Element3,
R.id.HUD_Text_Element4,
R.id.HUD_Text_Element5,
R.id.HUD_Text_Element6,
R.id.HUD_Text_Element7};
TextView[] text;
View v;
Object(Context context,View vs) {
super();
ObectIds = new int[8];
HUDDisplay=(LinearLayout)vs.findViewById(R.id.HUD_Display);
for (int i = 0; i < 8; i++) {
ObectIds[i] = (R.id.imageView1) + i;
Log.d("ImageView", "Image Id's " + ObectIds[i]);
}
randomize(vs);
setTextView();
}
public void setTextView()
{
for(int i=0;i<8;++i)
{
text[i] =(TextView) HUDDisplay.findViewById(HudDisplayText[i]);
text[i].setText(v.getContentDescription());
}
}
public void randomize(View vs) {
for (int i = 0; i < 8; i++) {
while (true) {
shuffleArray(ObectIds);
v = vs.findViewById(ObectIds[i]);
Log.d("Image", "Image Id's " + v.getId());
if (!v.isClickable()) {
v.setClickable(true);
break;
}
}
}
}
static void shuffleArray(int[] ar) {
Random rnd = new Random();
for (int i = ar.length - 1; i >= 0; i--) {
int index = rnd.nextInt(i + 1);
// Simple swap
int a = ar[index];
ar[index] = ar[i];
ar[i] = a;
}
}
}
Hey man I observed your code & found error in code :
Please compare following code with your code... Constructor
for (int i = 0; i < 8; i++) {
ObectIds[i] = **HudDisplayText[i]**;
Log.d("ImageView", "Image Id's " + ObectIds[i]);
}
You have a while(true) loop that you break from only if v is not clickable. What happens if v is clickable? Nothing in your code ever sets v to not clickable, and views by default are not clickable.
I notice you're using the Object class. Object is basically the root of which all classes extend. If you call super() in the constructor, it will call the super class constructor, which is Object as well... That might be the problem.
Try looking for tutorials on how to start with Java/Android, since you are also using variables names that are not recommended. E.g. in Java,:
- a Class starts with a Capital
- a variable, starts with lowercase
- a function starts with lowercase:
public class Captial
{
private int anIntegerStartsWithLowerCase;
private void functionsAreLowerCaseAsWell()
{
}
}
Also take a look at your loop... It looks like it is never ending

Drawing dynamic elements onto a normal xml layout

I've been trying to figure this out for a while now... I need to place marks over top of a seekBar to show the user places that they bookmarked in the past. The data is stored in xml. The problem is making the little ovals appear over the seekBar... It just doesn't work...
Here's my code:
public class seekMark extends View {
private int seekLength; // in pixels
private int seekLeftPad; // in pixels
private int seekBottomPad; // in pixels
private int trackLength; // in ms
private float pxOverMs; // in px/ms
ShapeDrawable lmark;
private seekMark instance;
public seekMark(Context context){
super(context);
instance = this;
seekLength = progressBar.getWidth();
seekLeftPad = progressBar.getPaddingLeft();
seekBottomPad = progressBar.getBottom();
trackLength = player.getDuration();
pxOverMs = pxPerMs();
lmark = new ShapeDrawable(new OvalShape());
}
private float pxPerMs(){
return ((float) seekLength)/((float) trackLength);
}
private int[] markPxList() throws XmlPullParserException, IOException {
int bmStartTime = 0;
String bmNames[] = bmNameList(xmlPath);
int[] bmPos = new int[bmNames.length];
for(int i=0; i < bmNames.length; i++){
bmStartTime = getBookmark(xmlPath, bmNames[i]);
bmPos[i] = (int) (bmStartTime * pxOverMs);
}
return (bmPos);
}
public void markPlace() throws XmlPullParserException, IOException {
int y = seekBottomPad;
int x = 0;
int bmPos[] = markPxList();
for(int i = 0; i < bmPos.length; i++){
x = bmPos[i] + seekLeftPad;
lmark = new ShapeDrawable();
lmark.getPaint().setColor(0xff74AC23);
lmark.setBounds(x, y, x + 1, y + 1);
instance.invalidate();
}
}
protected void onDraw(Canvas canvas) {
lmark.draw(canvas);
}
}
It's called from onCreate using this code. I call it using in another thread to avoid the problem where the dimensions of progressBar aren't yet set in onCreate.
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if (display.getRotation() == 1){ // if landscape
final Runnable runner = new Runnable() {
public void run() {
seekMark seekMarks = new seekMark(context);
try {
seekMarks.markPlace();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// runs in another thread to avoid the problem with calling
// seekMark directly from onCreate
}
};
handler.postDelayed(runner, 1000);
}
The program crashes whenever I try to call seekMark.markPlace()... I'm trying to draw this over top of my layout main.xml.
im not sure if this is what you are trying to do.
Customize Seekbar
this seems to be similar while the approach is different.

Categories

Resources