woadssda
This commit is contained in:
parent
143707f925
commit
ef262325d8
5 changed files with 151 additions and 85 deletions
|
@ -1,4 +0,0 @@
|
|||
don't forget when detecting collisions with moving players I should first check if they already overlap, if yes then push the ball out
|
||||
if two players overlap with the ball then I don't know if you can combine the pushing do it if you can't push it away somehow
|
||||
away I mean so like the ball has the largest possible same angle to both players
|
||||
look I'm too young college how am I supposed to know things
|
|
@ -1,14 +1,18 @@
|
|||
package net.pivipi.ball;
|
||||
|
||||
import javax.print.attribute.standard.MediaSize.Engineering;
|
||||
|
||||
import net.minestom.server.coordinate.Point;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.coordinate.Vec;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.GlobalEventHandler;
|
||||
import net.minestom.server.event.player.PlayerHandAnimationEvent;
|
||||
import net.minestom.server.event.player.PlayerMoveEvent;
|
||||
import net.minestom.server.event.player.PlayerStartSneakingEvent;
|
||||
import net.minestom.server.event.player.PlayerStopSneakingEvent;
|
||||
import net.pivipi.physics.Collision;
|
||||
import net.pivipi.physics.CollisionData;
|
||||
import net.pivipi.world.Stadium;
|
||||
|
||||
public class BallKicker { // TODO apply physics settings here
|
||||
|
@ -17,82 +21,19 @@ public class BallKicker { // TODO apply physics settings here
|
|||
private long lastSneak;
|
||||
private int sneakStreak;
|
||||
|
||||
private double headHeight = 0.3; // too low head kicks will be broken too high normal kicks will be broken
|
||||
private double touchStrength = 1; // when the player walks into a ball
|
||||
private double headJumpStrength = 5; // when the player jumps with a ball on their head, this is multiplied by touchstrength
|
||||
private double dragDownStrength = 1; // when the player touches a ball
|
||||
private double reach = 3;
|
||||
private double verticalReach = 2;
|
||||
private double maxKickStrength = 10; // if reach is 0, but you'll never hit the max
|
||||
|
||||
public BallKicker(Stadium stadium) {
|
||||
this.stadium = stadium;
|
||||
}
|
||||
|
||||
public void setup(GlobalEventHandler globalEventHandler) {
|
||||
globalEventHandler.addListener(PlayerMoveEvent.class, event -> onMove(event));
|
||||
//globalEventHandler.addListener(PlayerMoveEvent.class, event -> onMove(event));
|
||||
globalEventHandler.addListener(PlayerStartSneakingEvent.class, event -> onSneak(event));
|
||||
globalEventHandler.addListener(PlayerStopSneakingEvent.class, event -> onStopSneaking(event));
|
||||
}
|
||||
|
||||
private void onMove(PlayerMoveEvent event) { // is width x
|
||||
Player player = event.getPlayer();
|
||||
Vec movementVec = player.getPosition().sub(player.getPreviousPosition()).asVec();
|
||||
|
||||
double ballXSize = stadium.ball.getBoundingBox().width();
|
||||
double playerXSize = player.getBoundingBox().width();
|
||||
double ballZSize = stadium.ball.getBoundingBox().depth();
|
||||
double playerZSize = player.getBoundingBox().depth();
|
||||
double ballHeight = stadium.ball.getBoundingBox().height();
|
||||
double playerHeight = player.getBoundingBox().height();
|
||||
Pos ballCenterPos = stadium.ball.getPosition();
|
||||
Pos playerCenterPos = event.getNewPosition();
|
||||
|
||||
Pos ballPos = ballCenterPos.sub(ballXSize / 2, 0, ballZSize / 2);
|
||||
Pos playerPos = playerCenterPos.sub(playerXSize / 2, 0, playerZSize / 2);
|
||||
Vec ballDistance = ballCenterPos.sub(playerCenterPos).asVec();
|
||||
|
||||
|
||||
if (ballDistance.y() > 0) {
|
||||
if (ballPos.y() > playerPos.y() + playerHeight) return;
|
||||
} else {
|
||||
if (playerPos.y() > ballPos.y() + ballHeight) return;
|
||||
}
|
||||
|
||||
Vec newBallOffset = new Vec(0);
|
||||
double diffX = 0, diffZ = 0;
|
||||
|
||||
if (ballDistance.x() > 0) {
|
||||
diffX = ballPos.x() - (playerPos.x() + playerXSize);
|
||||
if (diffX < 0) // collides on x+
|
||||
newBallOffset = newBallOffset.withX(-diffX);
|
||||
} else {
|
||||
diffX = playerPos.x() - (ballPos.x() + ballXSize);
|
||||
if (diffX < 0) // collides on x-
|
||||
newBallOffset = newBallOffset.withX(diffX);
|
||||
}
|
||||
|
||||
if (ballDistance.z() > 0) {
|
||||
diffZ = ballPos.z() - (playerPos.z() + playerZSize);
|
||||
if (diffZ < 0)
|
||||
newBallOffset = newBallOffset.withZ(-diffZ);
|
||||
} else {
|
||||
diffZ = playerPos.z() - (ballPos.z() + ballZSize);
|
||||
if (diffZ < 0)
|
||||
newBallOffset = newBallOffset.withZ(diffZ);
|
||||
ballDistance = ballDistance.withY(-dragDownStrength);
|
||||
}
|
||||
|
||||
if (diffX < 0 && diffZ < 0) {
|
||||
if (ballPos.y() - player.getPreviousPosition().y() > playerHeight - headHeight) { // ball on head
|
||||
System.out.println("jumped");
|
||||
double jumpHeight = movementVec.y();
|
||||
if (jumpHeight == 0) return;
|
||||
newBallOffset = new Vec(0, jumpHeight, 0);
|
||||
ballDistance = ballDistance.withY(headJumpStrength);
|
||||
}
|
||||
|
||||
stadium.ball.addPos(diffX < diffZ ? newBallOffset.withX(0) : newBallOffset.withZ(0));
|
||||
stadium.ball.addVelocity(ballDistance.mul(touchStrength));
|
||||
System.out.println(ballDistance);
|
||||
}
|
||||
globalEventHandler.addListener(PlayerHandAnimationEvent.class, event -> onSwing(event));
|
||||
}
|
||||
|
||||
private void onStopSneaking(PlayerStopSneakingEvent event) {
|
||||
|
@ -131,4 +72,17 @@ public class BallKicker { // TODO apply physics settings here
|
|||
sneakStreak = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void onSwing(PlayerHandAnimationEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
CollisionData collisionData = new CollisionData();
|
||||
Collision.pushOutside(player, stadium.ball, collisionData);
|
||||
double distance = collisionData.distance.withY(0).distance(0, 0, 0);
|
||||
|
||||
if (collisionData.distance.y() < verticalReach && distance < reach) {
|
||||
double percent = 1 - distance / reach;
|
||||
stadium.ball.addVelocity(player.getPosition().direction().withY(y -> y + 1 - collisionData.distance.y()).mul(maxKickStrength * percent));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,10 @@ package net.pivipi.physics;
|
|||
import net.minestom.server.collision.BoundingBox;
|
||||
import net.minestom.server.collision.SweepResult;
|
||||
import net.minestom.server.collision.VisibleSweepResult;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.coordinate.Vec;
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.Player;
|
||||
|
||||
public class Collision {
|
||||
/**
|
||||
|
@ -39,4 +41,71 @@ public class Collision {
|
|||
public static boolean collidesWithGround(double groundY, Entity entity) {
|
||||
return new BoundingBox(10, 1, 10).intersectEntity(entity.getPosition().withY(groundY - 1).sub(5, 0, 5), entity);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pusher the entity that's pushing like a player
|
||||
* @param pushed the entity that's being pushed like a ball
|
||||
* @return offset you must apply to push the entity outside, null if doesn't collide
|
||||
*/
|
||||
public static Vec pushOutside(Entity pusher, Entity pushed) {
|
||||
return pushOutside(pusher, pushed, null);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pusher the entity that's pushing like a player
|
||||
* @param pushed the entity that's being pushed like a ball
|
||||
* @param collisionData puts data in this object
|
||||
* @return offset you must apply to push the entity outside, null if doesn't collide
|
||||
*/
|
||||
public static Vec pushOutside(Entity pusher, Entity pushed, CollisionData collisionData) {
|
||||
double ballXSize = pushed.getBoundingBox().width();
|
||||
double playerXSize = pusher.getBoundingBox().width();
|
||||
double ballZSize = pushed.getBoundingBox().depth();
|
||||
double playerZSize = pusher.getBoundingBox().depth();
|
||||
double ballHeight = pushed.getBoundingBox().height();
|
||||
double playerHeight = pusher.getBoundingBox().height();
|
||||
Pos ballCenterPos = pushed.getPosition();
|
||||
Pos playerCenterPos = pusher.getPosition();
|
||||
|
||||
Pos ballPos = ballCenterPos.sub(ballXSize / 2, 0, ballZSize / 2); // corner
|
||||
Pos playerPos = playerCenterPos.sub(playerXSize / 2, 0, playerZSize / 2);
|
||||
Vec ballDistance = ballCenterPos.sub(playerCenterPos).asVec(); // center distance
|
||||
|
||||
if (collisionData != null)
|
||||
collisionData.distance = ballDistance;
|
||||
|
||||
if (ballDistance.y() > 0 && ballPos.y() > playerPos.y() + playerHeight) return null; // doesn't collide on y+
|
||||
else if (playerPos.y() > ballPos.y() + ballHeight) return null; // doesn't collide on y-
|
||||
|
||||
Vec newBallOffset = new Vec(0);
|
||||
double diffX = 0, diffZ = 0;
|
||||
|
||||
if (ballDistance.x() > 0) {
|
||||
diffX = ballPos.x() - (playerPos.x() + playerXSize);
|
||||
if (diffX < 0) // collides on x+
|
||||
newBallOffset = newBallOffset.withX(-diffX);
|
||||
} else {
|
||||
diffX = playerPos.x() - (ballPos.x() + ballXSize);
|
||||
if (diffX < 0) // collides on x-
|
||||
newBallOffset = newBallOffset.withX(diffX);
|
||||
}
|
||||
|
||||
if (ballDistance.z() > 0) {
|
||||
diffZ = ballPos.z() - (playerPos.z() + playerZSize);
|
||||
if (diffZ < 0) // collides on z+
|
||||
newBallOffset = newBallOffset.withZ(-diffZ);
|
||||
} else {
|
||||
diffZ = playerPos.z() - (ballPos.z() + ballZSize);
|
||||
if (diffZ < 0) // collides on z-
|
||||
newBallOffset = newBallOffset.withZ(diffZ);
|
||||
}
|
||||
|
||||
|
||||
if (diffX < 0 && diffZ < 0)
|
||||
return diffX < diffZ ? newBallOffset.withX(0) : newBallOffset.withZ(0);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
10
src/main/java/net/pivipi/physics/CollisionData.java
Normal file
10
src/main/java/net/pivipi/physics/CollisionData.java
Normal file
|
@ -0,0 +1,10 @@
|
|||
package net.pivipi.physics;
|
||||
|
||||
import net.minestom.server.coordinate.Vec;
|
||||
|
||||
public class CollisionData {
|
||||
/**
|
||||
* distance between centers of entities (but bottom y)
|
||||
*/
|
||||
public Vec distance;
|
||||
}
|
|
@ -3,6 +3,7 @@ package net.pivipi.physics;
|
|||
import java.util.Set;
|
||||
|
||||
import net.minestom.server.collision.VisibleSweepResult;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.coordinate.Vec;
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.Player;
|
||||
|
@ -16,6 +17,10 @@ public class Physics {
|
|||
private final double playerSneakingHeadBounciness = 0.2;
|
||||
private final double playerBodyBounciness = 0.2;
|
||||
private final double playerSneakingBodyBounciness = 0;
|
||||
private final double playerCarryStrength = 2;
|
||||
private final double headJumpStrength = 5;
|
||||
private final double headNodStep = 20;
|
||||
private final double jumpStrength = 20;
|
||||
private final double groundFriction = 0.5;
|
||||
private final double airFriction = 0.1;
|
||||
|
||||
|
@ -27,6 +32,7 @@ public class Physics {
|
|||
private Vec velocity = new Vec(0, 0, 0);
|
||||
|
||||
private final Entity entity;
|
||||
private Player holder;
|
||||
private int p;
|
||||
|
||||
public Physics(Entity entity) {
|
||||
|
@ -47,32 +53,23 @@ public class Physics {
|
|||
|
||||
float offset = 0.5f;
|
||||
int count = (int) (f > delta / 1000 ? f / delta / 1000 : 1);
|
||||
System.out.println(f);
|
||||
System.out.println(dist);
|
||||
System.out.println(count);
|
||||
|
||||
entity.getInstance().sendGroupedPacket(new ParticlePacket(Particle.FLAME, false, entity.getPosition().x(), entity.getPosition().y() + 0.5, entity.getPosition().z(), offset, offset, offset, flameSpread, count));
|
||||
}
|
||||
}
|
||||
|
||||
public Vec applyPhysics(double delta, Set<Player> players) {
|
||||
private Vec applyPhysics(double delta, Set<Player> players) {
|
||||
velocity = velocity.sub(0, gravity * delta, 0).mul(1 - (airFriction * delta), 1, 1 - (airFriction * delta));
|
||||
|
||||
if (Collision.collidesWithGround(2, entity)) {
|
||||
entity.teleport(entity.getPosition().withY(2));
|
||||
velocity = velocity.mul(1 - (groundFriction * delta), 1, 1 - (groundFriction * delta));
|
||||
}
|
||||
|
||||
VisibleSweepResult result = Collision.willCollideWithGround(2, entity, velocity.mul(delta));
|
||||
if (result != null) {
|
||||
velocity = velocity.mul(1, -blockBounciness, 1);
|
||||
velocity = velocity.mul(1 - (groundFriction * delta), -blockBounciness, 1 - (groundFriction * delta));
|
||||
} else {
|
||||
for (Player player : players) {
|
||||
boolean collides = Collision.collidesWithEntity(player, entity);
|
||||
if (collides) {
|
||||
if (player.isSneaking())
|
||||
velocity = velocity.mul(-playerSneakingBodyBounciness, -playerSneakingHeadBounciness, -playerSneakingBodyBounciness);
|
||||
else velocity = velocity.mul(-playerBodyBounciness, -playerHeadBounciness, -playerBodyBounciness);
|
||||
handlePlayerTouch(player);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -81,6 +78,46 @@ public class Physics {
|
|||
return velocity;
|
||||
}
|
||||
|
||||
private void handlePlayerTouch(Player player) {
|
||||
CollisionData collisionData = new CollisionData();
|
||||
Vec offset = Collision.pushOutside(player, entity, collisionData); // TODO predict the collision
|
||||
|
||||
if (offset != null) {
|
||||
Pos movementPos = player.getPosition().sub(player.getPreviousPosition());
|
||||
|
||||
boolean oppositeX = (collisionData.distance.x() > 0 ? velocity.x() < 0 : velocity.x() > 0);
|
||||
boolean oppositeZ = (collisionData.distance.z() > 0 ? velocity.z() < 0 : velocity.z() > 0);
|
||||
double headOffsetY = player.getBoundingBox().height() - collisionData.distance.y();
|
||||
|
||||
System.out.println(offset);
|
||||
System.out.println(oppositeX);
|
||||
System.out.println(velocity.x());
|
||||
|
||||
if (headOffsetY < 0.6) { // landed on head, magic value head height
|
||||
if (movementPos.y() > 0) {
|
||||
double headPitchDiff = Math.abs(movementPos.pitch());
|
||||
System.out.println(headPitchDiff);
|
||||
addVelocity(player.getPosition().direction().mul(headPitchDiff / headNodStep).withY(headJumpStrength));
|
||||
} else velocity = velocity.mul(1, player.isSneaking() ? -playerSneakingHeadBounciness : -playerHeadBounciness, 1);
|
||||
entity.teleport(entity.getPosition().withY(y -> y + headOffsetY));
|
||||
} else {
|
||||
System.out.println("tping");
|
||||
entity.teleport(entity.getPosition().add(offset.mul(1.1))); // magic value to make some space in case of desync
|
||||
double bodyBounciness = player.isSneaking() ? -playerSneakingBodyBounciness : -playerBodyBounciness;
|
||||
|
||||
System.out.println(velocity);
|
||||
|
||||
velocity = velocity
|
||||
.withX(x -> oppositeX ? x * bodyBounciness : x + movementPos.x() * playerCarryStrength)
|
||||
.withY(y -> collisionData.distance.y() < 1.0 ? movementPos.y() * jumpStrength : y) // magic value legs
|
||||
.withZ(z -> oppositeZ ? z * bodyBounciness : z + movementPos.z() * playerCarryStrength);
|
||||
|
||||
System.out.println(velocity);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void addVelocity(Vec velocity) {
|
||||
this.velocity = this.velocity.add(velocity);
|
||||
|
|
Loading…
Reference in a new issue