I have a Custom View which draws lines an saves them to an ArrayList. What I want to be able to do is check if a specified point is on a line inside the Arraylist and return the line. I have been able to do this when the line is straight by using if (l.startX == l.stopX && l.startY < l.stopY but this doesn't work if the line is on an angle. I would also like to do this with drawText and drawCircle. Is there some simple way of doing this that I have missed?
DrawView.java
class Line {
float startX, startY, stopX, stopY;
public Line(float startX, float startY, float stopX, float stopY) {
this.startX = startX;
this.startY = startY;
this.stopX = stopX;
this.stopY = stopY;
}
public Line(float startX, float startY) { // for convenience
this(startX, startY, startX, startY);
}
}
public class DrawView extends View {
Paint paint = new Paint();
ArrayList<Line> lines = new ArrayList<Line>();
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setAntiAlias(true);
paint.setStrokeWidth(6f);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
}
#Override
protected void onDraw(Canvas canvas) {
for (Line l : lines) {
canvas.drawLine(l.startX, l.startY, l.stopX, l.stopY, paint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
lines.add(new Line(event.getX(), event.getY()));
return true;
}
else if ((event.getAction() == MotionEvent.ACTION_MOVE ||
event.getAction() == MotionEvent.ACTION_UP) &&
lines.size() > 0) {
Line current = lines.get(lines.size() - 1);
current.stopX = event.getX();
current.stopY = event.getY();
Invalidate();
return true;
}
else {
return false;
}
}
}
I don't know if there is a canvas library for this but manually you can:
go through your list of lines
form equations for each line in let's say slope-intercept form y = mx + b
plugin in the event.X() and event.Y() into the above equation as x and y for each line
if the 2 sides are equal then your touch event is on that line
After many hours of trying I managed to come up with a an algorithm to check if a point is on a given line using a mixture of slope-intersect formula and if (x = startX && y > startY && y < stopY) Below is the code, it returns true if point is on line otherwise false, hopefully this can save someone time!
public boolean checkPosition(float x, float y, float sx, float sy, float ex, float ey) {
float mX = ex - sx;
float mY = ey - sy;
float smX = sx - ex;
float smY = sy - ey;
float pmX = mX;
float pmY = mY;
float psmX = smX;
float psmY = smY;
float yY = ey - y;
float xX = ex - x;
float sX = sx - x;
float sY = sy - y;
float m = mY / mX;
float b = sy - (m * sx);
if (mX < 0) {
pmX = mX * - 1;
}
if (mY < 0) {
pmY = mY * - 1;
}
if (smX < 0) {
psmX = smX * - 1;
}
if (smY < 0) {
psmY = smY * - 1;
}
if (yY < 0) {
yY = yY * - 1;
}
if (xX < 0) {
xX = xX * - 1;
}
if (sX < 0) {
sX = sX * - 1;
}
if (sY < 0) {
sY = sY * - 1;
}
if (sy == ey && y == sy) {
if (sx >= ex) {
if (x <= sx && x >= ex) return true;
else return false;
}
else if (ex >= sx) {
if (x <= ex && x >= sx) return true;
else return false;
}
else return false;
}
else if (sx == ex && x == sx) {
if (sy >= ey) {
if (y <= sy && y >= ey) return true;
else return false;
}
else if (ey >= sy) {
if (y <= ey && y >= sy) return true;
else return false;
}
else return false;
}
else if (xX <= pmX && sX <= psmX && yY <= pmY && sY <= psmY) {
if (y == (m * x) + b) return true;
else return false;
}
else return false;
}
Related
I have a problem.
How do I check if path in Android intersect with itself?
I have this class:
public class GameView extends SurfaceView implements Runnable {
Thread gameThread = null;
SurfaceHolder surfaceHolder;
volatile boolean playing;
Canvas canvas;
private final static int MAX_FPS = 60;
private final static int FRAME_PERIOD = 1000 / MAX_FPS;
ArrayList<Point> points = new ArrayList<>();
private Context ctx;
Path path;
public static final int DEFAULT_COLOR = Color.RED;
public static final int DEFAULT_BG_COLOR = Color.WHITE;
private static final float TOUCH_TOLERANCE = 4;
private float mX, mY;
private Path mPath;
private Paint mPaint;
private int backgroundColor = DEFAULT_BG_COLOR;
public GameView(Context context) {
super(context);
ctx = context;
surfaceHolder = getHolder();
surfaceHolder.setFormat(PixelFormat.RGBA_8888);
path = new Path();
playing = true;
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(DEFAULT_COLOR);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setXfermode(null);
mPaint.setAlpha(0xff);
mPaint.setStrokeWidth(12);
}
static Boolean isPathComplex(List<Point> path) {
if (path == null || path.size() <= 2) {
return false;
}
int len = path.size();
for (int i = 1; i < len; i++) {
Point lineAStart = path.get(i - 1);
Point lineAEnd = path.get(i);
for (int j = i + 1; j < len; j++) {
Point lineBStart = path.get(j - 1);
Point lineBEnd = path.get(j);
if (lineSegmentsIntersect(lineAStart.x,lineAStart.y,
lineAEnd.x,lineAEnd.y,
lineBStart.x,lineBStart.y,
lineBEnd.x,lineBEnd.y)) {
return true;
}
} // inner loop
} // outer loop
return false;
}
static Boolean lineSegmentsIntersect(float p0_x, float p0_y, float p1_x, float p1_y,
float p2_x, float p2_y, float p3_x, float p3_y) {
float s1_x, s1_y, s2_x, s2_y;
s1_x = p1_x - p0_x; s1_y = p1_y - p0_y;
s2_x = p3_x - p2_x; s2_y = p3_y - p2_y;
float s, t;
s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);
t = ( s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);
if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
{
// Collision detected
return true;
}
return false; // No collision
}
public void update(){
isPathComplex(points);
}
public void draw(){
if(surfaceHolder.getSurface().isValid()){
canvas = surfaceHolder.lockCanvas();
if(canvas != null) {
canvas.drawColor(backgroundColor);
if (mPath != null) {
canvas.drawPath(mPath, mPaint);
}
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
#Override
public void run() {
while(playing){
long started = System.currentTimeMillis();
float deltaTime = (System.currentTimeMillis() - started);
int sleepTime = (int) (FRAME_PERIOD - deltaTime);
update();
draw();
if (sleepTime > 0) {
try {
Thread.sleep(sleepTime);
}
catch (InterruptedException e) {
}
}
while (sleepTime < 0) {
update();
draw();
sleepTime += FRAME_PERIOD;
}
}
}
private void touchStart(float x, float y) {
mPath = new Path();
points.add(new Point((int)x,(int)y));
mPath.reset();
mPath.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);
points.add(new Point((int)x,(int)y));
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touchUp() {
mPath.lineTo(mX, mY);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN :
touchStart(x, y);
break;
case MotionEvent.ACTION_MOVE :
touchMove(x, y);
break;
case MotionEvent.ACTION_UP :
touchUp();
break;
}
return true;
}
public void pause() {
playing = false;
try {
gameThread.join();
} catch (InterruptedException e) {
Log.e("Error:", "joining thread");
}
}
public void resume(Context context) {
playing = true;
gameThread = new Thread(this);
gameThread.start();
}
}
Please do you know some solution for this problem?
I tried a lot but nothing helped me with my problem.
What I want to achieve is to detect intersect like this
I tried solution with points from Check android.graphics.path intersection with itself but it seems not to be working for me.
I could also be doing something wrong because i am newbie to android development and programming in general :) .
Thank you in advance!
Edit:
To detect intersect i followed above solution and modified this function https://stackoverflow.com/a/1968345/9339525 but It returns almost all the time true even if path is not crossing itself.
All code for detect intersection:
static Boolean isPathComplex(List<Point> path) {
if (path == null || path.size() <= 2) {
return false;
}
int len = path.size();
for (int i = 1; i < len; i++) {
Point lineAStart = path.get(i - 1);
Point lineAEnd = path.get(i);
for (int j = i + 1; j < len; j++) {
Point lineBStart = path.get(j - 1);
Point lineBEnd = path.get(j);
if (lineSegmentsIntersect(lineAStart.x,lineAStart.y,
lineAEnd.x,lineAEnd.y,
lineBStart.x,lineBStart.y,
lineBEnd.x,lineBEnd.y)) {
return true;
}
} // inner loop
} // outer loop
return false;
}
static Boolean lineSegmentsIntersect(float p0_x, float p0_y, float p1_x, float p1_y,
float p2_x, float p2_y, float p3_x, float p3_y) {
float s1_x, s1_y, s2_x, s2_y;
s1_x = p1_x - p0_x; s1_y = p1_y - p0_y;
s2_x = p3_x - p2_x; s2_y = p3_y - p2_y;
float s, t;
s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);
t = ( s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);
if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {
// Collision detected
return true;
}
return false; // No collision
}
Edit:
I modified my class GameView and added method to detect intersection.
I could not stand that is was that difficult so i switched on the computer and coded something.
I tried only a few values and dont know what happens if begin-end points of segments coincide.
Please try out.
static boolean lineSegmentsDoIntersect(
float Ax, float Ay
, float Bx, float By
, float Cx, float Cy
, float Dx, float Dy) {
// two line segments: AB and CD
// segment AB intersects segment CD
// if A and B on different sides of line through C and D
// AND C and D on different sides of line through A and B
// note the difference between line and segment!
if ( ! pointsOnDifferentSidesOfLineThrough(Ax, Ay, Bx, By, Cx, Cy, Dx, Dy) )
return false;
if ( ! pointsOnDifferentSidesOfLineThrough(Cx, Cy, Dx, Dy, Ax, Ay, Bx, By) )
return false;
return true;
}
static boolean pointsOnDifferentSidesOfLineThrough(
float Ax, float Ay
, float Bx, float By
, float x1, float y1
, float x2, float y2) {
// determine equation of line through C and D
// y = ax + b
// a = (y2-y1)/(x2-x1) but.. ( x2-x1) not equal to zero
// y-y1 = a (x-x1)
// y = a (x-x1) + y1
// y = ax -ax1 + y1
// b = -ax1 + y1
//but.. (x2-x1) not 0
if ( x2==x1)
{
if ( Ax > x1 && Bx > x1 )
return false;
if ( Ax < x1 && Bx < x1 )
return false;
return true;
}
float a = (y2-y1)/(x2-x1);
float b = -a * x1 + y1;
float yA = a * Ax + b;
float yB = a * Bx + b;
if ( yA > Ay && yB > By )
return false;
if ( yA < Ay && yB < By )
return false;
return true;
}
I am working on a simple 2D infinite runner game. I am trying to get the player to move in any direction without needing to touch the player specifically. I want the game to find where the user touches and then allow the user to control the player from there. At the moment the player moves but only when the user is touching the player directly which makes it difficult for the user to see the actual player when playing and trying to dodge obstacles.
Here is the code I currently have:
public boolean recieveTouch(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
int action = event.getAction();
int x = (int) event.getX(); // or getRawX();
int y = (int) event.getY();
int h2 = bitmap2.getHeight();
int w2 = bitmap2.getWidth();
float xRatio2 = (Constants.SCREEN_WIDTH / 2)-( w2 / 2);
float yRatio2 = (Constants.SCREEN_HEIGHT / 2)-( h2 / 2) + (Constants.SCREEN_WIDTH/4 + (Constants.SCREEN_WIDTH/6)- Constants.SCREEN_HEIGHT/10);
int h55 = bitmap55.getHeight();
int w55 = bitmap55.getWidth();
int h66 = bitmap66.getHeight();
int w66 = bitmap66.getWidth();
float xRatio55 = ((Constants.SCREEN_WIDTH / 4)-( w55 / 4));
float yRatio55 = (((Constants.SCREEN_HEIGHT / 2) + (h55 / 2)) + (Constants.SCREEN_HEIGHT/6));
float xRatio66 = ((Constants.SCREEN_WIDTH / 2)+( w66 / 4) + (Constants.SCREEN_HEIGHT/24));
float yRatio66 = (((Constants.SCREEN_HEIGHT / 2) + (h66 / 2)) + (Constants.SCREEN_HEIGHT/6));
//help
int h5 = bitmap4.getHeight();
int w5 = bitmap4.getWidth();
float xRatio5 = ((Constants.SCREEN_WIDTH / 4) - (w5 / 1));
float yRatio5 = (((Constants.SCREEN_HEIGHT / 8) - (h5 / 1)));
long pressTime = System.currentTimeMillis();
if (!gameOver && player.getRectangle().contains((int) event.getX(), (int) event.getY()))
movingPlayer = true;
if (gameOver && System.currentTimeMillis() - gameOverTime >= 0) {
if (x >= xRatio2 && x < (xRatio2 + bitmap2.getWidth())
&& y >= yRatio2 && y < (yRatio2 + bitmap2.getHeight())) {
if (GamePanel.Ad1 == 1) {
MainActivity.click.start();
MainActivity.mAd = MobileAds.getRewardedVideoAdInstance(mActivityRef.get());
loadAd();
MainActivity.mAd.show();
//Appodeal.show(mActivityRef.get(), Appodeal.REWARDED_VIDEO);
}
}
if (x >= xRatio55 && x < (xRatio55 + bitmap55.getWidth())
&& y >= yRatio55 && y < (yRatio55 + bitmap55.getHeight())) {
MainActivity.click.start();
reset();
gameOver = false;
orientationData.newGame();
}
if (x >= xRatio66 && x < (xRatio66 + bitmap66.getWidth())
&& y >= yRatio66 && y < (yRatio66 + bitmap66.getHeight())) {
MainActivity.click.start();
SceneManager.ACTIVE_SCENE = 4;
MainActivity.mInterstitialAd.loadAd((new AdRequest.Builder().build()));
MainActivity.mInterstitialAd.show();
//Appodeal.show(mActivityRef.get(), Appodeal.INTERSTITIAL);
if (GamePanel.YelowBird == 4) {
GamePanel.YelowBird = 2;
GamePanel.RedBird = 1;
}
reset();
gameOver = false;
}
if (x >= xRatio5 && x < (xRatio5 + bitmap4.getWidth())
&& y >= yRatio5 && y < (yRatio5 + bitmap4.getHeight())) {
if (GamePanel.Help == 0) {
GamePanel.Help = 1;
if (GamePanel.Help == 1) {
MainActivity.click.start();
orientationData.register();
}
} else if (GamePanel.Help == 1) {
GamePanel.Help = 0;
if (GamePanel.Help == 0) {
MainActivity.click.start();
orientationData.pause();
}
}
} return true;
}
break;
case MotionEvent.ACTION_MOVE:
if (GamePanel.NinjaBird == 4) {
if (!gameOver)
playerPoint.set((int) event.getX(), (int) event.getY());
} else {
if (!gameOver && movingPlayer)
playerPoint.set((int) event.getX(), (int) event.getY());
}
break;
case MotionEvent.ACTION_UP:
movingPlayer = false;
break;
}
return false;
}
if anyone else wants to do a similar thing:
i changed the following line
from this:
if (!gameOver && movingPlayer)
playerPoint.set((int) event.getX(), (int) event.getY());
to this:
if (!gameOver && movingPlayer)
playerPoint.set((int) event.getX(), (int) event.getY()+200);
so you move the player by touching 200 pixels under it.
I need help with trying to make the circle in this program continuously follow my mouse's x and y coordinates.It does follow my mouse in certain points. I think this is due to the fact that i am using the slope between the two coordinates in my program. An example of the issue would be that it will go in the exact opposite direction and move away from my mouse if I am to the right of its x position. Can someone give me some guidance?
The ObjectMove class.
import java.awt.*;
import hsa.LASSConsole;
public class ObjectMove
{
static LASSConsole c; // The output console
public static void main (String[] args) throws java.lang.InterruptedException
{
c = new LASSConsole ();
double xcoord = c.maxx () / 2;
double ycoord = c.maxy () / 2;
double mouseX;
double mouseY;
double vely;
double velx;
double m;
int d = 20;
while (true)
{
mouseX = c.GetMouseX ();
mouseY = c.GetMouseY ();
m = ((mouseY - ycoord) / (mouseX - xcoord));
if (((mouseX - xcoord) / -1) == (mouseX - xcoord) / (mouseX - xcoord))
{
velx = -1;
}
else
{
velx = 1;
}
if (((mouseY - ycoord) / -1) == (mouseY - ycoord) / (mouseY - ycoord) && velx == -1)
{
vely = -m;
}
else if ((((mouseY - ycoord) / -1) == (mouseY - ycoord) / (mouseY - ycoord)) && velx == 1)
{
vely = m;
}
else if ((((mouseY - ycoord) / -1) != (mouseY - ycoord) / (mouseY - ycoord)) && velx == -1)
{
vely = -m;
}
else if (mouseX - xcoord == 0)
{
if (mouseY > ycoord)
{
vely = 1;
velx = 0;
}
else
{
vely = -1;
}
}
else
{
vely = m;
}
c.setColor (Color.black);
xcoord = xcoord - velx;
ycoord = ycoord - vely;
c.fillOval ((int) xcoord, (int) ycoord, (int) d, (int) d);
Thread.sleep (100);
c.setColor (Color.white);
c.fillOval ((int) xcoord, (int) ycoord, (int) d, (int) d);
}
} // main method
} // ObjectMove class
`
I am getting the error as
android.view.InflateException: Binary XML file line #16: Error inflating class DrawView
. I am creating customize view in DrawView class. In Oncreate method while calling setContentView(R.layout.newimage_activity); it will show me above error.
XML layout is:
<com.capricorn.RayMenu
android:id="#+id/ray_menu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="5dp"
android:paddingRight="5dp" />
<com.element45.android.camera.activities.DrawView
android:id="#+id/CustomView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
tools:context="com.element45.android.camera.activities.newImage_Activity"
/>
And DrawView Class code is:
public class DrawView extends View {
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
private Paint mPaint;
private RectF rectF ;
private Region Region1;
private Region Region2;
private List<Point> mPoints;
private List<Line> mLines;
private boolean bModify_line;
private float mX, mY;
private float mOriginal_X, mOriginal_Y;
private Line mLine ;
private static final float TOUCH_TOLERANCE = 50;
public DrawView(Context c)
{
super(c);
rectF = new RectF();
mPath = new Path();
mPath.computeBounds(rectF, true);
mPaint = new Paint();
mPaint.setColor(Color.WHITE);
mPaint.setAntiAlias(true);
mPaint.setXfermode(null);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5);
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mPoints = new ArrayList<Point>();
mLines = new ArrayList<Line>();
bModify_line = false;
}
int width,height;
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w ; height =h;
}
#Override
protected void onDraw(Canvas canvas)
{
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
canvas.drawColor(0xFFAAAAAA);//original color 0xFFAAAAAA
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
for(int i = 0 ; i < mLines.size();i++)
{
Line line = mLines.get(i);
mCanvas.drawLine(line.getStartPoint().x, line.getStartPoint().y, line.getEndPoint().x, line.getEndPoint().y, mPaint);
}
}
private void touch_move(float x, float y)
{
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE)
{
mX = x;
mY = y;
}
}
private void touch_start(float x, float y)
{
int iLineNumber = checkPointinLines(x, y);
if(iLineNumber >= 0 )
{
bModify_line = true;
mPath.moveTo(x, y);
mX = x;
mY = y;
}
else
{
mLine = new Line();
mLine.setStartPoint(new Point((int)x, (int)y));
mPath.moveTo(x, y);
mX = x;
mY = y;
}
mOriginal_X = mX;
mOriginal_Y = mY;
}
private void touch_up()
{
if(bModify_line)
{
int iLineNumber = checkPointinLines(mOriginal_X, mOriginal_Y);
if(iLineNumber > -1)
{
Line line = mLines.get(iLineNumber);
int iPoint = checkPointOnLine(mX,mY,line);
if(iPoint >= 0)
{
if(iPoint == 0)
{
mPath.moveTo(line.getEndPoint().x, line.getEndPoint().y);
line.setStartPoint(new Point((int)mX, (int)mY));
}
else if(iPoint == 1)
{
mPath.moveTo(line.getStartPoint().x, line.getStartPoint().y);
line.setEndPoint(new Point((int)mX, (int)mY));
}
mLines.set(iLineNumber, line);
System.out.println("After setline size of lineArray::"+mLines.size());
bModify_line = false;
}
}
}
else
{
mPath.lineTo(mX, mY);
mLine.setEndPoint(new Point((int)mX, (int)mY));
mLines.add(mLine);
mPath.reset();
}
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
float x = event.getX();
float y = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
/**
* Checks if user touch point with some tolerance
*/
private int checkPointOnLine(float x, float y,Line line)
{
int iPoint = -1;
Point point = line.getStartPoint();
if(x > (point.x - TOUCH_TOLERANCE) && x < (point.x + TOUCH_TOLERANCE) && y > (point.y - TOUCH_TOLERANCE) && y < (point.y + TOUCH_TOLERANCE) )
iPoint = 0;
point = line.getEndPoint();
if (x > (point.x - TOUCH_TOLERANCE) && x < (point.x + TOUCH_TOLERANCE) && (y > (point.y - TOUCH_TOLERANCE) && y < (point.y + TOUCH_TOLERANCE) ))
iPoint = 1 ;
return iPoint;
}
private int checkPointinLines(float x, float y)
{
int iLine = -1;
for(int i=0 ;i < mLines.size();i++)
{
Line line = mLines.get(i);
if(x > (line.getStartPoint().x - TOUCH_TOLERANCE)
&& x < (line.getStartPoint().x + TOUCH_TOLERANCE)
&& y > (line.getStartPoint().y - TOUCH_TOLERANCE)
&& y < (line.getStartPoint().y + TOUCH_TOLERANCE)
||
x > (line.getEndPoint().x - TOUCH_TOLERANCE)
&& x < (line.getEndPoint().x + TOUCH_TOLERANCE)
&& y > (line.getEndPoint().y - TOUCH_TOLERANCE)
&& y < (line.getEndPoint().y + TOUCH_TOLERANCE))
iLine = i;
}
return iLine;
}
public void movePoint(int position)
{
switch(position)
{
case 0:
//up
movePointUp();
break;
case 1:
//Right
movePointRight();
break;
case 2:
//Down
movePointDown();
break;
case 3:
//Left
movePointLeft();
break;
}
}
private void movePointUp()
{
if(bModify_line)
{
int iLineNumber = checkPointinLines(mOriginal_X, mOriginal_Y);
if(iLineNumber > -1)
{
Line line = mLines.get(iLineNumber);
int iPoint = checkPointOnLine(mX,mY,line);
if(iPoint >= 0)
{
int modifyPointX,modifyPointY;
if(iPoint == 0)
{
modifyPointX = line.getStartPoint().x ;
modifyPointY = line.getStartPoint().y - 2;
mPath.moveTo(line.getEndPoint().x, line.getEndPoint().y);
line.setStartPoint(new Point(modifyPointX, modifyPointY));
}
else if(iPoint == 1)
{
modifyPointX = line.getEndPoint().x;
modifyPointY = line.getEndPoint().y -2;
mPath.moveTo(line.getStartPoint().x, line.getStartPoint().y);
line.setEndPoint(new Point(modifyPointX, modifyPointY));
}
mLines.set(iLineNumber, line);
bModify_line = false;
}
}
}
else
{
Toast.makeText(getContext(), "Please select point", Toast.LENGTH_SHORT).show();
}
}
private void movePointRight()
{
if(bModify_line)
{
int iLineNumber = checkPointinLines(mOriginal_X, mOriginal_Y);
if(iLineNumber > -1)
{
Line line = mLines.get(iLineNumber);
int iPoint = checkPointOnLine(mX,mY,line);
if(iPoint >= 0)
{
int modifyPointX,modifyPointY;
if(iPoint == 0)
{
modifyPointX = line.getStartPoint().x + 2;
modifyPointY = line.getStartPoint().y ;
mPath.moveTo(line.getEndPoint().x, line.getEndPoint().y);
line.setStartPoint(new Point(modifyPointX, modifyPointY));
}
else if(iPoint == 1)
{
modifyPointX = line.getEndPoint().x + 2;
modifyPointY = line.getEndPoint().y ;
mPath.moveTo(line.getStartPoint().x, line.getStartPoint().y);
line.setEndPoint(new Point(modifyPointX, modifyPointY));
}
mLines.set(iLineNumber, line);
bModify_line = false;
}
}
}
else
{
Toast.makeText(getContext(), "Please select point", Toast.LENGTH_SHORT).show();
}
}
private void movePointLeft()
{
if(bModify_line)
{
int iLineNumber = checkPointinLines(mOriginal_X, mOriginal_Y);
if(iLineNumber > -1)
{
Line line = mLines.get(iLineNumber);
int iPoint = checkPointOnLine(mX,mY,line);
if(iPoint >= 0)
{
int modifyPointX,modifyPointY;
if(iPoint == 0)
{
modifyPointX = line.getStartPoint().x - 2 ;
modifyPointY = line.getStartPoint().y ;
mPath.moveTo(line.getEndPoint().x, line.getEndPoint().y);
line.setStartPoint(new Point(modifyPointX, modifyPointY));
}
else if(iPoint == 1)
{
modifyPointX = line.getEndPoint().x - 2;
modifyPointY = line.getEndPoint().y ;
mPath.moveTo(line.getStartPoint().x, line.getStartPoint().y);
line.setEndPoint(new Point(modifyPointX, modifyPointY));
}
mLines.set(iLineNumber, line);
bModify_line = false;
}
}
}
else
{
Toast.makeText(getContext(), "Please select point", Toast.LENGTH_SHORT).show();
}
}
private void movePointDown()
{
if(bModify_line)
{
int iLineNumber = checkPointinLines(mOriginal_X, mOriginal_Y);
if(iLineNumber > -1)
{
Line line = mLines.get(iLineNumber);
int iPoint = checkPointOnLine(mX,mY,line);
if(iPoint >= 0)
{
int modifyPointX,modifyPointY;
if(iPoint == 0)
{
modifyPointX = line.getStartPoint().x ;
modifyPointY = line.getStartPoint().y + 2;
mPath.moveTo(line.getEndPoint().x, line.getEndPoint().y);
line.setStartPoint(new Point(modifyPointX, modifyPointY));
}
else if(iPoint == 1)
{
modifyPointX = line.getEndPoint().x;
modifyPointY = line.getEndPoint().y + 2;
mPath.moveTo(line.getStartPoint().x, line.getStartPoint().y);
line.setEndPoint(new Point(modifyPointX, modifyPointY));
}
mLines.set(iLineNumber, line);
bModify_line = false;
}
}
}
else
{
Toast.makeText(getContext(), "Please select point", Toast.LENGTH_SHORT).show();
}
}
}
for the xml inflation you need to override the constructor that takes Context and AttributeSet as parameter. From the documentation
Constructor that is called when inflating a view from XML.
Add
public DrawView(Context c, AttributeSet attrs) {
super(c, attrs);
}
to your custom view. You could have a common init() method that you share between the two constructors where you perform your initialization (in order to avoid code duplicates)
I am currently creating a maze using a pair of boolean array (horizontal and vertical) in order to draw lines for the maze.
The maze only every displays 5 bools from the array at one time. Then, I have an user who is always centered and as he moves through the maze the next set of bools are drawn. This is working as it should.
The issue that I am having is: when the user moves to a certain part of the maze the for loop drawing the lines becomes higher than the bool array and therefore crashes the app. Please find below some code snippets.
The onDraw:
protected void onDraw(Canvas canvas) {
canvas.drawRect(0, 0, width, height, background);
int currentX = maze.getCurrentX(),currentY = maze.getCurrentY();
int drawSizeX = 6 + currentX;
int drawSizeY = 6 + currentY;
currentX = currentX - 2;
currentY = currentY - 2;
for(int i = 0; i < drawSizeX - 1; i++) {
for(int j = 0; j < drawSizeY - 1; j++) {
float x = j * totalCellWidth;
float y = i * totalCellHeight;
if(vLines[i + currentY][j + currentX]) {
canvas.drawLine(x + cellWidth, //start X
y, //start Y
x + cellWidth, //stop X
y + cellHeight, //stop Y
line);
}
if(hLines[i + currentY][j + currentX]) {
canvas.drawLine(x, //startX
y + cellHeight, //startY
x + cellWidth, //stopX
y + cellHeight, //stopY
line);
}
}
//draw the user ball
canvas.drawCircle((2 * totalCellWidth)+(cellWidth/2), //x of center
(2 * totalCellHeight)+(cellWidth/2), //y of center
(cellWidth*0.45f), //radius
ball);
}
EDIT 1 - The Move -
public boolean move(int direction) {
boolean moved = false;
if(direction == UP) {
if(currentY != 0 && !horizontalLines[currentY-1][currentX]) {
currentY--;
moved = true;
}
}
if(direction == DOWN) {
if(currentY != sizeY-1 && !horizontalLines[currentY][currentX]) {
currentY++;
moved = true;
}
}
if(direction == RIGHT) {
if(currentX != sizeX-1 && !verticalLines[currentY][currentX]) {
currentX++;
moved = true;
}
}
if(direction == LEFT) {
if(currentX != 0 && !verticalLines[currentY][currentX-1]) {
currentX--;
moved = true;
}
}
if(moved) {
if(currentX == finalX && currentY == finalY) {
gameComplete = true;
}
}
return moved;
}
If there is anything else that I need to clarify please let me know.
Thanks in advance.
drawSizeX/Y indexes over the array when currentX/Y is high enough (length-6)
So limit the values to Math.min(current + 6, array.length)