I've been doing trial and error for hours now and I have not yet come up with a solution for something that seems simple....
I am using the
public void onConfigurationChanged(Configuration newConfig)
method to detect if a user has changed their screen orientation.
Eventually, it gets sent to this method where the entitys are attached to the scene:
public void BuildScene(final Scene scene){
// Destroys current scene.
scene.detachChildren();
this.SpriteDayPortrait = new Sprite(-200, 0, 2000, 500, this.mParallaxLayerDayPortrait);
this.SpriteDayLandscape = new Sprite(0, 0, 750, 500, this.mParallaxLayerDayLandscape);
if (prefs.getString("frontImage", "1").equals("3"))
{
//Day
if (orientationValue.equals("PORTRAIT"))
{
Log.d("Orientation", "Portrait");
scene.detachChild(SpriteDayLandscape);
scene.attachChild(SpriteDayPortrait);
}
else if (orientationValue.equals("LANDSCAPE"))
{
Log.d("Orientation", "Landscape");
scene.detachChild(SpriteDayPortrait);
scene.attachChild(SpriteDayLandscape);
}
}
}
This method is called to when the wallpaper is first created, and also when a user changes screen orientation.
I have tested this on my phone and it successfully displays the log messages when I switch orientations, which means that it is doing it what I want it to do.
The Problem--
The sprite child does not detach when this method is called to. If I am in Portrait mode, and switch to Landscape, the portrait sprite remains and I would like it to disappear, and vice versa.
I would be extremely happy if anyone could answer this I've been having a headache over this for probably 20 hours.
It looks like the problem might be logic: You reassign the SpriteDayPortrait and SpriteDayLanscape before calling the branch about detaching them or attaching them.
So each time the detach script is called it is referring to a new instance of the sprite, rather than the old instance that you want to detach.
try moving the assignment of the sprites into another function that is only called when the scene is created:
// Move this
this.SpriteDayPortrait = new Sprite(-200, 0, 2000, 500, this.mParallaxLayerDayPortrait);
this.SpriteDayLandscape = new Sprite(0, 0, 750, 500, this.mParallaxLayerDayLandscape);
Keep in mind that since changing orientation in AndEngine doesn't exist (You are not allowed to change engine orientation), you should't make your game be using orientation changes (That would be weird for the user).
Anyways, onConfigurationChanged is called from the UI thread, and you should not manipulate objects of AndEngine but in the UpdateThread. It might cause some problems (However, if it would, your game would crash) so change it.
I think it happens because you didn't clear your ParallaxBackground before setting the new background (Perhaps the old background hides the new one?)
Keep a reference to your last ParallaxEntity then remove it from the background before adding a new one.
Related
I'm playing with stage2d.ui...
Just creating an empty stage with only a button, and it happens this in android (screenshot directly from a Nexus5):
Also, it looks ok in desktop, but if you resize the screen, you can see the image of the button flickering at its previous position like this (image after making the window a bit more width):
I'm not sure if I'm doing something wrong or it's just a graphic issue...
For the button widget, I'm using the test data like this:
stage = new Stage(new ScreenViewport());
Skin skin = new Skin(Gdx.files.internal("uiskin.json"));
TextButton button = new TextButton("Button 1", skin);
button.setSize(100, 50);
button.setPosition(10, 10);
stage.addActor(button);
And then in the main render method, stage.act(delta) and stage.draw() are called, of course.
For the resize part... here's the code
public void resize(int width, int height) {
stage.getViewport().update(width, height);
}
I have other stages without ui widgets working fine, but this is my first time with ui and I'm not sure about what's happening here...
Moved from comment above.
My guess is you are not clearing the screen at the start of your render method. Try adding Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); if it isn't there already.
Summary
I'm trying to reliably remove a view from my layout, from my GL Rendering thread.
Details
I've got a splash screen which is added to my main layout, so my views are in this order:
GLSurfaceView
Splashscreen (which is a simple Android View)
All my objects and anything that can be loaded in the background is loaded from an AsyncTask, then, my GL Textures are loaded on the GL Thread (as is required), I'm then removing the Splashscreen from my layout to reveal my app's main menu screen.
90% of the time it works perfectly, (load time on my device is approx 3.5 seconds), however, occasionally, it appears to either never remove the view, or can take up to 8 seconds.
This is my current implementation
In my Activity class, I have the following method setup
public void dismissSplashScreen(){
removeSplash = new Runnable(){
public void run(){
//Is splashscreen currently visible?
if (splash.isShown()){
//Remove the splashscreen
layout.removeView(splash);
//Recycle splash screen as it's no longer required
recycle();
}
}
};
//Remove it
handler.post(removeSplash);
}
And then in my GLRenderer's onSurfaceCreated method, I have this:
public void onSurfaceChanged(GL10 gl, int deviceWidth, int deviceHeight) {
GLES20.glViewport(offsetX, offsetY, width, height);
Matrix.orthoM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
loadGLTextures();
//Everything is done! Dismiss the splash to reveal main menu
activity.dismissSplashScreen();
}
I also attempted to use runOnUIThread, but the results were the same, if not worse. Is my implementation correct here? What things can I check and is there a simpler way to remove this view from my layout once everything is done? (I can't dismiss it from the activity class directly as I have to wait for the GL textures to load on the GL thread).
Sorted.
The reason was because I am calling activity.dismissSplashScreen from onSurfaceChanged and onSurfaceChanged is being called multiple times (a common problem I gather and one which I've not been able to get to the bottom of yet).
So what I think was happening, was it was posting my runnable to the queue and then posting another before the first one had either started or completed, sometimes a third time.
So everything was getting a bit confused.
I simply added a boolean flag to guarantee that the runnable was posted only once like so:
if (!splashIsGone){
activity.dismissSplash();
splashIsGone = true;
}
I am new to andengine and want to know that how I can switch between two BaseGameActivities. And also when switching from first activity to second, there is no black screen transition in between switching. Is there any possible way to do it.
Please help me out.
A BaseGameActivity can be used as any other Android Activity, too:
Intent intent = new Intent(this, MyOtherBaseGameActivity.class);
startActivity(intent);
So if you want to change from your program to another app (maybe by opening the browser…) you can do that as with any other Android App, too. However if both Activities are part of your own App, there is rarely a case where this is recommendable (It is like starting a second program). Although it is possible to exchange data between the activities as described in this post.
But maybe you are only looking for a way to switch between Views in AndEngine. If that's the case you can switch between Scenes without any transition necessary.
MyOtherScene secondScene = new MyOtherScene();
mEngine.setScene(secondScene);
That way you can switch between what is being displayed, without needing to load every image again.
EDIT:
Since you can't use AndEngine to switch between Activities, nor is a smooth switching between scenes possible. Here a quick example on how to switch between two screens (e.g. menus). In this example the screens are actually 2 different images (as big as the display … maybe some background images). Note: there is no such thing as 'screens' in AndEngine, it is simply a self made class that extends Entity.
Your Screen
public MyScreen extends Entity{
private float firstX;
public MyScreen(Sprite niceBackgroundImage1, Sprite niceBackgroundImage2){
this.attachChild(niceBackgroundImage1); // attach something to the screen, so you can see it (preferably an image that is as big as your camera)
this.attachChild(niceBackgroundImage2);
this.firstY=-1; // this is a variable to remember the first x coordinate touched
}
#Override
public boolean onAreaTouched(TouchEvent sceneTouchEvent, float touchAreaLocalX, float touchAreaLocalY) {
if(sceneTouchEvent.getAction()==TouchEvent.ACTION_DOWN){
this.firstY=touchAreaLocalX; // remember the x, on the first touch
}
if(sceneTouchEvent.getAction()==TouchEvent.ACTION_MOVE){
if(touchAreaLocalX>firstY+20){
// user swiped from left to right (at least 20 pixels)
niceBackgroundImage1.registerEntityModifier(new MoveModifier(3f, 0, niceBackgroundImage1.getWidth(), 0, 0, EaseBounceOut.getInstance()));
// the last line actualy moves the nice..image1 from left to right (in 3 seconds) and lets it bounce a little bit before it is completely out of the screen
return true;
}
}
return false;
}
...
}
Your Activity
private HUD hud; // create a HUD
...
#Override
protected void onCreateResources() {
this.hud = new HUD(); // init the HUD
this.myScreen = new MyScreen(image1, image2) // init the screen
this.hud.attachChild(myScreen); // attach the screen to the hud
mEngine.getCamera().setHud(hud); // attach your HUD to the camera
}
#Override
protected Scene onCreateScene() {
Scene myScene = new Scene();
myScene.registerTouchArea(myScreen); // you have to register the touch area of your Screen Class to the scene.
mEngine.setScene(myScene);
}
And this is how it works:
you create yourself a own screen class that extends Entity. An Entity can be everything visible in AndEngine (like a Sprite, Rectangle or even a whole scene). Put something in your screen class to make it look nice, preferably a big image that fills the whole display. That image will be responsible to register the touch afterwards. If the image is too small and the user misses the image, then no touch will be registered.
In this case I attach the instance of MyScreen to the cameras HUD. That way it will be at a fixed position on the display and it will have a fixed size (just in case you want to make the scene scrollable or zoomable).
Now when the app starts the HUD will be created and attached to the camera and with it your MyScreen class. Then the scene will be created and the screen's area will be registered as touch area to the scene. When a swipe movement on a horizontal axis gets noticed by the screen class, the first image will move outside the screen (in the same direction as the swipe).
But be careful, this is just an example. There is nothing defined on how the touch has to act when the first image was moved outside the screen or how big the screen actually is etc...
I know this is quite a long example, maybe it won't even work the first time and it is definitely not the only way on how switching between different screens can be done. But it shows you how to override the onAreaTouched() method and register the entity modifier to make the image move. Hopefully it will lead you in the right direction, to accomplish what you want to do.
I know this has been asked before and I went through all the answers and nope this ain't that, and yes I have the activity named in the manifest so it's not that.
Here's my problem:
I have a sprite moving across the screen and when in the window where you choose the livewallpaper, I have a preference that lets the user choose the height (so they can move the sprite up or down) the only problem is the sprite is constantly moving so when they use the seekbar to move the sprite up or down I get the old 'Window already focused, ignoring focus gain of" Now if I go out and come back in again of course this stop and restarts it and the new preference hight is already in their so it moves to the new height then but not in the live preview.
Here is the sprite code:
private void addShipOne() {
int heightPosition = (screenSized / 2) - (screenSized / /*this.bigShipHeight*/gettheFreakingHeight());
int widthPosition = 0;
Point startPoint = new Point(widthPosition, heightPosition);
this._shipone.add(new SpaceShipOne(this._context, this, startPoint, 125));
(sorry about the method name I was using to test a quick version I was a bit frustrated at that point) lol
It then goes into an OnDraw method then into the render to render it all.
public void render(){
Canvas canvas = null;
try{
canvas = this._surfaceHolder.lockCanvas(null);
synchronized (this._surfaceHolder) {
this.onDraw(canvas);
}
}finally{
if(canvas != null){
this._surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
I have another preference that allows the user to choose the frequency of the ships appearing it works fine but it goes from left to right and changes ships then so it updates the frequency then, but the height one doesn't work, I tested the log to make sure the height int goes through and it does so its not that, the only thing I can come up with is the maybe add this when the ship turns left or right, but it does not work while its moving by the looks of it.
this.bigShipHeight is where the new height value goes into ( I was just testing it another way with the gettheFreakingHeight() (I used an if else statement for that method that used the frquency preference instead which does work nicely.
Just to add the full code part.
In the onDraw(Canvas canvas)
I render the _shipone as such
for (Renderable renderable : this._shipone) {
renderable.render(canvas);
}
Any help would be appreciated.
Thanks in advance
Sam
Ok I should of looked into the my sprite class first, sorry about this I answered my own question once again and it was too obvious, that's what I get for looking at the code way to long, I should walk away then come back it always is clearer then.
Just in case others run into this issue I'll put the answer.
In my sprite class which SpaceShipOne runs from I just added this
this.getSprite().setYPos(this._blimp.gettheFreakingHeight());
This updates right away with no window already focused.
I don't know why I didn't see this last night because it is the only place it can be added and be updated right away, all I had to do was set the Y position to the preference instead.
It works like a charm.
Hope this helps someone else out
Sam
I have created a little screenmanager (to handle multiple scenes), where every class extends from a custom class called Screen, and does the following (for example) in its load method:
public Scene load() {
BitmapTextureAtlas mBitmapTextureAtlas = new BitmapTextureAtlas(512, 1024, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
SceneManager.loadTexture(mBitmapTextureAtlas);
scene.attachChild(bgSprite);
return scene;
}
The problem is that sometimes, if you move fast among screens, some sprites are not being rendered, sometimes they are (it depends on how fast I switch between scenes).
I guess the problem might be that I'm attaching the sprites to the scene when they still have been not fully loaded in memory. Can it be? Any idea how to solve this problem?
Yes it happens if you move across scenes, so you can set boolean flags for sprites. if true then perform operations. It is specially useful when perform collisionDetections.