This example shows how you can create Rubik’s cube in android.
Algorithm:
1.) Create a new project by File-> New -> Android Project name it RubikCubeAnimationExample.
2.) Create and write following into src/M4.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | package com.example.RubikCubeAnimationExample; public class M4 { public float[][] m = new float[4][4]; public M4() { } public M4(M4 other) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { m[i][j] = other.m[i][j]; } } } public void multiply(GLVertex src, GLVertex dest) { dest.x = src.x * m[0][0] + src.y * m[1][0] + src.z * m[2][0] + m[3][0]; dest.y = src.x * m[0][1] + src.y * m[1][1] + src.z * m[2][1] + m[3][1]; dest.z = src.x * m[0][2] + src.y * m[1][2] + src.z * m[2][2] + m[3][2]; } public M4 multiply(M4 other) { M4 result = new M4(); float[][] m1 = m; float[][] m2 = other.m; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { result.m[i][j] = m1[i][0]*m2[0][j] + m1[i][1]*m2[1][j] + m1[i][2]*m2[2][j] + m1[i][3]*m2[3][j]; } } return result; } public void setIdentity() { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { m[i][j] = (i == j ? 1f : 0f); } } } @Override public String toString() { StringBuilder builder = new StringBuilder("[ "); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { builder.append(m[i][j]); builder.append(" "); } if (i < 2) builder.append("n "); } builder.append(" ]"); return builder.toString(); } } |
3.) Create and write following into src/Layer.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | package com.example.RubikCubeAnimationExample; public class Layer { public Layer(int axis) { mAxis = axis; mTransform.setIdentity(); } public void startAnimation() { for (int i = 0; i < mShapes.length; i++) { GLShape shape = mShapes[i]; if (shape != null) { shape.startAnimation(); } } } public void endAnimation() { for (int i = 0; i < mShapes.length; i++) { GLShape shape = mShapes[i]; if (shape != null) { shape.endAnimation(); } } } public void setAngle(float angle) { // normalize the angle float twopi = (float)Math.PI *2f; while (angle >= twopi) angle -= twopi; while (angle < 0f) angle += twopi; // mAngle = angle; float sin = (float)Math.sin(angle); float cos = (float)Math.cos(angle); float[][] m = mTransform.m; switch (mAxis) { case kAxisX: m[1][1] = cos; m[1][2] = sin; m[2][1] = -sin; m[2][2] = cos; m[0][0] = 1f; m[0][1] = m[0][2] = m[1][0] = m[2][0] = 0f; break; case kAxisY: m[0][0] = cos; m[0][2] = sin; m[2][0] = -sin; m[2][2] = cos; m[1][1] = 1f; m[0][1] = m[1][0] = m[1][2] = m[2][1] = 0f; break; case kAxisZ: m[0][0] = cos; m[0][1] = sin; m[1][0] = -sin; m[1][1] = cos; m[2][2] = 1f; m[2][0] = m[2][1] = m[0][2] = m[1][2] = 0f; break; } for (int i = 0; i < mShapes.length; i++) { GLShape shape = mShapes[i]; if (shape != null) { shape.animateTransform(mTransform); } } } GLShape[] mShapes = new GLShape[9]; M4 mTransform = new M4(); int mAxis; static public final int kAxisX = 0; static public final int kAxisY = 1; static public final int kAxisZ = 2; } |
4.) Create and write following into src/KubeRenderer.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | package com.example.RubikCubeAnimationExample; import android.opengl.GLSurfaceView; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; class KubeRenderer implements GLSurfaceView.Renderer { public interface AnimationCallback { void animate(); } public KubeRenderer(GLWorld world, AnimationCallback callback) { mWorld = world; mCallback = callback; } public void onDrawFrame(GL10 gl) { if (mCallback != null) { mCallback.animate(); } gl.glClearColor(0.5f,0.5f,0.5f,1); gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0, 0, -3.0f); gl.glScalef(0.5f, 0.5f, 0.5f); gl.glRotatef(mAngle, 0, 1, 0); gl.glRotatef(mAngle*0.25f, 1, 0, 0); gl.glColor4f(0.7f, 0.7f, 0.7f, 1.0f); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_COLOR_ARRAY); gl.glEnable(GL10.GL_CULL_FACE); gl.glShadeModel(GL10.GL_SMOOTH); gl.glEnable(GL10.GL_DEPTH_TEST); mWorld.draw(gl); } public void onSurfaceChanged(GL10 gl, int width, int height) { gl.glViewport(0, 0, width, height); float ratio = (float)width / height; gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); gl.glFrustumf(-ratio, ratio, -1, 1, 2, 12); gl.glDisable(GL10.GL_DITHER); gl.glActiveTexture(GL10.GL_TEXTURE0); } public void onSurfaceCreated(GL10 gl, EGLConfig config) { } public void setAngle(float angle) { mAngle = angle; } public float getAngle() { return mAngle; } private GLWorld mWorld; private AnimationCallback mCallback; private float mAngle; } |
5.) Create and write following into src/GLWorld.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | package com.example.RubikCubeAnimationExample; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.IntBuffer; import java.nio.ShortBuffer; import java.util.Iterator; import java.util.ArrayList; import javax.microedition.khronos.opengles.GL10; public class GLWorld { public void addShape(GLShape shape) { mShapeList.add(shape); mIndexCount += shape.getIndexCount(); } public void generate() { ByteBuffer bb = ByteBuffer.allocateDirect(mVertexList.size()*4*4); bb.order(ByteOrder.nativeOrder()); mColorBuffer = bb.asIntBuffer(); bb = ByteBuffer.allocateDirect(mVertexList.size()*4*3); bb.order(ByteOrder.nativeOrder()); mVertexBuffer = bb.asIntBuffer(); bb = ByteBuffer.allocateDirect(mIndexCount*2); bb.order(ByteOrder.nativeOrder()); mIndexBuffer = bb.asShortBuffer(); Iterator iter2 = mVertexList.iterator(); while (iter2.hasNext()) { GLVertex vertex = iter2.next(); vertex.put(mVertexBuffer, mColorBuffer); } Iterator iter3 = mShapeList.iterator(); while (iter3.hasNext()) { GLShape shape = iter3.next(); shape.putIndices(mIndexBuffer); } } public GLVertex addVertex(float x, float y, float z) { GLVertex vertex = new GLVertex(x, y, z, mVertexList.size()); mVertexList.add(vertex); return vertex; } public void transformVertex(GLVertex vertex, M4 transform) { vertex.update(mVertexBuffer, transform); } int count = 0; public void draw(GL10 gl) { mColorBuffer.position(0); mVertexBuffer.position(0); mIndexBuffer.position(0); gl.glFrontFace(GL10.GL_CW); gl.glShadeModel(GL10.GL_FLAT); gl.glVertexPointer(3, GL10.GL_FIXED, 0, mVertexBuffer); gl.glColorPointer(4, GL10.GL_FIXED, 0, mColorBuffer); gl.glDrawElements(GL10.GL_TRIANGLES, mIndexCount, GL10.GL_UNSIGNED_SHORT, mIndexBuffer); count++; } static public float toFloat(int x) { return x/65536.0f; } private ArrayList mShapeList = new ArrayList(); private ArrayList mVertexList = new ArrayList(); private int mIndexCount = 0; private IntBuffer mVertexBuffer; private IntBuffer mColorBuffer; private ShortBuffer mIndexBuffer; } |
6.) Create and write following into src/GLVertex.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | package com.example.RubikCubeAnimationExample; import java.nio.IntBuffer; public class GLVertex { public float x; public float y; public float z; final short index; // index in vertex table GLColor color; GLVertex() { this.x = 0; this.y = 0; this.z = 0; this.index = -1; } GLVertex(float x, float y, float z, int index) { this.x = x; this.y = y; this.z = z; this.index = (short)index; } @Override public boolean equals(Object other) { if (other instanceof GLVertex) { GLVertex v = (GLVertex)other; return (x == v.x && y == v.y && z == v.z); } return false; } static public int toFixed(float x) { return (int)(x * 65536.0f); } public void put(IntBuffer vertexBuffer, IntBuffer colorBuffer) { vertexBuffer.put(toFixed(x)); vertexBuffer.put(toFixed(y)); vertexBuffer.put(toFixed(z)); if (color == null) { colorBuffer.put(0); colorBuffer.put(0); colorBuffer.put(0); colorBuffer.put(0); } else { colorBuffer.put(color.red); colorBuffer.put(color.green); colorBuffer.put(color.blue); colorBuffer.put(color.alpha); } } public void update(IntBuffer vertexBuffer, M4 transform) { // skip to location of vertex in mVertex buffer vertexBuffer.position(index * 3); if (transform == null) { vertexBuffer.put(toFixed(x)); vertexBuffer.put(toFixed(y)); vertexBuffer.put(toFixed(z)); } else { GLVertex temp = new GLVertex(); transform.multiply(this, temp); vertexBuffer.put(toFixed(temp.x)); vertexBuffer.put(toFixed(temp.y)); vertexBuffer.put(toFixed(temp.z)); } } } |
7.) Create and write following into src/GLShape.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | package com.example.RubikCubeAnimationExample; import java.nio.ShortBuffer; import java.util.ArrayList; import java.util.Iterator; public class GLShape { public GLShape(GLWorld world) { mWorld = world; } public void addFace(GLFace face) { mFaceList.add(face); } public void setFaceColor(int face, GLColor color) { mFaceList.get(face).setColor(color); } public void putIndices(ShortBuffer buffer) { Iterator iter = mFaceList.iterator(); while (iter.hasNext()) { GLFace face = iter.next(); face.putIndices(buffer); } } public int getIndexCount() { int count = 0; Iterator iter = mFaceList.iterator(); while (iter.hasNext()) { GLFace face = iter.next(); count += face.getIndexCount(); } return count; } public GLVertex addVertex(float x, float y, float z) { // look for an existing GLVertex first Iterator iter = mVertexList.iterator(); while (iter.hasNext()) { GLVertex vertex = iter.next(); if (vertex.x == x && vertex.y == y && vertex.z == z) { return vertex; } } // doesn't exist, so create new vertex GLVertex vertex = mWorld.addVertex(x, y, z); mVertexList.add(vertex); return vertex; } public void animateTransform(M4 transform) { mAnimateTransform = transform; if (mTransform != null) transform = mTransform.multiply(transform); Iterator iter = mVertexList.iterator(); while (iter.hasNext()) { GLVertex vertex = iter.next(); mWorld.transformVertex(vertex, transform); } } public void startAnimation() { } public void endAnimation() { if (mTransform == null) { mTransform = new M4(mAnimateTransform); } else { mTransform = mTransform.multiply(mAnimateTransform); } } public M4 mTransform; public M4 mAnimateTransform; protected ArrayList mFaceList = new ArrayList(); protected ArrayList mVertexList = new ArrayList(); protected ArrayList mIndexList = new ArrayList(); // make more efficient? protected GLWorld mWorld; } |
8.) Create and write following into src/GLFace.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | package com.example.RubikCubeAnimationExample; import android.util.Log; import java.nio.ShortBuffer; import java.util.ArrayList; public class GLFace { public GLFace() { } // for triangles public GLFace(GLVertex v1, GLVertex v2, GLVertex v3) { addVertex(v1); addVertex(v2); addVertex(v3); } // for quadrilaterals public GLFace(GLVertex v1, GLVertex v2, GLVertex v3, GLVertex v4) { addVertex(v1); addVertex(v2); addVertex(v3); addVertex(v4); } public void addVertex(GLVertex v) { mVertexList.add(v); } // must be called after all vertices are added public void setColor(GLColor c) { int last = mVertexList.size() - 1; if (last < 2) { Log.e("GLFace", "not enough vertices in setColor()"); } else { GLVertex vertex = mVertexList.get(last); // only need to do this if the color has never been set if (mColor == null) { while (vertex.color != null) { mVertexList.add(0, vertex); mVertexList.remove(last + 1); vertex = mVertexList.get(last); } } vertex.color = c; } mColor = c; } public int getIndexCount() { return (mVertexList.size() - 2) * 3; } public void putIndices(ShortBuffer buffer) { int last = mVertexList.size() - 1; GLVertex v0 = mVertexList.get(0); GLVertex vn = mVertexList.get(last); // push triangles into the buffer for (int i = 1; i < last; i++) { GLVertex v1 = mVertexList.get(i); buffer.put(v0.index); buffer.put(v1.index); buffer.put(vn.index); v0 = v1; } } private ArrayList mVertexList = new ArrayList(); private GLColor mColor; } [/code] 9.) Create and write following into src/GLColor.java: [code lang="java"] package com.example.RubikCubeAnimationExample; public class GLColor { public final int red; public final int green; public final int blue; public final int alpha; public GLColor(int red, int green, int blue, int alpha) { this.red = red; this.green = green; this.blue = blue; this.alpha = alpha; } public GLColor(int red, int green, int blue) { this.red = red; this.green = green; this.blue = blue; this.alpha = 0x10000; } @Override public boolean equals(Object other) { if (other instanceof GLColor) { GLColor color = (GLColor)other; return (red == color.red && green == color.green && blue == color.blue && alpha == color.alpha); } return false; } } |
10.) Create and write following into src/Cube.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | package com.example.RubikCubeAnimationExample; public class Cube extends GLShape { public Cube(GLWorld world, float left, float bottom, float back, float right, float top, float front) { super(world); GLVertex leftBottomBack = addVertex(left, bottom, back); GLVertex rightBottomBack = addVertex(right, bottom, back); GLVertex leftTopBack = addVertex(left, top, back); GLVertex rightTopBack = addVertex(right, top, back); GLVertex leftBottomFront = addVertex(left, bottom, front); GLVertex rightBottomFront = addVertex(right, bottom, front); GLVertex leftTopFront = addVertex(left, top, front); GLVertex rightTopFront = addVertex(right, top, front); addFace(new GLFace(leftBottomBack, leftBottomFront, rightBottomFront, rightBottomBack)); addFace(new GLFace(leftBottomFront, leftTopFront, rightTopFront, rightBottomFront)); addFace(new GLFace(leftBottomBack, leftTopBack, leftTopFront, leftBottomFront)); addFace(new GLFace(rightBottomBack, rightBottomFront, rightTopFront, rightTopBack)); addFace(new GLFace(leftBottomBack, rightBottomBack, rightTopBack, leftTopBack)); addFace(new GLFace(leftTopBack, rightTopBack, rightTopFront, leftTopFront)); } public static final int kBottom = 0; public static final int kFront = 1; public static final int kLeft = 2; public static final int kRight = 3; public static final int kBack = 4; public static final int kTop = 5; } |
11.) Run for output.
Steps:
1.) Create a project named RubikCubeAnimationExample and set the information as stated in the image.
Build Target: Android 4.0
Application Name: RubikCubeAnimationExample
Package Name: com. example. RubikCubeAnimationExample
Activity Name: RubikCubeAnimationExampleActivity
Min SDK Version: 14
2.) Open RubikCubeAnimationExampleActivity.java file and write following code there:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 | package com.example.RubikCubeAnimationExample; import java.util.Random; import android.app.Activity; import android.opengl.GLSurfaceView; import android.os.Bundle; import android.view.Window; public class RubikCubeAnimationExampleActivity extends Activity implements KubeRenderer.AnimationCallback { private GLWorld makeGLWorld() { GLWorld world = new GLWorld(); int one = 0x10000; int half = 0x08000; GLColor red = new GLColor(one, 0, 0); GLColor green = new GLColor(0, one, 0); GLColor blue = new GLColor(0, 0, one); GLColor yellow = new GLColor(one, one, 0); GLColor orange = new GLColor(one, half, 0); GLColor white = new GLColor(one, one, one); GLColor black = new GLColor(0, 0, 0); float c0 = -1.0f; float c1 = -0.38f; float c2 = -0.32f; float c3 = 0.32f; float c4 = 0.38f; float c5 = 1.0f; // top back, left to right mCubes[0] = new Cube(world, c0, c4, c0, c1, c5, c1); mCubes[1] = new Cube(world, c2, c4, c0, c3, c5, c1); mCubes[2] = new Cube(world, c4, c4, c0, c5, c5, c1); // top middle, left to right mCubes[3] = new Cube(world, c0, c4, c2, c1, c5, c3); mCubes[4] = new Cube(world, c2, c4, c2, c3, c5, c3); mCubes[5] = new Cube(world, c4, c4, c2, c5, c5, c3); // top front, left to right mCubes[6] = new Cube(world, c0, c4, c4, c1, c5, c5); mCubes[7] = new Cube(world, c2, c4, c4, c3, c5, c5); mCubes[8] = new Cube(world, c4, c4, c4, c5, c5, c5); // middle back, left to right mCubes[9] = new Cube(world, c0, c2, c0, c1, c3, c1); mCubes[10] = new Cube(world, c2, c2, c0, c3, c3, c1); mCubes[11] = new Cube(world, c4, c2, c0, c5, c3, c1); // middle middle, left to right mCubes[12] = new Cube(world, c0, c2, c2, c1, c3, c3); mCubes[13] = null; mCubes[14] = new Cube(world, c4, c2, c2, c5, c3, c3); // middle front, left to right mCubes[15] = new Cube(world, c0, c2, c4, c1, c3, c5); mCubes[16] = new Cube(world, c2, c2, c4, c3, c3, c5); mCubes[17] = new Cube(world, c4, c2, c4, c5, c3, c5); // bottom back, left to right mCubes[18] = new Cube(world, c0, c0, c0, c1, c1, c1); mCubes[19] = new Cube(world, c2, c0, c0, c3, c1, c1); mCubes[20] = new Cube(world, c4, c0, c0, c5, c1, c1); // bottom middle, left to right mCubes[21] = new Cube(world, c0, c0, c2, c1, c1, c3); mCubes[22] = new Cube(world, c2, c0, c2, c3, c1, c3); mCubes[23] = new Cube(world, c4, c0, c2, c5, c1, c3); // bottom front, left to right mCubes[24] = new Cube(world, c0, c0, c4, c1, c1, c5); mCubes[25] = new Cube(world, c2, c0, c4, c3, c1, c5); mCubes[26] = new Cube(world, c4, c0, c4, c5, c1, c5); // paint the sides int i, j; // set all faces black by default for (i = 0; i < 27; i++) { Cube cube = mCubes[i]; if (cube != null) { for (j = 0; j < 6; j++) cube.setFaceColor(j, black); } } // paint top for (i = 0; i < 9; i++) mCubes[i].setFaceColor(Cube.kTop, orange); // paint bottom for (i = 18; i < 27; i++) mCubes[i].setFaceColor(Cube.kBottom, red); // paint left for (i = 0; i < 27; i += 3) mCubes[i].setFaceColor(Cube.kLeft, yellow); // paint right for (i = 2; i < 27; i += 3) mCubes[i].setFaceColor(Cube.kRight, white); // paint back for (i = 0; i < 27; i += 9) for (j = 0; j < 3; j++) mCubes[i + j].setFaceColor(Cube.kBack, blue); // paint front for (i = 6; i < 27; i += 9) for (j = 0; j < 3; j++) mCubes[i + j].setFaceColor(Cube.kFront, green); for (i = 0; i < 27; i++) if (mCubes[i] != null) world.addShape(mCubes[i]); // initialize our permutation to solved position mPermutation = new int[27]; for (i = 0; i < mPermutation.length; i++) mPermutation[i] = i; createLayers(); updateLayers(); world.generate(); return world; } private void createLayers() { mLayers[kUp] = new Layer(Layer.kAxisY); mLayers[kDown] = new Layer(Layer.kAxisY); mLayers[kLeft] = new Layer(Layer.kAxisX); mLayers[kRight] = new Layer(Layer.kAxisX); mLayers[kFront] = new Layer(Layer.kAxisZ); mLayers[kBack] = new Layer(Layer.kAxisZ); mLayers[kMiddle] = new Layer(Layer.kAxisX); mLayers[kEquator] = new Layer(Layer.kAxisY); mLayers[kSide] = new Layer(Layer.kAxisZ); } private void updateLayers() { Layer layer; GLShape[] shapes; int i, j, k; // up layer layer = mLayers[kUp]; shapes = layer.mShapes; for (i = 0; i < 9; i++) shapes[i] = mCubes[mPermutation[i]]; // down layer layer = mLayers[kDown]; shapes = layer.mShapes; for (i = 18, k = 0; i < 27; i++) shapes[k++] = mCubes[mPermutation[i]]; // left layer layer = mLayers[kLeft]; shapes = layer.mShapes; for (i = 0, k = 0; i < 27; i += 9) for (j = 0; j < 9; j += 3) shapes[k++] = mCubes[mPermutation[i + j]]; // right layer layer = mLayers[kRight]; shapes = layer.mShapes; for (i = 2, k = 0; i < 27; i += 9) for (j = 0; j < 9; j += 3) shapes[k++] = mCubes[mPermutation[i + j]]; // front layer layer = mLayers[kFront]; shapes = layer.mShapes; for (i = 6, k = 0; i < 27; i += 9) for (j = 0; j < 3; j++) shapes[k++] = mCubes[mPermutation[i + j]]; // back layer layer = mLayers[kBack]; shapes = layer.mShapes; for (i = 0, k = 0; i < 27; i += 9) for (j = 0; j < 3; j++) shapes[k++] = mCubes[mPermutation[i + j]]; // middle layer layer = mLayers[kMiddle]; shapes = layer.mShapes; for (i = 1, k = 0; i < 27; i += 9) for (j = 0; j < 9; j += 3) shapes[k++] = mCubes[mPermutation[i + j]]; // equator layer layer = mLayers[kEquator]; shapes = layer.mShapes; for (i = 9, k = 0; i < 18; i++) shapes[k++] = mCubes[mPermutation[i]]; // side layer layer = mLayers[kSide]; shapes = layer.mShapes; for (i = 3, k = 0; i < 27; i += 9) for (j = 0; j < 3; j++) shapes[k++] = mCubes[mPermutation[i + j]]; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // We don't need a title either. requestWindowFeature(Window.FEATURE_NO_TITLE); mView = new GLSurfaceView(getApplication()); mRenderer = new KubeRenderer(makeGLWorld(), this); mView.setRenderer(mRenderer); setContentView(mView); } @Override protected void onResume() { super.onResume(); mView.onResume(); } @Override protected void onPause() { super.onPause(); mView.onPause(); } public void animate() { // change our angle of view mRenderer.setAngle(mRenderer.getAngle() + 1.2f); if (mCurrentLayer == null) { int layerID = mRandom.nextInt(9); mCurrentLayer = mLayers[layerID]; mCurrentLayerPermutation = mLayerPermutations[layerID]; mCurrentLayer.startAnimation(); boolean direction = mRandom.nextBoolean(); int count = mRandom.nextInt(3) + 1; count = 1; direction = false; mCurrentAngle = 0; if (direction) { mAngleIncrement = (float)Math.PI / 50; mEndAngle = mCurrentAngle + ((float)Math.PI * count) / 2f; } else { mAngleIncrement = -(float)Math.PI / 50; mEndAngle = mCurrentAngle - ((float)Math.PI * count) / 2f; } } mCurrentAngle += mAngleIncrement; if ((mAngleIncrement > 0f && mCurrentAngle >= mEndAngle) || (mAngleIncrement < 0f && mCurrentAngle <= mEndAngle)) { mCurrentLayer.setAngle(mEndAngle); mCurrentLayer.endAnimation(); mCurrentLayer = null; // adjust mPermutation based on the completed layer rotation int[] newPermutation = new int[27]; for (int i = 0; i < 27; i++) { newPermutation[i] = mPermutation[mCurrentLayerPermutation[i]]; } mPermutation = newPermutation; updateLayers(); } else { mCurrentLayer.setAngle(mCurrentAngle); } } GLSurfaceView mView; KubeRenderer mRenderer; Cube[] mCubes = new Cube[27]; // a Layer for each possible move Layer[] mLayers = new Layer[9]; // permutations corresponding to a pi/2 rotation of each layer about its axis static int[][] mLayerPermutations = { // permutation for UP layer { 2, 5, 8, 1, 4, 7, 0, 3, 6, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 }, // permutation for DOWN layer { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 23, 26, 19, 22, 25, 18, 21, 24 }, // permutation for LEFT layer { 6, 1, 2, 15, 4, 5, 24, 7, 8, 3, 10, 11, 12, 13, 14, 21, 16, 17, 0, 19, 20, 9, 22, 23, 18, 25, 26 }, // permutation for RIGHT layer { 0, 1, 8, 3, 4, 17, 6, 7, 26, 9, 10, 5, 12, 13, 14, 15, 16, 23, 18, 19, 2, 21, 22, 11, 24, 25, 20 }, // permutation for FRONT layer { 0, 1, 2, 3, 4, 5, 24, 15, 6, 9, 10, 11, 12, 13, 14, 25, 16, 7, 18, 19, 20, 21, 22, 23, 26, 17, 8 }, // permutation for BACK layer { 18, 9, 0, 3, 4, 5, 6, 7, 8, 19, 10, 1, 12, 13, 14, 15, 16, 17, 20, 11, 2, 21, 22, 23, 24, 25, 26 }, // permutation for MIDDLE layer { 0, 7, 2, 3, 16, 5, 6, 25, 8, 9, 4, 11, 12, 13, 14, 15, 22, 17, 18, 1, 20, 21, 10, 23, 24, 19, 26 }, // permutation for EQUATOR layer { 0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 14, 17, 10, 13, 16, 9, 12, 15, 18, 19, 20, 21, 22, 23, 24, 25, 26 }, // permutation for SIDE layer { 0, 1, 2, 21, 12, 3, 6, 7, 8, 9, 10, 11, 22, 13, 4, 15, 16, 17, 18, 19, 20, 23, 14, 5, 24, 25, 26 } }; // current permutation of starting position int[] mPermutation; // for random cube movements Random mRandom = new Random(System.currentTimeMillis()); // currently turning layer Layer mCurrentLayer = null; // current and final angle for current Layer animation float mCurrentAngle, mEndAngle; // amount to increment angle float mAngleIncrement; int[] mCurrentLayerPermutation; // names for our 9 layers (based on notation from http://www.cubefreak.net/notation.html) static final int kUp = 0; static final int kDown = 1; static final int kLeft = 2; static final int kRight = 3; static final int kFront = 4; static final int kBack = 5; static final int kMiddle = 6; static final int kEquator = 7; static final int kSide = 8; } |
3.) Compile and build the project.
Output
SSISO Community