package com.gebauz.HotPlate;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.MotionEvent;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.io.IOException;
import java.io.InputStream;
public class HotPlate
extends Activity
{
@
Override
protected void onCreate
(Bundle savedInstanceState
)
{
super.
onCreate(savedInstanceState
);
mGLView =
new HotPlateView
(this);
setContentView
(mGLView
);
}
@
Override
protected void onPause
()
{
super.
onPause();
mGLView.
onPause();
}
@
Override
protected void onResume
()
{
super.
onResume();
mGLView.
onResume();
}
private GLSurfaceView mGLView
;
}
class HotPlateView
extends GLSurfaceView
{
HotPlateRenderer renderer
;
long lastUpdate =
System.
currentTimeMillis();
public static int MAX_POINTERS =
5;
private long updateDelta =
1000/
30;
private RefreshHandler redrawHandler =
new RefreshHandler
();
class RefreshHandler
extends Handler
{
@
Override
public void handleMessage
(Message msg
)
{
HotPlateView.
this.
update();
HotPlateView.
this.
invalidate();
}
public void sleep
(long delayMillis
)
{
this.
removeMessages(0);
sendMessageDelayed
(obtainMessage
(0), delayMillis
);
}
};
public HotPlateView
(Context context
)
{
super(context
);
renderer =
new HotPlateRenderer
(context
);
setRenderer
(renderer
);
setFocusableInTouchMode
(true); // make sure we get touch events
lastUpdate =
System.
currentTimeMillis();
update
();
}
public float GetDeltaTime
()
{
long now =
System.
currentTimeMillis();
long delta = now - lastUpdate
;
lastUpdate = now
;
return ((float)delta / 1000.0f
);
}
public void update
()
{
float deltaTime = GetDeltaTime
();
// update game logic
renderer.
updatePlate(deltaTime
);
redrawHandler.
sleep(updateDelta
);
}
public boolean onKeyDown
(int keyCode, android.
view.
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
);
}
@
Override
public boolean onTouchEvent
(MotionEvent event
)
{
//dumpEvent(event);
int pointerCount = event.
getPointerCount();
if (pointerCount
> MAX_POINTERS
)
pointerCount = MAX_POINTERS
;
if (event.
getAction() == MotionEvent.
ACTION_UP)
{
renderer.
DisableAllTouchPoints();
return true;
}
for (int i =
0; i
< MAX_POINTERS
; i++
)
{
//int id = event.getPointerId(i);
//android.util.Log.v("TEST", "Pointer " + i + " [" + id + "]" + ": " + event.getX(i) + ", " + event.getY(i));
if (i
< pointerCount
)
{
if (!renderer.
touchPoints[i
].
isActive)
renderer.
touchPoints[i
].
Play();
renderer.
touchPoints[i
].
isActive =
true;
renderer.
touchPoints[i
].
X = event.
getX(i
);
renderer.
touchPoints[i
].
Y = event.
getY(i
);
}
else
{
renderer.
touchPoints[i
].
isActive =
false;
}
}
return true;
//return super.onTouchEvent(event);
}
private void dumpEvent
(MotionEvent event
) {
String names
[] =
{ "DOWN" ,
"UP" ,
"MOVE" ,
"CANCEL" ,
"OUTSIDE" ,
"POINTER_DOWN" ,
"POINTER_UP" ,
"7?" ,
"8?" ,
"9?" };
StringBuilder sb =
new StringBuilder();
int action = event.
getAction();
int actionCode = action
& MotionEvent.
ACTION_MASK;
sb.
append("event ACTION_" ).
append(names
[actionCode
]);
if (actionCode == MotionEvent.
ACTION_POINTER_DOWN
|| actionCode == MotionEvent.
ACTION_POINTER_UP) {
sb.
append("(pid " ).
append(
action
>> MotionEvent.
ACTION_POINTER_ID_SHIFT);
sb.
append(")" );
}
sb.
append("[" );
for (int i =
0; i
< event.
getPointerCount(); i++
) {
sb.
append("#" ).
append(i
);
sb.
append("(pid " ).
append(event.
getPointerId(i
));
sb.
append(")=" ).
append((int) event.
getX(i
));
sb.
append("," ).
append((int) event.
getY(i
));
if (i +
1 < event.
getPointerCount())
sb.
append(";" );
}
sb.
append("]" );
android.
util.
Log.
d("TEST", sb.
toString());
}
};
class HotPlateRenderer
implements GLSurfaceView.
Renderer
{
private Context context
;
float timePassed =
0;
float heatRate = 0.08f
;
private FloatBuffer vertexBuffer
;
private FloatBuffer vertexBuffer2
;
private FloatBuffer colorBuffer
;
private FloatBuffer texCoordBuffer
;
private int[] textures =
new int[2];
private float vertices
[] =
{
-1.0f, 1.0f, 0.0f,
//Top left
1.0f, 1.0f, 0.0f,
// Top right
-1.0f, -1.0f, 0.0f,
//Bottom Left
1.0f, -1.0f, 0.0f
//Bottom Right
};
private float vertices2
[] =
{
-10.0f, 10.0f, 0.0f,
10.0f, 10.0f, 0.0f,
-10.0f, -10.0f, 0.0f,
10.0f, -10.0f, 0.0f
};
private float colors
[] =
{
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f
};
private float texCoords
[] =
{
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
};
private int surfaceWidth
;
private int surfaceHeight
;
class TouchPoint
{
public boolean isActive =
false;
public float X = 0.0f
;
public float Y = 0.0f
;
public android.
media.
MediaPlayer soundPlayer
;
public TouchPoint
(Context context
)
{
soundPlayer = android.
media.
MediaPlayer.
create(context, R.
raw.
burn);
}
public void Play
()
{
soundPlayer.
seekTo(0);
soundPlayer.
start();
}
}
public TouchPoint touchPoints
[] =
new TouchPoint
[HotPlateView.
MAX_POINTERS];
public HotPlateRenderer
(Context context
)
{
this.
context = context
;
for (int i =
0; i
< HotPlateView.
MAX_POINTERS; i++
)
{
touchPoints
[i
] =
new TouchPoint
(context
);
}
ByteBuffer byteBuf =
ByteBuffer.
allocateDirect(vertices.
length * 4);
byteBuf.
order(ByteOrder.
nativeOrder());
vertexBuffer = byteBuf.
asFloatBuffer();
vertexBuffer.
put(vertices
);
vertexBuffer.
position(0);
byteBuf =
ByteBuffer.
allocateDirect(vertices2.
length * 4);
byteBuf.
order(ByteOrder.
nativeOrder());
vertexBuffer2 = byteBuf.
asFloatBuffer();
vertexBuffer2.
put(vertices2
);
vertexBuffer2.
position(0);
byteBuf =
ByteBuffer.
allocateDirect(colors.
length * 4);
byteBuf.
order(ByteOrder.
nativeOrder());
colorBuffer = byteBuf.
asFloatBuffer();
colorBuffer.
put(colors
);
colorBuffer.
position(0);
byteBuf =
ByteBuffer.
allocateDirect(texCoords.
length * 4);
byteBuf.
order(ByteOrder.
nativeOrder());
texCoordBuffer = byteBuf.
asFloatBuffer();
texCoordBuffer.
put(texCoords
);
texCoordBuffer.
position(0);
}
public void LoadTexture
(GL10 gl,
Context context,
int resource,
int texture
)
{
InputStream is = context.
getResources().
openRawResource(resource
);
Bitmap bitmap =
null;
try
{
bitmap = BitmapFactory.
decodeStream(is
);
}
finally
{
try
{
is.
close();
is =
null;
}
catch (IOException e
)
{
}
}
gl.
glBindTexture(GL10.
GL_TEXTURE_2D, textures
[texture
]);
gl.
glTexParameterf(GL10.
GL_TEXTURE_2D, GL10.
GL_TEXTURE_MIN_FILTER, GL10.
GL_LINEAR);
gl.
glTexParameterf(GL10.
GL_TEXTURE_2D, GL10.
GL_TEXTURE_MAG_FILTER, GL10.
GL_LINEAR);
gl.
glTexParameterf(GL10.
GL_TEXTURE_2D, GL10.
GL_TEXTURE_WRAP_S, GL10.
GL_CLAMP_TO_EDGE);
gl.
glTexParameterf(GL10.
GL_TEXTURE_2D, GL10.
GL_TEXTURE_WRAP_T, GL10.
GL_CLAMP_TO_EDGE);
GLUtils.
texImage2D(GL10.
GL_TEXTURE_2D,
0, bitmap,
0);
bitmap.
recycle();
}
public void DisableAllTouchPoints
()
{
for (int i =
0; i
< HotPlateView.
MAX_POINTERS; i++
)
touchPoints
[i
].
isActive =
false;
}
public void onSurfaceCreated
(GL10 gl, EGLConfig config
)
{
gl.
glGenTextures(2, textures,
0);
LoadTexture
(gl,
this.
context, R.
drawable.
hotplate,
0);
LoadTexture
(gl,
this.
context, R.
drawable.
smoke,
1);
gl.
glEnable(GL10.
GL_TEXTURE_2D); //Enable Texture Mapping ( NEW )
gl.
glShadeModel(GL10.
GL_SMOOTH); //Enable Smooth Shading
gl.
glClearColor(0.0f, 0.0f, 0.0f, 0.0f
); //Black Background
//Really Nice Perspective Calculations
gl.
glHint(GL10.
GL_PERSPECTIVE_CORRECTION_HINT, GL10.
GL_NICEST);
}
public void onSurfaceChanged
(GL10 gl,
int w,
int h
)
{
gl.
glViewport(0,
0, w, h
);
surfaceWidth = w
;
surfaceHeight = h
;
}
public void onDrawFrame
(GL10 gl
)
{
gl.
glClear(GL10.
GL_COLOR_BUFFER_BIT | GL10.
GL_DEPTH_BUFFER_BIT);
gl.
glMatrixMode(GL10.
GL_PROJECTION);
gl.
glLoadIdentity();
float halfW = 1.0f
;
float halfH = 1.0f
;
if (surfaceWidth
> surfaceHeight
)
{
halfW =
(float)surfaceWidth /
(float)surfaceHeight
;
halfH = 1.0f
;
}
else
{
halfW = 1.0f
;
halfH =
(float)surfaceHeight /
(float)surfaceWidth
;
}
gl.
glOrthof(-halfW, halfW, -halfH, halfH,
0, 1.0f
);
gl.
glMatrixMode(GL10.
GL_MODELVIEW);
gl.
glLoadIdentity();
gl.
glFrontFace(GL10.
GL_CW);
gl.
glBindTexture(GL10.
GL_TEXTURE_2D, textures
[0]);
//Point to our vertex buffer
gl.
glVertexPointer(3, GL10.
GL_FLOAT,
0, vertexBuffer
);
gl.
glColorPointer(4, GL10.
GL_FLOAT,
0, colorBuffer
);
gl.
glTexCoordPointer(2, GL10.
GL_FLOAT,
0, texCoordBuffer
);
//Enable vertex buffer
gl.
glEnableClientState(GL10.
GL_VERTEX_ARRAY);
gl.
glEnableClientState(GL10.
GL_COLOR_ARRAY);
gl.
glEnableClientState(GL10.
GL_TEXTURE_COORD_ARRAY);
gl.
glEnable(GL10.
GL_BLEND);
gl.
glBlendFunc(GL10.
GL_ONE, GL10.
GL_ONE);
gl.
glEnable(GL10.
GL_TEXTURE_2D);
//Draw the vertices as triangle strip
gl.
glDrawArrays(GL10.
GL_TRIANGLE_STRIP,
0, vertices.
length /
3);
// draw touch points
for (int i =
0; i
< HotPlateView.
MAX_POINTERS; i++
)
{
DrawTouchPoint
(gl, i
);
}
//Disable the client state before leaving
gl.
glDisableClientState(GL10.
GL_VERTEX_ARRAY);
gl.
glDisableClientState(GL10.
GL_COLOR_ARRAY);
gl.
glDisableClientState(GL10.
GL_TEXTURE_COORD_ARRAY);
}
public void updatePlate
(float deltaTime
)
{
timePassed += deltaTime
;
float alpha = timePassed
* heatRate
;
if (alpha
> 1.0f
)
alpha = 1.0f
;
for (int i =
0; i
< colors.
length; i++
)
{
colorBuffer.
put(i, alpha
);
}
}
public void DrawTouchPoint
(GL10 gl,
int i
)
{
if (!touchPoints
[i
].
isActive)
return;
gl.
glMatrixMode(GL10.
GL_PROJECTION);
gl.
glLoadIdentity();
gl.
glOrthof(0.0f, surfaceWidth, surfaceHeight, 0.0f, 0.0f, 1.0f
);
gl.
glMatrixMode(GL10.
GL_MODELVIEW);
gl.
glLoadIdentity();
gl.
glTranslatef(touchPoints
[i
].
X, touchPoints
[i
].
Y, 0.0f
);
gl.
glScalef(50.0f, 50.0f, 1.0f
);
gl.
glBindTexture(GL10.
GL_TEXTURE_2D, textures
[1]);
gl.
glDrawArrays(GL10.
GL_TRIANGLE_STRIP,
0, vertices.
length /
3);
}
}