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.
Related
Hello this is actually my first question here.. I have been developing a opengl lwjgl game and I'm working on the entities class.I have accomplished to make an entity jump(ill use this for animals) but the "issue" (99.9% sure its my fault) is that each time the entity touches the terrain and jumps again the jump is higher as seen in the video I recorded this is the code for jump thz =D I just want the tree to move up always the same.
Video
double velocity = 0;
double initVelX;
double initVelZ;
double time = 0;
float x;
float y;
float z;
public void bounce() {
double initialVelocity = 0.1;
double speed = 1/2500.0;
if(time == 0) {
velocity += initialVelocity;
}
time += speed;
velocity = velocity - 9.8 * speed;
if(y + velocity < 0.1){
velocity *= -1;
}
y += velocity;
setPosition(new Vector3f(getPosition().x,y,getPosition().z));
}
Fixed it just had to do a simple line of code and it even has the speed fluctuations correct:
double velocity = 0;
double initVelX;
double initVelZ;
double time = 0;
float x;
float y;
float z;
public void bounce() {
double initialVelocity = 0.1;
double speed = 1/2500.0;
if(time == 0) {
velocity = initialVelocity;
}
time += speed;
velocity = velocity - 9.8 * speed;
if(y + velocity < 0.1){
velocity *= -1;
velocity = initialVelocity;
}
y += velocity;
setPosition(new Vector3f(getPosition().x,y,getPosition().z));
}
I think it will be one of these increment statements:
velocity += initialVelocity;
time += speed;
velocity *= -1;
y += velocity;
Do you want all of these to keep rising continually? Because that's what will happen.
Which part of your code calculates the height of the jump?
I am currently working on a 2D side scroller and have implemented the techniques use in this article for a grapple hook, and it works really well. My problem is I want my player to be able to swing around the rope a little bit to gain a bit of momentum, but currently I can't stop the player from moving all the way up to 90 degrees either side. What techniques can be applied to force this limit?
I have tried using a separate player speed for swinging but this only slows the process down I can still swing up to 90 deg each side.
Here's my update function in the player
public void update(float dt){
//handle friction and air resistance
if(dx !=0){
if(touchingGround) {
// apply friction
if (dx > 0) {
dx -= retardation;
} else {
dx += retardation;
}
} else {
//applied air resistance
if (dx > 0) {
dx -= airResistance;
} else {
dx += airResistance;
}
}
}
// handle gravity
dy -= Constants.GRAVITY * dt;
if(dy < -terminalVelocity){
dy = -terminalVelocity;
}
/*
Handle Player movement
*/
if(right){
if(dx <= maxSpeed){
dx += acceleration;
}
dx = maxSpeed;
}
if(left){
if(dx <= -maxSpeed){
dx -= acceleration;
}
dx = -maxSpeed;
}
if(isGrappling){
//If we collide with something we need to stop grappling
if(hasCollided){
isGrappling = false;
} else {
// This algorithm from here:
// http://gamedev.stackexchange.com/questions/61596/player-rope-swing
float currentD = (float) Math.sqrt(((grappleX - x) * (grappleX - x)) + ((grappleY - y) * (grappleY - y)));
float prevX = getX(), prevY = getY();
if (currentD > grappleRadius) {
Vector2 hookPos = new Vector2(grappleX, grappleY);
Vector2 testPos = (new Vector2(x, y).sub(hookPos)).nor();
y = (hookPos.y + testPos.y * grappleRadius);
x = (hookPos.x + testPos.x * grappleRadius);
// s = d / t
dx += (x - prevX) / dt;
dy += (y - prevY) / dt;
}
}
}
/*
Collision Detection, handle last always!
*/
float oldX = getX(), oldY = getY();
boolean collisionX = false, collisionY = false;
// move on x
x += dx * dt;
// calculate the increment for step in #collidesLeft() and #collidesRight()
increment = collisionLayer.getTileWidth();
increment = getWidth() < increment ? getWidth() / 2 : increment / 2;
if(dx < 0) // going left
collisionX = collidesLeft();
else if(dx > 0) // going right
collisionX = collidesRight();
// react to x collision
if(collisionX) {
setX(oldX);
dx = 0;
}
// move on y
y += dy * dt;
// calculate the increment for step in #collidesBottom() and #collidesTop()
increment = collisionLayer.getTileHeight();
increment = getHeight() < increment ? getHeight() / 2 : increment / 2;
if(dy < 0) {
touchingGround = collisionY = collidesBottom();
// we can only jump 2 times before we have to touch the floor again
if(collisionY){
numberOfJumps = 2;
}
} else if(dy > 0) {
collisionY = collidesTop();
}
// react to y collision
if(collisionY) {
setY(oldY);
dy = 0;
}
hasCollided = collisionX || collisionY;
}
As I am not using any physics engine I chose to just emulate the physics by limiting the angle at which the player can apply force to the swing.
// check if angle permits movement
if(grappleAngle < Math.PI/9 && grappleAngle > -Math.PI/9) {
// handle momentum gaining on rope
if (right) {
dx += swingAcceleration * dt;
}
if (left) {
dx -= swingAcceleration * dt;
}
}
I'm trying to create a bouncing ball that can move in the x, y, and z coordinates. The ball originally starts a couple units in the y-axis above the origin. I've managed to figure out how to get my ball to bounce up and down in the y plane, but am having troubles figuring out what I am doing wrong whenever I try adding the x and z trajectories.
double initialVelocity = userInputY;
double initVelX = userInputX;
double initVelZ = userInputZ;
double speed = 1/500.0;
double time = 0;
double x, y, z =0;
if (time == 0){
velocity+= initialVelocity;
}
time += speed
velocity = velocity - 9.8 * speed;
if (y+velocity < 0.1){ //collision detection against the floor
velocity *= -1;
}
if (z + initVelZ < 100){ //Collision detection for ceiling of 100 units
initVelZ *= -1;
}
if (x + initVelX < 50){ //Collision detection for if ball moves 50 units away from origin in x
initVelX *= -1;
}
else{
y += velocity;
x += initVelX;
z += initVelZ;
}
gl.gltranslated(x, y, z);
glu.gluSphere() //not really that important to specify
When I only use my y variable my ball has a bouncing animation but only moves up and down.
The comparisons for the z and x coordinates look backwards:
if (z + initVelZ < 100){ //Collision detection for ceiling of 100 units
initVelZ *= -1;
}
if (x + initVelX < 50){ //Collision detection for if ball moves 50 units away from origin in x
initVelX *= -1;
}
This inverts the velocity every time the new position is found to be inside the bounds. But they need to be inverted when the new position would end up being outside the bounds.
Also, you probably need to test for collision with the walls at both ends of each coordinate direction, so that the ball can bounce off all 6 walls.
For example for the z coordinate, the logic could look like this:
if (z + initVelZ < 0.0 || z + initVelZ > 100.0) {
initVelZ *= -1.0;
}
Same thing for the other coordinates.
So I am working on a blackjack game, I have wrote a render process which will render a card going out of the cards stack and sliding to the place where it shows all dealer's cards.
My method works fine, except one problem which I will elaborate:
Whenever Y coordinate reaches the target Y coordinate first, the sprite will only move on X-asis because it cant move Y anymore, instead of making a straight angle to the point.
So what it will do is move up diagonally and then instantly go to the right (in my case)
GIF:
(source: gyazo.com)
MP4 (choose mp4 in the (..) menu http://gyazo.com/bec6daadcb46bedc4777a3e4c5ff8c77)
As you can see, it does what I just said.
What did I do wrong? how can I make it motion in a straight angle to the target without going diagonal up and than turn right away?
My process code:
// If the target is on the right side of the start point
if (startPoint.getX() < endPoint.getX()) {
if (current.getX() < endPoint.getX()) {
current.x += moveSpeed;
if (current.getX() > endPoint.getX()) {
current.x = (int) endPoint.getX();
}
}
else {
xDone = true;
}
}
else {
if (current.getX() > endPoint.getX()) {
current.x -= moveSpeed;
if (current.getX() < endPoint.getX()) {
current.x = (int) endPoint.getX();
}
}
else {
xDone = true;
}
}
// Vise-versa
if (startPoint.getY() < endPoint.getY()) {
if (current.getY() < endPoint.getY()) {
current.y += moveSpeed;
if (current.getY() > endPoint.getY()) {
current.y = (int) endPoint.getY();
}
}
else {
yDone = true;
}
}
else {
if (current.getY() > endPoint.getY()) {
current.y -= moveSpeed;
if (current.getY() < endPoint.getY()) {
current.y = (int) endPoint.getY();
}
}
else {
yDone = true;
}
}
// Callback, dw about it
CardContainer.getCardSprite(CardContainer.SPECIAL, 0).drawSprite((int) current.getX(), (int) current.getY());
// Alert finished, in poisiuton
if (xDone && yDone) {
ch.submitCard(card);
}
current = current position
startPoint = the start point
endPoint = the end point
Thanks!
EDited code:
private void applyMovement(double alpha) {
double dx = endPoint.getX() - startPoint.getX();
double dy = endPoint.getY() - startPoint.getY();
this.current.setLocation(startPoint.getX() + alpha * dx, startPoint.getY() + alpha * dy);
}
public void process() {
double alpha = (double) stepsDone / distance;
applyMovement(alpha);
stepsDone++;
// Callback, dw about it
CardContainer.getCardSprite(CardContainer.SPECIAL, 0).drawSprite((int) current.getX(), (int) current.getY());
// Alert finished, in poisiuton
if (stepsDone >= distance) {
ch.submitCard(card);
}
}
Distance calculation:
this.distance = (int) start.distance(end);
Used Point2D distance method:
public double distance(Point2D pt) {
double px = pt.getX() - this.getX();
double py = pt.getY() - this.getY();
return Math.sqrt(px * px + py * py);
}
I would recommend to not use any form of "slope" in such a computation. You will run into problems when the difference in x-direction approaches zero, because then the slope will tend towards infinity.
Assuming that your points are Point2D.Double (or something similar - you should include this kind of information in your questions!), you can compute the movement as follows:
private Point2D.Double initial = ... // The initial position
private Point2D.Double current = ... // The current position
private Point2D.Double target = ... // The target position
void applyMovment(double alpha) {
double dx = target.getX() - initial.getX();
double dy = target.getY() - initial.getY();
current.x = initial.getX() + alpha * dx;
current.y = initial.getY() + alpha * dy;
}
The applyMovment method sketched here can be called with a double value between 0.0 and 1.0, where 0.0 corresponds to the initial position and 1.0 corresponds to the target position. This is just a Linear Interpolation.
So for example, when you have some sort of loop for the animation, you can use the method as follows:
int numberOfSteps = 10;
for (int i=0; i<=numberOfSteps; i++)
{
double alpha = (double)i / numberOfSteps;
applyMovement(alpha);
repaint();
}
This works for any arrangement of the start- and end points, without any sign- or direction issues. It just interpolates between the two positions.
Your calculation needs to be based upon moving the currentY and currentX along a specific line, not a specific set of intervals (moveSpeed). The formula for graphing points on a line is:
y = mx + b
Where x and y are the varying points, m is equal to the slope of the line, and b is what's called the y-intercept.
Your slope is calculated by the formula:
double slope = ((double) endPoint.getY() - startPoint.getY()) / ((double) endPoint.getX() - startPoint.getX());
And the Y intercept can be calculated by just plugging in a bunch of known values once you have them:
double yIntercept = (double) endPoint.getY() - (slope * endPoint.getX())
Then, just loop through the count of the difference in X:
for (int xVal = startPoint.getX(); xVal < endPoint.getX(); xVal++){
currentX = xVal;
currentY = (slope * xVal) + yIntercept;
}
And you should be good.
Warning: this is all off of the top of my head, I don't know if it'll compile.
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.