Android sprite touch event gives error - android

I have the following code:
Sprite sPlayer = new Sprite(800 / 2, 480 / 2,
playerTextureRegion,
engine.getVertexBufferObjectManager()){
#Override
public boolean onAreaTouched(final TouchEvent tEvent, final float X,
final float Y)
{
if ( tEvent.isActionDown() )
// Some code
return true;
};
};
gameScene.registerTouchArea(sPlayer);
gameScene.setTouchAreaBindingOnActionDownEnabled(true);
gameScene.attachChild(sPlayer);
When I run it, it gives me error and the app closes
I see most people using gameScene.setTouchBindingEnabled(True)
instead of gameScene.setTouchAreaBindingOnActionDownEnabled(true); but Eclipse doesn't recognize this one and I can't import any package for it. What exactly am I doing wrong?
Thanks in advance for your answers.

According to your comment, you need to use the function runOnUiThread
YourActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(YourActivity.this, msg, Toast.LENGTH_SHORT).show();
}
});
or, you can use the function toastOnUiThread :
YourActivity.toastOnUiThread(msg,Toast.LENGTH_SHORT);
where YourActivity is your activity in the game(just pass a reference to it)

Related

How to animate zooming in Android

I'm developing an Android application, I used this library
barteksc:android-pdf-viewer:2.3.0
I have to implement a simple animation, this is the code that I have implemented:
private void selectArea(){
/* Stop movement, jump to page 2, disable all action on PDFView*/
pdfView.stopFling();
pdfView.jumpTo(2);
pdfView.setEnabled(false);
pdfView.zoomWithAnimation(0, 1500, (float) 1.95);
}
private void resetAnimation() {
pdfView.resetZoomWithAnimation();
}
I need to select a certain area, reset the zoom and select again the area, so the problem is :
When I call selectarea () function shows the area that I want to show, when it resetarea call () the zoom is restored, if i call again the selectarea function the pdfView.resetZoomWithAnimation() call is ignored, and I don't understand why.
Pseudocode of my app.
selectArea();
//do stuff
resetAnimation()
selectArea();
**** SOLUTION ****
After hours of attempts I found a solution of my problem:
private void selectAreaToSign(){
/* Stop movement, jump to page 2, disable all action on PDFView*/
pdfView.stopFling();
pdfView.clearFocus();
pdfView.jumpTo(2);
pdfView.setEnabled(false);
pdfView.clearAnimation();
pdfView.clearFocus();
if(isFirstTime){
pdfView.zoomWithAnimation(0, 1700, (float) 2.00);
}else{
resetAnimation();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
sv.setVisibility(View.VISIBLE);
pdfView.zoomWithAnimation(4500, 1700, (float) 2.00);
}
}, 1000);
}
}
private void resetAnimation() {
pdfView.resetZoomWithAnimation();
sv.setVisibility(View.INVISIBLE);
pdfView.zoomTo(1);
}

AndEngine registerEntityModifier is not working

Im trying to make simple puzzle game using AndEngine. Everything was wokring fine till I got this strange issue.
I have a function to move the sprite in the scene as below.
private void placeSprite(final float touchX, final float touchY) {
float posX = selectedSprite.getX();
float posY = selectedSprite.getY();
moveModifier = new MoveModifier(0.25f, posX, posY, touchX, touchY);
selectedSprite.registerEntityModifier(moveModifier);}
I was using this function to move sprite and was working perfectly.
But when I tried to call this function from a handler, sprite is not moved.
There is no any error displayed in LogCat.
Below is my handler:
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_STATE_CHANGE:
switch (msg.arg1) {
case MESSAGE_WRITE:
// other functions
break;
case MESSAGE_READ:
//function is called here.
placeSprite(400f,200f);
break;
case MESSAGE_TOAST:
//other functions
break;
}
}
};
I dont know why same code works if called from other thread but doesnt work if called from above handler.
I also found that main cause is registerEntityModifier was not working. I also want to know in what cases registerEntityModifier doesnt work.
Any help will be greatly appreciated. Thanks in advance.
You should call this method from Update thread not everywhere else.
mEngine.runOnUpdateThread((new Runnable() {
#Override
public void run() {
placeSprite(400f,200f);
}
});

AndEngine move two objects simultaneously

I am creating a game using Andengine and in this I want an object flying in the sky to drop bombs below. Currently I am using a timehandler to create both the flying object and the bombs. But its not working properly. The problems I am facing are:
1) Sometimes instead of a single bomb 2 or 3 bombs are dropped.
2) And the bomb objects are also not getting recycled. The code for recycling the object is getting called, but it doesn't seem to work.
I have noticed one thing i.e. suppose, initially I have one flying object that drops a bomb. When the bomb leaves the screen, the recycling code for bomb object gets called once. And after sometime as the flying object leaves the screen it also gets recycled. Now when another flying object is created and it drops the bomb, the code for recycling the bomb is getting called twice. Then for third flying object, the code for recycling the single bomb is getting called thrice and so on.
The code to add flying object is as follows
private void createDragonHandler() {
TimerHandler spriteTimerHandler;
float mEffectSpawnDelay = 10f;
spriteTimerHandler = new TimerHandler(mEffectSpawnDelay, true,
new ITimerCallback() {
#Override
public void onTimePassed(TimerHandler pTimerHandler) {
addDragon();
}
});
getEngine().registerUpdateHandler(spriteTimerHandler);
}
public void addDragon() {
Dragon dragon = (Dragon) dragonSpritePool.obtainPoolItem();
if (dragon.getParent() != mainScene)
mainScene.attachChild(dragon);
}
public synchronized Dragon obtainPoolItem() {
dragon = super.obtainPoolItem();
Random rand = new Random();
final int x = (int) (CAMERA_WIDTH + resourceManager.dragonTextureRegion
.getWidth());
int minY = (int) resourceManager.dragonTextureRegion.getHeight();
int maxY = (int) (CAMERA_HEIGHT / 2 - resourceManager.dragonTextureRegion
.getHeight());
int rangeY = maxY - minY;
final int y = rand.nextInt(rangeY) + minY;
dragon.reset();
dragon.setVisible(true);
dragon.setIgnoreUpdate(false);
dragon.animate(150);
dragon.setPosition(x, y);
MoveXModifier mod = new MoveXModifier(15, dragon.getX(),
-dragon.getWidth());
float mEffectSpawnDelay = 5f;
TimerHandler spriteTimerHandler = new TimerHandler(mEffectSpawnDelay,
true, new ITimerCallback() {
#Override
public void onTimePassed(TimerHandler pTimerHandler) {
DragonFire dragonFire = BirdShoot.dragonFireSpritePool
.obtainPoolItem(dragon.getX(), dragon.getY());
BirdShoot.mainScene.attachChild(dragonFire);
}
});
dragon.registerEntityModifier(mod.deepCopy());
dragon.setNoHit(0);
PhysicsHandler mPhysicsHandler;
mPhysicsHandler = new PhysicsHandler(dragon);
dragon.setPhysicsHandler(mPhysicsHandler);
dragon.registerUpdateHandler(dragon.getmPhysicsHandler());
BirdShoot.engine.registerUpdateHandler(spriteTimerHandler);
return dragon;
}
`
Where are you writing the code for recycling the sprite objects? According to your problem, I see something fishy there. It might be possible that the code is not getting executed. The code to recycle the sprites must be something like this:-
public void onHandleRecycleItem(Sprite sprite){
super.onHandleRecycleItem(sprite);
// Your code to recycle the object
}
Also it should be called using the following line :
yourPool.recyclePoolItem(spriteObject);
Without seeing your code, it will be hard to help with this. But, this has the smell of things not being done on the updateThread.
Any time you do something that affects AndEngine, be sure you call it via
runOnUpdateThread(new Runnable() {
#Override
public void run() {
/* Do your AndEngine changes in here*/
}
});`

Android (AndEngine): Sprite with body attached going up and down

I was trying to make the enemies in my game go up and down; since I'm using a physic body with a Sprite on it I can't use entity modifiers, so I decided give the body a little push using the .setLinearVelocity(float x, float y) method every time its sprite reach a certain point in the screen.
With just one body works great, but I need to have other enemeis (same sprite, different body) spawning every 5 seconds and doing the same thing, but I don't know how to track them... I mean, I don't know how to control if each body reaches the Y location independently from one another...
For example, right now the code is like this:
private void add_Box_Face()
{
float random_x = (float) (28 + (int)(Math.random() * ((this.CAMERA_WIDTH - 28*2) + 1)));
final Body rectangle_face_body;
final Sprite rectangle_face = new Sprite(random_x, this.y, this.mRectangleFaceTextureRegion, this.getVertexBufferObjectManager());
rectangle_face_body = PhysicsFactory.createBoxBody(this.m_PhysicsWorld, rectangle_face, BodyType.DynamicBody, this.BOX_FIXTURE_DEF);
rectangle_face_body.setUserData("target");
//I give the body a initial push
rectangle_face_body.setLinearVelocity(0, -5);
//I register an update handler to the sprite to control if it reaches a certain Y value
rectangle_face.registerUpdateHandler(new IUpdateHandler()
{
#Override
public void onUpdate(float pSecondsElapsed)
{
if (rectangle_face.getY() >= y-50)
{
//Here I just use a flag so that later on below I can do the push
MyApp.this.setLinearVelocity = true;
}
}
#Override
public void reset()
{
// TODO Auto-generated method stub
}
});
//Here I register the physic connector and if the flag permits it, I push the body up
this.m_PhysicsWorld.registerPhysicsConnector(new PhysicsConnector(rectangle_face, rectangle_face_body, true, false)
{
#Override
public void onUpdate(float pSecondsElapsed)
{
super.onUpdate(pSecondsElapsed);
if(MyApp.this.setLinearVelocity)
{
rectangle_face_body.setLinearVelocity(0, -3);
MyApp.this.setLinearVelocity = false;
}
}
});
this.mscene.attachChild(rectangle_face);
}
With the code like this the first body do what is planned, it moves up and down but as soon as another body pops up, it falls down and the other body goes up because the boolean setLinearVelocity is always set to true, so there is a costant push upwards; when a third body comes in, the second body falls down as well and this last one takes its place going up
With this code I didn't expect much else... but I don't know what else I can try... how can I control this?
Thanks in advance :)
EDIT: Added working code in an anwser below
I suggest you separate the code for the enemy from the code for the update handler. Create a class Enemy that will contain the Sprite and Body, hold your Enemies in an array and override the onUpdate method of your PhysicsWorld so that it goes through the array of Enemies and does what you want to all of them.
Here's a code snippet showing a very simple way of doing this:
mEngine.registerUpdateHandler(new IUpdateHandler() {
#Override
public void reset() {}
#Override
public void onUpdate(float pSecondsElapsed) {
for (Enemy e : enemies) {
e.checkPositionAndBounce();
}
}
});
Please note that this may not a very good idea as this code will probably run on a thread different to the one of the physics engine, which could cause all sorts of problems. A better way would be overriding the onUpdate method of PhysicsWorld:
#Override
public void onUpdate(final float pSecondsElapsed) {
super.onUpdate();
for (Enemy e : enemies) {
e.checkPositionAndBounce();
}
}
If you are unsure of what the first snippet means, look up "anonymous inner class".
Ok, here's the final working code (I didn't create a method to check the position or a class for the enemies just because right now I'm just messing around with the mechanics; I'll create a new project when I'm ready to really start):
this.m_PhysicsWorld = new PhysicsWorld(new Vector2(0, SensorManager.GRAVITY_EARTH), false)
{
#Override
public void onUpdate(float pSecondsElapsed)
{
super.onUpdate(pSecondsElapsed);
for(int i = 0; i <= MyApp.this.mSpriteCounter; i++)
{
if (rectangle_face[i].getY() >= y-50)
{
final PhysicsConnector spritePhysicsConnector = m_PhysicsWorld.getPhysicsConnectorManager().findPhysicsConnectorByShape(rectangle_face[i]);
spritePhysicsConnector.getBody().setLinearVelocity(0, -3);
}
}
};
In this code rectangle_face[] is an array of Sprites; each sprite is created like this:
private void add_Box_Face()
{
float random_x = (float) (28 + (int)(Math.random() * ((this.CAMERA_WIDTH - 28*2) + 1)));
final Body rectangle_face_body;
rectangle_face[this.mSpriteCounter] = new Sprite(random_x, y, this.mRectangleFaceTextureRegion, this.getVertexBufferObjectManager());
rectangle_face_body = PhysicsFactory.createBoxBody(this.m_PhysicsWorld, rectangle_face[this.mSpriteCounter], BodyType.DynamicBody, this.BOX_FIXTURE_DEF);
rectangle_face_body.setUserData("target");
rectangle_face_body.setLinearVelocity(0, -5);
this.m_PhysicsWorld.registerPhysicsConnector(new PhysicsConnector(rectangle_face[this.mSpriteCounter], rectangle_face_body, true, false));
this.mscene.attachChild(rectangle_face[this.mSpriteCounter]);
}
That's it, thanks again for the help :)

AndEngine - How to create a button?

I was on a roll last night, when I came across the issue of the ButtonSprite. I could have sworn I've done this before - it seems so simple - but using the code that AndEngineExamples provides doesn't really make sense and comes up with errors (for instance - why does a vague "run()" method create the response to every single touch event?).
So I did something that seemed to make sense.
private void loadScenes()
{
mainScene = new Scene();
menu = new Sprite(0, 0, menuTextureRegion, mEngine.getVertexBufferObjectManager()){
#Override
protected void preDraw(GLState pGLState, Camera pCamera)
{
super.preDraw(pGLState, pCamera);
pGLState.enableDither();
}
};
newgamebutton = new ButtonSprite(25, 200, newgameTextureRegion, mEngine.getVertexBufferObjectManager());
multiplayerbutton = new ButtonSprite(25, 310, multiplayerTextureRegion, mEngine.getVertexBufferObjectManager());
menu.setScale(1.65f);
menu.setPosition((CAMERA_WIDTH - menu.getWidth()) * 0.5f, (CAMERA_HEIGHT - menu.getHeight()) * 0.5f);
mainScene.attachChild(menu);
mainScene.attachChild(newgamebutton);
mainScene.attachChild(multiplayerbutton);
mainScene.registerTouchArea(multiplayerbutton);
mainScene.setTouchAreaBindingOnActionDownEnabled(true);
multiplayerbutton.onAreaTouched(mButtonTouched, multiplayerbutton.getWidth(), multiplayerbutton.getHeight());
if(mButtonTouched.isActionDown()) {
mainScene.detachChild(menu);
mainScene.detachChild(multiplayerbutton);
}
}
It seems to make good sense. When the "multiplayer button" is pressed, it gives you the mButtonTouched, and when that's pressed down... it detaches the menu and multiplayer button. This is obviously just me testing things, and not part of any actual project because I'm just learning, but I get a null pointer exception and the app right closes before displaying the "Menu Scene", which obviously normally works. Also, on various sites it says that I should put "public boolean" before multiplayerbutton, but Eclipse won't have that.
I'm sure you guys have already figured this out, but I'm suuuuuuper new to AndEngine. Thanks for any help, guys!
After looking at the code I believe you wanted to do something like this:
ButtonSprite button = new ButtonSprite(25, 310, multiplayerTextureRegion, mEngine.getVertexBufferObjectManager()) {
#Override
public boolean onAreaTouched(TouchEvent pTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
if(pTouchEvent.isActionDown()) {
mainScene.detachChild(menu);
mainScene.detachChild(multiplayerbutton);
}
return super.onAreaTouched(pTouchEvent, pTouchAreaLocalX, pTouchAreaLocalY);
}
};
Your code doesn't work because the last if statement doesn't really make sense - it is checking whether the button is pressed when the method loadScenes() executes. I suggest you read up on anonymous inner classes, it took me a long time to figure out that using them is a valid and useful approach in AndEngine.
Here is a primitive example of a different way of managing buttons:
mScene.setOnAreaTouchListener(new IOnAreaTouchListener() {
#Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, ITouchArea pTouchArea, float pTouchAreaLocalX, float pTouchAreaLocalY) {
if (pTouchArea.equals(button) {
doSomething();
return true;
}
return false;
}
});
Please note that this only works when touching Shapes, if you want to detect touch events outside of Shapes, you need to use IOnSceneTouchListener instead.

Categories

Resources