123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- package me.hammerle.supersnuvi.entity;
- 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;
- import me.hammerle.supersnuvi.entity.components.ItemCollector;
- import me.hammerle.supersnuvi.entity.components.Movement;
- import me.hammerle.supersnuvi.gamelogic.Level;
- import me.hammerle.supersnuvi.util.CollisionObject;
- import me.hammerle.supersnuvi.util.Face;
- import me.hammerle.supersnuvi.util.Utils;
- public final class Entity
- {
- public static final float GRAVITY = 8.0f;
- public static final float STEP = 0.0625f;
- // this one is a little bit bigger to prevent wrong calculation
- // while joing upwars
- public static final float UP_STEP = STEP + 0.001953125f;
-
- // the last position is used for interpolation during rendering
- private float lastPosX;
- private float lastPosY;
- // the current position of the entity
- private float posX;
- private float posY;
-
- // the collision box of the entity
- private final CollisionObject box;
-
- // the motion before the movement collision check
- private float preMotionX;
- private float preMotionY;
- // the motion after the movement collision check
- private float motionX;
- private float motionY;
-
- // a flag indicating that the entity is on the ground
- private boolean onGround = false;
-
- // the level of the entity
- private final Level level;
-
- // entity components
- protected Controller controller;
- protected Health health;
- protected Energy energy;
- protected Movement move;
- protected ItemCollector itemCollector;
-
- // face
- private Face face;
-
- protected Entity(Level level, float x, float y, CollisionObject box)
- {
- lastPosX = x;
- lastPosY = y;
- posX = x;
- posY = y;
- // ensure the box cannot be modified from the outside
- this.box = box.copy().offset(x, y);
-
- preMotionX = 0.0f;
- preMotionY = 0.0f;
- motionX = 0.0f;
- motionY = 0.0f;
-
- this.level = level;
-
- // components
- this.controller = Controller.NULL;
- this.health = Health.NULL;
- this.energy = Energy.NULL;
- this.move = Movement.NULL;
- this.itemCollector = ItemCollector.NULL;
- }
-
- public Level getLevel()
- {
- return level;
- }
-
- //--------------------------------------------------------------------------
- // components
- //--------------------------------------------------------------------------
-
- public boolean isAnimated()
- {
- return controller.isAnimated();
- }
-
- public Health getHealth()
- {
- return health;
- }
-
- public Energy getEnergy()
- {
- return energy;
- }
-
- public Movement getMovement()
- {
- return move;
- }
-
- public ItemCollector getItemCollector()
- {
- return itemCollector;
- }
-
- //--------------------------------------------------------------------------
- // basic stuff
- //--------------------------------------------------------------------------
-
- public float getSquaredDistance(Entity e)
- {
- return Utils.getSquaredDistance(
- posX + box.getWidth() * 0.5f, posY + box.getHeight() * 0.5f,
- e.posX + e.box.getWidth() * 0.5f, e.posY + e.box.getHeight() * 0.5f);
- }
-
- public CollisionObject getBox()
- {
- return box;
- }
-
- public float getX()
- {
- return posX;
- }
-
- public float getY()
- {
- return posY;
- }
-
- public float getLastX()
- {
- return lastPosX;
- }
-
- public float getLastY()
- {
- return lastPosY;
- }
-
- public float getCenterX()
- {
- return posX + box.getWidth() * 0.5f;
- }
-
- public float getCenterY()
- {
- return posY + box.getHeight() * 0.5f;
- }
-
- public Face getFace()
- {
- return face;
- }
-
- public float getMotionX()
- {
- return motionX;
- }
-
- public void setMotionX(float motionX)
- {
- this.motionX = motionX;
- }
-
- public float getMotionY()
- {
- return motionY;
- }
-
- public void setMotionY(float motionY)
- {
- this.motionY = motionY;
- }
-
- public float getPreMotionX()
- {
- return preMotionX;
- }
-
- public float getPreMotionY()
- {
- return preMotionY;
- }
-
- //--------------------------------------------------------------------------
- // ticking
- //--------------------------------------------------------------------------
-
- public void tick()
- {
- lastPosX = posX;
- lastPosY = posY;
-
- controller.tick();
- energy.tick();
-
- preMotionX = motionX;
- preMotionY = motionY;
-
- if(preMotionX != 0.0f)
- {
- face = preMotionX > 0.0f ? Face.RIGHT : Face.LEFT;
- }
-
- if(move.hasGravity())
- {
- preMotionY += GRAVITY * move.getGravityFactor();
- }
- if(move.canMoveEverywhere())
- {
- motionX = preMotionX;
- motionY = preMotionY;
- }
- else
- {
- CollisionObject testBox = box.copy().expand(preMotionX, preMotionY);
- List<CollisionObject> boxes = level.getMovementBoxesAt(testBox, this);
- if(!boxes.isEmpty())
- {
- float mx = preMotionX;
- float my = preMotionY;
-
- testBox.reset();
-
- float oldX = testBox.getMinX();
- float oldY = testBox.getMinY();
-
- while(mx != 0.0 || my != 0.0)
- {
- testBox.save();
- if(mx < 0.0)
- {
- if(mx > -STEP)
- {
- testBox.offsetX(mx);
- mx = 0.0f;
- }
- else
- {
- testBox.offsetX(-STEP);
- mx += STEP;
- }
- }
- else if(mx > 0.0)
- {
- if(mx < STEP)
- {
- testBox.offsetX(mx);
- mx = 0.0f;
- }
- else
- {
- testBox.offsetX(STEP);
- mx -= STEP;
- }
- }
- for(CollisionObject cb : boxes)
- {
- if(cb.isColliding(testBox))
- {
- testBox.offsetY(-UP_STEP);
- for(CollisionObject cb2 : boxes)
- {
- if(cb2.isColliding(testBox))
- {
- mx = 0.0f;
- testBox.reset();
- break;
- }
- }
- break;
- }
- }
-
- testBox.save();
- if(my < 0.0)
- {
- if(my > -STEP)
- {
- testBox.offsetY(my);
- my = 0.0f;
- }
- else
- {
- testBox.offsetY(-STEP);
- my += STEP;
- }
- }
- else if(my > 0.0)
- {
- if(my < STEP)
- {
- testBox.offsetY(my);
- my = 0.0f;
- }
- else
- {
- testBox.offsetY(STEP);
- my -= STEP;
- }
- }
- for(CollisionObject cb : boxes)
- {
- if(cb.isColliding(testBox))
- {
- my = 0.0f;
- testBox.reset();
- break;
- }
- }
- }
-
- motionX = testBox.getMinX() - oldX;
- motionY = testBox.getMinY() - oldY;
-
- /*if(motionX != 0.0f || motionY != 0.0f)
- {
- System.out.println("____________________");
- System.out.println(testBox + " " + preMotionX + " " + preMotionY);
- System.out.println(box);
- boxes.forEach(b -> System.out.println(b));
- System.out.println(motionX + " " + motionY);
- System.out.println("____________________");
- }*/
- }
- else
- {
- motionX = preMotionX;
- motionY = preMotionY;
- }
- }
-
- posX += motionX;
- posY += motionY;
- box.reset().offset(posX, posY);
-
- //onGround = preMotionY > 0.0f && motionY == 0;
- onGround = !level.getCollisionBoxesAt(box.copy().expand(0.0f, STEP * 2)).isEmpty();
-
- move.setInWater(false);
- move.setFrictionFactor(0.6f);
- // apply collision
- CollisionObject cb = box.copy();
- for(Face f : Face.values())
- {
- cb.reset();
- cb.expand(f.getCollisionOffsetX(), f.getCollisionOffsetY());
- level.getEntitiesCollidingWith(this, box).forEach(ent -> ent.controller.onCollideWithEntity(ent, f));
- level.getCollisionBoxesAt(cb).forEach(loc ->
- {
- controller.onCollideWithTile(loc, f);
- loc.getTile().onEntityCollide(this, loc.getX(), loc.getY(), f.getOpposite());
- });
- }
-
- motionX *= move.getFrictionFactor();
- if(Math.abs(motionX) < 0.3)
- {
- motionX = 0.0f;
- }
-
- health.tick();
- }
-
- public void renderTick(float lag)
- {
- controller.renderTick(lag);
- }
-
- //--------------------------------------------------------------------------
- // gravity, friction
- //--------------------------------------------------------------------------
-
- public boolean isOnGround()
- {
- return onGround;
- }
- }
|