I try to use SurfaceGestureDetector This class use only SurfaceGestureDetector and not work. i a msg "03-14 20:40:47.746: I/AndEngine(8963): org.anddev.andengine.input.touch.TouchEvent$TouchEventPool was exhausted, with 0 item not yet recycled. Allocated 1 more." Only Tag Log.d("test", "TouchEvent"); work
public class MainActivity extends BaseGameActivity {
// ===========================================================
// Constants
// ===========================================================
private static final int CAMERA_WIDTH = 480;
private static final int CAMERA_HEIGHT = 320;
// ===========================================================
// Fields
// ===========================================================
private Camera mCamera;
//private Texture mTexture, mBatTexture;
//private TiledTextureRegion mBatTextureRegion;
//private TextureRegion mSplashTextureRegion;
private Handler mHandler;
//static protected Music mMusic;
private Scene mScene;
private SurfaceGestureDetector surfaceGestureDetector;
private TouchEvent pSceneTouchEvent;
// ===========================================================
// Constructors
// ===========================================================
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
#Override
public Engine onLoadEngine() {
mHandler = new Handler();
this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
return new Engine(new EngineOptions(true, ScreenOrientation.LANDSCAPE, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), this.mCamera));
}
#Override
public void onLoadResources() {
}
#Override
public Scene onLoadScene() {
this.mEngine.registerUpdateHandler(new FPSLogger());
this.mScene = new Scene();
setupGestureDetaction();
return mScene;
}
#Override
public void onLoadComplete() {
//mHandler.post(mLaunchTask);
}
private Runnable mLaunchTask = new Runnable() {
public void run() {
Intent myIntent = new Intent(MainActivity.this, TMXTiledMapExample.class);
MainActivity.this.startActivity(myIntent);
}
};
private void setupGestureDetaction(){
surfaceGestureDetector = new SurfaceGestureDetector(1f) {
#Override
protected boolean onSingleTap() {
// TODO Auto-generated method stub
Log.d("test", "onSingleTap");
return true;
}
#Override
protected boolean onDoubleTap() {
Log.d("test", "onDoubleTap");
// TODO Auto-generated method stub
return false;
}
#Override
protected boolean onSwipeUp() {
// TODO Auto-generated method stub
return false;
}
#Override
protected boolean onSwipeDown() {
// TODO Auto-generated method stub
return false;
}
#Override
protected boolean onSwipeLeft() {
// TODO Auto-generated method stub
return false;
}
#Override
protected boolean onSwipeRight() {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean onManagedTouchEvent(TouchEvent pSceneTouchEvent) {
return super.onManagedTouchEvent(pSceneTouchEvent);
}
#Override
public boolean onSceneTouchEvent(Scene pScene,
TouchEvent pSceneTouchEvent) {
Log.d("test", "TouchEvent");
return super.onSceneTouchEvent(pScene, pSceneTouchEvent);
//return false;
}
};
// if (pSceneTouchEvent!=null){
// TouchEvent.recycle(pSceneTouchEvent);}
surfaceGestureDetector.setEnabled(true);
mScene.setOnSceneTouchListener(surfaceGestureDetector);
}
// ===========================================================
// Methods
// ===========================================================
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}
This question is old as i write this reply, but the log message you show above is a not an error message. It is an appropriate message letting you know that the Object Pool for touch events did not contain any touches, so it created more.
This is a normal message from Andengine, and you will see it when you first start using touches, but less as the app runs, because the pool size will grow, and so a touch will be recycled rather than created.
Related
Is there any way to get objects to foregorund in surfaceView.
for example:
canvas.drawBitmap(...);
canvas.drawText(...);
If I do that text appeared on bitmap. How can I reverse it without redrawing
Sorry for my English.
Canvas just encapsulates bitmap object and bitmap only saves colour of pixel at some position, it doesn't save separate layers. It's like to draw in MSPaint. So you can't change the Z-order of your primitives on canvas. However, why don't you just change the order of commands?
There is no method to bring elements front and back. You are trying to alter the Z-order of the elements here and this is not possible or there is no direct method in Android. All you can do is arrange them in the layout and enable and disable views so that it will give you the same effect.
You can use addView() or setVisibility(View.Visible) to bring bring elements back and front.
Please try to use bellow code.
//SurfaceView class
public class MainGamePanel extends SurfaceView implements
SurfaceHolder.Callback {
MainThread thread;
public MainGamePanel(Context context) {
super(context);
// TODO Auto-generated constructor stub
getHolder().addCallback(this);
setFocusable(true);
thread = new MainThread(getHolder(), this);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
Log.e("N", "Changed");
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
Log.e("N", "Created");
thread.setRunning(true);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
Log.e("N", "Destroyed");
boolean retry = true;
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
// try again shutting down the thread
}
}
}
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (event.getY() > getHeight() - 50) {
thread.setRunning(false);
((Activity) getContext()).finish();
} else {
Log.d("N", "Coords: x=" + event.getX() + ",y=" + event.getY());
}
}
return super.onTouchEvent(event);
}
}
//MainThread class
public class MainThread extends Thread {
// flag to hold game state
private boolean running;
private SurfaceHolder surfaceHolder;
private MainGamePanel gamePanel;
public void setRunning(boolean running) {
this.running = running;
}
public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) {
super();
this.surfaceHolder = surfaceHolder;
this.gamePanel = gamePanel;
}
#Override
public void run() {
long tickCount = 0L;
Log.d("N", "Starting game loop");
while (running) {
tickCount++;
// update game state
// render state to the screen
}
Log.d("N", "Game loop executed " + tickCount + " times");
}
}
//Main Activity
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MainGamePanel(this));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
i managed to animate a View on a Layout using ObjectAnimator.
i tried animating objects on canvas using the ObjectAnimator class but it didn't work.
is it even possible?
what i did is creating a class extending View, i defined the ObjectAnimator like i did on the Layout, then i drew it on the canvas and started the animation (objectanimator.start)
here is the code:
(the // lines are my Layout try witch worked)
public class MainActivity extends Activity {
SurfaceClass surface;
private ObjectAnimator anima;
//private Button but;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
surface = new SurfaceClass(this);
surface.resume();
setContentView(surface);
//but = (Button)findViewById(R.id.button1);
//anima = ObjectAnimator.ofFloat(but, "y",400);
//anima.setDuration(5000);
//anima.setRepeatCount(100);
//anima.setRepeatMode(1);
//anima.start();
}
surface:
public class SurfaceClass extends SurfaceView implements Runnable{
SurfaceHolder sHolder;
Boolean isRunning;
Thread th;
Canvas c;
Obj object;
ObjectAnimator anima;
public SurfaceClass(Context context) {
super(context);
// TODO Auto-generated constructor stub
anima = ObjectAnimator.ofFloat(object, "y",1f);
anima.setDuration(3000);
anima.setRepeatCount(100);
anima.setRepeatMode(1);
//anima.start();
object = new Obj(context);
sHolder = getHolder();
isRunning = false;
}
#Override
public void run() {
// TODO Auto-generated method stub
while(isRunning){
if(!sHolder.getSurface().isValid())
continue;
c = sHolder.lockCanvas();
synchronized(sHolder){
doDraw(c);
}
sHolder.unlockCanvasAndPost(c);
}
}
private void doDraw(Canvas c) {
// TODO Auto-generated method stub
c.drawBitmap(object.pic, object.x, object.y, null);
anima.start();
}
public void resume() {
// TODO Auto-generated method stub
isRunning = true;
th = new Thread(this);
th.start();
}
}
object:
public class Obj extends View {
float x = 200,y=30;
Bitmap pic;
public Obj(Context context) {
super(context);
// TODO Auto-generated constructor stub
pic = BitmapFactory.decodeResource(getResources(), R.drawable.cat_trance);
}
public void setY(float f){
y=f;
}
public float getY(){
return y;
}
}
try this,
#Override
protected void onAttachedToWindow(){
anima.start();
}
and remove anima.start(); in doDraw method.
I have a main activity class, I've also got a SurfaceView class that starts when my main activity starts.
I've got a seek bar in the main activity. I'd like to send whatever data that the seek bar produces to the SurfaceView to show it, every time it changes.
How can I do that?
Thanks.
Here is my SurfaceView class:
public class SurfaceViewGauge extends SurfaceView implements SurfaceHolder.Callback{
private MySurfaceThread thread;
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
public SurfaceViewGauge(Context context) {
super(context);
// TODO Auto-generated constructor stub
init();
}
public SurfaceViewGauge(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init();
}
public SurfaceViewGauge(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
init();
}
private void init(){
getHolder().addCallback(this);
thread = new MySurfaceThread(getHolder(), this);
setFocusable(true); // make sure we get key events
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
paint.setColor(Color.WHITE);
}
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
thread.setRunning(true);
thread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
boolean retry = true;
thread.setRunning(false);
while (retry) {
try {
thread.join();
retry = false;
}
catch (InterruptedException e) {
}
}
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
}
}
And Here is my Thread class:
public class MySurfaceThread extends Thread {
private SurfaceHolder myThreadSurfaceHolder;
private SurfaceViewGauge myThreadSurfaceView;
private boolean myThreadRun = false;
public MySurfaceThread(SurfaceHolder surfaceHolder, SurfaceViewGauge surfaceView) {
myThreadSurfaceHolder = surfaceHolder;
myThreadSurfaceView = surfaceView;
}
public void setRunning(boolean b) {
myThreadRun = b;
}
#Override
public void run() {
// TODO Auto-generated method stub
while(myThreadRun){
Canvas c = null;
try{
c = myThreadSurfaceHolder.lockCanvas(null);
synchronized (myThreadSurfaceHolder){
myThreadSurfaceView.onDraw(c);
}
sleep(0);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
myThreadSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
in your MainActivity declare a static variable which will hold seekbar value and in your surfaceview code with the help of handler just call that static variable
e.g.
MainClass.seekValue;
In your Code, add Handler..
public Handler mhandler;
public SurfaceViewGauge(Context context, Handler mhandler)
{
super(context);
this.mhandler = mhandler;
// TODO Auto-generated constructor stub
init();
}
In the above code, use the Handler object for sending the code.
I have code like this:
public class SnowFallService extends BaseLiveWallpaperService implements IOnAreaTouchListener{
// ===========================================================
// Constants
// ===========================================================
private static final int CAMERA_WIDTH = 480;
private static final int CAMERA_HEIGHT = 800;
private ArrayList<Sprite> allSnow = new ArrayList<Sprite>();
// ===========================================================
// Fields
// ===========================================================
private ScreenOrientation screenOrientation;
private static TextureRegion snowTexture;
private static TextureRegion backgroundTexture;
private static Textures texture = null;
private Scene mScene;
public org.anddev.andengine.engine.Engine onLoadEngine() {
return new org.anddev.andengine.engine.Engine(new EngineOptions(true, this.screenOrientation, new FillResolutionPolicy(), new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT)));
}
public void onLoadResources() {
texture = new Textures(this, getEngine());
}
public void onUnloadResources() {
}
public Scene onLoadScene() {
final Scene mScene = new Scene();
backgroundTexture = texture.getBackground();
mScene.attachChild(new Sprite(0, 0, backgroundTexture));
snowTexture = texture.getSnowTextureRegion();
mScene.registerUpdateHandler(new IUpdateHandler() {
private long lastRaindropAdd = 0;
#Override
public void onUpdate(final float pSecondsElapsed) {
int size = allSnow.size();
int tmpInt = 0;
Random randGen = new Random();
for (int i = 0; i < size; i++) {
if (allSnow.get(i) != null){
Sprite snow = allSnow.get(i);
tmpInt = randGen.nextInt(4);
snow.setPosition(snow.getX() + (randGen.nextInt(5) - randGen.nextInt(5)) * randGen.nextInt(3), snow.getY() + tmpInt);
if (snow.getY() > CAMERA_HEIGHT || snow.getX() > CAMERA_WIDTH) {
synchronized(snow) {
size--;
allSnow.remove(i);
mScene.detachChild(snow);
}
}
}
}
tmpInt = randGen.nextInt(5000);
if (System.currentTimeMillis() - lastRaindropAdd > tmpInt) {
lastRaindropAdd = System.currentTimeMillis();
tmpInt = randGen.nextInt(CAMERA_WIDTH);
Sprite snow = getRaindrop(tmpInt, 0);
allSnow.add(snow);
mScene.attachChild(snow);
}
}
#Override
public void reset() {
}
});
return mScene;
}
public void onLoadComplete() {
// TODO Auto-generated method stub
}
public void onPauseGame() {
// TODO Auto-generated method stub
}
public void onResumeGame() {
// TODO Auto-generated method stub
}
public Sprite getRaindrop(float x, float y) {
return (new Sprite(x, y, snowTexture.deepCopy()));
}
#Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent,ITouchArea pTouchArea, float pTouchAreaLocalX, float pTouchAreaLocalY) {
if(pSceneTouchEvent.isActionDown()) {
// HERE I WANT PLACE CODE, THAT WILL START ANIMATION.
return true;
}
return false;
}
}
So how to start animation on click? I want to make something like small cartoon.
In your onLoadScene method after registering update handler disable it.
mUpdateHandler.setEnabled(false);
And in onAreaTouched method enable it.
mUpdateHandler.setEnabled(true);
Btw I think it's not good practice to create Random instance every time in onUpdate method.
Here Josh describes how to override onTouch method (andEngine does not handle touch events for livewallpaper correctly, so you have to do it on your own). In few words, all you have to do is to override following function in BaseWallpaperGLEngine class (class is a part of andEngine live wallpaper extension:
#Override
public void onTouchEvent (MotionEvent event)
{
}
This might seem like a silly qustion but how do you change the picture that draws on the screen.I have already been able to program a app were it draws a little icon where you touch the screen.So natually after I completed that I want to make it better by adding a option menu and the ability to change what icon you were being drown but when I ran the code the icon picture stayed the same.When I looked at it I found that when you click on any of the menu item it does do it's job and change the image id but when you go back to the main screen and try to create a new image it revertes back to the old image.I have no idea why it doesn't change because when I look at it everything make sense for it to change icon properly.If any one has any idea on what i am doing wrong or any suggestion on how to do this it would be greatly appreciate
Main
public class main extends Activity {
/** Called when the activity is first created. */
MenuItem item2;
int item3=R.drawable.ic_launcher;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FrameLayout sv = new FrameLayout(this);
LinearLayout ll = new LinearLayout(this);
Panel test = new Panel(this);
//ImageButton button = new ImageButton(this);
ll.setOrientation(LinearLayout.VERTICAL);
sv.addView(test);
//ll.addView(button);
sv.addView(ll);
setContentView(sv);
}
public boolean onCreateOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
Log.v("test", "item3 before is: "+item3);
item3=R.drawable.box;
Log.v("test", "item3 after is: "+item3);
return super.onOptionsItemSelected(item);
}
}
Panel
public class Panel extends SurfaceView implements SurfaceHolder.Callback {
private Bitmap image;
private ViewThread mThread;
private int x;
private int y;
private ArrayList<Element> mElements = new ArrayList<Element>();
public Panel(Context context) {
super(context );
image = BitmapFactory.decodeResource(getResources(),yantz.imageapp4.R.drawable.test);
getHolder().addCallback(this);
mThread = new ViewThread(this);
}
public void doDraw(Canvas canvas) {
canvas.drawColor(Color.CYAN);
canvas.drawBitmap(image, x, y, null);
synchronized (mElements){
for(Element element : mElements){
element.doDraw(canvas);
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
Log.v("test", "you have touched the sreen: ");
synchronized (mElements){
mElements.add(new Element(getResources(),(int) event.getX(),(int) event.getY()));
}
return super.onTouchEvent(event);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (!mThread.isAlive()) {
mThread = new ViewThread(this);
mThread.setRunning(true);
mThread.start();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mThread.isAlive()) {
mThread.setRunning(false);
}
}
}
Elements
public class Element extends main{
private int mX;
private int mY;
int location ;
private Bitmap mBitmap;
public Element(Resources res, int x, int y) {
Log.v("element", "item3 before location is: "+item3);
location =item3;
mBitmap = BitmapFactory.decodeResource(res, location);
mX = x - mBitmap.getWidth() / 2;
mY = y - mBitmap.getHeight() / 2;
Log.v("element", "item3 before location is: "+item3);
}
public void doDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap, mX, mY, null);
}
public void setlocation(int location2){
location=location2;
}
}
ViewThread
public class ViewThread extends Thread {
private Panel mPanel;
private SurfaceHolder mHolder;
private boolean mRun = false;
public ViewThread(Panel panel) {
mPanel = panel;
mHolder = mPanel.getHolder();
}
public void setRunning(boolean run) {
mRun = run;
}
#Override
public void run() {
Canvas canvas = null;
while (mRun) {
canvas = mHolder.lockCanvas();
if (canvas != null) {
mPanel.doDraw(canvas);
mHolder.unlockCanvasAndPost(canvas);
}
}
}
}
you can use
#Override
protected void onResume() {
super.onResume();
id="what ever you want";
//and set it to imagevIew;
}
if i have understood the uestion correctly,this happens because your activity pauses when it is not focused and resumes with default values.