anodyne/AIR/intra/hsrc/entity/enemy/circus/Lion.hx

541 lines
13 KiB
Haxe

package entity.enemy.circus
{
import data.Common_Sprites;
import entity.gadget.Dust;
import entity.player.Player;
import flash.geom.Point;
import global.Registry;
import helper.EventScripts;
import helper.Parabola_Thing;
import org.flixel.FlxG;
import org.flixel.FlxGroup;
import org.flixel.FlxPoint;
import org.flixel.FlxSprite;
class Lion extends FlxSprite
{
//[Embed(source="../../../res/sprites/enemies/circus/lion.png")] public static var lion_sprite:Class;
//[Embed(source="../../../res/sprites/enemies/circus/lion_fireballs.png")] public static var lion_fireball_sprite:Class;
public var xml:XML;
public var player:Player;
public var parent:Dynamic;
private var max_health:Int=4;
private var is_hurt:Bool=false;
private var hori_hitbox:FlxSprite=new FlxSprite;
private var H_OFF_X:Int=3;
private var H_OFF_Y:Int=11;
private var vert_hitbox:FlxSprite=new FlxSprite;
private var V_OFF_X:Int=10;
private var V_OFF_Y:Int=4;
private var hitbox:FlxSprite;
private var state:Int=0;
private var state_pace:Int=0;
private var t_pace:Float=0;
private var tm_pace:Float=0.8;
private var vel_pace:Float=43;
private var ctr_pace:Int=0;
private var state_shoot:Int=1;
private var fireballs:FlxGroup=new FlxGroup(10);
private var vel_fireball:Int=88;
private var max_fireball_x_distance:Int=80;
private var ctr_shoot:Int=0;
private var t_shoot:Float=0;
private var tm_shoot:Float=0.165;
private var tm_shoot_warning:Float=0.8;
private var ctr_shots:Int=0;
private var max_shots:Int=18;
private var state_charge:Int=2;
private var ctr_charge:Int=0;
private var vel_charge:Int=110;
private var t_charge:Float=0;
private var h_shadow:FlxSprite=new FlxSprite;
private var v_shadow:FlxSprite=new FlxSprite;
private var state_dying:Int=3;
private var did_init:Bool=false;
public function new(_xml:XML, _player:Player, _parent:Dynamic)
{
xml=_xml;
player=_player;
parent=_parent;
super(parseInt(xml.@x), parseInt(xml.@y));
health=max_health;
solid=false;
loadGraphic(lion_sprite, true, false, 32, 32);
addAnimation("walk_l", [0, 1], 5);
addAnimation("walk_r", [0, 1], 5);
addAnimation("walk_d", [10,11], 5);
addAnimation("walk_u", [5,6], 5);
addAnimation("warn_l", [3], 5, true);
addAnimation("warn_r", [3], 5, true);
addAnimation("shoot_l", [2], 15, true);
addAnimation("shoot_r", [2], 15, true);
addAnimation("shoot_d", [12], 15, true);
addAnimation("shoot_u", [7], 15, true);
addAnimation("pounce_r", [4]);
addAnimation("pounce_l", [4]);
addAnimation("pounce_u", [9]);
addAnimation("pounce_d", [14]);
play("walk_r");
addAnimationCallback(on_anim_change);
add_sfx("shoot", Registry.sound_data.fireball_group);
/* Make shadows */
h_shadow.loadGraphic(Common_Sprites.shadow_sprite_28_10, true, false, 28, 10);
v_shadow.loadGraphic(Common_Sprites.shadow_sprite_28_10, true, false, 28, 10);
v_shadow.visible=h_shadow.visible=false;
h_shadow.frame=v_shadow.frame=4;
h_shadow.offset.x=-2;h_shadow.offset.y=-24;
v_shadow.offset.y=-12;
v_shadow.scale.x=0.5;v_shadow.scale.y=2;// Remove when you add teha ctual shadows
parabola_thing=new Parabola_Thing(this, 12, 1.0, "offset", "y");
hori_hitbox.makeGraphic(26, 13, 0x00ff0000);
vert_hitbox.makeGraphic(10, 20, 0x0000ff00);
hitbox=hori_hitbox;
hitbox.velocity.x=vel_pace;
for(i in 0...fireballs.maxSize){
var fireball:FlxSprite=new FlxSprite;
fireball.loadGraphic(lion_fireball_sprite, true, false, 16, 16);
fireball.width=fireball.height=8;
fireball.centerOffsets(true);
fireball.addAnimation("shoot", [0, 1], 10);
fireball.addAnimation("poof", [2,3,4,5], 10,false);
fireball.play("shoot");
fireball.alive=fireball.exists=false;
fireballs.add(fireball);
}
if(xml.@alive=="false"){
Registry.GRID_ENEMIES_DEAD++;
exists=false;
}
state=state_pace;
}
override public function update():Void
{
if(parent.state==parent.S_TRANSITION){
hitbox.velocity.x=hitbox.velocity.y=0;
return;
}
if(!did_init){
did_init=true;
center_hitboxes();
parent.fg_sprites.add(vert_hitbox);
parent.fg_sprites.add(hori_hitbox);
parent.fg_sprites.add(fireballs);
parent.bg_sprites.add(v_shadow);
parent.bg_sprites.add(h_shadow);
}
//Graphic pinned to hitbox(hitbox moves)
if(hitbox==vert_hitbox){
x=hitbox.x - V_OFF_X;
y=hitbox.y - V_OFF_Y;
} else if(hitbox==hori_hitbox){
x=hitbox.x - H_OFF_X;
y=hitbox.y - H_OFF_Y;
}
//Stop moving if touchign solid tile
FlxG.collide(hitbox, parent.curMapBuf);
if(hitbox.touching !=NONE){
hitbox.velocity.x=hitbox.velocity.y=0;
}
//hurt player
if(!player.invincible && player.overlaps(hitbox)){
player.touchDamage(1);
}
// Get hurt
if(!flickering && player.broom.visible && player.broom.overlaps(hitbox)){
flicker(1);
is_hurt=true;
play_sfx(HURT_SOUND_NAME);
health--;
if(health<=0){
state=state_dying;
}
} else {
is_hurt=false;
}
if(state==state_pace){
pace_state();
} else if(state==state_shoot){
shoot_state();
} else if(state==state_charge){
charge_state();
} else if(state==state_dying){
alpha -=0.05;
if(alpha==0){
Registry.GRID_ENEMIES_DEAD++;
EventScripts.make_explosion_and_sound(this);
exists=false;
v_shadow.exists=h_shadow.exists=false;
}
}
super.update();
}
public function on_anim_change(name:String, frame_nr:Int, frame_index:Int):Void {
if(name=="walk_l" || name=="shoot_l" || name=="warn_l" || name=="pounce_l"){
facing=LEFT;
scale.x=-1;
} else {
scale.x=1;
if(name=="walk_r" || name=="shoot_r"){
facing=RIGHT;
} else if(name=="walk_u" || name=="shoot_u"){
facing=UP;
} else if(name=="walk_d" || name=="shoot_d"){
facing=DOWN;
}
}
}
private function center_hitboxes():Void
{
hori_hitbox.x=x + H_OFF_X;
hori_hitbox.y=y + H_OFF_Y;
vert_hitbox.x=x + V_OFF_X;
vert_hitbox.y=y + V_OFF_Y;
}
private function pace_state():Void
{
t_pace +=FlxG.elapsed;
if(t_pace>tm_pace){
t_pace=0;
ctr_pace=Std.int(6 * Math.random());
var r:Float=Math.random();
if(r<0.25){
state=state_shoot;
if(player.x>x + 16){
play("warn_r");
} else {
play("warn_l");
}
return;
} else if(r<0.55){
state=state_charge;
return;
}
switch(ctr_pace){
case 0:
hitbox=hori_hitbox;
hitbox.velocity.x=vel_pace;
hitbox.velocity.y=0;
center_hitboxes();
play("walk_r");
break;
case 1:
hitbox=vert_hitbox;
hitbox.velocity.x=0;
hitbox.velocity.y=vel_pace;
play("walk_d");
center_hitboxes();
break;
case 2:
hitbox=hori_hitbox;
hitbox.velocity.y=0;
hitbox.velocity.x=-vel_pace;
play("walk_l");
center_hitboxes();
break;
case 3:
hitbox=vert_hitbox;
hitbox.velocity.x=0;
hitbox.velocity.y=-vel_pace;
play("walk_u");
center_hitboxes();
break;
default:
//hitbox.velocity.x=hitbox.velocity.y=0;
break;
}
}
}
private function shoot_state():Void
{
hitbox.velocity.x=hitbox.velocity.y=0;
var fireball:FlxSprite;
if(ctr_shoot==0){
t_shoot +=FlxG.elapsed;
if(t_shoot<=tm_shoot_warning){
return;
} else {
t_shoot=0;
ctr_shoot++;
}
}
// Periodically shoot a fireball
t_shoot +=FlxG.elapsed;
if(t_shoot>tm_shoot){
t_shoot=0;
if(ctr_shots<max_shots && fireballs.countDead()>0){
fireball=fireballs.getFirstDead()as FlxSprite;
if(fireball !=null){
ctr_shots++;
play_sfx("shoot");
face_player();
switch(facing){
case UP:
fireball.x=x + width / 2;
fireball.y=y - 2;
EventScripts.scale_vector(getMidpoint(), new Point(x + 32*Math.random(), y - 32), fireball.velocity, vel_fireball);
break;
case DOWN:
fireball.x=x + width / 2;
fireball.y=y + height + 2;
EventScripts.scale_vector(getMidpoint(), new Point(x + 32*Math.random(), y + 32), fireball.velocity, vel_fireball);
break;
case RIGHT:
fireball.x=x + width;
fireball.y=y + 6;
EventScripts.scale_vector(new Point(x + width, y + 6), new Point(x + 80, y - 26 + 52*Math.random()), fireball.velocity, vel_fireball);
break;
case LEFT:
fireball.x=x;
fireball.y=y + 6;
EventScripts.scale_vector(new Point(x, y + 6), new Point(x - 30, y - 26 + 52*Math.random()), fireball.velocity, vel_fireball);
break;
}
fireball.exists=fireball.alive=true;
fireball.finished=false;
fireball.play("shoot");
}
} else {
ctr_shots=0;
state=state_pace;
}
}
// Fireballs hit player and map
for(fireball in fireballs.members){
if(fireball._curAnim !=null && fireball._curAnim.name !="poof"){
for(var dust:Dust in Registry.subgroup_dust){
if(dust !=null){
if(dust.visible && dust.overlaps(fireball)){
fireball.play("poof");fireball.finished=false;
}
}
}
if(fireball.alive){
if(!player.invincible && player.overlaps(fireball)){
player.touchDamage(1);
fireball.play("poof");fireball.finished=false;
//fireball.alive=false;
}
if(player.broom.visible && player.broom.overlaps(fireball)){
fireball.play("poof");fireball.finished=false;
//fireball.alive=false;
}
}
if(Math.abs(fireball.x - x)>max_fireball_x_distance){
//fireball.alive=fireball.exists=false;
fireball.play("poof");fireball.finished=false;
} else if(Math.abs(fireball.y - y)>max_fireball_x_distance){
//fireball.alive=fireball.exists=false;
fireball.play("poof");fireball.finished=false;
}
}
if(fireball.finished && fireball._curAnim !=null && fireball._curAnim.name=="poof"){
fireball.exists=fireball.alive=false;
fireball.play("shoot");
}
}
// If hurt then go back to charge
if(is_hurt){
ctr_shots=max_shots;
}
}
private function charge_state():Void
{
if(ctr_charge==0){ // Walk away forom the player
hitbox=hori_hitbox;
center_hitboxes();
hitbox.velocity.x=20;
hitbox.velocity.y=0;
if(player.x>x){
hitbox.velocity.x *=-1;
play("walk_l");
} else {
play("walk_r");
}
ctr_charge++;
} else if(ctr_charge==1){ // Face the player
t_charge +=FlxG.elapsed;
if(t_charge>1.4){
hitbox.velocity.x=hitbox.velocity.y=0;
if(_curAnim.name=="walk_r"){
hitbox.velocity.x=-10;
play("warn_l");
} else {
hitbox.velocity.x=10;
play("warn_r");
}
t_charge=0;
ctr_charge++;
}
} else if(ctr_charge==2){ //pause a little
t_charge +=FlxG.elapsed;
if(t_charge>0.6){
t_charge=0;
ctr_charge++;
}
} else if(ctr_charge==3){ //dash to theplayer
EventScripts.scale_vector(new Point(x, y), new Point(player.x, player.y), hitbox.velocity, vel_charge);
ctr_charge++;
scale.x=1;
switch(EventScripts.get_entity_to_entity_dir(x, y, player.x, player.y)){
case UP:
v_shadow.visible=true;
play("pounce_u");
break;
case DOWN:
v_shadow.visible=true;
play("pounce_d");
break;
case LEFT:
h_shadow.visible=true;
play("pounce_l");
break;
case RIGHT:
h_shadow.visible=true;
play("pounce_r");
break;
}
if(v_shadow.visible){
v_shadow.x=x;
v_shadow.y=y;
} else {
h_shadow.x=x;
h_shadow.y=y;
}
} else if(ctr_charge==4){ //Check the graphic against tilemap to avoid weird graphics steppingoutside the bounds
solid=true;
if(v_shadow.visible){
v_shadow.x=x;
v_shadow.y=y;
} else {
h_shadow.x=x;
h_shadow.y=y;
}
FlxG.collide(this, parent.curMapBuf);
if(parabola_thing.tick()||(touching !=NONE && offset.y>4)){
offset.y=0;
parabola_thing.reset_time();
h_shadow.visible=v_shadow.visible=false;
hitbox.velocity.x=hitbox.velocity.y=0;
ctr_charge=0;
if(_curAnim.name=="pounce_l"){
play("walk_l");
} else if(_curAnim.name=="pounce_r"){
play("walk_r");
} else if(_curAnim.name=="pounce_d"){
play("walk_d");
} else {
play("walk_u");
}
state=state_pace;
}
solid=false;
}
}
/* Get dy/dx and the slope to figure out which way to face */
private function face_player():Void {
var midpoint:FlxPoint=getMidpoint();
var dy:Float=midpoint.y - player.midpoint.y;
var dx:Float=midpoint.x - player.midpoint.x;
var eps:Float=0.0001;
(Math.abs(dx)<eps)?(dx<0 ? dx=-0.1:dx=0.1):1;
var m:Float=Math.abs(dy / dx);
if(m>1){
if(dy>0){
if(state==state_shoot){
play("shoot_u");
} else {
play("walk_u")
}
} else {
if(state==state_shoot){
play("shoot_d");
} else {
play("walk_d");
}
}
} else {
if(dx>0){
if(state==state_shoot){
play("shoot_l");
} else {
play("walk_l");
}
} else {
if(state==state_shoot){
play("shoot_r");
} else {
play("walk_r");
}
}
}
}
override public function destroy():Void
{
fireballs=null;
h_shadow=null;
hori_hitbox=null;
hitbox=null;
v_shadow=null;
vert_hitbox=null;
super.destroy();
}
}