I have written a position locator application for indoor positioning. I've used TMX files to render my floor maps and load them with AndEngine. The problem is that the program does not show the TMX file properly.
Here is the original file:
and here is what my application shows:
How can I fix this? Here is code:
public class TiledViewer extends SimpleBaseGameActivity implements
IOnSceneTouchListener, IScrollDetectorListener,
IPinchZoomDetectorListener {
private static final int CAMERA_WIDTH = 480;
private static final int CAMERA_HEIGHT = 320;
private SmoothCamera camera;
private TMXTiledMap mTMXTiledMap;
private SurfaceScrollDetector mScrollDetector;
private PinchZoomDetector mPinchZoomDetector;
private float mPinchZoomStartedCameraZoomFactor;
#Override
public EngineOptions onCreateEngineOptions() {
this.camera = new SmoothCamera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT, 400,
400, 10f);
final CroppedResolutionPolicy canvasSurface = new CroppedResolutionPolicy(
CAMERA_WIDTH, CAMERA_HEIGHT);
EngineOptions engineOptions = new EngineOptions(true,
ScreenOrientation.PORTRAIT_FIXED, canvasSurface, this.camera);
if (MultiTouch.isSupported(this)) {
if (MultiTouch.isSupportedDistinct(this)) {
Toast.makeText(
this,
"MultiTouch detected --> Both controls will work properly!",
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(
this,
"MultiTouch detected, but your device has problems distinguishing between fingers.\n\nControls are placed at different vertical locations.",
Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(
this,
"Sorry your device does NOT support MultiTouch!\n\n(Falling back to SingleTouch.)\n\nControls are placed at different vertical locations.",
Toast.LENGTH_LONG).show();
}
return engineOptions;
}
#Override
public void onCreateResources() {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
}
#Override
public Scene onCreateScene() {
this.mEngine.registerUpdateHandler(new FPSLogger());
final Scene scene = new Scene();
scene.setOnAreaTouchTraversalFrontToBack();
this.mScrollDetector = new SurfaceScrollDetector(this);
this.mPinchZoomDetector = new PinchZoomDetector(this);
scene.setOnSceneTouchListener(this);
scene.setTouchAreaBindingOnActionDownEnabled(true);
try {
final TMXLoader tmxLoader = new TMXLoader(this.getAssets(),
this.mEngine.getTextureManager(), TextureOptions.DEFAULT,
this.getVertexBufferObjectManager(),
new ITMXTilePropertiesListener() {
#Override
public void onTMXTileWithPropertiesCreated(
final TMXTiledMap pTMXTiledMap,
final TMXLayer pTMXLayer,
final TMXTile pTMXTile,
final TMXProperties<TMXTileProperty> pTMXTileProperties) {
}
});
this.mTMXTiledMap = tmxLoader.loadFromAsset("tmx/m03.tmx");
} catch (final TMXLoadException e) {
Debug.e(e);
}
final TMXLayer tmxLayer = this.mTMXTiledMap.getTMXLayers().get(0);
scene.attachChild(tmxLayer);
this.camera.setBounds(0, 0, tmxLayer.getHeight(), tmxLayer.getWidth());
this.camera.setBoundsEnabled(true);
return scene;
}
#Override
public void onScrollStarted(final ScrollDetector pScollDetector,
final int pPointerID, final float pDistanceX, final float pDistanceY) {
final float zoomFactor = this.camera.getZoomFactor();
this.camera.offsetCenter(-pDistanceX / zoomFactor, -pDistanceY
/ zoomFactor);
}
#Override
public void onScroll(final ScrollDetector pScollDetector,
final int pPointerID, final float pDistanceX, final float pDistanceY) {
final float zoomFactor = this.camera.getZoomFactor();
this.camera.offsetCenter(-pDistanceX / zoomFactor, -pDistanceY
/ zoomFactor);
}
#Override
public void onScrollFinished(final ScrollDetector pScollDetector,
final int pPointerID, final float pDistanceX, final float pDistanceY) {
final float zoomFactor = this.camera.getZoomFactor();
this.camera.offsetCenter(-pDistanceX / zoomFactor, -pDistanceY
/ zoomFactor);
}
#Override
public void onPinchZoomStarted(final PinchZoomDetector pPinchZoomDetector,
final TouchEvent pTouchEvent) {
this.mPinchZoomStartedCameraZoomFactor = this.camera.getZoomFactor();
}
#Override
public void onPinchZoom(final PinchZoomDetector pPinchZoomDetector,
final TouchEvent pTouchEvent, final float pZoomFactor) {
this.camera.setZoomFactor(this.mPinchZoomStartedCameraZoomFactor
* pZoomFactor);
}
#Override
public void onPinchZoomFinished(final PinchZoomDetector pPinchZoomDetector,
final TouchEvent pTouchEvent, final float pZoomFactor) {
this.camera.setZoomFactor(this.mPinchZoomStartedCameraZoomFactor
* pZoomFactor);
}
#Override
public boolean onSceneTouchEvent(final Scene pScene,
final TouchEvent pSceneTouchEvent) {
this.mPinchZoomDetector.onTouchEvent(pSceneTouchEvent);
if (this.mPinchZoomDetector.isZooming()) {
this.mScrollDetector.setEnabled(false);
} else {
if (pSceneTouchEvent.isActionDown()) {
this.mScrollDetector.setEnabled(true);
}
this.mScrollDetector.onTouchEvent(pSceneTouchEvent);
}
return true;
}
}
I had the same problem for realize an indoor program.
I found a way to make better the display by editing directly the .tmx file.
In the tileset you should add those attributes spacing and margin.
For example:
tileset spacing="3" margin="2"
If you put the good value in the diferent field, you should have a better display.
My problem was resolved just by adding a margin=10 in this tileset.
I hope that help you,
Related
I am trying to draw bullets on the screen when the player presses, but
after a few bullets I get the following error: FATAL EXCEPTION: Thread-2
Here is the classes of the bullet and of the gameView
public class Bullet {
private int x;
private int y;
private int speed;
private Bitmap bitmap;
public Bullet(Context context,int PositionX,int PositionY) {
Log.v("i am in bullet"," come on!!!");
speed = 10;
x = PositionX;
y = PositionY;
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.flash);
}
public void update() {
//Log.v("i am in update bullet"," come on!!!");
//animating the star horizontally right side
//by increasing x coordinate with player speed
x += 20;
}
public Bitmap getBitmap(){return bitmap;}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
returns
public class GameView extends SurfaceView implements Runnable {
private long fps;
private long timeThisFrame;
volatile boolean playing;
private Thread gameThread = null;
private Player player;
//a screenX holder
int screenX;
int i=0;
//context to be used in onTouchEvent to cause the activity transition from GameAvtivity to MainActivity.
Context context;
//the score holder
int score;
//the high Scores Holder
int highScore[] = new int[4];
//Shared Prefernces to store the High Scores
SharedPreferences sharedPreferences;
//to count the number of Misses
int countMisses;
//indicator that the enemy has just entered the game screen
boolean flag ;
//an indicator if the game is Over
private boolean isGameOver ;
private Paint paint;
private Canvas canvas;
private SurfaceHolder surfaceHolder;
private Enemy enemies;
//created a reference of the class Friend
private Friend friend;
//private Bullet bullet;
private ArrayList<Star> stars = new
ArrayList<Star>();
private ArrayList<Bullet> bullet = new
ArrayList<Bullet>();
//defining a boom object to display blast
private Boom boom;
//the mediaplayer objects to configure the background music
static MediaPlayer gameOnsound;
final MediaPlayer killedEnemysound;
final MediaPlayer gameOversound;
public GameView(Context context, int screenX, int screenY) {
super(context);
player = new Player(context, screenX, screenY);
surfaceHolder = getHolder();
paint = new Paint();
//initializing context
this.context = context;
int starNums = 20;
for (int i = 0; i < starNums; i++) {
Star s = new Star(context,screenX, screenY);
stars.add(s);
}
enemies = new Enemy(context,screenX,screenY);
//initializing boom object
boom = new Boom(context);
//initializing the Friend class object
friend = new Friend(context, screenX, screenY);
//setting the score to 0 initially
score = 0;
//setting the countMisses to 0 initially
countMisses = 0;
this.screenX = screenX;
isGameOver = false;
//initializing shared Preferences
sharedPreferences = context.getSharedPreferences("SHAR_PREF_NAME",Context.MODE_PRIVATE);
//initializing the array high scores with the previous values
highScore[0] = sharedPreferences.getInt("score1",0);
highScore[1] = sharedPreferences.getInt("score2",0);
highScore[2] = sharedPreferences.getInt("score3",0);
highScore[3] = sharedPreferences.getInt("score4",0);
//initializing the media players for the game sounds
gameOnsound = MediaPlayer.create(context,R.raw.gameon);
killedEnemysound = MediaPlayer.create(context,R.raw.killedenemy);
gameOversound = MediaPlayer.create(context,R.raw.gameover);
//starting the music to be played across the game
gameOnsound.start();
}
#Override
public void run() {
while (playing) {
long startFrameTime = System.currentTimeMillis();
synchronized (surfaceHolder) {
update();
draw();
control();
}
timeThisFrame = System.currentTimeMillis() - startFrameTime;
if (timeThisFrame >= 1) {
fps = 1000 / timeThisFrame;
}
}
}
private void update() {
//incrementing score as time passes
score++;
player.update();
//setting boom outside the screen
boom.setX(-250);
boom.setY(-250);
for (Star s : stars) {
s.update(player.getSpeed());
}
for (Bullet b : bullet) {
b.update();
}
//setting the flag true when the enemy just enters the screen
if(enemies.getX()==screenX){
flag = true;
}
enemies.update(player.getSpeed(),getFps());
}
private void draw() {
if (surfaceHolder.getSurface().isValid()) {
canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.argb(500,135,206,250));
paint.setColor(Color.WHITE);
paint.setTextSize(20);
for (Star s : stars) {
canvas.drawBitmap(
s.getBitmap(),
s.getX(),
s.getY(),
paint);
}
for (Bullet b : bullet) {
canvas.drawBitmap(
b.getBitmap(),
b.getX(),
b.getY(),
paint);
}
canvas.drawBitmap(
player.getBitmap(),
player.getX(),
player.getY(),
paint);
canvas.drawBitmap( enemies.getBitmap(), enemies.getframeToDraw(), enemies.getwhereToDraw(), null);
//drawing the score on the game screen
paint.setTextSize(30);
canvas.drawText("Score:"+score,100,50,paint);
//drawing boom image
canvas.drawBitmap(
boom.getBitmap(),
boom.getX(),
boom.getY(),
paint
);
//draw game Over when the game is over
if(isGameOver){
paint.setTextSize(150);
paint.setTextAlign(Paint.Align.CENTER);
int yPos=(int) ((canvas.getHeight() / 2) - ((paint.descent() + paint.ascent()) / 2));
canvas.drawText("Game Over",canvas.getWidth()/2,yPos,paint);
}
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
private void control() {
try {
gameThread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void pause() {
playing = false;
try {
gameThread.join();
} catch (InterruptedException e) {
gameThread.interrupt();
}
}
public void resume() {
playing = true;
gameThread = new Thread(this);
gameThread.start();
}
//stop the music on exit
public static void stopMusic(){
gameOnsound.stop();
}
#Override
public boolean onTouchEvent(MotionEvent motionEvent) {
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_UP:
player.stopBoosting();
break;
case MotionEvent.ACTION_DOWN:
player.setBoosting();
break;
}
//if touch the player
if (player.getDetectCollision().contains((int)motionEvent.getX(), (int)motionEvent.getY())) {
Bullet b = new Bullet(context,player.getX()+player.getDetectCollision().width()
,player.getY()-(player.getDetectCollision().height()/2));
bullet.add(b);
Log.d("test", "touch not inside myEditText");
}
//if the game's over, tappin on game Over screen sends you to MainActivity
if(isGameOver){
if(motionEvent.getAction()==MotionEvent.ACTION_DOWN){
context.startActivity(new Intent(context,MainActivity.class));
}
}
return true;
}
public long getFps(){
return fps;
}
}
I am using the WallpaperService class to set a live wallpaper on the device.
I want to implement security on the system screen (to prevent screenshot or recording) where the 'Set Wallpaper' button shows up by the android system.
So far, I have found one method of SurfaceView class - surfaceview.setSecure(boolean value)
But, I am not able to get the instance of the SurfaceView inside my class.
Please suggest some workaround to get the instance of this class.
My Code-
public class LiveWallpaperService extends WallpaperService {
private int mDeviceWidth, mDeviceHeight;
private int mAnimationWidth, mAnimationHeight;
#Override
public Engine onCreateEngine() {
Movie movie = null;
// Some Code here
return new GIFWallpaperEngine(movie);
}
private class GIFWallpaperEngine extends Engine {
private final int frameDuration = 24;
private SurfaceHolder holder;
private final Movie movie;
private boolean visible;
private final Handler handler;
private final Runnable drawGIF = new Runnable() {
public void run() {
draw();
}
};
public SurfaceView getSurfaceView(){
// How to find the SurfaceView object here?
}
GIFWallpaperEngine(Movie movie) {
this.movie = movie;
handler = new Handler();
}
#Override
public void onCreate(SurfaceHolder surfaceHolder) {
super.onCreate(surfaceHolder);
this.holder = surfaceHolder;
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
mDeviceWidth = width;
mDeviceHeight = height;
}
private void draw() {
if (movie != null) {
try {
if (visible) {
Canvas canvas = holder.lockCanvas();
canvas.save();
final float scaleFactorX = mDeviceWidth / (mAnimationWidth * 1.f); //608 is image width
final float scaleFactorY = mDeviceHeight / (mAnimationHeight * 1.f);
// Adjust size and position to fit animation on the screen
canvas.scale(scaleFactorX, scaleFactorY); // w,h Size of displaying Item
movie.draw(canvas, 0, 0); // position on x,y
canvas.restore();
holder.unlockCanvasAndPost(canvas);
movie.setTime((int) (System.currentTimeMillis() % movie.duration()));
handler.removeCallbacks(drawGIF);
handler.postDelayed(drawGIF, frameDuration);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
#Override
public void onVisibilityChanged(boolean visible) {
this.visible = visible;
if (visible) {
handler.post(drawGIF);
} else {
handler.removeCallbacks(drawGIF);
}
}
#Override
public void onDestroy() {
super.onDestroy();
handler.removeCallbacks(drawGIF);
}
}
}
The scene is made pretty well but the touch is not working. I registered all sprites and made onTouchAreaBindingOnActionDownEnabled(true) too. I have tried using Andengine's made in MenuScene but it is not working touching part only too. Here's my present code.
I had same problem as this gentleman here, since I had no way out I changed my code to:
import org.andengine.engine.camera.Camera;
import org.andengine.entity.sprite.Sprite;
import org.andengine.input.touch.TouchEvent;
import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.opengl.util.GLState;
import org.andengine.opengl.vbo.VertexBufferObjectManager;
import com.***.RM; //I changed the directory name to ***
import com.***.SceneManager; //I changed the directory name to ***
import com.***.SceneType; //I changed the directory name to ***
public class MainMenuScene extends BaseScene {
private final int MENU_PLAY = 0;
private final int MENU_OPTIONS = 1;
private final int MENU_CREDITS = 2;
private final int MENU_EXIT = 3;
final int w = 256, h = 64;
public class MenuSprite extends Sprite {
private int ID;
public MenuSprite(int pID, int pX, int pY, ITextureRegion tex, VertexBufferObjectManager vbom) {
super(pX, pY, w, h, tex, vbom);
this.ID = pID;
}
#Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
System.out.println("text");
if (pSceneTouchEvent.isActionDown() || pSceneTouchEvent.isActionMove()) {
onclick(this.ID);
this.setScale(1.5f);
return true;
} else {
this.setScale(1f);
}
return true;
}
}
#Override
public void createScene() {
attachChild(new Sprite(RM.MX, RM.MY, rM.menu_back, vbom) {
#Override
protected void preDraw(GLState pGLState, Camera pCamera) {
super.preDraw(pGLState, pCamera);
pGLState.enableDither();
}
});
final MenuSprite playMenuItem = new MenuSprite(MENU_PLAY, RM.MX, RM.CH * 4 / 6, rM.menu_play, vbom);
final MenuSprite optionsMenuItem = new MenuSprite(MENU_OPTIONS, RM.MX, RM.CH * 3 / 6, rM.menu_options, vbom);
final MenuSprite creditsMenuItem = new MenuSprite(MENU_CREDITS, RM.MX, RM.CH * 2 / 6, rM.menu_credit, vbom);
final MenuSprite exitMenuItem = new MenuSprite(MENU_EXIT, RM.MX, RM.CH * 1 / 6, rM.menu_exit, vbom);
attachChild(playMenuItem);
attachChild(optionsMenuItem);
attachChild(creditsMenuItem);
attachChild(exitMenuItem);
registerTouchArea(playMenuItem);
registerTouchArea(optionsMenuItem);
registerTouchArea(creditsMenuItem);
registerTouchArea(exitMenuItem);
setTouchAreaBindingOnActionDownEnabled(true);
}
#Override
public void disposeScene() {
}
#Override
public SceneType getSceneType() {
return SceneType.SCENE_MENU;
}
#Override
public void onBackKeyPressed() {
System.exit(0);
}
public void onclick(int ID) {
switch (ID) {
case MENU_PLAY:
SceneManager.getInstance().createLevelSelectionScene();
break;
case MENU_OPTIONS:
break;
case MENU_EXIT:
onBackKeyPressed();
break;
default:
break;
}
}
}
Here's a screenshot(I removed the title):
In Logcat I get the following on touching:
04-02 22:29:31.909: I/InputReader(159): dispatchTouch::touch event's action is 0
04-02 22:29:31.909: I/InputDispatcher(159): Delivering touch to current input target
but my application filtered messages have no touch log, not even the system.out that I added.
pOnCreateSceneCallback.onCreateSceneFinished(menuScene); is not present.
This does not give any warnings or errors but creates problems.
I am a newbie in android and started with livewallpaper development using Wallpaper Engine. My problem is the run() method inside Runnable is not called dont know why.... Am I missing something?
Here is my code:
public class Hearts extends WallpaperService {
public static boolean LANDSCAPE;
public static Paint backgroundPaint;
public static Point backgroundSize;
public static Point globalCanvasSize;
public static boolean landscapeMode = false;
public static int maxScreenSize;
Bitmap background;
private final Handler mHandler = new Handler();
public void onCreate() {
super.onCreate();
}
public WallpaperService.Engine onCreateEngine() {
return new HeartsEngine();
}
public void onDestroy() {
super.onDestroy();
}
class HeartsEngine extends Engine {
private final int amountOfFlakes = 40;
private final Paint backgroundPaint = new Paint();
private Canvas c;
public Flake[] flakeArray = new Flake[40];
final SurfaceHolder holder = getSurfaceHolder();
private final Runnable mDrawCube = new Runnable() {
#Override
public void run() {
Log.d("tag", "Inside Run Called");
drawFrame();
}
};
float mXOffset;
float mYOffset;
private float oldScreen;
Random random = new Random();
Resources res = Hearts.this.getResources();
HeartsEngine() {
super();
Log.d("tag", "Constructyor");
}
void drawFrame() {
Log.d("tag", "drawFrame");
this.oldScreen -= this.mXOffset;
Flake.scrollSpeed = 48.0F * this.oldScreen;
this.oldScreen = this.mXOffset;
this.c = null;
this.c = this.holder.lockCanvas();
try {
if (this.c != null)
this.c.drawBitmap(Hearts.this.background, 0.0F, 0.0F, null);
for (int i = 0;; i++) {
if (i >= 40) {
this.holder.unlockCanvasAndPost(this.c);
Hearts.this.mHandler.postDelayed(this.mDrawCube, 16L);
}
this.flakeArray[i].updateFlake(this.random, this.res,
this.c);
}
} catch (IllegalArgumentException localIllegalArgumentException) {
// break label94;
localIllegalArgumentException.printStackTrace();
return;
}
}
You call drawFrame() only inside the mDrawCube Runnable. So there is no a first time call for the drawFrame() method
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)
{
}