package stray.entity;
import stray.Main;
import stray.ai.BaseAI;
import stray.entity.types.Inflammable;
import stray.entity.types.Stunnable;
import stray.util.AssetMap;
import stray.util.DamageSource;
import stray.util.Direction;
import stray.util.MathHelper;
import stray.util.Particle;
import stray.util.ParticlePool;
import stray.util.Utils;
import stray.world.World;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.MathUtils;
/**
* has AI object
*
*
*/
public abstract class EntityLiving extends Entity {
public static final float FIRE_DAMAGE = ((1f / 3f)) / (Main.TICKS * 1f);
protected BaseAI ai;
public Direction facing = Direction.RIGHT;
public float health = 1;
public float maxhealth = 1;
public int invincibility = 0;
public final float invulnTime = 1.5f;
protected DamageSource lastDmg = DamageSource.generic;
public int stunTime = 0;
public int fireTime = 0;
public EntityLiving(World world, float x, float y) {
super(world, x, y);
}
@Override
public void prepare() {
ai = getNewAI();
}
/**
* also handles invuln flashing
*
* @param sprite
* @param x
* @param y
*/
public void drawSpriteWithFacing(Texture sprite, float x, float y) {
world.batch.setColor(1, 1, 1,
(invincibility > 0 ? (System.currentTimeMillis() / 100 % 2 == 0 ? 0.25f : 0.5f)
: world.batch.getColor().a));
// world.batch.draw(sprite, x - (sprite.getWidth() - (sizex *
// World.tilesizex)) / 2, y
// - World.tilesizey + (sprite.getHeight() - (sizey * World.tilesizey))
// / 2,
// sprite.getWidth(), sprite.getHeight(), 0, 0, sprite.getWidth(),
// sprite.getHeight(),
// (facing != Direction.RIGHT), false);
world.batch.draw(sprite, x, y - sizey * World.tilesizey, sprite.getWidth(),
sprite.getHeight(), 0, 0, sprite.getWidth(), sprite.getHeight(),
(facing != Direction.RIGHT), false);
}
public abstract BaseAI getNewAI();
@Override
public void render(float delta) {
if (stunTime > 0) {
Texture star = world.main.manager.get(AssetMap.get("particlestar"), Texture.class);
world.batch.setColor(1, 1, 1, MathHelper.clampNumberFromTime(1.5f) + 0.25f);
Utils.drawRotated(world.batch,
world.main.manager.get(AssetMap.get("stunhalo"), Texture.class),
(x * World.tilesizex) - world.camera.camerax + ((sizex * World.tilesizex) / 2)
- star.getWidth(),
Main.convertY((y * World.tilesizey) - world.camera.cameray) - 10, 64, 24,
((MathHelper.clampNumberFromTime(1.5f) - 0.25f) * 30), true);
world.batch.setColor(1, 1, 1, 1);
world.batch
.draw(star,
(x * World.tilesizex)
- world.camera.camerax
+ ((sizex / 4f) * World.tilesizex)
- ((MathHelper.clampNumberFromTime(3f) - 0.25f)
* star.getWidth() * 4f),
Main.convertY((y * World.tilesizey) - world.camera.cameray
+ (star.getHeight() / 4f)));
if (MathHelper.getNumberFromTime(1.5f) >= 0.5f) {
world.batch
.draw(star,
(x * World.tilesizex)
- world.camera.camerax
+ ((sizex / 4f) * World.tilesizex)
- ((MathHelper.clampNumberFromTime(1.5f) - 0.25f)
* star.getWidth() * 3f),
Main.convertY((y * World.tilesizey) - world.camera.cameray
+ (star.getHeight() / 4f))
- ((star.getHeight() / 3f)
* (MathHelper.clampNumberFromTime(3) - 0.25f) * 2));
super.render(delta);
world.batch
.draw(star,
(x * World.tilesizex)
- world.camera.camerax
+ ((sizex / 4f) * World.tilesizex)
+ ((MathHelper.clampNumberFromTime(1.5f) - 0.25f)
* star.getWidth() * 3f),
Main.convertY((y * World.tilesizey) - world.camera.cameray
+ (star.getHeight() / 4f))
+ ((star.getHeight() / 3f)
* (MathHelper.clampNumberFromTime(3) - 0.25f) * 2));
} else {
world.batch
.draw(star,
(x * World.tilesizex)
- world.camera.camerax
+ ((sizex / 4f) * World.tilesizex)
+ ((MathHelper.clampNumberFromTime(1.5f) - 0.25f)
* star.getWidth() * 3f),
Main.convertY((y * World.tilesizey) - world.camera.cameray
+ (star.getHeight() / 4f))
+ ((star.getHeight() / 3f)
* (MathHelper.clampNumberFromTime(1) - 0.25f) * 2));
super.render(delta);
world.batch
.draw(star,
(x * World.tilesizex)
- world.camera.camerax
+ ((sizex / 4f) * World.tilesizex)
- ((MathHelper.clampNumberFromTime(1.5f) - 0.25f)
* star.getWidth() * 3f),
Main.convertY((y * World.tilesizey) - world.camera.cameray
+ (star.getHeight() / 4f))
- ((star.getHeight() / 3f)
* (MathHelper.clampNumberFromTime(1) - 0.25f) * 2));
}
} else {
super.render(delta);
}
if (fireTime > 0 && !(this instanceof Inflammable)) {
world.batch.setColor(1, 1, 1, 0.9f);
world.batch.draw(world.main.animations.get("fire").getCurrentFrame(),
(x * World.tilesizex) - world.camera.camerax,
Main.convertY((y * World.tilesizey) - world.camera.cameray)
- (sizey * World.tilesizex), sizex * World.tilesizex, sizey
* World.tilesizey);
world.batch.setColor(1, 1, 1, 1);
}
}
public void poof() {
// centre
world.particles.add(getBaseParticle());
world.particles.add(getBaseParticle().setPosition((float) x, (float) y));
world.particles.add(getBaseParticle().setPosition((float) (x + sizex), (float) y));
world.particles
.add(getBaseParticle().setPosition((float) (x + sizex), (float) (y + sizey)));
world.particles.add(getBaseParticle().setPosition((float) x, (float) (y + sizey)));
world.particles.add(getBaseParticle().setPosition((float) (x + (sizex / 2)), (float) y));
world.particles.add(getBaseParticle().setPosition((float) (x + (sizex / 2)),
(float) (y + (sizey))));
world.particles.add(getBaseParticle().setPosition((float) (x + (sizex)),
(float) (y + (sizey / 2))));
world.particles.add(getBaseParticle().setPosition((float) x, (float) (y + (sizey / 2))));
// moving particles
world.particles.add(getBaseParticle().setPosition((float) x, (float) y).setVelocity(-1.5f,
-1.5f));
world.particles.add(getBaseParticle().setPosition((float) (x + sizex), (float) y)
.setVelocity(1.5f, -1.5f));
world.particles.add(getBaseParticle().setPosition((float) (x + sizex), (float) (y + sizey))
.setVelocity(1.5f, 1.5f));
world.particles.add(getBaseParticle().setPosition((float) x, (float) (y + sizey))
.setVelocity(-1.5f, 1.5f));
world.particles.add(getBaseParticle().setPosition((float) (x + (sizex / 2)), (float) y)
.setVelocity(0f, -1.5f));
world.particles.add(getBaseParticle().setPosition((float) (x + (sizex / 2)),
(float) (y + (sizey))).setVelocity(0f, 1.5f));
world.particles.add(getBaseParticle().setPosition((float) (x + (sizex)),
(float) (y + (sizey / 2))).setVelocity(1.5f, 0f));
world.particles.add(getBaseParticle().setPosition((float) x, (float) (y + (sizey / 2)))
.setVelocity(-1.5f, 0f));
}
private Particle getBaseParticle() {
return ParticlePool
.obtain()
.setPosition((float) (x + (sizex / 2)), (float) (y + (sizey / 2)))
.setLifetime(0.4f)
.setTexture("particlecircle")
.setTint(
Main.getRainbow(
Main.getRandom().nextFloat()
* (Main.getRandom().nextInt() / MathUtils.random(2,
Short.MAX_VALUE)), 1)).setAlpha(0.8f);
}
@Override
public void tickUpdate() {
do {
if (fireTime > 0) {
if (this instanceof Inflammable) {
fireTime = 0;
break;
}
fireTime--;
heal(-FIRE_DAMAGE, DamageSource.fire);
}
} while (false);
if (stunTime > 0) {
stunTime--;
return;
}
super.tickUpdate();
if (ai != null) ai.tickUpdate();
if (invincibility > 0) invincibility--;
}
/**
*
* @param dmg
* @return false if cancelled
*/
public boolean damage(float dmg, DamageSource source) {
if (dmg <= 0 || health <= 0 || invincibility > 0) {
return false;
}
health = MathUtils.clamp(health - dmg, 0f, maxhealth);
lastDmg = source;
if (dmg > 0) {
invincibility = Math.round(invulnTime * Main.TICKS);
}
return true;
}
/**
* adds health to entity, use negative for damage without invuln
*
* @param amt
*/
public void heal(float amt, DamageSource source) {
if (health <= 0) return;
health = MathUtils.clamp(health + amt, 0f, maxhealth);
if (health <= 0f) {
// this is so the damage override methods get triggered
health = Math.min(0.0001f, maxhealth);
damage(1, source);
}
}
@Override
public void renderUpdate() {
super.renderUpdate();
if (ai != null) ai.renderUpdate();
}
public float jump = 3f;
public void jump() {
if ((getBlockCollidingUp() == null && getEntityCollidingUp() == null)
&& (getBlockCollidingDown() != null || getEntityCollidingDown() != null)) {
veloy = -jump;
}
}
public void stun(float seconds) {
if (!(this instanceof Stunnable)) return;
stunTime = Math.max(Math.round(seconds * Main.TICKS), 0);
}
public void setFire(float seconds) {
if (this instanceof Inflammable) {
fireTime = 0;
return;
}
fireTime = Math.max(Math.round(seconds * Main.TICKS), 0);
}
@Override
public boolean isDead() {
return health <= 0;
}
public DamageSource getLastDamageSource() {
return lastDmg;
}
@Override
public boolean onDeath() {
poof();
return false;
}
@Override
public void moveLeft() {
super.moveLeft();
facing = Direction.LEFT;
}
@Override
public void moveRight() {
super.moveRight();
facing = Direction.RIGHT;
}
@Override
public void moveUp() {
super.moveUp();
facing = Direction.UP;
}
@Override
public void moveDown() {
super.moveDown();
facing = Direction.DOWN;
}
}