LibGDX player movement - java

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!

Related

Draw circles permanetly given an if statement - Processing

I have an if statement which checks for collision as such:
if (BallY == y && BallX == x) // check for collision
{
x = 80; // reset x to initial
y = 240; // reset y to initial
z = 100; //reset z to initial
}
I have a for loop inside this if statement as such:
if (BallY == y && BallX == x) // check for collision
{
x = 80; // reset x to initial
y = 240; // reset y to initial
z = 100; //reset z to initial
for (int i=50; i<width; i+=80)
{
fill(250,0,0);
ellipse(i, 50, 70, 70);
}
}
So the point is to draw a line of circles on the top of the screen once the collision occurs. This code however, only draws them for a split second then they disappear. How would I make them stay given that a collision has occurred?
You might want to use a boolean value that tracks whether the ball has collided. Set it to true when you detect a collision, and then check the value to decide what to draw. Here's a simplified example:
boolean drawRed = false;
void draw() {
if (mouseY > height/2) {
drawRed = true;
}
if (drawRed) {
background(255, 0, 0);
}
}
This code draws a gray background by default, but then turns to red if the mouse goes in the lower half of the window. It stays red even if you move the mouse back to the top part.
This is just a simple example, but the idea is the same: use a variable to track the state of the sketch, set that variable when your condition is met, and check that variable to decide what to draw.
By the way, your collision detection is a little bit suspicious. You probably don't want to check whether the ball is at an exact location. Instead you probably want to check whether the ball overlaps some area. Here is a guide on collision detection in Processing that might be useful.
If you still can't get it working, please narrow your problem down to a MCVE instead of posting disconnected snippets or your full sketch. Good luck!

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
}

if statement help for controling a drone

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().

Optimize my "capture" algorithm for my Java checkered-type board game

checkered board game is a 11x11 matrix.
pieces are white, black, (1)whiteking
can "capture" a piece by sandwiching opponent
ex) a black piece has a white piece/white king to its left and right or top and bottom
can also sandwich and capture using the edge of the board or any of the 4 corner pieces
ex) white piece on the left edge of board, and then black piece moves directly to the right of the white piece, that would be a capture
so far i have a
11 x 11 matrix
(int) 0 = empty, 1 = white, 2 = black, 3 = whiteking
so my algorithm so far is the basic, check top/bottom/left/right, if it's the opposition, then check if the piece next to that again is a friendly piece, if so, then capture.
but then i can't just do it that simply, because if the piece is on the 2 outter edge rows or columns, using that above algorithm i'll get an ArrayOutofBoundsException error.
then i have a huge if-statement for if the piece is White or Black.
i just feel like there's an easier way to optimize this.. and as a beginning programmer, I can't see it. can someone maybe suggest something?
if you look at my code below.. you can see this is ONLY if the move is in the outer edges... then i gotta pretty much re-copy and paste all that if it's in the "1" column/row... THEN i can finally check 2 spaces up/left/right/down without having to worry about the ArrayOutofBoundsException.
THEN i have to do all that again for Black Pieces..my code is just looking really sloppy and i feel there's an easier way of doing this. Any suggestions?
void makeMove(int typePiece, int fromRow, int fromCol, int toRow, int toCol) {
board[toRow][toCol] = board[fromRow][fromCol];
board[fromRow][fromCol] = EMPTY;
//CAPTURE
if(typePiece == WHITE) {
if(toRow==0) { //top row
//check right
if(toCol!=9 && board[toRow][toCol+1]==BLACK &&
(toCol==10 || board[toRow][toCol+2]==WHITE || board[toRow][toCol+2]==WHITEKING)) {
board[toRow][toCol+1]=EMPTY;
}
//check left
if(toCol!=1 && board[toRow][toCol-1]==BLACK &&
(toCol==0 || board[toRow][toCol-2]==WHITE || board[toRow][toCol-2]==WHITEKING)) {
board[toRow][toCol-1]=EMPTY;
}
//check bottom
if(board[toRow-1][toCol]==BLACK && (board[toRow-2][toCol]==WHITE || board[toRow-2][toCol]==WHITEKING)) {
board[toRow-1][toCol]=EMPTY;
}
}
else if(toRow == 10) { //bottom row
//check right
if(toCol!=9 && board[toRow][toCol+1]==BLACK && (toCol==10 || board[toRow][toCol+2]==WHITE || board[toRow][toCol+2]==WHITEKING)) {
board[toRow][toCol+1]=EMPTY;
}
//check left
if(toCol!=1 && board[toRow][toCol-1]==BLACK && (toCol==0 || board[toRow][toCol-2]==WHITE || board[toRow][toCol-2]==WHITEKING)) {
board[toRow][toCol-1]=EMPTY;
}
//check top
if(board[toRow+1][toCol]==BLACK && (board[toRow+2][toCol]==WHITE || board[toRow+2][toCol]==WHITEKING)) {
board[toRow+1][toCol]=EMPTY;
}
}
else if(toCol == 0) { //left column
//check right
if(board[toRow][toCol+1]==BLACK && (board[toRow][toCol+2]==WHITE || board[toRow][toCol+2]==WHITEKING)) {
board[toRow][toCol+1]=EMPTY;
}
//check top
if(toRow!=1 && board[toRow+1][toCol]==BLACK && (board[toRow+2][toCol]==WHITE || board[toRow+2][toCol]==WHITEKING)) {
board[toRow+1][toCol]=EMPTY;
}
//check bottom
if(toRow != 9 && board[toRow-1][toCol]==BLACK && (board[toRow-2][toCol]==WHITE || board[toRow-2][toCol]==WHITEKING)) {
board[toRow-1][toCol]=EMPTY;
}
}
else if(toCol == 10) { //right column
//check left
if(board[toRow][toCol-1]==BLACK && (toCol==0 || board[toRow][toCol-2]==WHITE || board[toRow][toCol-2]==WHITEKING)) {
board[toRow][toCol-1]=EMPTY;
//check top
if(toRow!=1 && board[toRow+1][toCol]==BLACK && (board[toRow+2][toCol]==WHITE || board[toRow+2][toCol]==WHITEKING)) {
board[toRow+1][toCol]=EMPTY;
}
//check bottom
if(toRow != 9 && board[toRow-1][toCol]==BLACK && (board[toRow-2][toCol]==WHITE || board[toRow-2][toCol]==WHITEKING)) {
board[toRow-1][toCol]=EMPTY;
}
}
Consider that a piece can be captured only as the result of the movement of another piece. Say that you have a white piece that moves to some spot adjacent to a black piece (eight checks of "is there a black piece next to me"?); at that point, check if there is a white piece across from it along the same line (if the black piece is below the first white piece, check for another white piece directly below the first black piece; if the black piece is diagonally up and to the right, check for another white piece up and to the right of the black piece; etc.). Also, you'd need to check every time a piece moved for a) is there an enemy piece around me, and if so b) is it mirrored on the other side by another enemy piece?
Try something along these lines:
for all eight directions (up, down, left, right, and the four diagonals):
is there an enemy piece in that direction adjacent to me?
if so:
is there a friendly piece in that direction that is also adjacent to that enemy piece?
if so:
remove that piece
and
for all eight directions:
is there an enemy piece in that direction adjacent to me?
if so:
is there another enemy piece in the opposite direction that is also adjacent to me?
if so:
remove me
Your problem seem very similar to the "Go" game.
What you could do is to check what is called in go "liberties".
A liberty is a free place next to a group of pieces. If a group has no more liberties (surrounded by the opponent) then the group dies.
Here are some hints on how you can implement that.
When a piece is moved, you check its neighbours. If one of the neighbours is an opponent,
function: hasPieceLiberty(Position piece): return true if one of the neighbours is empty
function: hasGroupLiberty(Position currentPiece):
add current piece to visited pieces for this group
if currentPiece.hasPieceLiberty -> return true
else
if currentPiece has no more non visited neighbours for this group -> return false
else call hasGroupLiberty for non visited neighbours in the group
function: move(Position piece)
if piece has neighbours that are opponents, check if opponent group has liberties
I hope that helps
Edit: I notice that your problem is actually simpler that what I thought in the first place. I thought that you had to surround the opponent everywhere, not simply to sides of a line. Then you should check CosmicComputer's proposal
A few custom items helped to clean up the code when I was trying to solve this:
structPoint takes an 'x' and a 'y'. Handy for mapping out the contents of a 2d array.
Operations can include adding, subtracting, etc, that operate, separately, on the 'x' and 'y' values.
An isValid check could be useful for determining if the point is a valid index of an array (given the array, as a parameter). Overriding ToString() is also nice.
An array of Points that holds all the desired directions from a source Point, (dir4, dir8, etc) is great for checking what is around it. Iterate through the provided directions: [foreach( Point dir in dir4 ){ testPoint = sourcePoint + dir; ... }]. Use isValid to determine if the Point is outside the array before attempting to check the position's contents to avoid an IndexOutOfBoundsException.

How to refresh buttons Image Icons for Java

Does anybody know how to refresh button Image Icons?
The problem is:
I'm making a checkers game, and creating a GUI. Everything works including the AI, except that I called my AI after I placed a move, resulting the buttons does not appear to have checker on it.
Clicked Button
Click on a specific button where there is a checker
Click on the the next spot where the checker has to go
Immediately call the AI to make a move.
My buttons have ImageIcons of checkers pictures, when I click to the next spot where the checker needs to go, the JButton on the JPanel does not refresh at that instant, but waiting until the AI to make the move and finish it's move, resulting that I don't see where my checker went.
When 3-4 Calls one after another, I only see the resulting move the AI did, but not mine, because everything refreshes after it exits the implements actionListener.
I tried calling:
repaint();
revalidate();
invalidate();
On the JPanel that contains the buttons.
before step 4 so that the user can see what he/she has placed before the AI making the move.
else
{
//This is where the code starts
if ("White".equals(Red_Or_White.getText()))
{
//Meaning that it is white's turn, then
playerPlaysAMove(x, y, goingToGo_x, goingToGo_y);
}
if ("AI".equals(AI_Enabled.getText()))
{
//AI is enabled
AIMoves(board, "Red");
//the AI needs to play the position as if the AI was a red player,
//because the player must be white
}
}
Both the AI plays on the same round, but AI calculations takes about 1 minute, and at that time, the player's move is not visible until the AI plays, because it updates all of the buttons after going out of actionListener (after else statement).
Board is a array of 8x8 Buttons that is placed on a JPanel
static void playerPlaysAMove(int save_x, int save_y, int moveTo_x, int moveTo_y)
{
if(save_x - moveTo_x == 1 || save_x - moveTo_x == -1)
{
board[moveTo_x][moveTo_y].setIcon(board[save_x][save_y].getIcon());
board[save_x][save_y].setIcon(null);
}
else if (save_x - moveTo_x == 2 && save_y - moveTo_y == 2)
{
board[save_x-1][save_y-1].setIcon(null);
board[moveTo_x][moveTo_y].setIcon(board[save_x][save_y].getIcon());
board[save_x][save_y].setIcon(null);
}
else if (save_x - moveTo_x == 2 && save_y - moveTo_y == -2)
{
board[save_x-1][save_y+1].setIcon(null);
board[moveTo_x][moveTo_y].setIcon(board[save_x][save_y].getIcon());
board[save_x][save_y].setIcon(null);
}
else if (save_x - moveTo_x == -2 && save_y - moveTo_y == 2)
{
board[save_x+1][save_y-1].setIcon(null);
board[moveTo_x][moveTo_y].setIcon(board[save_x][save_y].getIcon());
board[save_x][save_y].setIcon(null);
}
else if (save_x - moveTo_x == -2 && save_y - moveTo_y == -2)
{
board[save_x+1][save_y+1].setIcon(null);
board[moveTo_x][moveTo_y].setIcon(board[save_x][save_y].getIcon());
board[save_x][save_y].setIcon(null);
}
}
Basically is I calculated the X Y coordinate of the user's select button, and the user's destination button. There are some checking whether he is playing the correct move or not, but this is the major movement part.
If the X Y coordinate difference is 1, that means the player is moving, not jumping, if the X Y coordinate difference is 2, that means the player is jumping. I also need to set the original X Y coordinate's button to null, that means the icon disappears, and then place the new imageIcon at the destination X Y coordinate.
If the player is jumping, then I also need to calculate the place where the user eats the piece, and set that imageIcon to be null also.
The AI does the exact same thing, except the AI calculates the X Y coordinate by using recursive functions to calculate the best move.
The Main problem is that the player players, and then AI computes, and plays, then after the process, it will show the result of both together. Is it possible to let it redraw the image icon before the AI computes and plays? So that the player can see what he played, and then what the AI played
Try with board[save_x][save_y].repaint();

Categories