How to refresh buttons Image Icons for Java - 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();

Related

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!

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.

libGDX - How to stop player's movement at a specific position?

I'll try to explain what i need to achieve.
My player starts at 0, 0 position.
When I touch the screen, the player starts to move up.
And when the player is at the specific position in the Y axis (Let's say 200), I want him to stop moving.
When I touch the screen this method is called:
public void move() {
if (player.getPosition().y < 200) {
player.velocity.set(0, 100);
}
And in my player's update method I have:
if (player.getPosition().y > 200) {
player.position.set(0, 200);
player.velocity.set(0, 0);
}
The problem with this is that if I set the velocity in the move method to something like 1000, there is one frame rendered with the position of the player above 200. Then it changes it to 200 and stays there.
I tried this in the update method:
if (player.getPosition().y == 200) {
player.velocity.set(0, 0);
}
But this statement is never true because the position of the player is always 200 and some random numbers like 200.1257 or 200.54578
I will appreciate all your answers!
You can cast it to an integer like this:
if ((int)player.getPosition().y == 200) {
player.velocity.set(0, 0);
}
But i will not recommend it because if your player is at high speed it could skip the 200 and go on, i think the right thing to do is
if (player.getPosition().y > 200) {
player.velocity.set(0, 0);
player.setPosition(new Vector2(player.getX,200));
}
You can predict where your player are going and calculate the deacceleration as well for a smooth feel for the player..
Now if you want multiple vectors on screen the best is to calculate a distance between the player and the points on screen like this:
//If the player is 20 units closer than the point 200,200 do something
if(player.getPosition().dst2(new Vector2(200,200) < 20){
//do something
}

how to check two rectangles are touching from left or top or right

I am using Java awt library.
I am making a simple game where I have a player and enemy as Rectangles. then I set them bounds so I can use the intersect function on them.
Now I want to check how the player and enemy touch. see attchemnt.
there are mostly 4 different way player can touch the enemy. see the attachemnt. now if player touch the enemy from top than I was go inside the 'if' statment. but if player touch the enemy from left or right than I want to go inseide 'else' statment. I wrote the code below but it doesnt work. for some reason it always goes in else statment.
I was thinking may be there is another function I can use?
if (player.getBounds().intersects(enemy.getBounds())) {
if (playerY + playerHeight <= enemy.getY()) {
//player touch enemy from top
} else {
//player touch enemy from left or right
}
}
Might be not the best solution but it work for what I want. Thanks
if (player.getBounds().intersects(enemy.getBounds())) {
if (y + height <= enemy.getY() + enemy.getHeight() / 2) {
//player touch enemy from top
} else {
//player touch enemy from left or right
}
}
You are checking first the rectangles to see whether they intersect. Intersection is not "touching". It's when they have a common rectangle that is not empty.
So, for example, the following two rectangles do not intersect:
Rectangle a = new Rectangle( 100,100,200,200);
Rectangle b = new Rectangle( 100,300,200,200);
But note that a.y (100) + a.height (200) is exactly b.y (300).
Of course, if a is above b, say, its y is 99, then a.y + a.height is less than b.y.
So in all cases where a.y + a.height <= b.y, the rectangles do not intersect.
Since you only go into that if if the rectangles do intersect, you'll always end up in the else.
If you want to check if they have a slight overlap from above, you can change your condition to playerY + playerHeight == enemy.getY() + 1, or even
int playerBottom = playerY + playerHeight;
if ( playerBottom > enemy.getY() && playerBottom <= enemy.getY() + DELTA ) {
....
}
where DELTA is a constant that represents how big an overlap you consider "touching".
If you want to see that they touch without overlapping, you can't use the intersects method.

Developing a chess game in java, my board object is not getting modified properly

so I am fairly new to the Java language, so there must be something here that I am forgetting. So for a homework I have to create a chess game in Java. As of now, I have created a class for a "Pawn" piece, and another class called "GameState", which contains the board for the game. The Pawn class has a method called move() which takes the x and y coordinates of the spot on the board to move to, as well as the current gamestate object, and the move() function will move the pawn to that spot on the board. The pawn class is extended from an abstract class called "Piece", and all the other specific piece classes I make will inherit from this class.
My problem is that the move() method is not properly modifying the board in the GameState class.
Below is the relevant snippet of code from the move() method of the pawn class:
public GameState move(GameState state, int xDest, int yDest) {
//Make sure that the destination coordinates are not outside of the board
if (xDest < 0 || yDest < 0 || xDest >= state.getBoardCols() || yDest >= state.getBoardRows())
return null;
/*
* A black piece moves forward on the downward pointing y
* axis, and a a white piece moves up. Thus, we assign a
* +1 to the variable if the piece is white, and -1 if the
* piece is black.
*/
int dir = (color.equals("black")) ? -1 : 1;
//In the case that the pawn is moving forward 2 spaces
if (firstMove == true && xCurr == xDest && yDest == yCurr + dir * 2) {
if (state.insertPiece(xDest, yDest, this)) {
firstMove = false;
//Null the old coordinates the Pawn was at
state.nullCoordinates(xCurr, yCurr);
return state;
} else
return null;
}
so, the insertPiece() method is what actually inserts the pawn at the x and y coordinates on the board. I used the eclipse debugger, and when the program is running the insertPiece() method, the board of the "state" object does indeed insert the pawn at the correct x and y coordinates. Now, I have a unit test function which is running this move method, shown here:
state = pawnToTest.move(state, 4, 1 + dir * 2);
assertEquals(false, pawnToTest.firstMove());
assertEquals(pawnToTest, state.getPiece(4, 1 + dir * 2));
assertEquals(null, state.getPiece(4, 1));
Now, in this scenario, I have a pawn placed at x=4,y=1 on the board initially (which indexes to [1][4], but whatever). So, the first move() call here will move it forward to x=4,y=3. Now, I've verified w/ the debugger that INSIDE the pawnToTest.move() call, the board at x=4,y=3 does indeed contain the pawn. However, when the program exits the control of that method, the pawn is no longer at that location, and so the 2nd assert equals fails. Why is the board not getting modified properly?
EDIT: nvm, I foudn the bug, turns out I was not updating the position of the pawn properly, stupid me :P

Categories