I have this match 3 game, but if I swiping outside the game board this error showed to me and crush the app:
java.lang.ArrayIndexOutOfBoundsException: length=9; index=11
I tried to fix this error but I don't know how to make it work when I touch outside the game board, is that way to make touch only inside the game board game or just a way to ignore this error when it's happing?
public void swap()
{
if(swapIndex > 0)
{
switch (direction){
case "right":
board[poseI][poseJ + 1].poseX -= cellWidth/ 8;
board[poseI][poseJ].poseX += cellWidth/ 8;
break;
case "left":
board[poseI][poseJ - 1].poseX += cellWidth/ 8;
board[poseI][poseJ].poseX -= cellWidth/ 8;
break;
case "up":
board[poseI - 1][poseJ].poseY += cellWidth/ 8;
board[poseI][poseJ].poseY -= cellWidth/ 8;
break;
case "down":
board[poseI + 1][poseJ].poseY -= cellWidth/ 8;
board[poseI][poseJ].poseY += cellWidth/ 8;
break;
}
swapIndex--;
}else {
Candies candies;
candies = board[poseI][poseJ];
board[poseI][poseJ] = board[newPoseI][newPoseJ];
board[newPoseI][newPoseJ] = candies;
board[poseI][poseJ].poseX = (int) (poseJ * cellWidth + drawX);
board[poseI][poseJ].poseY = (int) (poseI * cellWidth + drawY);
board[newPoseI][newPoseJ].poseX = (int) (newPoseJ * cellWidth + drawX);
board[newPoseI][newPoseJ].poseY = (int) (newPoseI * cellWidth + drawY);
swapIndex = 8;
if (gameState == GameState.swapping)
{
gameState = GameState.checkSwapping;
// count user moves
increaseUserMove();
}else {
gameState = GameState.nothing;
}
}
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
canvas.drawColor(Color.WHITE); // Background Color
// Create Game top Background
canvas.drawBitmap(spriteSheet.topBG , 0, - cellWidth * 2, null);
// Create Game bottom Background
canvas.drawBitmap(spriteSheet.bottomBG , 0, drawY + cellWidth * 9, null);
// Create Game middle Background
canvas.drawBitmap(spriteSheet.bg_middle , 0, drawY, null);
// Create Game Cells
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setColor(Color.BLACK); // cells color
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 9; j++)
{
canvas.drawLine(0, drawY + (i * cellWidth), cellWidth * 10, drawY + (i * cellWidth), p);
canvas.drawLine(j * cellWidth , drawY, j * cellWidth, drawY + cellWidth * 9, p);
}
}
for (Candies[] candie: board)
{
for (Candies candies: candie)
{
candies.drawCandies(canvas, spriteSheet);
}
}
for(int i = 0; i < board.length; i++)
{
for(int j = 0; j < board[0].length; j++)
{
candies.drawCandies(canvas, spriteSheet);
}
}
//canvas.drawBitmap(spriteSheet.candiesBMP, candies.poseX, candies.poseY, null);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getAction();
switch (action)
{
case MotionEvent.ACTION_DOWN:
oldX = event.getX();
oldY = event.getY();
poseI = (int) (oldY - drawY) / cellWidth;
poseJ = (int) (oldX - drawX) / cellWidth;
move = true;
break;
case MotionEvent.ACTION_MOVE:
if(gameState == GameState.nothing)
{
float newX = event.getX();
float newY = event.getY();
float deltaX = Math.abs(newX - oldX);
float deltaY = Math.abs(newY - oldY);
if(move && deltaX > 30 || deltaY > 30)
{
// check how many pixels our fingers moved
// if we moved our finger more than 30 pixels we start checking in which direction
move = false;
if (Math.abs(oldX- newX) > Math.abs(oldY - newY))
{
// if the first X touch - the end of the X touch is bigger than the
// first Y touch - the end of the touch Y so the direction is in the X direction
// now we will check which is bigger the oldX or newX for know if its left or right
if(newX > oldX)
{
direction = "right";
newPoseJ = (poseJ + 1);
}else {
direction = "left";
newPoseJ = (poseJ - 1);
}
newPoseI = poseI;
}
if (Math.abs(oldY - newY) > Math.abs(oldX - newX))
{
if(newY > oldY)
{
direction = "down";
newPoseI = (poseI + 1);
}else {
direction = "up";
newPoseI = (poseI - 1);
}
newPoseJ = poseJ;
}
gameState = GameState.swapping;
}
}
break;
}
return true;
}
I'm trying to implement rope swinging in my platformer, following this tutorial. Instead of swing on the rope, the player looks like he's sliding down a slope: he moves very slowly towards the bottom.
This is what it looks like now:
Instead, I want the player to have more natural movement, like he's really swinging on the rope.
This is the update method from my player class:
#Override
public final void update() {
setPosition(getNextPosition());
if (direction == Direction.LEFT && moving) {
getVelocity().x = -WALK_SPEED;
} else if (getVelocity().x < 0) {
getVelocity().x *= COEF_FRIC;
}
if (direction == Direction.RIGHT && moving) {
getVelocity().x = WALK_SPEED;
} else if (getVelocity().x > 0) {
getVelocity().x *= COEF_FRIC;
}
checkAsleep();
animations.update();
if (ropePoint != null) {
//getCenter() returns the center position of the player
if (getCenter().toPoint().distanceSq(ropePoint) > ROPE_LENGTH * ROPE_LENGTH) {
final Vec2D oldPosition = getCenter();
final Vec2D oldVelocity = getVelocity();
final Vec2D ropePosition = new Vec2D(ropePoint);
setCenter((oldPosition.subtract(ropePosition).unit().multiply(ROPE_LENGTH).add(ropePosition)));
setVelocity(oldPosition.subtract(getCenter()).unit().multiply(oldVelocity));
}
}
}
This is my implementation of getNextPosition(), if it is needed.
public final Vec2D getNextPosition() {
final int currCol = (int) (getX() / Tile.SIZE);
final int currRow = (int) (getY() / Tile.SIZE);
final double destX = getX() + moveData.velocity.x;
final double destY = getY() + moveData.velocity.y;
double tempX = getX();
double tempY = getY();
Corners solidCorners = getCornersAreSolid(getX(), destY);
boolean topLeft = solidCorners.topLeft;
boolean topRight = solidCorners.topRight;
boolean bottomLeft = solidCorners.bottomLeft;
boolean bottomRight = solidCorners.bottomRight;
framesSinceLastTopCollision += 1;
framesSinceLastBottomCollision += 1;
framesSinceLastLeftCollision += 1;
framesSinceLastRightCollision += 1;
if (moveData.velocity.y < 0) {
if (topLeft || topRight) {
moveData.velocity.y = 0;
tempY = currRow * Tile.SIZE;
framesSinceLastTopCollision = 0;
} else {
tempY += moveData.velocity.y;
}
} else if (moveData.velocity.y > 0) {
if (bottomLeft || bottomRight) {
moveData.velocity.y = 0;
tempY = (currRow + 1) * Tile.SIZE - moveData.collisionBox.getHeight() % Tile.SIZE - 1;
framesSinceLastBottomCollision = 0;
} else {
tempY += moveData.velocity.y;
}
}
solidCorners = getCornersAreSolid(destX, getY());
topLeft = solidCorners.topLeft;
topRight = solidCorners.topRight;
bottomLeft = solidCorners.bottomLeft;
bottomRight = solidCorners.bottomRight;
if (moveData.velocity.x < 0) {
if (topLeft || bottomLeft) {
moveData.velocity.x = 0;
tempX = currCol * Tile.SIZE;
framesSinceLastLeftCollision = 0;
} else {
tempX += moveData.velocity.x;
}
}
if (moveData.velocity.x > 0) {
if (topRight || bottomRight) {
moveData.velocity.x = 0;
tempX = (currCol + 1) * Tile.SIZE - moveData.collisionBox.getWidth() % Tile.SIZE - 1;
framesSinceLastRightCollision = 0;
} else {
tempX += moveData.velocity.x;
}
}
return new Vec2D(tempX, tempY);
}
What should I change in this code to get natural movement?
My first guess is that the problem lies in that first if statement:
if (direction == Direction.LEFT && moving) {
getVelocity().x = -WALK_SPEED;
} else if (getVelocity().x < 0) {
getVelocity().x *= COEF_FRIC;
}
If the first thing is true, you're going to constantly be setting the velocity to walking pace, which doesn't make sense when your guy is swinging on a rope. He should be speeding up as he goes down and slowing down on the way up.
If the first thing is false, then since he is going left, you're definitely going to go into the else if statement, and he'll be slowed down by friction. I don't see where you set that, but it seems to still be the friction he has on the ground, which would seem to explain why he's all stuttery and looks more like he's sliding than falling.
You might want to add different states instead of just "moving", (perhaps jumping, swinging, walking, running, stopped) and vary how he behaves while doing each of those things.
I have a problem when I upload my sketch to website.
I write a processing program which is a 3D guiding library.This is my code.
//Camera Variables
float x,y,z;
float tx,ty,tz;
float rotX,rotY;
float mX, mY;
float frameCounter;
float xComp, zComp;
float angle;
//Movement Variables
int moveX;
int moveZ;
float vY;
boolean canJump;
boolean moveUP,moveDOWN,moveLEFT,moveRIGHT;
//check input
int m =0;
//Constants
int ground = 0;
int totalBoxes = 100;
int standHeight = 100;
int dragMotionConstant = 10;
int pushMotionConstant = 100;
int movementSpeed = 50; //Bigger number = slower
float sensitivity = 15; //Bigger number = slower
int stillBox = 100; //Center of POV, mouse must be stillBox away from center to move
float camBuffer = 10;
int cameraDistance = 1000; //distance from camera to camera target in lookmode... 8?
//Options
int lookMode = 8;
int spotLightMode = 4;
int cameraMode = 1;
int moveMode = 2;
void setup(){
size(800,600,P3D);
noStroke();
//dwa(#EDEDE8);
//Camera Initialization
//default
x = -28;
y = height/2;
y-= standHeight;
z = -4830;
tx = width/2;
ty = height/2;
tz = 0;
rotX = 0;
rotY = 0;
xComp = tx - x;
zComp = tz - z;
angle = 0;
//Movement Initialization
moveX = 0;
moveX = 0;
moveUP = false;
moveDOWN = false;
moveLEFT = false;
moveRIGHT = false;
canJump = true;
vY = 0;
}
void draw(){
if(z<-5000)
z=-5000;
if(z>9700)
z=9700;
//println(x,y,z ,mouseX , mouseY ,tx ,ty,tz);
//update frame
background(0);
lights();
if(m==1)
{
//rotateY(0.5);
fill(#EAFF0F);
textSize(50);
text("menu", x-100, y, z+300);
// rotateY(0.5);
//the point
pushMatrix();
fill(#FC1919);
translate(-28,300,4000);
box(10, 20000, -10);
popMatrix();
//the point
}
if(spotLightMode == 0)
lights();
else if(spotLightMode == 1)
spotLight(255,255,255,x,y-standHeight,z,tx,ty,tz,PI,1);
else if(spotLightMode == 2)
spotLight(255,255,255,x,y-standHeight-200,z,x+100,y+100,z,frameCounter/10,1);
else if(spotLightMode == 3)
spotLight(255,255,255,width/2,height/2-1000,0,width/2,height/2,0,PI,1);
else if(spotLightMode == 4)
{
pointLight(255,255,255,x,y,z);
}
/*
for(int i=1;i<=7;i++)
{
spotLight(255, 255, 255, -28, 2000, -5500+i*1875, 1, 1, 1, 360, 1);
}*/
//-5500 9500s
//back wall
pushMatrix();
fill(255);
translate(-28,300,-5500);
box(15000, 5000, -100);
popMatrix();
//back wall
//fount wall
pushMatrix();
fill(255);
translate(-28,300,10500);
box(15000, 5000, -100);
popMatrix();
//fount wall
//L1
bookshielf(800,-4000,7,1);
bookshielf(1000,-4000,7,1);
bookshielf(1200,-4000,7,1);
bookshielf(1400,-4000,7,1);
cameraUpdate();
locationUpdate();
jumpManager(10);
//Camera Mode 1 - Original
if(cameraMode == 1)
camera(x,y,z,tx,ty,tz,0,1,0);
//Camera Mode 2 - Matrix'd
/* if(cameraMode == 2){
beginCamera();
camera();
translate(x,y,z);
translate(0,2*-standHeight,0);
rotateX(rotY/100.0); //This seems to work o.o
rotateY(-rotX/100.0);
//rotateX(rotX/100.0);
endCamera();
}*/
//frameCounter++;
}
void cylinder(float w, float h, int sides)
{
float angle;
float[] x = new float[sides+1];
float[] z = new float[sides+1];
translate(0,100,-500);
//get the x and z position on a circle for all the sides
for(int i=0; i < x.length; i++){
angle = TWO_PI / (sides) * i;
x[i] = sin(angle) * w;
z[i] = cos(angle) * w;
}
//draw the top of the cylinder
beginShape(TRIANGLE_FAN);
vertex(0, -h/2, 0);
for(int i=0; i < x.length; i++){
vertex(x[i], -h/2, z[i]);
}
endShape();
//draw the center of the cylinder
beginShape(QUAD_STRIP);
for(int i=0; i < x.length; i++){
vertex(x[i], -h/2, z[i]);
vertex(x[i], h/2, z[i]);
}
endShape();
//draw the bottom of the cylinder
beginShape(TRIANGLE_FAN);
vertex(0, h/2, 0);
for(int i=0; i < x.length; i++){
vertex(x[i], h/2, z[i]);
}
endShape();
}
public void bookshielf(int thex ,int thez ,int theheight ,int therotate)
{
fill(#938056);
if(theheight==7)
{
if(therotate==1)
{
//left
pushMatrix();
translate(thex,0,thez);
box(20, 500, -100);
popMatrix();
//right
pushMatrix();
translate(thex-200,0,thez);
box(20, 500, -100);
popMatrix();
//back
pushMatrix();
translate(thex-100,0,thez+40);
box(220, 500, -30);
popMatrix();
//middle side
for(int i=1;i<7;i++)
{
pushMatrix();
translate(thex-100,-250+71.5*i,thez-10);
box(220, 5, -100);
popMatrix();
}
//top
pushMatrix();
translate(thex-100,250,thez);
box(220, 10, -100);
popMatrix();
//block
pushMatrix();
translate(thex-100,-250,thez);
box(220, 10, -100);
popMatrix();
}
if(therotate==2)
{
//left
pushMatrix();
translate(thex,0,thez);
box(20, 500, -100);
popMatrix();
//right
pushMatrix();
translate(thex-200,0,thez);
box(20, 500, -100);
popMatrix();
//back
pushMatrix();
translate(thex-100,0,thez-40);
box(220, 500, -30);
popMatrix();
//middle side
for(int i=1;i<7;i++)
{
pushMatrix();
translate(thex-100,-250+71.5*i,thez+10);
box(220, 5, -100);
popMatrix();
}
//top
pushMatrix();
translate(thex-100,250,thez);
box(220, 10, -100);
popMatrix();
//block
pushMatrix();
translate(thex-100,-250,thez);
box(220, 10, -100);
popMatrix();
}
}
}
public void cameraUpdate(){
ty=constrain(dragMotionConstant, -100000, 500000);
//Drag-motion
if (lookMode == 1){
if(pmouseX > mouseX)
tx += dragMotionConstant;
else if (pmouseX < mouseX)
tx -= dragMotionConstant;
if(pmouseY > mouseY)
ty -= dragMotionConstant/1.5;
else if (pmouseY < mouseY)
ty += dragMotionConstant/1.5;
}
//Push-motion
else if (lookMode == 2){
if (mouseX > (width/2+pushMotionConstant))
tx += dragMotionConstant;
else if (mouseX < (width/2-pushMotionConstant))
tx -= dragMotionConstant;
if (mouseY > (height/2+pushMotionConstant))
ty += dragMotionConstant;
else if (mouseY < (height/2-pushMotionConstant))
ty -= dragMotionConstant;
}
//Push-motion V2 (Hopefully improved!)
else if (lookMode == 3){
int diffX = mouseX - width/2;
int diffY = mouseY - width/2;
if (abs(diffX) > pushMotionConstant)
tx += diffX/25;
if (abs(diffY) > pushMotionConstant)
ty += diffY/25;
}
//Push Motion V3 (For Camera-Mode 2)
else if (lookMode == 4){
int diffX = mouseX - width/2;
int diffY = mouseY - width/2;
//println(diffX);
if (abs(diffX) > pushMotionConstant)
rotX += diffX/100;
if (abs(diffY) > pushMotionConstant)
rotY += diffY/100;//diffY/100;
}
//Push Motion V4.1 (Because it crashed and I lost V4.0 T.T
//Designed to work in cohesion with movement mode 2
else if (lookMode == 5){
int diffX = mouseX - width/2;
int diffY = mouseY - width/2;
if(abs(diffX) > stillBox){
xComp = tx - x;
zComp = tz - z;
angle = degrees(atan(xComp/zComp));
//---------DEBUG STUFF GOES HERE----------
//println("tx: " + tx);
//println("tz: " + tz);
// println("xC: " + xComp);
// println("zC: " + zComp);
// println("Angle: " +angle);
//--------------------------------------*/
if (angle < 45 && angle > -45 && zComp < 0)
tx += diffX/sensitivity;
else if (angle < 45 && angle > -45 && zComp > 0)
tx -= diffX/sensitivity;
//Left Sector
else if (angle > 45 && angle < 90 && xComp < 0 && zComp < 0)
tz -= diffX/sensitivity;
else if (angle >-90 && angle <-45 && xComp < 0 && zComp > 0)
tz -= diffX/sensitivity;
//Right Sector
else if (angle <-45 && angle >-90)
tz += diffX/sensitivity;
else if (angle < 90 && angle > 45 && xComp > 0 && zComp > 0)
tz += diffX/sensitivity;
}
if (abs(diffY) > stillBox)
ty += diffY/(sensitivity/1.5);
}
//Lookmode 4.2
//Using a more proper unit circle.
else if (lookMode == 6){
int diffX = mouseX - width/2;
int diffY = mouseY - width/2;
if(abs(diffX) > stillBox){
xComp = tx - x;
zComp = tz - z;
angle = correctAngle(xComp,zComp);
//---------DEBUG STUFF GOES HERE----------
// println("tx: " + tx);
// println("tz: " + tz);
// println("xC: " + xComp);
/// println("zC: " + zComp);
/// println("Angle: " +angle);
//--------------------------------------*/
//Looking 'forwards'
if ((angle >= 0 && angle < 45) || (angle > 315 && angle < 360))
tx += diffX/sensitivity;
//Looking 'left'
else if (angle > 45 && angle < 135)
tz += diffX/sensitivity;
//Looking 'back'
else if (angle > 135 && angle < 225)
tx -= diffX/sensitivity;
//Looking 'right'
else if (angle > 225 && angle < 315)
tz -= diffX/sensitivity;
}
if (abs(diffY) > stillBox)
ty += diffY/(sensitivity/1.5);
}
//Lookmode 7, trying to get rid of the slowdown in the corners with a sorta-buffer thing
else if (lookMode == 7){
int diffX = mouseX - width/2;
int diffY = mouseY - width/2;
if(abs(diffX) > stillBox){
xComp = tx - x;
zComp = tz - z;
angle = correctAngle(xComp,zComp);
//---------DEBUG STUFF GOES HERE----------
// println("tx: " + tx);
// println("tz: " + tz);
// println("xC: " + xComp);
// println("zC: " + zComp);
// println("Angle: " +angle);
//--------------------------------------*/
//Looking 'forwards'
if ((angle >= 0-camBuffer && angle < 45+camBuffer) || (angle > 315-camBuffer && angle < 360+camBuffer))
tx += diffX/sensitivity;
//Looking 'left'
else if (angle > 45-camBuffer && angle < 135+camBuffer)
tz += diffX/sensitivity;
//Looking 'back'
else if (angle > 135-camBuffer && angle < 225+camBuffer)
tx -= diffX/sensitivity;
//Looking 'right'
else if (angle > 225-camBuffer && angle < 315+camBuffer)
tz -= diffX/sensitivity;
}
if (abs(diffY) > stillBox)
ty += diffY/(sensitivity/1.5);
}
else if (lookMode == 8){
int diffX = mouseX - width/2;
int diffY = mouseY - width/2;
if(abs(diffX) > stillBox){
xComp = tx - x;
zComp = tz - z;
angle = correctAngle(xComp,zComp);
angle+= diffX/(sensitivity*10);
if(angle < 0)
angle += 360;
else if (angle >= 360)
angle -= 360;
float newXComp = cameraDistance * sin(radians(angle));
float newZComp = cameraDistance * cos(radians(angle));
tx = newXComp + x;
tz = -newZComp + z;
//---------DEBUG STUFF GOES HERE----------
/*println("tx: " + tx);
println("tz: " + tz);
println("xC: " + xComp);
println("NewXC: " + newXComp);
println("zC: " + zComp);
println("NewZC: " + newZComp);
println("Angle: " +angle);*/
//--------------------------------------*/
}
if (abs(diffY) > stillBox)
ty += diffY/(sensitivity/1.5);
}
}
public void locationUpdate(){
/*Old method==================================
if(keyPressed){
if (keyCode == UP || key == 'w'){
z-=10;
tz-=10;
}
else if (keyCode == DOWN || key == 's'){
tz+=10;
z+=10;
}
else if (keyCode == LEFT || key == 'a' ){
tx-=10;
x-=10;
}
else if (keyCode == RIGHT || key == 'd'){
tx+=10;
x+=10;
}
}
============================================*/
//Apply Movement
if(moveMode == 1){
z += moveZ;
tz += moveZ;
x += moveX;
tx += moveX;
}
else if(moveMode == 2){
if(moveUP){
z += zComp/movementSpeed;
tz+= zComp/movementSpeed;
x += xComp/movementSpeed;
tx+= xComp/movementSpeed;
}
else if(moveDOWN){
z -= zComp/movementSpeed;
tz-= zComp/movementSpeed;
x -= xComp/movementSpeed;
tx-= xComp/movementSpeed;
}
if (moveRIGHT){
z += xComp/movementSpeed;
tz+= xComp/movementSpeed;
x -= zComp/movementSpeed;
tx-= zComp/movementSpeed;
}
if (moveLEFT){
z -= xComp/movementSpeed;
tz-= xComp/movementSpeed;
x += zComp/movementSpeed;
tx+= zComp/movementSpeed;
}
}
//New method also uses keyPressed() and keyReleased()
// Scroll Down!
}
public void jumpManager(int magnitude){
/*
if(keyPressed && key == ' ' && canJump){
vY -= magnitude;
if(vY < -20)
canJump = false;
}
else*/ if (y < ground+standHeight)
vY ++;
else if (y >= ground+standHeight){
vY = 0;
y = ground + standHeight;
}
if((!canJump) && (!keyPressed)){
//println("Jump Reset!");
canJump = true;
}
y += vY;
}
public void keyPressed(){
if(keyCode == UP || key == 'w'){
moveZ = -10;
moveUP = true;
}
else if(keyCode == DOWN || key == 's'){
moveZ = 10;
moveDOWN = true;
}
else if(keyCode == LEFT || key == 'a'){
moveX = -10;
moveLEFT = true;
}
else if(keyCode == RIGHT || key == 'd'){
moveX = 10;
moveRIGHT = true;
}
if(key == 'm' && m==1){
m=0;
}
else if(key == 'm' && m==0){
if(key == '1')
{
}
rotateY(180);
fill(#EAFF0F);
textSize(50);
text("menu", x-100, y, z+300);
m=1;
}
}
public void keyReleased(){
if(keyCode == UP || key == 'w'){
moveUP = false;
moveZ = 0;
}
else if(keyCode == DOWN || key == 's'){
moveDOWN = false;
moveZ = 0;
}
else if(keyCode == LEFT || key == 'a'){
moveLEFT = false;
moveX = 0;
}
else if(keyCode == RIGHT || key == 'd'){
moveRIGHT = false;
moveX = 0;
}
}
void mousePressed()
{
}
public float correctAngle(float xc, float zc){
float newAngle = -degrees(atan(xc/zc));
if (xComp > 0 && zComp > 0)
newAngle = (90 + newAngle)+90;
else if (xComp < 0 && zComp > 0)
newAngle = newAngle + 180;
else if (xComp < 0 && zComp < 0)
newAngle = (90+ newAngle) + 270;
return newAngle;
}
People can use their first person view to walk the library.It is fine in java mode,but when I put it in java script mode,the view has problem.So , which part of my code has problems so that it can not run on website?
Thank you very much.
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;
}