I'm using a class that extends GenericPool to handle getting and recycling of sprites. What I'd like to do is have a method in that class to recycle after a certain duration. Something like:
public void recyleIn(Sprite sprite, float durationSeconds) {}
And there's a handy/dandy DelayModifier that seems like the proper way to implement it. So we'd have something like the following:
public void recyleIn(MySprite mySprite, float durationSeconds) {
mySprite.registerEntityModifier(
new DelayModifier(
durationSeconds,
new IEntityModifierListener() {
#Override
public void onModifierStarted(IModifier<IEntity> pModifier, IEntity pItem) {
}
#Override
public void onModifierFinished(IModifier<IEntity> pModifier, IEntity pItem) {
recycle(mySprite);
}
}
));
}
Now here's the problem: I can't call the recycle() method or do the recycling right there unless the Sprite is "final". Ordinarily that wouldn't be a problem, I'd just make a "final" deepcopy and use that. But in this case, making a copy defeats the original purpose of recycling in a pool. (E.g., if I'm just going to make a copy anyway, why bother to recycle and use pooling in the first place?)
Any ideas on the proper approach/model for this sort of thing? Thanks in advance.
UPDATE:
Umm.. I just realized I could just use the IEntity parameter in the onModifierFinished() method. (I'm used to ignoring those parameters for some reason.) So I could do something like this within the onModifierFinished():
recycle((MySprite) pItem);
I'd still be curious on anyone's thoughts on the best approach, but I think I may have just missed the obvious here.
I'm going to go ahead and answer my own question to help those in this situation. The short answer is that it's proper to use the IEntity parameter rather than an object outside it. The second issue I ran into when doing this is that I wanted to detach the IEntity from the scene in this method but, in AndEngine, it's important that when an IEntity is detached from the scene it must happen in the UpdateThread--otherwise you have a chance of errors as the scene is drawing while something is being removed from it. The end result looks like this:
#Override
public void onModifierFinished(IModifier<IEntity> pModifier, final IEntity pItem) {
pool.getContext().runOnUpdateThread(new Runnable() {
#Override
public void run() {
pItem.detachSelf();
}
});
}
One other small but important point is the "final" modifier on the Ientity parameter--necessary so that it can be called within the run() thread.
Related
I am creating a custom View and I would like to listen for the transformation changes. For example, the ones triggered by View#setScaleX. One way to do it is overriding all the methods:
setTranslationX
setTranslationY
setTranslationZ
setElevation
setRotation
setRotationX
setRotationY
setScaleX
setScaleY
setPivotX
setPivotY
setCameraDistance
setAnimationMatrix
Am I missing anything? I don't care for the top/left/bottom/right properties so they are left out intentionally. However this is cumbersome. It would be better if I can just get a callback and listen for it. Is that possible?
//Make some kind of callback
public interface TransformationCallback{
//String whatWho is an example it can be anything.
void onTransform(String whatWho);
}
public class YourView extends View{
private TransformationCallback callback;
//Pass an interface into the View constructor
public YourView(Context context, TransformationCallback callback){
super(context);
this.callback = callback;
}
}
#Override
public void setTranslationX(float x){
//call onTransform from the callback
callback.onTransform("setTranslationX was called");
super.setTranslationX(x);
}
The only problem with this, is it will not detect internal changes to the underlining values that these functions "set".
For example there is a variable inside View called protected int mLeft; Which is modified multiple times, internally not using functions.
The variable is also protected meaning abstractions of View can also modify it without function calls.
For the most part only external classes that mess with Views will use those functions which may or may not effect you.
I've got a fragment, which I construct and insert a GraphicalView, and I need to know when the GraphicalView (chart) is done being drawn. the api isChartDrawn always returns false, including within onResume of the containing fragment.
public void onResume()
{
Log.d(TAG, "onResume, the mChart isDrawn: " + mChart.isChartDrawn());
super.onResume();
mListener.didNotificyChartDrawn();
}
Is there a notification I'm not seeing, or strategy for knowing when the chart is done being rendered? I'm asking because I need to access the series points from within one of the series of the XYChart used to construct the graphical view, like this:
mChart = new GraphicalView(getActivity(), mXYChart);
where mXYChart is an instance of the LineChart.
The graph renders fine, and I'm able to access the points I need later on via touch handling, just need to get to them a little earlier now and am hitting this issue. Any work arounds, etc, appreciated.
you're getting that because during onResume still was not draw yet. That's whole Android, not just aChartEngine. I'm not sure it's the best design decision, but that's how it is.
But good news is: there's a nice trick.
getView().getViewTreeObserver().addOnDrawListener(new OnDrawListener(){
void onDraw(){
getView().getViewTreeObserver().removeOnDrawListener(this);
// do your stuff here
}
});
this trick is used A LOT for animation, so you can measure stuff on screen and do the proper animations.
If you look at the onDraw method in GraphicalView, it sets the boolean mDrawn to true at the very end. So what must be happening is you are calling
public boolean isChartDrawn() {
return mDrawn;
}
Before it has completed the onDraw method. I would either create a interval handler to keep checking if mDrawn has been changed to true, or modify the library file GraphicalView so that it has an optional listener that you can attach to be fired off when the thing is drawn:
DrawnInterface mCallback;
public interface DrawnInterface{
public void onDrawn();
}
.....
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.getClipBounds(mRect);
......
canvas.drawBitmap(fitZoomImage, left + width - zoomSize * 0.75f, buttonY, null);
}
mDrawn = true;
mCallback.onDrawn();
}
Then make your calling activity implement the DrawnInterface you defined, and initialize the interface inside the constructor of GraphicalView
I have the following (simplified) rig so far:
MyActivity.java:
public class MyActivity extends Activity {
public GLSurfaceView myGLView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myGLView = new MyGLSurfaceView(this);
setContentView(myGLView);
}
}
MyGLSurfaceView.java:
public class MyGLSurfaceView extends GLSurfaceView {
private MyRenderer mMyRenderer = new MyRenderer();
private MyThread mMyThread = new MyThread();
public MyView(Context context) {
super(context);
setRenderer(mGameRenderer);
setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
mGameThread.setRunning(true);
}
}
MyRenderer.java:
public class GameRenderer implements GLSurfaceView.Renderer {
#Override
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
// ...
}
}
MyThread.java:
Here I'm doing all initializations, creating objects and so on.
public class MyThread extends Thread {
private MyObject mMyObject = new MyObject();
public MyThread {
// ...
mMyObject.setRot();
this.start();
}
public void run() {
// Fixed Timestep Loop goes here
mMyObject.getRot();
}
}
MyObject.java:
This is a sample object which holds different fileds and methods.
public class MyObject {
private double mRot;
// Getters & Setters
protected double getRot() { return mRot; }
protected void setRot() {
// ... Do calculations
}
public void draw() {
// OGL Instructions go here
gl.glRotatef(1.2f, 0, 0, setRot());
}
}
Now the problem I was running into is the following: (I guess, I missed something very basic and simple :) )
As stated above, I'm creating my object instances in the MyThread class. The Thread is created in the MyGLSurface class, same goes for the Renderer. Now, that I have that two threads I can't figure out, how to use that one instance and their methods in that two separate threads.
I tried different approaches, but nothing did work. So in my opinion I made a mistake in the class design. I mean, I don't just want to get it running (that'd be quite easy), but I want to know how to do it correctly.
The main problem is actually that I can't access the MyObject's instance and simply use the draw() method in the renderer - because I don't get it.
I thought, it would be possible to call the draw() method of MyObject within the rendering thread without the need of using a singleton and so on. So simply referencing the instance to it. But somehow that seemed weird and dirty (besides that it doesn't work for me).
I tried dozens of different approaches, but I really need a bump into the right direction. I'm quite familar with OOP, but here I might really miss something.
In that many samples I found on the web (stackoverflow, Replica Island, different tutorial sites, Google I/O, DevCentral, etc.) they either didn't use a multithreaded system or they split it directly (GL objects from regular objects).
Any hint into the right direction would be much appreciated!
Another example to peruse:
https://code.google.com/p/android-breakout/
The wiki and code comments discuss the threading issues inherent in using GLSurfaceView. In particular, the game does as much setup as it can before the Renderer thread starts; once it's running, as much work as possible is done on that thread. The game state objects are effectively "owned" by the renderer thread, and the Activity is owned by the UI thread, so any "off-thread" interactions are handled by sending messages rather than making direct method calls. For example, see the handling of touch events.
It's good that you're thinking about this -- you either need synchronization or careful object discipline to avoid nasty race conditions.
See also: android game loop vs updating in the rendering thread
The nice thing about GLSurfaceView is that it creates the OpenGL rendering thread for you, so you don't need to create one yourself. The main UI thread will call the OnDraw() method in your view class and that's all the threads you need. If you really want to create your own thread for OpenGL rendering, use TextureView instead of GLSurfaceView. Here is an article that I think will help:
http://software.intel.com/en-us/articles/porting-opengl-games-to-android-on-intel-atom-processors-part-1
I know a good amount of java but this is my first time programming with the android sdk. I need to get the rotation of the phone in real time and display it on the screen. I was wondering what sensor method to use, as I heard that getOrientation was processor intensive and may not work in real time. Secondly, I was wondering which class I'd right this program in, I don't quite understand android class hierarchy yet. Thirdly, how would I make the numbers change on the screen in real time?
Thanks for the help!
I was wondering what sensor method to use, as I heard that getOrientation was processor intensive and may not work in real time.
You'll want to have a look at the OrientationEventListener object.
Secondly, I was wondering which class I'd right this program in, I don't quite understand android class hierarchy yet.
To get you started, you could build all this code into an Activity. Unlike a traditional Java program there is no main() entry point method and you won't user the constructors of application component classes to instantiate them. Lifecycle callback methods like onCreate() and onDestroy() are where you will want to do initialization and teardown of instance information. This guide may help you in how to construct your application to use a single Activity.
Thirdly, how would I make the numbers change on the screen in real time? Thanks for the help!
The OrientationEventListener includes a callback method for each change, simply use this callback to update a view in your UI.
Here is a simple example pulling it all together:
public class OrientationActivity extends Activity {
private OrientationEventListener mListener;
private TextView mTextView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mTextView = new TextView(this);
setContentView(mTextView);
mListener = new OrientationEventListener(this, SensorManager.SENSOR_DELAY_UI) {
#Override
public void onOrientationChanged(int orientation) {
mTextView.setText(String.valueOf(orientation);
}
};
}
#Override
public void onResume() {
super.onResume();
mListener.enable();
}
#Override
public void onPause() {
super.onPause();
mListener.disable();
}
}
I am designing a simple Android game and I am having problem with collusion.
There is Sprite object and another static sprite object when they collide beginContact(Contact..) function never gets called.
When does this get beginContact function get called? Is there any nice example that u know of?
Thanks for the help.
Much appreciated.
I am not sure if you can use beginContact on sprites, as far as I know it is tied to the box2D extension. Anyway, I use the following snippet:
public boolean setListener(PhysicsWorld mGamePhysicsWorld) {
mGamePhysicsWorld.setContactListener(new ContactListener() {
#Override
public void beginContact(final Contact contact) {
// do stuff
}
public void endContact(Contact contact) {
// do some other stuff
});
return true;
}