Limit ACTION_MOVE area ouside circle - java

I have custom View for color picking and I want to restrict selector be inside circle cardview in the center.
Selector is moving by ACTION_MOVE and ACTION_UP.Coordinates change via this function:
private void updateSelector(float eventX, float eventY) {
float x = eventX - centerX;
float y = eventY - centerY;
double r = Math.sqrt(x * x + y * y);
if (r > radius) {
x *= radius / r;
y *= radius / r;
}
currentPoint.x = x + centerX;
currentPoint.y = y + centerY;
selector.setCurrentPoint(currentPoint);
}
I've also written this helper function to check if selector inside cardview and it's correctly works, but I've no idea how to restrict selector go in.
private boolean isInBounds(float x, float y) {
return Math.sqrt(x - centerX) + Math.sqrt(y - centerY) <= Math.sqrt(cardradius);
}

Related

Drawing paths from a point where each path is distanced from the initial point

I am having a bit of trouble trying to figure out how to draw paths from a point on a canvas with the start of each path being equally distanced from the initial point. To illustrate what I mean, the code that I have so far is able to generate this:
and the desired result is something like this:
My code:
int n = 3;
int r;
double x;
double y;
point1 = new Point(mWidth/2, mHeight/2);
double angle;
double angleFactor;
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < 3; i++){
angleFactor = 2 * Math.PI / n;
angle = i * angleFactor;
x = (point1.x) + r * Math.cos(angle);
y = (point1.y) + r * Math.sin(angle);
//Draw paths
path.reset();
path.moveTo(point1.x, point1.y);
path.lineTo((float) x, (float) y);
canvas.drawPath(path, paint);
}
}
Is there a simple solution to this?
Since you want to have a tiny distance between the offset of a line and the center point, you can define start coordinates like this:
double xStart, xEnd;
double yStart, yEnd;
double offsetFraction = 0.1;
Inside the for loop in onDraw() :
double lengthX = r * Math.cos(angle);
double lengthY = r * Math.sin(angle);
xStart = (point1.x) + offsetFraction * lengthX;
yStart = (point1.y) + offsetFraction * lengthY;
xEnd = (point1.x) + lengthX;
yEnd = (point1.y) + lengthY;
//Draw paths
path.reset();
path.moveTo((float) xStart, (float) yStart);
path.lineTo((float) xEnd, (float) yEnd);
canvas.drawPath(path, paint);

Coordinate values arent stored in processing

I really have no idea why the x and y values wont go to the drawLines function
float x, x1, x2;
float y, y1, y2;
float rad; //radius
int lines = 30; //number of lines
int colorNumber = 1;
void setup() {
background(#FFFFFF);
size (800, 600);
rad = 8;
}
void draw() {
}
This creates the three dots or vertices of the mathematical envelope
void mouseClicked() {
float x = mouseX;
float x1 = mouseX;
float x2 = mouseX;
float y = mouseY;
float y1 = mouseY;
float y2 = mouseY;
if (colorNumber == 1) {
fill(#9393ff);
ellipse(x, y, rad, rad);
} else if (colorNumber == 2) {
fill(#FF9393);
ellipse(x1, y1, rad, rad);
} else if (colorNumber == 3) {
fill(#93ff93);
ellipse(x2, y2, rad, rad);
}
}
This is supposed to draw the envelope using the coordinates of the vertices
void drawLines(int numLines) {
for (int i = 0; i < numLines; i = i + 1) {
float x = mouseX;
float x1 = mouseX;
float x2 = mouseX;
float y = mouseY;
float y1 = mouseY;
float y2 = mouseY;
float t = (float) i/(numLines-1);
float startX = x + t * (x1 - x);
float startY = y + t * (y1 - y);
float endX = x1 + t * (x2 - x1);
float endY = y1 + t * (y2 - y1);
line (startX, startY, endX, endY);
}
}
void mouseReleased() {
colorNumber++;
if (colorNumber == 4) {
colorNumber = 1;
}
println(colorNumber);
}
void keyPressed() {
if (keyPressed == true) {
background(#FFFFFF);
}
}
this last stuff just tells the code if you press a key, it will reset the backround
I understand your intention with using mouseX and mouseY to specify the coordinates of one of the 3 points of the envelope on click. The current issue is that all 3 points are being set to the same coordinate with each click. You need to introduce a variable to keep track of which coordinate to set on-click, such that only one pair is set. Then, only once all 3 coordinates are set, drawLines() can be called.
I propose the following:
Introduce 2 variables, one to keep track of which point is being modified; the other an array of PVectors (just to make it cleaner).
int index = 0;
PVector[] coords = new PVector[3];
Modify mouseClicked() to include the following:
void mouseClicked() {
ellipse(mouseX, mouseY, 8, 8);
coords[index] = new PVector(mouseX, mouseY);
index += 1;
if (index == 3) {
drawLines(lines);
}
index %= 3;
}
drawLines() becomes:
void drawLines(int numLines) {
for (int i = 0; i < numLines; i = i + 1) {
x = coords[0].x;
x1 = coords[1].x;
x2 = coords[2].x;
y = coords[0].y;
y1 = coords[1].y;
y2 = coords[2].y;
float t = (float) i / (numLines - 1);
float startX = x + t * (x1 - x);
float startY = y + t * (y1 - y);
float endX = x1 + t * (x2 - x1);
float endY = y1 + t * (y2 - y1);
line(startX, startY, endX, endY);
}
}
Finally, since your drawing on a black background, and the default stroke colour is black, use strokeColour() to change the colour of the lines so that you can see the envelope once its drawn.

javaFX- what is getBoundsInLocal() ,getBoundsInParent() method?

A image (here the node named hero) is moved according to the KEY pressed in keyboard. But a method named getBoundsInLocal() is used. I can't truly understand the purpose of this method . Does it helps to get the width and height of the image ?
private void moveHeroBy(int dx, int dy) {
if (dx == 0 && dy == 0) return;
final double cx = hero.getBoundsInLocal().getWidth() / 2;
final double cy = hero.getBoundsInLocal().getHeight() / 2;
double x = cx + hero.getLayoutX() + dx;
double y = cy + hero.getLayoutY() + dy;
moveHeroTo(x, y);
}
private void moveHeroTo(double x, double y) {
final double cx = hero.getBoundsInLocal().getWidth() / 2;
final double cy = hero.getBoundsInLocal().getHeight() / 2;
if (x - cx >= 0 &&
x + cx <= W &&
y - cy >= 0 &&
y + cy <= H) {
hero.relocate(x - cx, y - cy);
}
}
This method is called by an AnimationTimer by this way:
AnimationTimer timer = new AnimationTimer() {
#Override
public void handle(long now) {
int dx = 0, dy = 0;
if (goNorth) dy -= 1;
if (goSouth) dy += 1;
if (goEast) dx += 1;
if (goWest) dx -= 1;
if (running) { dx *= 3; dy *= 3; }
moveHeroBy(dx, dy);
}
};
timer.start();
I have found similar method named getBoundsInParent() . what do these two methods do & what are the differences ?
getBoundsInLocal returns the bounds of a Node in it's own coordinate system.
getBoundsInParent returns the bounds after adjusting them with depending on transforms/layoutX/layoutY.
Both can be used to determine the size, but which size you need is determined by the coordinate system you're using...
Example
Rectangle rect = new Rectangle(100, 200);
rect.setLayoutX(11);
rect.setLayoutY(33);
rect.setScaleX(2);
Pane root = new Pane();
root.getChildren().add(rect);
System.out.println(rect.getBoundsInLocal());
System.out.println(rect.getBoundsInParent());
prints
BoundingBox [minX:0.0, minY:0.0, minZ:0.0, width:100.0, height:200.0, depth:0.0, maxX:100.0, maxY:200.0, maxZ:0.0]
BoundingBox [minX:-39.0, minY:33.0, minZ:0.0, width:200.0, height:200.0, depth:0.0, maxX:161.0, maxY:233.0, maxZ:0.0]
For a untransformed ImageView you can determine the size by using the viewport's size or if this property is set to null the width/height of the image used with the ImageView

Shoot to the mouse direction

The problem:
I've got this "Shot" class. In the code, the target variables are the mouseX and mouseY.
So when i click the mouse button, my player class will create a new shot object.
But the shooting is inaccurate.
How can i calculate the correct dx and dy?
If i add the dx and dy to the "bullet's" x and y, the bullet will move to the mouse's direction.This is what i want. The mouse position is stored in targetX and targetY, when the object is created. This is the point what the oval wants to reach.
Links:
The game (finished)
The code (from Shot.java):
public class Shot extends Entity {
private float targetX, targetY;
public Shot(World world, float x, float y, int width, int height, Color color, float targetX, float targetY) {
super(world, x, y, width, height, color);
this.targetX = targetX;
this.targetY = targetY;
}
#Override
public void render(GameContainer gc, Graphics g, Camera camera) {
g.setColor(color);
g.fillOval(x - camera.getX(), y - camera.getY(), width, height);
}
#Override
public void update(GameContainer gc, int delta) {
float dx = targetX - x;
float dy = targetY - y;
x += dx * delta * .001f;
y += dy * delta * .001f;
}
}
I tried this, but still not work:
#Override
public void update(GameContainer gc, int delta) {
float length = (float) Math.sqrt((targetX - x) * (targetX - x) + (targetY - y) * (targetY - y));
double dx = (targetX - x) / length * delta;
double dy = (targetY - y) / length * delta;
x += dx;
y += dy;
}
I did it! Here is my solution:
The problem was that, the target was the window's mouse position, and not the world's mouse position.
This is how i calculated the world's mouse positions:
float mouseWorldX = x + (mouseX - screen_width / 2); // x = player's x position
float mouseWorldY = y + (mouseY - screen_height / 2); // y = player's y position
This is code from my game at the moment is used to move a unit to the mouse when the right mouse button is pressed:
length = Math.sqrt((target_X - player_X)*(target_X - player_X) + (target_Y - player_Y)*(target_Y - player_Y)); //calculates the distance between the two points
speed_X = (target_X - player_X) /length * player_Speed;
speed_Y = (target_Y - player_Y) /length * player_Speed;
This will move an object to the target in a line at a set speed.
Edit: this is the actual code right from my game
if(input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON))
{
length = (float) Math.sqrt((player_waypoint_X - player_X)*(player_waypoint_X - player_X) + (player_waypoint_Y - player_Y)*(player_waypoint_Y - player_Y));
velocityX = (float) (player_waypoint_X - player_X) /length * (float) PlayerStats.player.db_player_Speed;
velocityY = (float) (player_waypoint_Y - player_Y) /length * (float) PlayerStats.player.db_player_Speed;
player_waypoint_X = input.getMouseX() - 2;
player_waypoint_Y = input.getMouseY() - 2;
}
For testing purposes the velocity's are defined in the init method along with length. Every time the right mouse is pressed the waypoints's X and Y are changed to the mouse location.
I learned this from this question
velocity calculation algorithm.
in order to make the bullets not all change direction every shot, create an array list so that each bullet fired has its own x and y velocity

Logic for analog stick produces a square instead of a circle

I'm trying to simulate an analog stick on a mobile platform.
I calculate a stick vector which based on the position of the finger and the radius of the stick returns a value from -1 to 1.
public void calcStickVector(float x, float y)
{
float cx = getCenterX();
float cy = getCenterY();
float distX = x - cx;
float distY = y - cy;
distX /= getRadius();
distY /= getRadius();
distX = JMath.clamp(-1.0f, 1.0f, distX);
distY = JMath.clamp(-1.0f, 1.0f, distY);
stickVector.x = distX;
stickVector.y = distY;
}
public RectF getInnerStickRect()
{
float r = getInnerRadius();
float cx = getCenterX() + (getRadius() * getStickVector().x);
float cy = getCenterY() + (getRadius() * getStickVector().y);
innerStickRect.left = cx - r;
innerStickRect.top = cy - r;
innerStickRect.right = cx + r;
innerStickRect.bottom = cy + r;
return innerStickRect;
}
It almost works, but visually the inner stick, when moved around seems to form a square rather than going around in a circle. Is there something wrong with my logic?
Thanks
As it is, you really are making a box with 1's as the corners. You need to normalize the vector(divide x and y by distance) instead of dividing by radius and clamping.
double dist = Math.sqrt(distX*distX) + (distY*distY));
distX /= dist;
distY /= dist;

Categories

Resources