package me.hammerle.supersnuvi.entity.components.ai; import me.hammerle.snuviengine.api.Shader; import me.hammerle.snuviengine.api.Texture; import me.hammerle.supersnuvi.entity.Entity; import me.hammerle.supersnuvi.gamelogic.Level; import me.hammerle.supersnuvi.tiles.RampTile; import me.hammerle.supersnuvi.tiles.Tile; import me.hammerle.supersnuvi.util.Face; import me.hammerle.supersnuvi.util.SoundUtils; import me.hammerle.supersnuvi.util.Utils; public class LondonerController extends Controller { private final static Texture LONDONER = new Texture("resources/londoner.png"); // for render offset: 0.21875f, 0.59375f, 0.65625f, 2.0f // render offset: -0.21875, -0.59375 private final static float OFFSET_X = -Tile.SIZE * 0.21875f; private final static float OFFSET_Y = -Tile.SIZE * 0.59375f; private final boolean evil; private float ox = 0.0f; private float tx = 0.0f; private float ty = 0.0f; private int walkFrame = 0; private int transformFrame = -1; private int deathCounter = 0; private int deathFrame = 0; private Face oldFace = Face.LEFT; private Face direction = Face.LEFT; private boolean shouldJump = false; private int hurtTicks = 0; public LondonerController(boolean evil) { this.evil = evil; } private boolean hasRedEyes() { return transformFrame >= 3; } @Override public boolean isAnimated() { return deathFrame < 7; } @Override public void tick(Entity ent, Level level) { if(hurtTicks > 0) { hurtTicks--; } if(evil) { if(transformFrame != -1) { if(transformFrame < 3) { ox = direction == Face.RIGHT ? 0.0f: -1.125f * Tile.SIZE; tx = transformFrame * 0.125f + 0.125f; ty = 0.375f; transformFrame++; return; } } else if(level.getHero().getSquaredDistance(ent) <= 16384) // 4 Tiles { transformFrame = 0; } } if(ent.getHealth().isDead()) { ox = direction == Face.RIGHT ? -Tile.SIZE: -0.125f * Tile.SIZE; tx = deathFrame * 0.125f; ty = hasRedEyes() ? 0.125f : 0.25f; walkFrame = 0; deathCounter++; if(deathCounter >= 3) { deathCounter = 0; deathFrame++; } return; } if(hasRedEyes()) { float hx = level.getHero().getCenterX(); if(hx < ent.getCenterX()) { ent.applyOwnForce(-ent.getMovement().getVelocityX(), 0.0f); direction = Face.LEFT; } else { ent.applyOwnForce(ent.getMovement().getVelocityX(), 0.0f); direction = Face.RIGHT; } } else { if(direction == Face.LEFT) { ent.applyOwnForce(-ent.getMovement().getVelocityX(), 0.0f); } else { ent.applyOwnForce(ent.getMovement().getVelocityX(), 0.0f); } } if(shouldJump) { SoundUtils.playSound(SoundUtils.Sound.LONDONER_JUMP); ent.jump(); shouldJump = false; } ox = direction == Face.RIGHT ? 0.0f: -1.125f * Tile.SIZE; if(ent.isOnGround()) { if(ent.getOwnForceX() == 0.0f) { tx = 0.875f; ty = hasRedEyes() ? 0.25f : 0.375f; } else { deathFrame = 0; walkFrame = (walkFrame + 1) % 6; tx = walkFrame * 0.125f; ty = hasRedEyes() ? 0.5f : 0.625f; } } else { deathFrame = 0; walkFrame = 0; tx = 0.125f; ty = hasRedEyes() ? 0.5f : 0.625f; } oldFace = direction; } @Override public void renderTick(Entity ent, float lag) { if(ent.getHealth().wasHurt()) { Shader.setColorEnabled(true); Shader.setMixColorEnabled(true); Shader.setMixColor(1.0f, 0.0f, 0.0f, 1.0f); } if(ent.getHealth().wasHealed()) { Shader.setColorEnabled(true); Shader.setMixColorEnabled(true); Shader.setMixColor(0.0f, 1.0f, 0.0f, 1.0f); } LONDONER.bind(); float x = Utils.interpolate(ent.getLastX(), ent.getX(), lag); float y = Utils.interpolate(ent.getLastY(), ent.getY(), lag); float m1; float m2; if(oldFace == Face.LEFT) { m1 = 2.0f * Tile.SIZE; m2 = 0.0f; } else { m1 = 0.0f; m2 = 2.0f * Tile.SIZE; } Shader.getTextureRenderer().drawRectangle( x + ox + m1 + OFFSET_X, y + OFFSET_Y, x + ox + m2 + OFFSET_X, y + 2.0f * Tile.SIZE + OFFSET_Y, tx, ty, tx + 0.125f, ty + 0.125f); if(ent.getHealth().wasHurt() || ent.getHealth().wasHealed()) { Shader.setColorEnabled(false); Shader.setMixColorEnabled(false); } } @Override public void onCollideWithTile(Entity ent, int x, int y, Level l, Tile t, Face face) { if(ent.getHealth().isDead()) { return; } if(hasRedEyes()) { if(!(t instanceof RampTile) && face == direction && ent.getOwnForceX() == 0.0f) { shouldJump = true; } } else { if(t.shouldAiUseCollisionBox(x, y, l)) { switch(face) { case LEFT: direction = Face.RIGHT; break; case RIGHT: direction = Face.LEFT; break; } } } } @Override public void onCollideWithEntity(Entity ent, Entity other, Face face) { if(ent.getHealth().isDead()) { return; } switch(face) { case LEFT: case RIGHT: if(hurtTicks > 0) { return; } if(other.getItemCollector().isHero() && hasRedEyes()) { other.getHealth().addHealthPercent(-0.1f); other.applyForce(0.0f, -20.0f * Tile.SIZE_SCALE); if(ent.getCenterX() < other.getCenterX()) { other.applyForce(20.0f * Tile.SIZE_SCALE, 0.0f); } else { other.applyForce(-20.0f * Tile.SIZE_SCALE, 0.0f); } } else { direction = direction.getOpposite(); } break; case UP: ent.getHealth().addHealthPercent(-0.201f); other.applyForce(0.0f, -other.getMotionY() - other.getMovement().getJumpPower() * 0.5f); hurtTicks = 10; break; } } }