I am trying to implement a Drawing Application in Android where the user should be able to select and move the drawn shapes.
Currently, I have statically drawn some rects and text on my Drawing Canvas.
I want to select (draw borders on the selected shape) and move the drawn shapes in onTouch events of the drawing canvas.
package com.android.graphics;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;
public class CanvasView extends View {
public enum Mode {
DRAW,
TEXT,
ERASER;
}
public enum Drawer {
PEN,
LINE,
RECTANGLE,
CIRCLE,
ELLIPSE,
QUADRATIC_BEZIER,
QUBIC_BEZIER;
}
private Canvas canvas = null;
private Bitmap bitmap = null;
private List<Path> pathLists = new ArrayList<Path>();
private List<Paint> paintLists = new ArrayList<Paint>();
private final Paint emptyPaint = new Paint();
private int baseColor = Color.WHITE;
// for Undo, Redo
private int historyPointer = 0;
// Flags
private Mode mode = Mode.DRAW;
private Drawer drawer = Drawer.PEN;
private boolean isDown = false;
// for Paint
private Paint.Style paintStyle = Paint.Style.STROKE;
private int paintStrokeColor = Color.BLACK;
private int paintFillColor = Color.BLACK;
private float paintStrokeWidth = 3F;
private int opacity = 255;
private float blur = 0F;
private Paint.Cap lineCap = Paint.Cap.ROUND;
private PathEffect drawPathEffect = null;
// for Text
private String text = "";
private Typeface fontFamily = Typeface.DEFAULT;
private float fontSize = 32F;
private Paint.Align textAlign = Paint.Align.RIGHT; // fixed
private Paint textPaint = new Paint();
private float textX = 0F;
private float textY = 0F;
// for Drawer
private float startX = 0F;
private float startY = 0F;
private float controlX = 0F;
private float controlY = 0F;
public CanvasView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.setup();
}
public CanvasView(Context context, AttributeSet attrs) {
super(context, attrs);
this.setup();
}
public CanvasView(Context context) {
super(context);
this.setup();
}
private void setup() {
this.pathLists.add(new Path());
this.paintLists.add(this.createPaint());
this.historyPointer++;
this.textPaint.setARGB(0, 255, 255, 255);
}
private Paint createPaint() {
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(this.paintStyle);
paint.setStrokeWidth(this.paintStrokeWidth);
paint.setStrokeCap(this.lineCap);
paint.setStrokeJoin(Paint.Join.MITER); // fixed
// for Text
if (this.mode == Mode.TEXT) {
paint.setTypeface(this.fontFamily);
paint.setTextSize(this.fontSize);
paint.setTextAlign(this.textAlign);
paint.setStrokeWidth(0F);
}
if (this.mode == Mode.ERASER) {
// Eraser
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
paint.setARGB(0, 0, 0, 0);
} else {
// Otherwise
paint.setColor(this.paintStrokeColor);
paint.setShadowLayer(this.blur, 0F, 0F, this.paintStrokeColor);
paint.setAlpha(this.opacity);
paint.setPathEffect(this.drawPathEffect);
}
return paint;
}
private Path createPath(MotionEvent event) {
Path path = new Path();
// Save for ACTION_MOVE
this.startX = event.getX();
this.startY = event.getY();
path.moveTo(this.startX, this.startY);
return path;
}
private void updateHistory(Path path) {
if (this.historyPointer == this.pathLists.size()) {
this.pathLists.add(path);
this.paintLists.add(this.createPaint());
this.historyPointer++;
} else {
// On the way of Undo or Redo
this.pathLists.set(this.historyPointer, path);
this.paintLists.set(this.historyPointer, this.createPaint());
this.historyPointer++;
for (int i = this.historyPointer, size = this.paintLists.size(); i < size; i++) {
this.pathLists.remove(this.historyPointer);
this.paintLists.remove(this.historyPointer);
}
}
}
private Path getCurrentPath() {
return this.pathLists.get(this.historyPointer - 1);
}
private void drawText(Canvas canvas) {
if (this.text.length() <= 0) {
return;
}
if (this.mode == Mode.TEXT) {
this.textX = this.startX;
this.textY = this.startY;
this.textPaint = this.createPaint();
}
float textX = this.textX;
float textY = this.textY;
Paint paintForMeasureText = new Paint();
// Line break automatically
float textLength = paintForMeasureText.measureText(this.text);
float lengthOfChar = textLength / (float) this.text.length();
float restWidth = this.canvas.getWidth() - textX; // text-align : right
int numChars = (lengthOfChar <= 0) ? 1 : (int) Math.floor((double) (restWidth / lengthOfChar)); // The number of characters at 1 line
int modNumChars = (numChars < 1) ? 1 : numChars;
float y = textY;
for (int i = 0, len = this.text.length(); i < len; i += modNumChars) {
String substring = "";
if ((i + modNumChars) < len) {
substring = this.text.substring(i, (i + modNumChars));
} else {
substring = this.text.substring(i, len);
}
y += this.fontSize;
canvas.drawText(substring, textX, y, this.textPaint);
}
}
private void onActionDown(MotionEvent event) {
switch (this.mode) {
case DRAW:
case ERASER:
if ((this.drawer != Drawer.QUADRATIC_BEZIER) && (this.drawer != Drawer.QUBIC_BEZIER)) {
// Oherwise
this.updateHistory(this.createPath(event));
this.isDown = true;
} else {
// Bezier
if ((this.startX == 0F) && (this.startY == 0F)) {
// The 1st tap
this.updateHistory(this.createPath(event));
} else {
// The 2nd tap
this.controlX = event.getX();
this.controlY = event.getY();
this.isDown = true;
}
}
break;
case TEXT:
this.startX = event.getX();
this.startY = event.getY();
break;
default:
break;
}
}
private void onActionMove(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (this.mode) {
case DRAW:
case ERASER:
if ((this.drawer != Drawer.QUADRATIC_BEZIER) && (this.drawer != Drawer.QUBIC_BEZIER)) {
if (!isDown) {
return;
}
Path path = this.getCurrentPath();
switch (this.drawer) {
case PEN:
path.lineTo(x, y);
break;
case LINE:
path.reset();
path.moveTo(this.startX, this.startY);
path.lineTo(x, y);
break;
case RECTANGLE:
path.reset();
float left = Math.min(this.startX, x);
float right = Math.max(this.startX, x);
float top = Math.min(this.startY, y);
float bottom = Math.max(this.startY, y);
path.addRect(left, top, right, bottom, Path.Direction.CCW);
break;
case CIRCLE:
double distanceX = Math.abs((double) (this.startX - x));
double distanceY = Math.abs((double) (this.startX - y));
double radius = Math.sqrt(Math.pow(distanceX, 2.0) + Math.pow(distanceY, 2.0));
path.reset();
path.addCircle(this.startX, this.startY, (float) radius, Path.Direction.CCW);
break;
case ELLIPSE:
RectF rect = new RectF(this.startX, this.startY, x, y);
path.reset();
path.addOval(rect, Path.Direction.CCW);
break;
default:
break;
}
} else {
if (!isDown) {
return;
}
Path path = this.getCurrentPath();
path.reset();
path.moveTo(this.startX, this.startY);
path.quadTo(this.controlX, this.controlY, x, y);
}
break;
case TEXT:
this.startX = x;
this.startY = y;
break;
default:
break;
}
}
private void onActionUp(MotionEvent event) {
if (isDown) {
this.startX = 0F;
this.startY = 0F;
this.isDown = false;
}
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Before "drawPath"
canvas.drawColor(this.baseColor);
if (this.bitmap != null) {
canvas.drawBitmap(this.bitmap, 0F, 0F, emptyPaint);
}
for (int i = 0; i < this.historyPointer; i++) {
Path path = this.pathLists.get(i);
Paint paint = this.paintLists.get(i);
canvas.drawPath(path, paint);
}
this.drawText(canvas);
this.canvas = canvas;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
this.onActionDown(event);
break;
case MotionEvent.ACTION_MOVE:
this.onActionMove(event);
break;
case MotionEvent.ACTION_UP:
this.onActionUp(event);
break;
default:
break;
}
// Re draw
this.invalidate();
return true;
}
public Mode getMode() {
return this.mode;
}
public void setMode(Mode mode) {
this.mode = mode;
}
public Drawer getDrawer() {
return this.drawer;
}
public void setDrawer(Drawer drawer) {
this.drawer = drawer;
}
public boolean canUndo() {
return this.historyPointer > 1;
}
public boolean canRedo() {
return this.historyPointer < this.pathLists.size();
}
public boolean undo() {
if (canUndo()) {
this.historyPointer--;
this.invalidate();
return true;
} else {
return false;
}
}
public boolean redo() {
if (canRedo()) {
this.historyPointer++;
this.invalidate();
return true;
} else {
return false;
}
}
public void clear() {
Path path = new Path();
path.moveTo(0F, 0F);
path.addRect(0F, 0F, 3000F, 3000F, Path.Direction.CCW);
path.close();
Paint paint = new Paint();
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.FILL);
if (this.historyPointer == this.pathLists.size()) {
this.pathLists.add(path);
this.paintLists.add(paint);
this.historyPointer++;
} else {
// On the way of Undo or Redo
this.pathLists.set(this.historyPointer, path);
this.paintLists.set(this.historyPointer, paint);
this.historyPointer++;
for (int i = this.historyPointer, size = this.paintLists.size(); i < size; i++) {
this.pathLists.remove(this.historyPointer);
this.paintLists.remove(this.historyPointer);
}
}
this.text = "";
// Clear
this.invalidate();
}
public int getBaseColor() {
return this.baseColor;
}
public void setBaseColor(int color) {
this.baseColor = color;
}
public String getText() {
return this.text;
}
public void setText(String text) {
this.text = text;
}
public Paint.Style getPaintStyle() {
return this.paintStyle;
}
public void setPaintStyle(Paint.Style style) {
this.paintStyle = style;
}
public int getPaintStrokeColor() {
return this.paintStrokeColor;
}
public void setPaintStrokeColor(int color) {
this.paintStrokeColor = color;
}
public int getPaintFillColor() {
return this.paintFillColor;
}
public void setPaintFillColor(int color) {
this.paintFillColor = color;
}
public float getPaintStrokeWidth() {
return this.paintStrokeWidth;
}
public void setPaintStrokeWidth(float width) {
if (width >= 0) {
this.paintStrokeWidth = width;
} else {
this.paintStrokeWidth = 3F;
}
}
public int getOpacity() {
return this.opacity;
}
public void setOpacity(int opacity) {
if ((opacity >= 0) && (opacity <= 255)) {
this.opacity = opacity;
} else {
this.opacity = 255;
}
}
public float getBlur() {
return this.blur;
}
public void setBlur(float blur) {
if (blur >= 0) {
this.blur = blur;
} else {
this.blur = 0F;
}
}
public Paint.Cap getLineCap() {
return this.lineCap;
}
public void setLineCap(Paint.Cap cap) {
this.lineCap = cap;
}
public PathEffect getDrawPathEffect() {
return drawPathEffect;
}
public void setDrawPathEffect(PathEffect drawPathEffect) {
this.drawPathEffect = drawPathEffect;
}
public float getFontSize() {
return this.fontSize;
}
public void setFontSize(float size) {
if (size >= 0F) {
this.fontSize = size;
} else {
this.fontSize = 32F;
}
}
public Typeface getFontFamily() {
return this.fontFamily;
}
public void setFontFamily(Typeface face) {
this.fontFamily = face;
}
public Bitmap getBitmap() {
this.setDrawingCacheEnabled(false);
this.setDrawingCacheEnabled(true);
return Bitmap.createBitmap(this.getDrawingCache());
}
public Bitmap getScaleBitmap(int w, int h) {
this.setDrawingCacheEnabled(false);
this.setDrawingCacheEnabled(true);
return Bitmap.createScaledBitmap(this.getDrawingCache(), w, h, true);
}
public void drawBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
this.invalidate();
}
public void drawBitmap(byte[] byteArray) {
this.drawBitmap(BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length));
}
public static byte[] getBitmapAsByteArray(Bitmap bitmap, CompressFormat format, int quality) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(format, quality, byteArrayOutputStream);
return byteArrayOutputStream.toByteArray();
}
public byte[] getBitmapAsByteArray(CompressFormat format, int quality) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
this.getBitmap().compress(format, quality, byteArrayOutputStream);
return byteArrayOutputStream.toByteArray();
}
public byte[] getBitmapAsByteArray() {
return this.getBitmapAsByteArray(CompressFormat.PNG, 100);
}
}
Related
I am working on an application which captures an applicant's signature and saves it to the phone memory. The class used for the signature view is given below
public class SignatureView extends View {
private static final float STROKE_WIDTH = 5f;
/** Need to track this so the dirty region can accommodate the stroke. **/
private static final float HALF_STROKE_WIDTH = STROKE_WIDTH / 2;
private Paint paint = new Paint();
private Path path = new Path();
/**
* Optimizes painting by invalidating the smallest possible area.
*/
private float lastTouchX;
private float lastTouchY;
private final RectF dirtyRect = new RectF();
public SignatureView(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(STROKE_WIDTH);
}
/**
* Erases the signature.
*/
public void clear() {
path.reset();
// Repaints the entire view.
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawARGB(255, 233, 255, 255);
canvas.drawPath(path, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(eventX, eventY);
lastTouchX = eventX;
lastTouchY = eventY;
// There is no end point yet, so don't waste cycles invalidating.
return true;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
// Start tracking the dirty region.
resetDirtyRect(eventX, eventY);
// When the hardware tracks events faster than they are delivered, the
// event will contain a history of those skipped points.
int historySize = event.getHistorySize();
for (int i = 0; i < historySize; i++) {
float historicalX = event.getHistoricalX(i);
float historicalY = event.getHistoricalY(i);
expandDirtyRect(historicalX, historicalY);
path.lineTo(historicalX, historicalY);
}
// After replaying history, connect the line to the touch point.
path.lineTo(eventX, eventY);
break;
default:
//debug("Ignored touch event: " + event.toString());
return false;
}
// Include half the stroke width to avoid clipping.
invalidate(
(int) (dirtyRect.left - HALF_STROKE_WIDTH),
(int) (dirtyRect.top - HALF_STROKE_WIDTH),
(int) (dirtyRect.right + HALF_STROKE_WIDTH),
(int) (dirtyRect.bottom + HALF_STROKE_WIDTH));
lastTouchX = eventX;
lastTouchY = eventY;
return true;
}
/**
* Called when replaying history to ensure the dirty region includes all
* points.
*/
private void expandDirtyRect(float historicalX, float historicalY) {
if (historicalX < dirtyRect.left) {
dirtyRect.left = historicalX;
} else if (historicalX > dirtyRect.right) {
dirtyRect.right = historicalX;
}
if (historicalY < dirtyRect.top) {
dirtyRect.top = historicalY;
} else if (historicalY > dirtyRect.bottom) {
dirtyRect.bottom = historicalY;
}
}
/**
* Resets the dirty region when the motion event occurs.
*/
private void resetDirtyRect(float eventX, float eventY) {
// The lastTouchX and lastTouchY were set when the ACTION_DOWN
// motion event occurred.
dirtyRect.left = Math.min(lastTouchX, eventX);
dirtyRect.right = Math.max(lastTouchX, eventX);
dirtyRect.top = Math.min(lastTouchY, eventY);
dirtyRect.bottom = Math.max(lastTouchY, eventY);
}
// get drawn image as bitmap
public Bitmap getBitmap() {
this.setDrawingCacheEnabled(true);
this.buildDrawingCache();
Bitmap bmp = Bitmap.createBitmap(this.getDrawingCache());
this.setDrawingCacheEnabled(false);
return bmp;
}
public boolean isDrawn(){
return ! path.isEmpty();
}
}
This class returns the signature bitmap.This view works fine for devices with Android 8.0 and below, but its not working for Android 8.0 plus devices. For Devices above Android 8.0, the method getBitmap() returns a bitmap of the signature, but for Devices above Android 8.0, it returns empty.
Another Solution I tried which did not work either
public class SignatureViewType3 extends View {
private Bitmap _Bitmap;
private Canvas _Canvas;
private Path _Path;
private Paint _BitmapPaint;
private Paint _paint;
private float _mX;
private float _mY;
private float TouchTolerance = 4;
private float LineThickness = 4;
private boolean signatureAdded;
public SignatureViewType3(Context context, AttributeSet attr) {
super(context, attr);
_Path = new Path();
_BitmapPaint = new Paint(Paint.DITHER_FLAG);
_paint = new Paint();
_paint.setAntiAlias(true);
_paint.setDither(true);
_paint.setColor(Color.argb(255, 0, 0, 0));
_paint.setStyle(Paint.Style.STROKE);
_paint.setStrokeJoin(Paint.Join.ROUND);
_paint.setStrokeCap(Paint.Cap.ROUND);
_paint.setStrokeWidth(LineThickness);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
_Bitmap = Bitmap.createBitmap(w, (h > 0 ? h : ((View) this.getParent()).getHeight()), Bitmap.Config.ARGB_8888);
_Canvas = new Canvas(_Bitmap);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
getParent().requestDisallowInterceptTouchEvent(true);
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(_Bitmap, 0, 0, _BitmapPaint);
canvas.drawPath(_Path, _paint);
}
private void TouchStart(float x, float y) {
_Path.reset();
_Path.moveTo(x, y);
_mX = x;
_mY = y;
}
private void TouchMove(float x, float y) {
float dx = Math.abs(x - _mX);
float dy = Math.abs(y - _mY);
if (dx >= TouchTolerance || dy >= TouchTolerance) {
_Path.quadTo(_mX, _mY, (x + _mX) / 2, (y + _mY) / 2);
_mX = x;
_mY = y;
}
}
private void TouchUp() {
if (!_Path.isEmpty()) {
_Path.lineTo(_mX, _mY);
_Canvas.drawPath(_Path, _paint);
} else {
_Canvas.drawPoint(_mX, _mY, _paint);
}
signatureAdded = true;
_Path.reset();
}
#Override
public boolean onTouchEvent(MotionEvent e) {
super.onTouchEvent(e);
float x = e.getX();
float y = e.getY();
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
TouchStart(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
TouchMove(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
TouchUp();
invalidate();
break;
}
return true;
}
public void clear() {
_Canvas.drawColor(Color.WHITE);
invalidate();
}
public byte[] getBytes() {
Bitmap b = getBitmap();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.PNG, 100, baos);
if(signatureAdded)
return baos.toByteArray();
else
return null;
}
public Bitmap getBitmap() {
View v = (View) this.getParent();
Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.layout(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
v.draw(c);
return b;
}
public boolean isDrawn(){
// return ! _Path.isEmpty();
return true;
}
}
getDrawingCache() is deprecated in Android API 28, so you should use Canvas like in this answer of Ashvin solanki
RelativeLayout view = (RelativeLayout)findViewById(R.id.relativelayout);
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Drawable bgDrawable = view.getBackground();
if (bgDrawable != null) {
bgDrawable.draw(canvas);
} else {
canvas.drawColor(Color.WHITE);
}
view.draw(canvas);
or PixelCopy like in that article of Shivesh Karan Mehta:
// for api level 28
fun getScreenShotFromView(view: View, activity: Activity, callback: (Bitmap) -> Unit) {
activity.window?.let { window ->
val bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
val locationOfViewInWindow = IntArray(2)
view.getLocationInWindow(locationOfViewInWindow)
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
PixelCopy.request(
window,
Rect(
locationOfViewInWindow[0],
locationOfViewInWindow[1],
locationOfViewInWindow[0] + view.width,
locationOfViewInWindow[1] + view.height
), bitmap, { copyResult ->
if (copyResult == PixelCopy.SUCCESS) {
callback(bitmap) }
else {
}
// possible to handle other result codes ...
},
Handler()
)
}
} catch (e: IllegalArgumentException) {
// PixelCopy may throw IllegalArgumentException, make sure to handle it
e.printStackTrace()
}
}
}
i keep getting error draw to canvas
Error
The error keep happening when I tried to draw to the canvas the player after the user move the joystick
it always writes me "cant lock canvas ,canvas already locked"
i'm kind of beginner in game development and sorry if the question is a little unclear if you need more details just say and I will send you more info
Main class - the main activity
package app.shahardagan.Raven;
import android.graphics.Point;
import android.os.Bundle;
import android.app.Activity;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
import android.widget.RelativeLayout;
public class Main extends Activity {
RelativeLayout layout_joystick;
ImageView image_joystick, image_border;
GameEngine gameEngine;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get a Display object to access screen details
Display display = getWindowManager().getDefaultDisplay();
// Load the resolution into a Point object
Point size = new Point();
size.set(display.getWidth(),display.getHeight());
layout_joystick = (RelativeLayout)findViewById(R.id.layout_joystick);
gameEngine = new GameEngine(this,size.x,size.y);
setContentView(gameEngine);
}
#Override
protected void onResume(){
super.onResume();
gameEngine.resume();
}
#Override
protected void onPause(){
super.onPause();
gameEngine.pause();
}
}
GameEngine class - responsible to draw the player and update the game
package app.shahardagan.Raven;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
public class GameEngine extends SurfaceView implements Runnable {
JoyStickClass js;
// This is our thread
private Thread gameThread = null;
// This is new. We need a SurfaceHolder
// When we use Paint and Canvas in a thread
// We will see it in action in the draw method soon.
private SurfaceHolder ourHolder;
// A boolean which we will set and unset
// when the game is running- or not.
private volatile boolean playing;
// Game is paused at the start
private boolean paused = true;
// A Canvas and a Paint object
private Canvas canvas;
private Paint paint;
// How wide and high is the screen?
private int screenX;
private int screenY;
// This variable tracks the game frame rate
private long fps;
// This is used to help calculate the fps
private long timeThisFrame;
private Context context;
private Player player;
private Drawable playerImage;
public GameEngine(Context context, int x, int y) {
// This calls the default constructor to setup the rest of the object
super(context);
this.context = context;
// Initialize ourHolder and paint objects
ourHolder = getHolder();
paint = new Paint();
// Initialize screenX and screenY because x and y are local
screenX = x;
screenY = y;
prepareLevel();
}
private void prepareLevel(){
player = new Player(context,screenX,screenY);
}
public void PlayerControls(Context context,RelativeLayout layout_joystick, ImageView image_joystick, ImageView image_border){
js = new JoyStickClass(context, layout_joystick, R.drawable.image_button);
js.setStickSize(150, 150);
js.setLayoutSize(500, 500);
js.setLayoutAlpha(150);
js.setStickAlpha(100);
js.setOffset(90);
js.setMinimumDistance(50);
layout_joystick.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View arg0, MotionEvent arg1) {
js.drawStick(arg1);
if(arg1.getAction() == MotionEvent.ACTION_DOWN || arg1.getAction() == MotionEvent.ACTION_MOVE) {
int direction = js.get8Direction();
if(direction == JoyStickClass.STICK_UP) {
} else if(direction == JoyStickClass.STICK_UPRIGHT) {
player.setMovementState(Player.UP);
} else if(direction == JoyStickClass.STICK_RIGHT) {
} else if(direction == JoyStickClass.STICK_DOWNRIGHT) {
} else if(direction == JoyStickClass.STICK_DOWN) {
} else if(direction == JoyStickClass.STICK_DOWNLEFT) {
} else if(direction == JoyStickClass.STICK_LEFT) {
} else if(direction == JoyStickClass.STICK_UPLEFT) {
} else if(direction == JoyStickClass.STICK_NONE) {
}
} else if(arg1.getAction() == MotionEvent.ACTION_UP) {
}
return true;
}
});
}
// Runs when the OS calls onPause on BreakoutActivity method
public void pause() {
playing = false;
try {
gameThread.join();
} catch (InterruptedException e) {
Log.e("Error:", "joining thread");
}
}
// Runs when the OS calls onResume on BreakoutActivity method
public void resume() {
playing = true;
gameThread = new Thread(this);
gameThread.start();
}
#Override
public void run() {
while (playing) {
// Capture the current time in milliseconds in startFrameTime
long startFrameTime = System.currentTimeMillis();
// Update the frame
// Update the frame
if(!paused){
update();
}
// Draw the frame
draw();
// Calculate the fps this frame
// We can then use the result to
// time animations and more.
timeThisFrame = System.currentTimeMillis() - startFrameTime;
if (timeThisFrame >= 1) {
fps = 1000 / timeThisFrame;
}
}
}
private void draw() {
// Make sure our drawing surface is valid or game will crash
if (ourHolder.getSurface().isValid()) {
// Lock the canvas ready to draw
canvas = ourHolder.lockCanvas();
// Draw the background color
canvas.drawColor(Color.argb(255, 26, 128, 182));
// Draw everything to the screen
// Choose the brush color for drawing
paint.setColor(Color.argb(255, 255, 255, 255));
canvas.drawBitmap(player.getBitmap(),player.getX(),screenY - player.getHeight(),paint);
}
}
private void update() {
player.update(fps);
}
}
Player class - the player class methods
package app.shahardagan.Raven;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.RectF;
public class Player {
// RectF is an object that holds four coordinates - just what we need
private RectF rect;
private Bitmap bitmap;
// How long will our paddle will be
private float length;
private float height;
// X is the far left of the rectangle which forms our paddle
private float x;
private float y;
// Which ways can the player move
final int STOPPED = 0;
public static final int UP = 1;
public static final int UPRIGHT = 2;
public static final int RIGHT = 3;
public static final int DOWNRIGHT = 4;
public static final int DOWN = 5;
public static final int DOWNLEFT = 6;
public static final int LEFT = 7;
public static final int UPLEFT = 8;
// Is the paddle moving and in which direction
private int playerMoving = STOPPED;
private int playerSpeed;
public Player(Context context,int screenX, int screenY){
rect = new RectF();
length =screenX/10;
height = screenX/10;
x = screenX;
y= 0;
bitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.eagle_fly);
bitmap = Bitmap.createScaledBitmap(bitmap,(int)length,(int)height,false);
playerSpeed = 350;
}
public RectF getRect(){
return rect;
}
public Bitmap getBitmap(){
return bitmap;
}
public float getX(){ return x; }
public float getHeight(){return height;}
private float getLength(){return length;}
public void setMovementState(int state){
playerMoving = state;
}
void update(long fps){
if(playerMoving == LEFT){
x = x - playerSpeed / fps;
}
if(playerMoving == RIGHT){
x = x + playerSpeed / fps;
}
rect.top = y;
rect.bottom = y+ height;
rect.left = x;
rect.right = x + length;
}
}
Joy stick class
package app.shahardagan.Raven;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
public class JoyStickClass {
public static final int STICK_NONE = 0;
public static final int STICK_UP = 1;
public static final int STICK_UPRIGHT = 2;
public static final int STICK_RIGHT = 3;
public static final int STICK_DOWNRIGHT = 4;
public static final int STICK_DOWN = 5;
public static final int STICK_DOWNLEFT = 6;
public static final int STICK_LEFT = 7;
public static final int STICK_UPLEFT = 8;
private int STICK_ALPHA = 200;
private int LAYOUT_ALPHA = 200;
private int OFFSET = 0;
private Context mContext;
private ViewGroup mLayout;
private LayoutParams params;
private int stick_width, stick_height;
private int position_x = 0, position_y = 0, min_distance = 0;
private float distance = 0, angle = 0;
private DrawCanvas draw;
private Paint paint;
private Bitmap stick;
private boolean touch_state = false;
public JoyStickClass (Context context, ViewGroup layout, int stick_res_id) {
mContext = context;
stick = BitmapFactory.decodeResource(mContext.getResources(),
stick_res_id);
stick_width = stick.getWidth();
stick_height = stick.getHeight();
draw = new DrawCanvas(mContext);
paint = new Paint();
mLayout = layout;
params = mLayout.getLayoutParams();
}
public void drawStick(MotionEvent arg1) {
position_x = (int) (arg1.getX() - (params.width / 2));
position_y = (int) (arg1.getY() - (params.height / 2));
distance = (float) Math.sqrt(Math.pow(position_x, 2) + Math.pow(position_y, 2));
angle = (float) cal_angle(position_x, position_y);
if(arg1.getAction() == MotionEvent.ACTION_DOWN) {
if(distance <= (params.width / 2) - OFFSET) {
draw.position(arg1.getX(), arg1.getY());
draw();
touch_state = true;
}
} else if(arg1.getAction() == MotionEvent.ACTION_MOVE && touch_state) {
if(distance <= (params.width / 2) - OFFSET) {
draw.position(arg1.getX(), arg1.getY());
draw();
} else if(distance > (params.width / 2) - OFFSET){
float x = (float) (Math.cos(Math.toRadians(cal_angle(position_x, position_y))) * ((params.width / 2) - OFFSET));
float y = (float) (Math.sin(Math.toRadians(cal_angle(position_x, position_y))) * ((params.height / 2) - OFFSET));
x += (params.width / 2);
y += (params.height / 2);
draw.position(x, y);
draw();
} else {
mLayout.removeView(draw);
}
} else if(arg1.getAction() == MotionEvent.ACTION_UP) {
mLayout.removeView(draw);
touch_state = false;
}
}
public int[] getPosition() {
if(distance > min_distance && touch_state) {
return new int[] { position_x, position_y };
}
return new int[] { 0, 0 };
}
public int getX() {
if(distance > min_distance && touch_state) {
return position_x;
}
return 0;
}
public int getY() {
if(distance > min_distance && touch_state) {
return position_y;
}
return 0;
}
public float getAngle() {
if(distance > min_distance && touch_state) {
return angle;
}
return 0;
}
public float getDistance() {
if(distance > min_distance && touch_state) {
return distance;
}
return 0;
}
public void setMinimumDistance(int minDistance) {
min_distance = minDistance;
}
public int getMinimumDistance() {
return min_distance;
}
public int get8Direction() {
if(distance > min_distance && touch_state) {
if(angle >= 247.5 && angle < 292.5 ) {
return STICK_UP;
} else if(angle >= 292.5 && angle < 337.5 ) {
return STICK_UPRIGHT;
} else if(angle >= 337.5 || angle < 22.5 ) {
return STICK_RIGHT;
} else if(angle >= 22.5 && angle < 67.5 ) {
return STICK_DOWNRIGHT;
} else if(angle >= 67.5 && angle < 112.5 ) {
return STICK_DOWN;
} else if(angle >= 112.5 && angle < 157.5 ) {
return STICK_DOWNLEFT;
} else if(angle >= 157.5 && angle < 202.5 ) {
return STICK_LEFT;
} else if(angle >= 202.5 && angle < 247.5 ) {
return STICK_UPLEFT;
}
} else if(distance <= min_distance && touch_state) {
return STICK_NONE;
}
return 0;
}
public int get4Direction() {
if(distance > min_distance && touch_state) {
if(angle >= 225 && angle < 315 ) {
return STICK_UP;
} else if(angle >= 315 || angle < 45 ) {
return STICK_RIGHT;
} else if(angle >= 45 && angle < 135 ) {
return STICK_DOWN;
} else if(angle >= 135 && angle < 225 ) {
return STICK_LEFT;
}
} else if(distance <= min_distance && touch_state) {
return STICK_NONE;
}
return 0;
}
public void setOffset(int offset) {
OFFSET = offset;
}
public int getOffset() {
return OFFSET;
}
public void setStickAlpha(int alpha) {
STICK_ALPHA = alpha;
paint.setAlpha(alpha);
}
public int getStickAlpha() {
return STICK_ALPHA;
}
public void setLayoutAlpha(int alpha) {
LAYOUT_ALPHA = alpha;
mLayout.getBackground().setAlpha(alpha);
}
public int getLayoutAlpha() {
return LAYOUT_ALPHA;
}
public void setStickSize(int width, int height) {
stick = Bitmap.createScaledBitmap(stick, width, height, false);
stick_width = stick.getWidth();
stick_height = stick.getHeight();
}
public void setStickWidth(int width) {
stick = Bitmap.createScaledBitmap(stick, width, stick_height, false);
stick_width = stick.getWidth();
}
public void setStickHeight(int height) {
stick = Bitmap.createScaledBitmap(stick, stick_width, height, false);
stick_height = stick.getHeight();
}
public int getStickWidth() {
return stick_width;
}
public int getStickHeight() {
return stick_height;
}
public void setLayoutSize(int width, int height) {
params.width = width;
params.height = height;
}
public int getLayoutWidth() {
return params.width;
}
public int getLayoutHeight() {
return params.height;
}
private double cal_angle(float x, float y) {
if(x >= 0 && y >= 0)
return Math.toDegrees(Math.atan(y / x));
else if(x < 0 && y >= 0)
return Math.toDegrees(Math.atan(y / x)) + 180;
else if(x < 0 && y < 0)
return Math.toDegrees(Math.atan(y / x)) + 180;
else if(x >= 0 && y < 0)
return Math.toDegrees(Math.atan(y / x)) + 360;
return 0;
}
private void draw() {
try {
mLayout.removeView(draw);
} catch (Exception e) { }
mLayout.addView(draw);
}
private class DrawCanvas extends View{
float x, y;
private DrawCanvas(Context mContext) {
super(mContext);
}
public void onDraw(Canvas canvas) {
canvas.drawBitmap(stick, x, y, paint);
}
private void position(float pos_x, float pos_y) {
x = pos_x - (stick_width / 2);
y = pos_y - (stick_height / 2);
}
}
}
In your draw() method, you're locking the Canvas, but not unlocking the Canvas after you finish drawing. So, when you re-enter your draw method, the Canvas is still locked from the previous call.
You likely need to add unlockCanvasAndPost(Canvas canvas) after you finish drawing. See the full docs here.
Trying to make a motion detection app based on this project. The intention is to make the app take pictures when motion is detected by comparing two images. Up to this part, the app is working fine.
Requirement:
To specify area of detection by a custom view. So that, the pictures will be captured only if a motion is detected inside the defined area by calculating the detection area.
What I have done so far:
Created a movable custom view, like a crop view of which the dimensions (Rect) are saved in the preference each time when the view is moved.
What is not working:
The motion detection from inside the custom view is not working. I believe that the bitmaps must be cropped according to the size of the custom view to do the comparison.
In the detection thread I tried setting the width and height from the preference like :
private int width = Prefe.DetectionArea.width();
private int height = Prefe.DetectionArea.height();
But it didn't work. Please help me by explaining how this could be achieved so that the motion detection will happen according to the size of the custom view. Any help is appreciated.
Project Source Code: https://drive.google.com/drive/folders/0B7-oKqt7w49mbTR6VWZYVURmVms
MotionDetectionActivity.java
public class MotionDetectionActivity extends SensorsActivity {
private static final String TAG = "MotionDetectionActivity";
private static long mReferenceTime = 0;
private static IMotionDetection detector = null;
public static MediaPlayer song;
public static Vibrator mVibrator;
private static SurfaceView preview = null;
private static SurfaceHolder previewHolder = null;
private static Camera camera = null;
private static boolean inPreview = false;
private static AreaDetectorView mDetector;
private static FrameLayout layoutDetectorArea;
static FrameLayout layoutMain;
static View mView;
private static volatile AtomicBoolean processing = new AtomicBoolean(false);
/**
* {#inheritDoc}
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.main);
mVibrator = (Vibrator)this.getSystemService(VIBRATOR_SERVICE);
layoutMain=(FrameLayout)findViewById(R.id.layoutMain);
preview = (SurfaceView) findViewById(R.id.preview);
previewHolder = preview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mView=layoutMain;
mDetector= (AreaDetectorView) findViewById(R.id.viewDetector);
layoutDetectorArea=(FrameLayout) findViewById(R.id.layoutDetectArea);
ToggleButton toggle = (ToggleButton) findViewById(R.id.simpleToggleButton);
toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
// The toggle is enabled
} else {
// The toggle is disabled
}
}
});
if (Preferences.USE_RGB) {
detector = new RgbMotionDetection();
} else if (Preferences.USE_LUMA) {
detector = new LumaMotionDetection();
} else {
// Using State based (aggregate map)
detector = new AggregateLumaMotionDetection();
}
}
/**
* {#inheritDoc}
*/
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
/**dd:
* Song play # 1
* Camera callback
*
* {#inheritDoc}
*/
#Override
public void onPause() {
super.onPause();
if(song!=null && song.isPlaying())
{
song.stop();}
camera.setPreviewCallback(null);
if (inPreview) camera.stopPreview();
inPreview = false;
camera.release();
camera = null;
}
/**
* {#inheritDoc}
*/
#Override
public void onResume() {
super.onResume();
camera = Camera.open();
}
private PreviewCallback previewCallback = new PreviewCallback() {
/**
* {#inheritDoc}
*/
#Override
public void onPreviewFrame(byte[] data, Camera cam) {
if (data == null) return;
Camera.Size size = cam.getParameters().getPreviewSize();
if (size == null) return;
if (!GlobalData.isPhoneInMotion()) {
DetectionThread thread = new DetectionThread(data, size.width, size.height);
thread.start();
}
}
};
private SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {
/**
* {#inheritDoc}
*/
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera.setPreviewDisplay(previewHolder);
camera.setPreviewCallback(previewCallback);
} catch (Throwable t) {
Log.e("Prek", "Exception in setPreviewDisplay()", t);
}
}
/**
* {#inheritDoc}
*/
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if(camera != null) {
Camera.Parameters parameters = camera.getParameters();
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
Camera.Size size = getBestPreviewSize(width, height, parameters);
if (size != null) {
parameters.setPreviewSize(size.width, size.height);
Log.d(TAG, "Using width=" + size.width + " height=" + size.height);
}
camera.setParameters(parameters);
camera.startPreview();
inPreview = true;
}
//AreaDetectorView.InitDetectionArea();
}
/**
* {#inheritDoc}
*/
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// Ignore
}
};
private static Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters) {
Camera.Size result = null;
for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
if (size.width <= width && size.height <= height) {
if (result == null) {
result = size;
} else {
int resultArea = result.width * result.height;
int newArea = size.width * size.height;
if (newArea > resultArea) result = size;
}
}
}
return result;
}
//***************Detection Class******************//
private final class DetectionThread extends Thread {
private byte[] data;
private int width;
private int height;
public DetectionThread(byte[] data, int width, int height) {
this.data = data;
this.width = width;
this.height = height;
}
/**
* {#inheritDoc}
*/
#Override
public void run() {
if (!processing.compareAndSet(false, true)) return;
// Log.d(TAG, "BEGIN PROCESSING...");
try {
// Previous frame
int[] pre = null;
if (Preferences.SAVE_PREVIOUS) pre = detector.getPrevious();
// Current frame (with changes)
// long bConversion = System.currentTimeMillis();
int[] img = null;
if (Preferences.USE_RGB) {
img = ImageProcessing.decodeYUV420SPtoRGB(data, width, height);
} else {
img = ImageProcessing.decodeYUV420SPtoLuma(data, width, height);
}
// Current frame (without changes)
int[] org = null;
if (Preferences.SAVE_ORIGINAL && img != null) org = img.clone();
if (img != null && detector.detect(img, width, height)) {
// The delay is necessary to avoid taking a picture while in
// the
// middle of taking another. This problem can causes some
// phones
// to reboot.
long now = System.currentTimeMillis();
if (now > (mReferenceTime + Preferences.PICTURE_DELAY)) {
mReferenceTime = now;
//mVibrator.vibrate(10);
Bitmap previous = null;
if (Preferences.SAVE_PREVIOUS && pre != null) {
if (Preferences.USE_RGB) previous = ImageProcessing.rgbToBitmap(pre, width, height);
else previous = ImageProcessing.lumaToGreyscale(pre, width, height);
}
Bitmap original = null;
if (Preferences.SAVE_ORIGINAL && org != null) {
if (Preferences.USE_RGB) original = ImageProcessing.rgbToBitmap(org, width, height);
else original = ImageProcessing.lumaToGreyscale(org, width, height);
}
Bitmap bitmap = null;
if (Preferences.SAVE_CHANGES) {
if (Preferences.USE_RGB) bitmap = ImageProcessing.rgbToBitmap(img, width, height);
else bitmap = ImageProcessing.lumaToGreyscale(img, width, height);
}
Log.i(TAG, "Saving.. previous=" + previous + " original=" + original + " bitmap=" + bitmap);
Looper.prepare();
new SavePhotoTask().execute(previous, original, bitmap);
} else {
Log.i(TAG, "Not taking picture because not enough time has passed since the creation of the Surface");
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
processing.set(false);
}
// Log.d(TAG, "END PROCESSING...");
processing.set(false);
}
};
private static final class SavePhotoTask extends AsyncTask<Bitmap, Integer, Integer> {
/**
* {#inheritDoc}
*/
#Override
protected Integer doInBackground(Bitmap... data) {
for (int i = 0; i < data.length; i++) {
Bitmap bitmap = data[i];
String name = String.valueOf(System.currentTimeMillis());
if (bitmap != null) save(name, bitmap);
}
return 1;
}
private void save(String name, Bitmap bitmap) {
File photo = new File(Environment.getExternalStorageDirectory(), name + ".jpg");
if (photo.exists()) photo.delete();
try {
FileOutputStream fos = new FileOutputStream(photo.getPath());
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.close();
} catch (java.io.IOException e) {
Log.e("PictureDemo", "Exception in photoCallback", e);
}
}
}
}
AreaDetectorView.java
public class AreaDetectorView extends LinearLayout {
public static int Width;
public static int Height;
private static Paint BoxPaint = null;
private static Paint TextPaint = null;
private static Paint ArrowPaint = null;
private static Path mPath = null;
private static Rect mRect = null;
private static int lastX, lastY = 0;
private static boolean mBoxTouched = false;
private static boolean mArrowTouched = false;
private static Context mContext;
private static int ArrowWidth = 0;
private static Paint BoxPaint2 = null;
public AreaDetectorView(Context context) {
super(context);
mContext = context;
}
//attrs was not there
public AreaDetectorView(Context context, AttributeSet attrs) {
super(context,attrs);
mContext = context;
// TODO Auto-generated constructor stub
if (!this.getRootView().isInEditMode()) {
ArrowWidth =GetDisplayPixel(context, 30);
}
//InitDetectionArea();
InitMemberVariables();
setWillNotDraw(false);
}
public static int GetDisplayPixel(Context paramContext, int paramInt)
{
return (int)(paramInt * paramContext.getResources().getDisplayMetrics().density + 0.5F);
}
public static void InitMemberVariables() {
if (BoxPaint == null) {
BoxPaint = new Paint();
BoxPaint.setAntiAlias(true);
BoxPaint.setStrokeWidth(2.0f);
//BoxPaint.setStyle(Style.STROKE);
BoxPaint.setStyle(Style.FILL_AND_STROKE);
BoxPaint.setColor(ContextCompat.getColor(mContext, R.color.bwff_60));
}
if (ArrowPaint == null) {
ArrowPaint = new Paint();
ArrowPaint.setAntiAlias(true);
ArrowPaint.setColor(ContextCompat.getColor(mContext,R.color.redDD));
ArrowPaint.setStyle(Style.FILL_AND_STROKE);
}
if (TextPaint == null) {
TextPaint = new Paint();
TextPaint.setColor(ContextCompat.getColor(mContext,R.color.yellowL));
TextPaint.setTextSize(16);
//txtPaint.setTypeface(lcd);
TextPaint.setStyle(Style.FILL_AND_STROKE);
}
if (mPath == null) {
mPath = new Path();
} else {
mPath.reset();
}
if (mRect == null) {
mRect = new Rect();
}
if (BoxPaint2 == null) {
BoxPaint2 = new Paint();
BoxPaint2.setAntiAlias(true);
BoxPaint2.setStrokeWidth(2.0f);
//BoxPaint.setStyle(Style.STROKE);
BoxPaint2.setStyle(Style.STROKE);
BoxPaint2.setColor(ContextCompat.getColor(mContext,R.color.bwff_9e));
}
}
public static void InitDetectionArea() {
try {
int w = Prefe.DetectionArea.width();
int h = Prefe.DetectionArea.height();
int x = Prefe.DetectionArea.left;
int y = Prefe.DetectionArea.top;
// ver 2.6.0
if (Prefe.DetectionArea.left == 1
&& Prefe.DetectionArea.top == 1
&& Prefe.DetectionArea.right == 1
&& Prefe.DetectionArea.bottom == 1) {
w = Prefe.DisplayWidth / 4;
h = Prefe.DisplayHeight / 3;
// ver 2.5.9
w = Width / 4;
h = Height / 3;
Prefe.DetectorWidth = w; //UtilGeneralHelper.GetDisplayPixel(this, 100);
Prefe.DetectorHeight = h; //UtilGeneralHelper.GetDisplayPixel(this, 100);
x = (Prefe.DisplayWidth / 2) - (w / 2);
y = (Prefe.DisplayHeight / 2) - (h / 2);
// ver 2.5.9
x = (Width / 2) - (w / 2);
y = (Height / 2) - (h / 2);
}
//Prefe.DetectionArea = new Rect(x, x, x + Prefe.DetectorWidth, x + Prefe.DetectorHeight);
Prefe.DetectionArea = new Rect(x, y, x + w, y + h);
Prefe.gDetectionBitmapInt = new int[Prefe.DetectionArea.width() * Prefe.DetectionArea.height()];
Prefe.gDetectionBitmapIntPrev = new int[Prefe.DetectionArea.width() * Prefe.DetectionArea.height()];
} catch (Exception e) {
e.printStackTrace();
}
}
public static void SetDetectionArea(int x, int y, int w, int h) {
try {
Prefe.DetectionArea = new Rect(x, y, w, h);
} catch (Exception e) {
e.printStackTrace();
}
}
private void DrawAreaBox(Canvas canvas) {
try {
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void dispatchDraw(Canvas canvas) {
try {
if (this.getRootView().isInEditMode()) {
super.dispatchDraw(canvas);
return;
}
//canvas.save(Canvas.MATRIX_SAVE_FLAG);
//Prefe.DetectionAreaOrient = UtilGeneralHelper.GetDetectRectByOrientation();
canvas.drawColor(0);
mPath.reset();
canvas.drawRect(Prefe.DetectionArea, BoxPaint);
mPath.moveTo(Prefe.DetectionArea.right - ArrowWidth, Prefe.DetectionArea.bottom);
mPath.lineTo(Prefe.DetectionArea.right, Prefe.DetectionArea.bottom - ArrowWidth);
mPath.lineTo(Prefe.DetectionArea.right, Prefe.DetectionArea.bottom);
mPath.lineTo(Prefe.DetectionArea.right - ArrowWidth, Prefe.DetectionArea.bottom);
mPath.close();
canvas.drawPath(mPath, ArrowPaint);
mPath.reset();
//canvas.drawRect(Prefe.DetectionAreaOrient, BoxPaint2);
//canvas.drawRect(Prefe.DetectionAreaOrientPort, BoxPaint2);
TextPaint.setTextSize(16);
//TextPaint.setLetterSpacing(2);
TextPaint.setColor(ContextCompat.getColor(mContext,R.color.bwff));
TextPaint.getTextBounds(getResources().getString(R.string.str_detectarea), 0, 1, mRect);
canvas.drawText(getResources().getString(R.string.str_detectarea),
Prefe.DetectionArea.left + 4,
Prefe.DetectionArea.top + 4 + mRect.height(),
TextPaint);
int recH = mRect.height();
TextPaint.setStrokeWidth(1.2f);
TextPaint.setTextSize(18);
TextPaint.setColor(ContextCompat.getColor(mContext,R.color.redD_9e));
TextPaint.getTextBounds(getResources().getString(R.string.str_dragandmove), 0, 1, mRect);
canvas.drawText(getResources().getString(R.string.str_dragandmove),
Prefe.DetectionArea.left + 4,
Prefe.DetectionArea.top + 20 + mRect.height()*2,
TextPaint);
TextPaint.getTextBounds(getResources().getString(R.string.str_scalearea), 0, 1, mRect);
canvas.drawText(getResources().getString(R.string.str_scalearea),
Prefe.DetectionArea.left + 4,
Prefe.DetectionArea.top + 36 + mRect.height()*3,
TextPaint);
super.dispatchDraw(canvas);
//canvas.restore();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void onDraw(Canvas canvas) {
try {
super.onDraw(canvas);
invalidate();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
boolean retValue = true;
int X = (int)event.getX();
int Y = (int)event.getY();
//AppMain.txtLoc.setText(String.valueOf(X) + ", " + String.valueOf(Y));
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mBoxTouched = TouchedInBoxArea(X, Y);
//AppMain.txtLoc.setText("BoxTouched: " + String.valueOf(mBoxTouched));
if (!mBoxTouched) break;
lastX = X;
lastY = Y;
BoxPaint.setStyle(Style.FILL_AND_STROKE);
BoxPaint.setColor(ContextCompat.getColor(mContext,R.color.redD_9e));
mArrowTouched = TouchedInArrow(X, Y);
//AppMain.txtLoc.setText("ArrowTouched: " + String.valueOf(mBoxTouched));
if (mArrowTouched) {
ArrowPaint.setColor(ContextCompat.getColor(mContext,R.color.bwff_9e));
}
break;
case MotionEvent.ACTION_MOVE:
if (!mBoxTouched) break;
int moveX = X - lastX;
int moveY = Y - lastY;
//AppMain.txtLoc.setText("Move X, Y: " + String.valueOf(moveX) + "," + String.valueOf(moveY));
if (!mArrowTouched) {
if (Prefe.DetectionArea.left + moveX < 0) {
break;
}
// if (Prefe.DetectionArea.right + moveX > Prefe.gDisplay.getWidth()) {
// break;
// }
// ver 2.5.9
if (Prefe.DetectionArea.right + moveX > Width) {
break;
}
if (Prefe.DetectionArea.top + moveY < 0) {
break;
}
// if (Prefe.DetectionArea.bottom + moveY > Prefe.gDisplay.getHeight()) {
// break;
// }
// ver 2.5.9
if (Prefe.DetectionArea.bottom + moveY > Height) {
break;
}
}
if (mArrowTouched) {
if ((Prefe.DetectionArea.width() + moveX) < ArrowWidth * 2){
break;
}
if ((Prefe.DetectionArea.height() + moveY) < ArrowWidth * 2) {
break;
}
Prefe.DetectionArea.right += moveX;
Prefe.DetectionArea.bottom += moveY;
//Log.i("DBG", "W,H: " + String.valueOf(Prefe.DetectionArea.width()) + "," + String.valueOf(Prefe.DetectionArea.height()));
} else {
Prefe.DetectionArea.left += moveX;
Prefe.DetectionArea.right += moveX;
Prefe.DetectionArea.top += moveY;
Prefe.DetectionArea.bottom += moveY;
}
lastX = X;
lastY = Y;
//AppMain.txtLoc.setText(String.valueOf(Prefe.DetectionArea.left) + ", " + String.valueOf(Prefe.DetectionArea.top));
break;
case MotionEvent.ACTION_UP:
mBoxTouched = false;
mArrowTouched = false;
//BoxPaint.setStyle(Style.STROKE);
BoxPaint.setStyle(Style.FILL_AND_STROKE);
BoxPaint.setColor(ContextCompat.getColor(mContext,R.color.bwff_60));
ArrowPaint.setColor(ContextCompat.getColor(mContext,R.color.redDD));
//AppMain.txtLoc.setText(String.valueOf(Prefe.DetectionArea.left) + ", " + String.valueOf(Prefe.DetectionArea.top));
if (Prefe.DetectionArea.left < 0) {
Prefe.DetectionArea.left = 0;
}
// if (Prefe.DetectionArea.right > Prefe.gDisplay.getWidth()) {
// Prefe.DetectionArea.right = Prefe.gDisplay.getWidth();
// }
// ver 2.5.9
if (Prefe.DetectionArea.right > Width) {
Prefe.DetectionArea.right = Width;
}
if (Prefe.DetectionArea.top < 0) {
Prefe.DetectionArea.top = 0;
}
// if (Prefe.DetectionArea.bottom > Prefe.gDisplay.getHeight()) {
// Prefe.DetectionArea.bottom = Prefe.gDisplay.getHeight();
// }
if (Prefe.DetectionArea.bottom > Height) {
Prefe.DetectionArea.bottom = Height;
}
Prefe.gDetectionBitmapInt = new int[Prefe.DetectionArea.width() * Prefe.DetectionArea.height()];
Prefe.gDetectionBitmapIntPrev = new int[Prefe.DetectionArea.width() * Prefe.DetectionArea.height()];
//Prefe.gDetectionBitmapInt = null;
//Prefe.gDetectionBitmapIntPrev = null;
String area = String.valueOf(Prefe.DetectionArea.left)
+ "," + String.valueOf(Prefe.DetectionArea.top)
+ "," + String.valueOf(Prefe.DetectionArea.right)
+ "," + String.valueOf(Prefe.DetectionArea.bottom);
// UtilGeneralHelper.SavePreferenceSetting(Prefe.gContext, Prefe.PREF_DETECTION_AREA_KEY, area);
//Saving the value
SharedPrefsUtils.setStringPreference(mContext.getApplicationContext(), Prefe.PREF_DETECTION_AREA_KEY, area);
Log.v("TAG", SharedPrefsUtils.getStringPreference(mContext.getApplicationContext(),Prefe.PREF_DETECTION_AREA_KEY));
break;
}
invalidate();
return retValue;
}
private boolean TouchedInBoxArea(int x, int y) {
boolean retValue = false;
try {
if (x > Prefe.DetectionArea.left && x < Prefe.DetectionArea.right) {
if (y > Prefe.DetectionArea.top && y < Prefe.DetectionArea.bottom) {
retValue = true;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return retValue;
}
private boolean TouchedInArrow(int x, int y) {
boolean retValue = false;
try {
if (x > Prefe.DetectionArea.right - ArrowWidth && x < Prefe.DetectionArea.right) {
if (y > Prefe.DetectionArea.bottom - ArrowWidth && y < Prefe.DetectionArea.bottom) {
retValue = true;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return retValue;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
Width = width;
Height = height;
InitDetectionArea();
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
for (int i = 0; i < this.getChildCount()-1; i++){
(this.getChildAt(i)).layout(l, t, r, b);
}
if (changed) {
// check width height
if (r != Width || b != Height) {
// size does not match
}
}
}
}
Prefe.java
public class Prefe extends Application{
...
public static final String PREF_DETECTION_AREA_KEY = "pref_detection_area_key";
}
static{
...
DetectionArea = new Rect(1, 1, 1, 1);
}
}
How to create a component that can be dragged and resized in Java Swing?
Like "Text Tools" text box feature in MS Paint, highlighted by red border in image.
I only want drag and resize feature, not text formatting.
How can I implement this component using Java Swing?
In my quest to solve this problem, I found Piccolo2d ZUI library.
That's exactly, what I was looking for! However, it might not be best approach just to implement a "Draggable & Resizable Text Box", but I got it working in under an hour using Piccolo2d. So, I am posting the code here, if someone can find it useful.
Here is the screenshot of sample application!
I tried to make the code as describable as possible, so it's a bit long.
You'll require piccolo2d-core-XXX.jar & piccolo2d-extras-XXX.jar to run this code, that can be downloaded from Maven Central Repository. I used version 3.0 & didn't tested with any other version!
Custom Component Class
class PBox extends PNode {
private PCanvas canvas;
private Rectangle2D rectangle;
private Cursor moveCursor;
public PBox(PCanvas canvas) {
this(0, 0, 50, 50, canvas);
}
public PBox(double x, double y, double width, double height, PCanvas canvas) {
this.canvas = canvas;
rectangle = new Rectangle2D.Double();
moveCursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
addAnchors(x, y, width, height);
setBounds(x, y, width, height);
setInputEventListener();
}
private void addAnchors(double x, double y, double width, double height) {
addChild(new Anchor(SwingConstants.NORTH));
addChild(new Anchor(SwingConstants.NORTH_EAST));
addChild(new Anchor(SwingConstants.EAST));
addChild(new Anchor(SwingConstants.SOUTH_EAST));
addChild(new Anchor(SwingConstants.SOUTH));
addChild(new Anchor(SwingConstants.SOUTH_WEST));
addChild(new Anchor(SwingConstants.WEST));
addChild(new Anchor(SwingConstants.NORTH_WEST));
}
private void setInputEventListener() {
addInputEventListener(new PBasicInputEventHandler() {
#Override
public void mouseEntered(PInputEvent event) {
canvas.setCursor(moveCursor);
}
#Override
public void mouseExited(PInputEvent event) {
canvas.setCursor(Cursor.getDefaultCursor());
}
#Override
public void mouseDragged(PInputEvent event) {
PDimension delta = event.getDeltaRelativeTo(PBox.this);
translate(delta.width, delta.height);
event.setHandled(true);
}
});
}
#Override
protected void layoutChildren() {
Iterator iterator = getChildrenIterator();
int position = SwingConstants.NORTH;
while (iterator.hasNext()) {
PNode anchor = (PNode) iterator.next();
anchor.setBounds(getAnchorBounds(position));
++position;
}
}
private Rectangle2D getAnchorBounds(int position) {
double x = 0, y = 0;
Rectangle2D b = getBounds();
switch (position) {
case SwingConstants.NORTH:
x = b.getX()+b.getWidth()/2;
y = b.getY();
break;
case SwingConstants.NORTH_EAST:
x = b.getX()+b.getWidth();
y = b.getY();
break;
case SwingConstants.EAST:
x = b.getX()+b.getWidth();
y = b.getY()+b.getHeight()/2;
break;
case SwingConstants.SOUTH_EAST:
x = b.getX()+b.getWidth();
y = b.getY()+b.getHeight();
break;
case SwingConstants.SOUTH:
x = b.getX()+b.getWidth()/2;
y = b.getY()+b.getHeight();
break;
case SwingConstants.SOUTH_WEST:
x = b.getX();
y = b.getY()+b.getHeight();
break;
case SwingConstants.WEST:
x = b.getX();
y = b.getY()+b.getHeight()/2;
break;
case SwingConstants.NORTH_WEST:
x = b.getX();
y = b.getY();
break;
}
return new Rectangle2D.Double(x-2, y-2, 4, 4);
}
#Override
public boolean setBounds(double x, double y, double width, double height) {
if (super.setBounds(x, y, width, height)) {
rectangle.setFrame(x, y, width, height);
return true;
}
return false;
}
#Override
public boolean intersects(Rectangle2D localBounds) {
return rectangle.intersects(localBounds);
}
#Override
protected void paint(PPaintContext paintContext) {
Graphics2D g2 = paintContext.getGraphics();
g2.setPaint(Color.BLACK);
g2.setStroke(new BasicStroke(1.0f,
BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER,
1.0f, new float[]{4.0f}, 0));
g2.draw(rectangle);
}
class Anchor extends PNode {
private Rectangle2D point;
private Cursor resizeCursor;
Anchor(int position) {
point = new Rectangle2D.Double();
setCursor(position);
setInputEventListener(position);
}
private void setCursor(int position) {
switch (position) {
case SwingConstants.NORTH:
resizeCursor = Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR);
break;
case SwingConstants.NORTH_EAST:
resizeCursor = Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR);
break;
case SwingConstants.EAST:
resizeCursor = Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR);
break;
case SwingConstants.SOUTH_EAST:
resizeCursor = Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR);
break;
case SwingConstants.SOUTH:
resizeCursor = Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR);
break;
case SwingConstants.SOUTH_WEST:
resizeCursor = Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR);
break;
case SwingConstants.WEST:
resizeCursor = Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR);
break;
case SwingConstants.NORTH_WEST:
resizeCursor = Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR);
break;
default:
resizeCursor = Cursor.getDefaultCursor();
}
}
private void setInputEventListener(final int position) {
addInputEventListener(new PBasicInputEventHandler() {
#Override
public void mouseEntered(PInputEvent event) {
canvas.setCursor(resizeCursor);
event.setHandled(true);
}
#Override
public void mouseExited(PInputEvent event) {
canvas.setCursor(Cursor.getDefaultCursor());
event.setHandled(true);
}
#Override
public void mouseDragged(PInputEvent event) {
PDimension delta = event.getDeltaRelativeTo(Anchor.this);
PNode parent = getParent();
if (position == SwingConstants.EAST
|| position == SwingConstants.NORTH_EAST
|| position == SwingConstants.SOUTH_EAST) {
parent.setWidth(parent.getWidth() + delta.width);
} else if (position == SwingConstants.WEST
|| position == SwingConstants.NORTH_WEST
|| position == SwingConstants.SOUTH_WEST) {
parent.setX(parent.getX() + delta.width);
parent.setWidth(parent.getWidth() - delta.width);
}
if (position == SwingConstants.SOUTH
|| position == SwingConstants.SOUTH_EAST
|| position == SwingConstants.SOUTH_WEST) {
parent.setHeight(parent.getHeight() + delta.height);
} else if (position == SwingConstants.NORTH
|| position == SwingConstants.NORTH_EAST
|| position == SwingConstants.NORTH_WEST) {
parent.setY(parent.getY() + delta.height);
parent.setHeight(parent.getHeight() - delta.height);
}
event.setHandled(true);
}
});
}
#Override
public boolean setBounds(double x, double y, double width, double height) {
if (super.setBounds(x, y, width, height)) {
point.setFrame(x, y, width, height);
return true;
}
return false;
}
#Override
public boolean intersects(Rectangle2D localBounds) {
return point.intersects(localBounds);
}
#Override
protected void paint(PPaintContext paintContext) {
Graphics2D g2 = paintContext.getGraphics();
g2.setColor(Color.WHITE);
g2.fill(point);
g2.setStroke(new BasicStroke(1.0f));
g2.setColor(Color.BLACK);
g2.draw(point);
}
}
}
And, the main class
public class Piccolo2DExample extends PFrame {
#Override
public void initialize() {
PCanvas canvas = getCanvas();
PNode text = new PText("Draggable & Resizable Box using Piccolo2d");
text.scale(2.0);
canvas.getCamera().addChild(text);
PLayer layer = canvas.getLayer();
PNode aLayerNode = new PText("A_Layer_Node");
aLayerNode.setOffset(10, 50);
layer.addChild(aLayerNode);
// Adding the component to layer
layer.addChild(new PBox(50, 100, 250, 50, canvas));
}
public static void main(String[] args) {
PFrame frame = new Piccolo2DExample();
frame.setSize(800, 640);
}
}
2 part question here. I'm having some trouble here with my for loops. The basic idea of my code is that whenever checkX and checkY are called they compare the x of the touch and the x of the player then if the players x is less than the touchx then it increments the player x by 1 until the player x equals touch x. Its the exact same thing for checky. Everything works fine, the problem is that it never stops. The player just keeps moving on the exact same path.
Heres the player class
package com.gametest;
import java.util.concurrent.CopyOnWriteArrayList;
import com.gametest.GameSurfaceView.MyView;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
public class Player {
int ID;
static int x, y, width, height, widthEnd, currentFrame, boundsX, boundsY,
dirTimer, dir, simx, simy;
static Bitmap currentSprite, playerSprite, deathSprite;
static MyView mv;
public Player(MyView v, Bitmap orb, Bitmap explosion, int screenWidth,
int screenHeight) {
// TODO Auto-generated constructor stub
playerSprite = orb;
deathSprite = explosion;
currentSprite = playerSprite;
mv = v;
height = playerSprite.getHeight();
width = playerSprite.getWidth() / 3;
currentFrame = 1;
}
public static void sprite_draw(Canvas canvas,
CopyOnWriteArrayList<Sprite> copy) {
// TODO Auto-generated method stub
x = (mv.getWidth() / 2) - 50;
y = (mv.getHeight() / 2) - 50;
currentFrame = currentFrame + 1;
if (currentFrame > 3) {
currentFrame = 1;
}
widthEnd = (currentFrame * width) + width;
boundsX = x + width;
boundsY = y + height;
Rect src = new Rect(currentFrame * width, 0, widthEnd, height);
Rect dst = new Rect(x, y, boundsX, boundsY);
canvas.drawBitmap(currentSprite, src, dst, null);
for (Sprite s : copy) {
if (s.x + 50 > x && s.x + 50 < boundsX && s.y + 50 > y
&& s.y + 50 < boundsY) {
GameSurfaceView.damagePlayer();
};
}
}
public void checkX(Integer touchx) {
if (touchx > x) {
for (int newx = x; newx < touchx; newx++) {
GameSurfaceView.setDirection(1, 0);
try {
mv.t.sleep (10);
} catch (InterruptedException e) {
}
}
}
if (touchx < x ) {
for (int newx = x; newx > touchx; newx--) {
GameSurfaceView.setDirection(-1, 0);
try {
mv.t.sleep (10);
} catch (InterruptedException e) {
}
}
}
}
public void checkY(int touchy) {
if (touchy > y) {
for (int newy = y; newy < touchy; newy++) {
GameSurfaceView.setDirection(0, 1);
try {
mv.t.sleep (10);
} catch (InterruptedException e) {
}
}
}
if (touchy < y) {
for (int newy = y; newy > touchy; newy--) {
GameSurfaceView.setDirection(0, -1);
try {
mv.t.sleep (10);
} catch (InterruptedException e) {
}
}
}
}
}
And in case its needed here is the surface view class
package com.gametest;
import java.util.concurrent.CopyOnWriteArrayList;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
public class GameSurfaceView extends Activity implements OnTouchListener {
double ran;
int touchX, touchY, screenWidth, screenHeight, objX, objY;
static boolean canUpdate;
static int enemyCount, score, playerHealth, test1, test2;
static MyView v;
static Bitmap orb, orb2, explosion;
static CopyOnWriteArrayList<Sprite> copy = new CopyOnWriteArrayList<Sprite>();
static String hpString;
static Player player;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
v = new MyView(this);
v.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent me) {
touchX = (int) me.getX();
touchY = (int) me.getY();
for (Sprite sprite : copy) {
sprite.checkTouch(touchX, touchY);
player.checkY(touchY);
player.checkX(touchX);
}
return true;
}
});
canUpdate = true;
screenWidth = v.getWidth();
screenHeight = v.getHeight();
playerHealth = 250;
hpString = "Health " + playerHealth;
ran = 0;
score = 0;
test1 = 5000;
test2 = 5000;
orb = BitmapFactory.decodeResource(getResources(), R.drawable.blue_orb);
orb2 = BitmapFactory.decodeResource(getResources(), R.drawable.red_orb);
explosion = BitmapFactory.decodeResource(getResources(), R.drawable.explosion);
player = new Player(v, orb2, explosion, screenWidth, screenHeight);
createEnemies();
setContentView(v);
}
private void createEnemies() {
if (enemyCount < 5) {
screenWidth = v.getWidth();
screenHeight = v.getHeight();
int listLength = copy.size();
copy.add(new Sprite(v, orb, explosion, screenWidth, screenHeight, listLength));
enemyCount = enemyCount + 1;
}
}
public static void checkECount(int id) {
canUpdate = false;
copy.remove(id);
enemyCount = enemyCount - 1;
int index = 0;
for(Sprite s : copy) {
s.ID = index;
index++;
}
score = score + 10;
canUpdate = true;
}
#Override
protected void onPause() {
super.onPause();
v.pause();
}
#Override
protected void onResume() {
super.onResume();
v.resume();
}
public class MyView extends SurfaceView implements Runnable {
Thread t = null;
SurfaceHolder holder;
boolean isItOk = false;
public MyView(Context context) {
super(context);
holder = getHolder();
}
#Override
public void run() {
while (isItOk == true) {
if (!holder.getSurface().isValid()) {
continue;
}
Canvas c = holder.lockCanvas();
if(canUpdate){
canvas_draw(c);
}
holder.unlockCanvasAndPost(c);
try {
t.sleep (50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
protected void canvas_draw(Canvas canvas) {
canvas.drawARGB(255, 50, 10, 10);
String ranString = "Score " + score;
ran = Math.random() * 5;
String t = "max1" + test1;
String t2 = "max2" + test2;
if (ran > 3) {
createEnemies();
}
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize(15);
canvas.drawText(hpString, 10, 25, paint);
canvas.drawText(ranString, 10, screenHeight - 25, paint);
for (Sprite sprite : copy) {
sprite.sprite_draw(canvas);
}
Player.sprite_draw(canvas, copy);
}
public void pause() {
isItOk = false;
while (true) {
try {
t.join();
} catch (InterruptedException e) {
}
break;
}
t = null;
}
public void resume() {
isItOk = true;
t = new Thread(this);
t.start();
}
}
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
return false;
}
public static void damagePlayer() {
hpString = "Health " + playerHealth;
playerHealth = playerHealth - 5;
if(playerHealth<0){
hpString = "game over";
}
}
public static void setDirection(int i, int j) {
if(i == 0 && j == -1){
for(Sprite s: copy){
s.y++;
}
}
if(i == 0 && j == 1){
for(Sprite s: copy){
s.y--;
}
}
if(i == -1 && j == 0){
for(Sprite s: copy){
s.x++;
}
}
if(i == 1 && j == 0){
for(Sprite s: copy){
s.x--;
}
}
}
}
So the first part of my question is can anyone tell me why the for loops wont stop looping. And the second part of my question is how can I force the checkX and checkY methods to restart if the player selects a different point before he makes it to the first location.
Check and see if your problem lies with your signature in your checkX and checkY functions. Integer is a class, and int is a primitive type, so you can't do something like Integer n = 1, but you can do int n = 1.
public void checkX(int touchx)
public void checkY(int touchx)