public new static void LoadSharedAssetsOnce()
        {
                        #if __IOS__
            var whiteColor = UIColor.White;
                        #else
            NSColor whiteColor = null;
            new NSObject().InvokeOnMainThread(() => {
                whiteColor = NSColor.White;
            });
                        #endif

            SKTextureAtlas atlas = SKTextureAtlas.FromName("Environment");

            sharedProjectile             = SKSpriteNode.FromTexture(atlas.TextureNamed("warrior_throw_hammer.png"));
            sharedProjectile.PhysicsBody = SKPhysicsBody.CreateCircularBody(ProjectileCollisionRadius);
            sharedProjectile.Name        = "Projectile";
            sharedProjectile.PhysicsBody.CategoryBitMask    = (uint)ColliderType.Projectile;
            sharedProjectile.PhysicsBody.CollisionBitMask   = (uint)ColliderType.Wall;
            sharedProjectile.PhysicsBody.ContactTestBitMask = sharedProjectile.PhysicsBody.CollisionBitMask;

            sharedProjectileEmitter     = GraphicsUtilities.EmitterNodeWithEmitterNamed("WarriorProjectile");
            sharedIdleAnimationFrames   = GraphicsUtilities.LoadFramesFromAtlas("Warrior_Idle", "warrior_idle_", WarriorIdleFrames);
            sharedWalkAnimationFrames   = GraphicsUtilities.LoadFramesFromAtlas("Warrior_Walk", "warrior_walk_", DefaultNumberOfWalkFrames);
            sharedAttackAnimationFrames = GraphicsUtilities.LoadFramesFromAtlas("Warrior_Attack", "warrior_attack_", WarriorThrowFrames);
            sharedGetHitAnimationFrames = GraphicsUtilities.LoadFramesFromAtlas("Warrior_GetHit", "warrior_getHit_", WarriorGetHitFrames);
            sharedDeathAnimationFrames  = GraphicsUtilities.LoadFramesFromAtlas("Warrior_Death", "warrior_death_", WarriorDeathFrames);
            sharedDamageAction          = SKAction.Sequence(new [] {
                SKAction.ColorizeWithColor(whiteColor, 10, 0),
                SKAction.WaitForDuration(0.5),
                SKAction.ColorizeWithColorBlendFactor(0, 0.25)
            });
        }
        public override nfloat DistanceToWall(CGPoint pos0, CGPoint pos1)
        {
            var a = ConvertWorldPointToLevelMapPoint(pos0);
            var b = ConvertWorldPointToLevelMapPoint(pos1);

            var deltaX = b.X - a.X;
            var deltaY = b.Y - a.Y;
            var dist   = GraphicsUtilities.DistanceBetweenCGPoints(a, b);
            var inc    = 1f / dist;
            var p      = CGPoint.Empty;

            for (nfloat i = 0; i <= 1; i += inc)
            {
                p.X = a.X + i * deltaX;
                p.Y = a.Y + i * deltaY;

                DataMap point = levelMap.QueryLevelMap(p);
                if (point.Wall > 200)
                {
                    CGPoint wpos2 = ConvertLevelMapPointToWorldPoint(p);
                    return(GraphicsUtilities.DistanceBetweenCGPoints(pos0, wpos2));
                }
            }
            return(nfloat.MaxValue);
        }
Ejemplo n.º 3
0
        public void Generate()
        {
            if (GoblinCap <= 0 || sGlobalAllocation >= GoblinCap)
            {
                return;
            }

            Goblin character = inactiveGoblins [inactiveGoblins.Count - 1];

            if (character == null)
            {
                return;
            }

            var offset = CollisionRadius * 0.75f;
            var rot    = GraphicsUtilities.PalarAdjust(VirtualZRotation);
            var pos    = new CGPoint((float)Math.Cos(rot) * offset, (float)Math.Sin(rot) * offset);

            character.Position = new CGPoint(pos.X + Position.X, pos.Y + Position.Y);

            MultiplayerLayeredCharacterScene scene = CharacterScene;

            character.AddToScene(CharacterScene);

            character.ZPosition = -1f;
            character.FadeIn(0.5f);

            inactiveGoblins.Remove(character);
            ActiveGoblins.Add(character);
            sGlobalAllocation++;
        }
        public void MoveTowards(CGPoint position, double timeInterval)
        {
            CGPoint curPosition = Position;
            var     dx          = position.X - curPosition.X;
            var     dy          = position.Y - curPosition.Y;
            var     ds          = MovementSpeed * (float)timeInterval;

            var angle = GraphicsUtilities.RadiansBetweenCGPoints(position, curPosition);

            angle     = GraphicsUtilities.PalarAdjust(angle);
            ZRotation = angle;

            var distRemaining = GraphicsUtilities.Hypotenuse(dx, dy);

            if (distRemaining < ds)
            {
                Position = position;
            }
            else
            {
                var x = (float)(curPosition.X - Math.Sin(angle) * ds);
                var y = (float)(curPosition.Y + Math.Cos(angle) * ds);
                Position = new CGPoint(x, y);
            }

            RequestedAnimation = AnimationState.Walk;
        }
Ejemplo n.º 5
0
        protected HeroCharacter AddHeroFor(Player player)
        {
            if (player == null)
            {
                throw new ArgumentNullException("player", "Player should not be null");
            }

            if (player.Hero != null && !player.Hero.Dying)
            {
                player.Hero.RemoveFromParent();
            }

            CGPoint       spawnPos = DefaultSpawnCGPoint;
            HeroCharacter hero     = CreateHeroBy(player.HeroType, spawnPos, player);

            if (hero != null)
            {
                var emitter = (SKEmitterNode)SharedSpawnEmitter.Copy();
                emitter.Position = spawnPos;
                AddNode(emitter, WorldLayer.AboveCharacter);
                GraphicsUtilities.RunOneShotEmitter(emitter, 0.15f);

                hero.FadeIn(2f);
                hero.AddToScene(this);
                Heroes.Add(hero);
            }
            player.Hero = hero;

            return(hero);
        }
        void OnDidBeginContact(object sender, EventArgs e)
        {
            var contact = (SKPhysicsContact)sender;
            // Either bodyA or bodyB in the collision could be a character.
            var node = contact.BodyA.Node as Character;

            if (node != null)
            {
                node.CollidedWith(contact.BodyB);
            }

            // Check bodyB too.
            node = contact.BodyB.Node as Character;
            if (node != null)
            {
                node.CollidedWith(contact.BodyA);
            }

            // Handle collisions with projectiles.
            var isBodyA = (contact.BodyA.CategoryBitMask & (uint)ColliderType.Projectile) != 0;
            var isBodyB = (contact.BodyB.CategoryBitMask & (uint)ColliderType.Projectile) != 0;

            if (isBodyA || isBodyB)
            {
                SKNode projectile = isBodyA ? contact.BodyA.Node : contact.BodyB.Node;
                projectile.RunAction(SKAction.RemoveFromParent());

                // Build up a "one shot" particle to indicate where the projectile hit.
                var emitter = (SKEmitterNode)SharedProjectileSparkEmitter.Copy();
                AddNode(emitter, WorldLayer.AboveCharacter);
                emitter.Position = projectile.Position;
                GraphicsUtilities.RunOneShotEmitter(emitter, 0.15f);
            }
        }
        public static void LoadSharedAssetsOnce()
        {
                        #if __IOS__
            var whiteColor = UIColor.White;
                        #else
            NSColor whiteColor = null;
            new NSObject().InvokeOnMainThread(() => {
                whiteColor = NSColor.White;
            });
                        #endif

            SKTextureAtlas atlas = SKTextureAtlas.FromName("Environment");

            sharedIdleAnimationFrames   = GraphicsUtilities.LoadFramesFromAtlas("Goblin_Idle", "goblin_idle_", DefaultNumberOfIdleFrames);
            sharedWalkAnimationFrames   = GraphicsUtilities.LoadFramesFromAtlas("Goblin_Walk", "goblin_walk_", DefaultNumberOfWalkFrames);
            sharedAttackAnimationFrames = GraphicsUtilities.LoadFramesFromAtlas("Goblin_Attack", "goblin_attack_", GoblinAttackFrames);
            sharedGetHitAnimationFrames = GraphicsUtilities.LoadFramesFromAtlas("Goblin_GetHit", "goblin_getHit_", GoblinGetHitFrames);
            sharedDeathAnimationFrames  = GraphicsUtilities.LoadFramesFromAtlas("Goblin_Death", "goblin_death_", GoblinDeathFrames);
            sharedDamageEmitter         = GraphicsUtilities.EmitterNodeWithEmitterNamed("Damage");
            sharedDeathSplort           = SKSpriteNode.FromTexture(atlas.TextureNamed("minionSplort.png"));
            sharedDamageAction          = SKAction.Sequence(new [] {
                SKAction.ColorizeWithColor(whiteColor, 1, 0),
                SKAction.WaitForDuration(0.75f),
                SKAction.ColorizeWithColorBlendFactor(0, 0.1)
            });
        }
        public void MoveInDirection(CGPoint direction, double timeInterval)
        {
            var curPosition = Position;
            var dx          = MovementSpeed * direction.X;
            var dy          = MovementSpeed * direction.Y;
            var ds          = MovementSpeed * (float)timeInterval;

            var targetPosition = new CGPoint(curPosition.X + dx, curPosition.Y + dy);

            var angle = GraphicsUtilities.RadiansBetweenCGPoints(targetPosition, curPosition);
            var ang   = GraphicsUtilities.PalarAdjust(angle);

            ZRotation = ang;

            var distRemaining = GraphicsUtilities.Hypotenuse(dx, dy);

            if (distRemaining < ds)
            {
                Position = targetPosition;
            }
            else
            {
                float x = (float)(curPosition.X - Math.Sin(ang) * ds);
                float y = (float)(curPosition.Y + Math.Cos(ang) * ds);
                Position = new CGPoint(x, y);
            }

            // Don't change to a walk animation if we planning an attack.
            if (!Attacking)
            {
                RequestedAnimation = AnimationState.Walk;
            }
        }
        protected override void LoadSceneAssets()
        {
            SKTextureAtlas atlas = SKTextureAtlas.FromName("Environment");

            // Load archived emitters and create copyable sprites.
            sharedProjectileSparkEmitter = GraphicsUtilities.EmitterNodeWithEmitterNamed("ProjectileSplat");
            sharedSpawnEmitter           = GraphicsUtilities.EmitterNodeWithEmitterNamed("Spawn");

            sharedSmallTree = new Tree(new SKNode[] {
                SKSpriteNode.FromTexture(atlas.TextureNamed("small_tree_base.png")),
                SKSpriteNode.FromTexture(atlas.TextureNamed("small_tree_middle.png")),
                SKSpriteNode.FromTexture(atlas.TextureNamed("small_tree_top.png"))
            }, 25);
            sharedBigTree = new Tree(new SKNode[] {
                SKSpriteNode.FromTexture(atlas.TextureNamed("big_tree_base.png")),
                SKSpriteNode.FromTexture(atlas.TextureNamed("big_tree_middle.png")),
                SKSpriteNode.FromTexture(atlas.TextureNamed("big_tree_top.png"))
            }, 150);
            sharedBigTree.FadeAlpha = true;
            sharedLeafEmitterA      = GraphicsUtilities.EmitterNodeWithEmitterNamed("Leaves_01");
            sharedLeafEmitterB      = GraphicsUtilities.EmitterNodeWithEmitterNamed("Leaves_02");

            // Load the tiles that make up the ground layer.
            LoadWorldTiles();

            // Load assets for all the sprites within this scene.
            Cave.LoadSharedAssetsOnce();
            HeroCharacter.LoadSharedAssetsOnce();
            Archer.LoadSharedAssetsOnce();
            Warrior.LoadSharedAssetsOnce();
            Goblin.LoadSharedAssetsOnce();
            Boss.LoadSharedAssetsOnce();
        }
        public void FaceTo(CGPoint position)
        {
            var      angle  = GraphicsUtilities.RadiansBetweenCGPoints(position, Position);
            var      ang    = GraphicsUtilities.PalarAdjust(angle);
            SKAction action = SKAction.RotateToAngle(ang, 0);

            RunAction(action);
        }
        public override void DidSimulatePhysics()
        {
            base.DidSimulatePhysics();

            // Get the position either of the default hero or the hero spawn point.
            HeroCharacter defaultHero = DefaultPlayer.Hero;
            CGPoint       position;

            if (defaultHero != null && Heroes.Contains(defaultHero))
            {
                position = defaultHero.Position;
            }
            else
            {
                position = DefaultSpawnCGPoint;
            }

            // Update the alphas of any trees that are near the hero (center of the camera) and therefore visible or soon to be visible.
            foreach (Tree tree in trees)
            {
                if (GraphicsUtilities.DistanceBetweenCGPoints(tree.Position, position) < 1024)
                {
                    tree.UpdateAlphaWithScene(this);
                }
            }

            if (!WorldMovedForUpdate)
            {
                return;
            }

            // Show any nearby hidden particle systems and hide those that are too far away to be seen.
            foreach (SKEmitterNode particles in particleSystems)
            {
                bool particlesAreVisible = GraphicsUtilities.DistanceBetweenCGPoints(particles.Position, position) < 1024;

                if (!particlesAreVisible && !particles.Paused)
                {
                    particles.Paused = true;
                }
                else if (particlesAreVisible && particles.Paused)
                {
                    particles.Paused = false;
                }
            }

            // Update nearby parallax sprites.
            foreach (ParallaxSprite sprite in parallaxSprites)
            {
                if (GraphicsUtilities.DistanceBetweenCGPoints(sprite.Position, position) >= 1024)
                {
                    continue;
                }

                sprite.UpdateOffset();
            }
        }
Ejemplo n.º 12
0
        public override void UpdateWithTimeSinceLastUpdate(double interval)
        {
            if (Character.Dying)
            {
                Target = null;
                return;
            }

            var position = Character.Position;
            MultiplayerLayeredCharacterScene scene = Character.CharacterScene;
            nfloat closestHeroDistance             = float.MaxValue;

            // Find the closest living hero, if any, within our alert distance.
            foreach (HeroCharacter hero in scene.Heroes)
            {
                var heroPosition = hero.Position;
                var distance     = GraphicsUtilities.DistanceBetweenCGPoints(position, heroPosition);
                if (distance < EnemyAlertRadius &&
                    distance < closestHeroDistance &&
                    !hero.Dying)
                {
                    closestHeroDistance = distance;
                    Target = hero;
                }
            }

            // If there's no target, don't do anything.
            if (Target == null)
            {
                return;
            }

            // Otherwise chase or attack the target, if it's near enough.
            var   heroPos     = Target.Position;
            float chaseRadius = ChaseRadius;

            if (closestHeroDistance > MaxAlertRadius)
            {
                Target = null;
            }
            else if (closestHeroDistance > ChaseRadius)
            {
                Character.MoveTowards(heroPos, interval);
            }
            else if (closestHeroDistance < ChaseRadius)
            {
                Character.FaceTo(heroPos);
                Character.PerformAttackAction();
            }
        }
Ejemplo n.º 13
0
        public override void UpdateWithTimeSinceLastUpdate(double interval)
        {
            Cave cave = (Cave)Character;

            if (cave.Health <= 0)
            {
                return;
            }

            MultiplayerLayeredCharacterScene scene = cave.CharacterScene;

            nfloat closestHeroDistance = MinimumHeroDistance;
            var    closestHeroPosition = CGPoint.Empty;

            var cavePosition = cave.Position;

            foreach (SKNode hero in scene.Heroes)
            {
                var heroPosition = hero.Position;
                var distance     = GraphicsUtilities.DistanceBetweenCGPoints(cavePosition, heroPosition);
                if (distance < closestHeroDistance)
                {
                    closestHeroDistance = distance;
                    closestHeroPosition = heroPosition;
                }
            }

            var distScale = closestHeroDistance / MinimumHeroDistance;

            // Generate goblins more quickly if the closest hero is getting closer.
            cave.TimeUntilNextGenerate -= (float)interval;

            // Either time to generate or the hero is so close we need to respond ASAP!
            int goblinCount = cave.ActiveGoblins.Count;

            if (goblinCount < 1 ||
                cave.TimeUntilNextGenerate <= 0 ||
                (distScale < 0.35f && cave.TimeUntilNextGenerate > 5))
            {
                if (goblinCount < 1 || (goblinCount < 4 && closestHeroPosition != CGPoint.Empty) &&
                    scene.CanSee(closestHeroPosition, cave.Position))
                {
                    cave.Generate();
                }
                cave.TimeUntilNextGenerate = 4 * distScale;
            }
        }
        public override void Initialize()
        {
            base.Initialize();

            // Build level and tree maps from map_collision.png and map_foliage.png respectively.
            levelMap = GraphicsUtilities.CreateMapScaner("map_level.png");
            treeMap  = GraphicsUtilities.CreateMapScaner("map_trees.png");

            Cave.GoblinCap = 32;

            BuildWorld();

            // Center the camera on the hero spawn point.
            var startPosition = DefaultSpawnCGPoint;

            CenterWorld(startPosition);
        }
Ejemplo n.º 15
0
        public static void LoadSharedAssetsOnce()
        {
                        #if __IOS__
            var whiteColor = UIColor.White;
                        #else
            NSColor whiteColor = null;
            new NSObject().InvokeOnMainThread(() => {
                whiteColor = NSColor.White;
            });
                        #endif

            SKTextureAtlas atlas = SKTextureAtlas.FromName("Environment");

            SKEmitterNode fire = GraphicsUtilities.EmitterNodeWithEmitterNamed("CaveFire");
            fire.ZPosition = 1;

            SKEmitterNode smoke = GraphicsUtilities.EmitterNodeWithEmitterNamed("CaveFireSmoke");

            var sKNode = new SKNode();
            sKNode.Add(fire);
            sKNode.Add(smoke);
            SKNode torch = sKNode;

            sharedCaveBase = SKSpriteNode.FromTexture(atlas.TextureNamed("cave_base.png"));

            // Add two torches either side of the entrance.
            torch.Position = new CGPoint(83, 83);
            sharedCaveBase.AddChild(torch);
            var torchB = (SKNode)torch.Copy();
            torchB.Position = new CGPoint(-83, 83);
            sharedCaveBase.AddChild(torchB);

            sharedCaveTop     = SKSpriteNode.FromTexture(atlas.TextureNamed("cave_top.png"));
            sharedDeathSplort = SKSpriteNode.FromTexture(atlas.TextureNamed("cave_destroyed.png"));

            sharedDamageEmitter = GraphicsUtilities.EmitterNodeWithEmitterNamed("CaveDamage");
            sharedDeathEmitter  = GraphicsUtilities.EmitterNodeWithEmitterNamed("CaveDeathSmoke");

            sharedDamageAction = SKAction.Sequence(new [] {
                SKAction.ColorizeWithColor(whiteColor, 1, 0),
                SKAction.WaitForDuration(0.25),
                SKAction.ColorizeWithColorBlendFactor(0, 0.1),
            });
        }
        // Apply damage and return true if death.
        public virtual bool ApplyDamage(nfloat damage)
        {
            Health -= damage;

            if (Health <= 0)
            {
                PerformDeath();
                return(true);
            }

            var emitter = (SKEmitterNode)DamageEmitter.Copy();

            CharacterScene.AddNode(emitter, WorldLayer.AboveCharacter);
            emitter.Position = Position;
            GraphicsUtilities.RunOneShotEmitter(emitter, 0.15f);

            // Show the damage.
            RunAction(DamageAction);

            return(false);
        }
 public static void LoadSharedAssetsOnce()
 {
                 #if __IOS__
     var whiteColor = UIColor.White;
                 #else
     NSColor whiteColor = null;
     new NSObject().InvokeOnMainThread(() => {
         whiteColor = NSColor.White;
     });
                 #endif
     sharedIdleAnimationFrames   = GraphicsUtilities.LoadFramesFromAtlas("Boss_Idle", "boss_idle_", BossIdleFrames);
     sharedWalkAnimationFrames   = GraphicsUtilities.LoadFramesFromAtlas("Boss_Walk", "boss_walk_", BossWalkFrames);
     sharedAttackAnimationFrames = GraphicsUtilities.LoadFramesFromAtlas("Boss_Attack", "boss_attack_", BossAttackFrames);
     sharedGetHitAnimationFrames = GraphicsUtilities.LoadFramesFromAtlas("Boss_GetHit", "boss_getHit_", BossGetHitFrames);
     sharedDeathAnimationFrames  = GraphicsUtilities.LoadFramesFromAtlas("Boss_Death", "boss_death_", BossDeathFrames);
     sharedDamageEmitter         = GraphicsUtilities.EmitterNodeWithEmitterNamed("BossDamage");
     sharedDamageAction          = SKAction.Sequence(new [] {
         SKAction.ColorizeWithColor(whiteColor, 1, 0),
         SKAction.WaitForDuration(0.5),
         SKAction.ColorizeWithColorBlendFactor(0, 0.1)
     });
 }
        public override void AnimationDidComplete(AnimationState animation)
        {
            switch (animation)
            {
            case AnimationState.Death:
                var emitter = (SKEmitterNode)DeathEmitter.Copy();
                emitter.ZPosition = -0.8f;
                AddChild(emitter);
                GraphicsUtilities.RunOneShotEmitter(emitter, 4.5f);

                RunAction(SKAction.Sequence(new [] {
                    SKAction.WaitForDuration(4),
                    SKAction.Run(() => CharacterScene.HeroWasKilled(this)),
                    SKAction.RemoveFromParent()
                }));
                break;

            case AnimationState.Attack:
                FireProjectile();
                break;
            }
        }
        public void UpdateAlphaWithScene(MultiplayerLayeredCharacterScene scene)
        {
            if (scene == null)
            {
                throw new ArgumentNullException("scene");
            }

            if (!FadeAlpha)
            {
                return;
            }

            nfloat closestHeroDistance = nfloat.MaxValue;

            // See if there are any heroes nearby.
            var ourPosition = Position;

            foreach (SKNode hero in scene.Heroes)
            {
                var theirPos = hero.Position;
                var distance = GraphicsUtilities.DistanceBetweenCGPoints(ourPosition, theirPos);
                closestHeroDistance = (nfloat)Math.Min(distance, closestHeroDistance);
            }

            if (closestHeroDistance > OpaqueDistance)
            {
                // No heroes nearby.
                Alpha = 1;
            }
            else
            {
                // Adjust the alpha based on how close the hero is.
                var ratio = closestHeroDistance / OpaqueDistance;
                Alpha = 0.1f + ratio * ratio * 0.9f;
            }
        }
Ejemplo n.º 20
0
        void ConfigureController(GCController controller, Player player)
        {
            Console.WriteLine("Assigning {0} to player {1} [{2}]", controller.VendorName, player, players.IndexOf(player));

            // Assign the controller to the player.
            player.Controller = controller;

            GCControllerDirectionPadValueChangedHandler dpadMoveHandler = (dpad, xValue, yValue) => {
                var length = GraphicsUtilities.Hypotenuse(xValue, yValue);
                if (length > 0f)
                {
                    var invLength = 1 / length;
                    player.HeroMoveDirection = new CGPoint(xValue * invLength, yValue * invLength);
                }
                else
                {
                    player.HeroMoveDirection = CGPoint.Empty;
                }
            };

            // Use either the dpad or the left thumbstick to move the character.
            controller.ExtendedGamepad.LeftThumbstick.ValueChangedHandler = dpadMoveHandler;
            controller.Gamepad.DPad.ValueChangedHandler = dpadMoveHandler;

            GCControllerButtonValueChanged fireButtonHandler = (button, value, pressed) => {
                player.FireAction = pressed;
            };

            controller.Gamepad.ButtonA.SetValueChangedHandler(fireButtonHandler);
            controller.Gamepad.ButtonB.SetValueChangedHandler(fireButtonHandler);

            if (player != DefaultPlayer && player.Hero == null)
            {
                AddHeroFor(player);
            }
        }
        public override bool CanSee(CGPoint pos0, CGPoint pos1)
        {
            var a = ConvertWorldPointToLevelMapPoint(pos0);
            var b = ConvertWorldPointToLevelMapPoint(pos1);

            var deltaX = b.X - a.Y;
            var deltaY = b.Y - a.Y;
            var dist   = GraphicsUtilities.DistanceBetweenCGPoints(a, b);
            var inc    = 1 / dist;
            var p      = CGPoint.Empty;

            for (nfloat i = 0; i <= 1; i += inc)
            {
                p.X = a.X + i * deltaX;
                p.Y = a.Y + i * deltaY;

                DataMap point = levelMap.QueryLevelMap(p);
                if (point.Wall > 200)
                {
                    return(false);
                }
            }
            return(true);
        }
Ejemplo n.º 22
0
        public override void Update(double currentTime)
        {
            // Handle time delta.
            // If we drop below 60fps, we still want everything to move the same distance.
            double timeSinceLast = currentTime - lastUpdateTimeInterval;

            lastUpdateTimeInterval = currentTime;

            // more than a second since last update
            if (timeSinceLast > 1)
            {
                timeSinceLast       = MIN_TIME_INTERVAL;
                WorldMovedForUpdate = true;
            }

            UpdateWithTimeSinceLastUpdate(timeSinceLast);

            var           defaultPlayer = DefaultPlayer;
            HeroCharacter hero          = Heroes.Count > 0 ? defaultPlayer.Hero : null;

                        #if __IOS__
            if (hero != null && !hero.Dying &&
                defaultPlayer.TargetLocation != CGPoint.Empty)
            {
                if (defaultPlayer.FireAction)
                {
                    hero.FaceTo(defaultPlayer.TargetLocation);
                }

                if (defaultPlayer.MoveRequested)
                {
                    if (defaultPlayer.TargetLocation != hero.Position)
                    {
                        hero.MoveTowards(defaultPlayer.TargetLocation, timeSinceLast);
                    }
                    else
                    {
                        defaultPlayer.MoveRequested = false;
                    }
                }
            }
                        #endif

            foreach (var player in players)
            {
                if (player == null)
                {
                    continue;
                }

                hero = player.Hero;
                if (hero == null || hero.Dying)
                {
                    continue;
                }

                // heroMoveDirection is used by game controllers.
                CGPoint heroMoveDirection = player.HeroMoveDirection;
                if (GraphicsUtilities.Hypotenuse(heroMoveDirection.X, heroMoveDirection.Y) > 0f)
                {
                    hero.MoveInDirection(heroMoveDirection, timeSinceLast);
                }
                else
                {
                    if (player.MoveForward)
                    {
                        hero.Move(MoveDirection.Forward, timeSinceLast);
                    }
                    else if (player.MoveBack)
                    {
                        hero.Move(MoveDirection.Back, timeSinceLast);
                    }

                    if (player.MoveLeft)
                    {
                        hero.Move(MoveDirection.Left, timeSinceLast);
                    }
                    else if (player.MoveRight)
                    {
                        hero.Move(MoveDirection.Right, timeSinceLast);
                    }
                }

                if (player.FireAction)
                {
                    hero.PerformAttackAction();
                }
            }
        }
 public static void LoadSharedAssetsOnce()
 {
     sharedProjectileSoundAction = SKAction.PlaySoundFileNamed("magicmissile.caf", false);
     sharedDeathEmitter          = GraphicsUtilities.EmitterNodeWithEmitterNamed("Death");
     sharedDamageEmitter         = GraphicsUtilities.EmitterNodeWithEmitterNamed("Damage");
 }