Start animation with AndEngine Live Wallpaper extansion - android

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)
{
}

Related

TMX file is not shown properly using AndEngine

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,

After 5 minutes of running , my libgdx game crashes and turns red

public class PlayScreen implements Screen{
Stage stage;
LabelStyle style;
BitmapFont font;
TextureAtlas backbuttonatlas;
TextButtonStyle backbuttonstyle;
TextButton backbutton;
Skin backskin;
SpriteBatch batch;
Texture pibe;
Sprite sprite;
Vector2 position;
Game game;
Texture texture;
public PlayScreen(Game game){
this.game=game;
}
#Override
public void render(float delta) {
stage=new Stage();
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if(Gdx.input.isKeyPressed(Keys.W))
{
position.x+=5f;
}
if(Gdx.input.isKeyPressed(Keys.A))
{
position.y-=5f;
}
if(Gdx.input.isKeyPressed(Keys.S))
{
position.x-=5f;
}
if(Gdx.input.isKeyPressed(Keys.D))
{
position.y+=5f;
}
if(Gdx.input.isTouched()==true)
{
if(Gdx.input.getY()>Gdx.graphics.getHeight()/2)
{
position.x-=5;
}
if(Gdx.input.getY()<Gdx.graphics.getHeight()/2)
{
position.x+=5;
}
if(Gdx.input.getX()>Gdx.graphics.getWidth()/2)
{
position.y+=5;
}
if(Gdx.input.getX()<Gdx.graphics.getWidth()/2)
{
position.y-=5;
}
if(Gdx.input.isKeyPressed(Keys.BACK))
{
game.setScreen(new MainMenu(game));
}
}
font = new BitmapFont(Gdx.files.internal("font.fnt"), false);
style = new LabelStyle(font, Color.WHITE);
backskin = new Skin();
backbuttonatlas = new TextureAtlas("buttons/backbutton.pack");
backskin.addRegions(backbuttonatlas);
backbuttonstyle = new TextButtonStyle();
backbuttonstyle.up = backskin.getDrawable("backbutton");
backbuttonstyle.over = backskin.getDrawable("backbuttonpressed");
backbuttonstyle.down = backskin.getDrawable("backbuttonpressed");
backbuttonstyle.font = font;
backbutton = new TextButton("", backbuttonstyle);
backbutton.setWidth((float) (Gdx.graphics.getHeight()/8));
backbutton.setHeight((float) (Gdx.graphics.getHeight()/8));
backbutton.setPosition((Gdx.graphics.getWidth()/20), (float) (Gdx.graphics.getHeight()-(Gdx.graphics.getWidth()/8)));
backbutton.addListener(new InputListener(){
public boolean touchDown(InputEvent event, float x, float y, int pointer, int backbutton) {
game.setScreen(new MainMenu(game));
return true;
};});
batch=new SpriteBatch();
stage.addActor(backbutton);
Gdx.input.setInputProcessor(stage);
batch.begin();
batch.draw(texture, 0, 0, Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
batch.draw(pibe,(position.y/2-pibe.getWidth()/2),(position.x/2-pibe.getHeight()/2));
batch.end();
stage.act();
stage.draw();
}
#Override
public void resize(int width, int height) {
// TODO Auto-generated method stub
}
#Override
public void show() {
texture = new Texture("cielo.png");
pibe = new Texture("superman (100x52).jpg");
position = new Vector2(Gdx.graphics.getHeight(),Gdx.graphics.getWidth());
}
#Override
public void hide() {
// TODO Auto-generated method stub
}
#Override
public void pause() {
// TODO Auto-generated method stub
}
#Override
public void resume() {
// TODO Auto-generated method stub
}
#Override
public void dispose() {
// TODO Auto-generated method stub
}
}
My LibGDX Game, collapse after a few minutes and I don't know why. I have read a little about the problem, and it says that the solution is to "dispose" the bitmapfont, or something like that. I'm new in LibGDX and I don't understand so much. A full explanation is appreciated. Sorry for my poor English.
This is the Play Class. Please, need help. Thanks.
you have to put your "creating" stuff like batch = new SpriteBatch() inside
#Override
public void create() {
)
you create billions of SpriteBatches that causes a memory issue.
Render is called each time the device is ready to update the screen. You are creating new objects each frame. Some of them must be disposed of manually, which means calling the .dispose() method of that object.
call
font.dispose();
when you are finished with the font to prevent it eating up all the memory.
Ideally you'd want to create that font outside of the render loop.
You should create your objects in the constructor, so that they are not recreated every single frame. Unless of course that is intended behavior.
Try something like this
public class PlayScreen implements Screen{
Stage stage;
LabelStyle style;
BitmapFont font;
TextureAtlas backbuttonatlas;
TextButtonStyle backbuttonstyle;
TextButton backbutton;
Skin backskin;
SpriteBatch batch;
Texture pibe;
Sprite sprite;
Vector2 position;
Game game;
Texture texture;
public PlayScreen(Game game){
this.game=game;
font = new BitmapFont(Gdx.files.internal("font.fnt"), false);
style = new LabelStyle(font, Color.WHITE);
stage=new Stage();
backskin = new Skin();
backbuttonatlas = new TextureAtlas("buttons/backbutton.pack");
backskin.addRegions(backbuttonatlas);
backbuttonstyle = new TextButtonStyle();
backbuttonstyle.up = backskin.getDrawable("backbutton");
backbuttonstyle.over = backskin.getDrawable("backbuttonpressed");
backbuttonstyle.down = backskin.getDrawable("backbuttonpressed");
backbuttonstyle.font = font;
backbutton = new TextButton("", backbuttonstyle);
backbutton.setWidth((float) (Gdx.graphics.getHeight()/8));
backbutton.setHeight((float) (Gdx.graphics.getHeight()/8));
backbutton.setPosition((Gdx.graphics.getWidth()/20), (float) (Gdx.graphics.getHeight()-(Gdx.graphics.getWidth()/8)));
backbutton.addListener(new InputListener(){
public boolean touchDown(InputEvent event, float x, float y, int pointer, int backbutton) {
game.setScreen(new MainMenu(game));
return true;
};});
batch=new SpriteBatch();
stage.addActor(backbutton);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if(Gdx.input.isKeyPressed(Keys.W))
{
position.x+=5f;
}
if(Gdx.input.isKeyPressed(Keys.A))
{
position.y-=5f;
}
if(Gdx.input.isKeyPressed(Keys.S))
{
position.x-=5f;
}
if(Gdx.input.isKeyPressed(Keys.D))
{
position.y+=5f;
}
if(Gdx.input.isTouched()==true)
{
if(Gdx.input.getY()>Gdx.graphics.getHeight()/2)
{
position.x-=5;
}
if(Gdx.input.getY()<Gdx.graphics.getHeight()/2)
{
position.x+=5;
}
if(Gdx.input.getX()>Gdx.graphics.getWidth()/2)
{
position.y+=5;
}
if(Gdx.input.getX()<Gdx.graphics.getWidth()/2)
{
position.y-=5;
}
if(Gdx.input.isKeyPressed(Keys.BACK))
{
game.setScreen(new MainMenu(game));
}
}
Gdx.input.setInputProcessor(stage);
batch.begin();
batch.draw(texture, 0, 0, Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
batch.draw(pibe,(position.y/2-pibe.getWidth()/2),(position.x/2-pibe.getHeight()/2));
batch.end();
stage.act();
stage.draw();
}
#Override
public void resize(int width, int height) {
// TODO Auto-generated method stub
}
#Override
public void show() {
texture = new Texture("cielo.png");
pibe = new Texture("superman (100x52).jpg");
position = new Vector2(Gdx.graphics.getHeight(),Gdx.graphics.getWidth());
}
#Override
public void hide() {
// TODO Auto-generated method stub
}
#Override
public void pause() {
// TODO Auto-generated method stub
}

Run Method not called in live wallpaper engine

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

Refreshing canvas?

I try to display one from list of bitmaps during onDraw.
When i'm passing list to the canvas all are display and stay in their places.
When I pass one random bitmaps it's redrawing canvas all the time.
All works when i'm using public void drawEnemy(Canvas canvas) but not exactly like I want when using public void drawEn(Canvas canvas).
I want to display one random bitmap, then after a few seconds, delete it and display other bitmap. I think the problem is how I implemented onDrow() method. It's redrawing canvas all the time.
Activity:
public class NewGameActivity extends Activity{
NewGame newgame;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
// Landscape mode
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
// no title
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
// content Newgame.java
newgame = new NewGame(this);
setContentView(newgame);
}
Thread:
public class MainThread extends Thread{
private SurfaceHolder surfaceHolder;
private NewGame screen;
public MainThread(SurfaceHolder surfaceHolder, NewGame ekran) {
super();
this.surfaceHolder = surfaceHolder;
this.screen= screen;
}
private boolean running;
public void setRunning(boolean running) {
this.running = running;
}
#Override
public void run() {
Canvas canvas;
while (running) {
canvas = null;
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
this.screen.onDraw(canvas);
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
SurfaceView:
public class NewGame extends SurfaceView implements SurfaceHolder.Callback{
private MainThread thread;
private EnemyManager manager;
public NewGame(Context context) {
super(context);
getHolder().addCallback(this);
thread = new MainThread(getHolder(), this);
manager = new EnemyManager();
// TODO Auto-generated constructor stub
//adding enemy
Enemy e1 = new Enemy(BitmapFactory.decodeResource(getResources(), R.drawable.card), 1);
Enemy e2 = new Enemy(BitmapFactory.decodeResource(getResources(), R.drawable.horse), 2);
EnemyLocation l1 = new EnemyLocation(60, 180);
EnemyLocation l2 = new EnemyLocation(60, 50);
manager.AddEnemy(e1, l1);
manager.AddEnemy(e2, l2);
setFocusable(true);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.saloon), 0, 0, null);
manager.drawEn(canvas);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
thread.setRunning(true);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
thread.setRunning(false);
thread.stop();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
manager.handleActionDown((int)event.getX(), (int)event.getY());
}
return true;
}
}
EnemyManager:
public class EnemyManager {
private ArrayList<Enemy> enemyList;
private ArrayList<Enemy> suspects;
private Enemy cow;
private String message;
private int suspectID;
private Random rnd;
public String getMessage() {
return message;
}
public EnemyManager(){
enemyList = new ArrayList<Enemy>();
suspects = new ArrayList<Enemy>();
}
public void AddEnemy(Enemy enemy, EnemyLocation loc){
// set x,y enemy localization
enemy.setX(loc.getX());
enemy.setY(loc.getY());
enemyList.add(enemy);
}
public void clearEnemy() {
enemyList.clear();
}
// message if enemy touched
public void handleActionDown(int x, int y) {
for (Enemy enemy: enemyList) {
if (enemy.wasTouched(x, y)) {
message = enemy.getId();
return;
}
}
}
public void PrepareEnemy(){
suspectID = enemyList.get(rnd.nextInt(enemyList.size()+1)).getId();
suspects = new ArrayList<Enemy>();
suspects.add(getSuspectByID(suspectID));
}
private Enemy SingleEnemy(){
Double i = 1 + Math.random() * ((enemyList.size()-1)+1);
cow = getSuspectByID(i.intValue());
return cow;
}
private Enemy getSuspectByID(int suspectID) {
for (Enemy s: enemyList) {
if (s.getId() == suspectID) {
return s;
}
}
return null;
}
public void drawEn(Canvas canvas){
try {
Enemy k = SingleEnemy();
canvas.drawBitmap(cow.picture, cow.x, cow.y, null);
} catch (Exception e) {
// TODO: handle exception
}
}
// draw enemy
public void drawEnemy(Canvas canvas) {
try {
for (Enemy enemy: enemyList) {
canvas.drawBitmap(enemy.picture, enemy.x, enemy.y, null);
}
} catch (Exception e) {
// TODO: handle exception
}
}
}
das
As for as understand you are trying to do something like this (if it's not, please correct me):
This is rendering the canvas with all components:
Draw background
Draw enemy
To "refresh" the canvas you simply do something like this:
Draw background
Update
To pause the rendering you could do something like this:
int lastUpdateTime;
int delayTime = 2000; 2 seconds
if(System.currenttimeMillis() > lastUpdateTime + delayTime) {
// Finished waiting
}
You should only define lastUpdateTime when you want to wait and not in every iteration.
NB: Don't call Thread.sleep() in a rendering thread!

Passing context to Handler

Is it possible to pass arguments to an Android Handler?? I have two pieces of code.
new Thread(){
public void run(){
for(;;){
uiCallback.sendEmptyMessage(0);
Thread.sleep(2000); //sleep for 2 seconds
}
}
}.start();
private Handler uiCallback = new Handler(){
public void handleMessage(Message msg){
//add a new blossom to the blossom ArrayList!!
blossomArrayList.add(new Blossom(context, R.drawable.blossom));
}
};
I of course get an error because the Handler method cannot see my context. This is probably because of this piece of code
public BoardView(Context context){
super(context);
Context is not visible elsewhere, and I'm wondering if I can pass it as an argument to my Handler.
EDIT: I am posting the two main pieces of code to answer a question about why my Blossom object needs context. I myself am not 100% sure >.> Maybe you could have a look and see what's going on.
public class Blossom{
private Bitmap blossom;
private float blossomX = 0;
private float blossomY = 0;
private Random generator = new Random();
public Blossom(Context context, int drawable)
{
blossom = BitmapFactory.decodeResource(context.getResources(), drawable);
blossomX = generator.nextInt(300);
}
public Bitmap getBitmap()
{
return blossom;
}
public float getBlossomX()
{
return blossomX;
}
public float getBlossomY()
{
return blossomY;
}
public void Fall(Canvas canvas, float boxY)
{
//draws the flower falling
canvas.drawBitmap(blossom, blossomX,
blossomY = blossomY+3 , null);
//collision detection, currently not working after
//implementing random start location
//if(blossomY + 29 == boxY)
//{
//canvas.drawBitmap(blossom,0,0,null);
//}
}
}
public class BoardView extends SurfaceView implements SurfaceHolder.Callback{
Context mContext;
Bitmap box =
(BitmapFactory.decodeResource
(getResources(), R.drawable.box));
private BoardThread thread;
private float box_x = 140;
private float box_y = 378;
private float boxWidth = box.getWidth();
private float boxHeight = box.getHeight();
private ArrayList<Blossom> blossomArrayList = new ArrayList<Blossom>();;
boolean mode = false;
RectF boxRect = new RectF(box_x,box_y, box_x + boxWidth, box_y + boxHeight);
public BoardView(Context context){
super(context);
//surfaceHolder provides canvas that we draw on
getHolder().addCallback(this);
// controls drawings
thread = new BoardThread(getHolder(),this);
//pass variables to instance of Blossom
//for(int i = 0; i <= 3; i++)
//{
//blossomArrayList.add(new Blossom(context, R.drawable.blossom));
//}
new Thread(){
public void run(){
for(;;){
uiCallback.sendEmptyMessage(0);
Thread.sleep(2000); //sleep for 2 seconds
}
}
}.start();
//intercepts touch events
setFocusable(true);
}
#Override
public void onDraw(Canvas canvas){
canvas.drawColor(Color.WHITE);
//draw box and set start location
canvas.drawBitmap(box, box_x - (boxWidth/2),
box_y - (boxHeight/2), null);
for(int i = 0; i<= 3; i++)
{
blossomArrayList.get(i).Fall(canvas, box_y);
}
}
#Override
public boolean onTouchEvent(MotionEvent event){
if(event.getAction() == MotionEvent.ACTION_DOWN){
if(boxRect.contains(event.getX(),event.getY())){
mode = true;
}
}
if(event.getAction() == MotionEvent.ACTION_MOVE) {
if(boxRect.contains(event.getX(),event.getY())){
mode = true;
}
if(mode == true){
box_x = (int)event.getX();
boxRect.set(box_x,box_y, box_x + boxWidth, box_y + boxHeight);
}
}
if(event.getAction() == MotionEvent.ACTION_UP){
mode = false;
}
invalidate();
return true;
}
#Override
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height ){
}
#Override
public void surfaceCreated(SurfaceHolder holder){
thread.startRunning(true);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder){
thread.startRunning(false);
thread.stop();
}
private Handler uiCallback = new Handler(){
public void handleMessage(Message msg){
//add a new blossom to the blossom ArrayList!!
blossomArrayList.add(new Blossom(context, R.drawable.blossom));
}
};
}
Create a class that extends Handler, and store a weak reference to the context. This will help prevent some memory issues.
public class SomeHandler extends Handler {
// A weak reference to the enclosing context
private WeakReference<Context> mContext;
public SomeHandler (Context context) {
mContext = new WeakReference<Context>(context);
}
public void handleMessage(Message msg) {
// Get an actual reference to the DownloadActivity
// from the WeakReference.
Context context=mContext.get();
...
}
}
What if you create a subclass which extends Handler? That way you could pass any parameters you want.
But just out of curiosity, why does the Blossom object require the context object? It's usually best to separate your logic from GUI dependencies.

Categories

Resources