|
@@ -1,7 +1,5 @@
|
|
|
package me.hammerle.supersnuvi.entity;
|
|
|
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.List;
|
|
|
import me.hammerle.supersnuvi.entity.components.ai.Controller;
|
|
|
import me.hammerle.supersnuvi.entity.components.Energy;
|
|
|
import me.hammerle.supersnuvi.entity.components.Health;
|
|
@@ -17,7 +15,7 @@ import me.hammerle.supersnuvi.entity.components.IDespawn;
|
|
|
public final class Entity
|
|
|
{
|
|
|
public static final float GRAVITY = 8.0f * Tile.SIZE_SCALE;
|
|
|
- public static final float STEP = 0.0625f;
|
|
|
+ public static final float STEP = 0.015625f;
|
|
|
// this one is a little bit bigger to prevent wrong calculation
|
|
|
// while going upwards
|
|
|
public static final float UP_STEP = STEP + 0.00390625f;
|
|
@@ -37,6 +35,7 @@ public final class Entity
|
|
|
// the motion, reduced by the movement collision check
|
|
|
private final Vector motion = new Vector();
|
|
|
// the friction reducing motion each tick
|
|
|
+ private final Vector baseFriction = new Vector(0.0f, 1.0f);
|
|
|
private final Vector friction = new Vector(0.0f, 1.0f);
|
|
|
// a flag indicating that the entity is on the ground
|
|
|
private boolean onGround = true;
|
|
@@ -49,6 +48,7 @@ public final class Entity
|
|
|
private final IDespawn onDespawn;
|
|
|
// the type of the entity, used by snuvi script
|
|
|
private final String type;
|
|
|
+ private Face direction = Face.NULL;
|
|
|
|
|
|
protected Entity(float width, float height, Controller c, Health h, Energy e, Movement m, ItemCollector ic, IDespawn d, String type)
|
|
|
{
|
|
@@ -192,9 +192,14 @@ public final class Entity
|
|
|
motion.add(x, y);
|
|
|
}
|
|
|
|
|
|
- public void setFriction(float fx, float fy)
|
|
|
+ public void setBaseFriction(float fx, float fy)
|
|
|
{
|
|
|
- friction.set(fx, fy);
|
|
|
+ baseFriction.set(fx, fy);
|
|
|
+ }
|
|
|
+
|
|
|
+ public Vector getFriction()
|
|
|
+ {
|
|
|
+ return friction;
|
|
|
}
|
|
|
|
|
|
public boolean isAt(float x, float y)
|
|
@@ -229,6 +234,11 @@ public final class Entity
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ public Face getDirection()
|
|
|
+ {
|
|
|
+ return direction;
|
|
|
+ }
|
|
|
+
|
|
|
//--------------------------------------------------------------------------
|
|
|
// ticking
|
|
|
//--------------------------------------------------------------------------
|
|
@@ -240,16 +250,20 @@ public final class Entity
|
|
|
lastMotion.set(0.0f, 0.0f);
|
|
|
|
|
|
// reset own force
|
|
|
- ownForce.set(0.0f, 0.0f);
|
|
|
-
|
|
|
- // remeber last position for rendering
|
|
|
- lastPos.set(pos);
|
|
|
+ ownForce.set(0.0f, 0.0f);
|
|
|
|
|
|
// update onGround before controller tick
|
|
|
onGround = isOnTileGround(level);
|
|
|
if(onGround)
|
|
|
{
|
|
|
- motion.setY(0.0f);
|
|
|
+ if(!move.canMoveOnTiles())
|
|
|
+ {
|
|
|
+ motion.setY(0.0f);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ friction.set(0.2f, 1.0f);
|
|
|
}
|
|
|
|
|
|
// tick components
|
|
@@ -262,13 +276,31 @@ public final class Entity
|
|
|
{
|
|
|
motion.addY(GRAVITY * move.getGravityFactor());
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// apply friction
|
|
|
motion.mul(friction);
|
|
|
+ if(move.isInWater())
|
|
|
+ {
|
|
|
+ motion.mul(friction);
|
|
|
+ move.setInWater(false);
|
|
|
+ }
|
|
|
+ friction.set(baseFriction);
|
|
|
|
|
|
// modify current motion by own force
|
|
|
motion.add(ownForce);
|
|
|
|
|
|
+ if(ownForce.getX() < 0.0f)
|
|
|
+ {
|
|
|
+ direction = Face.LEFT;
|
|
|
+ }
|
|
|
+ else if(ownForce.getX() > 0.0f)
|
|
|
+ {
|
|
|
+ direction = Face.RIGHT;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void tickCollision(Level level)
|
|
|
+ {
|
|
|
// (entity <-> tile) collision
|
|
|
doTileCollision(level);
|
|
|
// (entity <-> entity) collision
|
|
@@ -276,6 +308,11 @@ public final class Entity
|
|
|
{
|
|
|
controller.onCollideWithEntity(this, ent, getCollidingFace(ent));
|
|
|
});
|
|
|
+
|
|
|
+ slideOnEdge(level);
|
|
|
+
|
|
|
+ // remeber last position for rendering
|
|
|
+ lastPos.set(pos);
|
|
|
}
|
|
|
|
|
|
public int move(Level level)
|
|
@@ -287,8 +324,10 @@ public final class Entity
|
|
|
Vector maxMotion = new Vector();
|
|
|
maxMotion.set(motion);
|
|
|
|
|
|
- reduceMotionByTiles(level);
|
|
|
- reduceMotionByEntities(level);
|
|
|
+ if(!move.canMoveOnEntities() || !move.canMoveOnTiles())
|
|
|
+ {
|
|
|
+ reduceMotion(level);
|
|
|
+ }
|
|
|
pos.add(motion);
|
|
|
|
|
|
int r = (motion.getX() == 0.0f && motion.getY() == 0.0f) ? 0 : 1;
|
|
@@ -363,112 +402,12 @@ public final class Entity
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void reduceMotionByEntities(Level level)
|
|
|
+ private boolean isCollidingWithTiles(int startX, int startY, int endX, int endY, Level level)
|
|
|
{
|
|
|
- if(motion.getX() == 0.0f && motion.getY() == 0.0f)
|
|
|
+ if(move.canMoveOnTiles())
|
|
|
{
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- float mx = motion.getX();
|
|
|
- float my = motion.getY();
|
|
|
-
|
|
|
- float oldPosX = pos.getX();
|
|
|
- float oldPosY = pos.getY();
|
|
|
-
|
|
|
- while(mx != 0.0 || my != 0.0)
|
|
|
- {
|
|
|
- if(mx != 0.0f)
|
|
|
- {
|
|
|
- float oldX = pos.getX();
|
|
|
- if(mx < 0.0)
|
|
|
- {
|
|
|
- if(mx > -STEP)
|
|
|
- {
|
|
|
- pos.addX(mx);
|
|
|
- mx = 0.0f;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- pos.addX(-STEP);
|
|
|
- mx += STEP;
|
|
|
- }
|
|
|
- }
|
|
|
- else if(mx > 0.0)
|
|
|
- {
|
|
|
- if(mx < STEP)
|
|
|
- {
|
|
|
- pos.addX(mx);
|
|
|
- mx = 0.0f;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- pos.addX(STEP);
|
|
|
- mx -= STEP;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- List<Entity> list = isCollidingWithEntities(level);
|
|
|
- for(Entity ent : list)
|
|
|
- {
|
|
|
- if(move.isSolid() || ent.move.isSolid())
|
|
|
- {
|
|
|
- //controller.onCollideWithEntity(this, ent, getCollidingFace(ent));
|
|
|
- pos.setX(oldX);
|
|
|
- mx = 0.0f;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if(my != 0.0f)
|
|
|
- {
|
|
|
- float oldY = pos.getY();
|
|
|
-
|
|
|
- if(my < 0.0)
|
|
|
- {
|
|
|
- if(my > -STEP)
|
|
|
- {
|
|
|
- pos.addY(my);
|
|
|
- my = 0.0f;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- pos.addY(-STEP);
|
|
|
- my += STEP;
|
|
|
- }
|
|
|
- }
|
|
|
- else if(my > 0.0)
|
|
|
- {
|
|
|
- if(my < STEP)
|
|
|
- {
|
|
|
- pos.addY(my);
|
|
|
- my = 0.0f;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- pos.addY(STEP);
|
|
|
- my -= STEP;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- List<Entity> list = isCollidingWithEntities(level);
|
|
|
- for(Entity ent : list)
|
|
|
- {
|
|
|
- if(move.isSolid() || ent.move.isSolid())
|
|
|
- {
|
|
|
- //controller.onCollideWithEntity(this, ent, getCollidingFace(ent));
|
|
|
- pos.setY(oldY);
|
|
|
- my = 0.0f;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ return false;
|
|
|
}
|
|
|
-
|
|
|
- motion.set(pos.getX() - oldPosX, pos.getY() - oldPosY);
|
|
|
- pos.set(oldPosX, oldPosY);
|
|
|
- }
|
|
|
-
|
|
|
- private boolean isCollidingWithTiles(int startX, int startY, int endX, int endY, Level level)
|
|
|
- {
|
|
|
float minX = getX();
|
|
|
float minY = getY();
|
|
|
float maxX = minX + width;
|
|
@@ -486,22 +425,25 @@ public final class Entity
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- private List<Entity> isCollidingWithEntities(Level level)
|
|
|
+ private boolean isCollidingWithEntities(Level level)
|
|
|
{
|
|
|
+ if(move.canMoveOnEntities())
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
float minX = pos.getX();
|
|
|
float minY = pos.getY();
|
|
|
float maxX = pos.getX() + width;
|
|
|
float maxY = pos.getY() + height;
|
|
|
- ArrayList<Entity> list = new ArrayList<>();
|
|
|
for(Entity ent : level.getEntities())
|
|
|
{
|
|
|
if(ent == this)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
- if(ent.isColliding(minX, minY, maxX, maxY))
|
|
|
+ if(ent.isColliding(minX, minY, maxX, maxY) && (move.isSolid() || ent.move.isSolid()))
|
|
|
{
|
|
|
- list.add(ent);
|
|
|
+ return true;
|
|
|
}
|
|
|
}
|
|
|
for(Entity ent : level.getEntitiesInQueue())
|
|
@@ -510,17 +452,17 @@ public final class Entity
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
- if(ent.isColliding(minX, minY, maxX, maxY))
|
|
|
+ if(ent.isColliding(minX, minY, maxX, maxY) && (move.isSolid() || ent.move.isSolid()))
|
|
|
{
|
|
|
- list.add(ent);
|
|
|
+ return true;
|
|
|
}
|
|
|
}
|
|
|
- return list;
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
- public void reduceMotionByTiles(Level level)
|
|
|
+ public void reduceMotion(Level level)
|
|
|
{
|
|
|
- if(move.canMoveEverywhere() || (motion.getX() == 0.0f && motion.getY() == 0.0f))
|
|
|
+ if(motion.getX() == 0.0f && motion.getY() == 0.0f)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
@@ -590,10 +532,10 @@ public final class Entity
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if(isCollidingWithTiles(startX, startY, endX, endY, level))
|
|
|
+ if(isCollidingWithTiles(startX, startY, endX, endY, level) || isCollidingWithEntities(level))
|
|
|
{
|
|
|
pos.addY(-UP_STEP);
|
|
|
- if(isCollidingWithTiles(startX, startY, endX, endY, level))
|
|
|
+ if(isCollidingWithTiles(startX, startY, endX, endY, level) || isCollidingWithEntities(level))
|
|
|
{
|
|
|
pos.addY(UP_STEP);
|
|
|
pos.setX(oldX);
|
|
@@ -632,7 +574,7 @@ public final class Entity
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if(isCollidingWithTiles(startX, startY, endX, endY, level))
|
|
|
+ if(isCollidingWithTiles(startX, startY, endX, endY, level) || isCollidingWithEntities(level))
|
|
|
{
|
|
|
my = 0.0f;
|
|
|
pos.setY(oldY);
|
|
@@ -644,6 +586,49 @@ public final class Entity
|
|
|
pos.set(oldPosX, oldPosY);
|
|
|
}
|
|
|
|
|
|
+ private void slideOnEdge(Level level)
|
|
|
+ {
|
|
|
+ float minY = pos.getY() + height;
|
|
|
+ float maxY = pos.getY() + height + STEP * 2;
|
|
|
+
|
|
|
+ float minX = pos.getX();
|
|
|
+ float midX = pos.getX() + width * 0.5f;
|
|
|
+ float maxX = pos.getX() + width;
|
|
|
+
|
|
|
+ int startX = Utils.toBlock(minX);
|
|
|
+ int startY = Utils.toBlock(minY);
|
|
|
+ int endX = Utils.toBlock(maxX);
|
|
|
+ int endY = Utils.toBlock(maxY);
|
|
|
+
|
|
|
+ int leftEdges = 0;
|
|
|
+ int rightEdges = 0;
|
|
|
+
|
|
|
+ for(int x = startX; x <= endX; x++)
|
|
|
+ {
|
|
|
+ for(int y = startY; y <= endY; y++)
|
|
|
+ {
|
|
|
+ Tile t = level.getInteractionTile(x, y);
|
|
|
+ if(t.isMoveColliding(minX, minY, midX, maxY, x, y, level))
|
|
|
+ {
|
|
|
+ rightEdges++;
|
|
|
+ }
|
|
|
+ if(t.isMoveColliding(midX, minY, maxX, maxY, x, y, level))
|
|
|
+ {
|
|
|
+ leftEdges++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(leftEdges == 0)
|
|
|
+ {
|
|
|
+ applyForce(STEP * 25, 0.0f);
|
|
|
+ }
|
|
|
+ if(rightEdges == 0)
|
|
|
+ {
|
|
|
+ applyForce(-STEP * 25, 0.0f);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public void renderTick(float lag)
|
|
|
{
|
|
|
controller.renderTick(this, lag);
|