Etchasketch

Tutorials concerning the OpenGL® ES cross-platform API for full-function 2D and 3D graphics on the Google-Android platform.

Etchasketch

Postby linuxer » Thu Apr 08, 2010 3:29 am

I have been trying for the life of me to make an Etch a sketch style game. The problem I am having is getting the drawPoint to continually draw instead of just moving the point around. I ended up putting each point into an array, but it slows down after a while, because it is redrawing every dot every time. Anyone have a solution?

Here is my complete code:


package com.DoodleDots.particularidiom;



import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.hardware.SensorListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
import android.widget.FrameLayout;

public class DoodleDots extends Activity {

private SensorManager mSensorManager;
private DDView mDDView;

private int x = 160;
private int y = 200;
private int x2 = 0;
private int y2 = 0;
private int x3 = 0;
private int y3 = 0;
private int c = 0;
private int r = 0;
private int[] oldXs = new int[10000];
private int[] oldYs = new int[10000];

private class DDView extends View implements SensorListener {

private Paint mPaint = new Paint();

private float mOrientationValues[] = new float[3];

public DDView(Context context) {
super(context);
mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
}

@Override
protected void onDraw(Canvas canvas) {
mPaint.setColor(0xFF000000);
synchronized (this) {
float[] values = mOrientationValues;
x3 = (int) values[2];
y3 = (int) values[1];

if(x2 < x3 && (x3 - x2) > 15 && x != 299) {
x++;
}
else if(x2 > x3 && (x3 - x2) < -15 && x != 22) {
x--;
}
if(y2 < y3 && (y3 - y2) > 15 && y != 22) {
y--;
}
else if(y2 > y3 && (y3 - y2) < -15 && y != 409) {
y++;
}

mPaint.setColor(0xC2C20000);
canvas.drawRect(0, 0, 20, 480, mPaint);
canvas.drawRect(20, 410, 300, 440, mPaint);
canvas.drawRect(300, 0, 320, 440, mPaint);
canvas.drawRect(20, 0, 300, 20, mPaint);

oldXs[c] = x;
oldYs[r] = y;

mPaint.setColor(0xFF000000);
mPaint.setStrokeWidth(3);

for(int i = 0; i < c; i++)
{
canvas.drawPoint(oldXs[i], oldYs[i], mPaint);
}
}

invalidate();

r++;
c++;
}

public void onSensorChanged(int sensor, float[] values) {

synchronized (this) {
if (sensor == SensorManager.SENSOR_ORIENTATION) {
for (int i=0 ; i<3 ; i++) {
mOrientationValues[i] = values[i];
}
}
}
}

public void onAccuracyChanged(int arg0, int arg1) {
// TODO Auto-generated method stub
}
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
FrameLayout main = (FrameLayout) findViewById(R.id.main_view);
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);

mDDView = new DDView(this);
main.addView(mDDView);
}

@Override
protected void onResume() {
super.onResume();
mSensorManager.registerListener(mDDView,
SensorManager.SENSOR_ACCELEROMETER |
SensorManager.SENSOR_MAGNETIC_FIELD |
SensorManager.SENSOR_ORIENTATION,
SensorManager.SENSOR_DELAY_FASTEST);
}

@Override
protected void onStop() {
mSensorManager.unregisterListener(mDDView);
super.onStop();
}
}
linuxer
Freshman
Freshman
 
Posts: 8
Joined: Thu Apr 08, 2010 2:54 am

Top

Postby MichaelEGR » Thu Apr 08, 2010 5:08 am

What you will want to do is essentially manually double buffer the drawing. Create a Bitmap (RGB_565) draw any stylized background into it. Then draw only new points into it as they come in. I'm not sure how the asynchronous nature of receiving sensor events will affect this process. IE sensor events coming in as you are drawing/rendering. Each cycle of your game loop you'll just draw this one RGB_565 image and performance will be snappy!

With TyphonRT which is my middleware for real time app development that is being released soon I have a custom event system that is cross platform (desktop & Android). It's nice because it supports polled input on Android which is something the Android SDK does not support. This means that at the beginning of your loop you can specifically ask for all events (including sensor events) that have occurred since the last poll / game loop cycle and you can process them in your game thread reliably.

Best of luck, but once you buffer the drawing with a Bitmap performance will scream and you can have an unlimited amount of points to draw. You should even be able to blur or distort this bitmap with a filter for the user shaking the screen to mimic a clearing effect.

Best of luck!
Founder & Principal Architect; EGR Software LLC
http://www.typhonrt.org
http://www.egrsoftware.com
User avatar
MichaelEGR
Senior Developer
Senior Developer
 
Posts: 147
Joined: Thu Jan 21, 2010 5:30 am
Location: San Francisco, CA

Postby MichaelEGR » Thu Apr 08, 2010 1:43 pm

A FYI... I'm going to make a tutorial out of the procedure I described for TyphonRT including a blurred shake effect. ~2 months before public launch, but I'll be doing a closed beta and this tutorial should make the closed beta. Hit up my contact email on the TyphonRT web site if you'd like to get into the closed beta. Thanks for the idea as this provides a great way to demonstrate polled input and double buffering. :)
Founder & Principal Architect; EGR Software LLC
http://www.typhonrt.org
http://www.egrsoftware.com
User avatar
MichaelEGR
Senior Developer
Senior Developer
 
Posts: 147
Joined: Thu Jan 21, 2010 5:30 am
Location: San Francisco, CA

Postby linuxer » Mon Apr 12, 2010 1:00 am

I feel stupid here, but could anyone give me an idea on where to start with dealing with bitmaps? I am pretty new to this stuff and can't seem to get anything working.
linuxer
Freshman
Freshman
 
Posts: 8
Joined: Thu Apr 08, 2010 2:54 am

Postby linuxer » Wed Apr 14, 2010 3:16 am

I can't figure out how to get it to draw a new dot! It just moves the object.
linuxer
Freshman
Freshman
 
Posts: 8
Joined: Thu Apr 08, 2010 2:54 am

Postby mb_zi » Wed Apr 14, 2010 10:10 pm

haven't worked with canvas, but if this was Opengl then you can simply have a float[] which you pass to a Lines class which draws the line you want (aka the etchasketch). each time the user moves the point you can add the new x and y to the float[]. thus everytime you render you render the line with the new float[].
e.g.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. Class Etchasketch
  3.  
  4.  
  5.  
  6. private Lines lines;
  7.  
  8. private float[] coords ={0,0};
  9.  
  10.  
  11.  
  12. Etchasketch()
  13.  
  14. {
  15.  
  16.  
  17.  
  18.         lines = new Lines(coords);
  19.  
  20. }
  21.  
  22.  
  23.  
  24. onDrawFrame(GL10 gl)
  25.  
  26. { lines.draw(gl)
  27.  
  28. }
  29.  
  30.  
  31.  
  32. onTouchEvent(MotionEvent event)//if using keys to do the input aka the ball thingy sensor then onKeyEvent
  33.  
  34. {
  35.  
  36.       coords = coords{previous coords + new x and y};
  37.  
  38.       lines.upDateArr(coords);
  39.  
  40. }
  41.  
  42. }
  43.  
  44.  
Parsed in 0.031 seconds, using GeSHi 1.0.8.4
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. public class Lines
  3.  
  4. {
  5.  
  6.         private FloatBuffer vertexBuffer;
  7.  
  8.         private float vertices[];
  9.  
  10.  
  11.  
  12.         public Lines(float[] vertices)
  13.  
  14.         {      
  15.  
  16.  
  17.  
  18.                 this.vertices = vertices;
  19.  
  20.                 ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
  21.  
  22.                 byteBuf.order(ByteOrder.nativeOrder());
  23.  
  24.                 vertexBuffer = byteBuf.asFloatBuffer();
  25.  
  26.                 vertexBuffer.put(vertices);
  27.  
  28.                 vertexBuffer.position(0);
  29.  
  30.         }
  31.  
  32.  
  33.  
  34.         public void draw(GL10 gl)
  35.  
  36.         {      
  37.  
  38.                 gl.glFrontFace(GL10.GL_CW);
  39.  
  40.                 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
  41.  
  42.                 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
  43.  
  44.                 gl.glColor4f(1f, 0f, 1f, 1f);
  45.  
  46.                 gl.glDrawArrays(GL10.GL_LINES, 0, vertices.length / 3);
  47.  
  48.                 gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
  49.  
  50.         }
  51.  
  52.  
  53.  
  54.         upDateArr(Float[] vertices)
  55.  
  56.         {
  57.  
  58.                 this.vertices = vertices;
  59.  
  60.                 ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
  61.  
  62.                 byteBuf.order(ByteOrder.nativeOrder());
  63.  
  64.                 vertexBuffer = byteBuf.asFloatBuffer();
  65.  
  66.                 vertexBuffer.put(vertices);
  67.  
  68.                 vertexBuffer.position(0);
  69.  
  70.          }
  71.  
  72. }
Parsed in 0.035 seconds, using GeSHi 1.0.8.4


Thats the way id do it anyway. er the lines class should work as i currently use it on my apps. its a basic draw class which theres numerous versions of on the web. you can easily make it more efficient to. as for the OpenGL class (Etchasketch) its in basic pseudo code. if you do a nehe tutorial or any other basic opengl tutorial youll get the jist. hope this helps somewhat. currently _train_lagged (heaters on full... no open windows.... boiling weather... :'( ) so sorry if i havent typed coherently
mb_zi
Junior Developer
Junior Developer
 
Posts: 17
Joined: Sat Feb 27, 2010 2:16 am

Top

Return to Android 2D/3D Graphics - OpenGL Tutorials

Who is online

Users browsing this forum: No registered users and 2 guests