App craches when changing orientation

Started by Shot, July 25, 2013, 09:48:48 AM

Previous topic - Next topic

Shot

Hello! :)

I'm new to jpct-AE and I've separated main class and renderer class. When I change orientation from vertical to horizontal app craches. Here's how it looks now:

Main class

package core;

import java.lang.reflect.Field;

import renderer.SimpleRenderer;

import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.MotionEvent;

import com.threed.jpct.Logger;
/**
* A simple demo. This shows more how to use jPCT-AE than it shows how to write
* a proper application for Android. It includes basic activity management to
* handle pause and resume...
*
* @author EgonOlsen
*
*/
public class BoxGame extends Activity
{

// Used to handle pause and resume...
private static BoxGame master = null;

private GLSurfaceView mGLView;
private SimpleRenderer renderer = null;

private float touchTurn = 0;
private float touchTurnUp = 0;

private float xpos = -1;
private float ypos = -1;

protected void onCreate(Bundle savedInstanceState)
{

Logger.log("onCreate");

if (getMaster() != null)
{
copy(getMaster());
}

super.onCreate(savedInstanceState);
mGLView = new GLSurfaceView(getApplication());
mGLView.setEGLContextClientVersion(2);

renderer = new SimpleRenderer(this);
mGLView.setRenderer(renderer);
setContentView(mGLView);
}

@Override
protected void onPause()
{
super.onPause();
mGLView.onPause();
}

@Override
protected void onResume()
{
super.onResume();
mGLView.onResume();
}

@Override
protected void onStop()
{
super.onStop();
}

private void copy(Object src)
{
//dziwny sposób na pamiętanie głównego obiektu przy pause/resume
// na razie zostawmy, ale chyba dobrze by było to zmienić
try
{
Logger.log("Copying data from master Activity!");
Field[] fs = src.getClass().getDeclaredFields();
for (Field f : fs)
{
f.setAccessible(true);
f.set(this, f.get(src));
}
} catch (Exception e)
{
throw new RuntimeException(e);
}
}

public boolean onTouchEvent(MotionEvent me)
{

if (me.getAction() == MotionEvent.ACTION_DOWN)
{
xpos = me.getX();
ypos = me.getY();
return true;
}

if (me.getAction() == MotionEvent.ACTION_UP)
{
xpos = -1;
ypos = -1;
setTouchTurn(0);
setTouchTurnUp(0);
return true;
}

if (me.getAction() == MotionEvent.ACTION_MOVE)
{
float xd = me.getX() - xpos;
float yd = me.getY() - ypos;

xpos = me.getX();
ypos = me.getY();

setTouchTurn(xd / -100f);
setTouchTurnUp(yd / -100f);
return true;
}

try
{
Thread.sleep(15);
} catch (Exception e)
{
// No need for this...
}

return super.onTouchEvent(me);
}

protected boolean isFullscreenOpaque()
{
return true;
}



//===================================
//===================================
//stąd
public float getTouchTurn()
{
return touchTurn;
}

public void setTouchTurn(float touchTurn)
{
this.touchTurn = touchTurn;
}

public float getTouchTurnUp()
{
return touchTurnUp;
}

public void setTouchTurnUp(float touchTurnUp)
{
this.touchTurnUp = touchTurnUp;
}
//dotąd powinno to być w input
//===================================
//===================================

///nie wiem czy to jest potrzebne
public static BoxGame getMaster()
{
return master;
}

public static void setMaster(BoxGame master)
{
BoxGame.master = master;
}
}


Renderer class:

package renderer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLSurfaceView;

import com.mktd.boxstory.R;
import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Light;
import com.threed.jpct.Logger;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.RGBColor;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;
import com.threed.jpct.util.BitmapHelper;
import com.threed.jpct.util.MemoryHelper;

import core.BoxGame;

public class SimpleRenderer implements GLSurfaceView.Renderer
{

/**
*
*/
private BoxGame as;
private FrameBuffer fb = null;
private RGBColor back = new RGBColor(50, 50, 100);
private World world = null;
private Camera cam = null;

Object3D cube = null;
private int fps = 0;
Light sun = null;

private float switcher = 1.0f;
private long time = System.currentTimeMillis();
private long time2 = System.currentTimeMillis();;

public SimpleRenderer(BoxGame boxGame)
{
as = boxGame;
}

public void onSurfaceChanged(GL10 gl, int w, int h)
{
if (fb != null)
{
fb.dispose();
}
fb = new FrameBuffer(w, h);

if (BoxGame.getMaster() == null)
{

world =new World();
world.setAmbientLight(20, 20, 20);

sun = new Light(world);
sun.setIntensity(250, 250, 250);

// Create a texture out of the icon...:-)
Texture texture = new Texture(BitmapHelper.rescale(
BitmapHelper.convert(as.getResources().getDrawable(
R.drawable.ic_launcher)), 64, 64));
TextureManager.getInstance().addTexture("texture", texture);

cube = Primitives.getCube(10);
//te prymitywy nie mają współrzednych do tekstur, dlatego można je wymusic
//jak wczytujemy objekty to bez tej lini, bo to rozwali wsp tekstur
cube.calcTextureWrapSpherical();
cube.setTexture("texture");
cube.rotateY((float)Math.toRadians(45.0f));
cube.strip();
cube.build();

world.addObject(cube);

cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 50);
cam.moveCamera(Camera.CAMERA_MOVEUP, 20);
cam.lookAt(cube.getTransformedCenter());

SimpleVector sv = new SimpleVector();
sv.set(cube.getTransformedCenter());
sv.y -= 100;
sv.z -= 100;
sun.setPosition(sv);

//przyspieszenie garbage collectora (chyba już nie potrzebne)
MemoryHelper.compact();

if (BoxGame.getMaster() == null)
{
Logger.log("Saving master Activity!");
BoxGame.setMaster(as);
}
}
}

public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
}

public void onDrawFrame(GL10 gl)
{
if(System.currentTimeMillis() - time2 >= 3000)
{
switcher *= -1;
time2 = System.currentTimeMillis();
}

cube.rotateZ((float)-Math.toRadians(2.0f) * switcher);
cube.translate(0.5f * switcher, 0.0f, 0.0f);
cam.moveCamera(new SimpleVector(switcher, 0, 0), 0.5f);

fb.clear(back);
world.renderScene(fb);
world.draw(fb);
fb.display();

//tutaj można ograniczać fps'y by oszczędzać baterie
if (System.currentTimeMillis() - time >= 1000)
{
Logger.log(fps + "fps");
fps=0;
time = System.currentTimeMillis();
}
fps++;
}

}


I can't figure out what's wrong with it... Thanks for help in advance :)

EgonOlsen

QuoteI can't figure out what's wrong with it
Neither do i...without a stack trace of the exception that happens.

Shot

These are the messages that prints after changing phone's orientation:


07-26 13:24:09.938: W/dalvikvm(10078): threadid=11: thread exiting with uncaught exception (group=0x40ac4210)
07-26 13:24:09.938: E/AndroidRuntime(10078): FATAL EXCEPTION: GLThread 715
07-26 13:24:09.938: E/AndroidRuntime(10078): java.lang.NullPointerException
07-26 13:24:09.938: E/AndroidRuntime(10078):    at renderer.SimpleRenderer.onDrawFrame(SimpleRenderer.java:118)
07-26 13:24:09.938: E/AndroidRuntime(10078):    at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1487)
07-26 13:24:09.938: E/AndroidRuntime(10078):    at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1241)

EgonOlsen

That's your code's fault. You are mixing the idea that the example uses to save your Activities data with additional attributes in your renderer implementation. It doesn't work this way. After the first initialisation, you never instantiate a new cube, because master isn't null anymore. But because cube (among other things) is part of your renderer and not (like in the example) part of the Activity, it remains null and isn't copied from your master like it is in the example.