123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616 |
- package me.hammerle.supersnuvi.entity;
- import java.util.LinkedList;
- import javafx.scene.image.Image;
- import javafx.scene.paint.Color;
- import me.hammerle.supersnuvi.gamelogic.Level;
- import me.hammerle.supersnuvi.input.IKeyHandler;
- import me.hammerle.supersnuvi.rendering.GameRenderer;
- import me.hammerle.supersnuvi.tiles.Location;
- import me.hammerle.supersnuvi.util.CollisionBox;
- import me.hammerle.supersnuvi.util.Face;
- import me.hammerle.supersnuvi.util.Utils;
- public class Entity
- {
- // 1 Tile = 1 m
- // Pixel m s Pixel
- // ----- * --- * ------ = -------
- // m s Tick Tick
- // added correction factor, real life gravity seems to strong
- public static double GRAVITY = GameRenderer.TILE_SIZE * 9.81 / 60 * 0.1;
-
- private double prevPosX;
- private double prevPrevY;
- private double posX;
- private double posY;
-
- private double prevMotionX;
- private double prevMotionY;
- private double motionX;
- private double motionY;
- private boolean onGround;
- private boolean inWater;
-
- private final CollisionBox collisionBox;
- private final double width;
- private final double height;
-
- private Image image;
-
- private final Level level;
-
- public Entity(Level level, double x, double y, double width, double height)
- {
- this.level = level;
- this.posX = x;
- this.posY = y;
- this.prevPosX = x;
- this.prevPrevY = y;
- this.motionX = 0;
- this.motionY = 0;
- this.onGround = false;
- this.inWater = false;
- this.collisionBox = new CollisionBox(0, 0, width, height);
- this.width = width;
- this.height = height;
-
- image = Utils.getColoredImage(Color.BLACK, (int) width, (int) height);
- }
- public Level getLevel()
- {
- return level;
- }
-
- //--------------------------------------------------------------------------
- // ticking
- //--------------------------------------------------------------------------
-
- public void controlTick(IKeyHandler keyHandler)
- {
- }
-
- public final void tick()
- {
- if(isAffectedByGravity())
- {
- motionY -= GRAVITY;
- }
-
- prevMotionX = motionX;
- prevMotionY = motionY;
-
- prevPosX = posX;
- prevPrevY = posY;
- setAllowedMotion();
- posX += motionX;
- posY += motionY;
-
- motionX = Utils.round(motionX);
- motionY = Utils.round(motionY);
-
- if(motionY != 0)
- {
- onGround = false;
- }
-
- posX = Utils.round(posX);
- posY = Utils.round(posY);
-
- if(!onGround)
- {
- motionX *= 0.7;
- }
-
- LinkedList<CollisionBox> list = level.getMovementBoxesAt(this, getBox());
- if(!list.isEmpty())
- {
- System.out.println(getBox());
- list.forEach(s -> System.out.println(s));
- System.out.println("WELL");
- posX = prevPosX;
- posY = prevPrevY;
- }
-
- doCollision();
- }
-
- //--------------------------------------------------------------------------
- // gravity, friction
- //--------------------------------------------------------------------------
-
- public final boolean jump()
- {
- if(onGround)
- {
- onGround = false;
- motionY += getJumpPower();
- return true;
- }
- return false;
- }
-
- public boolean isAffectedByGravity()
- {
- return true;
- }
-
- public double getJumpPower()
- {
- return 0;
- }
-
- public boolean isOnGround()
- {
- return onGround;
- }
-
- public final double getMaxSpeedModifier()
- {
- double max = 1;
- if(inWater)
- {
- max *= 0.65;
- }
- return max;
- }
-
- public final void setInWater(boolean b)
- {
- inWater = b;
- }
-
- public final boolean isInWater()
- {
- return inWater;
- }
-
- public final void resetMovementData()
- {
- inWater = false;
- }
-
- //--------------------------------------------------------------------------
- // collision stuff
- //--------------------------------------------------------------------------
-
- public final CollisionBox getBox()
- {
- return collisionBox.reset().offset(posX, posY);
- }
-
- private void setAllowedMotion()
- {
- if(motionX == 0 && motionY == 0)
- {
- return;
- }
- double dirX = motionX;
- double dirY = motionY;
- double startX = posX;
- double startY = posY;
- double endX = startX + dirX;
- double endY = startY + dirY;
-
-
- CollisionBox eBox = getBox();
- double halfWidth = eBox.getWidth() / 2;
- double halfHeight = eBox.getHeight() / 2;
- eBox = eBox.copy();
-
- startX += halfWidth;
- startY += halfHeight;
- endX += halfWidth;
- endY += halfHeight;
-
- // expanding area by the size of the entity
- CollisionBox expandedBox = eBox.copy().expand(motionX, motionY);
-
- LinkedList<CollisionBox> allBoxes = level.getMovementBoxesAt(this, expandedBox);
- if(allBoxes.isEmpty())
- {
- return;
- }
-
- double x;
- double y;
- char lastWall = 0;
-
- if(dirX >= 0)
- {
- if(dirY <= 0) // Right - Down
- {
- for(CollisionBox box : allBoxes)
- {
- box.grow(halfWidth, halfHeight);
- if(endX <= box.getMinX() || endY >= box.getMaxY() ||
- startX >= box.getMaxX() || startY <= box.getMinY())
- {
- continue;
- }
- x = Utils.interpolateX(startX, startY, endX, endY, box.getMaxY());
- y = Utils.interpolateY(startX, startY, endX, endY, box.getMinX());
- if(y > box.getMinY() && y < box.getMaxY())
- {
- endX = box.getMinX();
- endY = y;
- lastWall = 'x';
- }
- else if(x > box.getMinX() && x < box.getMaxX())
- {
- endY = box.getMaxY();
- endX = x;
- lastWall = 'y';
- }
- else if(x >= box.getMinX() && x <= box.getMaxX())
- {
- lastWall = 'y';
- }
- }
- if(lastWall == 'x')
- {
- double lineEndY = startY + dirY;
- for(CollisionBox box : allBoxes)
- {
- if(endX <= box.getMinX() || lineEndY >= box.getMaxY() ||
- endX >= box.getMaxX() || endY <= box.getMinY())
- {
- continue;
- }
- lineEndY = box.getMaxY();
- }
- endY = lineEndY;
- }
- else if(lastWall == 'y')
- {
- double lineEndX = startX + dirX;
- for(CollisionBox box : allBoxes)
- {
- if(lineEndX <= box.getMinX() || endY >= box.getMaxY() ||
- endX >= box.getMaxX() || endY <= box.getMinY())
- {
- continue;
- }
- lineEndX = box.getMinX();
- }
- endX = lineEndX;
- }
- }
- else // Right - Up
- {
- for(CollisionBox box : allBoxes)
- {
- box.grow(halfWidth, halfHeight);
- if(endX <= box.getMinX() || endY <= box.getMinY() ||
- startX >= box.getMaxX() || startY >= box.getMaxY())
- {
- continue;
- }
- x = Utils.interpolateX(startX, startY, endX, endY, box.getMinY());
- y = Utils.interpolateY(startX, startY, endX, endY, box.getMinX());
- if(y > box.getMinY() && y < box.getMaxY())
- {
- endX = box.getMinX();
- endY = y;
- lastWall = 'x';
- }
- else if(x > box.getMinX() && x < box.getMaxX())
- {
- endY = box.getMinY();
- endX = x;
- lastWall = 'y';
- }
- else if(x >= box.getMinX() && x <= box.getMaxX())
- {
- lastWall = 'y';
- }
- }
- if(lastWall == 'x')
- {
- double lineEndY = startY + dirY;
- for(CollisionBox box : allBoxes)
- {
- if(endX <= box.getMinX() || lineEndY <= box.getMinY() ||
- endX >= box.getMaxX() || endY >= box.getMaxY())
- {
- continue;
- }
- lineEndY = box.getMinY();
- }
- endY = lineEndY;
- }
- else if(lastWall == 'y')
- {
- double lineEndX = startX + dirX;
- for(CollisionBox box : allBoxes)
- {
- if(lineEndX <= box.getMinX() || endY >= box.getMaxY() ||
- endX >= box.getMaxX() || endY <= box.getMinY())
- {
- continue;
- }
- lineEndX = box.getMinX();
- }
- endX = lineEndX;
- }
- }
- }
- else
- {
- if(dirY <= 0) // Left - Down
- {
- for(CollisionBox box : allBoxes)
- {
- box.grow(halfWidth, halfHeight);
- if(endX >= box.getMaxX() || endY >= box.getMaxY() ||
- startX <= box.getMinX() || startY <= box.getMinY())
- {
- continue;
- }
- x = Utils.interpolateX(startX, startY, endX, endY, box.getMaxY());
- y = Utils.interpolateY(startX, startY, endX, endY, box.getMaxX());
- if(y > box.getMinY() && y < box.getMaxY())
- {
- endX = box.getMaxX();
- endY = y;
- lastWall = 'x';
- }
- else if(x > box.getMinX() && x < box.getMaxX())
- {
- endY = box.getMaxY();
- endX = x;
- lastWall = 'y';
- }
- else if(x >= box.getMinX() && x <= box.getMaxX())
- {
- lastWall = 'y';
- }
- }
- if(lastWall == 'x')
- {
- double lineEndY = startY + dirY;
- for(CollisionBox box : allBoxes)
- {
- if(endX <= box.getMinX() || lineEndY >= box.getMaxY() ||
- endX >= box.getMaxX() || endY <= box.getMinY())
- {
- continue;
- }
- lineEndY = box.getMaxY();
- }
- endY = lineEndY;
- }
- else if(lastWall == 'y')
- {
- double lineEndX = startX + dirX;
- for(CollisionBox box : allBoxes)
- {
- if(lineEndX >= box.getMaxX() || endY >= box.getMaxY() ||
- endX <= box.getMinX() || endY <= box.getMinY())
- {
- continue;
- }
- lineEndX = box.getMaxX();
- }
- endX = lineEndX;
- }
- }
- else // Left - Up
- {
- for(CollisionBox box : allBoxes)
- {
- box.grow(halfWidth, halfHeight);
- if(endX >= box.getMaxX() || endY <= box.getMinY() ||
- startX <= box.getMinX() || startY >= box.getMaxY())
- {
- continue;
- }
- x = Utils.interpolateX(startX, startY, endX, endY, box.getMinY());
- y = Utils.interpolateY(startX, startY, endX, endY, box.getMaxX());
- if(y > box.getMinY() && y < box.getMaxY())
- {
- endX = box.getMaxX();
- endY = y;
- lastWall = 'x';
- }
- else if(x > box.getMinX() && x < box.getMaxX())
- {
- endY = box.getMinY();
- endX = x;
- lastWall = 'y';
- }
- else if(x >= box.getMinX() && x <= box.getMaxX())
- {
- lastWall = 'y';
- }
- }
- if(lastWall == 'x')
- {
- double lineEndY = startY + dirY;
- for(CollisionBox box : allBoxes)
- {
- if(endX <= box.getMinX() || lineEndY <= box.getMinY() ||
- endX >= box.getMaxX() || endY >= box.getMaxY())
- {
- continue;
- }
- lineEndY = box.getMinY();
- }
- endY = lineEndY;
- }
- else if(lastWall == 'y')
- {
- double lineEndX = startX + dirX;
- for(CollisionBox box : allBoxes)
- {
- if(lineEndX >= box.getMaxX() || endY >= box.getMaxY() ||
- endX <= box.getMinX() || endY <= box.getMinY())
- {
- continue;
- }
- lineEndX = box.getMaxX();
- }
- endX = lineEndX;
- }
- }
- }
-
- motionX = endX - startX;
- motionY = endY - startY;
-
- if(dirY < 0 && motionY == 0)
- {
- onGround = true;
- }
-
- if(Math.abs(motionY) >= 1000 || Math.abs(motionX) >= 1000)
- {
- System.err.println("illegal movement " + motionX + " " + motionY);
- System.exit(0);
- }
-
- /*if(!onGround && Math.abs(dirY) - Math.abs(motionY) > 1)
- {
- System.out.println("\nVORHER " + dirX + " " + dirY);
- System.out.println("NACHHER " + motionX + " " + motionY);
- System.out.println("\nPOS " + posX + " " + posY);
- System.exit(0);
- }*/
- //System.exit(0);
- }
-
- private void doCollision()
- {
- CollisionBox box = getBox().copy();
- for(Face f : Face.values())
- {
- box.reset();
- box.expand(f.getCollisionOffsetX(), f.getCollisionOffsetY());
- level.getEntitiesCollidingWith(this, box).forEach(ent -> this.onCollideWithEntity(ent, f));
- level.getTilesCollidingWith(box).forEach(loc ->
- {
- this.onCollideWithTile(loc, f);
- loc.getTile().onEntityCollide(this, loc.getX(), loc.getY(), f);
- });
- }
- }
-
- public void onCollideWithTile(Location loc, Face face)
- {
- }
-
- public void onCollideWithEntity(Entity ent, Face face)
- {
- }
-
- //--------------------------------------------------------------------------
- // basic coord and motion stuff
- //--------------------------------------------------------------------------
-
- public final double getX()
- {
- return posX;
- }
-
- public final double getY()
- {
- return posY;
- }
-
- public final double getPreviousX()
- {
- return prevPosX;
- }
-
- public final double getPreviousY()
- {
- return prevPrevY;
- }
-
- public boolean isMoving()
- {
- return motionX != 0.0 || motionY != 0.0;
- }
-
- public final double getMotionX()
- {
- return motionX;
- }
-
- public final void setMotionX(double motionX)
- {
- prevMotionX = this.motionX;
- this.motionX = motionX;
- }
-
- public final double getMotionY()
- {
- return motionY;
- }
-
- public final void setMotionY(double motionY)
- {
- prevMotionY = this.motionY;
- this.motionY = motionY;
- }
-
- public final double getPreviousMotionX()
- {
- return prevMotionX;
- }
-
- public final double getPreviousMotionY()
- {
- return prevMotionY;
- }
-
- //--------------------------------------------------------------------------
- // rendering stuff
- //--------------------------------------------------------------------------
-
- public final double getWidth()
- {
- return width;
- }
-
- public final double getHeight()
- {
- return height;
- }
-
- public final double getRenderX()
- {
- return posX;
- }
-
- public final double getRenderY()
- {
- return posY + height;
- }
-
- public void setImage(Image image)
- {
- this.image = image;
- }
-
- public boolean drawImageFlipped()
- {
- return false;
- }
-
- public Image getImage()
- {
- return image;
- }
-
- public double getRenderOffsetX()
- {
- return 0;
- }
-
- public double getRenderOffsetY()
- {
- return 0;
- }
- }
|