Jumping difficulty in Slick2D - java

I have researched how to implement a rudimentary gravity system in slick2d. Here is the code that I have (This is in the update function):
if (input.isKeyDown(Input.KEY_UP)) {
spressed = true; //Has the UP key been pressed?
}
if (spressed) {
if (!sjumping) {//if so, are we already in the air?
Sub_vertical_speed = -1.0f * delta;//negative value indicates an upward movement
sjumping = true;//yes, we are in the air
}
if (sjumping) { //if we're in the air, make gravity happen
Sub_vertical_speed += 0.04f * delta;//change this value to alter gravity strength
}
Sub.y += Sub_vertical_speed;
}
if (Sub.y == Sub.bottom){//Sub.bottom is the floor of the game
sjumping = false;//we're not jumping anymore
spressed = false;//up key reset
}
Here is where the problem arises. When I press the up key, the sprite jumps and comes down normally, but pressing the up key again does nothing. I originally thought it was cause I didn't reset spressed, so I added the line to set it to false, but you can still only jump once. :/

It looks like your Sub.y needs to be Clamped to your Sub.bottom so it doesn't go above it. Try:
if(Sub.y >= Sub.bottom) {
Sub.y = Sub.bottom;
sjumping = false;
spressed = false;
}

I've done something similar before, and my assumption here is that Sub.y never equals Sub.bottom. Depending on the y position and the vertical speed, the object's y position will never be exactly the value of Sub.bottom. The code below will test for this:
if (Sub_vertical_speed + Sub.y > Sub.bottom){ //new position would be past the bottom
Sub.y = Sub.bottom;
sjumping = false; //we're not jumping anymore
spressed = false; //up key reset
}

Related

How to make a player only be able to jump a certain height in Java?

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

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!

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.

Slick2d collision detection with Tiles using rectangles

i'm quite stuck. Before I do anything, heres the code:
if(inAir&&!falling&&!jumping){
if(py<600){
if (!(isBlocked(xminusd, py) || isBlocked(xminus, py + 32 - 1))) {
falling=true;
}else{
py-=2;
inAir=false;
}
}
}
for(int g = 0;g<Map.r.size();g++){
if(rect.intersects(Map.r.get(g))||Map.r.get(g).contains(rect)||rect.contains(Map.r.get(g))||Map.r.get(g).intersects(rect)){
System.out.println("Intersecting!");
inAir= false;
hasjumped=false;
onPlat = true;
falling = false;
jumping = false;
py-=4;
break;
}else{
onPlat = false;
if(inAir==false&&!onPlat){
inAir = true;
onPlat = false;
}
}
}
Now the problem is, i'm trying to make collision detection with a certain type of tile, by creating rectangles for each tile, and if the player collides with it it stops all movement.(falling wise at least). But i've run into a problem. I've used an array list, to create all my rectangles, and i'm using a for loop to check each rectangle. Problem is, if it checks a rectangle and i'm not colliding with that rectangle currently, it immidiatly starts falling, then resetting, because it finds the rectangle i'm colliding with. The problem is im using a for loop to cycle through each rectangle... I'm really stuck on how to do collision detection with platform tiles. Anyone have any help to provide? Please be descriptive.
It doesn't look like it matters which rectangle you are colliding with so try abstracting by making a function that returns true or false if it is colliding with any block and put that in your else if statement. that way if you are still colliding it wont start falling while cycling through the rest of your blocks
Something like
...
if(colliding())
{
//stop falling
}
else
{
//start falling
}
....
boolean colliding(){
for(int g = 0;g<Map.r.size();g++){
//check for collision if true return true
}
return false;
}
EDIT:
The reason this works is because as you are going through the for loop it keeps the object falling while it determines that it should stop. By moving the falling logic away from the collision logic we can determine if it is colliding and then take the appropriate action.

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