Skip to content

Loading the Sample Scene into Android (JPCTBlend AE)

andresjesse edited this page Jan 3, 2014 · 8 revisions

JPCTBlend running on android device

This page will guide you to load the sample (or any other) scene into an JPCT-AT Project. I assume that you have are familiar to Android codes and already used JPCT-AE, this way basic concepts will be skipped. Let's get started!

First Step

The first step is to create a JPCT-AE project. My example is based on JPCT-AE HelloWorld code, here's a "clean" version (without any objects in the scene):

package com.example.jpctblendaesample;

import java.lang.reflect.Field;

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

import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;

import com.andresjesse.jpctblend.JPCTBlendScene;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Logger;
import com.threed.jpct.World;
import com.threed.jpct.util.MemoryHelper;

/**
 * JPCTBlend AE sample. Based on EgonOlsen's JPCT-AE Hello World (more information at http://www.jpct.net/jpct-ae/).
 * @author andres
 */
public class MainActivity extends Activity {

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

	private GLSurfaceView mGLView;
	private MyRenderer renderer = null;
	private FrameBuffer fb = null;
	private World world = null;

	private int fps = 0;

	protected void onCreate(Bundle savedInstanceState) {

		Logger.log("onCreate");

		this.requestWindowFeature(Window.FEATURE_NO_TITLE);
		this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);

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

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

		mGLView.setEGLConfigChooser(new GLSurfaceView.EGLConfigChooser() {
			public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
				// Ensure that we get a 16bit framebuffer. Otherwise, we'll fall
				// back to Pixelflinger on some device (read: Samsung I7500)
				int[] attributes = new int[] { EGL10.EGL_DEPTH_SIZE, 16,
						EGL10.EGL_NONE };
				EGLConfig[] configs = new EGLConfig[1];
				int[] result = new int[1];
				egl.eglChooseConfig(display, attributes, configs, 1, result);
				return configs[0];
			}
		});

		renderer = new MyRenderer();
		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) {
		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);
		}
	}

	protected boolean isFullscreenOpaque() {
		return true;
	}

	class MyRenderer implements GLSurfaceView.Renderer {

		private long time = System.currentTimeMillis();

		public MyRenderer() {
		}

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

			if (master == null) {
				world = new World();

				MemoryHelper.compact();

				if (master == null) {
					Logger.log("Saving master Activity!");
					master = MainActivity.this;
				}
			}
		}

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

		public void onDrawFrame(GL10 gl) {
			fb.clear();
			world.renderScene(fb);
			world.draw(fb);
			fb.display();

			if (System.currentTimeMillis() - time >= 1000) {
				Logger.log(fps + "fps");
				fps = 0;
				time = System.currentTimeMillis();
			}
			fps++;
		}
	}
}

Make sure this code works (you must see a fullscreen black scene). Next step is to add the JPCTBlend-AE sources into the project. Download and copy the full packages com.andresjesse.jpctblendae and com.andresjesse.jpctblendae.actors to your project:

Project with JPCTBlend-AE sources

Now you are able to load JPCTBlend scenes to your world, create a field in the MainActivity class:

private JPCTBlendScene scn;

Locate the "onSurfaceChanged" method and add a command to load the scene:

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

			if (master == null) {

				world = new World();

				//========================== LOAD SCENE
				scn = new JPCTBlendScene("media/scene_test.xml", getAssets(),world);

				MemoryHelper.compact();

				if (master == null) {
					Logger.log("Saving master Activity!");
					master = MainActivity.this;
				}
			}
		}

Note that the JPCTBlendScene constructor receives an extra parameter: the Android Asset Manager. Why to use Assets instead of simple "raw" resources? Simple: google says that assets is the best folder to put game data, in addition we have a more powerful directory-based way to store and organize files (in my opinion better than add everything in "res/raw" folder). Now, let's add our content (JPCTBlend exported scene) to the "assets" folder:

Content in "assets" folder.

Everything OK? Almost.. our actors are not "rotating", that's because we forgot to update them, let's do it. Locate the "onDrawFrame" method and add a scn.updateActors() call before fb.clear():

		public void onDrawFrame(GL10 gl) {

			//=============UPDATE ACTORS
			scn.updateActors();

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

			if (System.currentTimeMillis() - time >= 1000) {
				Logger.log(fps + "fps");
				fps = 0;
				time = System.currentTimeMillis();
			}
			fps++;
		}

Some Considerations

  • When creating scenes for AE version take care for how much detail you add, remember the target hardware is limited;
  • Avoid to create too much lights, OpenGL-ES is limited;
  • When creating Actors for AE version take care to ALWAYS create a default constructor that receives the AssetManager (this is needed by ActorFactory):
	public YourActor(AssetManager assets) {
		//Do your initialization stuff hehe.
	}
  • In your custom Actors load objects and textures using AssetManager (take a look into the SampleActor class);
  • ALWAYS put your custom actors into the com.andresjesse.jpctblendae.actors package (or change the actors package in the ActorFactory class).

Tested Device

Processor: Quad Core NVidia Tegra 3 @ 1.5Ghz

RAM: 1Gb

Screen Resolution: 1280x720

OS: Android 4.1.2 (CyanogenMod)

Links

Go Back to HOME

Android Project (JPCTBlend-AE, Eclipse IDE)

You can’t perform that action at this time.