I have a bullet class and an algorithm that will move my bullet to where I pressed, but how would I have the bullet continuing on past the mouse_x and mouse_y when it was clicked?
In My Update method:
float xSpeed = (MoveToX - x) / 9;
float ySpeed = (MoveToY - y) / 9;
this.x += xSpeed;
this.y += ySpeed;
And this is when I first create the bullet:
Bullet(int Mx, int My){
c = Color.red;
MoveToX = Mx;
MoveToY = My;
MoveToX += Board.cam.camX;
MoveToY += Board.cam.camY;
Mx is the mouses x when it was clicked. Same with the y.
Edit:
This is my final product: everything works as it should
Bullet(int Mx, int My){
c = Color.red;
MoveToX = Mx + Board.cam.camX;
MoveToY = My + Board.cam.camY;
int speed = 5;
float distance = (float) Math.sqrt(Math.pow(MoveToX - x, 2) + Math.pow(MoveToY - y, 2));
amountToMoveX = (((MoveToX - x) / distance) * speed);
amountToMoveY = (((MoveToY - y) / distance) * speed);
}
public void update(){
x += amountToMoveX;
y += amountToMoveY;
}
The instance variables of your bullet shouldn't be moveTo_, but velocity and direction.
Calculate the direction (i.e. the angle) in the constructor, from the bullet position and the target position. velocity may also be a static constant, depending on your use case.
If it is an option, I would strongly recommend to use a physics- or game-engine. Those kind of problems were already solved a hundred times in those engines. They relieve you from those basic tasks and help you concentrate on your actual problem.
Related
I am unable to create several instances of the waveClock object even though I have put it in an array and marked the centre positions for each object. I would like to create 4 objects in one window, all responding to different sound frequencies/beat onsets etc
Could someone shed some light on how to go about this? I believe it may be an issue with the centerX and centerY variables in the waveClock class
ArrayList<waveClock> waveClocks = new ArrayList<waveClock>();
//global variables
float angnoise, radiusnoise;
float xnoise, ynoise;
float angle = -PI/6;
float radius;
float strokeCol = 254;
int strokeChange = -1;
int speed; //changes speed of visualisation once beat is detected?
void setup()
//for every waveClock we need 180 pixels width, then add 20 pixels for first gap
size(740, 650);
background(255);
//code is called
waveClocks.add(new waveClock(100, height/2, minRadius, bassColour, lowBassBand, highBassBand, numberOfLowOnsetsThreshold));
waveClocks.add(new waveClock(280, height/2, minRadius, midColour, lowMidBand, highMidBand, numberOfMidOnsetsThreshold));
waveClocks.add(new waveClock(460, height/2, minRadius, highColour, lowHighBand, highHighBand, numberOfHighOnsetsThreshold));
waveClocks.add(new waveClock(640, height/2, minRadius, veryHighColour, lowVeryHighBand, highVeryHighBand, numberOfVeryHighOnsetsThreshold));
//set the min and max radius of each of the viz circles
/* for (int i = 0; i < waveClocks.size(); i++) {
//go through the arraylist of waveClocks and set the min and max radius of each circle
waveClocks.get(i).setMinMaxRadius(minRadius, maxRadius);
}*/
song.play();
beat = new BeatDetect(song.bufferSize(), song.sampleRate());
bl = new BeatListener(beat, song);
}
void draw() {
//clear the screen by painting it black
//background(0);
for (int i = 0; i < waveClocks.size(); i++) {
//has there been a beat in the range? get(circle ID).low band, high band etc.
if (beat.isRange(waveClocks.get(i).getLowBand(), waveClocks.get(i).getHighBand(), waveClocks.get(i).getOnsetThreshold())) {
waveClocks.get(i).setMaxRadius();
}
//waveClocks.get(i).drawCircle();
waveClocks.get(i).drawWaveClock();
}
}
waveClock class in a separate tab
//class is an architecture blueprint
//objects are the actual buildings built from the methods (can make as many as you like)
//constructor is the builder/constructor literally
class waveClock {
float centerX; //co-ordinates of circle's position
float centerY; //co-ordinates of circle's position
float radius; //avg radius
// float minRadius; //smallest size it can be
// float maxRadius; //biggest size it can be
color col; //colour
int onsetThreshold; //
int lowBand; //looks at lowest band of frequency and makes circle sensitive to it
int highBand; //looks at highest band of frequency and makes circle sensitive to it
boolean onset; //has there been an onset (beat has occurred or not?)
//the constructor
waveClock(float x, float y, float r, color c, int lb, int hb, int t) {
centerX = x;
centerY = y;
radius = r;
col = c;
lowBand = lb;
highBand = hb;
onsetThreshold = t;
}
void drawWaveClock() {
radiusnoise += 0.005;
radius = (noise(radiusnoise)*350) + 1;
angnoise += 0.005;
angle += (noise(angnoise)*6) - 3;
if (angle > 360) {
angle -= 360;
} else if (angle < 0) {
angle += 360;
}
xnoise += 0.01;
ynoise =+ 0.01;
float centerX = width/2 + (noise(xnoise)*100) - 50;
float centerY = height/2 + (noise(ynoise)*100) - 50;
float rad = radians(angle);
float x1 = centerX + (radius*cos(rad));
float y1 = centerY + (radius*sin(rad));
float opprad = rad + PI;
float x2 = centerX + (radius*cos(opprad));
float y2 = centerY + (radius*sin(opprad));
strokeCol += strokeChange;
if (strokeCol > 354) {
strokeChange = -1;
} else if (strokeCol < 0) {
strokeChange = 1;
}
stroke(strokeCol, 60);
strokeWeight(1);
line(x1, y1, x2, y2);
}
}
You aren't ever using the class-level centerX and centerY variables. Instead, you're recalculating a new centerX and centerY in the drawWaveClock() function.
float centerX = width/2 + (noise(xnoise)*100) - 50;
float centerY = height/2 + (noise(ynoise)*100) - 50;
These are all drawn from the center of the screen, so the waves will end up in the same position.
In the future, please try to narrow your problem down to a MCVE that demonstrates the problem. Also please use proper naming conventions- classes start with an upper-case letter, for example. Good luck.
I am having an annoying problem trying to resize a draggable square in Java. To resize the square I am checking to see if the mouse cursor is inside a rectangular area surrounding the bottom right hand corner of the square - if it is, then the square resizes when I drag the mouse. This code works fine, BUT if I then click on the square to drag it around the screen, it jumps back to the default size of 100 x 100.
My class starts off like this:
public class DragPanel extends JPanel implements MouseListener,
MouseMotionListener, MouseWheelListener
{
Graphics2D g2;
Rectangle2D square;
Color colour;
double x1, y1, x2, y2, sizex, sizey;
double offsetX, offsetY;
double oldx, oldy;
boolean dragging = false;
boolean resizing = false;
public DragPanel()
{
x1 = 10.0;
y1 = 10.0;
sizex = 100.0;
sizey = 100.0;
x2 = x1 + sizex;
y2 = y1 + sizey;
square = new Rectangle2D.Double(x1, y1, sizex, sizey);
colour = Color.BLUE;
setFocusable(true);
addMouseListener(this);
addMouseMotionListener(this);
addMouseWheelListener(this);
this.requestFocus();
}
Here are my Mouse Pressed and Mouse Dragged Methods:
Mouse Pressed:
#Override
public void mousePressed(MouseEvent ev)
{
double mx = ev.getX();
double my = ev.getY();
if (mx > x1 && mx < x2 && my > y1 && my < y2)
{
dragging = true;
offsetX = mx - x1;
offsetY = my - y1;
}
if (mx > x2 - 3 && mx < x2 + 3 && my > y2 - 3 && my < y2 + 3)
{
oldx = mx;
oldy = my;
resizing = true;
}
}
Mouse Dragged:
#Override
public void mouseDragged(MouseEvent ev)
{
if (dragging)
{
double mx = ev.getX();
double my = ev.getY();
x1 = mx - offsetX;
y1 = my - offsetY;
x2 = x1 + sizex;
y2 = y1 + sizey;
square = new Rectangle2D.Double(x1, y1, sizex, sizey);
repaint();
}
if (resizing)
{
double mx = ev.getX();
double my = ev.getY();
double diffx, diffy;
diffx = oldx - mx;
diffy = oldy - my;
square = new Rectangle2D.Double(x1, y1, sizex - diffx, sizey - diffy);
repaint();
}
}
The code you see above does what I want it to do in terms of resizing, but as I already explained, DOESN'T work properly when I try and drag the square after resizing. And I know why - it is because of THIS line:
square = new Rectangle2D.Double(x1, y1, sizex - diffx, sizey - diffy);
So my solution was to change the last part of the if (resizing) block as follows:
diffx = oldx - mx;
diffy = oldy - my;
sizex -= diffx;
sizey -= diffy;
square = new Rectangle2D.Double(x1, y1, sizex, sizey);
repaint();
When I do this however, the thing stops working! I can still drag the square, but if I try and resize, the movement is erratic and extreme.
WHAT am I doing wrong?
Seems to me that the conditions for dragging and resizing are not mutually exclusive, particularly close to the borders. Assuming you are putting these two flags to false on mouse release, a single mouse click or move could still go into both modes at once.
I would put else if (mx > x2 - 3 && mx < x2 + 3 && my > y2 - 3 && my < y2 + 3) and else if (resizing) to avoid any intended consequences. This would make any dragging a priority over any resizing.
Being a graphical thing, hard to say if this is your problem (or part of it), but give it can't hurt to clear this up.
Edit: Of course, you might want to do the resize conditions take priority over (go before) the drag condition, since the area for resizing is much smaller than the area for dragging.
Edit 2: BTW, when you resize you are modifying your square, but not your sizex and sizey variables. Naturally, when you ask for those values when dragging they are the same as before (100). Store the changes and it should work. On that note, it is probably a bad idea to have multiple representations of the same information. It causes redundancies and synchronization issues like this one. If possible, remove these variables: double x1, y1, x2, y2, sizex, sizey; and read/write then from the current state of square (you probably don't need a new square every time either).
I treat these a two separate functions:
Check out the Component Mover
and the Component Resizer
The code in these classes is more complex than you need but you may want to consider the separation of the logic for each function in your final solution.
I found the solution, or rather, I found a solution. I changed my if (resizing) statement within the mouseDragged method as follows:
Old:
if (resizing)
{
double mx = ev.getX();
double my = ev.getY();
double diffx, diffy;
diffx = oldx - mx;
diffy = oldy - my;
square = new Rectangle2D.Double(x1, y1, sizex - diffx, sizey - diffy);
repaint();
}
New:
if (resizing)
{
double mx = ev.getX();
double my = ev.getY();
x2 = mx - rOffX;
y2 = my - rOffX;
sizex = x2 - x1;
sizey = sizex;
square.setRect(x1, y1, sizex, sizey);
repaint();
}
I can't understand the http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm enough to write it in Java (I'm in 8th grade). From a starting point, I need to get a point toward a destination point. I have found several forum posts but no examples in Java.
I tried this (inside my Vector2 class):
public Vector2 getNextPointTowardOther(Vector2 dest, int speed) {
if (dest == null)
return this;
double deltaX = dest.getX() - this.x;
double deltaY = dest.getY() - this.y;
double direction = Math.atan(deltaY / deltaX);
double x = this.x + (speed * Math.cos(direction));
double y = this.y + (speed * Math.sin(direction));
return new Vector2(x, y);
}
But it never returns a negative x or y coordinate, and it just doesn't seem to be altogether accurate.
In order to move towards a certain destination point by a certain amount, you have to compute the direction from the current point towards the target point, and multiply this direction with the speed that you want to use, before adding it to the original point:
public Vector2 getNextPointTowardOther(Vector2 dest, int speed) {
if (dest == null)
return this;
double deltaX = dest.getX() - this.x;
double deltaY = dest.getY() - this.y;
// Compute the distance
double distance = Math.sqrt(deltaX*deltaX+deltaY*deltaY);
// Compute the (normalized) direction
double dirX = deltaX / distance;
double dirY = deltaY / distance;
// (The vector (dirX, dirY) now has length 1.0)
double x = this.x + speed * dirX;
double y = this.y + speed * dirY;
return new Vector2(x, y);
}
im tring to animate motion of the mouse from 1 button to another in an array with the class robot.
here are the two methods I used:
public void optimusprime(int row, int column, JButton current) throws InterruptedException {
Point p;
Point p2;
double x;
double y;
double x2;
double y2;
double conx = 0;
double m;
double b;
double cony;
p = current.getLocationOnScreen();
x = (int)( p.getX() + 30.5);
y = (int)( p.getY() + 30.5);
optimus((int) x, (int) y);
p2 = mesa[row][column].getLocationOnScreen();
x2 = (int) (p2.getX() + 30.5);
y2 = (int) (p2.getY() + 30.5);
m = (y2 - y) / (x2 - x);
b = y - (m * x);
while (conx != x2) {
conx = x;
cony = (m * conx) + b;
optimus((int) conx, (int) cony);
conx++;
Thread.sleep(500);
}
}
public void optimus(int x, int y) {
try {
Robot robot = new Robot();
robot.mouseMove(x, y);
} catch (AWTException e) {
}
}
can any 1 help me here or at least give a recommendation?. got stock in an endless loop(had to shutdown the pc) and it didnt work at all; Im new to java it could be several stupid mistakes ;
The problem may be that your conx never truly equals your x2 because you're doing all your math as doubles. That would mean that conx would go from being slightly less than x2 to being slightly greater than x2 and would either bounce back and forth between the two or would continue moving along its current trajectory. You will want to add some logic to make sure you don't step over your target, which you could do by setting a threshold for once it's close enough or by stopping as soon as you over step it.
Maybe a beginner question, but thank you for reading. I'm working on a 2d Java game in which I have missiles that track the position of an object using the following code. I'd like the missiles to stop homing when they reach a certain minimum displacement from their target, at which point they should fall straight down. Right now, the homing behavior turns off whenever the missile is within the minimum displacement, and turns on again if the displacement increases. I'd like the behavior to turn off only once, staying off for the remainder of the missile's lifespan. How can I accomplish this?
public void home(int targetX, int targetY, int scale){
int dy = targetY - y;
int dx = targetX - x;
double speed, sep;
sep = Math.sqrt(dx * dx + dy * dy);
speed = scale/sep;
if(dy > 50 || dx > 50){
x += dx * speed;
y += dy * speed;
}
else{
x += 0;
y += scale;
}
}
Add a member variable, such as boolean homing = true. Then, change your conditional to something like the following:
if (dy < 50 && dx < 50)
homing = false;
if(homing){
x += dx * speed;
y += dy * speed;
}
else{
x += 0;
y += scale;
}
You basically just need to break the mutual dependence between you missile's behaviour and its state.