if statement help for controling a drone - java

I have a ardrone that detect a face,sends me coordinates of the face etc.
I am at the stage for drone to track the face. I have center point of face and center point of frame, by which I calculate what command do I send the drone.
But my problem is that the moment drone sees a face, it sends first command e.g. go.left() and it just keeps going left until it crashes.
What am I doing wrong here? Here is piece of my code
//if result positive on x move drone left
if(piccX - facecX > 50){
drone.goLeft();
}
//if result negative on x move drone right
if(piccX - facecX < 50){
drone.goRight();
}
//if result positiveon Y, move drone up
if(piccY - facecY > 50){
drone.up();
}
//if result negative on Y, move drone Down
if(piccY - facecY > 50){
drone.down();
}
Do I introduce sleep()? I wanted to do a while loop, but I dont think I can here. Any help is appreciated, thank you.

Perhaps you could introduce state.
enum Heading {
None, Up, Down, Left, Right
}
Heading currentHeading = Heading.None;
//if result positive on x move drone left
if(piccX - facecX > 50 && currentHeading != Heading.Left){
drone.goLeft();
currentHeading = Heading.Left;
}
//if result negative on x move drone right
if(piccX - facecX < 50 && currentHeading != Heading.Right){
drone.goRight();
currentHeading = Heading.Right;
}
//if result positiveon Y, move drone up
if(piccY - facecY > 50 && currentHeading != Heading.Up){
drone.up();
currentHeading = Heading.Up;
}
//if result negative on Y, move drone Down
if(piccY - facecY > 50 && currentHeading != Heading.Down){
drone.down();
currentHeading = Heading.Down;
}
If that isn't enough movement in the current direction, maybe creating an array of currentHeading states can simulate ramp up or distance traveled.

From my experience with ARDrones, those functions will continuously move the drone in that direction. There should be other methods within the drone object in which you can call. I think there's one called setPosition().

Related

Get mouse direction relative to x y coordinates

I am working on a java game, in which I want to implement some combat. the way I want to implement the combat is through a single button, and depending on where the mouse cursor is, I want to attack in that direction. The problem is, i can't detect the direction relative to the player with just the x and y coordinates. if i did this without any math or anything else, i would get these kind of quadrants to measure directions from:
^^ These wouldn't work because that would get me: up-left, up-right, down-left, and down-right.
I want instead have up, down, left, and right, like this: where if the mouse is in one of these quadrants, it would attack in that direction. this would get me up, right, down, left (following the quadrants shown above)
Heres the information I have: Mouse x coordinate, Mouse Y coordinate, player X coordinate, player Y coordinate.
Im sure there is some math to convert these quadrants into these quadrants so that I can detect which direction the mouse is, relative to the player.
Here is an example of the code I would use to detect the mouse direction (this code is for the format, because I cant figure out the other one):
private Direction getMouseRelativeDirection() {
if(mouseX > x && mouseY < y)
return Direction.topRight;
if(mouseX > x && mouseY > y)
return Direction.bottomRight;
if(mouseX < x && mouseY < y)
return Direction.topLeft;
if(mouseX < x && mouseY > y)
return Direction.bottomLeft;
//to prevent errors if the mouse isn't in a quadrant, just return null
return null;
}
I hope I gave enough information for someone to figure out the direction math, but let me know if you need more info!
EDIT:
I fixed this with some searching on google and troubleshooting of my own.. turns out using lines formulas to get each line relative to the mouse is the way to go.
Maybe it would help you calculate the angle between the two points.
double angle = Math.toDegrees(Math.atan2(mouseY - y, mouseX - x));
if(angle < 0) { angle += 360; } // angle always >= 0

LibGDX player movement

I'm developing a 2D space shooter game with the player only moving left and right. I've rendered a button on the left and the right side of the screen and constantly check if it's touched. The problem with this is that you have to lift your finger of the button in order to press the button on the other side of the screen. I want the ship to be moving towards the last touched part of the screen(Even when you actually didn't lift the finger of your first-touched button).
public void keyListener(float delta){
//right movement
if(Gdx.input.isKeyPressed(Keys.RIGHT) || (Gdx.input.isTouched() && game.cam.getInputInGameWorld().x >= arrowMoveX - 40) && !isPlayerHit)
x+=SPEED*Gdx.graphics.getDeltaTime();
//left movement
if(Gdx.input.isKeyPressed(Keys.LEFT) || (Gdx.input.isTouched() && game.cam.getInputInGameWorld().x < arrowMoveWhite.getWidth() + 40) && !isPlayerHit)
x-=SPEED*Gdx.graphics.getDeltaTime();
I've tried puting another if statements in these to check for a second movement, but this way it only works on one direction.
Can you please help me?
What you need to know about for this is that Android indexes each separate touch in order of when the screen was touched, the index is known as a "pointer". For example, when you touch the screen with only one finger, the touch pointer is 0, and the second touch pointer is 1. The highest pointer that libGDX registers is 20.
For your particular situation, you want to read only the input that is on the highest pointer that is currently reading a touch, and have an int reading the highest touch. You can loop through the pointers, and set the int to whatever touch event is actually the highest pointer which is referring to the most recent press like this:
int highestpointer = -1; // Setting to -1 because if the pointer is -1 at the end of the loop, then it would be clear that there was no touch
for(int pointer = 0; pointer < 20; pointer++) {
if(Gdx.input.isTouched(pointer)) { // First check if there is a touch in the first place
int x = Gdx.input.getX(pointer); // Get x position of touch in screen coordinates (far left of screen will be 0)
if(x < arrowMoveWhite.getWidth() + 40 || x >= arrowMoveX - 40) {
highestpinter = pointer;
} // Note that if the touch is in neither button, the highestpointer will remain what ever it was previously
}
} // At the end of the loop, the highest pointer int would be the most recent touch, or -1
// And to handle actual movement you need to pass the highest pointer into Gdx.input.getX()
if(!isPlayerHit) { // Minor improvement: only check this once
if(Gdx.input.isKeyPressed(Keys.RIGHT) || (highestpointer > -1 && Gdx.input.getX(highestpointer) >= arrowMoveX - 40)) {
x+=SPEED*Gdx.graphics.getDeltaTime();
} else if(Gdx.input.isKeyPressed(Keys.LEFT) || (highestpointer > -1 && Gdx.input.getX(highestpointer) < arrowMoveWhite.getWidth() + 40)) {
x-=SPEED*Gdx.graphics.getDeltaTime();
}
}
Note that you will probably want a separate camera drawing your buttons (or any hud elements) because you would not need to worry about translating screen coordinates to world coordinates since x goes in the same direction.
Let me know how that works and if you need any changes!

How do I use an if statement to run except when something else has happened?

I am using Java to run balls around a box. By using this piece of code it bounces off the edges.
if (y >= borderBottom)
{
y = border;
speedOfY = -speedofY;
}
I have a hole in the box of balls. If the ball hits the hole I would like it to continue through the gap.
I want the if statement to run until:
it's between two points on x (the hole)
and at the border bottom on the y axis (the side of the hole).
How can I make this happen? I know I need to use simulation.pauseSimulation() but I don't know how to get the balls to stop specifically when it's between the two points and when it's at the border bottom, thanks!
I have tried using the previous statement with this afterwards,
if(y >= borderBottom && (x < 275) && (x > 325>))
simulation.pauseSimulation()
but I have played around and the simulation has ignored the whole bottom border and at one point all the objects flashed.
It may be a good time to learn about logical operators (&&, &, ||, |, !, ^). Specifically in this case:
if (Condition A && Condition B)
{
//Do something
}
You could also use:
if(Condition A || Condition B)
{
//Do something
}
First of all, you need to know the bottom and top coordinates of the hole.
Afterwards, you can simply write:
if ( y >= borderBottom || ( y < holeBottom && y > holeTop ) ) {
Simulation.pauseSimulation();
//You can pause simulation or do anything you prefer
}

Near perfect collision in LibGdx Java

I am trying to get the collision in my game to be exactly perfect. What I am testing is if you hit a wall with the player, you come to a stop. I only implemented the collision code for when the player hits the left side of a wall(when the wall is on the right side of the player). Here is the code.
if(entityOnRight){
if(player.getPositionCorner(SquareMapTuples.BOTTOM_RIGHT).x -
ent.getPositionCorner(SquareMapTuples.BOTTOM_LEFT).x > -.9f)
player.setMovementBooleans(false, false, false, false);
else
player.setMovementBooleans(true, false, false, false);
}
Note: If I go very slow, it will stop the player where I desire it to be stopped, but going fast, it won't do the collision the way I want
Essentially, the code states if the wall is on the right side, it will check the bottom right corner of the rectangle of the player, subtract the bottom left corner of the wall, and check if the distance between the two is 0.001. 0.001 is almost an unnoticeable distance, hence why I used that value. Here is the code for player.setMovementBooleans
public void setMovementBooleans(boolean canMoveRight, boolean canMoveLeft, boolean canMoveUp, boolean canMoveDown){
this.canMoveRight = canMoveRight;
if(canMoveRight == false && moveRight)
vel.x = 0;
}
The canMoveRight boolean in the Player class (not in parameters) is what allows you to be able to move, moveRight is when you are trying to move right. Here is some code that will better explain how these booleans interact:
//If you clicked right arrow key and you're not going
//Faster then the max speed
if(moveRight && !(vel.x >= 3)){
vel.x += movementSpeed;
}else if(vel.x >= 0 && !moveRight){
vel.x -= movementSpeed * 1.5f;
System.out.println("stopping");
//Make sure it goes to rest
if(vel.x - movementSpeed * 1.5f < 0)
vel.x = 0;
}
and:
if(Gdx.input.isKeyPressed(Keys.D) && canMoveRight)
moveRight = true;
else
moveRight = false;
So to give a summary, if you click the "D" key, it allows you to start moving. However if the boolean canMoveRight is false, it won't move you. Here is an image showing what happens (The player is yellow, the wall is green)
As you can see, the player goes much further then I want it to. It should stop at this point:
Any help with figuring out how to accomplish this is extremely appreciated!
Maybe the way you tried it is a bit too complicated :-). I suggest a simpler way from scratch: make the map and the player a com.badlogic.gdx.math.Rectangle instance. Now, in the following part of the code you make a check, whether after the move the player would still be inside the map, if yes then allow the move, if not, then don't allow:
if(Gdx.input.isKeyPressed(Keys.D){
float requestedX, requestedY;
//calculate the requested coordinates
Rectangle newPlayerPositionRectangle = new Rectangle(requestedX, requestedY, player.getWidth(), player.getHeight());
if (newPlayerPositionRectangle.overlaps(map) {
//move the player
} else {
//move the player only to the edge of the map and stop there
}
}
The best way to handle those collisions would be to use a physics engine like Box2D which already comes packed with Libgdx. When a collision occurs in Box2D a event gets fired and you can easly handle that event. So you should probably take a look here.
Another alternative to achieve this without physics would be to use logical rectanlges representing the player and walls (can also be polyline) and use Intersector class of libgdx.
which is here.

Moving objects getting stuck in a corner

I am working on a program which simulates objects moving in a field. The field has a boundary of 1024x1024. The object cannot go below 0 in terms of x,y coordinate and it cannot go above 1024. I have a method for each object called "move()" which moves the object in its current direction at its current speed. If the object approaches the boundary, it then turns around with a new direction and same speed.
The problem I am having is that when one of my objects gets close to both the x and y bound (corner of the field), it gets stuck in the corner. It is almost as if it is trying to move away from the corner, but then it turns back. It must love that corner. I looked over my code and to me, my logic seems correct. I check to make sure the new direction is not negative or over 359. I check to make sure the new x,y coordinate with the new direction is within the bounds too. I even have a method to set a new direction.
I have tried re-implementing this method with different logic, but no luck. If anyone could possibly find a flaw in my programming or point out what may be causing it, then that would be much appreciated.
I have tried to debug and step through my program and I see that when it gets to the corner, it changes direction to turn around, moves about 3 spaces, then goes back to the corner. Must be a wonderful corner.
Code for move method is below:
public void move(){
localX = super.getX();
localY = super.getY();
float newX=0, newY=0;
float testX, testY;
boolean acceptX = false, acceptY = false;
testX = (float) (Math.cos(direction)*10) + localX;
testY = (float) (Math.sin(direction)*10) + localY;
int testDirection;
while(!acceptX){
if(testX >= 0 && testX <= bound){
newX = testX;
acceptX = true;
}//end if statement
else{
if(direction+180 > 359){
setDirection(direction-180);
testX = (float) (Math.cos(Math.toRadians(direction))*speed) + localX;
}
else{
setDirection(direction+180);
testX = (float) (Math.cos(Math.toRadians(direction))*speed) + localX;
}
}//end else
}//end while that checks for X value
while(!acceptY){
if(testY >= 0 && testY <= bound){
newY = testY;
acceptY = true;
}//end if statement
else{
if(direction+180 > 359){
setDirection(direction-180);
testY = (float) (Math.sin(Math.toRadians(direction))*speed) + localY;
}
else{
setDirection(direction+180);
testY = (float) (Math.sin(Math.toRadians(direction))*speed) + localY;
}
}//end else
}//end while that checks for Y value
super.setX(newX);
super.setY(newY);
}
and here is the code for setDirection
public void setDirection(int d) {
direction = d;
}
Say you have an object in the upper left corner, going up. Your first test turns it around so it goes down. Then comes your second check, which turns it around again to go up... again.
Your code could also use some more readability. The very first thing I noticed is that you're using the >359 checks to normalize the new direction to go in. Yet all cases include the movement code as well. I would do something like:
setDirection(direction + 180); //turn around
if (direction >= 360) direction -= 360; //normalize
testY = ...; //move
to move the movement code out of the direction checking if/else blocks. 360 is also a better magic number to use; 359 degrees means nothing. As has been suggested, you should ultimately use a vector library and thus throw away most of the math.
I'd really recommend storing your direction as a vector (x, y) instead of calculating that vector from a scalar; I think that would help you immensely with your code.
Issue: When your object hits an edge, you turn it 180 degrees. If it hits both edges, it'll spin in place, and the test coordinates will always be in the wrong spot.
When one of your objects hits an edge, it needs to bounce, not About Face! Angle of incidence == angle of refraction, or some such. In other words, if you're checking the x coordinate and it bounces, negate the x velocity, not both x & y.

Categories