sorter) {
+ mSorter = sorter;
+ }
+}
diff --git a/src/com/replica/replicaisland/GLErrorLogger.java b/src/com/replica/replicaisland/GLErrorLogger.java
new file mode 100644
index 0000000..7d84d47
--- /dev/null
+++ b/src/com/replica/replicaisland/GLErrorLogger.java
@@ -0,0 +1,1184 @@
+package com.replica.replicaisland;
+
+import java.nio.Buffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
+
+import javax.microedition.khronos.opengles.GL;
+import javax.microedition.khronos.opengles.GL10;
+import javax.microedition.khronos.opengles.GL10Ext;
+import javax.microedition.khronos.opengles.GL11;
+import javax.microedition.khronos.opengles.GL11Ext;
+
+import android.opengl.GLU;
+
+public class GLErrorLogger implements GLSurfaceView.GLWrapper {
+
+ public GL wrap(GL gl) {
+ return new ErrorLoggingGL(gl);
+ }
+
+ static class ErrorLoggingGL implements GL, GL10, GL10Ext, GL11, GL11Ext {
+ private GL mGL;
+
+ public ErrorLoggingGL(GL gl) {
+ mGL = gl;
+ }
+
+ public void checkError() {
+
+ int error = ((GL10)mGL).glGetError();
+ if (error != GL10.GL_NO_ERROR) {
+ String method = Thread.currentThread().getStackTrace()[3].getMethodName();
+ DebugLog.d("GL ERROR", "Error: " + error + " (" + GLU.gluErrorString(error) + "): " + method);
+ }
+
+ assert error == GL10.GL_NO_ERROR;
+ }
+
+ public void glActiveTexture(int texture) {
+ ((GL10) mGL).glActiveTexture(texture);
+ checkError();
+ }
+
+ public void glAlphaFunc(int func, float ref) {
+ ((GL10)mGL).glAlphaFunc(func, ref);
+ checkError();
+ }
+
+ public void glAlphaFuncx(int func, int ref) {
+ ((GL10)mGL).glAlphaFuncx(func, ref);
+ checkError();
+ }
+
+ public void glBindTexture(int target, int texture) {
+ ((GL10)mGL).glBindTexture(target, texture);
+ checkError();
+ }
+
+ public void glBlendFunc(int sfactor, int dfactor) {
+ ((GL10)mGL).glBlendFunc(sfactor, dfactor);
+ checkError();
+ }
+
+ public void glClear(int mask) {
+ ((GL10)mGL).glClear(mask);
+ checkError();
+ }
+
+ public void glClearColor(float red, float green, float blue, float alpha) {
+ ((GL10)mGL).glClearColor(red, green, blue, alpha);
+ checkError();
+ }
+
+ public void glClearColorx(int red, int green, int blue, int alpha) {
+ ((GL10)mGL).glClearColorx(red, green, blue, alpha);
+ checkError();
+ }
+
+ public void glClearDepthf(float depth) {
+ ((GL10)mGL).glClearDepthf(depth);
+ checkError();
+ }
+
+ public void glClearDepthx(int depth) {
+ ((GL10)mGL).glClearDepthx(depth);
+ checkError();
+ }
+
+ public void glClearStencil(int s) {
+ ((GL10)mGL).glClearStencil(s);
+ checkError();
+ }
+
+ public void glClientActiveTexture(int texture) {
+ ((GL10)mGL).glClientActiveTexture(texture);
+ checkError();
+ }
+
+ public void glColor4f(float red, float green, float blue, float alpha) {
+ ((GL10)mGL).glColor4f(red, green, blue, alpha);
+ checkError();
+ }
+
+ public void glColor4x(int red, int green, int blue, int alpha) {
+ ((GL10)mGL).glColor4x(red, green, blue, alpha);
+ checkError();
+ }
+
+ public void glColorMask(boolean red, boolean green, boolean blue,
+ boolean alpha) {
+ ((GL10)mGL).glColorMask(red, green, blue, alpha);
+ checkError();
+ }
+
+ public void glColorPointer(int size, int type, int stride,
+ Buffer pointer) {
+ ((GL10)mGL).glColorPointer(size, type, stride, pointer);
+ checkError();
+ }
+
+ public void glCompressedTexImage2D(int target, int level,
+ int internalformat, int width, int height, int border,
+ int imageSize, Buffer data) {
+ ((GL10)mGL).glCompressedTexImage2D(target, level,
+ internalformat, width, height, border, imageSize, data);
+ checkError();
+ }
+
+ public void glCompressedTexSubImage2D(int target, int level,
+ int xoffset, int yoffset, int width, int height, int format,
+ int imageSize, Buffer data) {
+ ((GL10)mGL).glCompressedTexSubImage2D( target, level,
+ xoffset, yoffset, width, height, format,
+ imageSize, data);
+ checkError();
+ }
+
+ public void glCopyTexImage2D(int target, int level, int internalformat,
+ int x, int y, int width, int height, int border) {
+ ((GL10)mGL).glCopyTexImage2D( target, level, internalformat,
+ x, y, width, height, border);
+ checkError();
+
+ }
+
+ public void glCopyTexSubImage2D(int target, int level, int xoffset,
+ int yoffset, int x, int y, int width, int height) {
+ ((GL10)mGL).glCopyTexSubImage2D( target, level, xoffset,
+ yoffset, x, y, width, height);
+ checkError();
+ }
+
+ public void glCullFace(int mode) {
+ ((GL10)mGL).glCullFace(mode);
+ checkError();
+ }
+
+ public void glDeleteTextures(int n, IntBuffer textures) {
+ ((GL10)mGL).glDeleteTextures(n, textures);
+ checkError();
+ }
+
+ public void glDeleteTextures(int n, int[] textures, int offset) {
+ ((GL10)mGL).glDeleteTextures(n, textures, offset);
+ checkError();
+ }
+
+ public void glDepthFunc(int func) {
+ ((GL10)mGL).glDepthFunc(func);
+ checkError();
+ }
+
+ public void glDepthMask(boolean flag) {
+ ((GL10)mGL).glDepthMask(flag);
+ checkError();
+ }
+
+ public void glDepthRangef(float zNear, float zFar) {
+ ((GL10)mGL).glDepthRangef(zNear, zFar);
+ checkError();
+ }
+
+ public void glDepthRangex(int zNear, int zFar) {
+ ((GL10)mGL).glDepthRangex(zNear, zFar);
+ checkError();
+ }
+
+ public void glDisable(int cap) {
+ ((GL10)mGL).glDisable(cap);
+ checkError();
+ }
+
+ public void glDisableClientState(int array) {
+ ((GL10)mGL).glDisableClientState(array);
+ checkError();
+ }
+
+ public void glDrawArrays(int mode, int first, int count) {
+ ((GL10)mGL).glDrawArrays(mode, first, count);
+ checkError();
+ }
+
+ public void glDrawElements(int mode, int count, int type, Buffer indices) {
+ ((GL10)mGL).glDrawElements(mode, count, type, indices);
+ checkError();
+ }
+
+ public void glEnable(int cap) {
+ ((GL10)mGL).glEnable(cap);
+ checkError();
+ }
+
+ public void glEnableClientState(int array) {
+ ((GL10)mGL).glEnableClientState(array);
+ checkError();
+ }
+
+ public void glFinish() {
+ ((GL10)mGL).glFinish();
+ checkError();
+ }
+
+ public void glFlush() {
+ ((GL10)mGL).glFlush();
+ checkError();
+ }
+
+ public void glFogf(int pname, float param) {
+ ((GL10)mGL).glFogf(pname, param);
+ checkError();
+ }
+
+ public void glFogfv(int pname, FloatBuffer params) {
+ ((GL10)mGL).glFogfv(pname, params);
+ checkError();
+ }
+
+ public void glFogfv(int pname, float[] params, int offset) {
+ ((GL10)mGL).glFogfv(pname, params, offset);
+ checkError();
+ }
+
+ public void glFogx(int pname, int param) {
+ ((GL10)mGL).glFogx(pname, param);
+ checkError();
+ }
+
+ public void glFogxv(int pname, IntBuffer params) {
+ ((GL10)mGL).glFogxv(pname, params);
+ checkError();
+ }
+
+ public void glFogxv(int pname, int[] params, int offset) {
+ ((GL10)mGL).glFogxv(pname, params, offset);
+ checkError();
+ }
+
+ public void glFrontFace(int mode) {
+ ((GL10)mGL).glFrontFace(mode);
+ checkError();
+ }
+
+ public void glFrustumf(float left, float right, float bottom,
+ float top, float zNear, float zFar) {
+ ((GL10)mGL).glFrustumf( left, right, bottom,
+ top, zNear, zFar);
+ checkError();
+ }
+
+ public void glFrustumx(int left, int right, int bottom, int top,
+ int zNear, int zFar) {
+ ((GL10)mGL).glFrustumx( left, right, bottom, top,
+ zNear, zFar);
+ checkError();
+ }
+
+ public void glGenTextures(int n, IntBuffer textures) {
+ ((GL10)mGL).glGenTextures(n, textures);
+ checkError();
+ }
+
+ public void glGenTextures(int n, int[] textures, int offset) {
+ ((GL10)mGL).glGenTextures(n, textures, offset);
+ checkError();
+ }
+
+ public int glGetError() {
+ return ((GL10)mGL).glGetError();
+ }
+
+ public void glGetIntegerv(int pname, IntBuffer params) {
+ ((GL10)mGL).glGetIntegerv(pname, params);
+ checkError();
+ }
+
+ public void glGetIntegerv(int pname, int[] params, int offset) {
+ ((GL10)mGL).glGetIntegerv(pname, params, offset);
+ checkError();
+ }
+
+ public String glGetString(int name) {
+ String result = ((GL10)mGL).glGetString(name);
+ checkError();
+ return result;
+ }
+
+ public void glHint(int target, int mode) {
+ ((GL10)mGL).glHint(target, mode);
+ checkError();
+ }
+
+ public void glLightModelf(int pname, float param) {
+ ((GL10)mGL).glLightModelf(pname, param);
+ checkError();
+ }
+
+ public void glLightModelfv(int pname, FloatBuffer params) {
+ ((GL10)mGL).glLightModelfv(pname, params);
+ checkError();
+ }
+
+ public void glLightModelfv(int pname, float[] params, int offset) {
+ ((GL10)mGL).glLightModelfv(pname, params, offset);
+ checkError();
+ }
+
+ public void glLightModelx(int pname, int param) {
+ ((GL10)mGL).glLightModelx(pname, param);
+ checkError();
+ }
+
+ public void glLightModelxv(int pname, IntBuffer params) {
+ ((GL10)mGL).glLightModelxv(pname, params);
+ checkError();
+ }
+
+ public void glLightModelxv(int pname, int[] params, int offset) {
+ ((GL10)mGL).glLightModelxv(pname, params, offset);
+ checkError();
+ }
+
+ public void glLightf(int light, int pname, float param) {
+ ((GL10)mGL).glLightf(light, pname, param);
+ checkError();
+ }
+
+ public void glLightfv(int light, int pname, FloatBuffer params) {
+ ((GL10)mGL).glLightfv(light, pname, params);
+ checkError();
+ }
+
+ public void glLightfv(int light, int pname, float[] params, int offset) {
+ ((GL10)mGL).glLightfv(light, pname, params, offset);
+ checkError();
+ }
+
+ public void glLightx(int light, int pname, int param) {
+ ((GL10)mGL).glLightx(light, pname, param);
+ checkError();
+ }
+
+ public void glLightxv(int light, int pname, IntBuffer params) {
+ ((GL10)mGL).glLightxv(light, pname, params);
+ checkError();
+ }
+
+ public void glLightxv(int light, int pname, int[] params, int offset) {
+ ((GL10)mGL).glLightxv(light, pname, params, offset);
+ checkError();
+ }
+
+ public void glLineWidth(float width) {
+ ((GL10)mGL).glLineWidth(width);
+ checkError();
+ }
+
+ public void glLineWidthx(int width) {
+ ((GL10)mGL).glLineWidthx(width);
+ checkError();
+ }
+
+ public void glLoadIdentity() {
+ ((GL10)mGL).glLoadIdentity();
+ checkError();
+ }
+
+ public void glLoadMatrixf(FloatBuffer m) {
+ ((GL10)mGL).glLoadMatrixf(m);
+ checkError();
+ }
+
+ public void glLoadMatrixf(float[] m, int offset) {
+ ((GL10)mGL).glLoadMatrixf(m, offset);
+ checkError();
+ }
+
+ public void glLoadMatrixx(IntBuffer m) {
+ ((GL10)mGL).glLoadMatrixx(m);
+ checkError();
+ }
+
+ public void glLoadMatrixx(int[] m, int offset) {
+ ((GL10)mGL).glLoadMatrixx(m, offset);
+ checkError();
+ }
+
+ public void glLogicOp(int opcode) {
+ ((GL10)mGL).glLogicOp(opcode);
+ checkError();
+ }
+
+ public void glMaterialf(int face, int pname, float param) {
+ ((GL10)mGL).glMaterialf(face, pname, param);
+ checkError();
+ }
+
+ public void glMaterialfv(int face, int pname, FloatBuffer params) {
+ ((GL10)mGL).glMaterialfv(face, pname, params);
+ checkError();
+ }
+
+ public void glMaterialfv(int face, int pname, float[] params, int offset) {
+ ((GL10)mGL).glMaterialfv(face, pname, params, offset);
+ checkError();
+ }
+
+ public void glMaterialx(int face, int pname, int param) {
+ ((GL10)mGL).glMaterialx(face, pname, param);
+ checkError();
+ }
+
+ public void glMaterialxv(int face, int pname, IntBuffer params) {
+ ((GL10)mGL).glMaterialxv(face, pname, params);
+ checkError();
+ }
+
+ public void glMaterialxv(int face, int pname, int[] params, int offset) {
+ ((GL10)mGL).glMaterialxv(face, pname, params, offset);
+ checkError();
+ }
+
+ public void glMatrixMode(int mode) {
+ ((GL10)mGL).glMatrixMode(mode);
+ checkError();
+ }
+
+ public void glMultMatrixf(FloatBuffer m) {
+ ((GL10)mGL).glMultMatrixf(m);
+ checkError();
+ }
+
+ public void glMultMatrixf(float[] m, int offset) {
+ ((GL10)mGL).glMultMatrixf(m, offset);
+ checkError();
+ }
+
+ public void glMultMatrixx(IntBuffer m) {
+ ((GL10)mGL).glMultMatrixx(m);
+ checkError();
+ }
+
+ public void glMultMatrixx(int[] m, int offset) {
+ ((GL10)mGL).glMultMatrixx(m, offset);
+ checkError();
+ }
+
+ public void glMultiTexCoord4f(int target, float s, float t, float r,
+ float q) {
+ ((GL10)mGL).glMultiTexCoord4f( target, s, t, r, q);
+ checkError();
+ }
+
+ public void glMultiTexCoord4x(int target, int s, int t, int r, int q) {
+ ((GL10)mGL).glMultiTexCoord4x( target, s, t, r, q);
+ checkError();
+ }
+
+ public void glNormal3f(float nx, float ny, float nz) {
+ ((GL10)mGL).glNormal3f(nx, ny, nz);
+ checkError();
+ }
+
+ public void glNormal3x(int nx, int ny, int nz) {
+ ((GL10)mGL).glNormal3x(nx, ny, nz);
+ checkError();
+ }
+
+ public void glNormalPointer(int type, int stride, Buffer pointer) {
+ ((GL10)mGL).glNormalPointer(type, stride, pointer);
+ checkError();
+ }
+
+ public void glOrthof(float left, float right, float bottom, float top,
+ float zNear, float zFar) {
+ ((GL10)mGL).glOrthof( left, right, bottom, top,
+ zNear, zFar);
+ checkError();
+ }
+
+ public void glOrthox(int left, int right, int bottom, int top,
+ int zNear, int zFar) {
+ ((GL10)mGL).glOrthox( left, right, bottom, top,
+ zNear, zFar);
+ checkError();
+ }
+
+ public void glPixelStorei(int pname, int param) {
+ ((GL10)mGL).glPixelStorei(pname, param);
+ checkError();
+ }
+
+ public void glPointSize(float size) {
+ ((GL10)mGL).glPointSize(size);
+ checkError();
+ }
+
+ public void glPointSizex(int size) {
+ ((GL10)mGL).glPointSizex(size);
+ checkError();
+ }
+
+ public void glPolygonOffset(float factor, float units) {
+ ((GL10)mGL).glPolygonOffset(factor, units);
+ checkError();
+ }
+
+ public void glPolygonOffsetx(int factor, int units) {
+ ((GL10)mGL).glPolygonOffsetx(factor, units);
+ checkError();
+ }
+
+ public void glPopMatrix() {
+ ((GL10)mGL).glPopMatrix();
+ checkError();
+ }
+
+ public void glPushMatrix() {
+ ((GL10)mGL).glPushMatrix();
+ checkError();
+ }
+
+ public void glReadPixels(int x, int y, int width, int height,
+ int format, int type, Buffer pixels) {
+ ((GL10)mGL).glReadPixels( x, y, width, height,
+ format, type, pixels);
+ checkError();
+ }
+
+ public void glRotatef(float angle, float x, float y, float z) {
+ ((GL10)mGL).glRotatef(angle, x, y, z);
+ checkError();
+ }
+
+ public void glRotatex(int angle, int x, int y, int z) {
+ ((GL10)mGL).glRotatex(angle, x, y, z);
+ checkError();
+ }
+
+ public void glSampleCoverage(float value, boolean invert) {
+ ((GL10)mGL).glSampleCoverage(value, invert);
+ checkError();
+ }
+
+ public void glSampleCoveragex(int value, boolean invert) {
+ ((GL10)mGL).glSampleCoveragex(value, invert);
+ checkError();
+ }
+
+ public void glScalef(float x, float y, float z) {
+ ((GL10)mGL).glScalef(x, y, z);
+ checkError();
+ }
+
+ public void glScalex(int x, int y, int z) {
+ ((GL10)mGL).glScalex(x, y, z);
+ checkError();
+ }
+
+ public void glScissor(int x, int y, int width, int height) {
+ ((GL10)mGL).glScissor(x, y, width, height);
+ checkError();
+ }
+
+ public void glShadeModel(int mode) {
+ ((GL10)mGL).glShadeModel(mode);
+ checkError();
+ }
+
+ public void glStencilFunc(int func, int ref, int mask) {
+ ((GL10)mGL).glStencilFunc(func, ref, mask);
+ checkError();
+ }
+
+ public void glStencilMask(int mask) {
+ ((GL10)mGL).glStencilMask(mask);
+ checkError();
+ }
+
+ public void glStencilOp(int fail, int zfail, int zpass) {
+ ((GL10)mGL).glStencilOp(fail, zfail, zpass);
+ checkError();
+ }
+
+ public void glTexCoordPointer(int size, int type, int stride,
+ Buffer pointer) {
+ ((GL10)mGL).glTexCoordPointer( size, type, stride,
+ pointer);
+ checkError();
+ }
+
+ public void glTexEnvf(int target, int pname, float param) {
+ ((GL10)mGL).glTexEnvf(target, pname, param);
+ checkError();
+ }
+
+ public void glTexEnvfv(int target, int pname, FloatBuffer params) {
+ ((GL10)mGL).glTexEnvfv(target, pname, params);
+ checkError();
+ }
+
+ public void glTexEnvfv(int target, int pname, float[] params, int offset) {
+ ((GL10)mGL).glTexEnvfv(target, pname, params, offset);
+ checkError();
+ }
+
+ public void glTexEnvx(int target, int pname, int param) {
+ ((GL10)mGL).glTexEnvx(target, pname, param);
+ checkError();
+ }
+
+ public void glTexEnvxv(int target, int pname, IntBuffer params) {
+ ((GL10)mGL).glTexEnvxv(target, pname, params);
+ checkError();
+ }
+
+ public void glTexEnvxv(int target, int pname, int[] params, int offset) {
+ ((GL10)mGL).glTexEnvxv(target, pname, params, offset);
+ checkError();
+ }
+
+ public void glTexImage2D(int target, int level, int internalformat,
+ int width, int height, int border, int format, int type,
+ Buffer pixels) {
+ ((GL10)mGL).glTexImage2D( target, level, internalformat,
+ width, height, border, format, type,
+ pixels);
+ checkError();
+ }
+
+ public void glTexParameterf(int target, int pname, float param) {
+ ((GL10)mGL).glTexParameterf(target, pname, param);
+ checkError();
+ }
+
+ public void glTexParameterx(int target, int pname, int param) {
+ ((GL10)mGL).glTexParameterx(target, pname, param);
+ checkError();
+ }
+
+ public void glTexSubImage2D(int target, int level, int xoffset,
+ int yoffset, int width, int height, int format, int type,
+ Buffer pixels) {
+ ((GL10)mGL).glTexSubImage2D( target, level, xoffset,
+ yoffset, width, height, format, type,
+ pixels);
+ checkError();
+ }
+
+ public void glTranslatef(float x, float y, float z) {
+ ((GL10)mGL).glTranslatef(x, y, z);
+ checkError();
+ }
+
+ public void glTranslatex(int x, int y, int z) {
+ ((GL10)mGL).glTranslatex(x, y, z);
+ checkError();
+ }
+
+ public void glVertexPointer(int size, int type, int stride,
+ Buffer pointer) {
+ ((GL10)mGL).glVertexPointer( size, type, stride,
+ pointer);
+ checkError();
+ }
+
+ public void glViewport(int x, int y, int width, int height) {
+ ((GL10)mGL).glViewport(x, y, width, height);
+ checkError();
+ }
+
+ public void glBindBuffer(int arg0, int arg1) {
+ ((GL11)mGL).glBindBuffer(arg0, arg1);
+ checkError();
+ }
+
+ public void glBufferData(int arg0, int arg1, Buffer arg2, int arg3) {
+ ((GL11)mGL).glBufferData(arg0, arg1, arg2, arg3);
+ checkError();
+ }
+
+ public void glBufferSubData(int arg0, int arg1, int arg2, Buffer arg3) {
+ ((GL11)mGL).glBufferSubData(arg0, arg1, arg2, arg3);
+ checkError();
+ }
+
+ public void glClipPlanef(int arg0, FloatBuffer arg1) {
+ ((GL11)mGL).glClipPlanef(arg0, arg1);
+ checkError();
+ }
+
+ public void glClipPlanef(int arg0, float[] arg1, int arg2) {
+ ((GL11)mGL).glClipPlanef(arg0, arg1, arg2);
+ checkError();
+ }
+
+ public void glClipPlanex(int arg0, IntBuffer arg1) {
+ ((GL11)mGL).glClipPlanex(arg0, arg1);
+ checkError();
+ }
+
+ public void glClipPlanex(int arg0, int[] arg1, int arg2) {
+ ((GL11)mGL).glClipPlanex(arg0, arg1, arg2);
+ checkError();
+ }
+
+ public void glColor4ub(byte arg0, byte arg1, byte arg2, byte arg3) {
+ ((GL11)mGL).glColor4ub(arg0, arg1, arg2, arg3);
+ checkError();
+ }
+
+ public void glColorPointer(int arg0, int arg1, int arg2, int arg3) {
+ ((GL11)mGL).glColorPointer(arg0, arg1, arg2, arg3);
+ checkError();
+ }
+
+ public void glDeleteBuffers(int n, IntBuffer buffers) {
+ ((GL11)mGL).glDeleteBuffers(n, buffers);
+ checkError();
+ }
+
+ public void glDeleteBuffers(int n, int[] buffers, int offset) {
+ ((GL11)mGL).glDeleteBuffers(n, buffers, offset);
+ checkError();
+ }
+
+ public void glDrawElements(int mode, int count, int type, int offset) {
+ ((GL11)mGL).glDrawElements(mode, count, type, offset);
+ checkError();
+ }
+
+ public void glGenBuffers(int n, IntBuffer buffers) {
+ ((GL11)mGL).glGenBuffers(n, buffers);
+ checkError();
+ }
+
+ public void glGenBuffers(int n, int[] buffers, int offset) {
+ ((GL11)mGL).glGenBuffers(n, buffers, offset);
+ checkError();
+ }
+
+ public void glGetBooleanv(int pname, IntBuffer params) {
+ ((GL11)mGL).glGetBooleanv(pname, params);
+ checkError();
+ }
+
+ public void glGetBooleanv(int pname, boolean[] params, int offset) {
+ ((GL11)mGL).glGetBooleanv(pname, params, offset);
+ checkError();
+ }
+
+ public void glGetBufferParameteriv(int target, int pname,
+ IntBuffer params) {
+ ((GL11)mGL).glGetBufferParameteriv( target, pname,
+ params);
+ checkError();
+ }
+
+ public void glGetBufferParameteriv(int target, int pname, int[] params,
+ int offset) {
+ ((GL11)mGL).glGetBufferParameteriv( target, pname, params,
+ offset);
+ checkError();
+ }
+
+ public void glGetClipPlanef(int pname, FloatBuffer eqn) {
+ ((GL11)mGL).glGetClipPlanef(pname, eqn);
+ checkError();
+ }
+
+ public void glGetClipPlanef(int pname, float[] eqn, int offset) {
+ ((GL11)mGL).glGetClipPlanef(pname, eqn, offset);
+ checkError();
+ }
+
+ public void glGetClipPlanex(int pname, IntBuffer eqn) {
+ ((GL11)mGL).glGetClipPlanex(pname, eqn);
+ checkError();
+ }
+
+ public void glGetClipPlanex(int pname, int[] eqn, int offset) {
+ ((GL11)mGL).glGetClipPlanex(pname, eqn, offset);
+ checkError();
+ }
+
+ public void glGetFixedv(int pname, IntBuffer params) {
+ ((GL11)mGL).glGetFixedv(pname, params);
+ checkError();
+ }
+
+ public void glGetFixedv(int pname, int[] params, int offset) {
+ ((GL11)mGL).glGetFixedv(pname, params, offset);
+ checkError();
+ }
+
+ public void glGetFloatv(int pname, FloatBuffer params) {
+ ((GL11)mGL).glGetFloatv(pname, params);
+ checkError();
+ }
+
+ public void glGetFloatv(int pname, float[] params, int offset) {
+ ((GL11)mGL).glGetFloatv(pname, params, offset);
+ checkError();
+ }
+
+ public void glGetLightfv(int light, int pname, FloatBuffer params) {
+ ((GL11)mGL).glGetLightfv(light, pname, params);
+ checkError();
+ }
+
+ public void glGetLightfv(int light, int pname, float[] params,
+ int offset) {
+ ((GL11)mGL).glGetLightfv( light, pname, params,
+ offset);
+ checkError();
+ }
+
+ public void glGetLightxv(int light, int pname, IntBuffer params) {
+ ((GL11)mGL).glGetLightxv(light, pname, params);
+ checkError();
+ }
+
+ public void glGetLightxv(int light, int pname, int[] params, int offset) {
+ ((GL11)mGL).glGetLightxv(light, pname, params, offset);
+ checkError();
+ }
+
+ public void glGetMaterialfv(int face, int pname, FloatBuffer params) {
+ ((GL11)mGL).glGetMaterialfv(face, pname, params);
+ checkError();
+ }
+
+ public void glGetMaterialfv(int face, int pname, float[] params,
+ int offset) {
+ ((GL11)mGL).glGetMaterialfv( face, pname, params,
+ offset);
+ checkError();
+ }
+
+ public void glGetMaterialxv(int face, int pname, IntBuffer params) {
+ ((GL11)mGL).glGetMaterialxv(face, pname, params);
+ checkError();
+ }
+
+ public void glGetMaterialxv(int face, int pname, int[] params,
+ int offset) {
+ ((GL11)mGL).glGetMaterialxv( face, pname, params,
+ offset);
+ checkError();
+ }
+
+ public void glGetPointerv(int pname, Buffer[] params) {
+ ((GL11)mGL).glGetPointerv(pname, params);
+ checkError();
+ }
+
+ public void glGetTexEnviv(int env, int pname, IntBuffer params) {
+ ((GL11)mGL).glGetTexEnviv(env, pname, params);
+ checkError();
+ }
+
+ public void glGetTexEnviv(int env, int pname, int[] params, int offset) {
+ ((GL11)mGL).glGetTexEnviv(env, pname, params, offset);
+ checkError();
+ }
+
+ public void glGetTexEnvxv(int env, int pname, IntBuffer params) {
+ ((GL11)mGL).glGetTexEnvxv(env, pname, params);
+ checkError();
+ }
+
+ public void glGetTexEnvxv(int env, int pname, int[] params, int offset) {
+ ((GL11)mGL).glGetTexEnvxv(env, pname, params, offset);
+ checkError();
+ }
+
+ public void glGetTexParameterfv(int target, int pname,
+ FloatBuffer params) {
+ ((GL11)mGL).glGetTexParameterfv( target, pname,
+ params);
+ checkError();
+ }
+
+ public void glGetTexParameterfv(int target, int pname, float[] params,
+ int offset) {
+ ((GL11)mGL).glGetTexParameterfv( target, pname, params,
+ offset);
+ checkError();
+ }
+
+ public void glGetTexParameteriv(int target, int pname, IntBuffer params) {
+ ((GL11)mGL).glGetTexParameteriv(target, pname, params);
+ checkError();
+ }
+
+ public void glGetTexParameteriv(int target, int pname, int[] params,
+ int offset) {
+ ((GL11)mGL).glGetTexParameteriv( target, pname, params,
+ offset);
+ checkError();
+ }
+
+ public void glGetTexParameterxv(int target, int pname, IntBuffer params) {
+ ((GL11)mGL).glGetTexParameterxv(target, pname, params);
+ checkError();
+ }
+
+ public void glGetTexParameterxv(int target, int pname, int[] params,
+ int offset) {
+ ((GL11)mGL).glGetTexParameterxv( target, pname, params,
+ offset);
+ checkError();
+ }
+
+ public boolean glIsBuffer(int buffer) {
+ boolean result = ((GL11)mGL).glIsBuffer( buffer);
+ checkError();
+ return result;
+ }
+
+ public boolean glIsEnabled(int cap) {
+ boolean result = ((GL11)mGL).glIsEnabled(cap);
+ checkError();
+ return result;
+ }
+
+ public boolean glIsTexture(int texture) {
+ boolean result = ((GL11)mGL).glIsTexture( texture);
+ checkError();
+ return result;
+ }
+
+ public void glNormalPointer(int type, int stride, int offset) {
+ ((GL11)mGL).glNormalPointer(type, stride, offset);
+ checkError();
+ }
+
+ public void glPointParameterf(int pname, float param) {
+ ((GL11)mGL).glPointParameterf(pname, param);
+ checkError();
+ }
+
+ public void glPointParameterfv(int pname, FloatBuffer params) {
+ ((GL11)mGL).glPointParameterfv(pname, params);
+ checkError();
+ }
+
+ public void glPointParameterfv(int pname, float[] params, int offset) {
+ ((GL11)mGL).glPointParameterfv(pname, params, offset);
+ checkError();
+ }
+
+ public void glPointParameterx(int pname, int param) {
+ ((GL11)mGL).glPointParameterx(pname, param);
+ checkError();
+ }
+
+ public void glPointParameterxv(int pname, IntBuffer params) {
+ ((GL11)mGL).glPointParameterxv(pname, params);
+ checkError();
+ }
+
+ public void glPointParameterxv(int pname, int[] params, int offset) {
+ ((GL11)mGL).glPointParameterxv(pname, params, offset);
+ checkError();
+ }
+
+ public void glPointSizePointerOES(int type, int stride, Buffer pointer) {
+ ((GL11)mGL).glPointSizePointerOES(type, stride, pointer);
+ checkError();
+ }
+
+ public void glTexCoordPointer(int size, int type, int stride, int offset) {
+ ((GL11)mGL).glTexCoordPointer(size, type, stride, offset);
+ checkError();
+ }
+
+ public void glTexEnvi(int target, int pname, int param) {
+ ((GL11)mGL).glTexEnvi(target, pname, param);
+ checkError();
+ }
+
+ public void glTexEnviv(int target, int pname, IntBuffer params) {
+ ((GL11)mGL).glTexEnviv(target, pname, params);
+ checkError();
+ }
+
+ public void glTexEnviv(int target, int pname, int[] params, int offset) {
+ ((GL11)mGL).glTexEnviv(target, pname, params, offset);
+ checkError();
+ }
+
+ public void glTexParameterfv(int target, int pname, FloatBuffer params) {
+ ((GL11)mGL).glTexParameterfv(target, pname, params);
+ checkError();
+ }
+
+ public void glTexParameterfv(int target, int pname, float[] params,
+ int offset) {
+ ((GL11)mGL).glTexParameterfv( target, pname, params,
+ offset);
+ checkError();
+ }
+
+ public void glTexParameteri(int target, int pname, int param) {
+ ((GL11)mGL).glTexParameteri(target, pname, param);
+ checkError();
+ }
+
+ public void glTexParameteriv(int target, int pname, IntBuffer params) {
+ ((GL11)mGL).glTexParameteriv(target, pname, params);
+ checkError();
+ }
+
+ public void glTexParameteriv(int target, int pname, int[] params,
+ int offset) { }
+
+ public void glTexParameterxv(int target, int pname, IntBuffer params) {
+ ((GL11)mGL).glTexParameterxv(target, pname, params);
+ checkError();
+ }
+
+ public void glTexParameterxv(int target, int pname, int[] params,
+ int offset) {
+ ((GL11)mGL).glTexParameterxv( target, pname, params,
+ offset);
+ checkError();
+ }
+
+ public void glVertexPointer(int size, int type, int stride, int offset) {
+ ((GL11)mGL).glVertexPointer(size, type, stride, offset);
+ checkError();
+ }
+
+ public void glCurrentPaletteMatrixOES(int matrixpaletteindex) {
+ ((GL11Ext)mGL).glCurrentPaletteMatrixOES(matrixpaletteindex);
+ checkError();
+ }
+
+ public void glDrawTexfOES(float x, float y, float z, float width,
+ float height) {
+ ((GL11Ext)mGL).glDrawTexfOES( x, y, z, width,
+ height);
+ checkError();
+ }
+
+ public void glDrawTexfvOES(FloatBuffer coords) {
+ ((GL11Ext)mGL).glDrawTexfvOES(coords);
+ checkError();
+ }
+
+ public void glDrawTexfvOES(float[] coords, int offset) {
+ ((GL11Ext)mGL).glDrawTexfvOES(coords, offset);
+ checkError();
+ }
+
+ public void glDrawTexiOES(int x, int y, int z, int width, int height) {
+ ((GL11Ext)mGL).glDrawTexiOES( x, y, z, width, height);
+ checkError();
+ }
+
+ public void glDrawTexivOES(IntBuffer coords) {
+ ((GL11Ext)mGL).glDrawTexivOES(coords);
+ checkError();
+
+
+ }
+
+ public void glDrawTexivOES(int[] coords, int offset) {
+ ((GL11Ext)mGL).glDrawTexivOES(coords, offset);
+ checkError();
+
+
+ }
+
+ public void glDrawTexsOES(short x, short y, short z, short width,
+ short height) {
+ ((GL11Ext)mGL).glDrawTexsOES( x, y, z, width,
+ height);
+ checkError();
+ }
+
+ public void glDrawTexsvOES(ShortBuffer coords) {
+ ((GL11Ext)mGL).glDrawTexsvOES(coords);
+ checkError();
+
+
+ }
+
+ public void glDrawTexsvOES(short[] coords, int offset) {
+ ((GL11Ext)mGL).glDrawTexsvOES(coords, offset);
+ checkError();
+
+
+ }
+
+ public void glDrawTexxOES(int x, int y, int z, int width, int height) {
+ ((GL11Ext)mGL).glDrawTexxOES( x, y, z, width, height);
+ checkError();
+ }
+
+ public void glDrawTexxvOES(IntBuffer coords) {
+ ((GL11Ext)mGL).glDrawTexxvOES(coords);
+ checkError();
+
+
+ }
+
+ public void glDrawTexxvOES(int[] coords, int offset) {
+ ((GL11Ext)mGL).glDrawTexxvOES(coords, offset);
+ checkError();
+
+
+ }
+
+ public void glLoadPaletteFromModelViewMatrixOES() {
+ ((GL11Ext)mGL).glLoadPaletteFromModelViewMatrixOES();
+ checkError();
+
+
+ }
+
+ public void glMatrixIndexPointerOES(int size, int type, int stride,
+ Buffer pointer) {
+ ((GL11Ext)mGL).glMatrixIndexPointerOES( size, type, stride,
+ pointer);
+ checkError();
+
+ }
+
+ public void glMatrixIndexPointerOES(int size, int type, int stride,
+ int offset) {
+ ((GL11Ext)mGL).glMatrixIndexPointerOES( size, type, stride,
+ offset);
+ checkError();
+ }
+
+ public void glWeightPointerOES(int size, int type, int stride,
+ Buffer pointer) {
+ ((GL11Ext)mGL).glWeightPointerOES( size, type, stride,
+ pointer);
+ checkError();
+ }
+
+ public void glWeightPointerOES(int size, int type, int stride,
+ int offset) {
+ ((GL11Ext)mGL).glWeightPointerOES( size, type, stride,
+ offset);
+ checkError();
+ }
+
+ public int glQueryMatrixxOES(IntBuffer arg0, IntBuffer arg1) {
+ int result = ((GL10Ext)mGL).glQueryMatrixxOES( arg0, arg1);
+ checkError();
+ return result;
+ }
+
+ public int glQueryMatrixxOES(int[] arg0, int arg1, int[] arg2, int arg3) {
+ int result = ((GL10Ext)mGL).glQueryMatrixxOES(arg0, arg1,arg2, arg3);
+ checkError();
+ return result;
+ }
+ }
+}
diff --git a/src/com/replica/replicaisland/GLSurfaceView.java b/src/com/replica/replicaisland/GLSurfaceView.java
new file mode 100644
index 0000000..4430ae2
--- /dev/null
+++ b/src/com/replica/replicaisland/GLSurfaceView.java
@@ -0,0 +1,1631 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.replica.replicaisland;
+
+import java.io.Writer;
+import java.util.ArrayList;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGL11;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.egl.EGLSurface;
+import javax.microedition.khronos.opengles.GL;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.opengl.GLDebugHelper;
+import android.util.AttributeSet;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+/**
+ * An implementation of SurfaceView that uses the dedicated surface for
+ * displaying OpenGL rendering.
+ *
+ * A GLSurfaceView provides the following features:
+ *
+ *
+ * - Manages a surface, which is a special piece of memory that can be
+ * composited into the Android view system.
+ *
- Manages an EGL display, which enables OpenGL to render into a surface.
+ *
- Accepts a user-provided Renderer object that does the actual rendering.
+ *
- Renders on a dedicated thread to decouple rendering performance from the
+ * UI thread.
+ *
- Supports both on-demand and continuous rendering.
+ *
- Optionally wraps, traces, and/or error-checks the renderer's OpenGL calls.
+ *
+ *
+ * Using GLSurfaceView
+ *
+ * Typically you use GLSurfaceView by subclassing it and overriding one or more of the
+ * View system input event methods. If your application does not need to override event
+ * methods then GLSurfaceView can be used as-is. For the most part
+ * GLSurfaceView behavior is customized by calling "set" methods rather than by subclassing.
+ * For example, unlike a regular View, drawing is delegated to a separate Renderer object which
+ * is registered with the GLSurfaceView
+ * using the {@link #setRenderer(Renderer)} call.
+ *
+ *
Initializing GLSurfaceView
+ * All you have to do to initialize a GLSurfaceView is call {@link #setRenderer(Renderer)}.
+ * However, if desired, you can modify the default behavior of GLSurfaceView by calling one or
+ * more of these methods before calling setRenderer:
+ *
+ * - {@link #setDebugFlags(int)}
+ *
- {@link #setEGLConfigChooser(boolean)}
+ *
- {@link #setEGLConfigChooser(EGLConfigChooser)}
+ *
- {@link #setEGLConfigChooser(int, int, int, int, int, int)}
+ *
- {@link #setGLWrapper(GLWrapper)}
+ *
+ *
+ *
Choosing an EGL Configuration
+ * A given Android device may support multiple possible types of drawing surfaces.
+ * The available surfaces may differ in how may channels of data are present, as
+ * well as how many bits are allocated to each channel. Therefore, the first thing
+ * GLSurfaceView has to do when starting to render is choose what type of surface to use.
+ *
+ * By default GLSurfaceView chooses an available surface that's closest to a 16-bit R5G6B5 surface
+ * with a 16-bit depth buffer and no stencil. If you would prefer a different surface (for example,
+ * if you do not need a depth buffer) you can override the default behavior by calling one of the
+ * setEGLConfigChooser methods.
+ *
+ *
Debug Behavior
+ * You can optionally modify the behavior of GLSurfaceView by calling
+ * one or more of the debugging methods {@link #setDebugFlags(int)},
+ * and {@link #setGLWrapper}. These methods may be called before and/or after setRenderer, but
+ * typically they are called before setRenderer so that they take effect immediately.
+ *
+ *
Setting a Renderer
+ * Finally, you must call {@link #setRenderer} to register a {@link Renderer}.
+ * The renderer is
+ * responsible for doing the actual OpenGL rendering.
+ *
+ *
Rendering Mode
+ * Once the renderer is set, you can control whether the renderer draws
+ * continuously or on-demand by calling
+ * {@link #setRenderMode}. The default is continuous rendering.
+ *
+ *
Activity Life-cycle
+ * A GLSurfaceView must be notified when the activity is paused and resumed. GLSurfaceView clients
+ * are required to call {@link #onPause()} when the activity pauses and
+ * {@link #onResume()} when the activity resumes. These calls allow GLSurfaceView to
+ * pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate
+ * the OpenGL display.
+ *
+ *
Handling events
+ *
+ * To handle an event you will typically subclass GLSurfaceView and override the
+ * appropriate method, just as you would with any other View. However, when handling
+ * the event, you may need to communicate with the Renderer object
+ * that's running in the rendering thread. You can do this using any
+ * standard Java cross-thread communication mechanism. In addition,
+ * one relatively easy way to communicate with your renderer is
+ * to call
+ * {@link #queueEvent(Runnable)}. For example:
+ *
+ * class MyGLSurfaceView extends GLSurfaceView {
+ *
+ * private MyRenderer mMyRenderer;
+ *
+ * public void start() {
+ * mMyRenderer = ...;
+ * setRenderer(mMyRenderer);
+ * }
+ *
+ * public boolean onKeyDown(int keyCode, KeyEvent event) {
+ * if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
+ * queueEvent(new Runnable() {
+ * // This method will be called on the rendering
+ * // thread:
+ * public void run() {
+ * mMyRenderer.handleDpadCenter();
+ * }});
+ * return true;
+ * }
+ * return super.onKeyDown(keyCode, event);
+ * }
+ * }
+ *
+ *
+ */
+public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
+ private final static boolean LOG_THREADS = false;
+ private final static boolean LOG_SURFACE = true;
+ private final static boolean LOG_RENDERER = false;
+ // Work-around for bug 2263168
+ private final static boolean DRAW_TWICE_AFTER_SIZE_CHANGED = true;
+ /**
+ * The renderer only renders
+ * when the surface is created, or when {@link #requestRender} is called.
+ *
+ * @see #getRenderMode()
+ * @see #setRenderMode(int)
+ */
+ public final static int RENDERMODE_WHEN_DIRTY = 0;
+ /**
+ * The renderer is called
+ * continuously to re-render the scene.
+ *
+ * @see #getRenderMode()
+ * @see #setRenderMode(int)
+ * @see #requestRender()
+ */
+ public final static int RENDERMODE_CONTINUOUSLY = 1;
+
+ /**
+ * Check glError() after every GL call and throw an exception if glError indicates
+ * that an error has occurred. This can be used to help track down which OpenGL ES call
+ * is causing an error.
+ *
+ * @see #getDebugFlags
+ * @see #setDebugFlags
+ */
+ public final static int DEBUG_CHECK_GL_ERROR = 1;
+
+ /**
+ * Log GL calls to the system log at "verbose" level with tag "GLSurfaceView".
+ *
+ * @see #getDebugFlags
+ * @see #setDebugFlags
+ */
+ public final static int DEBUG_LOG_GL_CALLS = 2;
+
+ /**
+ * Standard View constructor. In order to render something, you
+ * must call {@link #setRenderer} to register a renderer.
+ */
+ public GLSurfaceView(Context context) {
+ super(context);
+ init();
+ }
+
+ /**
+ * Standard View constructor. In order to render something, you
+ * must call {@link #setRenderer} to register a renderer.
+ */
+ public GLSurfaceView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ private void init() {
+ // Install a SurfaceHolder.Callback so we get notified when the
+ // underlying surface is created and destroyed
+ SurfaceHolder holder = getHolder();
+ holder.addCallback(this);
+ holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
+
+ }
+
+ /**
+ * Set the glWrapper. If the glWrapper is not null, its
+ * {@link GLWrapper#wrap(GL)} method is called
+ * whenever a surface is created. A GLWrapper can be used to wrap
+ * the GL object that's passed to the renderer. Wrapping a GL
+ * object enables examining and modifying the behavior of the
+ * GL calls made by the renderer.
+ *
+ * Wrapping is typically used for debugging purposes.
+ *
+ * The default value is null.
+ * @param glWrapper the new GLWrapper
+ */
+ public void setGLWrapper(GLWrapper glWrapper) {
+ mGLWrapper = glWrapper;
+ }
+
+ /**
+ * Set the debug flags to a new value. The value is
+ * constructed by OR-together zero or more
+ * of the DEBUG_CHECK_* constants. The debug flags take effect
+ * whenever a surface is created. The default value is zero.
+ * @param debugFlags the new debug flags
+ * @see #DEBUG_CHECK_GL_ERROR
+ * @see #DEBUG_LOG_GL_CALLS
+ */
+ public void setDebugFlags(int debugFlags) {
+ mDebugFlags = debugFlags;
+ }
+
+ /**
+ * Get the current value of the debug flags.
+ * @return the current value of the debug flags.
+ */
+ public int getDebugFlags() {
+ return mDebugFlags;
+ }
+
+ /**
+ * Set the renderer associated with this view. Also starts the thread that
+ * will call the renderer, which in turn causes the rendering to start.
+ *
This method should be called once and only once in the life-cycle of
+ * a GLSurfaceView.
+ *
The following GLSurfaceView methods can only be called before
+ * setRenderer is called:
+ *
+ * - {@link #setEGLConfigChooser(boolean)}
+ *
- {@link #setEGLConfigChooser(EGLConfigChooser)}
+ *
- {@link #setEGLConfigChooser(int, int, int, int, int, int)}
+ *
+ *
+ * The following GLSurfaceView methods can only be called after
+ * setRenderer is called:
+ *
+ * - {@link #getRenderMode()}
+ *
- {@link #onPause()}
+ *
- {@link #onResume()}
+ *
- {@link #queueEvent(Runnable)}
+ *
- {@link #requestRender()}
+ *
- {@link #setRenderMode(int)}
+ *
+ *
+ * @param renderer the renderer to use to perform OpenGL drawing.
+ */
+ public void setRenderer(Renderer renderer) {
+ checkRenderThreadState();
+ if (mEGLConfigChooser == null) {
+ mEGLConfigChooser = new SimpleEGLConfigChooser(true);
+ }
+ if (mEGLContextFactory == null) {
+ mEGLContextFactory = new DefaultContextFactory();
+ }
+ if (mEGLWindowSurfaceFactory == null) {
+ mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory();
+ }
+ mGLThread = new GLThread(renderer);
+ mGLThread.start();
+ }
+
+ /**
+ * Install a custom EGLContextFactory.
+ * If this method is
+ * called, it must be called before {@link #setRenderer(Renderer)}
+ * is called.
+ *
+ * If this method is not called, then by default
+ * a context will be created with no shared context and
+ * with a null attribute list.
+ */
+ public void setEGLContextFactory(EGLContextFactory factory) {
+ checkRenderThreadState();
+ mEGLContextFactory = factory;
+ }
+
+ /**
+ * Install a custom EGLWindowSurfaceFactory.
+ *
If this method is
+ * called, it must be called before {@link #setRenderer(Renderer)}
+ * is called.
+ *
+ * If this method is not called, then by default
+ * a window surface will be created with a null attribute list.
+ */
+ public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) {
+ checkRenderThreadState();
+ mEGLWindowSurfaceFactory = factory;
+ }
+
+ /**
+ * Install a custom EGLConfigChooser.
+ *
If this method is
+ * called, it must be called before {@link #setRenderer(Renderer)}
+ * is called.
+ *
+ * If no setEGLConfigChooser method is called, then by default the
+ * view will choose a config as close to 16-bit RGB as possible, with
+ * a depth buffer as close to 16 bits as possible.
+ * @param configChooser
+ */
+ public void setEGLConfigChooser(EGLConfigChooser configChooser) {
+ checkRenderThreadState();
+ mEGLConfigChooser = configChooser;
+ }
+
+ /**
+ * Install a config chooser which will choose a config
+ * as close to 16-bit RGB as possible, with or without an optional depth
+ * buffer as close to 16-bits as possible.
+ *
If this method is
+ * called, it must be called before {@link #setRenderer(Renderer)}
+ * is called.
+ *
+ * If no setEGLConfigChooser method is called, then by default the
+ * view will choose a config as close to 16-bit RGB as possible, with
+ * a depth buffer as close to 16 bits as possible.
+ *
+ * @param needDepth
+ */
+ public void setEGLConfigChooser(boolean needDepth) {
+ setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth));
+ }
+
+ /**
+ * Install a config chooser which will choose a config
+ * with at least the specified component sizes, and as close
+ * to the specified component sizes as possible.
+ *
If this method is
+ * called, it must be called before {@link #setRenderer(Renderer)}
+ * is called.
+ *
+ * If no setEGLConfigChooser method is called, then by default the
+ * view will choose a config as close to 16-bit RGB as possible, with
+ * a depth buffer as close to 16 bits as possible.
+ *
+ */
+ public void setEGLConfigChooser(int redSize, int greenSize, int blueSize,
+ int alphaSize, int depthSize, int stencilSize) {
+ setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize,
+ blueSize, alphaSize, depthSize, stencilSize));
+ }
+
+ /**
+ * Inform the default EGLContextFactory and default EGLConfigChooser
+ * which EGLContext client version to pick.
+ *
Use this method to create an OpenGL ES 2.0-compatible context.
+ * Example:
+ *
+ * public MyView(Context context) {
+ * super(context);
+ * setEGLContextClientVersion(2); // Pick an OpenGL ES 2.0 context.
+ * setRenderer(new MyRenderer());
+ * }
+ *
+ * Note: Activities which require OpenGL ES 2.0 should indicate this by
+ * setting @lt;uses-feature android:glEsVersion="0x00020000" /> in the activity's
+ * AndroidManifest.xml file.
+ *
If this method is called, it must be called before {@link #setRenderer(Renderer)}
+ * is called.
+ *
This method only affects the behavior of the default EGLContexFactory and the
+ * default EGLConfigChooser. If
+ * {@link #setEGLContextFactory(EGLContextFactory)} has been called, then the supplied
+ * EGLContextFactory is responsible for creating an OpenGL ES 2.0-compatible context.
+ * If
+ * {@link #setEGLConfigChooser(EGLConfigChooser)} has been called, then the supplied
+ * EGLConfigChooser is responsible for choosing an OpenGL ES 2.0-compatible config.
+ * @param version The EGLContext client version to choose. Use 2 for OpenGL ES 2.0
+ */
+ public void setEGLContextClientVersion(int version) {
+ checkRenderThreadState();
+ mEGLContextClientVersion = version;
+ }
+
+ /**
+ * Set the rendering mode. When renderMode is
+ * RENDERMODE_CONTINUOUSLY, the renderer is called
+ * repeatedly to re-render the scene. When renderMode
+ * is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface
+ * is created, or when {@link #requestRender} is called. Defaults to RENDERMODE_CONTINUOUSLY.
+ *
+ * Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system performance
+ * by allowing the GPU and CPU to idle when the view does not need to be updated.
+ *
+ * This method can only be called after {@link #setRenderer(Renderer)}
+ *
+ * @param renderMode one of the RENDERMODE_X constants
+ * @see #RENDERMODE_CONTINUOUSLY
+ * @see #RENDERMODE_WHEN_DIRTY
+ */
+ public void setRenderMode(int renderMode) {
+ mGLThread.setRenderMode(renderMode);
+ }
+
+ /**
+ * Get the current rendering mode. May be called
+ * from any thread. Must not be called before a renderer has been set.
+ * @return the current rendering mode.
+ * @see #RENDERMODE_CONTINUOUSLY
+ * @see #RENDERMODE_WHEN_DIRTY
+ */
+ public int getRenderMode() {
+ return mGLThread.getRenderMode();
+ }
+
+ /**
+ * Request that the renderer render a frame.
+ * This method is typically used when the render mode has been set to
+ * {@link #RENDERMODE_WHEN_DIRTY}, so that frames are only rendered on demand.
+ * May be called
+ * from any thread. Must not be called before a renderer has been set.
+ */
+ public void requestRender() {
+ mGLThread.requestRender();
+ }
+
+ /**
+ * This method is part of the SurfaceHolder.Callback interface, and is
+ * not normally called or subclassed by clients of GLSurfaceView.
+ */
+ public void surfaceCreated(SurfaceHolder holder) {
+ mGLThread.surfaceCreated();
+ }
+
+ /**
+ * This method is part of the SurfaceHolder.Callback interface, and is
+ * not normally called or subclassed by clients of GLSurfaceView.
+ */
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ // Surface will be destroyed when we return
+ mGLThread.surfaceDestroyed();
+ }
+
+ /**
+ * This method is part of the SurfaceHolder.Callback interface, and is
+ * not normally called or subclassed by clients of GLSurfaceView.
+ */
+ public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+ mGLThread.onWindowResize(w, h);
+ }
+
+ /**
+ * Inform the view that the activity is paused. The owner of this view must
+ * call this method when the activity is paused. Calling this method will
+ * pause the rendering thread.
+ * Must not be called before a renderer has been set.
+ */
+ public void onPause() {
+ mGLThread.onPause();
+ }
+
+ /**
+ * Inform the view that the activity is resumed. The owner of this view must
+ * call this method when the activity is resumed. Calling this method will
+ * recreate the OpenGL display and resume the rendering
+ * thread.
+ * Must not be called before a renderer has been set.
+ */
+ public void onResume() {
+ mGLThread.onResume();
+ }
+
+ public void flushTextures(TextureLibrary library) {
+ mGLThread.flushTextures(library);
+ }
+
+ public void loadTextures(TextureLibrary library) {
+ mGLThread.loadTextures(library);
+ }
+
+ public void flushBuffers(BufferLibrary library) {
+ mGLThread.flushBuffers(library);
+ }
+
+ public void loadBuffers(BufferLibrary library) {
+ mGLThread.loadBuffers(library);
+ }
+
+ /**
+ * Queue a runnable to be run on the GL rendering thread. This can be used
+ * to communicate with the Renderer on the rendering thread.
+ * Must not be called before a renderer has been set.
+ * @param r the runnable to be run on the GL rendering thread.
+ */
+ public void queueEvent(Runnable r) {
+ mGLThread.queueEvent(r);
+ }
+
+ /**
+ * Inform the view that the window focus has changed.
+ */
+ @Override
+ public void onWindowFocusChanged(boolean hasFocus) {
+ super.onWindowFocusChanged(hasFocus);
+ mGLThread.onWindowFocusChanged(hasFocus);
+ }
+
+ /**
+ * This method is used as part of the View class and is not normally
+ * called or subclassed by clients of GLSurfaceView.
+ * Must not be called before a renderer has been set.
+ */
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mGLThread.requestExitAndWait();
+ }
+
+ // ----------------------------------------------------------------------
+
+ /**
+ * An interface used to wrap a GL interface.
+ *
Typically
+ * used for implementing debugging and tracing on top of the default
+ * GL interface. You would typically use this by creating your own class
+ * that implemented all the GL methods by delegating to another GL instance.
+ * Then you could add your own behavior before or after calling the
+ * delegate. All the GLWrapper would do was instantiate and return the
+ * wrapper GL instance:
+ *
+ * class MyGLWrapper implements GLWrapper {
+ * GL wrap(GL gl) {
+ * return new MyGLImplementation(gl);
+ * }
+ * static class MyGLImplementation implements GL,GL10,GL11,... {
+ * ...
+ * }
+ * }
+ *
+ * @see #setGLWrapper(GLWrapper)
+ */
+ public interface GLWrapper {
+ /**
+ * Wraps a gl interface in another gl interface.
+ * @param gl a GL interface that is to be wrapped.
+ * @return either the input argument or another GL object that wraps the input argument.
+ */
+ GL wrap(GL gl);
+ }
+
+ /**
+ * A generic renderer interface.
+ *
+ * The renderer is responsible for making OpenGL calls to render a frame.
+ *
+ * GLSurfaceView clients typically create their own classes that implement
+ * this interface, and then call {@link GLSurfaceView#setRenderer} to
+ * register the renderer with the GLSurfaceView.
+ *
+ *
Threading
+ * The renderer will be called on a separate thread, so that rendering
+ * performance is decoupled from the UI thread. Clients typically need to
+ * communicate with the renderer from the UI thread, because that's where
+ * input events are received. Clients can communicate using any of the
+ * standard Java techniques for cross-thread communication, or they can
+ * use the {@link GLSurfaceView#queueEvent(Runnable)} convenience method.
+ *
+ *
EGL Context Lost
+ * There are situations where the EGL rendering context will be lost. This
+ * typically happens when device wakes up after going to sleep. When
+ * the EGL context is lost, all OpenGL resources (such as textures) that are
+ * associated with that context will be automatically deleted. In order to
+ * keep rendering correctly, a renderer must recreate any lost resources
+ * that it still needs. The {@link #onSurfaceCreated(GL10, EGLConfig)} method
+ * is a convenient place to do this.
+ *
+ *
+ * @see #setRenderer(Renderer)
+ */
+ public interface Renderer {
+ /**
+ * Called when the surface is created or recreated.
+ *
+ * Called when the rendering thread
+ * starts and whenever the EGL context is lost. The context will typically
+ * be lost when the Android device awakes after going to sleep.
+ *
+ * Since this method is called at the beginning of rendering, as well as
+ * every time the EGL context is lost, this method is a convenient place to put
+ * code to create resources that need to be created when the rendering
+ * starts, and that need to be recreated when the EGL context is lost.
+ * Textures are an example of a resource that you might want to create
+ * here.
+ *
+ * Note that when the EGL context is lost, all OpenGL resources associated
+ * with that context will be automatically deleted. You do not need to call
+ * the corresponding "glDelete" methods such as glDeleteTextures to
+ * manually delete these lost resources.
+ *
+ * @param gl the GL interface. Use instanceof
to
+ * test if the interface supports GL11 or higher interfaces.
+ * @param config the EGLConfig of the created surface. Can be used
+ * to create matching pbuffers.
+ */
+ void onSurfaceCreated(GL10 gl, EGLConfig config);
+
+ /**
+ * Called when the surface changed size.
+ *
+ * Called after the surface is created and whenever
+ * the OpenGL ES surface size changes.
+ *
+ * Typically you will set your viewport here. If your camera
+ * is fixed then you could also set your projection matrix here:
+ *
+ * void onSurfaceChanged(GL10 gl, int width, int height) {
+ * gl.glViewport(0, 0, width, height);
+ * // for a fixed camera, set the projection too
+ * float ratio = (float) width / height;
+ * gl.glMatrixMode(GL10.GL_PROJECTION);
+ * gl.glLoadIdentity();
+ * gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
+ * }
+ *
+ * @param gl the GL interface. Use instanceof
to
+ * test if the interface supports GL11 or higher interfaces.
+ * @param width
+ * @param height
+ */
+ void onSurfaceChanged(GL10 gl, int width, int height);
+
+ /**
+ * Called when the OpenGL context has been lost is about
+ * to be recreated. onSurfaceCreated() will be called after
+ * onSurfaceLost().
+ * */
+ void onSurfaceLost();
+
+ /**
+ * Called to draw the current frame.
+ *
+ * This method is responsible for drawing the current frame.
+ *
+ * The implementation of this method typically looks like this:
+ *
+ * void onDrawFrame(GL10 gl) {
+ * gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+ * //... other gl calls to render the scene ...
+ * }
+ *
+ * @param gl the GL interface. Use instanceof
to
+ * test if the interface supports GL11 or higher interfaces.
+ */
+ void onDrawFrame(GL10 gl);
+
+ void loadTextures(GL10 gl, TextureLibrary library);
+ void flushTextures(GL10 gl, TextureLibrary library);
+ void loadBuffers(GL10 gl, BufferLibrary library);
+ void flushBuffers(GL10 gl, BufferLibrary library);
+
+
+
+ }
+
+ /**
+ * An interface for customizing the eglCreateContext and eglDestroyContext calls.
+ *
+ * This interface must be implemented by clients wishing to call
+ * {@link GLSurfaceView#setEGLContextFactory(EGLContextFactory)}
+ */
+ public interface EGLContextFactory {
+ EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig);
+ void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context);
+ }
+
+ private class DefaultContextFactory implements EGLContextFactory {
+ private int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+
+ public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig config) {
+ int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, mEGLContextClientVersion,
+ EGL10.EGL_NONE };
+
+ return egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT,
+ mEGLContextClientVersion != 0 ? attrib_list : null);
+ }
+
+ public void destroyContext(EGL10 egl, EGLDisplay display,
+ EGLContext context) {
+ egl.eglDestroyContext(display, context);
+ }
+ }
+
+ /**
+ * An interface for customizing the eglCreateWindowSurface and eglDestroySurface calls.
+ *
+ * This interface must be implemented by clients wishing to call
+ * {@link GLSurfaceView#setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory)}
+ */
+ public interface EGLWindowSurfaceFactory {
+ EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config,
+ Object nativeWindow);
+ void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface);
+ }
+
+ private static class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory {
+
+ public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display,
+ EGLConfig config, Object nativeWindow) {
+ return egl.eglCreateWindowSurface(display, config, nativeWindow, null);
+ }
+
+ public void destroySurface(EGL10 egl, EGLDisplay display,
+ EGLSurface surface) {
+ egl.eglDestroySurface(display, surface);
+ }
+ }
+
+ /**
+ * An interface for choosing an EGLConfig configuration from a list of
+ * potential configurations.
+ *
+ * This interface must be implemented by clients wishing to call
+ * {@link GLSurfaceView#setEGLConfigChooser(EGLConfigChooser)}
+ */
+ public interface EGLConfigChooser {
+ /**
+ * Choose a configuration from the list. Implementors typically
+ * implement this method by calling
+ * {@link EGL10#eglChooseConfig} and iterating through the results. Please consult the
+ * EGL specification available from The Khronos Group to learn how to call eglChooseConfig.
+ * @param egl the EGL10 for the current display.
+ * @param display the current display.
+ * @return the chosen configuration.
+ */
+ EGLConfig chooseConfig(EGL10 egl, EGLDisplay display);
+ }
+
+ private abstract class BaseConfigChooser
+ implements EGLConfigChooser {
+ public BaseConfigChooser(int[] configSpec) {
+ mConfigSpec = filterConfigSpec(configSpec);
+ }
+
+ public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
+ int[] num_config = new int[1];
+ if (!egl.eglChooseConfig(display, mConfigSpec, null, 0,
+ num_config)) {
+ throw new IllegalArgumentException("eglChooseConfig failed");
+ }
+
+ int numConfigs = num_config[0];
+
+ if (numConfigs <= 0) {
+ throw new IllegalArgumentException(
+ "No configs match configSpec");
+ }
+
+ EGLConfig[] configs = new EGLConfig[numConfigs];
+ if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs,
+ num_config)) {
+ throw new IllegalArgumentException("eglChooseConfig#2 failed");
+ }
+ EGLConfig config = chooseConfig(egl, display, configs);
+ if (config == null) {
+ throw new IllegalArgumentException("No config chosen");
+ }
+ return config;
+ }
+
+ abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
+ EGLConfig[] configs);
+
+ protected int[] mConfigSpec;
+
+ private int[] filterConfigSpec(int[] configSpec) {
+ if (mEGLContextClientVersion != 2) {
+ return configSpec;
+ }
+ /* We know none of the subclasses define EGL_RENDERABLE_TYPE.
+ * And we know the configSpec is well formed.
+ */
+ int len = configSpec.length;
+ int[] newConfigSpec = new int[len + 2];
+ System.arraycopy(configSpec, 0, newConfigSpec, 0, len-1);
+ newConfigSpec[len-1] = EGL10.EGL_RENDERABLE_TYPE;
+ newConfigSpec[len] = 4; /* EGL_OPENGL_ES2_BIT */
+ newConfigSpec[len+1] = EGL10.EGL_NONE;
+ return newConfigSpec;
+ }
+ }
+
+ private class ComponentSizeChooser extends BaseConfigChooser {
+ public ComponentSizeChooser(int redSize, int greenSize, int blueSize,
+ int alphaSize, int depthSize, int stencilSize) {
+ super(new int[] {
+ EGL10.EGL_RED_SIZE, redSize,
+ EGL10.EGL_GREEN_SIZE, greenSize,
+ EGL10.EGL_BLUE_SIZE, blueSize,
+ EGL10.EGL_ALPHA_SIZE, alphaSize,
+ EGL10.EGL_DEPTH_SIZE, depthSize,
+ EGL10.EGL_STENCIL_SIZE, stencilSize,
+ EGL10.EGL_NONE});
+ mValue = new int[1];
+ mRedSize = redSize;
+ mGreenSize = greenSize;
+ mBlueSize = blueSize;
+ mAlphaSize = alphaSize;
+ mDepthSize = depthSize;
+ mStencilSize = stencilSize;
+ }
+
+ @Override
+ public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
+ EGLConfig[] configs) {
+ EGLConfig closestConfig = null;
+ int closestDistance = 1000;
+ for(EGLConfig config : configs) {
+ int d = findConfigAttrib(egl, display, config,
+ EGL10.EGL_DEPTH_SIZE, 0);
+ int s = findConfigAttrib(egl, display, config,
+ EGL10.EGL_STENCIL_SIZE, 0);
+ if (d >= mDepthSize && s>= mStencilSize) {
+ int r = findConfigAttrib(egl, display, config,
+ EGL10.EGL_RED_SIZE, 0);
+ int g = findConfigAttrib(egl, display, config,
+ EGL10.EGL_GREEN_SIZE, 0);
+ int b = findConfigAttrib(egl, display, config,
+ EGL10.EGL_BLUE_SIZE, 0);
+ int a = findConfigAttrib(egl, display, config,
+ EGL10.EGL_ALPHA_SIZE, 0);
+ int distance = Math.abs(r - mRedSize)
+ + Math.abs(g - mGreenSize)
+ + Math.abs(b - mBlueSize)
+ + Math.abs(a - mAlphaSize);
+ if (distance < closestDistance) {
+ closestDistance = distance;
+ closestConfig = config;
+ }
+ }
+ }
+ return closestConfig;
+ }
+
+ private int findConfigAttrib(EGL10 egl, EGLDisplay display,
+ EGLConfig config, int attribute, int defaultValue) {
+
+ if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
+ return mValue[0];
+ }
+ return defaultValue;
+ }
+
+ private int[] mValue;
+ // Subclasses can adjust these values:
+ protected int mRedSize;
+ protected int mGreenSize;
+ protected int mBlueSize;
+ protected int mAlphaSize;
+ protected int mDepthSize;
+ protected int mStencilSize;
+ }
+
+ /**
+ * This class will choose a supported surface as close to
+ * RGB565 as possible, with or without a depth buffer.
+ *
+ */
+ private class SimpleEGLConfigChooser extends ComponentSizeChooser {
+ public SimpleEGLConfigChooser(boolean withDepthBuffer) {
+ super(4, 4, 4, 0, withDepthBuffer ? 16 : 0, 0);
+ // Adjust target values. This way we'll accept a 4444 or
+ // 555 buffer if there's no 565 buffer available.
+ mRedSize = 5;
+ mGreenSize = 6;
+ mBlueSize = 5;
+ }
+ }
+
+ /**
+ * An EGL helper class.
+ */
+
+ private class EglHelper {
+ public EglHelper() {
+
+ }
+
+ /**
+ * Initialize EGL for a given configuration spec.
+ * @param configSpec
+ */
+ public void start(){
+ /*
+ * Get an EGL instance
+ */
+ mEgl = (EGL10) EGLContext.getEGL();
+
+ /*
+ * Get to the default display.
+ */
+ mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+
+ if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
+ throw new RuntimeException("eglGetDisplay failed");
+ }
+
+ /*
+ * We can now initialize EGL for that display
+ */
+ int[] version = new int[2];
+ if(!mEgl.eglInitialize(mEglDisplay, version)) {
+ throw new RuntimeException("eglInitialize failed");
+ }
+ mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);
+
+ /*
+ * Create an OpenGL ES context. This must be done only once, an
+ * OpenGL context is a somewhat heavy object.
+ */
+ mEglContext = mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig);
+ if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) {
+ throwEglException("createContext");
+ }
+
+ mEglSurface = null;
+ }
+
+ /*
+ * React to the creation of a new surface by creating and returning an
+ * OpenGL interface that renders to that surface.
+ */
+ public GL createSurface(SurfaceHolder holder) {
+ /*
+ * The window size has changed, so we need to create a new
+ * surface.
+ */
+ if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) {
+
+ /*
+ * Unbind and destroy the old EGL surface, if
+ * there is one.
+ */
+ mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
+ EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
+ mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface);
+ }
+
+ /*
+ * Create an EGL surface we can render into.
+ */
+ mEglSurface = mEGLWindowSurfaceFactory.createWindowSurface(mEgl,
+ mEglDisplay, mEglConfig, holder);
+
+ if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
+ throwEglException("createWindowSurface");
+ }
+
+ /*
+ * Before we can issue GL commands, we need to make sure
+ * the context is current and bound to a surface.
+ */
+ if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
+ throwEglException("eglMakeCurrent");
+ }
+
+ GL gl = mEglContext.getGL();
+ if (mGLWrapper != null) {
+ gl = mGLWrapper.wrap(gl);
+ }
+
+ if ((mDebugFlags & (DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS)) != 0) {
+ int configFlags = 0;
+ Writer log = null;
+ if ((mDebugFlags & DEBUG_CHECK_GL_ERROR) != 0) {
+ configFlags |= GLDebugHelper.CONFIG_CHECK_GL_ERROR;
+ }
+ if ((mDebugFlags & DEBUG_LOG_GL_CALLS) != 0) {
+ log = new LogWriter();
+ }
+ gl = GLDebugHelper.wrap(gl, configFlags, log);
+ }
+ return gl;
+ }
+
+ /**
+ * Display the current render surface.
+ * @return false if the context has been lost.
+ */
+ public boolean swap() {
+ mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
+
+ /*
+ * Always check for EGL_CONTEXT_LOST, which means the context
+ * and all associated data were lost (For instance because
+ * the device went to sleep). We need to sleep until we
+ * get a new surface.
+ */
+ return mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST;
+ }
+
+ public void destroySurface() {
+ if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) {
+ mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
+ EGL10.EGL_NO_SURFACE,
+ EGL10.EGL_NO_CONTEXT);
+ mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface);
+ mEglSurface = null;
+ }
+ }
+
+ public void finish() {
+ if (mEglContext != null) {
+ mEGLContextFactory.destroyContext(mEgl, mEglDisplay, mEglContext);
+ mEglContext = null;
+ }
+ if (mEglDisplay != null) {
+ mEgl.eglTerminate(mEglDisplay);
+ mEglDisplay = null;
+ }
+ }
+
+ private void throwEglException(String function) {
+ throw new RuntimeException(function + " failed: " + mEgl.eglGetError());
+ }
+
+ /** Checks to see if the current context is valid. **/
+ public boolean verifyContext() {
+ EGLContext currentContext = mEgl.eglGetCurrentContext();
+ return currentContext != EGL10.EGL_NO_CONTEXT && mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST;
+ }
+
+ EGL10 mEgl;
+ EGLDisplay mEglDisplay;
+ EGLSurface mEglSurface;
+ EGLConfig mEglConfig;
+ EGLContext mEglContext;
+
+ }
+
+ /**
+ * A generic GL Thread. Takes care of initializing EGL and GL. Delegates
+ * to a Renderer instance to do the actual drawing. Can be configured to
+ * render continuously or on request.
+ *
+ * All potentially blocking synchronization is done through the
+ * sGLThreadManager object. This avoids multiple-lock ordering issues.
+ *
+ */
+ private class GLThread extends Thread {
+ public GLThread(Renderer renderer) {
+ super();
+ mWidth = 0;
+ mHeight = 0;
+ mRequestRender = true;
+ mRenderMode = RENDERMODE_CONTINUOUSLY;
+ mRenderer = renderer;
+ }
+
+
+ @Override
+ public void run() {
+ setName("GLThread " + getId());
+ if (LOG_THREADS) {
+ DebugLog.i("GLThread", "starting tid=" + getId());
+ }
+
+ try {
+ guardedRun();
+ } catch (InterruptedException e) {
+ // fall thru and exit normally
+ } finally {
+ sGLThreadManager.threadExiting(this);
+ }
+ }
+
+ /*
+ * This private method should only be called inside a
+ * synchronized(sGLThreadManager) block.
+ */
+ private void stopEglLocked() {
+ if (mHaveEglSurface) {
+ mHaveEglSurface = false;
+ mEglHelper.destroySurface();
+ sGLThreadManager.releaseEglSurfaceLocked(this);
+ }
+ }
+
+ private void guardedRun() throws InterruptedException {
+ mEglHelper = new EglHelper();
+ mHaveEglContext = false;
+ mHaveEglSurface = false;
+ try {
+ GL10 gl = null;
+ boolean createEglSurface = false;
+ boolean sizeChanged = false;
+ boolean wantRenderNotification = false;
+ boolean doRenderNotification = false;
+ int w = 0;
+ int h = 0;
+ Runnable event = null;
+
+ while (true) {
+ synchronized (sGLThreadManager) {
+ while (true) {
+ if (mShouldExit) {
+ return;
+ }
+
+ if (! mEventQueue.isEmpty()) {
+ event = mEventQueue.remove(0);
+ break;
+ }
+
+ // Do we need to release the EGL surface?
+ if (mHaveEglSurface && mPaused) {
+ if (LOG_SURFACE) {
+ DebugLog.i("GLThread", "releasing EGL surface because paused tid=" + getId());
+ }
+ stopEglLocked();
+ }
+
+ // Have we lost the surface view surface?
+ if ((! mHasSurface) && (! mWaitingForSurface)) {
+ if (LOG_SURFACE) {
+ DebugLog.i("GLThread", "noticed surfaceView surface lost tid=" + getId());
+ }
+ if (mHaveEglSurface) {
+ stopEglLocked();
+ }
+ mWaitingForSurface = true;
+ sGLThreadManager.notifyAll();
+ }
+
+ // Have we acquired the surface view surface?
+ if (mHasSurface && mWaitingForSurface) {
+ if (LOG_SURFACE) {
+ DebugLog.i("GLThread", "noticed surfaceView surface acquired tid=" + getId());
+ }
+ mWaitingForSurface = false;
+ sGLThreadManager.notifyAll();
+ }
+
+ if (doRenderNotification) {
+ wantRenderNotification = false;
+ doRenderNotification = false;
+ mRenderComplete = true;
+ sGLThreadManager.notifyAll();
+ }
+
+ // Ready to draw?
+ if ((!mPaused) && mHasSurface
+ && (mWidth > 0) && (mHeight > 0)
+ && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY))) {
+
+ if (mHaveEglContext && !mHaveEglSurface) {
+ // Let's make sure the context hasn't been lost.
+ if (!mEglHelper.verifyContext()) {
+ mEglHelper.finish();
+ mRenderer.onSurfaceLost();
+ mHaveEglContext = false;
+ }
+ }
+ // If we don't have an egl surface, try to acquire one.
+ if ((! mHaveEglContext) && sGLThreadManager.tryAcquireEglSurfaceLocked(this)) {
+ mHaveEglContext = true;
+ mEglHelper.start();
+
+ sGLThreadManager.notifyAll();
+ }
+
+ if (mHaveEglContext && !mHaveEglSurface) {
+ mHaveEglSurface = true;
+ createEglSurface = true;
+ sizeChanged = true;
+ }
+
+ if (mHaveEglSurface) {
+ if (mSizeChanged) {
+ sizeChanged = true;
+ w = mWidth;
+ h = mHeight;
+ wantRenderNotification = true;
+
+ if (DRAW_TWICE_AFTER_SIZE_CHANGED) {
+ // We keep mRequestRender true so that we draw twice after the size changes.
+ // (Once because of mSizeChanged, the second time because of mRequestRender.)
+ // This forces the updated graphics onto the screen.
+ } else {
+ mRequestRender = false;
+ }
+ mSizeChanged = false;
+ } else {
+ mRequestRender = false;
+ }
+ sGLThreadManager.notifyAll();
+ break;
+ }
+ }
+
+ // By design, this is the only place in a GLThread thread where we wait().
+ if (LOG_THREADS) {
+ DebugLog.i("GLThread", "waiting tid=" + getId());
+ }
+ sGLThreadManager.wait();
+ }
+ } // end of synchronized(sGLThreadManager)
+
+ if (event != null) {
+ event.run();
+ event = null;
+ continue;
+ }
+
+ if (mHasFocus) {
+ if (createEglSurface) {
+ gl = (GL10) mEglHelper.createSurface(getHolder());
+ sGLThreadManager.checkGLDriver(gl);
+ if (LOG_RENDERER) {
+ DebugLog.w("GLThread", "onSurfaceCreated");
+ }
+ mGL = gl;
+ mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);
+ createEglSurface = false;
+ }
+
+
+ if (sizeChanged) {
+ if (LOG_RENDERER) {
+ DebugLog.w("GLThread", "onSurfaceChanged(" + w + ", " + h + ")");
+ }
+ mRenderer.onSurfaceChanged(gl, w, h);
+ sizeChanged = false;
+ }
+
+
+
+ if (LOG_RENDERER) {
+ DebugLog.w("GLThread", "onDrawFrame");
+ }
+ mRenderer.onDrawFrame(gl);
+ if(!mEglHelper.swap()) {
+ if (LOG_SURFACE) {
+ DebugLog.i("GLThread", "egl surface lost tid=" + getId());
+ }
+ }
+
+ }
+ if (wantRenderNotification) {
+ doRenderNotification = true;
+ }
+ }
+
+ } finally {
+ mGL = null;
+ /*
+ * clean-up everything...
+ */
+ synchronized (sGLThreadManager) {
+ stopEglLocked();
+ mEglHelper.finish();
+ }
+ }
+ }
+
+ public void setRenderMode(int renderMode) {
+ if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) {
+ throw new IllegalArgumentException("renderMode");
+ }
+ synchronized(sGLThreadManager) {
+ mRenderMode = renderMode;
+ sGLThreadManager.notifyAll();
+ }
+ }
+
+ public int getRenderMode() {
+ synchronized(sGLThreadManager) {
+ return mRenderMode;
+ }
+ }
+
+ public void requestRender() {
+ synchronized(sGLThreadManager) {
+ mRequestRender = true;
+ sGLThreadManager.notifyAll();
+ }
+ }
+
+ public void surfaceCreated() {
+ synchronized(sGLThreadManager) {
+ if (LOG_THREADS) {
+ DebugLog.i("GLThread", "surfaceCreated tid=" + getId());
+ }
+ mHasSurface = true;
+ sGLThreadManager.notifyAll();
+ }
+ }
+
+ public void surfaceDestroyed() {
+ synchronized(sGLThreadManager) {
+ if (LOG_THREADS) {
+ DebugLog.i("GLThread", "surfaceDestroyed tid=" + getId());
+ }
+ mHasSurface = false;
+ sGLThreadManager.notifyAll();
+ while((!mWaitingForSurface) && (!mExited)) {
+ try {
+ sGLThreadManager.wait();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+ }
+
+ public void onPause() {
+ synchronized (sGLThreadManager) {
+ mPaused = true;
+ sGLThreadManager.notifyAll();
+ }
+ }
+
+ public void onResume() {
+ synchronized (sGLThreadManager) {
+ mPaused = false;
+ mRequestRender = true;
+ sGLThreadManager.notifyAll();
+ }
+ }
+
+ public void onWindowResize(int w, int h) {
+ synchronized (sGLThreadManager) {
+ mWidth = w;
+ mHeight = h;
+ mSizeChanged = true;
+ mRequestRender = true;
+ mRenderComplete = false;
+ sGLThreadManager.notifyAll();
+
+ // Wait for thread to react to resize and render a frame
+ while (! mExited && !mPaused && !mRenderComplete ) {
+ if (LOG_SURFACE) {
+ DebugLog.i("Main thread", "onWindowResize waiting for render complete.");
+ }
+ try {
+ sGLThreadManager.wait();
+ } catch (InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+ }
+
+ public void loadTextures(TextureLibrary library) {
+ synchronized (this) {
+ assert mGL != null;
+ if (mGL != null && mHasSurface) {
+ mRenderer.loadTextures(mGL, library);
+ }
+ }
+ }
+
+ public void flushTextures(TextureLibrary library) {
+ synchronized (this) {
+ assert mGL != null;
+ if (mGL != null) {
+ mRenderer.flushTextures(mGL, library);
+ }
+ }
+ }
+
+ public void loadBuffers(BufferLibrary library) {
+ synchronized (this) {
+ assert mGL != null;
+ if (mGL != null) {
+ mRenderer.loadBuffers(mGL, library);
+ }
+ }
+ }
+
+ public void flushBuffers(BufferLibrary library) {
+ synchronized (this) {
+ assert mGL != null;
+ if (mGL != null) {
+ mRenderer.flushBuffers(mGL, library);
+ }
+ }
+ }
+
+ // On some Qualcomm devices (such as the HTC Magic running Android 1.6),
+ // there's a bug in the graphics driver that will cause glViewport() to
+ // do the wrong thing in a very specific situation. When the screen is
+ // rotated, if a surface is created in one layout (say, portrait view)
+ // and then rotated to another, subsequent calls to glViewport are clipped.
+ // So, if the window is, say, 320x480 when the surface is created, and
+ // then the rotation occurs and glViewport() is called with the new
+ // size of 480x320, devices with the buggy driver will clip the viewport
+ // to the old width (which means 320x320...ugh!). This is fixed in
+ // Android 2.1 Qualcomm devices (like Nexus One) and doesn't affect
+ // non-Qualcomm devices (like the Motorola DROID).
+ //
+ // Unfortunately, under Android 1.6 this exact case occurs when the
+ // screen is put to sleep and then wakes up again. The lock screen
+ // comes up in portrait mode, but at the same time the window surface
+ // is also created in the backgrounded game. When the lock screen is closed
+ // and the game comes forward, the window is fixed to the correct size
+ // which causes the bug to occur.
+
+ // The solution used here is to simply never render when the window surface
+ // does not have the focus. When the lock screen (or menu) is up, rendering
+ // will stop. This resolves the driver bug (as the egl surface won't be created
+ // until after the screen size has been fixed), and is generally good practice
+ // since you don't want to be doing a lot of CPU intensive work when the lock
+ // screen is up (to preserve battery life).
+
+ public void onWindowFocusChanged(boolean hasFocus) {
+ synchronized(sGLThreadManager) {
+ mHasFocus = hasFocus;
+ sGLThreadManager.notifyAll();
+ }
+ if (LOG_SURFACE) {
+ DebugLog.i("Main thread", "Focus " + (mHasFocus ? "gained" : "lost"));
+ }
+
+ }
+
+ public void requestExitAndWait() {
+ // don't call this from GLThread thread or it is a guaranteed
+ // deadlock!
+ synchronized(sGLThreadManager) {
+ mShouldExit = true;
+ sGLThreadManager.notifyAll();
+ while (! mExited) {
+ try {
+ sGLThreadManager.wait();
+ } catch (InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+ }
+
+ /**
+ * Queue an "event" to be run on the GL rendering thread.
+ * @param r the runnable to be run on the GL rendering thread.
+ */
+ public void queueEvent(Runnable r) {
+ if (r == null) {
+ throw new IllegalArgumentException("r must not be null");
+ }
+ synchronized(sGLThreadManager) {
+ mEventQueue.add(r);
+ sGLThreadManager.notifyAll();
+ }
+ }
+
+ // Once the thread is started, all accesses to the following member
+ // variables are protected by the sGLThreadManager monitor
+ private boolean mShouldExit;
+ private boolean mExited;
+ private boolean mPaused;
+ private boolean mHasSurface;
+ private boolean mWaitingForSurface;
+ private boolean mHaveEglContext;
+ private boolean mHaveEglSurface;
+ private int mWidth;
+ private int mHeight;
+ private int mRenderMode;
+ private boolean mRequestRender;
+ private boolean mRenderComplete;
+ private ArrayList mEventQueue = new ArrayList();
+ private GL10 mGL;
+ private boolean mHasFocus;
+
+ // End of member variables protected by the sGLThreadManager monitor.
+
+ private Renderer mRenderer;
+ private EglHelper mEglHelper;
+ }
+
+ static class LogWriter extends Writer {
+
+ @Override public void close() {
+ flushBuilder();
+ }
+
+ @Override public void flush() {
+ flushBuilder();
+ }
+
+ @Override public void write(char[] buf, int offset, int count) {
+ for(int i = 0; i < count; i++) {
+ char c = buf[offset + i];
+ if ( c == '\n') {
+ flushBuilder();
+ }
+ else {
+ mBuilder.append(c);
+ }
+ }
+ }
+
+ private void flushBuilder() {
+ if (mBuilder.length() > 0) {
+ DebugLog.v("GLSurfaceView", mBuilder.toString());
+ mBuilder.delete(0, mBuilder.length());
+ }
+ }
+
+ private StringBuilder mBuilder = new StringBuilder();
+ }
+
+
+ private void checkRenderThreadState() {
+ if (mGLThread != null) {
+ throw new IllegalStateException(
+ "setRenderer has already been called for this instance.");
+ }
+ }
+
+ private static class GLThreadManager {
+
+ public synchronized void threadExiting(GLThread thread) {
+ if (LOG_THREADS) {
+ DebugLog.i("GLThread", "exiting tid=" + thread.getId());
+ }
+ thread.mExited = true;
+ if (mEglOwner == thread) {
+ mEglOwner = null;
+ }
+ notifyAll();
+ }
+
+ /*
+ * Tries once to acquire the right to use an EGL
+ * surface. Does not block. Requires that we are already
+ * in the sGLThreadManager monitor when this is called.
+ *
+ * @return true if the right to use an EGL surface was acquired.
+ */
+ public boolean tryAcquireEglSurfaceLocked(GLThread thread) {
+ if (mEglOwner == thread || mEglOwner == null) {
+ mEglOwner = thread;
+ notifyAll();
+ return true;
+ }
+ checkGLESVersion();
+ if (mMultipleGLESContextsAllowed) {
+ return true;
+ }
+ return false;
+ }
+ /*
+ * Releases the EGL surface. Requires that we are already in the
+ * sGLThreadManager monitor when this is called.
+ */
+ public void releaseEglSurfaceLocked(GLThread thread) {
+ if (mEglOwner == thread) {
+ mEglOwner = null;
+ }
+ notifyAll();
+ }
+
+ public synchronized void checkGLDriver(GL10 gl) {
+ if (! mGLESDriverCheckComplete) {
+ checkGLESVersion();
+ if (mGLESVersion < kGLES_20) {
+ String renderer = gl.glGetString(GL10.GL_RENDERER);
+ mMultipleGLESContextsAllowed = false;
+ notifyAll();
+ }
+ mGLESDriverCheckComplete = true;
+ }
+ }
+
+ private void checkGLESVersion() {
+ if (! mGLESVersionCheckComplete) {
+ mGLESVersion = ConfigurationInfo.GL_ES_VERSION_UNDEFINED;
+ if (mGLESVersion >= kGLES_20) {
+ mMultipleGLESContextsAllowed = true;
+ }
+ mGLESVersionCheckComplete = true;
+ }
+
+ }
+
+ private boolean mGLESVersionCheckComplete;
+ private int mGLESVersion;
+ private boolean mGLESDriverCheckComplete;
+ private boolean mMultipleGLESContextsAllowed;
+ private int mGLContextCount;
+ private static final int kGLES_20 = 0x20000;
+ private GLThread mEglOwner;
+
+ }
+
+ private static final GLThreadManager sGLThreadManager = new GLThreadManager();
+ private boolean mSizeChanged = true;
+
+ private GLThread mGLThread;
+ private EGLConfigChooser mEGLConfigChooser;
+ private EGLContextFactory mEGLContextFactory;
+ private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory;
+ private GLWrapper mGLWrapper;
+ private int mDebugFlags;
+ private int mEGLContextClientVersion;
+
+
+}
diff --git a/src/com/replica/replicaisland/Game.java b/src/com/replica/replicaisland/Game.java
new file mode 100644
index 0000000..a6cbf44
--- /dev/null
+++ b/src/com/replica/replicaisland/Game.java
@@ -0,0 +1,505 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.replica.replicaisland;
+
+import android.content.Context;
+import android.view.MotionEvent;
+import android.widget.Toast;
+
+/**
+ * High-level setup object for the AndouKun game engine.
+ * This class sets up the core game engine objects and threads. It also passes events to the
+ * game thread from the main UI thread.
+ */
+public class Game extends AllocationGuard {
+ private GameThread mGameThread;
+ private Thread mGame;
+ private ObjectManager mGameRoot;
+
+ private GameRenderer mRenderer;
+ private GLSurfaceView mSurfaceView;
+ private boolean mRunning;
+ private boolean mBootstrapComplete;
+ private LevelTree.Level mPendingLevel;
+ private LevelTree.Level mCurrentLevel;
+ private LevelTree.Level mLastLevel;
+ private boolean mGLDataLoaded;
+ private ContextParameters mContextParameters;
+
+ public Game() {
+ super();
+ mRunning = false;
+ mBootstrapComplete = false;
+ mGLDataLoaded = false;
+ mContextParameters = new ContextParameters();
+ }
+
+ /**
+ * Creates core game objects and constructs the game engine object graph. Note that the
+ * game does not actually begin running after this function is called (see start() below).
+ * Also note that textures are not loaded from the resource pack by this function, as OpenGl
+ * isn't yet available.
+ * @param context
+ */
+ public void bootstrap(Context context, int viewWidth, int viewHeight, int gameWidth, int gameHeight) {
+ if (!mBootstrapComplete) {
+ mRenderer = new GameRenderer(context, this, gameWidth, gameHeight);
+
+ // Create core systems
+ BaseObject.sSystemRegistry.openGLSystem = new OpenGLSystem(null);
+
+ BaseObject.sSystemRegistry.customToastSystem = new CustomToastSystem(context);
+
+ ContextParameters params = mContextParameters;
+ params.viewWidth = viewWidth;
+ params.viewHeight = viewHeight;
+ params.gameWidth = gameWidth;
+ params.gameHeight = gameHeight;
+ params.viewScaleX = (float)viewWidth / gameWidth;
+ params.viewScaleY = (float)viewHeight / gameHeight;
+ params.context = context;
+ BaseObject.sSystemRegistry.contextParameters = params;
+
+ // Short-term textures are cleared between levels.
+ TextureLibrary shortTermTextureLibrary = new TextureLibrary();
+ BaseObject.sSystemRegistry.shortTermTextureLibrary = shortTermTextureLibrary;
+
+ // Long-term textures persist between levels.
+ TextureLibrary longTermTextureLibrary = new TextureLibrary();
+ BaseObject.sSystemRegistry.longTermTextureLibrary = longTermTextureLibrary;
+
+ // The buffer library manages hardware VBOs.
+ BaseObject.sSystemRegistry.bufferLibrary = new BufferLibrary();
+
+
+
+ BaseObject.sSystemRegistry.soundSystem = new SoundSystem();
+
+ // The root of the game graph.
+ MainLoop gameRoot = new MainLoop();
+
+ InputSystem input = new InputSystem();
+ gameRoot.add(input);
+ BaseObject.sSystemRegistry.inputSystem = input;
+
+
+ LevelSystem level = new LevelSystem();
+ BaseObject.sSystemRegistry.levelSystem = level;
+
+ CollisionSystem collision = new CollisionSystem();
+ BaseObject.sSystemRegistry.collisionSystem = collision;
+ BaseObject.sSystemRegistry.hitPointPool = new HitPointPool();
+
+ GameObjectManager gameManager = new GameObjectManager(params.viewWidth * 2);
+ BaseObject.sSystemRegistry.gameObjectManager = gameManager;
+
+ GameObjectFactory objectFactory = new GameObjectFactory();
+ BaseObject.sSystemRegistry.gameObjectFactory = objectFactory;
+
+ BaseObject.sSystemRegistry.hotSpotSystem = new HotSpotSystem();
+
+ BaseObject.sSystemRegistry.levelBuilder = new LevelBuilder();
+
+ BaseObject.sSystemRegistry.channelSystem = new ChannelSystem();
+ BaseObject.sSystemRegistry.registerForReset(BaseObject.sSystemRegistry.channelSystem);
+
+ CameraSystem camera = new CameraSystem();
+
+
+ BaseObject.sSystemRegistry.cameraSystem = camera;
+ BaseObject.sSystemRegistry.registerForReset(camera);
+
+ collision.loadCollisionTiles(context.getResources().openRawResource(R.raw.collision));
+
+ gameRoot.add(gameManager);
+
+ // Camera must come after the game manager so that the camera target moves before the camera
+ // centers.
+
+ gameRoot.add(camera);
+
+
+ // More basic systems.
+
+ GameObjectCollisionSystem dynamicCollision = new GameObjectCollisionSystem();
+ gameRoot.add(dynamicCollision);
+ BaseObject.sSystemRegistry.gameObjectCollisionSystem = dynamicCollision;
+
+
+ RenderSystem renderer = new RenderSystem();
+ BaseObject.sSystemRegistry.renderSystem = renderer;
+ BaseObject.sSystemRegistry.vectorPool = new VectorPool();
+ BaseObject.sSystemRegistry.drawableFactory = new DrawableFactory();
+
+ HudSystem hud = new HudSystem();
+ hud.setFuelDrawable(
+ new DrawableBitmap(longTermTextureLibrary.allocateTexture(
+ R.drawable.ui_bar), 0, 0),
+ new DrawableBitmap(longTermTextureLibrary.allocateTexture(
+ R.drawable.ui_bar_bg), 0, 0));
+ hud.setFadeTexture(longTermTextureLibrary.allocateTexture(R.drawable.black));
+ hud.setButtonDrawables(
+ new DrawableBitmap(longTermTextureLibrary.allocateTexture(
+ R.drawable.ui_button_fly_disabled), 0, 0),
+ new DrawableBitmap(longTermTextureLibrary.allocateTexture(
+ R.drawable.ui_button_fly_off), 0, 0),
+ new DrawableBitmap(longTermTextureLibrary.allocateTexture(
+ R.drawable.ui_button_fly_on), 0, 0),
+ new DrawableBitmap(longTermTextureLibrary.allocateTexture(
+ R.drawable.ui_button_stomp_off), 0, 0),
+ new DrawableBitmap(longTermTextureLibrary.allocateTexture(
+ R.drawable.ui_button_stomp_on), 0, 0));
+ Texture[] digitTextures = {
+ longTermTextureLibrary.allocateTexture(R.drawable.ui_0),
+ longTermTextureLibrary.allocateTexture(R.drawable.ui_1),
+ longTermTextureLibrary.allocateTexture(R.drawable.ui_2),
+ longTermTextureLibrary.allocateTexture(R.drawable.ui_3),
+ longTermTextureLibrary.allocateTexture(R.drawable.ui_4),
+ longTermTextureLibrary.allocateTexture(R.drawable.ui_5),
+ longTermTextureLibrary.allocateTexture(R.drawable.ui_6),
+ longTermTextureLibrary.allocateTexture(R.drawable.ui_7),
+ longTermTextureLibrary.allocateTexture(R.drawable.ui_8),
+ longTermTextureLibrary.allocateTexture(R.drawable.ui_9)
+ };
+ DrawableBitmap[] digits = {
+ new DrawableBitmap(digitTextures[0], 0, 0),
+ new DrawableBitmap(digitTextures[1], 0, 0),
+ new DrawableBitmap(digitTextures[2], 0, 0),
+ new DrawableBitmap(digitTextures[3], 0, 0),
+ new DrawableBitmap(digitTextures[4], 0, 0),
+ new DrawableBitmap(digitTextures[5], 0, 0),
+ new DrawableBitmap(digitTextures[6], 0, 0),
+ new DrawableBitmap(digitTextures[7], 0, 0),
+ new DrawableBitmap(digitTextures[8], 0, 0),
+ new DrawableBitmap(digitTextures[9], 0, 0)
+ };
+ DrawableBitmap xDrawable = new DrawableBitmap(
+ longTermTextureLibrary.allocateTexture(R.drawable.ui_x), 0, 0);
+
+ hud.setDigitDrawables(digits, xDrawable);
+ hud.setCollectableDrawables(
+ new DrawableBitmap(
+ longTermTextureLibrary.allocateTexture(R.drawable.ui_pearl), 0, 0),
+ new DrawableBitmap(
+ longTermTextureLibrary.allocateTexture(R.drawable.ui_gem), 0, 0));
+
+ BaseObject.sSystemRegistry.hudSystem = hud;
+ gameRoot.add(hud);
+
+ BaseObject.sSystemRegistry.vibrationSystem = new VibrationSystem();
+
+ BaseObject.sSystemRegistry.eventRecorder = new EventRecorder();
+
+ gameRoot.add(collision);
+
+ // debug systems
+ //BaseObject.sSystemRegistry.debugSystem = new DebugSystem(longTermTextureLibrary);
+ //dynamicCollision.setDebugPrefs(false, true);
+
+
+ objectFactory.preloadEffects();
+
+ mGameRoot = gameRoot;
+
+ mGameThread = new GameThread(mRenderer);
+ mGameThread.setGameRoot(mGameRoot);
+
+
+ mCurrentLevel = null;
+
+ mBootstrapComplete = true;
+ }
+ }
+
+
+ protected synchronized void stopLevel() {
+ stop();
+ GameObjectManager manager = BaseObject.sSystemRegistry.gameObjectManager;
+ manager.destroyAll();
+ manager.commitUpdates();
+
+ //TODO: it's not strictly necessary to clear the static data here, but if I don't do it
+ // then two things happen: first, the static data will refer to junk Texture objects, and
+ // second, memory that may not be needed for the next level will hang around. One solution
+ // would be to break up the texture library into static and non-static things, and
+ // then selectively clear static game components based on their usefulness next level,
+ // but this is way simpler.
+ GameObjectFactory factory = BaseObject.sSystemRegistry.gameObjectFactory;
+ factory.clearStaticData();
+ factory.sanityCheckPools();
+
+ // Reset the level
+ BaseObject.sSystemRegistry.levelSystem.reset();
+
+ // Reset systems that need it.
+ BaseObject.sSystemRegistry.reset();
+
+ // Dump the short-term texture objects only.
+ mSurfaceView.flushTextures(BaseObject.sSystemRegistry.shortTermTextureLibrary);
+ BaseObject.sSystemRegistry.shortTermTextureLibrary.removeAll();
+ mSurfaceView.flushBuffers(BaseObject.sSystemRegistry.bufferLibrary);
+ BaseObject.sSystemRegistry.bufferLibrary.removeAll();
+ }
+
+ public synchronized void requestNewLevel() {
+ // tell the Renderer to call us back when the
+ // render thread is ready to manage some texture memory.
+ mRenderer.requestCallback();
+ }
+
+ public synchronized void restartLevel() {
+ DebugLog.d("AndouKun", "Restarting...");
+ final LevelTree.Level level = mCurrentLevel;
+ stop();
+
+ // Destroy all game objects and respawn them. No need to destroy other systems.
+ GameObjectManager manager = BaseObject.sSystemRegistry.gameObjectManager;
+ manager.destroyAll();
+ manager.commitUpdates();
+
+ // Reset systems that need it.
+ BaseObject.sSystemRegistry.reset();
+
+ LevelSystem levelSystem = BaseObject.sSystemRegistry.levelSystem;
+ levelSystem.incrementAttemptsCount();
+ levelSystem.spawnObjects();
+
+ BaseObject.sSystemRegistry.hudSystem.startFade(true, 0.2f);
+
+ mCurrentLevel = level;
+ mPendingLevel = null;
+ start();
+ }
+
+ protected synchronized void goToLevel(LevelTree.Level level) {
+
+ ContextParameters params = BaseObject.sSystemRegistry.contextParameters;
+ BaseObject.sSystemRegistry.levelSystem.loadLevel(level,
+ params.context.getResources().openRawResource(level.resource), mGameRoot);
+
+ Context context = params.context;
+ mRenderer.setContext(context);
+ mSurfaceView.loadTextures(BaseObject.sSystemRegistry.longTermTextureLibrary);
+ mSurfaceView.loadTextures(BaseObject.sSystemRegistry.shortTermTextureLibrary);
+ mSurfaceView.loadBuffers(BaseObject.sSystemRegistry.bufferLibrary);
+
+ mGLDataLoaded = true;
+
+
+ mCurrentLevel = level;
+ mPendingLevel = null;
+
+ TimeSystem time = BaseObject.sSystemRegistry.timeSystem;
+ time.reset();
+
+ HudSystem hud = BaseObject.sSystemRegistry.hudSystem;
+ if (hud != null) {
+ hud.startFade(true, 1.0f);
+ }
+
+ CustomToastSystem toast = BaseObject.sSystemRegistry.customToastSystem;
+ if (toast != null) {
+ if (level.inThePast) {
+ toast.toast(context.getString(R.string.memory_playback_start), Toast.LENGTH_LONG);
+ } else {
+ if (mLastLevel != null && mLastLevel.inThePast) {
+ toast.toast(context.getString(R.string.memory_playback_complete), Toast.LENGTH_LONG);
+ }
+ }
+ }
+
+ mLastLevel = level;
+
+ start();
+ }
+
+ /** Starts the game running. */
+ public void start() {
+ if (!mRunning) {
+ assert mGame == null;
+ // Now's a good time to run the GC.
+ Runtime r = Runtime.getRuntime();
+ r.gc();
+ DebugLog.d("AndouKun", "Start!");
+ mGame = new Thread(mGameThread);
+ mGame.setName("Game");
+ mGame.start();
+ mRunning = true;
+ AllocationGuard.sGuardActive = false;
+ } else {
+ mGameThread.resumeGame();
+ }
+ }
+
+ public void stop() {
+ if (mRunning) {
+ DebugLog.d("AndouKun", "Stop!");
+ if (mGameThread.getPaused()) {
+ mGameThread.resumeGame();
+ }
+ mGameThread.stopGame();
+ try {
+ mGame.join();
+ } catch (InterruptedException e) {
+ mGame.interrupt();
+ }
+ mGame = null;
+ mRunning = false;
+ mCurrentLevel = null;
+ AllocationGuard.sGuardActive = false;
+ }
+ }
+
+ public boolean onTrackballEvent(MotionEvent event) {
+ if (mRunning) {
+ mGameThread.rollEvent(event.getRawX(), event.getRawY());
+ boolean clickDown = event.getAction() == MotionEvent.ACTION_DOWN;
+ if ((clickDown && event.getPressure() > 0)
+ || event.getAction() == MotionEvent.ACTION_UP){
+ mGameThread.clickEvent(clickDown);
+ }
+ }
+ return true;
+ }
+
+ public boolean onOrientationEvent(float x, float y, float z) {
+ if (mRunning) {
+ mGameThread.orientationEvent(x, y, z);
+ }
+ return true;
+ }
+
+ public boolean onTouchEvent(MotionEvent event) {
+ if (mRunning) {
+ if (event.getAction() == MotionEvent.ACTION_UP) {
+ mGameThread.touchUpEvent(event.getRawX() * (1.0f / mContextParameters.viewScaleX),
+ event.getRawY() * (1.0f / mContextParameters.viewScaleY));
+ } else {
+ mGameThread.touchDownEvent(event.getRawX() * (1.0f / mContextParameters.viewScaleX),
+ event.getRawY() * (1.0f / mContextParameters.viewScaleY));
+ }
+
+ }
+ return true;
+ }
+
+ public boolean onKeyDownEvent(int keyCode) {
+ boolean result = false;
+ if (mRunning) {
+ result = mGameThread.keydownEvent(keyCode);
+ }
+ return result;
+ }
+
+ public boolean onKeyUpEvent(int keyCode) {
+ boolean result = false;
+ if (mRunning) {
+ result = mGameThread.keyupEvent(keyCode);
+ }
+ return result;
+ }
+
+ public GameRenderer getRenderer() {
+ return mRenderer;
+ }
+
+ public void onPause() {
+ if (mRunning) {
+ mGameThread.pauseGame();
+ }
+ }
+
+ public void onResume(Context context, boolean force) {
+ if (force && mRunning) {
+ mGameThread.resumeGame();
+ } else {
+ mRenderer.setContext(context);
+ // Don't explicitly resume the game here. We'll do that in
+ // the SurfaceReady() callback, which will prevent the game
+ // starting before the render thread is ready to go.
+ BaseObject.sSystemRegistry.contextParameters.context = context;
+ }
+ }
+
+ public void onSurfaceReady() {
+ DebugLog.d("AndouKun", "Surface Ready");
+
+ if (mPendingLevel != null && mPendingLevel != mCurrentLevel) {
+ if (mRunning) {
+ stopLevel();
+ }
+ goToLevel(mPendingLevel);
+ } else if (mGameThread.getPaused() && mRunning) {
+ mGameThread.resumeGame();
+ }
+ }
+
+ public void setSurfaceView(GLSurfaceView view) {
+ mSurfaceView = view;
+ }
+
+ public void onSurfaceLost() {
+ DebugLog.d("AndouKun", "Surface Lost");
+
+ BaseObject.sSystemRegistry.shortTermTextureLibrary.invalidateAll();
+ BaseObject.sSystemRegistry.longTermTextureLibrary.invalidateAll();
+ BaseObject.sSystemRegistry.bufferLibrary.invalidateHardwareBuffers();
+
+ mGLDataLoaded = false;
+ }
+
+ public void onSurfaceCreated() {
+ DebugLog.d("AndouKun", "Surface Created");
+
+ // TODO: this is dumb. SurfaceView doesn't need to control everything here.
+ // GL should just be passed to this function and then set up directly.
+
+ if (!mGLDataLoaded && mGameThread.getPaused() && mRunning && mPendingLevel == null) {
+
+ mSurfaceView.loadTextures(BaseObject.sSystemRegistry.longTermTextureLibrary);
+ mSurfaceView.loadTextures(BaseObject.sSystemRegistry.shortTermTextureLibrary);
+ mSurfaceView.loadBuffers(BaseObject.sSystemRegistry.bufferLibrary);
+ mGLDataLoaded = true;
+ }
+ }
+
+ public void setPendingLevel(LevelTree.Level level) {
+ mPendingLevel = level;
+ }
+
+ public void setSoundEnabled(boolean soundEnabled) {
+ BaseObject.sSystemRegistry.soundSystem.setSoundEnabled(soundEnabled);
+ }
+
+ public void setControlOptions(boolean clickAttack, boolean tiltControls) {
+ BaseObject.sSystemRegistry.inputSystem.setClickActive(clickAttack);
+ BaseObject.sSystemRegistry.inputSystem.setUseOrientationForRoll(tiltControls);
+ }
+
+ public float getGameTime() {
+ return BaseObject.sSystemRegistry.timeSystem.getGameTime();
+ }
+
+ public Vector2 getLastDeathPosition() {
+ return BaseObject.sSystemRegistry.eventRecorder.getLastDeathPosition();
+ }
+
+ public boolean isPaused() {
+ return (mRunning && mGameThread != null && mGameThread.getPaused());
+ }
+
+}
diff --git a/src/com/replica/replicaisland/GameComponent.java b/src/com/replica/replicaisland/GameComponent.java
new file mode 100644
index 0000000..099c04f
--- /dev/null
+++ b/src/com/replica/replicaisland/GameComponent.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.replica.replicaisland;
+
+/**
+ * A game component implements a single feature of a game object. Components are run once per frame
+ * when their parent object is active. Updating a game object is equivalent to updating all of its
+ * components. Note that a game object may contain more than one instance of the same type of
+ * component.
+ */
+public abstract class GameComponent extends PhasedObject {
+ // Defines high-level buckets within which components may choose to run.
+ public enum ComponentPhases {
+ THINK, // decisions are made
+ PHYSICS, // impulse velocities are summed
+ POST_PHYSICS, // inertia, friction, and bounce
+ MOVEMENT, // position is updated
+ COLLISION_DETECTION, // intersections are detected
+ COLLISION_RESPONSE, // intersections are resolved
+ POST_COLLISION, // position is now final for the frame
+ ANIMATION, // animations are selected
+ PRE_DRAW, // drawing state is initialized
+ DRAW, // drawing commands are scheduled.
+ FRAME_END, // final cleanup before the next update
+ }
+
+ public boolean shared;
+
+ public GameComponent() {
+ super();
+ shared = false;
+ }
+
+}
diff --git a/src/com/replica/replicaisland/GameComponentPool.java b/src/com/replica/replicaisland/GameComponentPool.java
new file mode 100644
index 0000000..6270570
--- /dev/null
+++ b/src/com/replica/replicaisland/GameComponentPool.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.replica.replicaisland;
+
+public class GameComponentPool extends TObjectPool {
+ public Class> objectClass;
+
+ public GameComponentPool(Class> type) {
+ super();
+ objectClass = type;
+ fill();
+ }
+
+ public GameComponentPool(Class> type, int size) {
+ super(size);
+ objectClass = type;
+ fill();
+ }
+
+ @Override
+ protected void fill() {
+ if (objectClass != null) {
+ for (int x = 0; x < getSize(); x++) {
+ try {
+ getAvailable().add(objectClass.newInstance());
+ } catch (IllegalAccessException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (InstantiationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+}
+
+
+
diff --git a/src/com/replica/replicaisland/GameFlowEvent.java b/src/com/replica/replicaisland/GameFlowEvent.java
new file mode 100644
index 0000000..a7acf8f
--- /dev/null
+++ b/src/com/replica/replicaisland/GameFlowEvent.java
@@ -0,0 +1,48 @@
+package com.replica.replicaisland;
+
+import android.content.Context;
+
+public class GameFlowEvent implements Runnable {
+ public static final int EVENT_INVALID = -1;
+ public static final int EVENT_RESTART_LEVEL = 0;
+ public static final int EVENT_END_GAME = 1;
+ public static final int EVENT_GO_TO_NEXT_LEVEL = 2;
+
+ public static final int EVENT_SHOW_DIARY = 3;
+ public static final int EVENT_SHOW_DIALOG_CHARACTER1 = 4;
+ public static final int EVENT_SHOW_DIALOG_CHARACTER2 = 5;
+ public static final int EVENT_SHOW_ANIMATION = 6;
+
+ private int mEventCode;
+ private int mDataIndex;
+ private AndouKun mMainActivity;
+
+ public void post(int event, int index, Context context) {
+ if (context instanceof AndouKun) {
+ DebugLog.d("GameFlowEvent", "Post Game Flow Event: " + event + ", " + index);
+ mEventCode = event;
+ mDataIndex = index;
+ mMainActivity = (AndouKun)context;
+ mMainActivity.runOnUiThread(this);
+ }
+ }
+
+ public void postImmediate(int event, int index, Context context) {
+ if (context instanceof AndouKun) {
+ DebugLog.d("GameFlowEvent", "Execute Immediate Game Flow Event: " + event + ", " + index);
+ mEventCode = event;
+ mDataIndex = index;
+ mMainActivity = (AndouKun)context;
+ mMainActivity.onGameFlowEvent(mEventCode, mDataIndex);
+ }
+ }
+
+ public void run() {
+ if (mMainActivity != null) {
+ DebugLog.d("GameFlowEvent", "Execute Game Flow Event: " + mEventCode + ", " + mDataIndex);
+ mMainActivity.onGameFlowEvent(mEventCode, mDataIndex);
+ mMainActivity = null;
+ }
+ }
+
+}
diff --git a/src/com/replica/replicaisland/GameObject.java b/src/com/replica/replicaisland/GameObject.java
new file mode 100644
index 0000000..392486a
--- /dev/null
+++ b/src/com/replica/replicaisland/GameObject.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.replica.replicaisland;
+
+import com.replica.replicaisland.CollisionParameters.HitType;
+
+/**
+ * GameObject defines any object that resides in the game world (character, background, special
+ * effect, enemy, etc). It is a collection of GameComponents which implement its behavior;
+ * GameObjects themselves have no intrinsic behavior. GameObjects are also "bags of data" that
+ * components can use to share state (direct component-to-component communication is discouraged).
+ */
+public class GameObject extends PhasedObjectManager {
+ private final static float COLLISION_SURFACE_DECAY_TIME = 0.3f;
+ // These fields are managed by components.
+ private Vector2 mPosition;
+ private Vector2 mVelocity;
+ private Vector2 mTargetVelocity;
+ private Vector2 mAcceleration;
+ private Vector2 mImpulse;
+
+ private Vector2 mBackgroundCollisionNormal;
+
+ private float mLastTouchedFloorTime;
+ private float mLastTouchedCeilingTime;
+ private float mLastTouchedLeftWallTime;
+ private float mLastTouchedRightWallTime;
+
+ public boolean positionLocked;
+
+ public float activationRadius;
+ public boolean destroyOnDeactivation;
+
+ public int life;
+
+ public int lastReceivedHitType;
+
+ public Vector2 facingDirection;
+ public float width;
+ public float height;
+
+ private static final int DEFAULT_LIFE = 1;
+
+ public enum ActionType {
+ INVALID,
+ IDLE,
+ MOVE,
+ ATTACK,
+ HIT_REACT,
+ DEATH,
+ HIDE,
+ FROZEN
+ }
+
+ private ActionType mCurrentAction;
+
+ public enum Team {
+ NONE,
+ PLAYER,
+ ENEMY
+ }
+
+ public Team team;
+
+ public GameObject() {
+ super();
+
+ mPosition = new Vector2();
+ mVelocity = new Vector2();
+ mTargetVelocity = new Vector2();
+ mAcceleration = new Vector2();
+ mImpulse = new Vector2();
+ mBackgroundCollisionNormal = new Vector2();
+
+ facingDirection = new Vector2(1, 0);
+
+ reset();
+ }
+
+ @Override
+ public void reset() {
+ removeAll();
+ commitUpdates();
+
+ mPosition.zero();
+ mVelocity.zero();
+ mTargetVelocity.zero();
+ mAcceleration.zero();
+ mImpulse.zero();
+ mBackgroundCollisionNormal.zero();
+ facingDirection.set(1.0f, 1.0f);
+
+ mCurrentAction = ActionType.INVALID;
+ positionLocked = false;
+ activationRadius = 0;
+ destroyOnDeactivation = false;
+ life = DEFAULT_LIFE;
+ team = Team.NONE;
+ width = 0.0f;
+ height = 0.0f;
+
+ lastReceivedHitType = HitType.INVALID;
+ }
+
+ // Utility functions
+ public final boolean touchingGround() {
+ final TimeSystem time = sSystemRegistry.timeSystem;
+ final float gameTime = time.getGameTime();
+ final boolean touching = gameTime > 0.1f &&
+ Utils.close(mLastTouchedFloorTime, time.getGameTime(), COLLISION_SURFACE_DECAY_TIME);
+ return touching;
+ }
+
+ public final boolean touchingCeiling() {
+ final TimeSystem time = sSystemRegistry.timeSystem;
+ final float gameTime = time.getGameTime();
+ final boolean touching = gameTime > 0.1f &&
+ Utils.close(mLastTouchedCeilingTime, time.getGameTime(), COLLISION_SURFACE_DECAY_TIME);
+ return touching;
+ }
+
+ public final boolean touchingLeftWall() {
+ final TimeSystem time = sSystemRegistry.timeSystem;
+ final float gameTime = time.getGameTime();
+ final boolean touching = gameTime > 0.1f &&
+ Utils.close(mLastTouchedLeftWallTime, time.getGameTime(), COLLISION_SURFACE_DECAY_TIME);
+ return touching;
+ }
+
+ public final boolean touchingRightWall() {
+ final TimeSystem time = sSystemRegistry.timeSystem;
+ final float gameTime = time.getGameTime();
+ final boolean touching = gameTime > 0.1f &&
+ Utils.close(mLastTouchedRightWallTime, time.getGameTime(), COLLISION_SURFACE_DECAY_TIME);
+ return touching;
+ }
+
+ public final Vector2 getPosition() {
+ return mPosition;
+ }
+
+ public final void setPosition(Vector2 position) {
+ mPosition.set(position);
+ }
+
+ public final float getCenteredPositionX() {
+ return mPosition.x + (width / 2.0f);
+ }
+
+ public final float getCenteredPositionY() {
+ return mPosition.y + (height / 2.0f);
+ }
+
+ public final Vector2 getVelocity() {
+ return mVelocity;
+ }
+
+ public final void setVelocity(Vector2 velocity) {
+ mVelocity.set(velocity);
+ }
+
+ public final Vector2 getTargetVelocity() {
+ return mTargetVelocity;
+ }
+
+ public final void setTargetVelocity(Vector2 targetVelocity) {
+ mTargetVelocity.set(targetVelocity);
+ }
+
+ public final Vector2 getAcceleration() {
+ return mAcceleration;
+ }
+
+ public final void setAcceleration(Vector2 acceleration) {
+ mAcceleration.set(acceleration);
+ }
+
+ public final Vector2 getImpulse() {
+ return mImpulse;
+ }
+
+ public final void setImpulse(Vector2 impulse) {
+ mImpulse.set(impulse);
+ }
+
+ public final Vector2 getBackgroundCollisionNormal() {
+ return mBackgroundCollisionNormal;
+ }
+
+ public final void setBackgroundCollisionNormal(Vector2 normal) {
+ mBackgroundCollisionNormal.set(normal);
+ }
+
+ public final float getLastTouchedFloorTime() {
+ return mLastTouchedFloorTime;
+ }
+
+ public final void setLastTouchedFloorTime(float lastTouchedFloorTime) {
+ mLastTouchedFloorTime = lastTouchedFloorTime;
+ }
+
+ public final float getLastTouchedCeilingTime() {
+ return mLastTouchedCeilingTime;
+ }
+
+ public final void setLastTouchedCeilingTime(float lastTouchedCeilingTime) {
+ mLastTouchedCeilingTime = lastTouchedCeilingTime;
+ }
+
+ public final float getLastTouchedLeftWallTime() {
+ return mLastTouchedLeftWallTime;
+ }
+
+ public final void setLastTouchedLeftWallTime(float lastTouchedLeftWallTime) {
+ mLastTouchedLeftWallTime = lastTouchedLeftWallTime;
+ }
+
+ public final float getLastTouchedRightWallTime() {
+ return mLastTouchedRightWallTime;
+ }
+
+ public final void setLastTouchedRightWallTime(float lastTouchedRightWallTime) {
+ mLastTouchedRightWallTime = lastTouchedRightWallTime;
+ }
+
+ public final ActionType getCurrentAction() {
+ return mCurrentAction;
+ }
+
+ public final void setCurrentAction(ActionType type) {
+ mCurrentAction = type;
+ }
+}
diff --git a/src/com/replica/replicaisland/GameObjectCollisionSystem.java b/src/com/replica/replicaisland/GameObjectCollisionSystem.java
new file mode 100644
index 0000000..aa5f9a1
--- /dev/null
+++ b/src/com/replica/replicaisland/GameObjectCollisionSystem.java
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.replica.replicaisland;
+
+import java.util.Comparator;
+
+import com.replica.replicaisland.CollisionParameters.HitType;
+
+/**
+ * A system for calculating collisions between moving game objects. This system accepts collision
+ * volumes from game objects each frame and performs a series of tests to see which of them
+ * overlap. Collisions are only considered between offending "attack" volumes and receiving
+ * "vulnerability" volumes. This implementation works by using a sweep-and-prune algorithm:
+ * objects to be considered are sorted in the x axis and then compared in one dimension for
+ * overlaps. A bounding volume that encompasses all attack and vulnerability volumes is used for
+ * this test, and when an intersection is found the actual offending and receiving volumes are
+ * compared. If an intersection is detected both objects receive notification via a
+ * HitReactionComponent, if one has been specified.
+ */
+public class GameObjectCollisionSystem extends BaseObject {
+ private static final int MAX_COLLIDING_OBJECTS = 64;
+ private static final int COLLISION_RECORD_POOL_SIZE = 64;
+ private static final CollisionVolumeComparator sCollisionVolumeComparator
+ = new CollisionVolumeComparator();
+ private static CollisionVolume.FlipInfo sFlip = new CollisionVolume.FlipInfo();
+ private static CollisionVolume.FlipInfo sOtherFlip = new CollisionVolume.FlipInfo();
+
+ FixedSizeArray mObjects;
+ CollisionVolumeRecordPool mRecordPool;
+ private boolean mDrawDebugBoundingVolume = false;
+ private boolean mDrawDebugCollisionVolumes = false;
+
+
+ public GameObjectCollisionSystem() {
+ super();
+ mObjects = new FixedSizeArray(MAX_COLLIDING_OBJECTS);
+ mObjects.setComparator(sCollisionVolumeComparator);
+ //mObjects.setSorter(new ShellSorter());
+ mRecordPool = new CollisionVolumeRecordPool(COLLISION_RECORD_POOL_SIZE);
+ }
+
+ @Override
+ public void reset() {
+ final int count = mObjects.getCount();
+
+ for (int x = 0; x < count; x++) {
+ mRecordPool.release(mObjects.get(x));
+ }
+ mObjects.clear();
+
+ mDrawDebugBoundingVolume = false;
+ mDrawDebugCollisionVolumes = false;
+ }
+
+ /**
+ * Adds a game object, and its related volumes, to the dynamic collision world for one frame.
+ * Once registered for collisions the object may damage other objects via attack volumes or
+ * receive damage from other volumes via vulnerability volumes.
+ * @param object The object to consider for collision.
+ * @param reactionComponent A HitReactionComponent to notify when an intersection is calculated.
+ * If null, the intersection will still occur and no notification will be sent.
+ * @param boundingVolume A volume that describes the game object in space. It should encompass
+ * all of the attack and vulnerability volumes.
+ * @param attackVolumes A list of volumes that can hit other game objects. May be null.
+ * @param vulnerabilityVolumes A list of volumes that can receive hits from other game objects.
+ * May be null.
+ */
+ public void registerForCollisions(GameObject object,
+ HitReactionComponent reactionComponent,
+ CollisionVolume boundingVolume,
+ FixedSizeArray attackVolumes,
+ FixedSizeArray vulnerabilityVolumes) {
+ CollisionVolumeRecord record = mRecordPool.allocate();
+ if (record != null && object != null && boundingVolume != null
+ && (attackVolumes != null || vulnerabilityVolumes != null)) {
+ record.object = object;
+ record.boundingVolume = boundingVolume;
+ record.attackVolumes = attackVolumes;
+ record.vulnerabilityVolumes = vulnerabilityVolumes;
+ record.reactionComponent = reactionComponent;
+ mObjects.add(record);
+ }
+ }
+
+ @Override
+ public void update(float timeDelta, BaseObject parent) {
+ // Sort the objects by their x position.
+ mObjects.sort(true);
+
+ final int count = mObjects.getCount();
+ for (int x = 0; x < count; x++) {
+ final CollisionVolumeRecord record = mObjects.get(x);
+ final Vector2 position = record.object.getPosition();
+ sFlip.flipX = (record.object.facingDirection.x < 0.0f);
+ sFlip.flipY = (record.object.facingDirection.y < 0.0f);
+ sFlip.parentWidth = record.object.width;
+ sFlip.parentHeight = record.object.height;
+
+ if (sSystemRegistry.debugSystem != null) {
+ drawDebugVolumes(record);
+ }
+
+ final float maxX = record.boundingVolume.getMaxXPosition(sFlip) + position.x;
+ for (int y = x + 1; y < count; y++) {
+ final CollisionVolumeRecord other = mObjects.get(y);
+ final Vector2 otherPosition = other.object.getPosition();
+ sOtherFlip.flipX = (other.object.facingDirection.x < 0.0f);
+ sOtherFlip.flipY = (other.object.facingDirection.y < 0.0f);
+ sOtherFlip.parentWidth = other.object.width;
+ sOtherFlip.parentHeight = other.object.height;
+
+ if (otherPosition.x + other.boundingVolume.getMinXPosition(sOtherFlip) > maxX) {
+ // These objects can't possibly be colliding. And since the list is sorted,
+ // there are no potentially colliding objects after this object
+ // either, so we're done!
+ break;
+ } else {
+ final boolean testRequired = (record.attackVolumes != null && other.vulnerabilityVolumes != null) ||
+ (record.vulnerabilityVolumes != null && other.attackVolumes != null);
+ if (testRequired && record.boundingVolume.intersects(position, sFlip,
+ other.boundingVolume, otherPosition, sOtherFlip)) {
+ // These two objects are potentially colliding.
+ // Now we must test all attack vs vulnerability boxes.
+ final int hit = testAttackAgainstVulnerability(
+ record.attackVolumes,
+ other.vulnerabilityVolumes,
+ position,
+ otherPosition,
+ sFlip,
+ sOtherFlip);
+ if (hit != HitType.INVALID) {
+ boolean hitAccepted = false;
+ if (other.reactionComponent != null) {
+ hitAccepted = other.reactionComponent.receivedHit(
+ other.object, record.object, hit);
+ }
+ if (record.reactionComponent != null) {
+ record.reactionComponent.hitVictim(
+ record.object, other.object, hit, hitAccepted);
+ }
+
+ }
+
+ final int hit2 = testAttackAgainstVulnerability(
+ other.attackVolumes,
+ record.vulnerabilityVolumes,
+ otherPosition,
+ position,
+ sOtherFlip,
+ sFlip);
+ if (hit2 != HitType.INVALID) {
+ boolean hitAccepted = false;
+ if (record.reactionComponent != null) {
+ hitAccepted = record.reactionComponent.receivedHit(
+ record.object, other.object, hit2);
+ }
+ if (other.reactionComponent != null) {
+ other.reactionComponent.hitVictim(
+ other.object, record.object, hit2, hitAccepted);
+ }
+
+ }
+ }
+ }
+ }
+ // This is a little tricky. Since we always sweep forward in the list it's safe
+ // to invalidate the current record after we've tested it. This way we don't have to
+ // iterate over the object list twice.
+ mRecordPool.release(record);
+ }
+
+ mObjects.clear();
+ }
+
+ /** Compares the passed list of attack volumes against the passed list of vulnerability volumes
+ * and returns a hit type if an intersection is found.
+ * @param attackVolumes Offensive collision volumes.
+ * @param vulnerabilityVolumes Receiving collision volumes.
+ * @param attackPosition The world position of the attacking object.
+ * @param vulnerabilityPosition The world position of the receiving object.
+ * @return The hit type of the first attacking volume that intersects a vulnerability volume,
+ * or HitType.INVALID if no intersections are found.
+ */
+ private int testAttackAgainstVulnerability(
+ FixedSizeArray attackVolumes,
+ FixedSizeArray vulnerabilityVolumes,
+ Vector2 attackPosition,
+ Vector2 vulnerabilityPosition,
+ CollisionVolume.FlipInfo attackFlip,
+ CollisionVolume.FlipInfo vulnerabilityFlip) {
+ int intersectionType = HitType.INVALID;
+ if (attackVolumes != null && vulnerabilityVolumes != null) {
+ final int attackCount = attackVolumes.getCount();
+ for (int x = 0; x < attackCount && intersectionType == HitType.INVALID; x++) {
+ final CollisionVolume attackVolume = attackVolumes.get(x);
+ final int hitType = attackVolume.getHitType();
+ if (hitType != HitType.INVALID) {
+ final int vulnerabilityCount = vulnerabilityVolumes.getCount();
+ for (int y = 0; y < vulnerabilityCount; y++) {
+ final CollisionVolume vulnerabilityVolume = vulnerabilityVolumes.get(y);
+ final int vulnerableType = vulnerabilityVolume.getHitType();
+ if (vulnerableType == HitType.INVALID || vulnerableType == hitType) {
+ if (attackVolume.intersects(attackPosition, attackFlip,
+ vulnerabilityVolume, vulnerabilityPosition,
+ vulnerabilityFlip)) {
+ intersectionType = hitType;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return intersectionType;
+ }
+
+ private final void drawDebugVolumes(CollisionVolumeRecord record) {
+ final Vector2 position = record.object.getPosition();
+ if (mDrawDebugBoundingVolume) {
+ final CollisionVolume boundingVolume = record.boundingVolume;
+ sSystemRegistry.debugSystem.drawShape(
+ position.x + boundingVolume.getMinXPosition(sFlip), position.y + boundingVolume.getMinYPosition(sFlip),
+ boundingVolume.getMaxX() - boundingVolume.getMinX(),
+ boundingVolume.getMaxY() - boundingVolume.getMinY(),
+ DebugSystem.SHAPE_CIRCLE,
+ DebugSystem.COLOR_OUTLINE);
+ }
+ if (mDrawDebugCollisionVolumes) {
+ if (record.attackVolumes != null) {
+ final int attackVolumeCount = record.attackVolumes.getCount();
+ for (int y = 0; y < attackVolumeCount; y++) {
+ CollisionVolume volume = record.attackVolumes.get(y);
+ sSystemRegistry.debugSystem.drawShape(
+ position.x + volume.getMinXPosition(sFlip), position.y + volume.getMinYPosition(sFlip),
+ volume.getMaxX() - volume.getMinX(),
+ volume.getMaxY() - volume.getMinY(),
+ volume.getClass() == AABoxCollisionVolume.class ? DebugSystem.SHAPE_BOX : DebugSystem.SHAPE_CIRCLE,
+ DebugSystem.COLOR_RED);
+ }
+ }
+
+ if (record.vulnerabilityVolumes != null) {
+ final int vulnVolumeCount = record.vulnerabilityVolumes.getCount();
+ for (int y = 0; y < vulnVolumeCount; y++) {
+ CollisionVolume volume = record.vulnerabilityVolumes.get(y);
+ sSystemRegistry.debugSystem.drawShape(
+ position.x + volume.getMinXPosition(sFlip), position.y + volume.getMinYPosition(sFlip),
+ volume.getMaxX() - volume.getMinX(),
+ volume.getMaxY() - volume.getMinY(),
+ volume.getClass() == AABoxCollisionVolume.class ? DebugSystem.SHAPE_BOX : DebugSystem.SHAPE_CIRCLE,
+ DebugSystem.COLOR_BLUE);
+ }
+ }
+ }
+ }
+
+ public void setDebugPrefs(boolean drawBoundingVolumes, boolean drawCollisionVolumes) {
+ mDrawDebugBoundingVolume = drawBoundingVolumes;
+ mDrawDebugCollisionVolumes = drawCollisionVolumes;
+ }
+
+ /** A record of a single game object and its associated collision info. */
+ private class CollisionVolumeRecord extends AllocationGuard {
+ public GameObject object;
+ public HitReactionComponent reactionComponent;
+ public CollisionVolume boundingVolume;
+ public FixedSizeArray attackVolumes;
+ public FixedSizeArray vulnerabilityVolumes;
+
+ public void reset() {
+ object = null;
+ attackVolumes = null;
+ vulnerabilityVolumes = null;
+ boundingVolume = null;
+ reactionComponent = null;
+ }
+ }
+
+ /** A pool of collision volume records. */
+ private class CollisionVolumeRecordPool extends TObjectPool {
+
+ public CollisionVolumeRecordPool(int count) {
+ super(count);
+ }
+
+ @Override
+ protected void fill() {
+ for (int x = 0; x < getSize(); x++) {
+ getAvailable().add(new CollisionVolumeRecord());
+ }
+ }
+
+ @Override
+ public void release(Object entry) {
+ ((CollisionVolumeRecord)entry).reset();
+ super.release(entry);
+ }
+
+ }
+
+ /**
+ * Comparator for game objects that considers the world position of the object's bounding
+ * volume and sorts objects from left to right on the x axis. */
+ public final static class CollisionVolumeComparator implements Comparator {
+ private static CollisionVolume.FlipInfo sCompareFlip = new CollisionVolume.FlipInfo();
+ public int compare(CollisionVolumeRecord object1, CollisionVolumeRecord object2) {
+ int result = 0;
+ if (object1 == null && object2 != null) {
+ result = 1;
+ } else if (object1 != null && object2 == null) {
+ result = -1;
+ } else if (object1 != null && object2 != null) {
+ sCompareFlip.flipX = (object1.object.facingDirection.x < 0.0f);
+ sCompareFlip.flipY = (object1.object.facingDirection.y < 0.0f);
+ sCompareFlip.parentWidth = object1.object.width;
+ sCompareFlip.parentHeight = object1.object.height;
+
+ final float minX1 = object1.object.getPosition().x
+ + object1.boundingVolume.getMinXPosition(sCompareFlip);
+
+ sCompareFlip.flipX = (object2.object.facingDirection.x < 0.0f);
+ sCompareFlip.flipY = (object2.object.facingDirection.y < 0.0f);
+ sCompareFlip.parentWidth = object2.object.width;
+ sCompareFlip.parentHeight = object2.object.height;
+
+ final float minX2 = object2.object.getPosition().x
+ + object2.boundingVolume.getMinXPosition(sCompareFlip);
+
+ final float delta = minX1 - minX2;
+ if (delta < 0.0f) {
+ result = -1;
+ } else if (delta > 0.0f) {
+ result = 1;
+ }
+ }
+ return result;
+ }
+ }
+
+
+
+}
diff --git a/src/com/replica/replicaisland/GameObjectFactory.java b/src/com/replica/replicaisland/GameObjectFactory.java
new file mode 100644
index 0000000..6dd8d1a
--- /dev/null
+++ b/src/com/replica/replicaisland/GameObjectFactory.java
@@ -0,0 +1,6504 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.replica.replicaisland;
+
+import java.util.Comparator;
+
+import com.replica.replicaisland.AnimationComponent.PlayerAnimations;
+import com.replica.replicaisland.CollisionParameters.HitType;
+import com.replica.replicaisland.EnemyAnimationComponent.EnemyAnimations;
+import com.replica.replicaisland.GameObject.ActionType;
+import com.replica.replicaisland.GameObject.Team;
+
+/** A class for generating game objects at runtime.
+ * This should really be replaced with something that is data-driven, but it is hard to do data
+ * parsing quickly at runtime. For the moment this class is full of large functions that just
+ * patch pointers between objects, but in the future those functions should either be
+ * a) generated from data at compile time, or b) described by data at runtime.
+ */
+public class GameObjectFactory extends BaseObject {
+ private final static int MAX_GAME_OBJECTS = 256;
+ private final static ComponentPoolComparator sComponentPoolComparator = new ComponentPoolComparator();
+ private FixedSizeArray> mStaticData;
+ private FixedSizeArray mComponentPools;
+ private GameComponentPool mPoolSearchDummy;
+ private GameObjectPool mGameObjectPool;
+
+ private float mTightActivationRadius;
+ private float mNormalActivationRadius;
+ private float mWideActivationRadius;
+ private float mAlwaysActive;
+
+ private final static String sRedButtonChannel = "RED BUTTON";
+ private final static String sBlueButtonChannel = "BLUE BUTTON";
+ private final static String sGreenButtonChannel = "GREEN BUTTON";
+ private final static String sSurprisedNPCChannel = "SURPRISED";
+
+
+ // A list of game objects that can be spawned at runtime. Note that the indicies of these
+ // objects must match the order of the object tileset in the level editor in order for the
+ // level content to make sense.
+ public enum GameObjectType {
+ INVALID(-1),
+
+ PLAYER (0),
+
+ // Collectables
+ COIN (1),
+ RUBY (2),
+ DIARY (3),
+
+ // Characters
+ WANDA (10),
+ KYLE (11),
+ KYLE_DEAD (12),
+ ANDOU_DEAD (13),
+ KABOCHA (26),
+ ROKUDOU_TERMINAL (27),
+ KABOCHA_TERMINAL (28),
+ EVIL_KABOCHA (29),
+ ROKUDOU (30),
+
+ // AI
+ BROBOT (16),
+ SNAILBOMB (17),
+ SHADOWSLIME (18),
+ MUDMAN (19),
+ SKELETON (20),
+ KARAGUIN (21),
+ PINK_NAMAZU (22),
+ TURRET (23),
+ TURRET_LEFT (24),
+ BAT (6),
+ STING(7),
+ ONION(8),
+
+ // Objects
+ DOOR_RED (32),
+ DOOR_BLUE (33),
+ DOOR_GREEN (34),
+ BUTTON_RED (35),
+ BUTTON_BLUE (36),
+ BUTTON_GREEN (37),
+ CANNON (38),
+ BROBOT_SPAWNER (39),
+ BROBOT_SPAWNER_LEFT (40),
+ BREAKABLE_BLOCK(41),
+ THE_SOURCE(42),
+
+ // Effects
+ DUST(48),
+ EXPLOSION_SMALL(49),
+ EXPLOSION_LARGE(50),
+ EXPLOSION_GIANT(51),
+
+
+ // Special Spawnable
+ DOOR_RED_NONBLOCKING (52),
+ DOOR_BLUE_NONBLOCKING (53),
+ DOOR_GREEN_NONBLOCKING (54),
+
+ GHOST_NPC(55),
+
+ CAMERA_BIAS(56),
+
+ SMOKE_BIG(57),
+ SMOKE_SMALL(58),
+
+ CRUSH_FLASH(59),
+ FLASH(60),
+
+ // Projectiles
+ ENERGY_BALL(68),
+ CANNON_BALL(65),
+ TURRET_BULLET(66),
+ BROBOT_BULLET(67),
+ BREAKABLE_BLOCK_PIECE(68),
+ BREAKABLE_BLOCK_PIECE_SPAWNER(69),
+ WANDA_SHOT(70),
+
+ // Special Objects -- Not spawnable normally
+ PLAYER_JETS(-1),
+ PLAYER_SPARKS(-1),
+ PLAYER_GLOW(-1),
+ ENEMY_SPARKS(-1),
+ GHOST(-1),
+ SMOKE_POOF(-1),
+ GEM_EFFECT(-1),
+ GEM_EFFECT_SPAWNER(-1),
+
+
+ // End
+ OBJECT_COUNT(-1);
+
+ private final int mIndex;
+ GameObjectType(int index) {
+ this.mIndex = index;
+ }
+
+ public int index() {
+ return mIndex;
+ }
+
+ // TODO: Is there any better way to do this?
+ public static GameObjectType indexToType(int index) {
+ final GameObjectType[] valuesArray = values();
+ GameObjectType foundType = INVALID;
+ for (int x = 0; x < valuesArray.length; x++) {
+ GameObjectType type = valuesArray[x];
+ if (type.mIndex == index) {
+ foundType = type;
+ break;
+ }
+ }
+ return foundType;
+ }
+
+ }
+
+ public GameObjectFactory() {
+ super();
+
+ mGameObjectPool = new GameObjectPool(MAX_GAME_OBJECTS);
+
+ final int objectTypeCount = GameObjectType.OBJECT_COUNT.ordinal();
+ mStaticData = new FixedSizeArray>(objectTypeCount);
+
+ for (int x = 0; x < objectTypeCount; x++) {
+ mStaticData.add(null);
+ }
+
+ final ContextParameters context = sSystemRegistry.contextParameters;
+ final float halfHeight2 = (context.gameHeight * 0.5f) * (context.gameHeight * 0.5f);
+ final float halfWidth2 = (context.gameWidth * 0.5f) * (context.gameWidth * 0.5f);
+ final float screenSizeRadius = (float)Math.sqrt(halfHeight2 + halfWidth2);
+ mTightActivationRadius = screenSizeRadius + 128.0f;
+ mNormalActivationRadius = screenSizeRadius * 1.25f;
+ mWideActivationRadius = screenSizeRadius * 2.0f;
+ mAlwaysActive = -1.0f;
+
+ // TODO: I wish there was a way to do this automatically, but the ClassLoader doesn't seem
+ // to provide access to the currently loaded class list. There's some discussion of walking
+ // the actual class file objects and using forName() to instantiate them, but that sounds
+ // really heavy-weight. For now I'll rely on (sucky) manual enumeration.
+ class ComponentClass {
+ public Class> type;
+ public int poolSize;
+ public ComponentClass(Class> classType, int size) {
+ type = classType;
+ poolSize = size;
+ }
+ }
+ ComponentClass[] componentTypes = {
+ new ComponentClass(AnimationComponent.class, 1),
+ new ComponentClass(AttackAtDistanceComponent.class, 16),
+ new ComponentClass(BackgroundCollisionComponent.class, 128),
+ new ComponentClass(ButtonAnimationComponent.class, 32),
+ new ComponentClass(CameraBiasComponent.class, 8),
+ new ComponentClass(ChangeComponentsComponent.class, 128),
+ new ComponentClass(DoorAnimationComponent.class, 256), //!
+ new ComponentClass(DynamicCollisionComponent.class, 256),
+ new ComponentClass(EnemyAnimationComponent.class, 128),
+ new ComponentClass(FadeDrawableComponent.class, 32),
+ new ComponentClass(FixedAnimationComponent.class, 8),
+ new ComponentClass(GenericAnimationComponent.class, 32),
+ new ComponentClass(GhostComponent.class, 64),
+ new ComponentClass(GravityComponent.class, 128),
+ new ComponentClass(HitPlayerComponent.class, 256),
+ new ComponentClass(HitReactionComponent.class, 256),
+ new ComponentClass(InventoryComponent.class, 128),
+ new ComponentClass(LauncherComponent.class, 16),
+ new ComponentClass(LaunchProjectileComponent.class, 128),
+ new ComponentClass(LifetimeComponent.class, 256),
+ new ComponentClass(MotionBlurComponent.class, 1),
+ new ComponentClass(MovementComponent.class, 128),
+ new ComponentClass(NPCAnimationComponent.class, 8),
+ new ComponentClass(NPCComponent.class, 8),
+ new ComponentClass(OrbitalMagnetComponent.class, 1),
+ new ComponentClass(PatrolComponent.class, 128),
+ new ComponentClass(PhysicsComponent.class, 8),
+ new ComponentClass(PlayerComponent.class, 1),
+ new ComponentClass(PlaySingleSoundComponent.class, 32),
+ new ComponentClass(PopOutComponent.class, 32),
+ new ComponentClass(RenderComponent.class, 256),
+ new ComponentClass(ScrollerComponent.class, 8),
+ new ComponentClass(SelectDialogComponent.class, 8),
+ new ComponentClass(SimpleCollisionComponent.class, 32),
+ new ComponentClass(SimplePhysicsComponent.class, 128),
+ new ComponentClass(SleeperComponent.class, 32),
+ new ComponentClass(SolidSurfaceComponent.class, 16),
+ new ComponentClass(SpriteComponent.class, 256),
+ new ComponentClass(TheSourceComponent.class, 1),
+
+
+ };
+
+ mComponentPools = new FixedSizeArray(componentTypes.length, sComponentPoolComparator);
+ for (int x = 0; x < componentTypes.length; x++) {
+ ComponentClass component = componentTypes[x];
+ mComponentPools.add(new GameComponentPool(component.type, component.poolSize));
+ }
+ mComponentPools.sort(true);
+
+ mPoolSearchDummy = new GameComponentPool(Object.class, 1);
+
+ }
+
+ @Override
+ public void reset() {
+
+ }
+
+ protected GameComponentPool getComponentPool(Class> componentType) {
+ GameComponentPool pool = null;
+ mPoolSearchDummy.objectClass = componentType;
+ final int index = mComponentPools.find(mPoolSearchDummy, false);
+ if (index != -1) {
+ pool = mComponentPools.get(index);
+ }
+ return pool;
+ }
+
+ protected GameComponent allocateComponent(Class> componentType) {
+ GameComponentPool pool = getComponentPool(componentType);
+ assert pool != null;
+ GameComponent component = null;
+ if (pool != null) {
+ component = pool.allocate();
+ }
+ return component;
+ }
+
+ protected void releaseComponent(GameComponent component) {
+ GameComponentPool pool = getComponentPool(component.getClass());
+ assert pool != null;
+ if (pool != null) {
+ component.reset();
+ component.shared = false;
+ pool.release(component);
+ }
+ }
+
+ public void preloadEffects() {
+ // These textures appear in every level, so they are long-term.
+ TextureLibrary textureLibrary = sSystemRegistry.longTermTextureLibrary;
+ textureLibrary.allocateTexture(R.drawable.dust01);
+ textureLibrary.allocateTexture(R.drawable.dust02);
+ textureLibrary.allocateTexture(R.drawable.dust03);
+ textureLibrary.allocateTexture(R.drawable.dust04);
+ textureLibrary.allocateTexture(R.drawable.dust05);
+
+ textureLibrary.allocateTexture(R.drawable.effect_energyball01);
+ textureLibrary.allocateTexture(R.drawable.effect_energyball02);
+ textureLibrary.allocateTexture(R.drawable.effect_energyball03);
+ textureLibrary.allocateTexture(R.drawable.effect_energyball04);
+
+ textureLibrary.allocateTexture(R.drawable.effect_explosion_small01);
+ textureLibrary.allocateTexture(R.drawable.effect_explosion_small02);
+ textureLibrary.allocateTexture(R.drawable.effect_explosion_small03);
+ textureLibrary.allocateTexture(R.drawable.effect_explosion_small04);
+ textureLibrary.allocateTexture(R.drawable.effect_explosion_small05);
+ textureLibrary.allocateTexture(R.drawable.effect_explosion_small06);
+ textureLibrary.allocateTexture(R.drawable.effect_explosion_small07);
+
+ textureLibrary.allocateTexture(R.drawable.effect_explosion_big01);
+ textureLibrary.allocateTexture(R.drawable.effect_explosion_big02);
+ textureLibrary.allocateTexture(R.drawable.effect_explosion_big03);
+ textureLibrary.allocateTexture(R.drawable.effect_explosion_big04);
+ textureLibrary.allocateTexture(R.drawable.effect_explosion_big05);
+ textureLibrary.allocateTexture(R.drawable.effect_explosion_big06);
+ textureLibrary.allocateTexture(R.drawable.effect_explosion_big07);
+ textureLibrary.allocateTexture(R.drawable.effect_explosion_big08);
+ textureLibrary.allocateTexture(R.drawable.effect_explosion_big09);
+
+ textureLibrary.allocateTexture(R.drawable.effect_smoke_big01);
+ textureLibrary.allocateTexture(R.drawable.effect_smoke_big02);
+ textureLibrary.allocateTexture(R.drawable.effect_smoke_big03);
+ textureLibrary.allocateTexture(R.drawable.effect_smoke_big04);
+ textureLibrary.allocateTexture(R.drawable.effect_smoke_big05);
+
+ textureLibrary.allocateTexture(R.drawable.effect_smoke_small01);
+ textureLibrary.allocateTexture(R.drawable.effect_smoke_small02);
+ textureLibrary.allocateTexture(R.drawable.effect_smoke_small03);
+ textureLibrary.allocateTexture(R.drawable.effect_smoke_small04);
+ textureLibrary.allocateTexture(R.drawable.effect_smoke_small05);
+
+ textureLibrary.allocateTexture(R.drawable.effect_crush_back01);
+ textureLibrary.allocateTexture(R.drawable.effect_crush_back02);
+ textureLibrary.allocateTexture(R.drawable.effect_crush_back03);
+ textureLibrary.allocateTexture(R.drawable.effect_crush_front01);
+ textureLibrary.allocateTexture(R.drawable.effect_crush_front02);
+ textureLibrary.allocateTexture(R.drawable.effect_crush_front03);
+ textureLibrary.allocateTexture(R.drawable.effect_crush_front04);
+ textureLibrary.allocateTexture(R.drawable.effect_crush_front05);
+ textureLibrary.allocateTexture(R.drawable.effect_crush_front06);
+ textureLibrary.allocateTexture(R.drawable.effect_crush_front07);
+ }
+
+ public void destroy(GameObject object) {
+ object.commitUpdates();
+ final int componentCount = object.getCount();
+ for (int x = 0; x < componentCount; x++) {
+ GameComponent component = (GameComponent)object.get(x);
+ if (!component.shared) {
+ releaseComponent(component);
+ }
+ }
+ object.removeAll();
+ object.commitUpdates();
+ mGameObjectPool.release(object);
+ }
+
+ public GameObject spawn(GameObjectType type, float x, float y, boolean horzFlip) {
+ GameObject newObject = null;
+ switch(type) {
+ case PLAYER:
+ newObject = spawnPlayer(x, y);
+ break;
+ case COIN:
+ newObject = spawnCoin(x, y);
+ break;
+ case RUBY:
+ newObject = spawnRuby(x, y);
+ break;
+ case DIARY:
+ newObject = spawnDiary(x, y);
+ break;
+ case WANDA:
+ newObject = spawnEnemyWanda(x, y, true);
+ break;
+ case KYLE:
+ newObject = spawnEnemyKyle(x, y, true);
+ break;
+ case KYLE_DEAD:
+ newObject = spawnEnemyKyleDead(x, y);
+ break;
+ case ANDOU_DEAD:
+ newObject = spawnEnemyAndouDead(x, y);
+ break;
+ case KABOCHA:
+ newObject = spawnEnemyKabocha(x, y, true);
+ break;
+ case ROKUDOU_TERMINAL:
+ newObject = spawnRokudouTerminal(x, y);
+ break;
+ case KABOCHA_TERMINAL:
+ newObject = spawnKabochaTerminal(x, y);
+ break;
+ case EVIL_KABOCHA:
+ newObject = spawnEnemyEvilKabocha(x, y, true);
+ break;
+ case ROKUDOU:
+ newObject = spawnEnemyRokudou(x, y, true);
+ break;
+ case BROBOT:
+ newObject = spawnEnemyBrobot(x, y, horzFlip);
+ break;
+ case SNAILBOMB:
+ newObject = spawnEnemySnailBomb(x, y, horzFlip);
+ break;
+ case SHADOWSLIME:
+ newObject = spawnEnemyShadowSlime(x, y, horzFlip);
+ break;
+ case MUDMAN:
+ newObject = spawnEnemyMudman(x, y, horzFlip);
+ break;
+ case SKELETON:
+ newObject = spawnEnemySkeleton(x, y, horzFlip);
+ break;
+ case KARAGUIN:
+ newObject = spawnEnemyKaraguin(x, y, horzFlip);
+ break;
+ case PINK_NAMAZU:
+ newObject = spawnEnemyPinkNamazu(x, y, horzFlip);
+ break;
+ case BAT:
+ newObject = spawnEnemyBat(x, y, horzFlip);
+ break;
+ case STING:
+ newObject = spawnEnemySting(x, y, horzFlip);
+ break;
+ case ONION:
+ newObject = spawnEnemyOnion(x, y, horzFlip);
+ break;
+ case TURRET:
+ case TURRET_LEFT:
+ newObject = spawnObjectTurret(x, y, (type == GameObjectType.TURRET_LEFT));
+ break;
+ case DOOR_RED:
+ case DOOR_RED_NONBLOCKING:
+ newObject = spawnObjectDoor(x, y, GameObjectType.DOOR_RED, (type == GameObjectType.DOOR_RED));
+ break;
+ case DOOR_BLUE:
+ case DOOR_BLUE_NONBLOCKING:
+ newObject = spawnObjectDoor(x, y, GameObjectType.DOOR_BLUE, (type == GameObjectType.DOOR_BLUE));
+ break;
+ case DOOR_GREEN:
+ case DOOR_GREEN_NONBLOCKING:
+ newObject = spawnObjectDoor(x, y, GameObjectType.DOOR_GREEN, (type == GameObjectType.DOOR_GREEN));
+ break;
+ case BUTTON_RED:
+ newObject = spawnObjectButton(x, y, GameObjectType.BUTTON_RED);
+ break;
+ case BUTTON_BLUE:
+ newObject = spawnObjectButton(x, y, GameObjectType.BUTTON_BLUE);
+ break;
+ case BUTTON_GREEN:
+ newObject = spawnObjectButton(x, y, GameObjectType.BUTTON_GREEN);
+ break;
+ case CANNON:
+ newObject = spawnObjectCannon(x, y);
+ break;
+ case BROBOT_SPAWNER:
+ case BROBOT_SPAWNER_LEFT:
+ newObject = spawnObjectBrobotSpawner(x, y, (type == GameObjectType.BROBOT_SPAWNER_LEFT));
+ break;
+ case BREAKABLE_BLOCK:
+ newObject = spawnObjectBreakableBlock(x, y);
+ break;
+ case THE_SOURCE:
+ newObject = spawnObjectTheSource(x, y);
+ break;
+ case DUST:
+ newObject = spawnDust(x, y, horzFlip);
+ break;
+ case EXPLOSION_SMALL:
+ newObject = spawnEffectExplosionSmall(x, y);
+ break;
+ case EXPLOSION_LARGE:
+ newObject = spawnEffectExplosionLarge(x, y);
+ break;
+ case EXPLOSION_GIANT:
+ newObject = spawnEffectExplosionGiant(x, y);
+ break;
+ case GHOST_NPC:
+ newObject = spawnGhostNPC(x, y);
+ break;
+ case CAMERA_BIAS:
+ newObject = spawnCameraBias(x, y);
+ break;
+ case SMOKE_BIG:
+ newObject = spawnEffectSmokeBig(x, y);
+ break;
+ case SMOKE_SMALL:
+ newObject = spawnEffectSmokeSmall(x, y);
+ break;
+ case CRUSH_FLASH:
+ newObject = spawnEffectCrushFlash(x, y);
+ break;
+ case FLASH:
+ newObject = spawnEffectFlash(x, y);
+ break;
+ case ENERGY_BALL:
+ newObject = spawnEnergyBall(x, y, horzFlip);
+ break;
+ case CANNON_BALL:
+ newObject = spawnCannonBall(x, y, horzFlip);
+ break;
+ case TURRET_BULLET:
+ newObject = spawnTurretBullet(x, y, horzFlip);
+ break;
+ case BROBOT_BULLET:
+ newObject = spawnBrobotBullet(x, y, horzFlip);
+ break;
+ case BREAKABLE_BLOCK_PIECE:
+ newObject = spawnBreakableBlockPiece(x, y);
+ break;
+ case BREAKABLE_BLOCK_PIECE_SPAWNER:
+ newObject = spawnBreakableBlockPieceSpawner(x, y);
+ break;
+ case WANDA_SHOT:
+ newObject = spawnWandaShot(x, y, horzFlip);
+ break;
+ case SMOKE_POOF:
+ newObject = spawnSmokePoof(x, y);
+ break;
+ case GEM_EFFECT:
+ newObject = spawnGemEffect(x, y);
+ break;
+ case GEM_EFFECT_SPAWNER:
+ newObject = spawnGemEffectSpawner(x, y);
+ break;
+ }
+
+ return newObject;
+ }
+
+
+
+ public void spawnFromWorld(TiledWorld world, int tileWidth, int tileHeight) {
+ // Walk the world and spawn objects based on tile indexes.
+ final float worldHeight = world.getHeight() * tileHeight;
+ GameObjectManager manager = sSystemRegistry.gameObjectManager;
+ if (manager != null) {
+ for (int y = 0; y < world.getHeight(); y++) {
+ for (int x = 0; x < world.getWidth(); x++) {
+ int index = world.getTile(x, y);
+ if (index != -1) {
+ GameObjectType type = GameObjectType.indexToType(index);
+ if (type != GameObjectType.INVALID) {
+ final float worldX = x * tileWidth;
+ final float worldY = worldHeight - ((y + 1) * tileHeight);
+ GameObject object = spawn(type, worldX, worldY, false);
+ if (object != null) {
+ if (object.height < tileHeight) {
+ // make sure small objects are vertically centered in their
+ // tile.
+ object.getPosition().y += (tileHeight - object.height) / 2.0f;
+ }
+ if (object.width < tileWidth) {
+ object.getPosition().x += (tileWidth - object.width) / 2.0f;
+ } else if (object.width > tileWidth) {
+ object.getPosition().x -= (object.width - tileWidth) / 2.0f;
+ }
+ manager.add(object);
+ if (type == GameObjectType.PLAYER) {
+ manager.setPlayer(object);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ private FixedSizeArray getStaticData(GameObjectType type) {
+ return mStaticData.get(type.ordinal());
+ }
+
+ private void setStaticData(GameObjectType type, FixedSizeArray data) {
+ int index = type.ordinal();
+ assert mStaticData.get(index) == null;
+
+ final int staticDataCount = data.getCount();
+
+ for (int x = 0; x < staticDataCount; x++) {
+ BaseObject entry = data.get(x);
+ if (entry instanceof GameComponent) {
+ ((GameComponent) entry).shared = true;
+ }
+ }
+
+ mStaticData.set(index, data);
+ }
+
+ private void addStaticData(GameObjectType type, GameObject object, SpriteComponent sprite) {
+ FixedSizeArray staticData = getStaticData(type);
+ assert staticData != null;
+
+ if (staticData != null) {
+ final int staticDataCount = staticData.getCount();
+
+ for (int x = 0; x < staticDataCount; x++) {
+ BaseObject entry = staticData.get(x);
+ if (entry instanceof GameComponent && object != null) {
+ object.add((GameComponent)entry);
+ } else if (entry instanceof SpriteAnimation && sprite != null) {
+ sprite.addAnimation((SpriteAnimation)entry);
+ }
+ }
+ }
+ }
+
+ public void clearStaticData() {
+ final int typeCount = mStaticData.getCount();
+ for (int x = 0; x < typeCount; x++) {
+ FixedSizeArray staticData = mStaticData.get(x);
+ if (staticData != null) {
+ final int count = staticData.getCount();
+ for (int y = 0; y < count; y++) {
+ BaseObject entry = staticData.get(y);
+ if (entry != null) {
+ if (entry instanceof GameComponent) {
+ releaseComponent((GameComponent)entry);
+ }
+ }
+ }
+ staticData.clear();
+ mStaticData.set(x, null);
+ }
+ }
+ }
+
+ public void sanityCheckPools() {
+ final int outstandingObjects = mGameObjectPool.getAllocatedCount();
+ if (outstandingObjects != 0) {
+ DebugLog.d("Sanity Check", "Outstanding game object allocations! ("
+ + outstandingObjects + ")");
+ assert false;
+ }
+
+ final int componentPoolCount = mComponentPools.getCount();
+ for (int x = 0; x < componentPoolCount; x++) {
+ final int outstandingComponents = mComponentPools.get(x).getAllocatedCount();
+
+ if (outstandingComponents != 0) {
+ DebugLog.d("Sanity Check", "Outstanding "
+ + mComponentPools.get(x).objectClass.getSimpleName()
+ + " allocations! (" + outstandingComponents + ")");
+ //assert false;
+ }
+ }
+ }
+
+ public GameObject spawnPlayer(float positionX, float positionY) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mAlwaysActive;
+ object.width = 64;
+ object.height = 64;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.PLAYER);
+
+ if (staticData == null) {
+ final int staticObjectCount = 13;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ GameComponent gravity = allocateComponent(GravityComponent.class);
+ GameComponent movement = allocateComponent(MovementComponent.class);
+ PhysicsComponent physics = (PhysicsComponent)allocateComponent(PhysicsComponent.class);
+
+ physics.setMass(9.1f); // ~90kg w/ earth gravity
+ physics.setDynamicFrictionCoeffecient(0.2f);
+ physics.setStaticFrictionCoeffecient(0.01f);
+
+ // Animation Data
+ FixedSizeArray basicVulnerabilityVolume =
+ new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new SphereCollisionVolume(16, 32, 32));
+
+ FixedSizeArray pressAndCollectVolume =
+ new FixedSizeArray(2);
+ AABoxCollisionVolume collectionVolume = new AABoxCollisionVolume(16, 0, 32, 48);
+ collectionVolume.setHitType(HitType.COLLECT);
+ pressAndCollectVolume.add(collectionVolume);
+ AABoxCollisionVolume pressCollisionVolume = new AABoxCollisionVolume(16, 0, 32, 16);
+ pressCollisionVolume.setHitType(HitType.DEPRESS);
+ pressAndCollectVolume.add(pressCollisionVolume);
+
+ SpriteAnimation idle = new SpriteAnimation(PlayerAnimations.IDLE.ordinal(), 1);
+ idle.addFrame(new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_stand),
+ 1.0f, pressAndCollectVolume, basicVulnerabilityVolume));
+
+ SpriteAnimation angle = new SpriteAnimation(PlayerAnimations.MOVE.ordinal(), 1);
+ angle.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_diag01),
+ 0.0416f, pressAndCollectVolume, basicVulnerabilityVolume));
+
+ SpriteAnimation extremeAngle = new SpriteAnimation(
+ PlayerAnimations.MOVE_FAST.ordinal(), 1);
+ extremeAngle.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_diagmore01),
+ 0.0416f, pressAndCollectVolume, basicVulnerabilityVolume));
+
+ SpriteAnimation up = new SpriteAnimation(PlayerAnimations.BOOST_UP.ordinal(), 2);
+ up.addFrame(new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_flyup02),
+ Utils.framesToTime(24, 1), pressAndCollectVolume, basicVulnerabilityVolume));
+ up.addFrame(new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_flyup03),
+ Utils.framesToTime(24, 1), pressAndCollectVolume, basicVulnerabilityVolume));
+ up.setLoop(true);
+
+ SpriteAnimation boostAngle = new SpriteAnimation(PlayerAnimations.BOOST_MOVE.ordinal(), 2);
+ boostAngle.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_diag02),
+ Utils.framesToTime(24, 1), pressAndCollectVolume, basicVulnerabilityVolume));
+ boostAngle.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_diag03),
+ Utils.framesToTime(24, 1), pressAndCollectVolume, basicVulnerabilityVolume));
+ boostAngle.setLoop(true);
+
+ SpriteAnimation boostExtremeAngle = new SpriteAnimation(
+ PlayerAnimations.BOOST_MOVE_FAST.ordinal(), 2);
+ boostExtremeAngle.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_diagmore02),
+ Utils.framesToTime(24, 1), pressAndCollectVolume, basicVulnerabilityVolume));
+ boostExtremeAngle.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_diagmore03),
+ Utils.framesToTime(24, 1), pressAndCollectVolume, basicVulnerabilityVolume));
+ boostExtremeAngle.setLoop(true);
+
+ FixedSizeArray stompAttackVolume =
+ new FixedSizeArray(3);
+ stompAttackVolume.add(new AABoxCollisionVolume(16, -5.0f, 32, 37, HitType.HIT));
+ stompAttackVolume.add(pressCollisionVolume);
+ stompAttackVolume.add(collectionVolume);
+
+ SpriteAnimation stomp = new SpriteAnimation(PlayerAnimations.STOMP.ordinal(), 4);
+ stomp.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_stomp01),
+ Utils.framesToTime(24, 1), stompAttackVolume, null));
+ stomp.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_stomp02),
+ Utils.framesToTime(24, 1), stompAttackVolume, null));
+ stomp.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_stomp03),
+ Utils.framesToTime(24, 1), stompAttackVolume, null));
+ stomp.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_stomp04),
+ Utils.framesToTime(24, 1), stompAttackVolume, null));
+
+ SpriteAnimation hitReactAnim = new SpriteAnimation(PlayerAnimations.HIT_REACT.ordinal(), 1);
+ hitReactAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_hit),
+ 0.1f, pressAndCollectVolume, null));
+
+ SpriteAnimation deathAnim = new SpriteAnimation(PlayerAnimations.DEATH.ordinal(), 16);
+ AnimationFrame death1 =
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_die01),
+ Utils.framesToTime(24, 1), null, null);
+ AnimationFrame death2 =
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_die02),
+ Utils.framesToTime(24, 1), null, null);
+ deathAnim.addFrame(death1);
+ deathAnim.addFrame(death2);
+ deathAnim.addFrame(death1);
+ deathAnim.addFrame(death2);
+ deathAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_explode01),
+ Utils.framesToTime(24, 1), null, null));
+ deathAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_explode02),
+ Utils.framesToTime(24, 1), null, null));
+ deathAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_explode03),
+ Utils.framesToTime(24, 1), null, null));
+ deathAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_explode04),
+ Utils.framesToTime(24, 1), null, null));
+ deathAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_explode05),
+ Utils.framesToTime(24, 2), null, null));
+ deathAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_explode06),
+ Utils.framesToTime(24, 2), null, null));
+ deathAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_explode07),
+ Utils.framesToTime(24, 2), null, null));
+ deathAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_explode08),
+ Utils.framesToTime(24, 2), null, null));
+ deathAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_explode09),
+ Utils.framesToTime(24, 2), null, null));
+ deathAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_explode10),
+ Utils.framesToTime(24, 2), null, null));
+ deathAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_explode11),
+ Utils.framesToTime(24, 2), null, null));
+ deathAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_explode12),
+ Utils.framesToTime(24, 2), null, null));
+
+
+ SpriteAnimation frozenAnim = new SpriteAnimation(PlayerAnimations.FROZEN.ordinal(), 1);
+ // Frozen has no frames!
+
+
+ // Save static data
+ staticData.add(gravity);
+ staticData.add(movement);
+ staticData.add(physics);
+
+
+ staticData.add(idle);
+ staticData.add(angle);
+ staticData.add(extremeAngle);
+ staticData.add(up);
+ staticData.add(boostAngle);
+ staticData.add(boostExtremeAngle);
+ staticData.add(stomp);
+ staticData.add(hitReactAnim);
+ staticData.add(deathAnim);
+ staticData.add(frozenAnim);
+
+ setStaticData(GameObjectType.PLAYER, staticData);
+ }
+
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.PLAYER);
+ BackgroundCollisionComponent bgcollision
+ = (BackgroundCollisionComponent)allocateComponent(BackgroundCollisionComponent.class);
+ bgcollision.setSize(32, 48);
+ bgcollision.setOffset(16, 0);
+ PlayerComponent player = (PlayerComponent)allocateComponent(PlayerComponent.class);
+ AnimationComponent animation =
+ (AnimationComponent)allocateComponent(AnimationComponent.class);
+
+ animation.setPlayer(player);
+ SoundSystem sound = sSystemRegistry.soundSystem;
+ if (sound != null) {
+ animation.setLandThump(sound.load(R.raw.thump));
+ animation.setRocketSound(sound.load(R.raw.rockets));
+ animation.setRubySounds(sound.load(R.raw.gem1), sound.load(R.raw.gem2), sound.load(R.raw.gem3));
+ animation.setExplosionSound(sound.load(R.raw.sound_explode));
+ }
+
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+ animation.setSprite(sprite);
+
+
+
+ DynamicCollisionComponent dynamicCollision
+ = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(dynamicCollision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ hitReact.setBounceOnHit(true);
+ hitReact.setPauseOnAttack(true);
+ hitReact.setInvincibleTime(3.0f);
+ hitReact.setSpawnOnDealHit(HitType.HIT, GameObjectType.CRUSH_FLASH, false, true);
+
+ if (sound != null) {
+ hitReact.setTakeHitSound(HitType.HIT, sound.load(R.raw.deep_clang));
+ }
+
+ dynamicCollision.setHitReactionComponent(hitReact);
+
+ player.setHitReactionComponent(hitReact);
+
+ InventoryComponent inventory = (InventoryComponent)allocateComponent(InventoryComponent.class);
+
+ player.setInventory(inventory);
+ animation.setInventory(inventory);
+
+ ChangeComponentsComponent damageSwap = (ChangeComponentsComponent)allocateComponent(ChangeComponentsComponent.class);
+ animation.setDamageSwap(damageSwap);
+
+ LaunchProjectileComponent smokeGun
+ = (LaunchProjectileComponent)allocateComponent(LaunchProjectileComponent.class);
+ smokeGun.setDelayBetweenShots(0.25f);
+ smokeGun.setObjectTypeToSpawn(GameObjectType.SMOKE_BIG);
+ smokeGun.setOffsetX(32);
+ smokeGun.setOffsetY(15);
+ smokeGun.setVelocityX(-150.0f);
+ smokeGun.setVelocityY(100.0f);
+ smokeGun.setThetaError(0.1f);
+
+ LaunchProjectileComponent smokeGun2
+ = (LaunchProjectileComponent)allocateComponent(LaunchProjectileComponent.class);
+ smokeGun2.setDelayBetweenShots(0.35f);
+ smokeGun2.setObjectTypeToSpawn(GameObjectType.SMOKE_SMALL);
+ smokeGun2.setOffsetX(16);
+ smokeGun2.setOffsetY(15);
+ smokeGun2.setVelocityX(-150.0f);
+ smokeGun2.setVelocityY(150.0f);
+ smokeGun2.setThetaError(0.1f);
+
+ damageSwap.addSwapInComponent(smokeGun);
+ damageSwap.addSwapInComponent(smokeGun2);
+ damageSwap.setPingPongBehavior(true);
+
+ ChangeComponentsComponent invincibleSwap = (ChangeComponentsComponent)allocateComponent(ChangeComponentsComponent.class);
+ invincibleSwap.setPingPongBehavior(true);
+ player.setInvincibleSwap(invincibleSwap);
+
+ object.life = PlayerComponent.MAX_PLAYER_LIFE;
+ object.team = Team.PLAYER;
+
+ // Very very basic DDA. Make the game easier if we've died on this level too much.
+ LevelSystem level = sSystemRegistry.levelSystem;
+ if (level != null) {
+ player.adjustDifficulty(object, level.getAttemptsCount());
+ }
+
+
+ object.add(player);
+ object.add(inventory);
+ object.add(bgcollision);
+ object.add(render);
+ object.add(animation);
+ object.add(sprite);
+ object.add(dynamicCollision);
+ object.add(hitReact);
+ object.add(damageSwap);
+ object.add(invincibleSwap);
+
+ addStaticData(GameObjectType.PLAYER, object, sprite);
+
+
+
+ sprite.playAnimation(PlayerAnimations.IDLE.ordinal());
+
+
+ // Jets
+ {
+ FixedSizeArray jetStaticData = getStaticData(GameObjectType.PLAYER_JETS);
+ if (jetStaticData == null) {
+ jetStaticData = new FixedSizeArray(1);
+
+ SpriteAnimation jetAnim = new SpriteAnimation(0, 2);
+ jetAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.jetfire01),
+ Utils.framesToTime(24, 1)));
+ jetAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.jetfire02),
+ Utils.framesToTime(24, 1)));
+ jetAnim.setLoop(true);
+
+ jetStaticData.add(jetAnim);
+
+ setStaticData(GameObjectType.PLAYER_JETS, jetStaticData);
+ }
+
+ RenderComponent jetRender = (RenderComponent)allocateComponent(RenderComponent.class);
+ jetRender.setPriority(SortConstants.PLAYER - 1);
+ jetRender.setDrawOffset(0.0f, -16.0f);
+ SpriteComponent jetSprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ jetSprite.setSize(64, 64);
+ jetSprite.setRenderComponent(jetRender);
+
+ object.add(jetRender);
+ object.add(jetSprite);
+
+ addStaticData(GameObjectType.PLAYER_JETS, object, jetSprite);
+
+ jetSprite.playAnimation(0);
+
+ animation.setJetSprite(jetSprite);
+ }
+ // Sparks
+ {
+ FixedSizeArray sparksStaticData = getStaticData(GameObjectType.PLAYER_SPARKS);
+
+ if (sparksStaticData == null) {
+ sparksStaticData = new FixedSizeArray(1);
+
+ SpriteAnimation sparksAnim = new SpriteAnimation(0, 3);
+ sparksAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.spark01),
+ Utils.framesToTime(24, 1)));
+ sparksAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.spark02),
+ Utils.framesToTime(24, 1)));
+ sparksAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.spark03),
+ Utils.framesToTime(24, 1)));
+ sparksAnim.setLoop(true);
+
+ sparksStaticData.add(sparksAnim);
+
+ setStaticData(GameObjectType.PLAYER_SPARKS, sparksStaticData);
+ }
+
+ RenderComponent sparksRender = (RenderComponent)allocateComponent(RenderComponent.class);
+ sparksRender.setPriority(SortConstants.PLAYER + 1);
+ SpriteComponent sparksSprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sparksSprite.setSize(64, 64);
+ sparksSprite.setRenderComponent(sparksRender);
+
+ object.add(sparksRender);
+ object.add(sparksSprite);
+
+ addStaticData(GameObjectType.PLAYER_SPARKS, object, sparksSprite);
+
+ sparksSprite.playAnimation(0);
+
+ animation.setSparksSprite(sparksSprite);
+ }
+
+ // Glow
+ {
+ FixedSizeArray glowStaticData = getStaticData(GameObjectType.PLAYER_GLOW);
+ if (glowStaticData == null) {
+ glowStaticData = new FixedSizeArray(1);
+
+ FixedSizeArray glowAttackVolume =
+ new FixedSizeArray(1);
+ glowAttackVolume.add(new SphereCollisionVolume(40, 40, 40, HitType.HIT));
+
+ SpriteAnimation glowAnim = new SpriteAnimation(0, 3);
+ glowAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.effect_glow01),
+ Utils.framesToTime(24, 1), glowAttackVolume, null));
+ glowAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.effect_glow02),
+ Utils.framesToTime(24, 1), glowAttackVolume, null));
+ glowAnim.addFrame(
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.effect_glow03),
+ Utils.framesToTime(24, 1), glowAttackVolume, null));
+ glowAnim.setLoop(true);
+
+ glowStaticData.add(glowAnim);
+
+ setStaticData(GameObjectType.PLAYER_GLOW, glowStaticData);
+ }
+
+ RenderComponent glowRender = (RenderComponent)allocateComponent(RenderComponent.class);
+ glowRender.setPriority(SortConstants.PLAYER + 1);
+ glowRender.setDrawOffset(0, -5.0f);
+ SpriteComponent glowSprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ glowSprite.setSize(64, 64);
+ glowSprite.setRenderComponent(glowRender);
+
+ DynamicCollisionComponent glowCollision
+ = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ glowSprite.setCollisionComponent(glowCollision);
+
+ FadeDrawableComponent glowFade = (FadeDrawableComponent)allocateComponent(FadeDrawableComponent.class);
+ glowFade.setupFade(1.0f, 0.0f, 0.15f,
+ FadeDrawableComponent.LOOP_TYPE_PING_PONG,
+ FadeDrawableComponent.FADE_EASE,
+ PlayerComponent.GLOW_DURATION - 4.0f); // 4 seconds before the glow ends, start flashing
+ glowFade.setPhaseDuration(PlayerComponent.GLOW_DURATION);
+ glowFade.setRenderComponent(glowRender);
+
+ invincibleSwap.addSwapInComponent(glowRender);
+ invincibleSwap.addSwapInComponent(glowSprite);
+ invincibleSwap.addSwapInComponent(glowCollision);
+ invincibleSwap.addSwapInComponent(glowFade);
+
+ addStaticData(GameObjectType.PLAYER_GLOW, object, glowSprite);
+
+ glowSprite.playAnimation(0);
+
+ }
+
+ CameraSystem camera = sSystemRegistry.cameraSystem;
+ if (camera != null) {
+ camera.setTarget(object);
+ }
+
+ return object;
+ }
+
+
+ // Sparks are used by more than one enemy type, so the setup for them is abstracted.
+ private void setupEnemySparks() {
+ FixedSizeArray staticData = getStaticData(GameObjectType.ENEMY_SPARKS);
+ if (staticData == null) {
+ staticData = new FixedSizeArray(1);
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+ SpriteAnimation sparksAnim = new SpriteAnimation(0, 13);
+ AnimationFrame frame1 =
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.spark01),
+ Utils.framesToTime(24, 1));
+ AnimationFrame frame2 =
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.spark02),
+ Utils.framesToTime(24, 1));
+ AnimationFrame frame3 =
+ new AnimationFrame(textureLibrary.allocateTexture(R.drawable.spark03),
+ Utils.framesToTime(24, 1));
+ sparksAnim.addFrame(frame1);
+ sparksAnim.addFrame(frame2);
+ sparksAnim.addFrame(frame3);
+ sparksAnim.addFrame(frame1);
+ sparksAnim.addFrame(frame2);
+ sparksAnim.addFrame(frame3);
+ sparksAnim.addFrame(frame1);
+ sparksAnim.addFrame(frame2);
+ sparksAnim.addFrame(frame3);
+ sparksAnim.addFrame(frame1);
+ sparksAnim.addFrame(frame2);
+ sparksAnim.addFrame(frame3);
+ sparksAnim.addFrame(new AnimationFrame(null, 3.0f));
+ sparksAnim.setLoop(true);
+
+ staticData.add(sparksAnim);
+ setStaticData(GameObjectType.ENEMY_SPARKS, staticData);
+ }
+
+ }
+
+ public GameObject spawnEnemyBrobot(float positionX, float positionY, boolean flipHorizontal) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mNormalActivationRadius;
+ object.width = 64;
+ object.height = 64;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.BROBOT);
+ if (staticData == null) {
+ final int staticObjectCount = 5;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ GameComponent gravity = allocateComponent(GravityComponent.class);
+ GameComponent movement = allocateComponent(MovementComponent.class);
+ SimplePhysicsComponent physics = (SimplePhysicsComponent)allocateComponent(SimplePhysicsComponent.class);
+ physics.setBounciness(0.4f);
+
+
+ // Animations
+ FixedSizeArray basicVulnerabilityVolume =
+ new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new SphereCollisionVolume(16, 32, 32));
+
+ FixedSizeArray basicAttackVolume =
+ new FixedSizeArray(2);
+ basicAttackVolume.add(new SphereCollisionVolume(16, 32, 32, HitType.HIT));
+ basicAttackVolume.add(new AABoxCollisionVolume(16, 0, 32, 16, HitType.DEPRESS));
+
+ SpriteAnimation idle = new SpriteAnimation(EnemyAnimations.IDLE.ordinal(), 4);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_brobot_idle01),
+ Utils.framesToTime(24, 3), basicAttackVolume, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_brobot_idle02),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_brobot_idle03),
+ Utils.framesToTime(24, 3), basicAttackVolume, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_brobot_idle02),
+ Utils.framesToTime(24, 3), basicAttackVolume, basicVulnerabilityVolume));
+
+ idle.setLoop(true);
+
+ SpriteAnimation walk = new SpriteAnimation(EnemyAnimations.MOVE.ordinal(), 3);
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_brobot_walk01),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume));
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_brobot_walk02),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume));
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_brobot_walk03),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume));
+ walk.setLoop(true);
+
+ staticData.add(gravity);
+ staticData.add(movement);
+ staticData.add(physics);
+ staticData.add(idle);
+ staticData.add(walk);
+
+ setStaticData(GameObjectType.BROBOT, staticData);
+
+ }
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_ENEMY);
+ BackgroundCollisionComponent bgcollision
+ = (BackgroundCollisionComponent)allocateComponent(BackgroundCollisionComponent.class);
+ bgcollision.setSize(32, 48);
+ bgcollision.setOffset(16, 0);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ EnemyAnimationComponent animation
+ = (EnemyAnimationComponent)allocateComponent(EnemyAnimationComponent.class);
+ animation.setSprite(sprite);
+
+ PatrolComponent patrol = (PatrolComponent)allocateComponent(PatrolComponent.class);
+ patrol.setMovementSpeed(50.0f, 1000.0f);
+
+ DynamicCollisionComponent collision
+ = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(collision);
+
+ HitReactionComponent hitReact
+ = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ collision.setHitReactionComponent(hitReact);
+
+
+ LifetimeComponent lifetime = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+ lifetime.setObjectToSpawnOnDeath(GameObjectType.EXPLOSION_GIANT);
+ lifetime.setVulnerableToDeathTiles(true);
+
+ GhostComponent ghost = (GhostComponent)allocateComponent(GhostComponent.class);
+ ghost.setMovementSpeed(500.0f);
+ ghost.setAcceleration(1000.0f);
+ ghost.setJumpImpulse(300.0f);
+ ghost.setKillOnRelease(true);
+ ghost.setDelayOnRelease(1.5f);
+
+ SoundSystem sound = BaseObject.sSystemRegistry.soundSystem;
+ if (sound != null) {
+ ghost.setAmbientSound(sound.load(R.raw.sound_possession));
+ }
+
+ ChangeComponentsComponent ghostSwap
+ = (ChangeComponentsComponent)allocateComponent(ChangeComponentsComponent.class);
+ ghostSwap.addSwapInComponent(ghost);
+ ghostSwap.addSwapOutComponent(patrol);
+
+ SimplePhysicsComponent ghostPhysics = (SimplePhysicsComponent)allocateComponent(SimplePhysicsComponent.class);
+ ghostPhysics.setBounciness(0.0f);
+
+ object.add(render);
+ object.add(sprite);
+
+ object.add(bgcollision);
+ object.add(animation);
+ object.add(patrol);
+ object.add(collision);
+ object.add(hitReact);
+ object.add(lifetime);
+ object.add(ghostSwap);
+
+ object.team = Team.ENEMY;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+
+ addStaticData(GameObjectType.BROBOT, object, sprite);
+
+ object.commitUpdates();
+
+ SimplePhysicsComponent normalPhysics = object.findByClass(SimplePhysicsComponent.class);
+ if (normalPhysics != null) {
+ ghostSwap.addSwapOutComponent(normalPhysics);
+ }
+
+ ghostSwap.addSwapInComponent(ghostPhysics);
+
+ sprite.playAnimation(0);
+
+ // Sparks
+ setupEnemySparks();
+
+ RenderComponent sparksRender = (RenderComponent)allocateComponent(RenderComponent.class);
+ sparksRender.setPriority(render.getPriority() + 1);
+ SpriteComponent sparksSprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sparksSprite.setSize(64, 64);
+ sparksSprite.setRenderComponent(sparksRender);
+
+ addStaticData(GameObjectType.ENEMY_SPARKS, object, sparksSprite);
+
+ sparksSprite.playAnimation(0);
+
+ ghostSwap.addSwapInComponent(sparksSprite);
+ ghostSwap.addSwapInComponent(sparksRender);
+
+
+ hitReact.setPossessionComponent(ghostSwap);
+
+ return object;
+ }
+
+ public GameObject spawnEnemySnailBomb(float positionX, float positionY, boolean flipHorizontal) {
+
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ // Make sure related textures are loaded.
+ textureLibrary.allocateTexture(R.drawable.snail_bomb);
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mNormalActivationRadius;
+ object.width = 64;
+ object.height = 64;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.SNAILBOMB);
+ if (staticData == null) {
+ final int staticObjectCount = 6;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ GameComponent gravity = allocateComponent(GravityComponent.class);
+ GameComponent movement = allocateComponent(MovementComponent.class);
+ GameComponent physics = allocateComponent(SimplePhysicsComponent.class);
+
+ // Animations
+ FixedSizeArray basicVulnerabilityVolume =
+ new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new AABoxCollisionVolume(12, 5, 42, 27, HitType.HIT));
+
+ FixedSizeArray basicAttackVolume =
+ new FixedSizeArray(1);
+ basicAttackVolume.add(new AABoxCollisionVolume(12, 5, 42, 27, HitType.HIT));
+
+ SpriteAnimation idle = new SpriteAnimation(EnemyAnimations.IDLE.ordinal(), 1);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.snailbomb_stand),
+ Utils.framesToTime(24, 3), basicAttackVolume, basicVulnerabilityVolume));
+
+ SpriteAnimation walk = new SpriteAnimation(EnemyAnimations.MOVE.ordinal(), 5);
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.snailbomb_stand),
+ Utils.framesToTime(24, 2), basicAttackVolume, basicVulnerabilityVolume));
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.snailbomb_walk01),
+ Utils.framesToTime(24, 2), basicAttackVolume, basicVulnerabilityVolume));
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.snailbomb_walk02),
+ Utils.framesToTime(24, 6), basicAttackVolume, basicVulnerabilityVolume));
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.snailbomb_walk01),
+ Utils.framesToTime(24, 2), basicAttackVolume, basicVulnerabilityVolume));
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.snailbomb_stand),
+ Utils.framesToTime(24, 2), basicAttackVolume, basicVulnerabilityVolume));
+ walk.setLoop(true);
+
+ SpriteAnimation attack = new SpriteAnimation(EnemyAnimations.ATTACK.ordinal(), 2);
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.snailbomb_shoot01),
+ Utils.framesToTime(24, 3), basicAttackVolume, basicVulnerabilityVolume));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.snailbomb_shoot02),
+ Utils.framesToTime(24, 2), basicAttackVolume, basicVulnerabilityVolume));
+
+ staticData.add(gravity);
+ staticData.add(movement);
+ staticData.add(physics);
+ staticData.add(idle);
+ staticData.add(walk);
+ staticData.add(attack);
+
+
+ setStaticData(GameObjectType.SNAILBOMB, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_ENEMY);
+ BackgroundCollisionComponent bgcollision
+ = (BackgroundCollisionComponent)allocateComponent(BackgroundCollisionComponent.class);
+ bgcollision.setSize(32, 48);
+ bgcollision.setOffset(16, 5);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ EnemyAnimationComponent animation
+ = (EnemyAnimationComponent)allocateComponent(EnemyAnimationComponent.class);
+ animation.setSprite(sprite);
+
+ PatrolComponent patrol = (PatrolComponent)allocateComponent(PatrolComponent.class);
+ patrol.setMovementSpeed(20.0f, 1000.0f);
+ patrol.setupAttack(300, 1.0f, 4.0f, true);
+
+ DynamicCollisionComponent collision
+ = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(collision);
+
+ HitReactionComponent hitReact
+ = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ collision.setHitReactionComponent(hitReact);
+
+ LifetimeComponent lifetime = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+ lifetime.setVulnerableToDeathTiles(true);
+ lifetime.setObjectToSpawnOnDeath(GameObjectType.SMOKE_POOF);
+ SoundSystem sound = BaseObject.sSystemRegistry.soundSystem;
+ if (sound != null) {
+ lifetime.setDeathSound(sound.load(R.raw.sound_stomp));
+ }
+
+ LaunchProjectileComponent gun
+ = (LaunchProjectileComponent)allocateComponent(LaunchProjectileComponent.class);
+ gun.setSetsPerActivation(1);
+ gun.setShotsPerSet(3);
+ gun.setDelayBeforeFirstSet(1.0f);
+ gun.setDelayBetweenShots(0.25f);
+ gun.setObjectTypeToSpawn(GameObjectType.CANNON_BALL);
+ gun.setOffsetX(55);
+ gun.setOffsetY(21);
+ gun.setRequiredAction(GameObject.ActionType.ATTACK);
+ gun.setVelocityX(100.0f);
+
+ object.team = Team.ENEMY;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+
+ object.add(render);
+ object.add(sprite);
+ object.add(bgcollision);
+ object.add(animation);
+ object.add(patrol);
+ object.add(collision);
+ object.add(hitReact);
+ object.add(lifetime);
+ object.add(gun);
+
+ addStaticData(GameObjectType.SNAILBOMB, object, sprite);
+
+ final SpriteAnimation attack = sprite.findAnimation(EnemyAnimations.ATTACK.ordinal());
+ if (attack != null) {
+ gun.setDelayBeforeFirstSet(attack.getLength());
+ }
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnEnemyShadowSlime(float positionX, float positionY, boolean flipHorizontal) {
+
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ // Make sure related textures are loaded.
+ textureLibrary.allocateTexture(R.drawable.energy_ball01);
+ textureLibrary.allocateTexture(R.drawable.energy_ball02);
+ textureLibrary.allocateTexture(R.drawable.energy_ball03);
+ textureLibrary.allocateTexture(R.drawable.energy_ball04);
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 64;
+ object.height = 64;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.SHADOWSLIME);
+ if (staticData == null) {
+ final int staticObjectCount = 5;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ PopOutComponent popOut = (PopOutComponent)allocateComponent(PopOutComponent.class);
+ popOut.setAppearDistance(150);
+ popOut.setHideDistance(190);
+
+ FixedSizeArray basicVulnerabilityVolume = new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new SphereCollisionVolume(16, 32, 32));
+ basicVulnerabilityVolume.get(0).setHitType(HitType.HIT);
+
+ FixedSizeArray basicAttackVolume = new FixedSizeArray(1);
+ basicAttackVolume.add(new SphereCollisionVolume(16, 32, 32, HitType.HIT));
+
+ SpriteAnimation idle = new SpriteAnimation(EnemyAnimations.IDLE.ordinal(), 2);
+ AnimationFrame idle1 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_shadowslime_idle01),
+ Utils.framesToTime(24, 3), basicAttackVolume, basicVulnerabilityVolume);
+ AnimationFrame idle2 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_shadowslime_idle02),
+ Utils.framesToTime(24, 3), basicAttackVolume, basicVulnerabilityVolume);
+ idle.addFrame(idle1);
+ idle.addFrame(idle2);
+ idle.setLoop(true);
+
+
+ SpriteAnimation appear = new SpriteAnimation(EnemyAnimations.APPEAR.ordinal(), 6);
+ AnimationFrame appear1 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_shadowslime_activate01),
+ Utils.framesToTime(24, 2), basicAttackVolume, basicVulnerabilityVolume);
+
+ AnimationFrame appear2 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_shadowslime_activate02),
+ Utils.framesToTime(24, 2), basicAttackVolume, basicVulnerabilityVolume);
+ AnimationFrame appear3 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_shadowslime_activate03),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume);
+ AnimationFrame appear4 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_shadowslime_activate04),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume);
+ AnimationFrame appear5 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_shadowslime_activate05),
+ Utils.framesToTime(24, 2), basicAttackVolume, basicVulnerabilityVolume);
+ AnimationFrame appear6 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_shadowslime_activate06),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume);
+
+ appear.addFrame(appear1);
+ appear.addFrame(appear2);
+ appear.addFrame(appear3);
+ appear.addFrame(appear4);
+ appear.addFrame(appear5);
+ appear.addFrame(appear6);
+
+ SpriteAnimation hidden = new SpriteAnimation(EnemyAnimations.HIDDEN.ordinal(), 6);
+ hidden.addFrame(appear6);
+ hidden.addFrame(appear5);
+ hidden.addFrame(appear4);
+ hidden.addFrame(appear3);
+ hidden.addFrame(appear2);
+ hidden.addFrame(appear1);
+ /*hidden.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_shadowslime_stand),
+ Utils.framesToTime(24, 3), basicAttackVolume, basicVulnerabilityVolume));*/
+
+
+ SpriteAnimation attack = new SpriteAnimation(EnemyAnimations.ATTACK.ordinal(), 10);
+ AnimationFrame attack1 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_shadowslime_attack01),
+ Utils.framesToTime(24, 2), basicAttackVolume, basicVulnerabilityVolume);
+ AnimationFrame attack2 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_shadowslime_attack02),
+ Utils.framesToTime(24, 2), basicAttackVolume, basicVulnerabilityVolume);
+ AnimationFrame attack3 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_shadowslime_attack03),
+ Utils.framesToTime(24, 2), basicAttackVolume, basicVulnerabilityVolume);
+ AnimationFrame attack4 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_shadowslime_attack04),
+ Utils.framesToTime(24, 6), basicAttackVolume, basicVulnerabilityVolume);
+ AnimationFrame attackFlash = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_shadowslime_flash),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume);
+
+ AnimationFrame attack5 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_shadowslime_attack03),
+ Utils.framesToTime(24, 3), basicAttackVolume, basicVulnerabilityVolume);
+ AnimationFrame attack6 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_shadowslime_attack02),
+ Utils.framesToTime(24, 3), basicAttackVolume, basicVulnerabilityVolume);
+
+ AnimationFrame attack7 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_shadowslime_attack04),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume);
+
+ attack.addFrame(attack1);
+ attack.addFrame(attack2);
+ attack.addFrame(attack3);
+ attack.addFrame(attack4);
+ attack.addFrame(attackFlash);
+ attack.addFrame(attack7);
+ attack.addFrame(attackFlash);
+ attack.addFrame(attack5);
+ attack.addFrame(attack6);
+ attack.addFrame(attack1);
+
+ popOut.setupAttack(200, 2.0f, attack.getLength());
+
+
+ staticData.add(popOut);
+ staticData.add(idle);
+ staticData.add(hidden);
+ staticData.add(appear);
+ staticData.add(attack);
+
+ setStaticData(GameObjectType.SHADOWSLIME, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_ENEMY);
+ BackgroundCollisionComponent bgcollision
+ = (BackgroundCollisionComponent)allocateComponent(BackgroundCollisionComponent.class);
+ bgcollision.setSize(32, 48);
+ bgcollision.setOffset(16, 5);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+
+ sprite.playAnimation(0);
+
+ EnemyAnimationComponent animation
+ = (EnemyAnimationComponent)allocateComponent(EnemyAnimationComponent.class);
+ animation.setSprite(sprite);
+ animation.setFacePlayer(true);
+
+
+ DynamicCollisionComponent collision
+ = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(collision);
+
+ HitReactionComponent hitReact
+ = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ collision.setHitReactionComponent(hitReact);
+
+ LifetimeComponent lifetime = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+ lifetime.setObjectToSpawnOnDeath(GameObjectType.SMOKE_POOF);
+ SoundSystem sound = BaseObject.sSystemRegistry.soundSystem;
+ if (sound != null) {
+ lifetime.setDeathSound(sound.load(R.raw.sound_stomp));
+ }
+
+ LaunchProjectileComponent gun
+ = (LaunchProjectileComponent)allocateComponent(LaunchProjectileComponent.class);
+
+
+ gun.setShotsPerSet(1);
+ gun.setSetsPerActivation(1);
+ gun.setObjectTypeToSpawn(GameObjectType.ENERGY_BALL);
+ gun.setOffsetX(44);
+ gun.setOffsetY(22);
+ gun.setRequiredAction(GameObject.ActionType.ATTACK);
+ gun.setVelocityX(30.0f);
+
+ object.team = Team.ENEMY;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+
+ // Hack. Adjusting position lets us avoid giving this character gravity, physics, and
+ // collision.
+
+ object.getPosition().y -= 5;
+
+ object.add(render);
+ object.add(sprite);
+ object.add(bgcollision);
+ object.add(animation);
+ object.add(collision);
+ object.add(hitReact);
+ object.add(lifetime);
+ object.add(gun);
+
+ addStaticData(GameObjectType.SHADOWSLIME, object, sprite);
+
+ final SpriteAnimation attack = sprite.findAnimation(EnemyAnimations.ATTACK.ordinal());
+ final SpriteAnimation appear = sprite.findAnimation(EnemyAnimations.APPEAR.ordinal());
+ if (attack != null && appear != null) {
+ gun.setDelayBeforeFirstSet(attack.getLength() / 2.0f);
+ } else {
+ gun.setDelayBeforeFirstSet(Utils.framesToTime(24, 12));
+ }
+
+ return object;
+ }
+
+ public GameObject spawnEnemyMudman(float positionX, float positionY, boolean flipHorizontal) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mNormalActivationRadius;
+ object.width = 128;
+ object.height = 128;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.MUDMAN);
+ if (staticData == null) {
+ final int staticObjectCount = 7;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ GameComponent gravity = allocateComponent(GravityComponent.class);
+ GameComponent movement = allocateComponent(MovementComponent.class);
+
+ GameComponent physics = allocateComponent(SimplePhysicsComponent.class);
+
+ SolidSurfaceComponent solidSurface
+ = (SolidSurfaceComponent)allocateComponent(SolidSurfaceComponent.class);
+ solidSurface.inititalize(4);
+ // house shape:
+ // / \ 1/ \2
+ // | | 3| |4
+ Vector2 surface1Start = new Vector2(32, 64);
+ Vector2 surface1End = new Vector2(64, 96);
+ Vector2 surface1Normal = new Vector2(-0.707f, 0.707f);
+ surface1Normal.normalize();
+
+ Vector2 surface2Start = new Vector2(64, 96);
+ Vector2 surface2End = new Vector2(75, 64);
+ Vector2 surface2Normal = new Vector2(0.9456f, 0.3250f);
+ surface2Normal.normalize();
+
+ Vector2 surface3Start = new Vector2(32, 0);
+ Vector2 surface3End = new Vector2(32, 64);
+ Vector2 surface3Normal = new Vector2(-1, 0);
+
+ Vector2 surface4Start = new Vector2(75, 0);
+ Vector2 surface4End = new Vector2(75, 64);
+ Vector2 surface4Normal = new Vector2(1, 0);
+
+ solidSurface.addSurface(surface1Start, surface1End, surface1Normal);
+ solidSurface.addSurface(surface2Start, surface2End, surface2Normal);
+ solidSurface.addSurface(surface3Start, surface3End, surface3Normal);
+ solidSurface.addSurface(surface4Start, surface4End, surface4Normal);
+
+ SpriteAnimation idle = new SpriteAnimation(EnemyAnimations.IDLE.ordinal(), 4);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_mud_stand),
+ Utils.framesToTime(24, 12), null, null));
+ AnimationFrame idle1 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_mud_idle01),
+ Utils.framesToTime(24, 2), null, null);
+ AnimationFrame idle2 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_mud_idle01),
+ Utils.framesToTime(24, 7), null, null);
+ idle.addFrame(idle1);
+ idle.addFrame(idle2);
+ idle.addFrame(idle1);
+ idle.setLoop(true);
+
+
+ SpriteAnimation walk = new SpriteAnimation(EnemyAnimations.MOVE.ordinal(), 6);
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_mud_walk01),
+ Utils.framesToTime(24, 4), null, null));
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_mud_walk02),
+ Utils.framesToTime(24, 4), null, null));
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_mud_walk03),
+ Utils.framesToTime(24, 5), null, null));
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_mud_walk04),
+ Utils.framesToTime(24, 4), null, null));
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_mud_walk05),
+ Utils.framesToTime(24, 4), null, null));
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_mud_walk06),
+ Utils.framesToTime(24, 5), null, null));
+ walk.setLoop(true);
+
+ FixedSizeArray crushAttackVolume =
+ new FixedSizeArray(1);
+ crushAttackVolume.add(new AABoxCollisionVolume(64, 0, 64, 96, HitType.HIT));
+
+ SpriteAnimation attack = new SpriteAnimation(EnemyAnimations.ATTACK.ordinal(), 8);
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_mud_stand),
+ Utils.framesToTime(24, 2), null, null));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_mud_attack01),
+ Utils.framesToTime(24, 2), null, null));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_mud_attack02),
+ Utils.framesToTime(24, 2), null, null));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_mud_attack03),
+ Utils.framesToTime(24, 2), null, null));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_mud_attack04),
+ Utils.framesToTime(24, 1), crushAttackVolume, null));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_mud_attack05),
+ Utils.framesToTime(24, 1), crushAttackVolume, null));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_mud_attack06),
+ Utils.framesToTime(24, 8), crushAttackVolume, null));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_mud_attack07),
+ Utils.framesToTime(24, 5), null, null));
+
+ staticData.add(gravity);
+ staticData.add(movement);
+ staticData.add(physics);
+ staticData.add(solidSurface);
+ staticData.add(idle);
+ staticData.add(walk);
+ staticData.add(attack);
+
+ setStaticData(GameObjectType.MUDMAN, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_ENEMY);
+
+ BackgroundCollisionComponent bgcollision = (BackgroundCollisionComponent)allocateComponent(BackgroundCollisionComponent.class);
+ bgcollision.setSize(80, 90);
+ bgcollision.setOffset(32, 5);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+
+ sprite.playAnimation(0);
+
+ EnemyAnimationComponent animation = (EnemyAnimationComponent)allocateComponent(EnemyAnimationComponent.class);
+ animation.setSprite(sprite);
+
+ PatrolComponent patrol = (PatrolComponent)allocateComponent(PatrolComponent.class);
+ patrol.setMovementSpeed(20.0f, 400.0f);
+
+ DynamicCollisionComponent collision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(collision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ collision.setHitReactionComponent(hitReact);
+
+ LifetimeComponent lifetime = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+
+ object.team = Team.ENEMY;
+ object.life = 1;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+
+ object.add(render);
+ object.add(sprite);
+ object.add(bgcollision);
+ object.add(animation);
+ object.add(patrol);
+ object.add(collision);
+ object.add(hitReact);
+ object.add(lifetime);
+
+ addStaticData(GameObjectType.MUDMAN, object, sprite);
+
+ final SpriteAnimation attack = sprite.findAnimation(EnemyAnimations.ATTACK.ordinal());
+ if (attack != null) {
+ patrol.setupAttack(70.0f, attack.getLength(), 0.0f, true);
+ }
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnEnemySkeleton(float positionX, float positionY, boolean flipHorizontal) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mNormalActivationRadius;
+ object.width = 64;
+ object.height = 64;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.SKELETON);
+ if (staticData == null) {
+ final int staticObjectCount = 7;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ GameComponent gravity = allocateComponent(GravityComponent.class);
+ GameComponent movement = allocateComponent(MovementComponent.class);
+
+ GameComponent physics = allocateComponent(SimplePhysicsComponent.class);
+
+ SolidSurfaceComponent solidSurface = (SolidSurfaceComponent)allocateComponent(SolidSurfaceComponent.class);
+ solidSurface.inititalize(4);
+
+ Vector2 surface1Start = new Vector2(25, 0);
+ Vector2 surface1End = new Vector2(25, 64);
+ Vector2 surface1Normal = new Vector2(-1, 0);
+
+ Vector2 surface2Start = new Vector2(40, 0);
+ Vector2 surface2End = new Vector2(40, 64);
+ Vector2 surface2Normal = new Vector2(1, 0);
+
+ solidSurface.addSurface(surface1Start, surface1End, surface1Normal);
+ solidSurface.addSurface(surface2Start, surface2End, surface2Normal);
+
+ FixedSizeArray basicVulnerabilityVolume =
+ new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new SphereCollisionVolume(16, 32, 32));
+ basicVulnerabilityVolume.get(0).setHitType(HitType.HIT);
+
+ FixedSizeArray basicAttackVolume =
+ new FixedSizeArray(1);
+ basicAttackVolume.add(new SphereCollisionVolume(16, 48, 32, HitType.HIT));
+
+ SpriteAnimation idle = new SpriteAnimation(EnemyAnimations.IDLE.ordinal(), 1);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_skeleton_stand),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+
+ SpriteAnimation walk = new SpriteAnimation(EnemyAnimations.MOVE.ordinal(), 6);
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_skeleton_walk01),
+ Utils.framesToTime(24, 3), null, basicVulnerabilityVolume));
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_skeleton_walk02),
+ Utils.framesToTime(24, 4), null, basicVulnerabilityVolume));
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_skeleton_walk03),
+ Utils.framesToTime(24, 3), null, basicVulnerabilityVolume));
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_skeleton_walk04),
+ Utils.framesToTime(24, 3), null, basicVulnerabilityVolume));
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_skeleton_walk05),
+ Utils.framesToTime(24, 4), null, basicVulnerabilityVolume));
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_skeleton_walk03),
+ Utils.framesToTime(24, 3), null, basicVulnerabilityVolume));
+
+ walk.setLoop(true);
+
+
+ SpriteAnimation attack = new SpriteAnimation(EnemyAnimations.ATTACK.ordinal(), 3);
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_skeleton_attack01),
+ Utils.framesToTime(24, 5), null, basicVulnerabilityVolume));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_skeleton_attack03),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_skeleton_attack04),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume));
+
+ staticData.add(gravity);
+ staticData.add(movement);
+ staticData.add(physics);
+ staticData.add(solidSurface);
+ staticData.add(idle);
+ staticData.add(walk);
+ staticData.add(attack);
+
+ setStaticData(GameObjectType.SKELETON, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_ENEMY);
+
+ BackgroundCollisionComponent bgcollision = (BackgroundCollisionComponent)allocateComponent(BackgroundCollisionComponent.class);
+ bgcollision.setSize(32, 48);
+ bgcollision.setOffset(16, 5);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ EnemyAnimationComponent animation = (EnemyAnimationComponent)allocateComponent(EnemyAnimationComponent.class);
+ animation.setSprite(sprite);
+
+ PatrolComponent patrol = (PatrolComponent)allocateComponent(PatrolComponent.class);
+ patrol.setMovementSpeed(20.0f, 1000.0f);
+ patrol.setTurnToFacePlayer(true);
+
+ DynamicCollisionComponent collision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(collision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ collision.setHitReactionComponent(hitReact);
+
+ LifetimeComponent lifetime = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+ lifetime.setVulnerableToDeathTiles(true);
+ lifetime.setObjectToSpawnOnDeath(GameObjectType.SMOKE_POOF);
+ SoundSystem sound = BaseObject.sSystemRegistry.soundSystem;
+ if (sound != null) {
+ lifetime.setDeathSound(sound.load(R.raw.sound_stomp));
+ }
+
+ object.team = Team.ENEMY;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+
+ object.add(render);
+ object.add(sprite);
+ object.add(bgcollision);
+ object.add(animation);
+ object.add(patrol);
+ object.add(collision);
+ object.add(hitReact);
+ object.add(lifetime);
+
+ addStaticData(GameObjectType.SKELETON, object, sprite);
+
+ final SpriteAnimation attack = sprite.findAnimation(EnemyAnimations.ATTACK.ordinal());
+ if (attack != null) {
+ patrol.setupAttack(75.0f, attack.getLength(), 2.0f, true);
+ }
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+
+ public GameObject spawnEnemyKaraguin(float positionX, float positionY, boolean flipHorizontal) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mNormalActivationRadius;
+ object.width = 32;
+ object.height = 32;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.KARAGUIN);
+ if (staticData == null) {
+ final int staticObjectCount = 2;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ GameComponent movement = allocateComponent(MovementComponent.class);
+
+ FixedSizeArray basicVulnerabilityVolume =
+ new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new SphereCollisionVolume(8, 16, 16));
+ basicVulnerabilityVolume.get(0).setHitType(HitType.HIT);
+
+ FixedSizeArray basicAttackVolume =
+ new FixedSizeArray(1);
+ basicAttackVolume.add(new SphereCollisionVolume(8, 16, 16, HitType.HIT));
+
+ SpriteAnimation idle = new SpriteAnimation(0, 3);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_karaguin01),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_karaguin02),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_karaguin03),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume));
+ idle.setLoop(true);
+
+ staticData.add(movement);
+ staticData.add(idle);
+
+
+ setStaticData(GameObjectType.KARAGUIN, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_ENEMY);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ PatrolComponent patrol = (PatrolComponent)allocateComponent(PatrolComponent.class);
+ patrol.setMovementSpeed(50.0f, 1000.0f);
+ patrol.setTurnToFacePlayer(false);
+ patrol.setFlying(true);
+
+ DynamicCollisionComponent collision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(collision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ collision.setHitReactionComponent(hitReact);
+
+ LifetimeComponent lifetime = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+ lifetime.setObjectToSpawnOnDeath(GameObjectType.SMOKE_POOF);
+ SoundSystem sound = BaseObject.sSystemRegistry.soundSystem;
+ if (sound != null) {
+ lifetime.setDeathSound(sound.load(R.raw.sound_stomp));
+ }
+
+ EnemyAnimationComponent animation = (EnemyAnimationComponent)allocateComponent(EnemyAnimationComponent.class);
+ animation.setSprite(sprite);
+
+ object.team = Team.ENEMY;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+ // HACK. These guys originally moved on their own, so let's keep them that way.
+ object.getVelocity().x = 50.0f * object.facingDirection.x;
+ object.getTargetVelocity().x = 50.0f * object.facingDirection.x;
+
+ object.add(render);
+ object.add(animation);
+ object.add(sprite);
+ object.add(patrol);
+ object.add(collision);
+ object.add(hitReact);
+ object.add(lifetime);
+
+ addStaticData(GameObjectType.KARAGUIN, object, sprite);
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnEnemyPinkNamazu(float positionX, float positionY, boolean flipHorizontal) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 128;
+ object.height = 128;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.PINK_NAMAZU);
+ if (staticData == null) {
+ final int staticObjectCount = 7;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ GameComponent gravity = allocateComponent(GravityComponent.class);
+ GameComponent movement = allocateComponent(MovementComponent.class);
+
+ GameComponent physics = allocateComponent(SimplePhysicsComponent.class);
+
+ SolidSurfaceComponent solidSurface
+ = (SolidSurfaceComponent)allocateComponent(SolidSurfaceComponent.class);
+ solidSurface.inititalize(5);
+ // circle shape:
+ // __ __3
+ // / \ 2/ \4
+ // | | 1| |5
+ /*
+ 0:12,6:22,52:0.98058067569092,-0.19611613513818
+ 0:22,52:50,75:-0.62580046626293,0.77998318983495
+ 0:50,75:81,75:0,1
+ 0:81,75:104,49:0.74038072228541,0.67218776102228
+ 0:104,49:104,6:-0.99997086544204,-0.00763336538505
+ */
+ Vector2 surface1Start = new Vector2(12, 3);
+ Vector2 surface1End = new Vector2(22, 52);
+ Vector2 surface1Normal = new Vector2(-0.98058067569092f, -0.19611613513818f);
+ surface1Normal.normalize();
+
+ Vector2 surface2Start = new Vector2(22, 52);
+ Vector2 surface2End = new Vector2(50, 75);
+ Vector2 surface2Normal = new Vector2(-0.62580046626293f, 0.77998318983495f);
+ surface2Normal.normalize();
+
+ Vector2 surface3Start = new Vector2(50, 75);
+ Vector2 surface3End = new Vector2(81, 75);
+ Vector2 surface3Normal = new Vector2(0, 1);
+
+ Vector2 surface4Start = new Vector2(81, 75);
+ Vector2 surface4End = new Vector2(104,49);
+ Vector2 surface4Normal = new Vector2(0.74038072228541f, 0.67218776102228f);
+
+ Vector2 surface5Start = new Vector2(104,49);
+ Vector2 surface5End = new Vector2(104, 3);
+ Vector2 surface5Normal = new Vector2(1.0f, 0.0f);
+
+ solidSurface.addSurface(surface1Start, surface1End, surface1Normal);
+ solidSurface.addSurface(surface2Start, surface2End, surface2Normal);
+ solidSurface.addSurface(surface3Start, surface3End, surface3Normal);
+ solidSurface.addSurface(surface4Start, surface4End, surface4Normal);
+ solidSurface.addSurface(surface5Start, surface5End, surface5Normal);
+
+
+ SpriteAnimation idle = new SpriteAnimation(GenericAnimationComponent.Animation.IDLE, 4);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_pinkdude_stand),
+ Utils.framesToTime(24, 8), null, null));
+ AnimationFrame idle1 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_pinkdude_sleep01),
+ Utils.framesToTime(24, 3), null, null);
+ AnimationFrame idle2 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_pinkdude_sleep02),
+ Utils.framesToTime(24, 8), null, null);
+ idle.addFrame(idle1);
+ idle.addFrame(idle2);
+ idle.addFrame(idle1);
+ idle.setLoop(true);
+
+
+ SpriteAnimation wake = new SpriteAnimation(GenericAnimationComponent.Animation.MOVE, 4);
+ AnimationFrame wake1 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_pinkdude_eyeopen),
+ Utils.framesToTime(24, 3), null, null);
+ AnimationFrame wake2 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_pinkdude_stand),
+ Utils.framesToTime(24, 3), null, null);
+ wake.addFrame(wake1);
+ wake.addFrame(wake2);
+ wake.addFrame(wake1);
+ wake.addFrame(wake2);
+
+ FixedSizeArray crushAttackVolume =
+ new FixedSizeArray(1);
+ crushAttackVolume.add(new AABoxCollisionVolume(32, 0, 64, 32, HitType.HIT));
+
+ SpriteAnimation attack = new SpriteAnimation(GenericAnimationComponent.Animation.ATTACK, 1);
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_pinkdude_jump),
+ Utils.framesToTime(24, 2), crushAttackVolume, null));
+
+
+ staticData.add(gravity);
+ staticData.add(movement);
+ staticData.add(physics);
+ staticData.add(solidSurface);
+ staticData.add(idle);
+ staticData.add(wake);
+ staticData.add(attack);
+
+ setStaticData(GameObjectType.PINK_NAMAZU, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_ENEMY);
+
+ BackgroundCollisionComponent bgcollision = (BackgroundCollisionComponent)allocateComponent(BackgroundCollisionComponent.class);
+ bgcollision.setSize(100, 75);
+ bgcollision.setOffset(12, 5);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ GenericAnimationComponent animation =
+ (GenericAnimationComponent)allocateComponent(GenericAnimationComponent.class);
+ animation.setSprite(sprite);
+
+ SleeperComponent sleeper = (SleeperComponent)allocateComponent(SleeperComponent.class);
+ sleeper.setAttackImpulse(100.0f, 170.0f);
+ sleeper.setSlam(0.3f, 25.0f);
+
+ DynamicCollisionComponent collision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(collision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ collision.setHitReactionComponent(hitReact);
+
+
+ object.team = Team.ENEMY;
+ object.life = 1;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+
+ object.add(render);
+ object.add(sprite);
+ object.add(bgcollision);
+ object.add(animation);
+ object.add(collision);
+ object.add(hitReact);
+ object.add(sleeper);
+
+
+ addStaticData(GameObjectType.PINK_NAMAZU, object, sprite);
+
+ final SpriteAnimation wakeUp = sprite.findAnimation(GenericAnimationComponent.Animation.MOVE);
+ if (wakeUp != null) {
+ sleeper.setWakeUpDuration(wakeUp.getLength() + 1.0f);
+ }
+
+ sprite.playAnimation(GenericAnimationComponent.Animation.IDLE);
+
+ return object;
+ }
+
+ public GameObject spawnEnemyBat(float positionX, float positionY, boolean flipHorizontal) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mNormalActivationRadius;
+ object.width = 64;
+ object.height = 32;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.BAT);
+ if (staticData == null) {
+ final int staticObjectCount = 2;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ GameComponent movement = allocateComponent(MovementComponent.class);
+
+ FixedSizeArray basicVulnerabilityVolume =
+ new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new SphereCollisionVolume(16, 32, 16));
+ basicVulnerabilityVolume.get(0).setHitType(HitType.HIT);
+
+ FixedSizeArray basicAttackVolume =
+ new FixedSizeArray(1);
+ basicAttackVolume.add(new SphereCollisionVolume(16, 32, 16, HitType.HIT));
+
+ SpriteAnimation idle = new SpriteAnimation(0, 4);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_bat01),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_bat02),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_bat03),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_bat04),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume));
+ idle.setLoop(true);
+
+ staticData.add(movement);
+ staticData.add(idle);
+
+
+ setStaticData(GameObjectType.BAT, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_ENEMY);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ PatrolComponent patrol = (PatrolComponent)allocateComponent(PatrolComponent.class);
+ patrol.setMovementSpeed(75.0f, 1000.0f);
+ patrol.setTurnToFacePlayer(false);
+ patrol.setFlying(true);
+
+ DynamicCollisionComponent collision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(collision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ collision.setHitReactionComponent(hitReact);
+
+ LifetimeComponent lifetime = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+ lifetime.setObjectToSpawnOnDeath(GameObjectType.SMOKE_POOF);
+ SoundSystem sound = BaseObject.sSystemRegistry.soundSystem;
+ if (sound != null) {
+ lifetime.setDeathSound(sound.load(R.raw.sound_stomp));
+ }
+
+ EnemyAnimationComponent animation = (EnemyAnimationComponent)allocateComponent(EnemyAnimationComponent.class);
+ animation.setSprite(sprite);
+
+ object.team = Team.ENEMY;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+
+ // HACK. These guys originally moved on their own, so let's keep them that way.
+ object.getVelocity().x = 75.0f * object.facingDirection.x;
+ object.getTargetVelocity().x = 75.0f * object.facingDirection.x;
+
+ object.add(render);
+ object.add(animation);
+ object.add(sprite);
+ object.add(patrol);
+ object.add(collision);
+ object.add(hitReact);
+ object.add(lifetime);
+
+ addStaticData(GameObjectType.BAT, object, sprite);
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnEnemySting(float positionX, float positionY, boolean flipHorizontal) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mNormalActivationRadius;
+ object.width = 64;
+ object.height = 64;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.STING);
+ if (staticData == null) {
+ final int staticObjectCount = 2;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ GameComponent movement = allocateComponent(MovementComponent.class);
+
+ FixedSizeArray basicVulnerabilityVolume =
+ new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new SphereCollisionVolume(16, 32, 16));
+ basicVulnerabilityVolume.get(0).setHitType(HitType.HIT);
+
+ FixedSizeArray basicAttackVolume =
+ new FixedSizeArray(1);
+ basicAttackVolume.add(new SphereCollisionVolume(16, 32, 16, HitType.HIT));
+
+ SpriteAnimation idle = new SpriteAnimation(0, 3);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_sting01),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_sting02),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_sting03),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume));
+
+ idle.setLoop(true);
+
+ staticData.add(movement);
+ staticData.add(idle);
+
+
+ setStaticData(GameObjectType.STING, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_ENEMY);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ PatrolComponent patrol = (PatrolComponent)allocateComponent(PatrolComponent.class);
+ patrol.setMovementSpeed(75.0f, 1000.0f);
+ patrol.setTurnToFacePlayer(false);
+ patrol.setFlying(true);
+
+ DynamicCollisionComponent collision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(collision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ collision.setHitReactionComponent(hitReact);
+
+ LifetimeComponent lifetime = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+ lifetime.setObjectToSpawnOnDeath(GameObjectType.SMOKE_POOF);
+ SoundSystem sound = BaseObject.sSystemRegistry.soundSystem;
+ if (sound != null) {
+ lifetime.setDeathSound(sound.load(R.raw.sound_stomp));
+ }
+
+ EnemyAnimationComponent animation = (EnemyAnimationComponent)allocateComponent(EnemyAnimationComponent.class);
+ animation.setSprite(sprite);
+
+ object.team = Team.ENEMY;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+
+ // HACK. These guys originally moved on their own, so let's keep them that way.
+ object.getVelocity().x = 25.0f * object.facingDirection.x;
+ object.getTargetVelocity().x = 25.0f * object.facingDirection.x;
+
+ object.add(render);
+ object.add(animation);
+ object.add(sprite);
+ object.add(patrol);
+ object.add(collision);
+ object.add(hitReact);
+ object.add(lifetime);
+
+ addStaticData(GameObjectType.STING, object, sprite);
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnEnemyOnion(float positionX, float positionY, boolean flipHorizontal) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mNormalActivationRadius;
+ object.width = 64;
+ object.height = 64;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.ONION);
+ if (staticData == null) {
+ final int staticObjectCount = 5;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ GameComponent gravity = allocateComponent(GravityComponent.class);
+ GameComponent movement = allocateComponent(MovementComponent.class);
+ SimplePhysicsComponent physics = (SimplePhysicsComponent)allocateComponent(SimplePhysicsComponent.class);
+ physics.setBounciness(0.2f);
+
+
+ // Animations
+ FixedSizeArray basicVulnerabilityVolume =
+ new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new SphereCollisionVolume(16, 32, 32));
+
+ FixedSizeArray basicAttackVolume =
+ new FixedSizeArray(1);
+ basicAttackVolume.add(new SphereCollisionVolume(16, 32, 32, HitType.HIT));
+
+ SpriteAnimation idle = new SpriteAnimation(EnemyAnimations.IDLE.ordinal(), 1);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_onion01),
+ Utils.framesToTime(24, 3), basicAttackVolume, basicVulnerabilityVolume));
+
+ idle.setLoop(true);
+
+ SpriteAnimation walk = new SpriteAnimation(EnemyAnimations.MOVE.ordinal(), 3);
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_onion01),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume));
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_onion02),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume));
+ walk.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_onion03),
+ Utils.framesToTime(24, 1), basicAttackVolume, basicVulnerabilityVolume));
+ walk.setLoop(true);
+
+ staticData.add(gravity);
+ staticData.add(movement);
+ staticData.add(physics);
+ staticData.add(idle);
+ staticData.add(walk);
+
+ setStaticData(GameObjectType.ONION, staticData);
+
+ }
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_ENEMY);
+
+ BackgroundCollisionComponent bgcollision
+ = (BackgroundCollisionComponent)allocateComponent(BackgroundCollisionComponent.class);
+ bgcollision.setSize(32, 48);
+ bgcollision.setOffset(16, 5);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ EnemyAnimationComponent animation
+ = (EnemyAnimationComponent)allocateComponent(EnemyAnimationComponent.class);
+ animation.setSprite(sprite);
+
+ PatrolComponent patrol = (PatrolComponent)allocateComponent(PatrolComponent.class);
+ patrol.setMovementSpeed(50.0f, 1000.0f);
+
+ DynamicCollisionComponent collision
+ = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(collision);
+
+ HitReactionComponent hitReact
+ = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ collision.setHitReactionComponent(hitReact);
+
+ LifetimeComponent lifetime = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+ lifetime.setVulnerableToDeathTiles(true);
+ lifetime.setObjectToSpawnOnDeath(GameObjectType.SMOKE_POOF);
+ SoundSystem sound = BaseObject.sSystemRegistry.soundSystem;
+ if (sound != null) {
+ lifetime.setDeathSound(sound.load(R.raw.sound_stomp));
+ }
+
+ object.add(render);
+ object.add(sprite);
+
+ object.add(bgcollision);
+ object.add(animation);
+ object.add(patrol);
+ object.add(collision);
+ object.add(hitReact);
+ object.add(lifetime);
+
+ object.team = Team.ENEMY;
+
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+
+ addStaticData(GameObjectType.ONION, object, sprite);
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnEnemyWanda(float positionX, float positionY, boolean flipHorizontal) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ // Make sure related textures are loaded.
+ textureLibrary.allocateTexture(R.drawable.energy_ball01);
+ textureLibrary.allocateTexture(R.drawable.energy_ball02);
+ textureLibrary.allocateTexture(R.drawable.energy_ball03);
+ textureLibrary.allocateTexture(R.drawable.energy_ball04);
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mAlwaysActive;
+ object.width = 64;
+ object.height = 128;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.WANDA);
+ if (staticData == null) {
+ final int staticObjectCount = 9;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ GameComponent gravity = allocateComponent(GravityComponent.class);
+ GameComponent movement = allocateComponent(MovementComponent.class);
+
+ SimplePhysicsComponent physics = (SimplePhysicsComponent)allocateComponent(SimplePhysicsComponent.class);
+ physics.setBounciness(0.0f);
+
+
+
+ FixedSizeArray basicVulnerabilityVolume =
+ new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new AABoxCollisionVolume(20, 5, 26, 80, HitType.COLLECT));
+
+ SpriteAnimation idle = new SpriteAnimation(NPCAnimationComponent.IDLE, 1);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_stand),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+
+
+
+ AnimationFrame walkFrame1 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_walk01),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume);
+ AnimationFrame walkFrame2 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_walk02),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume);
+ AnimationFrame walkFrame3 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_walk03),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume);
+ AnimationFrame walkFrame4 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_walk04),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume);
+ AnimationFrame walkFrame5 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_walk05),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume);
+ SpriteAnimation walk = new SpriteAnimation(NPCAnimationComponent.WALK, 8);
+ walk.addFrame(walkFrame1);
+ walk.addFrame(walkFrame2);
+ walk.addFrame(walkFrame3);
+ walk.addFrame(walkFrame4);
+ walk.addFrame(walkFrame5);
+ walk.addFrame(walkFrame4);
+ walk.addFrame(walkFrame3);
+ walk.addFrame(walkFrame2);
+ walk.setLoop(true);
+
+
+ AnimationFrame runFrame4 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_run04),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume);
+
+ SpriteAnimation run = new SpriteAnimation(NPCAnimationComponent.RUN, 9);
+ run.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_run01),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ run.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_run02),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ run.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_run03),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ run.addFrame(runFrame4);
+ run.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_run05),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ run.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_run06),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ run.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_run07),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ run.addFrame(runFrame4);
+ run.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_run08),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ run.setLoop(true);
+
+ SpriteAnimation jumpStart = new SpriteAnimation(NPCAnimationComponent.JUMP_START, 4);
+ AnimationFrame jump1 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_jump01),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume);
+ AnimationFrame jump2 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_jump01),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume);
+ jumpStart.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_run04),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume));
+ jumpStart.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_crouch),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ jumpStart.addFrame(jump1);
+ jumpStart.addFrame(jump2);
+
+ SpriteAnimation jumpAir = new SpriteAnimation(NPCAnimationComponent.JUMP_AIR, 2);
+ jumpAir.addFrame(jump1);
+ jumpAir.addFrame(jump2);
+ jumpAir.setLoop(true);
+
+ SpriteAnimation attack = new SpriteAnimation(NPCAnimationComponent.SHOOT, 11);
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_shoot01),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_shoot02),
+ Utils.framesToTime(24, 8), null, basicVulnerabilityVolume));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_shoot03),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_shoot04),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_shoot05),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_shoot06),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_shoot07),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_shoot08),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_shoot09),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_shoot02),
+ Utils.framesToTime(24, 3), null, basicVulnerabilityVolume));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_wanda_shoot01),
+ Utils.framesToTime(24, 3), null, basicVulnerabilityVolume));
+
+ staticData.add(gravity);
+ staticData.add(movement);
+ staticData.add(physics);
+ staticData.add(idle);
+ staticData.add(walk);
+ staticData.add(run);
+ staticData.add(jumpStart);
+ staticData.add(jumpAir);
+ staticData.add(attack);
+
+ setStaticData(GameObjectType.WANDA, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.NPC);
+
+ BackgroundCollisionComponent bgcollision = (BackgroundCollisionComponent)allocateComponent(BackgroundCollisionComponent.class);
+ bgcollision.setSize(32, 82);
+ bgcollision.setOffset(20, 5);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ NPCAnimationComponent animation = (NPCAnimationComponent)allocateComponent(NPCAnimationComponent.class);
+ animation.setSprite(sprite);
+
+ NPCComponent patrol = (NPCComponent)allocateComponent(NPCComponent.class);
+
+ DynamicCollisionComponent collision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(collision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ collision.setHitReactionComponent(hitReact);
+
+ patrol.setHitReactionComponent(hitReact);
+
+ SoundSystem sound = sSystemRegistry.soundSystem;
+
+ LaunchProjectileComponent gun
+ = (LaunchProjectileComponent)allocateComponent(LaunchProjectileComponent.class);
+ gun.setShotsPerSet(1);
+ gun.setSetsPerActivation(1);
+ gun.setDelayBeforeFirstSet(Utils.framesToTime(24, 11));
+ gun.setObjectTypeToSpawn(GameObjectType.WANDA_SHOT);
+ gun.setOffsetX(45);
+ gun.setOffsetY(42);
+ gun.setRequiredAction(GameObject.ActionType.ATTACK);
+ gun.setVelocityX(300.0f);
+ gun.setShootSound(sound.load(R.raw.sound_poing));
+
+ object.team = Team.ENEMY;
+ object.life = 1;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+
+ object.add(gun);
+ object.add(render);
+ object.add(sprite);
+ object.add(bgcollision);
+ object.add(animation);
+ object.add(patrol);
+ object.add(collision);
+ object.add(hitReact);
+
+ addStaticData(GameObjectType.WANDA, object, sprite);
+
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+
+ public GameObject spawnEnemyKyle(float positionX, float positionY, boolean flipHorizontal) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mAlwaysActive;
+ object.width = 64;
+ object.height = 128;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.KYLE);
+ if (staticData == null) {
+ final int staticObjectCount = 9;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ GameComponent gravity = allocateComponent(GravityComponent.class);
+ GameComponent movement = allocateComponent(MovementComponent.class);
+
+ SimplePhysicsComponent physics = (SimplePhysicsComponent)allocateComponent(SimplePhysicsComponent.class);
+ physics.setBounciness(0.0f);
+
+ FixedSizeArray basicVulnerabilityVolume =
+ new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new AABoxCollisionVolume(20, 5, 26, 80, HitType.COLLECT));
+
+ SpriteAnimation idle = new SpriteAnimation(NPCAnimationComponent.IDLE, 1);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kyle_stand),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+
+ AnimationFrame walkFrame1 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kyle_walk01),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume);
+ AnimationFrame walkFrame2 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kyle_walk02),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume);
+ AnimationFrame walkFrame3 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kyle_walk03),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume);
+ AnimationFrame walkFrame4 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kyle_walk04),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume);
+ AnimationFrame walkFrame5 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kyle_walk05),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume);
+ AnimationFrame walkFrame6 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kyle_walk06),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume);
+ AnimationFrame walkFrame7 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kyle_walk07),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume);
+ SpriteAnimation walk = new SpriteAnimation(NPCAnimationComponent.WALK, 12);
+ walk.addFrame(walkFrame1);
+ walk.addFrame(walkFrame2);
+ walk.addFrame(walkFrame3);
+ walk.addFrame(walkFrame4);
+ walk.addFrame(walkFrame3);
+ walk.addFrame(walkFrame2);
+ walk.addFrame(walkFrame1);
+ walk.addFrame(walkFrame5);
+ walk.addFrame(walkFrame6);
+ walk.addFrame(walkFrame7);
+ walk.addFrame(walkFrame6);
+ walk.addFrame(walkFrame5);
+
+ walk.setLoop(true);
+
+ AnimationFrame crouch1 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kyle_crouch01),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume);
+ AnimationFrame crouch2 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kyle_crouch02),
+ Utils.framesToTime(24, 3), null, basicVulnerabilityVolume);
+
+ SpriteAnimation runStart = new SpriteAnimation(NPCAnimationComponent.RUN_START, 2);
+ runStart.addFrame(crouch1);
+ runStart.addFrame(crouch2);
+
+ FixedSizeArray attackVolume =
+ new FixedSizeArray(2);
+ attackVolume.add(new AABoxCollisionVolume(32, 32, 50, 32, HitType.HIT));
+ attackVolume.add(new AABoxCollisionVolume(32, 32, 50, 32, HitType.COLLECT));
+
+ SpriteAnimation run = new SpriteAnimation(NPCAnimationComponent.RUN, 2);
+ run.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kyle_dash01),
+ Utils.framesToTime(24, 1), attackVolume, basicVulnerabilityVolume));
+ run.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kyle_dash02),
+ Utils.framesToTime(24, 1), attackVolume, basicVulnerabilityVolume));
+ run.setLoop(true);
+
+ SpriteAnimation jumpStart = new SpriteAnimation(NPCAnimationComponent.JUMP_START, 2);
+ jumpStart.addFrame(crouch1);
+ jumpStart.addFrame(crouch2);
+
+ SpriteAnimation jumpAir = new SpriteAnimation(NPCAnimationComponent.JUMP_AIR, 2);
+ AnimationFrame jump1 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kyle_jump01),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume);
+ AnimationFrame jump2 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kyle_jump01),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume);
+ jumpAir.addFrame(jump1);
+ jumpAir.addFrame(jump2);
+ jumpAir.setLoop(true);
+
+
+
+ staticData.add(gravity);
+ staticData.add(movement);
+ staticData.add(physics);
+ staticData.add(idle);
+ staticData.add(walk);
+ staticData.add(runStart);
+ staticData.add(run);
+ staticData.add(jumpStart);
+ staticData.add(jumpAir);
+
+ setStaticData(GameObjectType.KYLE, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.NPC);
+
+ BackgroundCollisionComponent bgcollision = (BackgroundCollisionComponent)allocateComponent(BackgroundCollisionComponent.class);
+ bgcollision.setSize(32, 90);
+ bgcollision.setOffset(20, 5);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ NPCAnimationComponent animation = (NPCAnimationComponent)allocateComponent(NPCAnimationComponent.class);
+ animation.setSprite(sprite);
+ animation.setStopAtWalls(false); // Kyle can run through walls
+
+ NPCComponent patrol = (NPCComponent)allocateComponent(NPCComponent.class);
+ patrol.setSpeeds(350.0f, 50.0f, 400.0f, -10.0f, 400.0f);
+ patrol.setGameEvent(GameFlowEvent.EVENT_SHOW_ANIMATION, AnimationPlayerActivity.KYLE_DEATH, false);
+
+ DynamicCollisionComponent collision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(collision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ collision.setHitReactionComponent(hitReact);
+
+ patrol.setHitReactionComponent(hitReact);
+
+ MotionBlurComponent motionBlur = (MotionBlurComponent)allocateComponent(MotionBlurComponent.class);
+ motionBlur.setTarget(render);
+
+ LauncherComponent launcher = (LauncherComponent)allocateComponent(LauncherComponent.class);
+ launcher.setup((float)(Math.PI * 0.45f), 1000.0f, 0.0f, 0.0f, false);
+ launcher.setLaunchEffect(GameObjectType.FLASH, 70.0f, 50.0f);
+ hitReact.setLauncherComponent(launcher, HitType.HIT);
+
+ object.team = Team.NONE;
+ object.life = 1;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+
+ object.add(render);
+ object.add(sprite);
+ object.add(bgcollision);
+ object.add(animation);
+ object.add(patrol);
+ object.add(collision);
+ object.add(hitReact);
+ object.add(motionBlur);
+ object.add(launcher);
+
+ addStaticData(GameObjectType.KYLE, object, sprite);
+
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnEnemyKyleDead(float positionX, float positionY) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 128;
+ object.height = 32;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.KYLE_DEAD);
+ if (staticData == null) {
+ final int staticObjectCount = 1;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ FixedSizeArray basicVulnerabilityVolume =
+ new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new AABoxCollisionVolume(32, 5, 64, 32, HitType.COLLECT));
+
+ SpriteAnimation idle = new SpriteAnimation(0, 1);
+ AnimationFrame frame1 = new AnimationFrame(textureLibrary.allocateTexture(R.drawable.enemy_kyle_dead),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume);
+
+ idle.addFrame(frame1);
+
+ idle.setLoop(true);
+
+ staticData.add(idle);
+
+ setStaticData(GameObjectType.KYLE_DEAD, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_OBJECT);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ DynamicCollisionComponent dynamicCollision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(dynamicCollision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ dynamicCollision.setHitReactionComponent(hitReact);
+ hitReact.setSpawnGameEventOnHit(HitType.COLLECT, GameFlowEvent.EVENT_SHOW_DIALOG_CHARACTER2, 0);
+
+ SelectDialogComponent dialogSelect = (SelectDialogComponent)allocateComponent(SelectDialogComponent.class);
+ dialogSelect.setHitReact(hitReact);
+
+ // Since this object doesn't have gravity or background collision, adjust down to simulate the position
+ // at which a bounding volume would rest.
+
+ object.getPosition().y -= 5.0f;
+
+ object.add(dialogSelect);
+ object.add(render);
+ object.add(sprite);
+ object.add(dynamicCollision);
+ object.add(hitReact);
+
+ addStaticData(GameObjectType.KYLE_DEAD, object, sprite);
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnEnemyAndouDead(float positionX, float positionY) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 64;
+ object.height = 64;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.ANDOU_DEAD);
+ if (staticData == null) {
+ final int staticObjectCount = 1;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ SpriteAnimation idle = new SpriteAnimation(0, 1);
+ AnimationFrame frame1 = new AnimationFrame(textureLibrary.allocateTexture(R.drawable.andou_explode12),
+ Utils.framesToTime(24, 1), null, null);
+
+ idle.addFrame(frame1);
+
+ idle.setLoop(true);
+
+ staticData.add(idle);
+
+ setStaticData(GameObjectType.ANDOU_DEAD, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_OBJECT);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ LaunchProjectileComponent smokeGun
+ = (LaunchProjectileComponent)allocateComponent(LaunchProjectileComponent.class);
+ smokeGun.setDelayBetweenShots(0.25f);
+ smokeGun.setObjectTypeToSpawn(GameObjectType.SMOKE_BIG);
+ smokeGun.setOffsetX(32);
+ smokeGun.setOffsetY(15);
+ smokeGun.setVelocityX(-150.0f);
+ smokeGun.setVelocityY(100.0f);
+ smokeGun.setThetaError(0.1f);
+
+ LaunchProjectileComponent smokeGun2
+ = (LaunchProjectileComponent)allocateComponent(LaunchProjectileComponent.class);
+ smokeGun2.setDelayBetweenShots(0.35f);
+ smokeGun2.setObjectTypeToSpawn(GameObjectType.SMOKE_SMALL);
+ smokeGun2.setOffsetX(16);
+ smokeGun2.setOffsetY(15);
+ smokeGun2.setVelocityX(-150.0f);
+ smokeGun2.setVelocityY(150.0f);
+ smokeGun2.setThetaError(0.1f);
+
+ object.add(render);
+ object.add(sprite);
+ object.add(smokeGun);
+ object.add(smokeGun2);
+
+ object.facingDirection.x = -1.0f;
+
+ addStaticData(GameObjectType.ANDOU_DEAD, object, sprite);
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnEnemyKabocha(float positionX, float positionY, boolean flipHorizontal) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mAlwaysActive;
+ object.width = 64;
+ object.height = 128;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.KABOCHA);
+ if (staticData == null) {
+ final int staticObjectCount = 5;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ GameComponent gravity = allocateComponent(GravityComponent.class);
+ GameComponent movement = allocateComponent(MovementComponent.class);
+
+ SimplePhysicsComponent physics = (SimplePhysicsComponent)allocateComponent(SimplePhysicsComponent.class);
+ physics.setBounciness(0.0f);
+
+ FixedSizeArray basicVulnerabilityVolume =
+ new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new AABoxCollisionVolume(20, 5, 26, 80, HitType.COLLECT));
+
+ SpriteAnimation idle = new SpriteAnimation(NPCAnimationComponent.IDLE, 1);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_stand),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+
+ AnimationFrame walkFrame1 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_walk01),
+ Utils.framesToTime(24, 3), null, basicVulnerabilityVolume);
+ AnimationFrame walkFrame2 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_walk02),
+ Utils.framesToTime(24, 3), null, basicVulnerabilityVolume);
+ AnimationFrame walkFrame3 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_walk03),
+ Utils.framesToTime(24, 3), null, basicVulnerabilityVolume);
+ AnimationFrame walkFrame4 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_walk04),
+ Utils.framesToTime(24, 3), null, basicVulnerabilityVolume);
+ AnimationFrame walkFrame5 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_walk05),
+ Utils.framesToTime(24, 3), null, basicVulnerabilityVolume);
+ AnimationFrame walkFrame6 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_walk06),
+ Utils.framesToTime(24, 3), null, basicVulnerabilityVolume);
+
+ SpriteAnimation walk = new SpriteAnimation(NPCAnimationComponent.WALK, 6);
+ walk.addFrame(walkFrame1);
+ walk.addFrame(walkFrame2);
+ walk.addFrame(walkFrame3);
+ walk.addFrame(walkFrame4);
+ walk.addFrame(walkFrame5);
+ walk.addFrame(walkFrame6);
+
+
+ walk.setLoop(true);
+
+ staticData.add(gravity);
+ staticData.add(movement);
+ staticData.add(physics);
+ staticData.add(idle);
+ staticData.add(walk);
+
+ setStaticData(GameObjectType.KABOCHA, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.NPC);
+
+ BackgroundCollisionComponent bgcollision = (BackgroundCollisionComponent)allocateComponent(BackgroundCollisionComponent.class);
+ bgcollision.setSize(38, 82);
+ bgcollision.setOffset(16, 5);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ NPCAnimationComponent animation = (NPCAnimationComponent)allocateComponent(NPCAnimationComponent.class);
+ animation.setSprite(sprite);
+
+ NPCComponent patrol = (NPCComponent)allocateComponent(NPCComponent.class);
+
+ DynamicCollisionComponent collision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(collision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ collision.setHitReactionComponent(hitReact);
+
+ patrol.setHitReactionComponent(hitReact);
+
+ object.team = Team.ENEMY;
+ object.life = 1;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+
+ object.add(render);
+ object.add(sprite);
+ object.add(bgcollision);
+ object.add(animation);
+ object.add(patrol);
+ object.add(collision);
+ object.add(hitReact);
+
+ addStaticData(GameObjectType.KABOCHA, object, sprite);
+
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnRokudouTerminal(float positionX, float positionY) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 64;
+ object.height = 64;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.ROKUDOU_TERMINAL);
+ if (staticData == null) {
+ final int staticObjectCount = 1;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ FixedSizeArray basicVulnerabilityVolume = new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new AABoxCollisionVolume(0, 0, 64, 64));
+ basicVulnerabilityVolume.get(0).setHitType(HitType.COLLECT);
+
+
+ AnimationFrame frame1 = new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_terminal01),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume);
+ AnimationFrame frame2 = new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_terminal02),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume);
+ AnimationFrame frame3 = new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_terminal03),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume);
+ AnimationFrame frame4 = new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_terminal01),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume);
+ AnimationFrame frame5 = new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_terminal02),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume);
+ AnimationFrame frame6 = new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_terminal01),
+ 1.0f, null, basicVulnerabilityVolume);
+
+ SpriteAnimation idle = new SpriteAnimation(0, 12);
+ idle.addFrame(frame1);
+ idle.addFrame(frame5);
+ idle.addFrame(frame4);
+ idle.addFrame(frame3);
+ idle.addFrame(frame2);
+ idle.addFrame(frame6);
+ idle.addFrame(frame6);
+ idle.addFrame(frame3);
+ idle.addFrame(frame2);
+ idle.addFrame(frame1);
+ idle.addFrame(frame2);
+ idle.addFrame(frame6);
+
+ idle.setLoop(true);
+
+
+ staticData.add(idle);
+
+ setStaticData(GameObjectType.ROKUDOU_TERMINAL, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_OBJECT);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ DynamicCollisionComponent dynamicCollision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(dynamicCollision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ hitReact.setSpawnGameEventOnHit(HitType.COLLECT, GameFlowEvent.EVENT_SHOW_DIALOG_CHARACTER2, 0);
+
+ SelectDialogComponent dialogSelect = (SelectDialogComponent)allocateComponent(SelectDialogComponent.class);
+ dialogSelect.setHitReact(hitReact);
+
+ dynamicCollision.setHitReactionComponent(hitReact);
+
+ object.add(dialogSelect);
+ object.add(render);
+ object.add(sprite);
+ object.add(dynamicCollision);
+ object.add(hitReact);
+
+ addStaticData(GameObjectType.ROKUDOU_TERMINAL, object, sprite);
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+
+ public GameObject spawnKabochaTerminal(float positionX, float positionY) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 64;
+ object.height = 64;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.KABOCHA_TERMINAL);
+ if (staticData == null) {
+ final int staticObjectCount = 1;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ FixedSizeArray basicVulnerabilityVolume = new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new AABoxCollisionVolume(0, 0, 64, 64));
+ basicVulnerabilityVolume.get(0).setHitType(HitType.COLLECT);
+
+
+ AnimationFrame frame1 = new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_terminal_kabocha01),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume);
+ AnimationFrame frame2 = new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_terminal_kabocha02),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume);
+ AnimationFrame frame3 = new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_terminal_kabocha03),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume);
+ AnimationFrame frame4 = new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_terminal_kabocha01),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume);
+ AnimationFrame frame5 = new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_terminal_kabocha02),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume);
+ AnimationFrame frame6 = new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_terminal_kabocha01),
+ 1.0f, null, basicVulnerabilityVolume);
+
+ SpriteAnimation idle = new SpriteAnimation(0, 12);
+ idle.addFrame(frame1);
+ idle.addFrame(frame5);
+ idle.addFrame(frame4);
+ idle.addFrame(frame3);
+ idle.addFrame(frame2);
+ idle.addFrame(frame6);
+ idle.addFrame(frame6);
+ idle.addFrame(frame3);
+ idle.addFrame(frame2);
+ idle.addFrame(frame1);
+ idle.addFrame(frame2);
+ idle.addFrame(frame6);
+
+ idle.setLoop(true);
+
+
+ staticData.add(idle);
+
+ setStaticData(GameObjectType.KABOCHA_TERMINAL, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_OBJECT);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ DynamicCollisionComponent dynamicCollision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(dynamicCollision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ hitReact.setSpawnGameEventOnHit(HitType.COLLECT, GameFlowEvent.EVENT_SHOW_DIALOG_CHARACTER2, 0);
+
+ SelectDialogComponent dialogSelect = (SelectDialogComponent)allocateComponent(SelectDialogComponent.class);
+ dialogSelect.setHitReact(hitReact);
+
+ dynamicCollision.setHitReactionComponent(hitReact);
+
+ object.add(dialogSelect);
+ object.add(render);
+ object.add(sprite);
+ object.add(dynamicCollision);
+ object.add(hitReact);
+
+ addStaticData(GameObjectType.KABOCHA_TERMINAL, object, sprite);
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnEnemyEvilKabocha(float positionX, float positionY, boolean flipHorizontal) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mNormalActivationRadius;
+ object.width = 128;
+ object.height = 128;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.EVIL_KABOCHA);
+ if (staticData == null) {
+ final int staticObjectCount = 8;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ GameComponent gravity = allocateComponent(GravityComponent.class);
+ GameComponent movement = allocateComponent(MovementComponent.class);
+
+ SimplePhysicsComponent physics = (SimplePhysicsComponent)allocateComponent(SimplePhysicsComponent.class);
+ physics.setBounciness(0.0f);
+
+ FixedSizeArray basicVulnerabilityVolume =
+ new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new AABoxCollisionVolume(52, 5, 26, 80, HitType.HIT));
+
+ SpriteAnimation idle = new SpriteAnimation(NPCAnimationComponent.IDLE, 1);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_evil_stand),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+
+ AnimationFrame walkFrame1 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_evil_walk01),
+ Utils.framesToTime(24, 3), null, basicVulnerabilityVolume);
+ AnimationFrame walkFrame2 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_evil_walk02),
+ Utils.framesToTime(24, 3), null, basicVulnerabilityVolume);
+ AnimationFrame walkFrame3 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_evil_walk03),
+ Utils.framesToTime(24, 3), null, basicVulnerabilityVolume);
+ AnimationFrame walkFrame4 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_evil_walk04),
+ Utils.framesToTime(24, 3), null, basicVulnerabilityVolume);
+ AnimationFrame walkFrame5 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_evil_walk05),
+ Utils.framesToTime(24, 3), null, basicVulnerabilityVolume);
+ AnimationFrame walkFrame6 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_evil_walk06),
+ Utils.framesToTime(24, 3), null, basicVulnerabilityVolume);
+
+ SpriteAnimation walk = new SpriteAnimation(NPCAnimationComponent.WALK, 6);
+ walk.addFrame(walkFrame1);
+ walk.addFrame(walkFrame2);
+ walk.addFrame(walkFrame3);
+ walk.addFrame(walkFrame4);
+ walk.addFrame(walkFrame5);
+ walk.addFrame(walkFrame6);
+
+ walk.setLoop(true);
+
+
+ SpriteAnimation surprised = new SpriteAnimation(NPCAnimationComponent.SURPRISED, 1);
+ surprised.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_evil_surprised),
+ 4.0f, null, null));
+
+
+ SpriteAnimation hit = new SpriteAnimation(NPCAnimationComponent.TAKE_HIT, 2);
+ hit.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_evil_hit01),
+ Utils.framesToTime(24, 1), null, null));
+ hit.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_evil_hit02),
+ Utils.framesToTime(24, 10), null, null));
+
+ SpriteAnimation die = new SpriteAnimation(NPCAnimationComponent.DEATH, 5);
+ die.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_evil_die01),
+ Utils.framesToTime(24, 6), null, null));
+ die.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_evil_stand),
+ Utils.framesToTime(24, 2), null, null));
+ die.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_evil_die02),
+ Utils.framesToTime(24, 2), null, null));
+ die.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_evil_die03),
+ Utils.framesToTime(24, 2), null, null));
+ die.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_kabocha_evil_die04),
+ Utils.framesToTime(24, 6), null, null));
+
+ staticData.add(gravity);
+ staticData.add(movement);
+ staticData.add(physics);
+ staticData.add(idle);
+ staticData.add(walk);
+ staticData.add(surprised);
+ staticData.add(hit);
+ staticData.add(die);
+
+ setStaticData(GameObjectType.EVIL_KABOCHA, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.NPC);
+
+ BackgroundCollisionComponent bgcollision = (BackgroundCollisionComponent)allocateComponent(BackgroundCollisionComponent.class);
+ bgcollision.setSize(38, 82);
+ bgcollision.setOffset(45, 5);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ NPCAnimationComponent animation = (NPCAnimationComponent)allocateComponent(NPCAnimationComponent.class);
+ animation.setSprite(sprite);
+
+ ChannelSystem.Channel surpriseChannel = null;
+ ChannelSystem channelSystem = BaseObject.sSystemRegistry.channelSystem;
+ surpriseChannel = channelSystem.registerChannel(sSurprisedNPCChannel);
+ animation.setChannel(surpriseChannel);
+ animation.setChannelTrigger(NPCAnimationComponent.SURPRISED);
+
+ NPCComponent patrol = (NPCComponent)allocateComponent(NPCComponent.class);
+ patrol.setSpeeds(50.0f, 50.0f, 0.0f, -10.0f, 200.0f);
+ patrol.setReactToHits(true);
+ patrol.setGameEvent(GameFlowEvent.EVENT_SHOW_ANIMATION, AnimationPlayerActivity.ROKUDOU_ENDING, true);
+
+ DynamicCollisionComponent collision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(collision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ collision.setHitReactionComponent(hitReact);
+
+ SoundSystem sound = sSystemRegistry.soundSystem;
+ if (sound != null) {
+ hitReact.setTakeHitSound(HitType.HIT, sound.load(R.raw.sound_kabocha_hit));
+ }
+
+ patrol.setHitReactionComponent(hitReact);
+
+ object.team = Team.ENEMY;
+ object.life = 3;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+
+ object.add(render);
+ object.add(sprite);
+ object.add(bgcollision);
+ object.add(animation);
+ object.add(patrol);
+ object.add(collision);
+ object.add(hitReact);
+
+ addStaticData(GameObjectType.EVIL_KABOCHA, object, sprite);
+
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnEnemyRokudou(float positionX, float positionY, boolean flipHorizontal) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+ // Make sure related textures are loaded.
+ textureLibrary.allocateTexture(R.drawable.energy_ball01);
+ textureLibrary.allocateTexture(R.drawable.energy_ball02);
+ textureLibrary.allocateTexture(R.drawable.energy_ball03);
+ textureLibrary.allocateTexture(R.drawable.energy_ball04);
+
+ textureLibrary.allocateTexture(R.drawable.effect_bullet01);
+ textureLibrary.allocateTexture(R.drawable.effect_bullet02);
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mNormalActivationRadius;
+ object.width = 128;
+ object.height = 128;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.ROKUDOU);
+ if (staticData == null) {
+ final int staticObjectCount = 8;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ GameComponent movement = allocateComponent(MovementComponent.class);
+
+ SimplePhysicsComponent physics = (SimplePhysicsComponent)allocateComponent(SimplePhysicsComponent.class);
+ physics.setBounciness(0.0f);
+
+ FixedSizeArray basicVulnerabilityVolume =
+ new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new AABoxCollisionVolume(45, 23, 42, 75, HitType.HIT));
+
+ SpriteAnimation idle = new SpriteAnimation(NPCAnimationComponent.IDLE, 1);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_rokudou_fight_stand),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+
+ SpriteAnimation fly = new SpriteAnimation(NPCAnimationComponent.WALK, 2);
+ fly.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_rokudou_fight_fly01),
+ 1.0f, null, basicVulnerabilityVolume));
+ fly.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_rokudou_fight_fly02),
+ 1.0f, null, basicVulnerabilityVolume));
+ fly.setLoop(true);
+
+ SpriteAnimation shoot = new SpriteAnimation(NPCAnimationComponent.SHOOT, 2);
+ shoot.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_rokudou_fight_shoot01),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume));
+ shoot.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_rokudou_fight_shoot02),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume));
+ shoot.setLoop(true);
+
+
+ SpriteAnimation surprised = new SpriteAnimation(NPCAnimationComponent.SURPRISED, 1);
+ surprised.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_rokudou_fight_surprise),
+ 4.0f, null, null));
+
+
+ SpriteAnimation hit = new SpriteAnimation(NPCAnimationComponent.TAKE_HIT, 7);
+ AnimationFrame hitFrame1 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_rokudou_fight_hit01),
+ Utils.framesToTime(24, 2), null, null);
+ AnimationFrame hitFrame2 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_rokudou_fight_hit02),
+ Utils.framesToTime(24, 1), null, null);
+ AnimationFrame hitFrame3 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_rokudou_fight_hit03),
+ Utils.framesToTime(24, 1), null, null);
+
+ hit.addFrame(hitFrame1);
+ hit.addFrame(hitFrame2);
+ hit.addFrame(hitFrame3);
+ hit.addFrame(hitFrame2);
+ hit.addFrame(hitFrame3);
+ hit.addFrame(hitFrame2);
+ hit.addFrame(hitFrame3);
+
+ SpriteAnimation die = new SpriteAnimation(NPCAnimationComponent.DEATH, 5);
+ die.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_rokudou_fight_stand),
+ Utils.framesToTime(24, 6), null, null));
+ die.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_rokudou_fight_die01),
+ Utils.framesToTime(24, 2), null, null));
+ die.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_rokudou_fight_die02),
+ Utils.framesToTime(24, 4), null, null));
+ die.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_rokudou_fight_die03),
+ Utils.framesToTime(24, 6), null, null));
+ die.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_rokudou_fight_die04),
+ Utils.framesToTime(24, 6), null, null));
+
+ staticData.add(movement);
+ staticData.add(physics);
+ staticData.add(idle);
+ staticData.add(fly);
+ staticData.add(surprised);
+ staticData.add(hit);
+ staticData.add(die);
+ staticData.add(shoot);
+
+ setStaticData(GameObjectType.ROKUDOU, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.NPC);
+
+ BackgroundCollisionComponent bgcollision = (BackgroundCollisionComponent)allocateComponent(BackgroundCollisionComponent.class);
+ bgcollision.setSize(45, 75);
+ bgcollision.setOffset(45, 23);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+
+
+ NPCAnimationComponent animation = (NPCAnimationComponent)allocateComponent(NPCAnimationComponent.class);
+ animation.setSprite(sprite);
+ animation.setFlying(true);
+
+ ChannelSystem.Channel surpriseChannel = null;
+ ChannelSystem channelSystem = BaseObject.sSystemRegistry.channelSystem;
+ surpriseChannel = channelSystem.registerChannel(sSurprisedNPCChannel);
+ animation.setChannel(surpriseChannel);
+ animation.setChannelTrigger(NPCAnimationComponent.SURPRISED);
+
+ NPCComponent patrol = (NPCComponent)allocateComponent(NPCComponent.class);
+ patrol.setSpeeds(500.0f, 100.0f, 100.0f, -100.0f, 400.0f);
+ patrol.setFlying(true);
+ patrol.setReactToHits(true);
+ patrol.setGameEvent(GameFlowEvent.EVENT_SHOW_ANIMATION, AnimationPlayerActivity.KABOCHA_ENDING, true);
+ patrol.setPauseOnAttack(false);
+
+ DynamicCollisionComponent collision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(collision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ collision.setHitReactionComponent(hitReact);
+
+ SoundSystem sound = sSystemRegistry.soundSystem;
+ if (sound != null) {
+ hitReact.setTakeHitSound(HitType.HIT, sound.load(R.raw.sound_rokudou_hit));
+ }
+
+ patrol.setHitReactionComponent(hitReact);
+
+ ChangeComponentsComponent deathSwap = (ChangeComponentsComponent)allocateComponent(ChangeComponentsComponent.class);
+ deathSwap.addSwapInComponent(allocateComponent(GravityComponent.class));
+ deathSwap.setSwapAction(ActionType.DEATH);
+
+ LaunchProjectileComponent gun
+ = (LaunchProjectileComponent)allocateComponent(LaunchProjectileComponent.class);
+ gun.setShotsPerSet(1);
+ gun.setSetsPerActivation(-1);
+ gun.setDelayBetweenSets(1.5f);
+ gun.setObjectTypeToSpawn(GameObjectType.ENERGY_BALL);
+ gun.setOffsetX(75);
+ gun.setOffsetY(42);
+ gun.setRequiredAction(GameObject.ActionType.ATTACK);
+ gun.setVelocityX(300.0f);
+ gun.setVelocityY(-300.0f);
+ gun.setShootSound(sound.load(R.raw.sound_poing));
+
+
+ LaunchProjectileComponent gun2
+ = (LaunchProjectileComponent)allocateComponent(LaunchProjectileComponent.class);
+ gun2.setShotsPerSet(5);
+ gun2.setDelayBetweenShots(0.1f);
+ gun2.setSetsPerActivation(-1);
+ gun2.setDelayBetweenSets(2.5f);
+ gun2.setObjectTypeToSpawn(GameObjectType.TURRET_BULLET);
+ gun2.setOffsetX(75);
+ gun2.setOffsetY(42);
+ gun2.setRequiredAction(GameObject.ActionType.ATTACK);
+ gun2.setVelocityX(300.0f);
+ gun2.setVelocityY(-300.0f);
+ gun.setShootSound(sound.load(R.raw.sound_gun));
+
+
+ object.team = Team.ENEMY;
+ object.life = 3;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+
+ // HACK! Since there's no gravity and this is a big character, align him to the floor
+ // manually.
+ object.getPosition().y -= 23;
+
+ object.add(render);
+ object.add(sprite);
+ object.add(bgcollision);
+ object.add(animation);
+ object.add(patrol);
+ object.add(collision);
+ object.add(hitReact);
+ object.add(deathSwap);
+ object.add(gun);
+ object.add(gun2);
+
+ addStaticData(GameObjectType.ROKUDOU, object, sprite);
+
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+
+ public GameObject spawnPlayerGhost(float positionX, float positionY, GameObject player, float lifeTime) {
+ TextureLibrary textureLibrary = sSystemRegistry.longTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mAlwaysActive;
+ object.width = 64;
+ object.height = 64;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.GHOST);
+ if (staticData == null) {
+ final int staticObjectCount = 4;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ //GravityComponent gravity = (GravityComponent)allocateComponent(GravityComponent.class);
+ //gravity.setGravityMultiplier(0.1f);
+
+ GameComponent movement = allocateComponent(MovementComponent.class);
+ SimplePhysicsComponent physics = (SimplePhysicsComponent)allocateComponent(SimplePhysicsComponent.class);
+ physics.setBounciness(0.6f);
+
+ GhostComponent ghost = (GhostComponent)allocateComponent(GhostComponent.class);
+ ghost.setMovementSpeed(2000.0f);
+ ghost.setAcceleration(300.0f);
+ ghost.setUseOrientationSensor(true);
+ ghost.setKillOnRelease(true);
+
+ SoundSystem sound = BaseObject.sSystemRegistry.soundSystem;
+ if (sound != null) {
+ ghost.setAmbientSound(sound.load(R.raw.sound_possession));
+ }
+
+ FixedSizeArray basicAttackVolume =
+ new FixedSizeArray(1);
+ basicAttackVolume.add(new SphereCollisionVolume(32, 32, 32, HitType.POSSESS));
+
+ SpriteAnimation idle = new SpriteAnimation(0, 4);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.getTextureByResource(R.drawable.effect_energyball01),
+ Utils.framesToTime(24, 1), basicAttackVolume, null));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.getTextureByResource(R.drawable.effect_energyball02),
+ Utils.framesToTime(24, 1), basicAttackVolume, null));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.getTextureByResource(R.drawable.effect_energyball03),
+ Utils.framesToTime(24, 1), basicAttackVolume, null));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.getTextureByResource(R.drawable.effect_energyball04),
+ Utils.framesToTime(24, 1), basicAttackVolume, null));
+ idle.setLoop(true);
+
+ //staticData.add(gravity);
+ staticData.add(movement);
+ staticData.add(physics);
+ staticData.add(ghost);
+ staticData.add(idle);
+
+ setStaticData(GameObjectType.GHOST, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.PROJECTILE);
+
+ BackgroundCollisionComponent bgcollision = (BackgroundCollisionComponent)allocateComponent(BackgroundCollisionComponent.class);
+ bgcollision.setSize(64, 64);
+ bgcollision.setOffset(0, 0);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+
+ DynamicCollisionComponent dynamicCollision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(dynamicCollision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ hitReact.setDieOnAttack(true);
+
+ dynamicCollision.setHitReactionComponent(hitReact);
+ LifetimeComponent life = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+ // when the ghost dies it either releases itself or passes control to another object, so we
+ // don't want control to return to the player.
+
+ life.setReleaseGhostOnDeath(false);
+
+
+ object.life = 1;
+
+ object.add(bgcollision);
+ object.add(render);
+ object.add(sprite);
+ object.add(dynamicCollision);
+ object.add(hitReact);
+ object.add(life);
+
+ addStaticData(GameObjectType.GHOST, object, sprite);
+
+ object.commitUpdates();
+
+ GhostComponent ghost = object.findByClass(GhostComponent.class);
+ if (ghost != null) {
+ ghost.setLifeTime(lifeTime);
+ }
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnEnergyBall(float positionX, float positionY, boolean flipHorizontal) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 32;
+ object.height = 32;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.ENERGY_BALL);
+ if (staticData == null) {
+ final int staticObjectCount = 2;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ GameComponent movement = allocateComponent(MovementComponent.class);
+
+ FixedSizeArray basicAttackVolume =
+ new FixedSizeArray(1);
+ basicAttackVolume.add(new SphereCollisionVolume(16, 16, 16, HitType.HIT));
+
+ SpriteAnimation idle = new SpriteAnimation(0, 4);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.energy_ball01),
+ Utils.framesToTime(24, 1), basicAttackVolume, null));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.energy_ball02),
+ Utils.framesToTime(24, 1), basicAttackVolume, null));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.energy_ball03),
+ Utils.framesToTime(24, 1), basicAttackVolume, null));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.energy_ball04),
+ Utils.framesToTime(24, 1), basicAttackVolume, null));
+ idle.setLoop(true);
+
+ staticData.add(movement);
+ staticData.add(idle);
+
+ setStaticData(GameObjectType.ENERGY_BALL, staticData);
+
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.PROJECTILE);
+
+ LifetimeComponent lifetime = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+ lifetime.setTimeUntilDeath(5.0f);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ DynamicCollisionComponent dynamicCollision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(dynamicCollision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ hitReact.setDieOnAttack(true);
+
+ dynamicCollision.setHitReactionComponent(hitReact);
+
+ object.life = 1;
+ object.team = Team.ENEMY;
+ object.destroyOnDeactivation = true;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+
+ object.add(lifetime);
+ object.add(render);
+ object.add(sprite);
+ object.add(dynamicCollision);
+ object.add(hitReact);
+
+ addStaticData(GameObjectType.ENERGY_BALL, object, sprite);
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnWandaShot(float positionX, float positionY, boolean flipHorizontal) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 32;
+ object.height = 32;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.WANDA_SHOT);
+ if (staticData == null) {
+ final int staticObjectCount = 2;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ GameComponent movement = allocateComponent(MovementComponent.class);
+
+ FixedSizeArray basicAttackVolume =
+ new FixedSizeArray(1);
+ basicAttackVolume.add(new SphereCollisionVolume(16, 16, 16, HitType.HIT));
+
+ SpriteAnimation idle = new SpriteAnimation(0, 4);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.energy_ball01),
+ Utils.framesToTime(24, 1), basicAttackVolume, null));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.energy_ball02),
+ Utils.framesToTime(24, 1), basicAttackVolume, null));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.energy_ball03),
+ Utils.framesToTime(24, 1), basicAttackVolume, null));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.energy_ball04),
+ Utils.framesToTime(24, 1), basicAttackVolume, null));
+ idle.setLoop(true);
+
+ staticData.add(movement);
+ staticData.add(idle);
+
+ setStaticData(GameObjectType.WANDA_SHOT, staticData);
+
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.PROJECTILE);
+
+ LifetimeComponent lifetime = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+ lifetime.setTimeUntilDeath(5.0f);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ DynamicCollisionComponent dynamicCollision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(dynamicCollision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ //hitReact.setDieOnAttack(true);
+
+ dynamicCollision.setHitReactionComponent(hitReact);
+
+ object.life = 1;
+ object.team = Team.NONE;
+ object.destroyOnDeactivation = true;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+
+ object.add(lifetime);
+ object.add(render);
+ object.add(sprite);
+ object.add(dynamicCollision);
+ object.add(hitReact);
+
+ addStaticData(GameObjectType.WANDA_SHOT, object, sprite);
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnCannonBall(float positionX, float positionY, boolean flipHorizontal) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 32;
+ object.height = 32;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.CANNON_BALL);
+ if (staticData == null) {
+ final int staticObjectCount = 2;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ GameComponent movement = allocateComponent(MovementComponent.class);
+
+ FixedSizeArray basicAttackVolume =
+ new FixedSizeArray(1);
+ basicAttackVolume.add(new SphereCollisionVolume(8, 16, 16, HitType.HIT));
+
+ SpriteAnimation idle = new SpriteAnimation(0, 1);
+ idle.addFrame(new AnimationFrame(textureLibrary.allocateTexture(R.drawable.snail_bomb),
+ Utils.framesToTime(24, 1), basicAttackVolume, null));
+
+ staticData.add(movement);
+ staticData.add(idle);
+
+ setStaticData(GameObjectType.CANNON_BALL, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.PROJECTILE);
+
+ LifetimeComponent lifetime = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+ lifetime.setTimeUntilDeath(3.0f);
+ lifetime.setDieOnHitBackground(true);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ DynamicCollisionComponent dynamicCollision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(dynamicCollision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ hitReact.setDieOnAttack(true);
+
+ dynamicCollision.setHitReactionComponent(hitReact);
+
+ SimpleCollisionComponent collision = (SimpleCollisionComponent)allocateComponent(SimpleCollisionComponent.class);
+
+
+ object.life = 1;
+ object.team = Team.ENEMY;
+ object.destroyOnDeactivation = true;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+
+ object.add(lifetime);
+ object.add(render);
+ object.add(sprite);
+ object.add(dynamicCollision);
+ object.add(hitReact);
+ object.add(collision);
+
+ addStaticData(GameObjectType.CANNON_BALL, object, sprite);
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnTurretBullet(float positionX, float positionY, boolean flipHorizontal) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 16;
+ object.height = 16;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.TURRET_BULLET);
+ if (staticData == null) {
+ final int staticObjectCount = 2;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ GameComponent movement = allocateComponent(MovementComponent.class);
+
+ FixedSizeArray basicAttackVolume =
+ new FixedSizeArray(1);
+ basicAttackVolume.add(new SphereCollisionVolume(8, 8, 8, HitType.HIT));
+
+ SpriteAnimation idle = new SpriteAnimation(0, 2);
+ idle.addFrame(new AnimationFrame(textureLibrary.allocateTexture(R.drawable.effect_bullet01),
+ Utils.framesToTime(24, 1), basicAttackVolume, null));
+ idle.addFrame(new AnimationFrame(textureLibrary.allocateTexture(R.drawable.effect_bullet02),
+ Utils.framesToTime(24, 1), basicAttackVolume, null));
+ idle.setLoop(true);
+
+ staticData.add(movement);
+ staticData.add(idle);
+
+ setStaticData(GameObjectType.TURRET_BULLET, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.PROJECTILE);
+
+ LifetimeComponent lifetime = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+ lifetime.setTimeUntilDeath(3.0f);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ DynamicCollisionComponent dynamicCollision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(dynamicCollision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ hitReact.setDieOnAttack(true);
+
+ dynamicCollision.setHitReactionComponent(hitReact);
+
+
+ object.life = 1;
+ object.team = Team.ENEMY;
+ object.destroyOnDeactivation = true;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+
+ object.add(lifetime);
+ object.add(render);
+ object.add(sprite);
+ object.add(dynamicCollision);
+ object.add(hitReact);
+
+ addStaticData(GameObjectType.TURRET_BULLET, object, sprite);
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnBrobotBullet(float positionX, float positionY, boolean flipHorizontal) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 64;
+ object.height = 64;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.BROBOT_BULLET);
+ if (staticData == null) {
+ final int staticObjectCount = 2;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ GameComponent movement = allocateComponent(MovementComponent.class);
+
+ SpriteAnimation idle = new SpriteAnimation(0, 3);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_brobot_walk01),
+ Utils.framesToTime(24, 1), null, null));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_brobot_walk02),
+ Utils.framesToTime(24, 1), null, null));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.enemy_brobot_walk03),
+ Utils.framesToTime(24, 1), null, null));
+ idle.setLoop(true);
+
+ staticData.add(movement);
+ staticData.add(idle);
+
+ setStaticData(GameObjectType.BROBOT_BULLET, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.PROJECTILE);
+
+ LifetimeComponent lifetime = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+ lifetime.setTimeUntilDeath(3.0f);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ object.life = 1;
+ object.team = Team.ENEMY;
+ object.destroyOnDeactivation = true;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+
+ object.add(lifetime);
+ object.add(render);
+ object.add(sprite);
+
+
+ addStaticData(GameObjectType.BROBOT_BULLET, object, sprite);
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnCoin(float positionX, float positionY) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 16;
+ object.height = 16;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.COIN);
+ if (staticData == null) {
+ final int staticObjectCount = 2;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ FixedSizeArray basicVulnerabilityVolume = null; /*new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new SphereCollisionVolume(8, 8, 8));
+ basicVulnerabilityVolume.get(0).setHitType(HitType.COLLECT);*/
+
+ SpriteAnimation idle = new SpriteAnimation(0, 5);
+ idle.addFrame(new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_coin01),
+ Utils.framesToTime(24, 30), null, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_coin02),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_coin03),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_coin04),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_coin05),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume));
+ idle.setLoop(true);
+
+ InventoryComponent.UpdateRecord addCoin = new InventoryComponent.UpdateRecord();
+ addCoin.coinCount = 1;
+
+ staticData.add(addCoin);
+ staticData.add(idle);
+
+ setStaticData(GameObjectType.COIN, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_OBJECT);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ //DynamicCollisionComponent dynamicCollision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ //sprite.setCollisionComponent(dynamicCollision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ hitReact.setDieWhenCollected(true);
+ hitReact.setInvincible(true);
+
+ HitPlayerComponent hitPlayer = (HitPlayerComponent)allocateComponent(HitPlayerComponent.class);
+ hitPlayer.setup(32, hitReact, HitType.COLLECT, false);
+
+ SoundSystem sound = sSystemRegistry.soundSystem;
+ if (sound != null) {
+ hitReact.setTakeHitSound(HitType.COLLECT, sound.load(R.raw.ding));
+ }
+
+ // TODO: this is pretty dumb. The static data binding needs to be made generic.
+ final int staticDataSize = staticData.getCount();
+ for (int x = 0; x < staticDataSize; x++) {
+ final BaseObject entry = staticData.get(x);
+ if (entry instanceof InventoryComponent.UpdateRecord) {
+ hitReact.setInventoryUpdate((InventoryComponent.UpdateRecord)entry);
+ break;
+ }
+ }
+
+ //dynamicCollision.setHitReactionComponent(hitReact);
+
+ LifetimeComponent life = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+
+ object.life = 1;
+
+ object.add(render);
+ object.add(sprite);
+ //object.add(dynamicCollision);
+ object.add(hitPlayer);
+ object.add(hitReact);
+ object.add(life);
+
+ addStaticData(GameObjectType.COIN, object, sprite);
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnRuby(float positionX, float positionY) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 32;
+ object.height = 32;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.RUBY);
+ if (staticData == null) {
+ final int staticObjectCount = 2;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ FixedSizeArray basicVulnerabilityVolume = new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new SphereCollisionVolume(16, 16, 16));
+ basicVulnerabilityVolume.get(0).setHitType(HitType.COLLECT);
+
+ SpriteAnimation idle = new SpriteAnimation(0, 5);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.object_ruby01),
+ 2.0f, null, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.object_ruby02),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.object_ruby03),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.object_ruby04),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.object_ruby05),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume));
+ idle.setLoop(true);
+
+ InventoryComponent.UpdateRecord addRuby = new InventoryComponent.UpdateRecord();
+ addRuby.rubyCount = 1;
+
+ staticData.add(addRuby);
+
+ staticData.add(idle);
+ setStaticData(GameObjectType.RUBY, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_OBJECT);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ DynamicCollisionComponent dynamicCollision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(dynamicCollision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ hitReact.setDieWhenCollected(true);
+ hitReact.setInvincible(true);
+ // TODO: this is pretty dumb. The static data binding needs to be made generic.
+ final int staticDataSize = staticData.getCount();
+ for (int x = 0; x < staticDataSize; x++) {
+ final BaseObject entry = staticData.get(x);
+ if (entry instanceof InventoryComponent.UpdateRecord) {
+ hitReact.setInventoryUpdate((InventoryComponent.UpdateRecord)entry);
+ break;
+ }
+ }
+
+ dynamicCollision.setHitReactionComponent(hitReact);
+
+ LifetimeComponent life = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+ life.setObjectToSpawnOnDeath(GameObjectType.GEM_EFFECT_SPAWNER);
+
+ object.life = 1;
+
+ object.add(render);
+ object.add(sprite);
+ object.add(dynamicCollision);
+ object.add(hitReact);
+ object.add(life);
+
+ addStaticData(GameObjectType.RUBY, object, sprite);
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnDiary(float positionX, float positionY) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+ LevelSystem level = sSystemRegistry.levelSystem;
+ if (level != null) {
+ final LevelTree.Level currentLevel = level.getCurrentLevel();
+ if (currentLevel != null && currentLevel.diaryCollected) {
+ return null;
+ }
+ }
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 32;
+ object.height = 32;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.DIARY);
+ if (staticData == null) {
+ final int staticObjectCount = 2;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ FixedSizeArray basicVulnerabilityVolume = new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new SphereCollisionVolume(16, 16, 16));
+ basicVulnerabilityVolume.get(0).setHitType(HitType.COLLECT);
+
+ SpriteAnimation idle = new SpriteAnimation(0, 8);
+ AnimationFrame frame1 = new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_diary01),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume);
+ AnimationFrame frame2 = new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_diary02),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume);
+
+ idle.addFrame(new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_diary01),
+ 1.0f, null, basicVulnerabilityVolume));
+ idle.addFrame(frame2);
+ idle.addFrame(frame1);
+ idle.addFrame(frame2);
+ idle.addFrame(new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_diary03),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_diary04),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_diary05),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(textureLibrary.allocateTexture(R.drawable.object_diary06),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume));
+
+ idle.setLoop(true);
+
+ InventoryComponent.UpdateRecord addDiary = new InventoryComponent.UpdateRecord();
+ addDiary.diaryCount = 1;
+
+ staticData.add(addDiary);
+
+ staticData.add(idle);
+
+ setStaticData(GameObjectType.DIARY, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_OBJECT);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ DynamicCollisionComponent dynamicCollision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(dynamicCollision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ hitReact.setDieWhenCollected(true);
+ hitReact.setInvincible(true);
+ hitReact.setSpawnGameEventOnHit(CollisionParameters.HitType.COLLECT,
+ GameFlowEvent.EVENT_SHOW_DIARY, 0);
+ // TODO: this is pretty dumb. The static data binding needs to be made generic.
+ final int staticDataSize = staticData.getCount();
+ for (int x = 0; x < staticDataSize; x++) {
+ final BaseObject entry = staticData.get(x);
+ if (entry instanceof InventoryComponent.UpdateRecord) {
+ hitReact.setInventoryUpdate((InventoryComponent.UpdateRecord)entry);
+ break;
+ }
+ }
+
+ dynamicCollision.setHitReactionComponent(hitReact);
+
+ LifetimeComponent life = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+
+ object.life = 1;
+
+ object.add(render);
+ object.add(sprite);
+ object.add(dynamicCollision);
+ object.add(hitReact);
+ object.add(life);
+
+ addStaticData(GameObjectType.DIARY, object, sprite);
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnObjectDoor(float positionX, float positionY, GameObjectType type, boolean solid) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 32;
+ object.height = 64;
+
+ FixedSizeArray staticData = getStaticData(type);
+ if (staticData == null) {
+ final int staticObjectCount = 5;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ final int red_frames[] = {
+ R.drawable.object_door_red01,
+ R.drawable.object_door_red02,
+ R.drawable.object_door_red03,
+ R.drawable.object_door_red04,
+ };
+
+ final int blue_frames[] = {
+ R.drawable.object_door_blue01,
+ R.drawable.object_door_blue02,
+ R.drawable.object_door_blue03,
+ R.drawable.object_door_blue04,
+ };
+
+ final int green_frames[] = {
+ R.drawable.object_door_green01,
+ R.drawable.object_door_green02,
+ R.drawable.object_door_green03,
+ R.drawable.object_door_green04,
+ };
+
+ int frames[] = red_frames;
+
+ if (type == GameObjectType.DOOR_GREEN) {
+ frames = green_frames;
+ } else if (type == GameObjectType.DOOR_BLUE) {
+ frames = blue_frames;
+ }
+
+ FixedSizeArray vulnerabilityVolume = null;
+
+ AnimationFrame frame1 = new AnimationFrame(textureLibrary.allocateTexture(frames[0]),
+ Utils.framesToTime(24, 1), null, vulnerabilityVolume);
+ AnimationFrame frame2 = new AnimationFrame(textureLibrary.allocateTexture(frames[1]),
+ Utils.framesToTime(24, 2));
+ AnimationFrame frame3 = new AnimationFrame(textureLibrary.allocateTexture(frames[2]),
+ Utils.framesToTime(24, 2));
+ AnimationFrame frame4 = new AnimationFrame(textureLibrary.allocateTexture(frames[3]),
+ Utils.framesToTime(24, 1));
+
+ // one frame of closing is deadly
+
+ FixedSizeArray attackVolume =
+ new FixedSizeArray(1);
+ attackVolume.add(new AABoxCollisionVolume(12, 8, 8, 56));
+ attackVolume.get(0).setHitType(HitType.DEATH);
+
+
+
+ AnimationFrame closeFrame2 = new AnimationFrame(textureLibrary.allocateTexture(frames[1]),
+ Utils.framesToTime(24, 2), attackVolume, vulnerabilityVolume);
+
+ SpriteAnimation idle_closed = new SpriteAnimation(DoorAnimationComponent.Animation.CLOSED, 1);
+ idle_closed.addFrame(frame1);
+
+ SpriteAnimation idle_open = new SpriteAnimation(DoorAnimationComponent.Animation.OPEN, 1);
+ idle_open.addFrame(frame4);
+
+ SpriteAnimation open = new SpriteAnimation(DoorAnimationComponent.Animation.OPENING, 2);
+ open.addFrame(frame2);
+ open.addFrame(frame3);
+
+ SpriteAnimation close = new SpriteAnimation(DoorAnimationComponent.Animation.CLOSING, 2);
+ close.addFrame(frame3);
+ close.addFrame(closeFrame2);
+
+ SolidSurfaceComponent solidSurface
+ = (SolidSurfaceComponent)allocateComponent(SolidSurfaceComponent.class);
+ solidSurface.inititalize(4);
+ // box shape:
+ // ___ ___1
+ // | | 2| |3
+ // --- ---4
+ Vector2 surface1Start = new Vector2(0, object.height);
+ Vector2 surface1End = new Vector2(object.width, object.height);
+ Vector2 surface1Normal = new Vector2(0.0f, -1.0f);
+ surface1Normal.normalize();
+
+ Vector2 surface2Start = new Vector2(0, object.height);
+ Vector2 surface2End = new Vector2(0, 0);
+ Vector2 surface2Normal = new Vector2(-1.0f, 0.0f);
+ surface2Normal.normalize();
+
+ Vector2 surface3Start = new Vector2(object.width, object.height);
+ Vector2 surface3End = new Vector2(object.width, 0);
+ Vector2 surface3Normal = new Vector2(1.0f, 0);
+
+ Vector2 surface4Start = new Vector2(0, 0);
+ Vector2 surface4End = new Vector2(object.width, 0);
+ Vector2 surface4Normal = new Vector2(0, 1.0f);
+
+ solidSurface.addSurface(surface1Start, surface1End, surface1Normal);
+ solidSurface.addSurface(surface2Start, surface2End, surface2Normal);
+ solidSurface.addSurface(surface3Start, surface3End, surface3Normal);
+ solidSurface.addSurface(surface4Start, surface4End, surface4Normal);
+
+ staticData.add(idle_open);
+ staticData.add(idle_closed);
+ staticData.add(open);
+ staticData.add(close);
+ staticData.add(solidSurface);
+ setStaticData(type, staticData);
+ }
+
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.FOREGROUND_OBJECT);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ DoorAnimationComponent doorAnim = (DoorAnimationComponent)allocateComponent(DoorAnimationComponent.class);
+ doorAnim.setSprite(sprite);
+
+ SoundSystem sound = BaseObject.sSystemRegistry.soundSystem;
+ if (sound != null) {
+ doorAnim.setSounds(sound.load(R.raw.sound_open), sound.load(R.raw.sound_close));
+ }
+
+ ChannelSystem.Channel doorChannel = null;
+ ChannelSystem channelSystem = BaseObject.sSystemRegistry.channelSystem;
+ switch (type) {
+ case DOOR_RED:
+ doorChannel = channelSystem.registerChannel(sRedButtonChannel);
+ break;
+ case DOOR_BLUE:
+ doorChannel = channelSystem.registerChannel(sBlueButtonChannel);
+ break;
+ case DOOR_GREEN:
+ doorChannel = channelSystem.registerChannel(sGreenButtonChannel);
+ break;
+ }
+ doorAnim.setChannel(doorChannel);
+
+ DynamicCollisionComponent dynamicCollision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(dynamicCollision);
+
+ HitReactionComponent hitReact
+ = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ dynamicCollision.setHitReactionComponent(hitReact);
+
+
+
+ object.add(render);
+ object.add(sprite);
+ object.add(doorAnim);
+ object.add(dynamicCollision);
+ object.add(hitReact);
+ addStaticData(type, object, sprite);
+
+ object.commitUpdates();
+
+ SolidSurfaceComponent solidSurface = object.findByClass(SolidSurfaceComponent.class);
+ if (solid) {
+ doorAnim.setSolidSurface(solidSurface);
+ } else {
+ object.remove(solidSurface);
+ object.commitUpdates();
+ }
+
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnObjectButton(float positionX, float positionY, GameObjectType type) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 32;
+ object.height = 32;
+
+ FixedSizeArray staticData = getStaticData(type);
+ if (staticData == null) {
+ final int staticObjectCount = 2;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ final int red_frames[] = {
+ R.drawable.object_button_red,
+ R.drawable.object_button_pressed_red,
+ };
+
+ final int blue_frames[] = {
+ R.drawable.object_button_blue,
+ R.drawable.object_button_pressed_blue,
+ };
+
+ final int green_frames[] = {
+ R.drawable.object_button_green,
+ R.drawable.object_button_pressed_green,
+ };
+
+ int frames[] = red_frames;
+
+ if (type == GameObjectType.BUTTON_GREEN) {
+ frames = green_frames;
+ } else if (type == GameObjectType.BUTTON_BLUE) {
+ frames = blue_frames;
+ }
+
+ FixedSizeArray vulnerabilityVolume =
+ new FixedSizeArray(1);
+ vulnerabilityVolume.add(new AABoxCollisionVolume(0, 0, 32, 16));
+ vulnerabilityVolume.get(0).setHitType(HitType.DEPRESS);
+
+ AnimationFrame frame1 = new AnimationFrame(textureLibrary.allocateTexture(frames[0]),
+ Utils.framesToTime(24, 1), null, vulnerabilityVolume);
+ AnimationFrame frame2 = new AnimationFrame(textureLibrary.allocateTexture(frames[1]),
+ Utils.framesToTime(24, 1), null, vulnerabilityVolume);
+
+ SpriteAnimation idle = new SpriteAnimation(ButtonAnimationComponent.Animation.UP, 1);
+ idle.addFrame(frame1);
+
+ SpriteAnimation pressed = new SpriteAnimation(ButtonAnimationComponent.Animation.DOWN, 1);
+ pressed.addFrame(frame2);
+
+ staticData.add(idle);
+ staticData.add(pressed);
+
+ setStaticData(type, staticData);
+ }
+
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_OBJECT);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ ButtonAnimationComponent button = (ButtonAnimationComponent)allocateComponent(ButtonAnimationComponent.class);
+ button.setSprite(sprite);
+
+ SoundSystem sound = BaseObject.sSystemRegistry.soundSystem;
+ if (sound != null) {
+ button.setDepressSound(sound.load(R.raw.sound_button));
+ }
+
+ ChannelSystem.Channel buttonChannel = null;
+ ChannelSystem channelSystem = BaseObject.sSystemRegistry.channelSystem;
+ switch (type) {
+ case BUTTON_RED:
+ buttonChannel = channelSystem.registerChannel(sRedButtonChannel);
+ break;
+ case BUTTON_BLUE:
+ buttonChannel = channelSystem.registerChannel(sBlueButtonChannel);
+ break;
+ case BUTTON_GREEN:
+ buttonChannel = channelSystem.registerChannel(sGreenButtonChannel);
+ break;
+ }
+ button.setChannel(buttonChannel);
+
+ DynamicCollisionComponent dynamicCollision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(dynamicCollision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ hitReact.setInvincible(false);
+
+
+
+ dynamicCollision.setHitReactionComponent(hitReact);
+
+ object.team = Team.NONE;
+
+ object.add(render);
+ object.add(sprite);
+ object.add(button);
+ object.add(dynamicCollision);
+ object.add(hitReact);
+
+ addStaticData(type, object, sprite);
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnObjectCannon(float positionX, float positionY) {
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 64;
+ object.height = 128;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.CANNON);
+ if (staticData == null) {
+ final int staticObjectCount = 2;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ FixedSizeArray attackVolume =
+ new FixedSizeArray(1);
+ attackVolume.add(new AABoxCollisionVolume(16, 16, 32, 80));
+ attackVolume.get(0).setHitType(HitType.LAUNCH);
+
+ AnimationFrame frame1 = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.object_cannon),
+ 1.0f, attackVolume, null);
+
+ SpriteAnimation idle = new SpriteAnimation(GenericAnimationComponent.Animation.IDLE, 1);
+ idle.addFrame(frame1);
+
+ AnimationFrame frame1NoAttack = new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.object_cannon),
+ 1.0f, null, null);
+
+ SpriteAnimation shoot = new SpriteAnimation(GenericAnimationComponent.Animation.ATTACK, 1);
+ shoot.addFrame(frame1NoAttack);
+
+ staticData.add(idle);
+ staticData.add(shoot);
+
+ setStaticData(GameObjectType.CANNON, staticData);
+ }
+
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.FOREGROUND_OBJECT);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ LauncherComponent launcher = (LauncherComponent)allocateComponent(LauncherComponent.class);
+ launcher.setLaunchEffect(GameObjectType.SMOKE_POOF, 32.0f, 85.0f);
+
+ SoundSystem sound = BaseObject.sSystemRegistry.soundSystem;
+ if (sound != null) {
+ launcher.setLaunchSound(sound.load(R.raw.sound_cannon));
+ }
+
+
+ DynamicCollisionComponent dynamicCollision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(dynamicCollision);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ hitReact.setInvincible(false);
+ hitReact.setLauncherComponent(launcher, HitType.LAUNCH);
+
+ dynamicCollision.setHitReactionComponent(hitReact);
+
+ GenericAnimationComponent anim = (GenericAnimationComponent)allocateComponent(GenericAnimationComponent.class);
+ anim.setSprite(sprite);
+
+ object.team = Team.NONE;
+
+ object.add(render);
+ object.add(sprite);
+ object.add(dynamicCollision);
+ object.add(hitReact);
+ object.add(launcher);
+ object.add(anim);
+
+ addStaticData(GameObjectType.CANNON, object, sprite);
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnObjectBrobotSpawner(float positionX, float positionY, boolean flipHorizontal) {
+
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+ // This is pretty heavy-handed.
+ // TODO: figure out a general solution for objects that depend on other objects.
+ textureLibrary.allocateTexture(R.drawable.enemy_brobot_idle01);
+ textureLibrary.allocateTexture(R.drawable.enemy_brobot_idle02);
+ textureLibrary.allocateTexture(R.drawable.enemy_brobot_idle03);
+ textureLibrary.allocateTexture(R.drawable.enemy_brobot_walk01);
+ textureLibrary.allocateTexture(R.drawable.enemy_brobot_walk02);
+ textureLibrary.allocateTexture(R.drawable.enemy_brobot_walk03);
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 64;
+ object.height = 64;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.BROBOT_SPAWNER);
+ if (staticData == null) {
+ final int staticObjectCount = 3;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ FixedSizeArray basicVulnerabilityVolume =
+ new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new SphereCollisionVolume(32, 32, 32));
+ basicVulnerabilityVolume.get(0).setHitType(HitType.POSSESS);
+
+ SpriteAnimation idle = new SpriteAnimation(0, 1);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.object_brobot_machine),
+ 1.0f, null, basicVulnerabilityVolume));
+
+ SolidSurfaceComponent solidSurface
+ = (SolidSurfaceComponent)allocateComponent(SolidSurfaceComponent.class);
+ solidSurface.inititalize(3);
+ /*
+ 0:2,0:8,59:-0.99532399996093,0.09659262446878
+ 0:8,59:61,33:0.44551558813576,0.89527418187282
+ 0:61,33:61,-1:1,0
+
+ */
+ // trapezoid shape:
+ // |\ |\2
+ // | | 1| |3
+
+ Vector2 surface1Start = new Vector2(0, 0);
+ Vector2 surface1End = new Vector2(8.0f, 59.0f);
+ Vector2 surface1Normal = new Vector2(-0.9953f, 0.0965f);
+ surface1Normal.normalize();
+
+ Vector2 surface2Start = new Vector2(8.0f, 59.0f);
+ Vector2 surface2End = new Vector2(61.0f, 33.0f);
+ Vector2 surface2Normal = new Vector2(0.445515f, 0.89527f);
+ surface2Normal.normalize();
+
+ Vector2 surface3Start = new Vector2(61.0f, 33.0f);
+ Vector2 surface3End = new Vector2(61.0f, 0.0f);
+ Vector2 surface3Normal = new Vector2(1.0f, 0.0f);
+
+ solidSurface.addSurface(surface1Start, surface1End, surface1Normal);
+ solidSurface.addSurface(surface2Start, surface2End, surface2Normal);
+ solidSurface.addSurface(surface3Start, surface3End, surface3Normal);
+
+ GhostComponent ghost = (GhostComponent)allocateComponent(GhostComponent.class);
+ ghost.setTargetAction(ActionType.IDLE);
+ ghost.changeActionOnButton(ActionType.ATTACK);
+
+ SoundSystem sound = BaseObject.sSystemRegistry.soundSystem;
+ if (sound != null) {
+ ghost.setAmbientSound(sound.load(R.raw.sound_possession));
+ }
+
+ staticData.add(ghost);
+ staticData.add(solidSurface);
+ staticData.add(idle);
+
+
+ setStaticData(GameObjectType.BROBOT_SPAWNER, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_OBJECT);
+
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ DynamicCollisionComponent collision
+ = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(collision);
+
+ HitReactionComponent hitReact
+ = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ collision.setHitReactionComponent(hitReact);
+
+ LaunchProjectileComponent gun
+ = (LaunchProjectileComponent)allocateComponent(LaunchProjectileComponent.class);
+ gun.setDelayBeforeFirstSet(3.0f);
+ gun.setObjectTypeToSpawn(GameObjectType.BROBOT);
+ gun.setOffsetX(36);
+ gun.setOffsetY(50);
+ gun.setVelocityX(100.0f);
+ gun.setVelocityY(300.0f);
+ gun.enableProjectileTracking(1);
+
+ LaunchProjectileComponent possessedGun
+ = (LaunchProjectileComponent)allocateComponent(LaunchProjectileComponent.class);
+ possessedGun.setRequiredAction(ActionType.ATTACK);
+ possessedGun.setDelayBeforeFirstSet(0.0f);
+ possessedGun.setObjectTypeToSpawn(GameObjectType.BROBOT_BULLET);
+ possessedGun.setOffsetX(36);
+ possessedGun.setOffsetY(50);
+ possessedGun.setVelocityX(600.0f);
+ possessedGun.setVelocityY(600.0f);
+ possessedGun.setThetaError(0.3f);
+
+ ChangeComponentsComponent componentSwap = (ChangeComponentsComponent)allocateComponent(ChangeComponentsComponent.class);
+ componentSwap.addSwapOutComponent(gun);
+ componentSwap.addSwapInComponent(possessedGun);
+ componentSwap.setPingPongBehavior(true);
+
+ hitReact.setPossessionComponent(componentSwap);
+
+ object.team = Team.ENEMY;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ } else {
+ object.facingDirection.x = 1.0f;
+ }
+
+ object.add(render);
+ object.add(sprite);
+ object.add(gun);
+ object.add(collision);
+ object.add(hitReact);
+ object.add(componentSwap);
+
+
+ addStaticData(GameObjectType.BROBOT_SPAWNER, object, sprite);
+
+ object.commitUpdates();
+
+ GhostComponent possessedGhost = object.findByClass(GhostComponent.class);
+ if (possessedGhost != null) {
+ object.remove(possessedGhost); // Not supposed to be added yet.
+ componentSwap.addSwapInComponent(possessedGhost);
+ }
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+public GameObject spawnObjectBreakableBlock(float positionX, float positionY) {
+
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+ // Preload block piece texture.
+ textureLibrary.allocateTexture(R.drawable.object_debris_piece);
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 32;
+ object.height = 32;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.BREAKABLE_BLOCK);
+ if (staticData == null) {
+ final int staticObjectCount = 2;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ FixedSizeArray basicVulnerabilityVolume =
+ new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new AABoxCollisionVolume(7, 0, 32 - 7, 42, HitType.HIT));
+
+ SpriteAnimation idle = new SpriteAnimation(0, 1);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.object_debris_block),
+ 1.0f, null, basicVulnerabilityVolume));
+
+ SolidSurfaceComponent solidSurface
+ = (SolidSurfaceComponent)allocateComponent(SolidSurfaceComponent.class);
+ solidSurface.inititalize(4);
+
+ // box shape:
+ // ___ ___2
+ // | | 1| |3
+ // --- ---4
+
+ Vector2 surface1Start = new Vector2(0.0f, 0.0f);
+ Vector2 surface1End = new Vector2(0.0f, 32.0f);
+ Vector2 surface1Normal = new Vector2(-1.0f, 0.0f);
+ surface1Normal.normalize();
+
+ Vector2 surface2Start = new Vector2(0.0f, 32.0f);
+ Vector2 surface2End = new Vector2(32.0f, 32.0f);
+ Vector2 surface2Normal = new Vector2(0.0f, 1.0f);
+ surface2Normal.normalize();
+
+ Vector2 surface3Start = new Vector2(32.0f, 32.0f);
+ Vector2 surface3End = new Vector2(32.0f, 0.0f);
+ Vector2 surface3Normal = new Vector2(1.0f, 0.0f);
+
+ Vector2 surface4Start = new Vector2(32.0f, 0.0f);
+ Vector2 surface4End = new Vector2(0.0f, 0.0f);
+ Vector2 surface4Normal = new Vector2(0.0f, -1.0f);
+
+ solidSurface.addSurface(surface1Start, surface1End, surface1Normal);
+ solidSurface.addSurface(surface2Start, surface2End, surface2Normal);
+ solidSurface.addSurface(surface3Start, surface3End, surface3Normal);
+ solidSurface.addSurface(surface4Start, surface4End, surface4Normal);
+
+ staticData.add(solidSurface);
+ staticData.add(idle);
+
+
+ setStaticData(GameObjectType.BREAKABLE_BLOCK, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_OBJECT);
+
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ DynamicCollisionComponent collision
+ = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(collision);
+
+ HitReactionComponent hitReact
+ = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ collision.setHitReactionComponent(hitReact);
+
+ LifetimeComponent lifetime = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+ lifetime.setObjectToSpawnOnDeath(GameObjectType.BREAKABLE_BLOCK_PIECE_SPAWNER);
+ SoundSystem sound = BaseObject.sSystemRegistry.soundSystem;
+ if (sound != null) {
+ lifetime.setDeathSound(sound.load(R.raw.sound_break_block));
+ }
+
+ object.life = 1;
+ object.team = Team.ENEMY;
+
+ object.add(render);
+ object.add(sprite);
+ object.add(collision);
+ object.add(hitReact);
+ object.add(lifetime);
+
+
+ addStaticData(GameObjectType.BREAKABLE_BLOCK, object, sprite);
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnObjectTheSource(float positionX, float positionY) {
+
+ final TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+ GameObject object = mGameObjectPool.allocate();
+ object.activationRadius = mAlwaysActive;
+ object.width = 512;
+ object.height = 512;
+ object.getPosition().set(positionX, positionY);
+
+ RenderComponent layer1Render = (RenderComponent)allocateComponent(RenderComponent.class);
+ layer1Render.setPriority(SortConstants.THE_SOURCE_START);
+ FadeDrawableComponent layer1Fade = (FadeDrawableComponent)allocateComponent(FadeDrawableComponent.class);
+ layer1Fade.setRenderComponent(layer1Render);
+ layer1Fade.setTexture(textureLibrary.allocateTexture(R.drawable.enemy_source_spikes));
+ layer1Fade.setupFade(1.0f, 0.2f, 1.9f, FadeDrawableComponent.LOOP_TYPE_PING_PONG, FadeDrawableComponent.FADE_EASE, 0.0f);
+
+ RenderComponent layer2Render = (RenderComponent)allocateComponent(RenderComponent.class);
+ layer2Render.setPriority(SortConstants.THE_SOURCE_START + 1);
+ FadeDrawableComponent layer2Fade = (FadeDrawableComponent)allocateComponent(FadeDrawableComponent.class);
+ layer2Fade.setRenderComponent(layer2Render);
+ layer2Fade.setTexture(textureLibrary.allocateTexture(R.drawable.enemy_source_body));
+ layer2Fade.setupFade(1.0f, 0.8f, 5.0f, FadeDrawableComponent.LOOP_TYPE_PING_PONG, FadeDrawableComponent.FADE_EASE, 0.0f);
+
+ RenderComponent layer3Render = (RenderComponent)allocateComponent(RenderComponent.class);
+ layer3Render.setPriority(SortConstants.THE_SOURCE_START + 2);
+ FadeDrawableComponent layer3Fade = (FadeDrawableComponent)allocateComponent(FadeDrawableComponent.class);
+ layer3Fade.setRenderComponent(layer3Render);
+ layer3Fade.setTexture(textureLibrary.allocateTexture(R.drawable.enemy_source_black));
+ layer3Fade.setupFade(0.0f, 1.0f, 6.0f, FadeDrawableComponent.LOOP_TYPE_PING_PONG, FadeDrawableComponent.FADE_LINEAR, 0.0f);
+
+ RenderComponent layer4Render = (RenderComponent)allocateComponent(RenderComponent.class);
+ layer4Render.setPriority(SortConstants.THE_SOURCE_START + 3);
+ FadeDrawableComponent layer4Fade = (FadeDrawableComponent)allocateComponent(FadeDrawableComponent.class);
+ layer4Fade.setRenderComponent(layer4Render);
+ layer4Fade.setTexture(textureLibrary.allocateTexture(R.drawable.enemy_source_spots));
+ layer4Fade.setupFade(0.0f, 1.0f, 2.3f, FadeDrawableComponent.LOOP_TYPE_PING_PONG, FadeDrawableComponent.FADE_EASE, 0.0f);
+
+ RenderComponent layer5Render = (RenderComponent)allocateComponent(RenderComponent.class);
+ layer5Render.setPriority(SortConstants.THE_SOURCE_START + 4);
+ FadeDrawableComponent layer5Fade = (FadeDrawableComponent)allocateComponent(FadeDrawableComponent.class);
+ layer5Fade.setRenderComponent(layer5Render);
+ layer5Fade.setTexture(textureLibrary.allocateTexture(R.drawable.enemy_source_core));
+ layer5Fade.setupFade(0.2f, 1.0f, 1.2f, FadeDrawableComponent.LOOP_TYPE_PING_PONG, FadeDrawableComponent.FADE_EASE, 0.0f);
+
+
+ OrbitalMagnetComponent orbit = (OrbitalMagnetComponent)allocateComponent(OrbitalMagnetComponent.class);
+ orbit.setup(320.0f, 220.0f);
+
+ DynamicCollisionComponent collision = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ FixedSizeArray vulnerabilityVolume =
+ new FixedSizeArray(1);
+ vulnerabilityVolume.add(new SphereCollisionVolume(256, 256, 256, HitType.HIT));
+ FixedSizeArray attackVolume =
+ new FixedSizeArray(1);
+ attackVolume.add(new SphereCollisionVolume(256, 256, 256, HitType.HIT));
+ collision.setCollisionVolumes(attackVolume, vulnerabilityVolume);
+
+ HitReactionComponent hitReact = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ collision.setHitReactionComponent(hitReact);
+ hitReact.setInvincibleTime(TheSourceComponent.SHAKE_TIME);
+
+ TheSourceComponent theSource = (TheSourceComponent)allocateComponent(TheSourceComponent.class);
+ ChannelSystem.Channel surpriseChannel = null;
+ ChannelSystem channelSystem = BaseObject.sSystemRegistry.channelSystem;
+ surpriseChannel = channelSystem.registerChannel(sSurprisedNPCChannel);
+ theSource.setChannel(surpriseChannel);
+ theSource.setGameEvent(GameFlowEvent.EVENT_SHOW_ANIMATION, AnimationPlayerActivity.WANDA_ENDING);
+
+
+ object.life = 3;
+ object.team = Team.PLAYER;
+
+ object.add(layer1Render);
+ object.add(layer2Render);
+ object.add(layer3Render);
+ object.add(layer4Render);
+ object.add(layer5Render);
+
+ object.add(layer1Fade);
+ object.add(layer2Fade);
+ object.add(layer3Fade);
+ object.add(layer4Fade);
+ object.add(layer5Fade);
+
+ object.add(orbit);
+ object.add(collision);
+ object.add(hitReact);
+ object.add(theSource);
+
+ return object;
+ }
+
+ public GameObject spawnObjectTurret(float positionX, float positionY, boolean flipHorizontal) {
+
+ TextureLibrary textureLibrary = sSystemRegistry.shortTermTextureLibrary;
+
+ // Make sure related textures are loaded.
+ textureLibrary.allocateTexture(R.drawable.effect_bullet01);
+ textureLibrary.allocateTexture(R.drawable.effect_bullet02);
+
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 64;
+ object.height = 64;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.TURRET);
+ if (staticData == null) {
+ final int staticObjectCount = 3;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ // Animations
+ FixedSizeArray basicVulnerabilityVolume =
+ new FixedSizeArray(1);
+ basicVulnerabilityVolume.add(new SphereCollisionVolume(32, 32, 32));
+ basicVulnerabilityVolume.get(0).setHitType(HitType.POSSESS);
+
+ SpriteAnimation idle = new SpriteAnimation(EnemyAnimations.IDLE.ordinal(), 2);
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.object_gunturret01),
+ 1.0f, null, basicVulnerabilityVolume));
+ idle.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.object_gunturret_idle),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ idle.setLoop(true);
+
+ SpriteAnimation attack = new SpriteAnimation(EnemyAnimations.ATTACK.ordinal(), 4);
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.object_gunturret02),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.object_gunturret01),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.object_gunturret03),
+ Utils.framesToTime(24, 2), null, basicVulnerabilityVolume));
+ attack.addFrame(new AnimationFrame(
+ textureLibrary.allocateTexture(R.drawable.object_gunturret01),
+ Utils.framesToTime(24, 1), null, basicVulnerabilityVolume));
+ attack.setLoop(true);
+
+ GhostComponent ghost = (GhostComponent)allocateComponent(GhostComponent.class);
+ ghost.setTargetAction(ActionType.IDLE);
+ ghost.changeActionOnButton(ActionType.ATTACK);
+
+ staticData.add(idle);
+ staticData.add(attack);
+ staticData.add(ghost);
+
+
+ setStaticData(GameObjectType.TURRET, staticData);
+ }
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.GENERAL_OBJECT);
+
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+ GenericAnimationComponent animation
+ = (GenericAnimationComponent)allocateComponent(GenericAnimationComponent.class);
+ animation.setSprite(sprite);
+
+ AttackAtDistanceComponent attack = (AttackAtDistanceComponent)
+ allocateComponent(AttackAtDistanceComponent.class);
+ attack.setupAttack(300, 0.0f, 1.0f, true);
+
+
+ DynamicCollisionComponent collision
+ = (DynamicCollisionComponent)allocateComponent(DynamicCollisionComponent.class);
+ sprite.setCollisionComponent(collision);
+
+ HitReactionComponent hitReact
+ = (HitReactionComponent)allocateComponent(HitReactionComponent.class);
+ collision.setHitReactionComponent(hitReact);
+
+ LifetimeComponent lifetime = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+ lifetime.setObjectToSpawnOnDeath(GameObjectType.EXPLOSION_LARGE);
+
+ SoundSystem sound = sSystemRegistry.soundSystem;
+
+ LaunchProjectileComponent gun
+ = (LaunchProjectileComponent)allocateComponent(LaunchProjectileComponent.class);
+ gun.setShotsPerSet(1);
+ gun.setDelayBetweenShots(0.0f);
+ gun.setDelayBetweenSets(0.3f);
+ gun.setObjectTypeToSpawn(GameObjectType.TURRET_BULLET);
+ gun.setOffsetX(54);
+ gun.setOffsetY(13);
+ gun.setRequiredAction(GameObject.ActionType.ATTACK);
+ gun.setVelocityX(300.0f);
+ gun.setVelocityY(-300.0f);
+ gun.setShootSound(sound.load(R.raw.sound_gun));
+
+ // Components for possession
+
+ ChangeComponentsComponent componentSwap = (ChangeComponentsComponent)allocateComponent(ChangeComponentsComponent.class);
+ componentSwap.addSwapOutComponent(attack);
+ componentSwap.setPingPongBehavior(true);
+
+ hitReact.setPossessionComponent(componentSwap);
+
+ object.team = Team.ENEMY;
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ } else {
+ object.facingDirection.x = 1.0f;
+ }
+
+ object.add(render);
+ object.add(sprite);
+ object.add(animation);
+ object.add(attack);
+ object.add(collision);
+ object.add(hitReact);
+ object.add(lifetime);
+ object.add(gun);
+ object.add(componentSwap);
+
+ addStaticData(GameObjectType.TURRET, object, sprite);
+
+ object.commitUpdates();
+
+ GhostComponent possessedGhost = object.findByClass(GhostComponent.class);
+ if (possessedGhost != null) {
+ object.remove(possessedGhost); // Not supposed to be added yet.
+ componentSwap.addSwapInComponent(possessedGhost);
+ }
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnDust(float positionX, float positionY, boolean flipHorizontal) {
+ TextureLibrary textureLibrary = sSystemRegistry.longTermTextureLibrary;
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mTightActivationRadius;
+ object.width = 32;
+ object.height = 32;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.DUST);
+ if (staticData == null) {
+ final int staticObjectCount = 1;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ SpriteAnimation idle = new SpriteAnimation(0, 5);
+ idle.addFrame(new AnimationFrame(textureLibrary.getTextureByResource(R.drawable.dust01),
+ Utils.framesToTime(24, 1)));
+ idle.addFrame(new AnimationFrame(textureLibrary.getTextureByResource(R.drawable.dust02),
+ Utils.framesToTime(24, 1)));
+ idle.addFrame(new AnimationFrame(textureLibrary.getTextureByResource(R.drawable.dust03),
+ Utils.framesToTime(24, 1)));
+ idle.addFrame(new AnimationFrame(textureLibrary.getTextureByResource(R.drawable.dust04),
+ Utils.framesToTime(24, 1)));
+ idle.addFrame(new AnimationFrame(textureLibrary.getTextureByResource(R.drawable.dust05),
+ Utils.framesToTime(24, 1)));
+
+ staticData.add(idle);
+ setStaticData(GameObjectType.DUST, staticData);
+ }
+
+
+ RenderComponent render = (RenderComponent)allocateComponent(RenderComponent.class);
+ render.setPriority(SortConstants.EFFECT);
+
+ LifetimeComponent lifetime = (LifetimeComponent)allocateComponent(LifetimeComponent.class);
+ lifetime.setTimeUntilDeath(0.30f);
+
+ SpriteComponent sprite = (SpriteComponent)allocateComponent(SpriteComponent.class);
+ sprite.setSize((int)object.width, (int)object.height);
+ sprite.setRenderComponent(render);
+
+
+ if (flipHorizontal) {
+ object.facingDirection.x = -1.0f;
+ }
+ object.destroyOnDeactivation = true;
+
+ object.add(lifetime);
+ object.add(render);
+ object.add(sprite);
+
+ addStaticData(GameObjectType.DUST, object, sprite);
+
+ sprite.playAnimation(0);
+
+ return object;
+ }
+
+ public GameObject spawnEffectExplosionSmall(float positionX, float positionY) {
+ TextureLibrary textureLibrary = sSystemRegistry.longTermTextureLibrary;
+
+ GameObject object = mGameObjectPool.allocate();
+ object.getPosition().set(positionX, positionY);
+ object.activationRadius = mAlwaysActive;
+ object.width = 32;
+ object.height = 32;
+
+ FixedSizeArray staticData = getStaticData(GameObjectType.EXPLOSION_SMALL);
+ if (staticData == null) {
+ final int staticObjectCount = 1;
+ staticData = new FixedSizeArray(staticObjectCount);
+
+ FixedSizeArray