I am making a game in libGDX and I am having trouble setting up the Bullet class. I am unable to get the projectiles to go to the mouse location.
I have tried to use Math.atan() to find the angle that I need to fire at but I couldn't get that to work. right now I am just using the distance to find velocity on the x and y-axis.
private static final int SPEED = 500;
private static Texture texture;
String path = "C:\\Users\\minicodcraft\\Downloads\\game\\core\\assets\\";
private float x, y; // starting position
private float xVelocity, yVelocity;
private float yPos; // the y position of the mouse input
private float xPos; // the x position of the mouse input
public Bullet(float x, float y, float yPos, float xPos) {
this.x = x;
this.y = y;
this.xPos = xPos;
this.yPos = yPos;
this.xVelocity = 0f;
this.yVelocity = 0f;
calcDirection();
if (texture == null) {
texture = new Texture(path + "Bullet.png");
}
}
private void calcDirection() {
float xDistanceFromTarget = Math.abs(xPos - x);
float yDistanceFromTarget = Math.abs(yPos - y);
float totalDistanceFromTarget = xDistanceFromTarget + yDistanceFromTarget;
xVelocity = xDistanceFromTarget / totalDistanceFromTarget;
yVelocity = yDistanceFromTarget / totalDistanceFromTarget;
if (xPos < x) {
xVelocity *= -1;
}
if (yPos < y) {
yVelocity *= -1;
}
}
public void update(float deltaTime) {
if (x > 0 && y > 0) {
x += xVelocity * SPEED * deltaTime;
y += yVelocity * SPEED * deltaTime;
} else if (x < 0 && y > 0) {
x -= xVelocity * SPEED * deltaTime;
y += yVelocity * SPEED * deltaTime;
} else if (x > 0 && y < 0) {
x += xVelocity * SPEED * deltaTime;
y -= yVelocity * SPEED * deltaTime;
} else if (x < 0 && y < 0) {
x -= xVelocity * SPEED * deltaTime;
y -= yVelocity * SPEED * deltaTime;
}
}
public void render(SpriteBatch batch) {
batch.draw(texture, x, y);
}
The following code gives a velocity towards the mouse position from the player's position:
float diffX = mouse.x - player.x;
float diffY = mouse.y - player.y;
float angle = (float) Math.atan2(diffY, diffX);
float velX = (float) (Math.cos(angle));
float velY = (float) (Math.sin(angle));
Vector2 velocity = new Vector2(velX, -velY);
velocity.nor();
velocity.scl(magnitudeSpeed);
velocity.scl(deltaTime);
Then velocity.x is the x component of the velocity. Respective for y. No need to multiply by speed and deltaTime again, already done above.
Related
My title probably does not make much sense which is why I am having a bit of an issue googling my problem.
I am trying to move a shape on the screen from one set of X/Y coordinates to another in a direct line.
So for example,
This is the class method for setting the new target direction.
void setTargetPosition(int targetX, int targetY) {
xTar = targetX;
yTar = targetY;
if (xPos > xTar)
xDir = -1;
else
xDir = 1;
if (yPos > yTar)
yDir = -1;
else
xDir = 1;
}
This would set the Direction of the X/Y variables and the following code would move the player on the screen.
void drawPlayer() {
fill(circleColour);
circle(xPos,yPos,35);
//stops player from moving once target destination has been reached
if (xPos == xTar)
xDir = 0;
if (yPos == yTar)
yDir = 0;
xPos += xDir;
yPos += yDir;
}
The above code does work mostly as intended but I need to find a way to proportionally change the X/Y coordinate so that it's more of a 'direct line' to the destination.
Sorry if this does not make sense. I don't know the right terms to use.
You have to use floating point values for the computation of the movement rather than integral values:
float xTar;
float yTar;
float xPos;
float yPos;
setTargetPosition just set xTar and yTar:
void setTargetPosition(float targetX, float targetY) {
xTar = targetX;
yTar = targetY;
}
In drawPlayer you have to compute the direction vector (PVector) from the objects position to the target:
PVector dir = new PVector(xTar - xPos, yTar - yPos);
if the length of the vector (mag()) is greater than 0, the you have to move the object:
if (dir.mag() > 0.0) {
// [...]
}
If you have to move the object, then compute the Unit vector by normalize(). Note, the length of a unit vector is 1. Multiply the vector by a certain speed by mult(). This scales the vector to a certain length. Ensure that the length of the vector is not greater than the distance to the object (min(speed, dir.mag())). Finally add the components of the vector to the position of the object:
dir.normalize();
dir.mult(min(speed, dir.mag()));
xPos += dir.x;
yPos += dir.y;
See the example:
class Player {
float xTar;
float yTar;
float xPos;
float yPos;
color circleColour = color(255, 0, 0);
Player(float x, float y)
{
xTar = xPos = x;
yTar = yPos = y;
}
void setTargetPosition(float targetX, float targetY) {
xTar = targetX;
yTar = targetY;
}
void drawPlayer() {
fill(circleColour);
circle(xPos,yPos,35);
float speed = 2.0;
PVector dir = new PVector(xTar - xPos, yTar - yPos);
if (dir.mag() > 0.0) {
dir.normalize();
dir.mult(min(speed, dir.mag()));
xPos += dir.x;
yPos += dir.y;
}
}
}
Player player;
void setup() {
size(500, 500);
player = new Player(width/2, height/2);
}
void draw() {
background(255);
player.drawPlayer();
}
void mousePressed() {
player.setTargetPosition(mouseX, mouseY);
}
Most learned friends
I have a sprite that moves around on screen but at the moment it just moves diagonally from left to right and goes off screen and then comes back on the other side.
What I would like it to do is bounce off the edges of the screen in a random fashion but, not being all that clued up on maths, I'm struggling to figure out the coordinates to do this.
Below is what I have so far: (this is an updated code for the Sprite class:
public class Sprite {
//x,y position of sprite - initial position (0,50)
// int [] DIRECTION_TO_ANIMATION_MAP = {3, 1, 0, 2};
private static final int BMP_ROWS = 3;
private static final int BMP_COLUMNS = 4;
private int x = 0;
private int y = 0;
private int xSpeed = 5;//Horizontal increment of position (speed)
private int ySpeed;// Vertical increment of position (speed)
private int currentFrame = 0;
private GameView gameView;
private Bitmap spritebmp;
//Width and Height of the Sprite image
private int bmp_width;
private int bmp_height;
// Needed for new random coordinates.
//private Random random = new Random();
public Sprite(GameView gameView) {
this.gameView = gameView;
spritebmp = BitmapFactory.decodeResource(gameView.getResources(),
R.drawable.running_ninja_sprite);
this.bmp_width = spritebmp.getWidth() / BMP_COLUMNS;
this.bmp_height = spritebmp.getHeight() / BMP_ROWS;
/*Random rnd = new Random(System.currentTimeMillis());
xSpeed = rnd.nextInt(45)-5;
ySpeed = rnd.nextInt(25)-5;*/
}
//update the position of the sprite
public void update() {
//if (x < 0 || x > gameView.getWidth() ){ xSpeed = xSpeed * -1;}
//if (y < 0 || y > gameView.getHeight() ){ ySpeed = ySpeed * -1;}
if (x > gameView.getWidth() - bmp_width - xSpeed || x + xSpeed < 0) {
xSpeed = -xSpeed;
}
x = x + xSpeed;
if (y > gameView.getHeight() - bmp_height - ySpeed || y + ySpeed < 0) {
ySpeed = -ySpeed;
}
y = y + xSpeed;
currentFrame = ++currentFrame % BMP_COLUMNS;
//y = random.nextInt(gameView.getWidth());
//wrapAround(); //Adjust motion of sprite.
}
public void draw(Canvas canvas) {
update();
int srcX = currentFrame * bmp_width;
int srcY = 1 * bmp_height; //getAnimationRow()
Rect src = new Rect(srcX, srcY, srcX + bmp_width, srcY + bmp_height);
Rect dst = new Rect(x, y, x + bmp_width, y + bmp_height);
//Draw sprite image
canvas.drawBitmap(spritebmp, x, y, null);
}
/*private int getAnimationRow() {
double dirDouble = (Math.atan2(xSpeed, ySpeed) / (Math.PI / 2) + 2);
int direction = (int) Math.round(dirDouble) % BMP_ROWS;
return DIRECTION_TO_ANIMATION_MAP[direction];
}*/
public void wrapAround() {
//Code to wrap around
if (x < 0) x = x + gameView.getWidth(); //increment x whilst not off screen
if (x >= gameView.getWidth()) { //if gone of the right sides of screen
x = x - gameView.getWidth(); //Reset x
}
if (y < 0) y = y + gameView.getHeight();//increment y whilst not off screen
if (y >= gameView.getHeight()) {//if gone of the bottom of screen
y -= gameView.getHeight();//Reset y
}
}
// Checks if the sprite was touched
public boolean wasItTouched(float ex, float ey) {
boolean touched = false;
if ((x <= ex) && (ex < x + bmp_width) &&
(y <= ey) && (ey < y + bmp_height)) {
touched = true;
}
return touched;
}
}
It now does bounce off the edge but from top left, diagonally to the right and back up in the same direction and continues to do this back and forth. I'd like it to be random in its direction after hitting the edge. Any suggestions? As you can see from the code I have tried a lot of things but the sprite just keeps on doing this continuous back and forth diagonal motion and I'm at a loss as to what I can do.
Thanks
Just negate your speed every time you hit a wall
if (x < 0 || x > gameView.getWidth() ){ xSpeed = xSpeed * -1;}
if (y < 0 || y > gameView.getHeight() ){ ySpeed = ySpeed * -1;}
/////////////////////////////// Edit
It will fit something like this. You can also remove your wrap function as it is no longer applicable
//update the position of the sprite
public void update() {
x = x + xSpeed;
y = y + xSpeed;
bounce();
}
private void bounce(){
if (x <= 0 || x >= gameView.getWidth() ){ xSpeed = xSpeed * -1;}
if (y <= 0 || y >= gameView.getHeight() ){ ySpeed = ySpeed * -1;}
}
I want to create a drawLine function, however I am not able to use any graphics classes (I can set pixels though). I tried this method https://en.wikipedia.org/wiki/Bresenham's_line_algorithm#Method, but this only works when the line is going from top left to bottom right and not for example going from top right to bottom left. Does anyone have a way that does this? The current code I have:
public void drawLine(int startX, int startY, int endX, int endY) {
double deltaX = endX - startX;
double deltaY = endY - startY;
double error = -1;
double deltaError = Math.abs(deltaY / deltaX);
int y = startY;
for (int x = startX; x < endX - 1; x++) {
error += deltaError;
if (error >= 0) {
y++;
error--;
}
drawPixel(x, y);
}
}
Any help is appreciated.
I solved it. The end result is this.
public void drawLine(int startX, int startY, int endX, int endY) {
if (startX > endX && startY > endY) {
int startXCopy = startX;
startX = endX;
endX = startXCopy;
int startYCopy = startY;
startY = endY;
endY = startYCopy;
}
double deltaX = endX - startX;
double deltaY = endY - startY;
double error = -1;
double deltaError = Math.abs(deltaY / deltaX);
if (deltaX == 0) {
for (int y = startY; y < endY; y++)
drawPixel(startX, y);
}
if (deltaY == 0) {
for (int x = startX; x < endX; x++)
drawPixel(x, startY);
}
if (deltaX >= deltaY) {
int y = startY;
int yDirection = endY > startY ? 1 : -1;
for (int x = startX; x < endX - 1; x++) {
error += deltaError;
if (error >= 0) {
y += yDirection;
error--;
}
drawPixel(x, y);
}
} else if (deltaY > deltaX) {
int x = startX;
int xDirection = endX > startX ? 1 : -1;
for (int y = startY; y < endY - 1; y++) {
error += deltaError;
if (error >= 0) {
x += xDirection;
error--;
}
drawPixel(x, y);
}
}
}
To draw a line is a simple Math problem and can be achieved on different ways.
What you need is the basic linear euqation y = f(x) = mx + b
where m is your slope, defined as m=(y2−y1)/(x2−x1), bis your startY value and the x is expressed by x = x_i - startX where x_i is your current point on your line. Then you can compute all y-values for each x_i value on the line between your start point and your end point. The quantity of points depends on a resolution factor.
double slope = (double)(endY - startY) / (endX - startX);
//adjustable resolution factor
double resolution = 1;
double x = startX;
while (x <= endX) {
double y = slope * (x - startX) + startY;
drawPixel(x, y);
x += resolution;
}
Basically I wrote a "Dota like Style" based on the OrthographicCamera from libgdx.
You can test it out for youself here is the class.
I am using this to draw a TiledMap, and I have and array of tiles corresponding with the graphical tiles, however if I move the mouse, and with that the camera.
The coordinates off the mouse and the tiles are completely different.
Gdx.input x and y get their coordinates relative to the screen and not where the mouse is in the world relative to the camera.
I can't figure out a way to get the mouse position relative to the camera, so that if I move the camera I won't just get the regular mouse coordinates, but the actual world coordinates that the camera is showing, and where my mouse is located within the confines of the view of the camera relative to the world.
public class DotaCamera extends OrthographicCamera {
private float xmin;
private float xmax;
private float ymin;
private float ymax;
private float x;
private float y;
private int Width = Gdx.graphics.getWidth();;
private int Height = Gdx.graphics.getHeight();
private int camSpeedMax = 16;
private float camAcceleration = 0.3f;
private int camSpeedSmoother = 3;
private float camVelocityX = 0;
private float camVelocityY = 0;
private float fZoomMax = 1f;
private float fZoomMin = 0.5f;
private float fZoomSpeed = 0.03f;
public DotaCamera() {
this(0, 0, 0, 0);
}
public DotaCamera(float xmin, float xmax, float ymin, float ymax) {
super();
setBounds(xmin, xmax, ymin, ymax);
}
public void setBounds(float xmin, float xmax, float ymin, float ymax) {
this.xmin = xmin;
this.xmax = xmax;
this.ymin = ymin;
this.ymax = ymax;
}
public void setPosition(float x, float y) {
setPosition(x, y, 0);
}
public void setPosition(float x, float y, float z) {
position.set(x, y, z);
this.x = x;
this.y = y;
fixBounds();
}
private void fixBounds() {
if (position.x < xmin + viewportWidth / 2) {
position.x = xmin + viewportWidth / 2;
}
if (position.x > xmax - viewportWidth / 2) {
position.x = xmax - viewportWidth / 2;
}
if (position.y < ymin + viewportHeight / 2) {
position.y = ymin + viewportHeight / 2;
}
if (position.y > ymax - viewportHeight / 2) {
position.y = ymax - viewportHeight / 2;
}
}
/**
* Controls the zoom of the of the camera.
*/
public void updateZoom() {
int mouseWheelMovement = Mouse.getDWheel();
if (mouseWheelMovement > 0) {
if (this.zoom > fZoomMin) {
this.zoom -= fZoomSpeed;
} else {
this.zoom = fZoomMin;
}
}else if(mouseWheelMovement < 0){
if (this.zoom < fZoomMax) {
this.zoom += fZoomSpeed;
} else {
this.zoom = fZoomMax;
}
}
}
/**
* Update And move the Camera DOTA Stylized movement.
*/
public void updateAndMove() {
float dt = Gdx.graphics.getDeltaTime();
int MouseX = Mouse.getX(); // Get MouseX
int MouseY = Height - Mouse.getY(); // Get MouseY
int camSpeedX = 0;
int camSpeedY = 0;
String horizontalDirection = getMoveLeftRight(MouseX); // Get
// horizontalDirection
String verticalDirection = getMoveUpDown(MouseY); // Get
// verticalDirection
/* * * * * * * *
* Decide what to do with the horizontalDirection.
*/
switch (horizontalDirection) {
case "left":
camSpeedX = ((Width / 2) - (MouseX + (Width / 4)))
/ camSpeedSmoother; // Create Speed -X
camSpeedX = ((camSpeedX > camSpeedMax) ? camSpeedMax : camSpeedX); // Limit
// the
// speed.
if (camVelocityX < camSpeedX)
camVelocityX += camAcceleration;
break;
case "right":
camSpeedX = (((MouseX + (Width / 4)) - ((Width / 4) * 3)) - (Width / 4))
/ camSpeedSmoother; // Create speed +X.
camSpeedX = ((camSpeedX > camSpeedMax) ? camSpeedMax : camSpeedX); // Limit
// the
// speed.
if (camVelocityX < camSpeedX)
camVelocityX += camAcceleration; // Accelerate
camSpeedX *= -1; // To negate the speed.
break;
case "":
camVelocityX = 0;
break;
}
/* * * * * * * *
* Decide what to do with the verticalDirection.
*/
switch (verticalDirection) {
case "up":
camSpeedY = (Height / 4) - MouseY; // Create speed -Y
camSpeedY = ((camSpeedY > camSpeedMax) ? camSpeedMax : camSpeedY); // Limit
// the
// speed.
if (camVelocityY < camSpeedY)
camVelocityY += camAcceleration;
camSpeedY *= -1;
break;
case "down":
camSpeedY = (((MouseY + (Height / 4)) - ((Height / 4) * 3)) - (Height / 4))
/ camSpeedSmoother; // Create speed +Y.
camSpeedY = ((camSpeedY > camSpeedMax) ? camSpeedMax : camSpeedY); // Limit
// the
// speed.
if (camVelocityY < camSpeedY)
camVelocityY += camAcceleration;
break;
case "":
camVelocityY = 0;
break;
}
// System.out.println("vX:" +camVelocityX+ "vY: " +camVelocityY+ "sX: "
// +camSpeedX+ "sY: " +camSpeedY);
this.position.x -= (camVelocityX * camSpeedX) * dt;
this.position.y -= (camVelocityY * camSpeedY) * dt;
this.update();
}
/**
* Get the X-Axial Direction.
*
* #param MouseX
* #return Direction
*/
private String getMoveLeftRight(int MouseX) {
if (MouseX + (Width / 4) < Width / 2) {// Needs to move left?
return "left";
} else if (MouseX > (Width / 4) * 3) {// Needs to move right?
return "right";
}
return "";
}
/**
* Get the Y-Axial Direction.
*
* #param MouseY
* #return Direction
*/
private String getMoveUpDown(int MouseY) {
if (MouseY < Height / 4) {// Needs to move up?
return "up";
} else if (MouseY > (Height / 4) * 3) {// Needs to move down?
return "down";
}
return "";
}
Came across this problem and discovered the answer here:
https://gamedev.stackexchange.com/questions/27786/camera-coordinate-to-screen-coordinate
Supposedly, using Camera.unproject(Vector3 screenCoords) is the correct way of doing this.
My solution looks like this:
Vector3 getMousePosInGameWorld() {
return camera.unproject(new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0));
}
I hope you found the solution to what you need here
https://gamedev.stackexchange.com/questions/60703/libgdx-how-to-get-mouse-position-relative-to-a-tiled-map
maybe here
Get cursor position in LIBGDX
or here
http://www.netthreads.co.uk/2012/01/31/libgdx-example-of-using-scene2d-actions-and-event-handling/
Here is a program that has a ball drop and bounce from wherever the mouse is clicked. Would anyone know how to change the rate that the ball drops to the force of gravity?
Im trying to figure out the proper solution to this... but i am having a little trouble. All help and or input would be much appreciated.
float x;
float y;
float yspeed = 0;
float xspeed = 0;
float balldiameter = 10;
float ballradius = balldiameter/2;
void setup() {
size (400,400);
background (255);
fill (0);
ellipseMode(CENTER);
smooth();
noStroke();
x = width/2;
y = height/2;
}
void draw() {
mouseChecks();
boundaryChecks();
ballFunctions();
keyFunctions();
}
void mouseChecks() {
if (mousePressed == true) {
x = mouseX;
y = mouseY;
yspeed = mouseY - pmouseY;
xspeed = mouseX - pmouseX;
}
}
void boundaryChecks() {
if (y >= height - ballradius) {
y = height - ballradius;
yspeed = -yspeed/1.15;
}
if (y <= ballradius) {
y = ballradius;
yspeed = -yspeed/1.35;
}
if (x >= width -ballradius) {
x = width -ballradius;
xspeed = -xspeed/1.10;
}
if (x <= ballradius) {
x = ballradius;
xspeed = -xspeed/1.10;
}
}
void ballFunctions() {
if (balldiameter < 2) {
balldiameter = 2;
}
if (balldiameter > 400) {
balldiameter = 400;
}
ballradius = balldiameter/2;
background(255); //should this be in here?
ellipse (x,y,balldiameter,balldiameter);
yspeed = yspeed += 0.2;
xspeed = xspeed/1.005;
y = y + yspeed;
x = x + xspeed;
}
void keyFunctions() {
if (keyPressed) {
if(keyCode == UP) {
balldiameter +=1;
}
if (keyCode == DOWN) {
balldiameter -=1;
}
}
}
The acceleration of gravity on earth is 9.81 m/s^2. So, if your ball's velocity is 0 at the point the mouse is clicked, the final velocity will be the acceleration integrated in relation to time. This would be (9.81 * t) / 2. Where t is in seconds. The resulting units would be m/sec. You would have to convert meters to some screen space unit for drawing.