protected void HandleUpdate()
{
for(int a = 0; a<_ais.Count;a++)
{
_ais[a].Update ();
}
for(int p = 0; p<_players.Count; p++)
{
MPlayer player = _players[p];
if(player.isDead) continue;
player.framesTillBeast--;
if(player.framesTillBeast == 0)
{
player.framesTillBeast = player.maxFramesTillBeast;
CreateBeast(player);
}
}
float wallRadius = MConfig.WALL_RADIUS - 27.0f;
float towerRadius = MConfig.TOWER_RADIUS + 10.0f;
float attackRadius = 80.0f;
float nearbyRadius = 30.0f; //must be smaller than attackRadius
Vector2 tempVector = new Vector2(0,0);
int towerCount = _towers.Count;
bool isFrameEven = (frameCount % 2 == 0);
for(int b = 0; b<_beastCount; b++)
{
MBeast beast = _beasts[b];
float x = beast.x;
float y = beast.y;
MPlayer beastPlayer = beast.player;
Vector2 velocity = beast.velocity;
if(beastPlayer.areStatsDirty) beast.UpdateStats();
float deltaRotation = 0.0f;
for(int c = 0; c<_beastCount; c++)
{
MBeast otherBeast = _beasts[c];
if(otherBeast == beast) continue;
float dx = otherBeast.x - x;
if(dx > attackRadius || dx < -attackRadius) continue;
float dy = otherBeast.y - y;
if(dy > attackRadius || dy < -attackRadius) continue;
int distance = preCalcSQRTs[(int)(dx*dx + dy*dy)];
if(distance < attackRadius)
{
if(distance < nearbyRadius)
{
if(beastPlayer != otherBeast.player)
{
if(!beast.isAttacking)
{
//attack enemy
beast.isAttacking = true;
beast.isAttackingTower = false;
beast.attackTarget = otherBeast;
beast.attackFrame = 0;
}
//face the enemy you're attacking!
float faceEnemyRotation = -Mathf.Atan2(dy, dx) * RXMath.RTOD + 90.0f;
deltaRotation += RXMath.GetDegreeDelta(beast.rotation,faceEnemyRotation) * 0.3f;
}
//push away from other beast
tempVector.x = 0.0001f + -dx;
tempVector.y = -dy;
tempVector.Normalize();
velocity += tempVector; //push away from enemy or other beast
}
else if(distance < nearbyRadius + 4.0f) //fudge area, not too close or to far
{
if(beastPlayer != otherBeast.player)
{
if(!beast.isAttacking)
{
//attack enemy
beast.attackFrame = 0;
beast.isAttacking = true;
beast.isAttackingTower = false;
beast.attackTarget = otherBeast;
}
//face the enemy you're attacking!
float faceEnemyRotation = -Mathf.Atan2(dy, dx) * RXMath.RTOD + 90.0f;
deltaRotation += RXMath.GetDegreeDelta(beast.rotation,faceEnemyRotation) * 0.3f;
}
}
else
{
//move toward enemy!
if(beastPlayer != otherBeast.player)
{
tempVector.x = 0.0001f + -dx;
tempVector.y = -dy;
tempVector.Normalize();
velocity -= tempVector * 0.1f; //push towards enemy
}
}
}
}
for(int t = 0; t<towerCount; t++)
{
MTower tower = _towers[t];
float dx = tower.x - x;
float dy = tower.y - y;
float distanceToTower = Mathf.Sqrt(dx*dx + dy*dy);
if(distanceToTower < towerRadius+attackRadius)
{
if(distanceToTower < towerRadius + 5.0) //5 unit happy zone
{
if(distanceToTower < towerRadius)
{
tempVector.x = dx;
tempVector.y = dy;
tempVector.Normalize();
velocity -= tempVector * 2.0f; //push away from tower
}
if(beastPlayer != tower.player)
{
if(!beast.isAttacking)
{
//ATTACK TOWER
beast.attackFrame = 0;
beast.isAttacking = true;
beast.isAttackingTower = true;
beast.attackTower = tower;
}
//face the tower you're attacking!
float faceEnemyRotation = -Mathf.Atan2(dy, dx) * RXMath.RTOD + 90.0f;
deltaRotation += RXMath.GetDegreeDelta(beast.rotation,faceEnemyRotation) * 0.3f;
}
}
else
{
if(beastPlayer != tower.player)
{
tempVector.x = dx;
tempVector.y = dy;
tempVector.Normalize();
velocity += tempVector * 0.1f; //push towards the tower
}
}
}
}
if(beast.isAttacking)
{
if(isFrameEven) beast.attackFrame ++; //only increment every other frame
if(beast.attackFrame == 5)
{
if(beast.isAttackingTower)
{
if(beast.attackTower != null && beast.attackTower.health > 0)
{
MTower attackTower = beast.attackTower;
//tower has 25 defence
attackTower.health -= 1.0f; //Math.Max(1.0f, beast.offence - (float)_human.leapThreshold-1.0f); //tower always takes 1 damage, except when damage is maxed
attackTower.UpdateHealthPercent();
if(attackTower.health <= 0)
{
_towersThatWereDestroyed.Add (attackTower);
}
else
{
effectLayer.ShowTowerHitForTower(attackTower);
}
//this will make the attack graphic show on the closest side of the tower
tempVector.x = attackTower.x-x;
tempVector.y = attackTower.y-y;
tempVector.Normalize();
tempVector *= -30.0f;
effectLayer.ShowAttackMarkForPlayer(beastPlayer, new Vector2(attackTower.x+tempVector.x,attackTower.y+tempVector.y));
}
beast.attackTower = null;
}
else //attack the other beast
{
MBeast attackTarget = beast.attackTarget;
beast.attackFrame++;
if(attackTarget != null && attackTarget.isEnabled)
{
if(attackTarget.health > 0)
{
float damage = Math.Max(1.0f, beast.offence - attackTarget.defence); //damage must be at least 1
attackTarget.health -= damage;
if(attackTarget.health <= 0)
{
if(!_beastsThatDied.Contains(attackTarget))
{
effectLayer.CreateDNA(beastPlayer, new Vector2(attackTarget.x,attackTarget.y));
beastPlayer.AddKill();
_beastsThatDied.Add(attackTarget);
}
}
attackTarget.sprite.shader = FShader.AdditiveColor;
attackTarget.sprite.color = attackTarget.player.color.attackRedColor;
_beastContainerSpecial.AddChild (attackTarget);
attackTarget.blinkFrame = 7;
}
//this will make the attack graphic show on the closest side of the beast
tempVector.x = attackTarget.x-x;
tempVector.y = attackTarget.y-y;
tempVector.Normalize();
tempVector *= -10.0f;
effectLayer.ShowAttackMarkForPlayer(beastPlayer, new Vector2(attackTarget.x+tempVector.x,attackTarget.y+tempVector.y));
}
beast.attackTarget = null;
}
}
else if (beast.attackFrame >= 19)
{
beast.isAttacking = false;
beast.attackTarget = null;
beast.attackTower = null;
beast.attackFrame = 0;
}
}
if(beast.hasTarget)
{
float dx = beast.target.x - x;
float dy = beast.target.y - y;
float distanceToTarget = Mathf.Sqrt (dx*dx + dy*dy);
if(distanceToTarget > 50.0f)
{
tempVector.x = beast.target.x - beast.x;
tempVector.y = beast.target.y - beast.y;
tempVector.Normalize();
velocity += tempVector * beast.speed * 0.1f; //push towards target
}
}
float distanceToCenter = Mathf.Sqrt(x*x + y*y);
if(distanceToCenter > wallRadius)
{
tempVector.x = x;
tempVector.y = y;
tempVector.Normalize();
velocity -= tempVector * 2.0f; //push away from wall
}
//apply half the velocity
beast.x += velocity.x * 0.5f;
beast.y += velocity.y * 0.5f;
float goalRotation = -Mathf.Atan2(velocity.y, velocity.x) * RXMath.RTOD + 90.0f;
deltaRotation += RXMath.GetDegreeDelta(beast.rotation,goalRotation) * 0.06f;
beast.rotation += Math.Max(-3.0f, Math.Min (3.0f, deltaRotation*0.9f));
//ease the velocity
velocity.x *= 0.45f;
velocity.y *= 0.45f;
float moveAmount = Math.Min(1.5f, 20.0f*Mathf.Abs(velocity.x*velocity.y)) + Math.Abs (deltaRotation)*0.7f;
beast.velocity = velocity;
beast.AdvanceFrame(moveAmount);
if(beast.blinkFrame > 0)
{
beast.blinkFrame--;
if(beast.blinkFrame == 0) //put it back to normal
{
beast.sprite.shader = FShader.Basic;
beast.sprite.color = colorWhite;
_beastContainer.AddChild(beast);
}
}
//make it scale in
if(beast.scale < 1.0f)
{
beast.scale += 0.025f;
}
}
int diedCount = _beastsThatDied.Count;
for(int d = 0; d<diedCount; d++)
{
MBeast beast = _beastsThatDied[d];
if(beast.isEnabled)
{
effectLayer.ShowBeastExplosionForBeast(beast);
RemoveBeast(beast);
if(beast.player.isHuman) beast.player.isDirty = true;
FSoundManager.PlaySound("BeastExplode",1.0f);
}
}
_beastsThatDied.Clear();
for(int t = 0; t<_towersThatWereDestroyed.Count; t++)
{
MTower destroyedTower = _towersThatWereDestroyed[t];
KillPlayer(destroyedTower.player);
FSoundManager.PlaySound("BaseExplode",1.0f);
}
_towersThatWereDestroyed.Clear ();
if(_human.isDirty)
{
_beastLabel.text = _human.beasts.Count + "/"+_human.maxBeasts+" BEASTS";
if(_human.currentStatTotal < _human.statTotal)
{
_evolutionLabel.text = (_human.currentStatTotal % _human.leapThreshold) + "/"+_human.leapThreshold+" MUTATIONS";
}
else
{
_evolutionLabel.text = "MAX EVOLUTION!";
}
}
for(int p = 0; p<_players.Count; p++)
{
MPlayer player = _players[p];
player.areStatsDirty = false;
if(player.isDirty)
{
player.isDirty = false;
_playerLabels[p].text = player.name.ToUpper()+": "+((int)player.tower.health)+" HP ("+player.totalKills+" KILLS)";
}
}
frameCount++;
}