How can I draw individually on surfaceView? - android

I want to build a dx ball game. In my game, I want to draw a ball, a bar, bricks individually. It means when ball position is ready, the ball will draw; when bricks are ready bricks will draw. In the normal way, I lock surface holder then draw everything. Example:
#Override
public void run() {
while(ballPlay){
try{
gameCanvas = null;
gameCanvas = surfaceHolder.lockCanvas();
gameCanvas.drawColor(Color.WHITE);
ballPosition.drawBall(gameCanvas);
for (int i = 0; i < brickCount; i++) {
brick[i].drawBrick(gameCanvas);
}
gameBar.drawBar(gameCanvas);
}catch (Exception e){
e.printStackTrace();
} finally {
if(gameCanvas!=null){
surfaceHolder.unlockCanvasAndPost(gameCanvas);
}
}
}
}
Then, we unlock it and post. But, how can I draw everything separately?

Related

how render canvas on imageView to show circle moving faster (not jumping)

I have balls class extends ImageView
and on this i have Circle Ball going from left side to right side and in any time speed of Moving increased <
private void render() {
while (true) {
Thread.sleep(30);
if(x > getwidth()){
Step++ && x = 0;
}
x += step
}
}
private void update() {
while (true) {
Thread.sleep(60);
Postinvalidate();
}
}
any thing is Good but when step equals 20 and more < the ball do not movie Rightly and we see it jumping <
I testing the Step = 5 and Thread.sleep(value--) < but did not work Rightly
how can I Move the ball faster and render of onDraw was Rightly
TNX ALL < #};-

How to avoid ghost drawing after clearing SurfaceView canvas

Hi I am working on plotting a real time graph of incoming signals using SurfaceView.
The sampling rate is 128Hz and the target graph refresh rate is 50Zh.
Things run pretty smoothly, the points are drawn real-time properly.
I plot the data in segments of a few points using Path()
for each segment I call path.computeBounds() to get a rect that I will use to call holder.lockCanvas(rect) and draw the path. Using a rect prevents flickering and reduces cpu usage
when the graph reaches the end I lock the entire canvas and clear the background, draw the graph frame and then continue on plotting.
the problem is that at the beginning of each new "page" I get a ghost image from the last page:
I believe this is caused by double buffering / use of a dirty area when plotting.
I have looked for solutions to this problem but none seem adequate for this type of application. Any help is most welcome.
Thanks
Jean-Pierre
Code follows:
private void draw() {
Point point = null;
Canvas canvas = null;
Path path = new Path();
ArrayList<Point> pointArray;
float oldX = -1;
boolean setToClear = false;
boolean isNewSegment = false;
if (samplesInQueue == 0) {
return;
}
pointArray = new ArrayList<Point>((int) samplesInQueue);
for (int i = 0; i < samplesInQueue; i++) {
// take a peek at the point without retrieving it from the point
// queue
point = Points.peek();
// check if first point of segment is the start of a page
if (i == 0) {
if (lastSegmentEndPoint != null) {
if (point.x < lastSegmentEndPoint.x) {
// yes then we will need to clear the screen now
isNewSegment = true;
}
} else {
// yes then we will need to clear the screen now
isNewSegment = true;
}
}
if (point != null) {
if (point.x > oldX) {
// put consecutive points in the path point array
point = Points.poll();
samplesInQueue--;
pointArray.add(point);
oldX = point.x;
} else {
// we have a wrap around, stop and indicate we need to clear
// the screen on the next pass
if (!isNewSegment) {
setToClear = true;
}
break;
}
}
}
// no points, return
if (pointArray.size() == 0) {
return;
}
// fill the path
for (int i = 0; i < pointArray.size(); i++) {
Point p = pointArray.get(i);
if (i == 0) {
if (lastSegmentEndPoint != null) {
if (p.x >= lastSegmentEndPoint.x) {
// if we have the end of the last segment, move to it
// and line to the new point
path.moveTo(lastSegmentEndPoint.x, lastSegmentEndPoint.y);
path.lineTo(p.x, p.y);
} else {
// otherwise just line to the new point
path.moveTo(p.x, p.y);
}
} else {
path.moveTo(p.x, p.y);
}
} else {
path.lineTo(p.x, p.y);
}
}
if (clear || isNewSegment) {
if (clear) {
clear = false;
}
// we need to clear, lock the whole canvas
canvas = holder.lockCanvas();
// draw the graph frame / scales
drawGraphFrame = true;
drawGraphFrame(canvas);
} else {
// just draw the path
RectF bounds = new RectF();
Rect dirty = new Rect();
// calculate path bounds
path.computeBounds(bounds, true);
int extra = 0;
dirty.left = (int) java.lang.Math.floor(bounds.left - extra);
dirty.top = (int) java.lang.Math.floor(bounds.top - extra);
dirty.right = (int) java.lang.Math.round(bounds.right + 0.5);
dirty.bottom = (int) java.lang.Math.round(bounds.bottom + 0.5);
// just lock what is needed to plot the path
canvas = holder.lockCanvas(dirty);
}
// draw the path
canvas.drawPath(path, linePaint);
// unlock the canvas
holder.unlockCanvasAndPost(canvas);
// remember last segment end point
lastSegmentEndPoint = pointArray.get(pointArray.size() - 1);
// set clear flag for next pass
if (setToClear) {
clear = true;
}
}
Draw frame / clear graph code
private void drawGraphFrame(Canvas canvas) {
if (!drawGraphFrame) {
return;
}
if (canvas == null) {
Log.e(TAG, "trying to draw on a null canvas");
return;
}
drawGraphFrame = false;
// clear the graph
canvas.drawColor(Color.BLACK, Mode.CLEAR);
// draw the graph frame
canvas.drawLine(leftMargin, topMargin, leftMargin, mCanvasHeight - bottomMargin, framePaint);
canvas.drawLine(leftMargin, mCanvasHeight - bottomMargin, mCanvasWidth - rightMargin, mCanvasHeight
- bottomMargin, framePaint);
// more drawing
}
Your problem is quite straight forward.. your only locking the new portion of the canvas that the new path covers. So the best thing to do is to make your path and dirty rect's private members of your class. Then at the start of your draw method get the path's current bounds (the old bounds) in your dirty rect. Now call path.rewind(); and start modifying your path. After do a union on the dirty rect with the new bounds. Now your dirty rect covers the old and new rect's. So your clear will remove the old path. This also reduces overhead because you don't want to be allocating 100+ objects per second for rect's and path's. Now since your drawing an oscilloscope then you probably want to adjust the old bounds to only be a portion of the width of the view. The same amount your new portion covers.
Hope that's cleared things up.
My simple answer is just using this function clear_holder() wherever you want to clear the canvas. I copy and paste 3 line for 3 times because it need 3 times clear to leave holder blank.
After clearing holder, you should draw any new thing you want!
This link give me this source code!
private void clear_holder(SurfaceHolder holder){
Canvas c = holder.lockCanvas();
c.drawColor( 0, PorterDuff.Mode.CLEAR );
holder.unlockCanvasAndPost(c);
c = holder.lockCanvas();
c.drawColor( 0, PorterDuff.Mode.CLEAR );
holder.unlockCanvasAndPost(c);
c = holder.lockCanvas();
c.drawColor( 0, PorterDuff.Mode.CLEAR );
holder.unlockCanvasAndPost(c);
}
It looks like you are clearing the canvas so, it's not double buffering problem. I think it's related to your path been reused.
Try adding adding the next line when starting new page.
path.reset();

Flickering when drawing bitmaps with canvas in Android

I'm trying to do a menu based on bitmaps. The menu itself should be movable through screentouch move events, basically I want to drag the buttons around on the view. The button also includes collision detection, so whenever they touch they bounce from each other.
But I have some problems when it comes to drawing my bitmaps. Currently I'm using a rectangle to scale my bitmap to fit the window of my device. Want i want and can not get currently is for smoother movements of my bitmaps without flickering. Is the only option to move to open gl? Or have I missed something big in my code?
This is in my surfaceview for drawing each button, where MenuButton is the class that holds the bitmap and updates its position according to a touch and drag move.
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
for(MenuButton menuButton : menuButtonSprites) {
menuButton.onDraw(canvas);
}
}
I want the bitmaps to scale to each device's width and for that i use a rectangle for the bitmap to fit in.
public MenuButton(MenuView v, Bitmap bmp, int yPosition){
this.menuView = v;
this.menuButton = bmp;
this.xMax = v.getWidth();
this.yPosistion = yPosition;
menuButtonRectangle = new Rect(xMin, this.yPosistion-yMin, xMax, this.yPosistion+yMax);
}
public void update(int y){
if(menuButtonPressed)
{
this.yPosistion = y;
menuButtonRectangle.set(xMin, yPosistion-yMin, xMax, yPosistion+yMax);
}
}
public void onDraw(Canvas canvas){
canvas.drawBitmap(menuButton, null, menuButtonRectangle, null);
}
I also have a thread that updates the draw
public void run() {
long ticksPS = 1000 / FPS;
long startTime;
long sleepTime;
Canvas c = null;
while (running) {
startTime = System.currentTimeMillis();
try {
c = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
view.onDraw(c);
}
}
finally {
if (c != null) {
view.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime = ticksPS - (System.currentTimeMillis() - startTime);
try {
if (sleepTime > 0)
sleep(sleepTime);
else
sleep(10);
}
catch (Exception e) {
}
}
}
I don't really know what I'm doing wrong and why i can't manage to get a smooth movements of my buttons. Is it a downside for using canvas or have I missed something really important :D?
Usually This problem occurs when there is sync problem exists while painting. This may due to the higher Frame rate or also may be the lower frame rate. These kind of issue can be fixed by Double buffering or adjusting the Frame Rate.
Double buffering means, Instead of drawing the Image directly on to the main canvas, we will be creating an empty bitmap of screen size and getting the graphics object. Drawing every thing on to the bitmap then directly drawing this bitmap to the main canvas.

How to get a smooth move?

Hi I am not getting a smooth move, in my game train moves front and back it is nice, but train movement is not smooth(like not train move fixed speed and smooth). Please help............
public void run() {
Canvas canvas = null;
while (mRun) {
long beginTimeMillis, timeTakenMillis, timeLeftMillis;
canvas = mHolder.lockCanvas();
if (canvas != null) {
beginTimeMillis = System.currentTimeMillis();
gp.doDraw(canvas);
gp.animate();
timeTakenMillis = System.currentTimeMillis() - beginTimeMillis;
timeLeftMillis = (1000L / 30) - timeTakenMillis;
Log.i("timeLeftMillis"+timeLeftMillis,"");
mHolder.unlockCanvasAndPost(canvas);
if (timeLeftMillis < 5) {
timeLeftMillis = 5;
}
try {
TimeUnit.MILLISECONDS.sleep(timeLeftMillis);
} catch (InterruptedException ie) {
}
}
}
}
Edit: I don't know how to use the thread while getting a smooth move.
are you using View or SurfaceView. If your using View, use surfaceview. It will make your application much smoother.

Android overlapping views

I'm new to Android and let me first tell you what I'm trying to achieve. Using sockets, I'm sending pictures from my computer's webcam every 50ms. In Android app, I've created my display that extends View. I've added this view to FrameLayout. Parallel thread is receiving images from server app (desktop) and refreshing my display.
On this image I want to display some accelerometer data that refreshes every... Well it's set to SENSOR_DELAY_FASTEST. So I also created another display that extends View, and also I add it to another FrameLayout. Now I set my main.xml to overlap those FrameLayouts..
I'm getting my image from desktop application, I'm drawing accelerometer data, and It's overlapped, but the issue is.. It's flickering. Can anyone help? Or suggest something.. As I've pointed out, I'm new with Android.
Thanks..
This is a simple override that draws an image. - And and the method that calls for a redraw.
#Override
protected void onDraw(Canvas canvas){
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
paint.setARGB(10, 255, 255, 255);
if(Core.pic != null) {
canvas.drawBitmap(Core.pic, 0, 0, paint);
}
}
Here is a different class that calls for redraw when new image is available:
protected static volatile Bitmap pic;
public static void refreshDisplay(Bitmap img){
pic = img;
if(cameraDisplay != null) {
try{
cameraDisplay.invalidate();
}
catch(Exception e){
e.printStackTrace();
}
}
}
And here is a threaded class that ready port every 50ms:
while(running){
opt.inDither = true;
opt.inPreferredConfig = Bitmap.Config.ARGB_8888;
if(in != null){
byte[] recieve = new byte[7000];
try {
in.read(recieve, 0, 7000);
Core.pic = BitmapFactory.decodeByteArray(recieve, 0, 7000, opt);
} catch (IOException e) {}
}
try {
sleep(50);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
This alone works fine. When I overlap this views then it flickers. In the similar way I'm reading accelerometer data and draw it:
public void onAccelerationChanged(float x, float y, float z) {
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){
velocityBars.DrawVelocity(x, -z);
}
else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
velocityBars.DrawVelocity(y, -z);
}
}
velocityBars is my variable that is type of my custom View. This method DrawVelocity invokes the invalidate() method. This forces redraw.

Categories

Resources