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
}
Related
So, for a school project, I've been trying to get a jumping mechanism down. However, the problem I've been having is that the player is able to just float around, rather than having to fall down after reaching a certain jump height.
I have tried many things, including the normal idea of when the up key is pressed, setting jumping equal to true, and then in the actionPerformed method, setting the yVelocity to -4. But, when the jump key is clicked, I record the yPosition at the time, and when the current yPosition is less than the original position - 50, I set the yVelocity equal to 0, and the fallVelocity to 1.
This is the code in my actionPerformed method:
if (jumping) {
if (yPos <= homeY - 50) {
yVel = 0;
fallVel = 1;
falling = true;
jumping = false;
System.out.println("bye");
} else {
yVel = -JUMP_SPEED;
}
}
yPos += yVel + fallVel;
'''
This is the code in the keyPressed method:
if (!jumping && !falling) {
jumping = true;
homeY = yPos;
count = 0;
}
So, I expect the result to be a player that goes up 50 pixels, and then starts falling down. But in the program, the player just sort of keeps on floating, as long as the up key is pressed.
Jumping does not really work properly as an up/down switch imo. The best approach is to use gravity (which is very easy to add).
To add gravity just modify the player velocity each tick. This should be run on a fixed time update loop to make consistent gravity at different frame rates:
// Play with this number for rate of gravity
player.ySpeed -= 4.9; // Gravity = 9.8m/s^2
Then for your jumping just add to the player ySpeed. This will create a natural parabolic jump.
if (jumpWasPressed) {
player.ySpeed += 50; // play with this number for jump height
}
This approach does assume you have a hotbox for your "ground" object to stop the player from falling through the ground
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!
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.
I am writing a physics engine and when the ball hits a surface it bounces up at half the velocity it came down at(velocity.y = -velocity). However when the ball is almost at rest it switches velocities constantly and starts falling through the platform incredibly slow but still will eventually fall through if I let it run long enough, and this is not acceptable. I tried writing some code to stop it but it checks way too fast here is the update method that attempts to check it.
public void update() {
velocity.y += Globals.GRAVITY.y;
if(canFall)
position.y += velocity.y;
position.x += velocity.x;
oldPosition.y = position.y;
oldPosition.x = position.x;
elapsedTime += 1 * Gdx.graphics.getDeltaTime();
if(elapsedTime >= 5){
if(oldPosition.y - 5 <= position.y && oldPosition.y + 5 >= position.y){
elapsedTime = 0;
canFall = false;
}else{
canFall = true;
elapsedTime = 0;
}
}
}
The collision handler knows when it hits the top of the ball which is the only solution I need for this. How do I check when the ball is at rest.
This code attempts to check if the ball hasn't moved in a couple seconds, if it hasn't it sets canFall to false. I need a generic check that will see if the ball should be at a stop. The velocity of the ball when it is falling through the platform you can see from the picture below. The picture shows the ball "at rest" after ten seconds so as you can see the ball is slowly but surely falling through. Every three seconds with this "rest" velocity the y position goes down 1, the velocity changes from positive to negative so the velocity you see in the picture isn't constantly negative. Ignore the elapsed time variable Any help is greatly appreciated!
Why let time have anything to do with it? I'm not saying it coudln't, but should it? So maybe lose the if(elapsedTime ... ) conditional.
Isn't this what you want? If the magnitiude of the vertical difference between the last two positions is negligible (set tolerance accordingly; maybe it's 5), stop bouncing:
if(Math.abs(position.y - oldPosition.y) < tolerance)
{
canBounce = false;
...
}
else
{
canBounce = true;
...
}
or, if nothing else needs to change at the ... above:
canBounce = Math.abs(position.y - oldPosition.y) > tolerance;
Also, don't you need { and } somewhere in the segment below? Maybe not, if ball is bouncing vertically, but it looks like x can change, too, which might make the code above need adjusting. But the way code below is indented makes me think there's supposed to be more to do than just changing position.y:
if(canFall)
position.y += velocity.y;
position.x += velocity.x;
oldPosition.y = position.y;
oldPosition.x = position.x;
Finally, you're addding velocity to position. That seems questionable. Multiply velocity times time? Or is time = 1 always? (Doubt it.)
The problem may be external to this method. Something needs to keep ball's y from becoming less than the y of the top of the dark blue box. This code can't do that without knowing y of top of dark blue box (unless you apply physics formulas?). Maybe include this value in parameter list as topOfDarkBlueBox?
Then add code such as:
if(position.y < topOfDarkBlueBox.y) position.y = topOfDarkBlueBox.y
I'd rather see physics at work, but you might say, "Who'd notice?"
EDIT
You wrote, "The collision handler knows when it hits the top of the ball," but I assume you meant "when the ball hits the top of the dark blue box". Maybe call the collision handler instead of passing new parameter topOfDarkBlueBox?
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();