You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
597 lines
18 KiB
C#
597 lines
18 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
using Duality;
|
|
using Duality.Editor;
|
|
using Duality.Components;
|
|
using Duality.Components.Physics;
|
|
using Duality.Components.Renderers;
|
|
using Duality.Resources;
|
|
using Duality.Drawing;
|
|
using Duality.Audio;
|
|
|
|
namespace DualStickSpaceShooter
|
|
{
|
|
[RequiredComponent(typeof(Ship))]
|
|
public class EnemyClaymore : Component, ICmpUpdatable, ICmpInitializable, ICmpCollisionListener, ICmpMessageListener
|
|
{
|
|
[Flags]
|
|
public enum BehaviorFlags
|
|
{
|
|
None,
|
|
|
|
Chase
|
|
}
|
|
|
|
private enum MindState
|
|
{
|
|
Asleep,
|
|
Awaking,
|
|
FallingAsleep,
|
|
Idle
|
|
}
|
|
|
|
private struct SpikeState
|
|
{
|
|
public float OpenValue;
|
|
public float OpenTarget;
|
|
public float Speed;
|
|
public bool Blinking;
|
|
public int ContactCount;
|
|
}
|
|
|
|
private const float WakeupDist = 300.0f;
|
|
private const float SpikeAttackMoveDist = 100.0f;
|
|
private const float SleepTime = 3000.0f;
|
|
|
|
private MindState state = MindState.Asleep;
|
|
private BehaviorFlags behavior = BehaviorFlags.Chase;
|
|
private float idleTimer = 0.0f;
|
|
private float blinkTimer = 0.0f;
|
|
private float eyeOpenValue = 0.0f;
|
|
private float eyeOpenTarget = 0.0f;
|
|
private float eyeSpeed = 0.0f;
|
|
private bool eyeBlinking = false;
|
|
private bool spikesActive = false;
|
|
private SpikeState[] spikeState = new SpikeState[4];
|
|
private ContentRef<EnemyBlueprint> blueprint = null;
|
|
|
|
[DontSerialize] private AnimSpriteRenderer eye = null;
|
|
[DontSerialize] private SpriteRenderer[] spikes = null;
|
|
[DontSerialize] private SoundInstance moveSoundLoop = null;
|
|
[DontSerialize] private SoundInstance dangerSoundLoop = null;
|
|
|
|
public BehaviorFlags Behavior
|
|
{
|
|
get { return this.behavior; }
|
|
set { this.behavior = value; }
|
|
}
|
|
public ContentRef<EnemyBlueprint> Blueprint
|
|
{
|
|
get { return this.blueprint; }
|
|
set { this.blueprint = value; }
|
|
}
|
|
|
|
private void Sleep()
|
|
{
|
|
if (this.state == MindState.Asleep) return;
|
|
if (this.state == MindState.FallingAsleep) return;
|
|
|
|
this.state = MindState.FallingAsleep;
|
|
this.eyeOpenTarget = 0.0f;
|
|
this.eyeBlinking = false;
|
|
this.eyeSpeed = Time.SPFMult / MathF.Rnd.NextFloat(1.5f, 3.5f);
|
|
this.DeactivateSpikes();
|
|
}
|
|
private void Awake()
|
|
{
|
|
if (this.state == MindState.Idle) return;
|
|
if (this.state == MindState.Awaking) return;
|
|
|
|
this.state = MindState.Awaking;
|
|
this.eyeOpenTarget = 1.0f;
|
|
this.eyeBlinking = false;
|
|
this.eyeSpeed = Time.SPFMult / MathF.Rnd.NextFloat(1.0f, 1.5f);
|
|
|
|
this.RandomizeBlinkTimer();
|
|
}
|
|
private void RandomizeBlinkTimer()
|
|
{
|
|
this.blinkTimer += MathF.Rnd.Next(100, 10000);
|
|
}
|
|
|
|
private void BlinkEye(float blinkStrength = 1.0f)
|
|
{
|
|
this.eyeBlinking = true;
|
|
this.eyeOpenTarget = MathF.Min(1.0f - blinkStrength, this.eyeOpenTarget);
|
|
this.eyeSpeed = Time.SPFMult / MathF.Rnd.NextFloat(0.05f, 0.25f);
|
|
}
|
|
private void BlinkSpikes(float blinkStrength = 1.0f)
|
|
{
|
|
if (!this.spikesActive) return;
|
|
for (int i = 0; i < this.spikeState.Length; i++)
|
|
{
|
|
this.spikeState[i].Blinking = true;
|
|
this.spikeState[i].OpenTarget = MathF.Min(1.0f - blinkStrength, this.eyeOpenTarget);
|
|
this.spikeState[i].Speed = Time.SPFMult / MathF.Rnd.NextFloat(0.1f, 0.2f);
|
|
}
|
|
}
|
|
private void DeactivateSpikes()
|
|
{
|
|
if (!this.spikesActive) return;
|
|
this.spikesActive = false;
|
|
for (int i = 0; i < this.spikeState.Length; i++)
|
|
{
|
|
this.spikeState[i].Blinking = false;
|
|
this.spikeState[i].OpenTarget = 0.0f;
|
|
this.spikeState[i].Speed = Time.SPFMult / MathF.Rnd.NextFloat(0.25f, 1.0f);
|
|
}
|
|
}
|
|
private void ActivateSpikes()
|
|
{
|
|
if (this.spikesActive) return;
|
|
this.spikesActive = true;
|
|
for (int i = 0; i < this.spikeState.Length; i++)
|
|
{
|
|
this.spikeState[i].Blinking = false;
|
|
this.spikeState[i].OpenTarget = 1.0f;
|
|
this.spikeState[i].Speed = Time.SPFMult / MathF.Rnd.NextFloat(0.25f, 1.0f);
|
|
}
|
|
}
|
|
|
|
private void FireExplosives()
|
|
{
|
|
// Set up working data
|
|
EnemyBlueprint blueprint = this.blueprint.Res;
|
|
Ship ship = this.GameObj.GetComponent<Ship>();
|
|
Vector2 pos = this.GameObj.Transform.Pos.Xy;
|
|
|
|
// Push other objects away
|
|
GameplayHelper.Shockwave(
|
|
pos,
|
|
blueprint.ExplosionRadius,
|
|
blueprint.ExplosionForce,
|
|
blueprint.ExplosionMaxVelocity,
|
|
obj => obj.GameObj != this.GameObj);
|
|
|
|
// Damage other objects
|
|
GameplayHelper.ExplosionDamage(
|
|
pos,
|
|
blueprint.ExplosionRadius,
|
|
blueprint.ExplosionDamage,
|
|
body => body.GameObj.GetComponent<Ship>() != null && body.GameObj != ship.GameObj);
|
|
|
|
// Die instantly
|
|
ship.Die();
|
|
|
|
// Spawn explosion effects
|
|
if (blueprint.ExplosionEffects != null)
|
|
{
|
|
Transform transform = this.GameObj.Transform;
|
|
for (int i = 0; i < blueprint.ExplosionEffects.Length; i++)
|
|
{
|
|
GameObject effectObj = blueprint.ExplosionEffects[i].Res.Instantiate(transform.Pos);
|
|
Scene.Current.AddObject(effectObj);
|
|
}
|
|
}
|
|
|
|
// Play explosion sound
|
|
if (blueprint.ExplosionSound != null)
|
|
{
|
|
SoundInstance inst = DualityApp.Sound.PlaySound3D(blueprint.ExplosionSound, new Vector3(pos));
|
|
inst.Pitch = MathF.Rnd.NextFloat(0.8f, 1.25f);
|
|
}
|
|
}
|
|
|
|
private bool HasLineOfSight(GameObject obj, bool passThroughShips)
|
|
{
|
|
Transform otherTransform = obj.Transform;
|
|
Transform transform = this.GameObj.Transform;
|
|
|
|
RayCastData firstHit;
|
|
bool hitAnything = RigidBody.RayCast(transform.Pos.Xy, otherTransform.Pos.Xy, data =>
|
|
{
|
|
if (data.GameObj == this.GameObj) return -1;
|
|
if (data.Shape.IsSensor) return -1;
|
|
|
|
if (passThroughShips)
|
|
{
|
|
Ship otherShip = data.GameObj.GetComponent<Ship>();
|
|
if (otherShip != null && otherShip.Owner == null) return -1;
|
|
}
|
|
|
|
return data.Fraction;
|
|
}, out firstHit);
|
|
|
|
return hitAnything && firstHit.GameObj == obj;
|
|
}
|
|
private GameObject GetNearestPlayerObj(out float nearestDist)
|
|
{
|
|
nearestDist = float.MaxValue;
|
|
GameObject nearestObj = null;
|
|
|
|
Transform transform = this.GameObj.Transform;
|
|
foreach (Player player in Scene.Current.FindComponents<Player>())
|
|
{
|
|
if (player.ControlObject == null) continue;
|
|
if (!player.ControlObject.Active) continue;
|
|
Transform shipTransform = player.ControlObject.GameObj.Transform;
|
|
|
|
float dist = (shipTransform.Pos - transform.Pos).Length;
|
|
if (dist < nearestDist)
|
|
{
|
|
nearestDist = dist;
|
|
nearestObj = player.ControlObject.GameObj;
|
|
}
|
|
}
|
|
|
|
return nearestObj;
|
|
}
|
|
private int GetSpikeIndex(ShapeInfo spikeShape)
|
|
{
|
|
RigidBody body = this.GameObj.GetComponent<RigidBody>();
|
|
if (body == null) return -1;
|
|
|
|
int i = 0;
|
|
foreach (ShapeInfo shape in body.Shapes.Skip(1))
|
|
{
|
|
if (spikeShape == shape) return i;
|
|
i++;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
void ICmpUpdatable.OnUpdate()
|
|
{
|
|
EnemyBlueprint blueprint = this.blueprint.Res;
|
|
Transform transform = this.GameObj.Transform;
|
|
RigidBody body = this.GameObj.GetComponent<RigidBody>();
|
|
Ship ship = this.GameObj.GetComponent<Ship>();
|
|
|
|
// Calculate distress caused by going in a different direction than desired
|
|
float moveDistress = 0.0f;
|
|
if (body.LinearVelocity.Length > 1.0f)
|
|
{
|
|
Vector2 actualVelocityDir = body.LinearVelocity.Normalized;
|
|
Vector2 desiredVelocityDir = ship.TargetThrust;
|
|
float desiredDirectionFactor = Vector2.Dot(actualVelocityDir, desiredVelocityDir);
|
|
moveDistress = MathF.Clamp(1.0f - desiredDirectionFactor, 0.0f, 1.0f) * MathF.Clamp(body.LinearVelocity.Length - 0.5f, 0.0f, 1.0f);
|
|
}
|
|
|
|
// Do AI state handling stuff
|
|
float moveTowardsEnemyRatio = 0.0f;
|
|
switch (this.state)
|
|
{
|
|
case MindState.Asleep:
|
|
{
|
|
// Wake up, if there is a player near
|
|
float nearestDist;
|
|
GameObject nearestObj = this.GetNearestPlayerObj(out nearestDist);
|
|
if (nearestObj != null && nearestDist <= WakeupDist && this.HasLineOfSight(nearestObj, true))
|
|
{
|
|
this.Awake();
|
|
}
|
|
|
|
// Don't move actively
|
|
ship.TargetThrust = Vector2.Zero;
|
|
ship.TargetAngle = MathF.Rnd.NextFloat(-MathF.RadAngle30, MathF.RadAngle30);
|
|
ship.TargetAngleRatio = 0.0f;
|
|
break;
|
|
}
|
|
case MindState.FallingAsleep:
|
|
{
|
|
if (this.eyeOpenValue <= 0.0001f)
|
|
this.state = MindState.Asleep;
|
|
break;
|
|
}
|
|
case MindState.Awaking:
|
|
{
|
|
if (this.eyeOpenValue >= 0.9999f)
|
|
this.state = MindState.Idle;
|
|
break;
|
|
}
|
|
case MindState.Idle:
|
|
{
|
|
// Follow, if there is a player near
|
|
float nearestDist;
|
|
GameObject nearestObj = this.GetNearestPlayerObj(out nearestDist);
|
|
if (nearestObj != null && this.HasLineOfSight(nearestObj, false))
|
|
{
|
|
if (behavior.HasFlag(BehaviorFlags.Chase))
|
|
{
|
|
Transform nearestObjTransform = nearestObj.Transform;
|
|
Vector2 targetDiff = nearestObjTransform.Pos.Xy - transform.Pos.Xy;
|
|
ship.TargetThrust = targetDiff / MathF.Max(targetDiff.Length, 25.0f);
|
|
moveTowardsEnemyRatio = ship.TargetThrust.Length;
|
|
}
|
|
else
|
|
{
|
|
ship.TargetThrust = Vector2.Zero;
|
|
}
|
|
ship.TargetAngle += 0.001f * Time.TimeMult;
|
|
ship.TargetAngleRatio = 0.1f;
|
|
|
|
this.idleTimer = MathF.Rnd.NextFloat(0.0f, SleepTime * 0.25f);
|
|
|
|
if (nearestDist <= SpikeAttackMoveDist)
|
|
{
|
|
moveDistress = 0.0f;
|
|
if (!this.spikesActive)
|
|
this.ActivateSpikes();
|
|
}
|
|
else if (ship.TargetThrust.Length > 0.1f)
|
|
{
|
|
if (this.spikesActive)
|
|
this.DeactivateSpikes();
|
|
}
|
|
}
|
|
// Try to stay in place otherwise
|
|
else
|
|
{
|
|
ship.TargetThrust = -body.LinearVelocity / MathF.Max(body.LinearVelocity.Length, ship.Blueprint.Res.MaxSpeed);
|
|
ship.TargetAngleRatio = 0.1f;
|
|
this.idleTimer += Time.MsPFMult * Time.TimeMult;
|
|
|
|
if (this.spikesActive)
|
|
this.DeactivateSpikes();
|
|
}
|
|
|
|
// Blink occasionally
|
|
this.blinkTimer -= Time.MsPFMult * Time.TimeMult;
|
|
if (this.blinkTimer <= 0.0f)
|
|
{
|
|
this.RandomizeBlinkTimer();
|
|
this.BlinkEye();
|
|
}
|
|
|
|
// Go to sleep if nothing happens.
|
|
if (this.idleTimer > SleepTime)
|
|
{
|
|
this.Sleep();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Udpate the eyes state and visual appearance
|
|
{
|
|
float actualTarget = MathF.Clamp(this.eyeOpenTarget - moveDistress * 0.35f, 0.0f, 1.0f);
|
|
float eyeDiff = MathF.Abs(actualTarget - this.eyeOpenValue);
|
|
float eyeChange = MathF.Sign(actualTarget - this.eyeOpenValue) * MathF.Min(this.eyeSpeed, eyeDiff);
|
|
|
|
this.eyeOpenValue = MathF.Clamp(this.eyeOpenValue + eyeChange * Time.TimeMult, 0.0f, 1.0f);
|
|
if (this.eyeBlinking && this.eyeOpenValue <= this.eyeOpenTarget + 0.0001f) this.eyeOpenTarget = 1.0f;
|
|
|
|
if (this.eye != null)
|
|
{
|
|
this.eye.AnimTime = this.eyeOpenValue;
|
|
}
|
|
}
|
|
|
|
// Update the spikes state and visual appearance
|
|
for (int i = 0; i < this.spikeState.Length; i++)
|
|
{
|
|
float actualTarget = MathF.Clamp(this.spikeState[i].OpenTarget - moveDistress, 0.0f, 1.0f);
|
|
if (actualTarget > this.spikeState[i].OpenValue)
|
|
{
|
|
Vector2 spikeDir;
|
|
switch (i)
|
|
{
|
|
default:
|
|
case 0: spikeDir = new Vector2(1, -1); break;
|
|
case 1: spikeDir = new Vector2(1, 1); break;
|
|
case 2: spikeDir = new Vector2(-1, 1); break;
|
|
case 3: spikeDir = new Vector2(-1, -1); break;
|
|
}
|
|
|
|
Vector2 spikeBeginWorld = transform.GetWorldPoint(spikeDir * 4);
|
|
Vector2 spikeEndWorld = transform.GetWorldPoint(spikeDir * 11);
|
|
bool hitAnything = false;
|
|
RigidBody.RayCast(spikeBeginWorld, spikeEndWorld, data =>
|
|
{
|
|
if (data.Shape.IsSensor) return -1;
|
|
if (data.Body == body) return -1;
|
|
|
|
Ship otherShip = data.GameObj.GetComponent<Ship>();
|
|
if (otherShip != null && otherShip.Owner != null) return -1;
|
|
|
|
hitAnything = true;
|
|
return 0;
|
|
});
|
|
|
|
if (hitAnything)
|
|
{
|
|
actualTarget = 0.0f;
|
|
}
|
|
}
|
|
|
|
float spikeMoveDir = MathF.Sign(actualTarget - this.spikeState[i].OpenValue);
|
|
this.spikeState[i].OpenValue = MathF.Clamp(this.spikeState[i].OpenValue + spikeMoveDir * this.spikeState[i].Speed * Time.TimeMult, 0.0f, 1.0f);
|
|
if (this.spikeState[i].Blinking && this.spikeState[i].OpenValue <= this.spikeState[i].OpenTarget + 0.0001f)
|
|
{
|
|
this.spikeState[i].OpenTarget = 1.0f;
|
|
this.spikeState[i].Speed = Time.SPFMult / MathF.Rnd.NextFloat(0.25f, 1.0f);
|
|
}
|
|
|
|
// If we're extending a spike where the sensor has already registered a contact, explode
|
|
if (this.spikeState[i].OpenValue > 0.75f && this.spikeState[i].ContactCount > 0)
|
|
this.FireExplosives();
|
|
}
|
|
if (this.spikes != null)
|
|
{
|
|
for (int i = 0; i < this.spikes.Length; i++)
|
|
{
|
|
if (this.spikes[i] == null) continue;
|
|
Rect spikeRect = this.spikes[i].Rect;
|
|
|
|
spikeRect.Y = MathF.Lerp(3.5f, -4.5f, this.spikeState[i].OpenValue);
|
|
|
|
this.spikes[i].Rect = spikeRect;
|
|
}
|
|
}
|
|
|
|
// Make a sound while moving
|
|
if (blueprint.MoveSound != null)
|
|
{
|
|
// Determine the target volume
|
|
float targetVolume = MathF.Clamp(moveTowardsEnemyRatio, 0.0f, 1.0f);
|
|
|
|
// Clean up disposed loop
|
|
if (this.moveSoundLoop != null && this.moveSoundLoop.Disposed)
|
|
this.moveSoundLoop = null;
|
|
|
|
// Start the loop when requested
|
|
if (targetVolume > 0.0f && this.moveSoundLoop == null)
|
|
{
|
|
this.moveSoundLoop = DualityApp.Sound.PlaySound3D(blueprint.MoveSound, this.GameObj);
|
|
this.moveSoundLoop.Looped = true;
|
|
}
|
|
|
|
// Configure existing loop and dispose it when no longer needed
|
|
if (this.moveSoundLoop != null)
|
|
{
|
|
this.moveSoundLoop.Volume += (targetVolume - this.moveSoundLoop.Volume) * 0.05f * Time.TimeMult;
|
|
if (this.moveSoundLoop.Volume <= 0.05f)
|
|
{
|
|
this.moveSoundLoop.FadeOut(0.1f);
|
|
this.moveSoundLoop = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Make a danger sound while moving with spikes out
|
|
if (blueprint.AttackSound != null)
|
|
{
|
|
// Determine the target volume
|
|
float targetVolume = this.spikesActive ? MathF.Clamp(moveTowardsEnemyRatio, 0.25f, 1.0f) : 0.0f;
|
|
|
|
// Clean up disposed loop
|
|
if (this.dangerSoundLoop != null && this.dangerSoundLoop.Disposed)
|
|
this.dangerSoundLoop = null;
|
|
|
|
// Start the loop when requested
|
|
if (targetVolume > 0.0f && this.dangerSoundLoop == null)
|
|
{
|
|
this.dangerSoundLoop = DualityApp.Sound.PlaySound3D(blueprint.AttackSound, this.GameObj);
|
|
this.dangerSoundLoop.Looped = true;
|
|
}
|
|
|
|
// Configure existing loop and dispose it when no longer needed
|
|
if (this.dangerSoundLoop != null)
|
|
{
|
|
this.dangerSoundLoop.Volume += (targetVolume - this.dangerSoundLoop.Volume) * 0.1f * Time.TimeMult;
|
|
if (this.dangerSoundLoop.Volume <= 0.05f)
|
|
{
|
|
this.dangerSoundLoop.FadeOut(0.1f);
|
|
this.dangerSoundLoop = null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ICmpMessageListener.OnMessage(GameMessage msg)
|
|
{
|
|
// We're dead? Damnit! Blow up at least.
|
|
if (msg is ShipDeathMessage)
|
|
{
|
|
this.FireExplosives();
|
|
}
|
|
}
|
|
|
|
void ICmpInitializable.OnInit(Component.InitContext context)
|
|
{
|
|
if (context == InitContext.Activate)
|
|
{
|
|
// Retrieve eye object references and initialize it
|
|
GameObject eyeObject = this.GameObj.ChildByName("Eye");
|
|
this.eye = eyeObject != null ? eyeObject.GetComponent<AnimSpriteRenderer>() : null;
|
|
if (this.eye != null)
|
|
{
|
|
this.eye.AnimLoopMode = AnimSpriteRenderer.LoopMode.FixedSingle;
|
|
this.eye.AnimDuration = 1.0f;
|
|
this.eye.AnimTime = this.eyeOpenValue;
|
|
}
|
|
|
|
// Retrieve spike references
|
|
GameObject[] spikeObj = new GameObject[4];
|
|
spikeObj[0] = this.GameObj.ChildByName("SpikeTopRight");
|
|
spikeObj[1] = this.GameObj.ChildByName("SpikeBottomRight");
|
|
spikeObj[2] = this.GameObj.ChildByName("SpikeBottomLeft");
|
|
spikeObj[3] = this.GameObj.ChildByName("SpikeTopLeft");
|
|
this.spikes = new SpriteRenderer[spikeObj.Length];
|
|
for (int i = 0; i < spikeObj.Length; i++)
|
|
{
|
|
this.spikes[i] = spikeObj[i] != null ? spikeObj[i].GetComponent<SpriteRenderer>() : null;
|
|
}
|
|
}
|
|
}
|
|
void ICmpInitializable.OnShutdown(Component.ShutdownContext context)
|
|
{
|
|
if (context == ShutdownContext.Deactivate)
|
|
{
|
|
// Fade out playing loop sounds, if there are any. Clean up!
|
|
if (this.moveSoundLoop != null)
|
|
{
|
|
this.moveSoundLoop.FadeOut(0.5f);
|
|
this.moveSoundLoop = null;
|
|
}
|
|
if (this.dangerSoundLoop != null)
|
|
{
|
|
this.dangerSoundLoop.FadeOut(0.5f);
|
|
this.dangerSoundLoop = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ICmpCollisionListener.OnCollisionBegin(Component sender, CollisionEventArgs args)
|
|
{
|
|
RigidBodyCollisionEventArgs bodyArgs = args as RigidBodyCollisionEventArgs;
|
|
if (bodyArgs == null) return;
|
|
if (bodyArgs.OtherShape.IsSensor) return;
|
|
|
|
Bullet otherBullet = bodyArgs.CollideWith.GetComponent<Bullet>();
|
|
int spikeIndex = this.GetSpikeIndex(bodyArgs.MyShape);
|
|
if (spikeIndex != -1 && otherBullet == null)
|
|
{
|
|
this.spikeState[spikeIndex].ContactCount++;
|
|
}
|
|
|
|
if (this.state != MindState.Asleep)
|
|
{
|
|
if (spikeIndex != -1)
|
|
{
|
|
if (this.spikeState[spikeIndex].OpenValue > 0.75f && otherBullet == null)
|
|
this.FireExplosives();
|
|
}
|
|
else
|
|
{
|
|
if (otherBullet != null)
|
|
{
|
|
this.BlinkSpikes(MathF.Rnd.NextFloat(0.5f, 1.0f));
|
|
this.BlinkEye(MathF.Rnd.NextFloat(0.35f, 0.6f));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
void ICmpCollisionListener.OnCollisionEnd(Component sender, CollisionEventArgs args)
|
|
{
|
|
RigidBodyCollisionEventArgs bodyArgs = args as RigidBodyCollisionEventArgs;
|
|
if (bodyArgs == null) return;
|
|
if (bodyArgs.OtherShape.IsSensor) return;
|
|
|
|
Bullet otherBullet = bodyArgs.CollideWith.GetComponent<Bullet>();
|
|
int spikeIndex = this.GetSpikeIndex(bodyArgs.MyShape);
|
|
if (spikeIndex != -1 && otherBullet == null)
|
|
{
|
|
this.spikeState[spikeIndex].ContactCount--;
|
|
}
|
|
}
|
|
void ICmpCollisionListener.OnCollisionSolve(Component sender, CollisionEventArgs args)
|
|
{
|
|
}
|
|
}
|
|
}
|