Rotating a PVector - java

ok guys i want to rotate a PVector that i have in this method.
this method replaces the posX and posY by the x and y of the PVector.
the movement is determinated by a joystick that comes from arduino it moves the image in x and y but i would like to turn the vector depending on the axis the joystick is looking
public void moverPjUno(PVector coordenadas) {
if(areaXad==-1 && areaXat==-1){
miPersonaje.setPosX((miPersonaje.getPosX())+(int)coordenadas.x);
}
if(areaYab==-1 && areaYar==-1){
miPersonaje.setPosY((miPersonaje.getPosY())+(int)coordenadas.y);
}
}

I don't have an Arduino hooked up and I don't know what kind of information your joystick is giving you, so I made a Processing example that uses the mouse to imitate the joystick:
int rad = 100;
void setup() {
size(400, 400);
}
void draw() {
background(255);
ellipse(width/2, height/2, rad*2, rad*2);
// Using the mouse to mimic the position of the joystick
float theta = atan2(mouseY-height/2, mouseX-width/2);
// Get the new position
float x = width/2+cos(theta)*rad;
float y = height/2+sin(theta)*rad;
// Show the new position
ellipse(x, y, 30, 30);
}
The atan2 function gives the angle to the mouse position, replace the arguments with the equivalent of the joystick position. The smaller ellipse being drawn shows where your miPersonaje would be set based on x and y earlier in the code. The rad variable is arbitrary and just for displaying purposes, you can set it to be whatever you want (if needed at all).

Related

Processing - Zoom on clicked area then click again to zoom back out

I have a picture then used a flashlight type of light to only show where the mouse is hovering over. That part of the code works, but now I want to use if/else statements to zoom in on the selected area and then click again to zoom back out. Any other way to zoom in on specific area then back out of that area also helps. Really any help will be appreciated!
PImage ispy;
void setup () {
size(1024,768);
ispy = loadImage("ispy2.jpeg");
}
void draw () {
loadPixels();
ispy.loadPixels();
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int loc = x+y*width;
float r = red(ispy.pixels[loc]);
float g = green(ispy.pixels[loc]);
float b = blue(ispy.pixels[loc]);
float d = dist(mouseX, mouseY, x, y); //
float factor = map(d, 0, 200, 2, 0);
pixels[loc] = color(r*factor, g*factor, b*factor);
}
}
updatePixels();
}
Here is my interpretation of what you are talking about. We store a isClicked boolean to store the state of whether we should zoom in or not. When we are going to draw the image, we translate() to the mouse, then we scale(), then we translate() back the same amount that we moved before, but in the opposite direction. What this does is it does the scale transform around the mouse position.
One thing that I couldn't find a way around way your way of updating the pixels directly from the image and the flashlight effect. What the program is doing instead is using your method to make a mask image and applying that to a PGraphics object. Another thing that I noticed is that when just rendering straight to the screen, there is considerable lag from the scaling. Instead, I have moved the drawing to a PGraphics object. This improves the performance.
In the end, to render, the program is drawing everything on the PGraphics object, then applying the mask to that object to get the flashlight effect.
Here is the code that I have:
PImage ispy, distMask;
boolean isClicked = false;
PGraphics renderer;
void createDistanceMask(PImage distMask){ //Takes image and changes its pixels to "alpha" for the PGraphics renderer
distMask.loadPixels();
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int loc = x+(height-y-1)*width;
float d = dist(mouseX, mouseY, x, y); //
int factor = int(map(d, 0, 200, 400, 0)); //Pixel data will be between 0 and 255, must scale down later.
if (factor > 255)
factor = 255;
distMask.pixels[loc] = color(factor,factor,factor);
}
}
distMask.updatePixels();
}
void setup () {
size(1024,768, P2D);
ispy = loadImage("ispy2.jpeg");
distMask = new PImage(width,height);
renderer = createGraphics(width,height,P2D);
mouseX = width/2; //Not necessary, but will have black screen until mouse is moved
mouseY = height/2;
}
void draw () {
background(0);
pushMatrix();
createDistanceMask(distMask);
renderer.beginDraw(); //Starts processing stuff into PGraphics object
renderer.background(0);
if(isClicked){ //This is to get the zoom effect
renderer.translate(mouseX, mouseY);
renderer.scale(2);
renderer.translate(-mouseX, -mouseY);
}
renderer.image(ispy,0,0); //Render Image
renderer.endDraw();
renderer.mask(distMask); //Apply Distance mask for flashlight effect
image(renderer,0,0); //Draw renderer result to screen
popMatrix();
}
void mouseClicked(){
isClicked = !isClicked;
}
In my comment, I asked about having the screen move to the mouse, which is what this is doing. If you want to "freeze" the screen in one position, what you can do is store a lastMouseClickPosition PVector or simply just ints. Then, when translating, translate to the position instead of the PVector.
Here's the code that would change:
PVector lastClickPos = new PVector(); //Make the position
if(isClicked){ //When Rendering
renderer.translate(lastClickPos.x, lastClickPos.y);
renderer.scale(scalingFactor);
renderer.translate(-lastClickPos.x, -lastClickPos.y);
}
void mouseClicked(){ //At the bottom
isClicked = !isClicked;
lastClickPos.set(mouseX, mouseY);
}

How to make a ball go in a specific direction according to where it's clicked?

Table t1= new Table(300, 300);
float power=0;
float dx=0;
float dy=0;
void setup()
{
size(1000, 600);
frameRate(10);
}
void draw()
{
strokeWeight(1);
stroke(0, 0, 0);
strokeWeight(10);
stroke(255, 0, 0);
fill(26, 218, 35);
rect(0, 0, 1000, 600);
noStroke();
fill(0);
ellipse(0, 0, 80, 80);
ellipse(1000, 0, 80, 80);
ellipse(0, 600, 80, 80);
ellipse(1000, 600, 80, 80);
strokeWeight(1);
stroke(0, 0, 0);
fill(255);
ellipse(t1.cue_ball.center.x, t1.cue_ball.center.y, 20, 20);
dx=friction(dx);
dy=friction(dy);
if (mousePressed)
{
power+=5;
}
if (t1.cue_ball.center.x+30>1000 || t1.cue_ball.center.x-30<0)
{
dx*=-1;
}
if (t1.cue_ball.center.y+30 >=600 || t1.cue_ball.center.y -30<=0)
{
dy*=-1;
}
t1.cue_ball.center.x +=dx;
t1.cue_ball.center.y +=dy;
}
void mouseReleased()
{
dx=power*2;
dy=power*2;
}
float friction (float c)
{
c*=0.9;
return c;
}
class Ball
{
float rad;
Point center;
Point contact_point;
color col;
Ball ( float a, float b)
{
center = new Point (a+=dx, b+=dy);
//contact_point= new Point(
}
}
class Table
{
Ball [] b_arr;
Stick st;
Ball cue_ball;
Table ( float a, float b )
{
cue_ball= new Ball( a, b);
}
}
class Point
{
float x;
float y;
Point(float a, float b)
{
x=a;
y=b;
}
}
class Stick
{
Point start_p;
Point end_p;
color col;
int length;
}
So we want to add something so that when the ball is clicked, it will move accordingly. For example, if it is clicked in the top left, it will move diagonally right down. If clicked bottom left, it will move diagonally right up. Also, is there a way to correspond this to the angle? So a larger angle between the click point and the center will make a steeper diagonal.
Added lines of code I'm not sure where needs to be added:
t1.cue_ball.center.x+=dx;
t1.cue_ball.center.y+=dy;
dx=t1.cue_ball.center.x-mouseX;
dy=t1.cue_ball.center.y-mouseY;
float n= sqrt(pow(dx,2)+pow(dy,2));
dx*=power/n;
dy*=power/n;
If you have or know how to compute the angle between the x-axis and the cue (I'm assuming this is billiards), then to make the ball go in that direction, if I understand your code correctly, you could just set the dx and dy of the ball that you strike according to
dx = power*cos(angle)
dy = power*sin(angle)
You might have to take the negative angle instead, depending on the coordinate system (if going up is positive or negative in the y-direction), and precisely what angle you compute. The easiest is probably to just plug it in and see what happens!
EDIT:
Not related to your question, but as a matter of style, it might be a good idea to move your logic for moving and drawing the ball to the Ball class. So that every tick, you draw the balls on the screen by calling an appropriate draw() method for each instance of the Ball class. Then it would be much easier to move several balls at once.
EDIT2:
I just realized you can actually solve the problem without trigonometry, if you know the point where you click. Let's say cx,cy is the point where you click, and x,y is the center of the ball, then your dx and dy for the ball can be computed as:
dx = x-cx
dy = y-cy
n = sqrt(dx^2 + dy^2)
dx *= power/n
dy *= power/n
Explanation:
The outgoing velocity for the ball should be in the same direction as the click relative to the ball. So we already have the relative lengths of dx and dy, and to get the right power we just need to normalize and multiply by the power.

how can i make a graphic object solid in java?

I'm working on a simple game and i need these squareBumpers which simply stands idle and when got hit, collides and reflects the ball. But currently the ball just flies through my squareBumpers. I can only use java awt and swing libraries. Here's the code:
class squareBumper {
private int x = 300;
private int y = 300;
private Color color = new Color(66,139,139);
public void paint(Graphics g) {
Rectangle clipRect = g.getClipBounds();
g.setColor(color);
g.fillRect(x, y, 31, 31);
}
}
class BouncingBall {
// Overview: A BouncingBall is a mutable data type. It simulates a
// rubber ball bouncing inside a two dimensional box. It also
// provides methods that are useful for creating animations of the
// ball as it moves.
private int x = 320;
private int y = 598;
public static double vx;
public static double vy;
private int radius = 6;
private Color color = new Color(0, 0, 0);
public void move() {
// modifies: this
// effects: Move the ball according to its velocity. Reflections off
// walls cause the ball to change direction.
x += vx;
if (x <= radius) { x = radius; vx = -vx; }
if (x >= 610-radius) { x = 610-radius; vx = -vx; }
y += vy;
if (y <= radius) { y = radius; vy = -vy; }
if (y >= 605-radius) { y = 605-radius; vy = -vy; }
}
public void randomBump() {
// modifies: this
// effects: Changes the velocity of the ball by a random amount
vx += (int)((Math.random() * 10.0) - 5.0);
vx = -vx;
vy += (int)((Math.random() * 10.0) - 5.0);
vy = -vy;
}
public void paint(Graphics g) {
// modifies: the Graphics object <g>.
// effects: paints a circle on <g> reflecting the current position
// of the ball.
// the "clip rectangle" is the area of the screen that needs to be
// modified
Rectangle clipRect = g.getClipBounds();
// For this tiny program, testing whether we need to redraw is
// kind of silly. But when there are lots of objects all over the
// screen this is a very important performance optimization
if (clipRect.intersects(this.boundingBox())) {
g.setColor(color);
g.fillOval(x-radius, y-radius, radius+radius, radius+radius);
}
}
public Rectangle boundingBox() {
// effect: Returns the smallest rectangle that completely covers the
// current position of the ball.
// a Rectangle is the x,y for the upper left corner and then the
// width and height
return new Rectangle(x-radius, y-radius, radius+radius+1, radius+radius+1);
}
}
Take a look at the classes that implement the Shape interface. There are ellipses and other shapes, and they all implement a intersects(Rectangle2D) method. It might help you if you don't want to perform intersection yourself.
As for dealing with the collision, well, it depends on the level of accuracy you want. Simply deflecting the ball of edges is quite easy. Just determine whether the collided side of the rectangle is vertical or horizontal, and negate the corresponding velocity component accordingly. If you want to handle the corners, well that is a bit more complicated.
You need to detect when the ball has collided with the bumper. You have the boundingBox() method of BouncingBall, this will get you a rectangle that contains your ball. So you need to check if this rectangle intersects your square bumper (which implies a collision), and then do something with that.

How to find distance to / detect mouseover on scaled shapes in Processing

In Processing (2) I am currently creating a Java class diagram in a UML-ish sort of style. Classes, Interfaces and the like are represented as rectangles, created using processing's rect() method. A class is created for each rectangle to be displayed storing information about it, with a display() method which draws the rect.
In order to implement zooming in and out of this diagram (to facilitate very large or very small projects), I have added code which changes a scale variable each time the mousewheel is scrolled in and out. The code then uses Processing's scale() method each time the class rectangles, etc, are drawn.
I am also attempting to detect when one of these rectangles is moused over. This is currently done with the following code inside the class representing a rectangle:
//Checks to see if a mouse X and Y (posX and posY) position is inside the rectangle.
public boolean positionCollides(int posX, int posY) {
boolean xCollides = false, yCollides = false;
if((centreX + (width/2) >= posX) && (centreX - (width/2) <= posX)){
xCollides = true;
}
if((centreY + (height/2) >= posY) && (centreY - (height/2) <= posY)){
yCollides = true;
}
if(xCollides && yCollides){
return true;
}
else{
return false;
}
}
Where mouseX and mouseY are fed into that method. Note in this code centreX and centreY are variables which contain(ed) the co-ordinates of the centre of the rectangle when it was first created.
However, when I zoom in and the scaling is applied to the rectangle's display() method, the mousing over breaks - presumably because the things are displayed at slightly different X and Y co-ordinates and it's still checking the old ones.
Is there a way I can change my above positionCollides method to help it deal with the result of the scaling? How can I get this sorted?
I've attempted to sort this by putting the code which calls positionCollides after the scale() call in the display method (in an attempt to get the mouseX and mouseY values to scale as well), and by multiplying mouseX and mouseY by the scale (ie 0.9, 1.1) to try and get them to the correct values.
Perhaps there's a way I can alter the object's centreX and centreY dynamically?
Thanks for reading my wall of text.
tl;dr - How can I detect if the mouse pointer is inside a shape/rectangle which has been scaled in Processing?
Here, try this:
(tested in processing 1.5)
int x, y, sz;
float factor = 0.87;//any value here
float transx = 50;//any value here
float transy = 25;//any value here
void setup()
{
size(400, 400);
x=100;
y=100;
sz=50;
}
void draw()
{
noFill();
//draw at original positon, no fill
rect(x, y, sz, sz);
scale(factor);
translate(transx, transy);
fill(255);
//draw after scalling and positioning filled this is tested for insidness
rect(x, y, sz, sz);
if ( mouseX / factor - transx > x &&
mouseX / factor - transx < x+sz &&
mouseY / factor - transy > y &&
mouseY / factor - transy < y+sz)
{
println("i'm inside!!!");
}
else
{
println("i'm outside");
}
}

Rotate Rectangle in Java

I need to create rectangles that are rotated around their center (so they don't need to be parallel to the axes of the coordinate system). So basicelly each rectangle can be defined by center-X, center-Y, width, height and angle. What I want to do then is to perform calculations on whether certain points are contained in these rectangles or not (so no drawing will be involved). I guess I cant use the Rectangle2D class because these rectangles will always be parallel to the x and y-axis of the coordinate system. Is the only way to get this functionality by writing my own rectangle class or is there anything existing (similar to Rectangle2D) I can use?
Rotate all the points you want to test and use contains(Point) method of the Rectangle2D as Mihai did.
But if you really want to rotate the rectangles you can do it like this (this is the integer version but probably you can do it with Rectangle2D aswell :)).
public class TestRotate {
public static void main(String... args) {
Rectangle r = new Rectangle(50, 50, 100, 100);
Point check = new Point(100, 151); // clearly outside
System.out.println("first: " + r.contains(check));
AffineTransform at = AffineTransform.getRotateInstance(
Math.PI/4, r.getCenterX(), r.getCenterY());
Polygon p = new Polygon();
PathIterator i = r.getPathIterator(at);
while (!i.isDone()) {
double[] xy = new double[2];
i.currentSegment(xy);
p.addPoint((int) xy[0], (int) xy[1]);
System.out.println(Arrays.toString(xy));
i.next();
}
// should now be inside :)
System.out.println("second: " + p.contains(check));
}
}
You can use Rectangle2D to check for containment, if instead of rotating your rectangle by an angle, say, counterclockwise, you rotate each of the points you need to check by the same angle clockwise, relative to the center of the rectangle. Something like
double dx = point.x - rectangleCenter.x;
double dy = point.y - rectangleCenter.y;
double newX = rectangleCenter.x - dx*Math.cos(angle) + dy*Math.sin(angle);
double newY = rectangleCenter.x - dx*Math.sin(angle) - dy*Math.cos(angle);

Categories