My problem might be simple. I've spent most of today thinking of an algorithm(That will pretty probably be a couple if statements) that will determine the direction the mouse is pointing and shoot a bullet in that direction. I already tested the bullets to make sure they shoot by shooting in a defined direction.
how would i go about calculating if the mouse is on the left side of the player, the right side,top side, bottom side, or if it's on the corners of the player ?
Solved: Thanks for all your help but after a day of thinking I came up with a way my self. What I did is use the if statements to determine when I press the mouse down, is it going to be colliding with the top part of the player,bottom,right,left,or corners. Anyway, here is my code. P.S. I used the variable x1 as the mousex, y1 as mousey, x as playerx, and y as player y. The only other variable I have is dx and dy but you should know what those do.
//top
if (x1 > x && x1 < x + 40 && y1 > y - 250 && y1 < y){
dy = -1;
dx = 0;
}
//right
if (x1 > x + 40 && x1 < x + 250 && y1 > y && y1 < y + 40){
dx = 1;
dy = 0;
}
//bottom
if (x1 > x && x1 < x + 40 && y1 > y+40 && y1 < y+250){
dy = 1;
dx = 0;
}
//left
if (x1 < x && x1 > x - 250 && y1 > y && y1 < y + 40){
dx = -1;
dy = 0;
}
//top right corner
if (x1 > x + 40 && x1 < x + 250 && y1 > y - 250 && y1 < y){
dx = 1;
dy = -1;
}
//top left corner
if (x1 < x && x1 > x - 250 && y1 > y - 250 && y1 < y){
dx = -1;
dy = -1;
}
//bottom right corner
if (x1 > x + 40 && x1 < x + 250 && y1 > y + 40 && y1 < y + 250){
dx = 1;
dy = 1;
}
//bottom left corner
if (x1 < x && x1 > x - 250 && y1 > y + 40 && y1 < y + 250){
dx = -1;
dy = 1;
}
You have to implement Mouse move actionlistener if you want to implement shooting while the mouse button is pressed.
Simple equation of line will do it.
Solution: Get the initial point (x0,y0) when button is pressed. While mouse moves when pressed, get (x1,y1) point where the mouse is moving (this constantly changes) - get the line equation - (you have 2 points so find slope and then use one point to get the equation of the line).
Now the direction the bullet fires is the perpendicular to this line through (x1,y1). So you can find the equation of this perpendicular line when the other equation is known. Now to know whether it has to be fired up or down is relative to finding out which side the gun is pointed (direction be stored in a variable)
After all this, when mouse still moves, old point will now be (x1,y1) and new point will be (x2,y2) and you keep implementing these changes.
Related
What I'm trying to do is take 2 mouceclick input which gives me pixel coordinate x[0],y[0] and x[1],y[1]. Then I get a queue of array containing pixels coordinate of every pixel where the line joining these points would make. Don't need the line to be seen at all.
I decided to take the slope prospective such that 1 pixel change in x coordinate would change
(x[1]-x[0])]/(y[1]-y[0]) in y coordinate. I keep getting arithmetic error.
Edit: Used the DDA algorithm and still getting / by zero error even if all values is pre-asigned to something non-zero.
Queue<int[]> queue=new LinkedList<int[]>();
int dx = Math.abs(x[1] - x[0]);
int dy = Math.abs(y[1] - y[0]);
int sx = (x[0] < x[1]) ? 1 : -1;
int sy = (y[0] < y[1]) ? 1 : -1;
int err = dx / dy;
int[] tog= {x[0],y[0]};
queue.add(tog); //1st pixel into queue. nothing else
while(true) {
if (x[0] == x[1] && y[0] == y[1]) {
break;
}
int e2 = 2 * err;
if (e2 > -dy) {
err = err - dy;
x[0] = x[0] + sx;
}
if (e2 < dx) {
err = err + dx;
y[0] = y[0] + sy;
}
tog[0]= x[0];
tog[1]= y[0];
queue.add(tog);
}
System.out.println(queue);
Thanks to the comment on using DDA, the problem I got is now fixed. I have used the following code for the counting of the pixels and storing their coordinates.
I put this code inside the action listener for a mouse click.
private void counter() {//---------counter takes arguments x and y which are array that contain x1x2 and y1y2 coordinates of 1st and 2nd click
int dx = (x[1] - x[0]);
int dy = (y[1] - y[0]);//---------makes it applicable for both inclinations (if we add up there a math.abs it would work on only the positive inclination line )
step = Math.abs(dx) > Math.abs(dy) ? Math.abs(dx) : Math.abs(dy);
//------counts howmany pixels are to be recorded
float Xinc = dx / (float) step;//----slope change with respect to x axis
float Yinc = dy / (float) step;//----slope change with respect to y axis
tog= new int[step][3];
tog[0][0]=x[0]; tog[0][1]=y[0];
tog[0][2]= (black[0]!=0) ? 1 : 0;//------------Tertiary operator where the condition is true, then while is true
//---------------------------------------------------------------send value of x1 and y1 to listOfCoordinates
float xt=x[0],yt=y[0]; int i=0, j=1;
//-------------to get all the coordinates between the 2 points1111
System.out.println(tog[0][0]+" "+tog[0][1]+" "+tog[0][2]);
while (j<step){
if(i==2) i=0;
xt += Xinc;
yt += Yinc;
tog[j][i] = (int)xt;//------tog is the array where you store the coordinates of each pixel that overlaps the line made if the clicked points are connected
tog[j][i+1] = (int)yt;
j++;
}
//-------print tog here to see if it has the coordinates or not for check
}
I'm having a lot of trouble figuring out what is wrong with my code. Actually, I'm having a very difficult time solving the problem of two rectangles overlapping. The following code should, theoretically, work for the following rectangles:
Rect1: (2.5, 4) width = 2.5, height = 43
Rect2: (1.5, 5) width = 0.5, height = 3
Keep in mind I can't use the Rectangle class to solve this problem. What I've done is calculated the x-values for the left and right edges and the y-values for the top and bottom edges of both rectangles.
I'm first considering -- and I know this does not cover all possible cases -- the scenario in which r2 is within r1.
Note that (x1, y1) and (x2, y2) signify the centers of rectangles 1 and 2, respectively.
right1 = x1 + w1/2;
left1 = x1 - w1/2;
bottom1 = y1 - h1/2;
top1 = y1 + h1/2;
right2 = x2 + w2/2;
left2 = x2 - w2/2;
bottom2 = y2 - h2/2;
top2 = y2 + h2/2;
overlap = ( (right2 < right1 && right2 > left1) &&
(bottom2 > bottom1 && bottom2 < top1) &&
(left2 > left1 && left2 < right1) &&
(top2 < top1 && top2 > bottom1) );
Again, I realize this scenario is not all-encompassing. But even at this point with testing if one rectangle is within another using the above Rect1 and Rect2 values for input, overlap evaluates to false...but it shouldn't -- I've done the math and suggests that the code should work. What did I do wrong?
Rectangles will be overlapping if there is some intersection between both their horizontal and vertical sides - so basically it's a case of checking whether two lines overlap for each dimension.
The check whether a line x1 -> x2 overlaps a line x3 -> x4 is whether the first line starts before the end of the second and ends after its start, or in code:
x1 <= x4 && x2 >= x3
To translate this to rectangles, apply the test to both dimensions:
(x1 <= x4 && x2 >= x3) && (y1 <= y4 && y2 >= y3)
..where one rectangle is x1,y1 -> x2,y2 and the other is x3,y3 -> x4,y4 (easily calculated from a start position and a width).
I will keep this quick.
Just making a processing program where the ball bounces off the rectangle.
At the moment I can only figure out how to do the top,left,right and bottom sides but when the ball goes into the corners of the rectangle, it doesn't bounce off but instead goes into the rectangle and after 1 or 2 bounces gets realeased.
I just really want to know how I should go about making the ball deflect off the corners of the rectangle so it doens't glitch
Here is my code :
float x = 100, y = 100, radius = 50;
float vx = 3, vy = 3;
float MX = 0;
float MY = 0;
void setup() {
size(500, 700);
}
void draw() {
background(0);
fill(255);
x += vx;
y += vy;
if (x + radius > width) {
vx = vx * -1;
}
//makes the ball bounce off the right
if (x - radius < 0) {
vx = vx * -1;
}
//makes the ball bounce off the left
if (y + radius > height) {
vy = vy * -1;
y = height - radius;
}
//make the ball bounce off the top
if (y - radius < 0) {
vy = vy * -1;
y = radius;
}
//makes the ball bounce off the top
if (y + radius > MY && x + radius > MX + 50 && x + radius < MX + 150 &&
y + radius < MY + 20) {
vy *= -1;
y = MY - 3 - radius;
} //Top Side
if (x - radius < MX + 100 && y > MY - 10 && y < MY + 10 && x - radius > MX) {
vx *= -1;
} // Right Side
if (y - radius < MY + 20 && x + radius > MX + 50 && x + radius < MX + 150 &&
y - radius > MY) {
vy *= -1;
y = MY + 20 + radius;
} //Bottom Side
if (x + radius > MX && y > MY - 10 && y < MY + 10 && x + radius < MX + 100) {
vx *= -1;
} // Left Side
ellipse(x, y, radius * 2, radius * 2);
rect(MX, MY, 100, 20);
}
void mouseMoved() {
MX = mouseX - 50;
MY = mouseY - 10;
if (MX < 0) {
MX = 0;
}
if (MX > 400) {
MX = 400;
}
if (MY < 0) {
MY = 0;
}
if (MY > 680) {
MY = 680;
}
Sorry I do know know how to insert the code very well, I am new to this site, please have mercy haha :)
Cheers
The problem is not that you need to detect corner collision. You've got two other problems:
Problem 1: When you detect a collision, you need to move the ball so it's not colliding with the rectangle anymore.
If you don't, then when the ball intersects the top of the box, you multiply the vy variable by -1. That causes the circle to start moving up. But the next frame, the circle is still colliding with the rectangle, because it hasn't moved up enough yet. So your code detects that collision, multiples vy by -1 again, and the ball moves back down. Next frame the same thing happens, until the ball eventually stop colliding with the rectangle.
Slow the framerate down to see what I'm talking about:
To fix this, you need to "pop" the ball back to a location that's no longer intersecting with the rectangle. That way you know it won't still be colliding in the next frame.
Problem 2: You shouldn't do collision on each side separately. Instead, do collisions between the entire circle and the entire rectangle, and then check one axis of movement at a time.
Checking against one side at a time will lead to plenty of headaches, including the problem where multiple sides are hit at one time. I would also bet that your code isn't doing what you think it is: try adding println() statements to all of your if statements to make sure they're executing when you think they are.
To fix this problem, I would create a collides() function that takes parameters for the next position of the ball, and returns whether the ball will be colliding with any side of the rectangle. Then pass in the next X and Y positions and flip their speeds. It'll look something like this:
if (collides(circleX + vx, circleY)) {
vx*=-1;
}
else {
circleX += vx;
}
if (collides(circleX, circleY + vy)) {
vy*=-1;
}
else {
circleY += vy;
}
You'd also want to add the logic for "popping" the ball so it's no longer colliding.
PS: Did you try searching for your problem on google or the Stack Overflow search? This question is almost an exact duplicate of your question, to the point where I'm pretty sure you're in the same class!
A quick dirty way i have previously achieved this is by first adding bounding boxes to each side and positioning them in a way that if the ball collides with for example on the top right corner i would then have a condition:
If ball intercepts bounds top and bounds right: do this;
I hope this helps!
I am trying to make a small program that will move the mouse from the current position to the given position. Here is a method that i can use which will move the mouse from one point to another but without animation:
moveMouse(int x, int y);
This will move the mouse from the current coordinates to x,y on screen without animation. Now my job is to move the mouse to that coordinate, but it should also show the mouse moving one pixel at a time. I need to create a loop which moves the mouse cursor few pixels x and y at a time so that Here is what i have been thinking:
public void moveMouseAnimation(x,y){
//Integers x2 and y2 will be the current position of the mouse cursor
boolean isRunning = true;
while(isRunning){
delay(10); // <- 10 Milliseconds pause so that people can see the animation
x2 -= 1;
y2 -= 1;
moveMouse(x2,y2);
if(x2 == x && y2 == y) isRunning = false; //Ends loop
}
}
Now i need to find correct x2 and y2 values so that the mouse moves in a straight line and reaches x and y at last. Could someone help me.
You want the Bresenham's line algorithm. It is commonly used to draw a line between two points, but you, instead of drawing a line, will move the mouse along it.
Below is the code to do that. This code uses Bresenham Line Algo. For more ref on soln try http://en.wikipedia.org/wiki/Bresenham's_line_algorithm if you are looking not to have jagged lines
boolean steep = Math.abs(y1 - y0) > Math.abs(x1 - x0);
if (steep) {
int t;
// swap(x0, y0);
t = x0;
x0 = y0;
y0 = t;
// swap(x1, y1);
t = x1;
x1 = y1;
y1 = t;
}
if (x0 > x1) {
int t;
// swap(x0, x1);
t = x0;
x0 = x1;
x1 = t;
// swap(y0, y1);
t = y0;
y0 = y1;
y1 = t;
}
int deltax = x1 - x0;
int deltay = Math.abs(y1 - y0);
int error = deltax / 2;
int ystep;
int y = y0;
if (y0 < y1)
ystep = 1;
else
ystep = -1;
for (int x = x0; x < x1; x++) {
if (steep)
moveMouse(y, x);
else
moveMouse(x, y);
error = error - deltay;
if (error < 0) {
y = y + ystep;
error = error + deltax;
}
}
The problem that you are attempting to solve is that of linear interpolation, in that you have a linear function, that of a line between the starting point (x0, y0) and the ending point (x1, y1).
Luckily the solution is simple. The Wikipedia article gives examples almost exactly what you're trying to do.
http://en.wikipedia.org/wiki/Linear_interpolation
You could interpolate a straight line....basically fitting y=mx+b to the given points.
I'm trying to move a sprite across the screen in a straight line, towards on the location where've I touched the screen, what i did was upon the update() in each loop , it checks to see if the current sprite's location x y is == to the destination x ,y . if it hasn't sprite's x++ and y++...
the thing is ..it ain't moving in a straight line... as there are cases where the x or y coordinate reaches the destination x or y first... how do i changed it so that the both x and y meets the destination together?
my current pseudo code for the sprite object
destX = destination X
destY = destination Y
posX = current X
posY = current Y
public void update(){
if(destX > posX && destY < posY)
{
posX++;
posY--;
}
else if (destX > posX && destY > posY){
posX++;
posY++;
}
else if(destX < posX && destY > posY)
{
posX--;
posY++;
}
else if(destX < posX && destY < posY){
posX--;
posY--;
}
else if(destX < posX)
posX--;
else if(destX > posX)
posX++;
else if(destY < posY)
posY--;
else if(destY > posY)
posY++;
Check out: http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
This simple algorithm will tell you each X,Y coordinate on a line between two points. You could use this algorithm to compute all of the positions it needs to visit, store the coordinates in an array, and iterate over the array as you update the position.
From the Article:
function line(x0, x1, y0, y1)
int deltax := x1 - x0
int deltay := y1 - y0
real error := 0
real deltaerr := abs (deltay / deltax) // Assume deltax != 0 (line is not vertical),
// note that this division needs to be done in a way that preserves the fractional part
int y := y0
for x from x0 to x1
plot(x,y)
error := error + deltaerr
if error ≥ 0.5 then
y := y + 1
error := error - 1.0
This is the most primitive version. The article contains a better generalized algorithm that you should look at.
I am dealing with a similair problem as yours. (I have an arraylist holding the history of positions my player has gone and I want to use that to rewind the game.)
Instead of simply increasing x and y position with 1 you can:
Calculate the angle between the source postion and your destination
position.
Calculate the new direction using a variable which
represents the speed
Update your postion using calculated direction
I made a class of that. I hope it is usefull.
import java.awt.geom.Point2D;
public class MyVelocityCalculator {
public static void main(String[] args) {
Point2D.Double currentPosition = new Point2D.Double();
Point2D.Double destinationPosition = new Point2D.Double();
currentPosition.setLocation(100, 100);
destinationPosition.setLocation(50, 50);
Double speed = 0.5;
Point2D.Double nextPosition = MyVelocityCalculator.getVelocity(currentPosition, destinationPosition, speed);
System.out.println("player was initially at: "+currentPosition);
System.out.println("player destination is at: "+destinationPosition);
System.out.println("half seconds later player should be at: "+nextPosition);
}
public static final Point2D.Double getVelocity(Point2D.Double currentPosition, Point2D.Double destinationPosition, double speed){
Point2D.Double nextPosition = new Point2D.Double();
double angle = calcAngleBetweenPoints(currentPosition, destinationPosition);
double distance = speed;
Point2D.Double velocityPoint = getVelocity(angle, distance);
nextPosition.x = currentPosition.x + velocityPoint.x;
nextPosition.y = currentPosition.y + velocityPoint.y;
return nextPosition;
}
public static final double calcAngleBetweenPoints(Point2D.Double p1, Point2D.Double p2)
{
return Math.toDegrees( Math.atan2( p2.getY()-p1.getY(), p2.getX()-p1.getX() ) );
}
public static final Point2D.Double getVelocity(double angle, double speed){
double x = Math.cos(Math.toRadians(angle))*speed;
double y = Math.sin(Math.toRadians(angle))*speed;
return (new Point2D.Double(x, y));
}
}
Don't use integers. This is a very bad idea to work with ints. Use floats. The main concept is: define the number of steps you want to perform (s). Compute differences in X and Y (diffX and diffY). Don't take absolute values: Compute them this way
float diffX = destX - currentX;
Then compute the xMove and yMove values by dividing diffX and diffY by s (number of steps).
float moveX = diffX / s;
float moveY = diffY / s;
And now you have to add for each iteration the moveX and moveY values to the current position.
And for drawing it, you should use Graphics2D, which supports floating points. If you don't want to use Graphics2D, you can round the floats to ints, using Math.round(float).