Exemple #1
0
        public void Update(Area area, GameTime gameTime)
        {
            OnUpdate(area, gameTime);

            // Bewegung
            if (destination.HasValue)
            {
                Vector2 expectedDistance = destination.Value - startPoint.Value;
                Vector2 currentDistance = Host.Position - startPoint.Value;

                // Prüfen ob das Ziel erreicht (oder überschritten) wurde.
                if (currentDistance.LengthSquared() > expectedDistance.LengthSquared())
                {
                    startPoint = null;
                    destination = null;
                    Host.Velocity = Vector2.Zero;
                }
                else
                {
                    // Kurs festlegen
                    Vector2 direction = destination.Value - Host.Position;
                    direction.Normalize();
                    Host.Velocity = direction * speed * Host.MaxSpeed;
                }
            }
        }
        /// <summary>
        /// Lädt alle Areas die sich aktuell im Maps-Verzeichnis befinden.
        /// </summary>
        public static Area[] LoadAll(ref int nextId)
        {
            // Alle json-Files im Map-Folder suchen
            string mapPath = ".\\Maps";
            var files = Directory.GetFiles(mapPath, "*.json");

            // Alle gefundenen json-Files laden
            Area[] result = new Area[files.Length];
            for (int i = 0; i < files.Length; i++)
                result[i] = LoadFromJson(files[i], ref nextId);

            return result;
        }
        public override void OnUpdate(Area area, GameTime gameTime)
        {
            // Initiales Zentrum festlegen
            if (!center.HasValue)
                center = Host.Position;

            if (!Walking)
            {
                // Delay abwarten
                if (delay > TimeSpan.Zero)
                {
                    delay -= gameTime.ElapsedGameTime;
                    return;
                }

                // Neuen Zielpunkt wählen
                Vector2 variation = new Vector2(
                    (float)(Random.NextDouble() * 2 - 1.0), 
                    (float)(Random.NextDouble() * 2 - 1.0));
                WalkTo(center.Value + variation * 2 * range, 0.4f);
                delay = TimeSpan.FromSeconds(2);
            }
        }
        public override void OnUpdate(Area area, GameTime gameTime)
        {
            // Referenzpunkt ermitteln
            if (!startPoint.HasValue)
                startPoint = Host.Position;

            // Nach zielen ausschau halten
            if (target == null)
            {
                var potentialTargets = area.Items.
                    Where(i => (i.Position - Host.Position).LengthSquared() < range * range). // Filter nach Angriffsreichweite
                    Where(i => i.GetType() != Host.GetType()).                                // Items vom selben Typ verschonen
                    OrderBy(i => (i.Position - Host.Position).LengthSquared()).               // Sortiert nach Entfernung
                    OfType<IAttackable>().                                                    // Gefiltert nach Angreifbarkeit
                    Where(a => a.Hitpoints > 0);                                              // Gefiltert nach Lebendigkeit

                target = potentialTargets.FirstOrDefault() as Item;
            }

            // Ziel angreifen
            if (target != null)
            {
                attacker.AttackSignal = true;

                // Bei zu großem Abstand vom Ziel ablassen
                if ((target.Position - Host.Position).LengthSquared() > range * range ||
                    (target as IAttackable).Hitpoints <= 0)
                {
                    target = null;
                    WalkTo(startPoint.Value, 0.4f);
                }
                else
                {
                    WalkTo(target.Position, 0.6f);
                }
            }
        }
        public override void Update(GameTime gameTime)
        {
            maxVolume = game.Settings.MusicVolume * 0.05f;

            // Nur wenn Komponente aktiviert wurde.
            if (!Enabled)
                return;
            
            // Nur arbeiten, wenn es eine Welt, einen Player und eine aktive Area gibt.
            Area area = game.Local.GetCurrentArea();
            if (currentArea != area)
            {
                currentArea = area;
                if (currentArea != null)
                    Play(currentArea.Song);
            }

            // Override verhindern
            if (currentEffect == nextEffect)
                nextEffect = null;

            // Ausfaden
            if (currentEffect != null && nextEffect != null)
            {
                float currentVolume = currentSong.Volume;
                currentVolume -= (float)gameTime.ElapsedGameTime.TotalMilliseconds / totalFadeTime;
                if (currentVolume <= 0f)
                {
                    // Ausschalten
                    currentSong.Volume = 0;
                    currentSong.Stop();
                    currentSong.Dispose();
                    currentSong = null;
                    currentEffect = null;
                }
                else
                {
                    // Leiser
                    currentSong.Volume = currentVolume;
                }
            }

            // Einschalten
            if (currentEffect == null && nextEffect != null)
            {
                currentEffect = nextEffect;
                nextEffect = null;

                // Initialisieren mit 0 Lautstärke
                currentSong = currentEffect.CreateInstance();
                currentSong.IsLooped = true;
                currentSong.Volume = 0f;
                currentSong.Play();
            }

            // Einfaden
            if (currentEffect != null && nextEffect == null && currentSong.Volume < maxVolume)
            {
                float currentVolume = currentSong.Volume;
                currentVolume += (float)gameTime.ElapsedGameTime.TotalMilliseconds / totalFadeTime;
                currentVolume = Math.Min(currentVolume, maxVolume);
                currentSong.Volume = currentVolume;
            }
        }
        public override void Update(GameTime gameTime)
        {
            // Nur wenn Komponente aktiviert wurde.
            if (!Enabled)
                return;

            // Nur arbeiten, wenn es eine Welt, einen Player und eine aktive Area gibt.
            Area nextArea = game.Local.GetCurrentArea();
            if (game.Simulation.World == null || game.Local.Player == null || nextArea == null)
                return;
            
            // Reset aller Variablen falls sich der Player ändert
            if (player != game.Local.Player)
            {
                player = game.Local.Player;
                coins = player.Inventory.Count(i => i is Coin);
                recoveryTimes.Clear();
            }

            // Reset der Item variablen falls sich die Area ändert
            if (area != nextArea)
            {
                area = nextArea;

                // Recovery Times
                recoveryTimes.Clear();
                foreach (var item in area.Items.OfType<IAttacker>())
                    recoveryTimes.Add(item, item.Recovery);

                // Hitpoints
                hitpoints.Clear();
                foreach (var item in area.Items.OfType<IAttackable>())
                    hitpoints.Add(item, item.Hitpoints);
            }

            // Coins
            int c = player.Inventory.Count(i => i is Coin);
            if (coins < c)
                Play("coin");
            coins = c;

            // Sword
            foreach (var item in area.Items.OfType<IAttacker>())
            {
                TimeSpan recovery;
                if (!recoveryTimes.TryGetValue(item, out recovery))
                {
                    recovery = item.Recovery;
                    recoveryTimes.Add(item, item.Recovery);
                }

                if (recovery < item.Recovery)
                    Play("sword");
                recoveryTimes[item] = item.Recovery;
            }

            // Hit
            foreach (var item in area.Items.OfType<IAttackable>())
            {
                int points;
                if (!hitpoints.TryGetValue(item, out points))
                {
                    points = item.Hitpoints;
                    hitpoints.Add(item, item.Hitpoints);
                }

                if (points > item.Hitpoints)
                    Play("hit");
                hitpoints[item] = item.Hitpoints;
            }
        }
        /// <summary>
        /// Sendet einen Area/Inventar-Transfer des angegebenen Items an diesen Client.
        /// </summary>
        /// <param name="item">Item.</param>
        /// <param name="oldArea">Old area.</param>
        /// <param name="newArea">New area.</param>
        /// <param name="oldInventory">Old inventory.</param>
        /// <param name="newInventory">New inventory.</param>
        public void SendMove(Item item, Area oldArea, Area newArea, IInventory oldInventory, IInventory newInventory)
        {
            if (oldArea != null)
            {
                if (newArea != null)
                {
                    // Area to Area
                    // ItemId[int];OldArea[string];NewArea[string]
                    writer.Write((byte)MessageType.ServerMoveAreaToArea);
                    writer.Write((short)0);
                    writer.Write(item.Id);
                    writer.Write(oldArea.Name);
                    writer.Write(newArea.Name);
                }
                else
                {
                    // Area to Inventory
                    // ItemId[int];OldArea[string];InventoryId[int]
                    writer.Write((byte)MessageType.ServerMoveAreaToInventory);
                    writer.Write((short)0);
                    writer.Write(item.Id);
                    writer.Write(oldArea.Name);
                    writer.Write((newInventory as Item).Id);
                }
            }
            else
            {
                if (newArea != null)
                {
                    // Inventory To Area
                    // ItemId[int];InventoryId[int];NewArea[string]
                    writer.Write((byte)MessageType.ServerMoveInventoryToArea);
                    writer.Write((short)0);
                    writer.Write(item.Id);
                    writer.Write((oldInventory as Item).Id);
                    writer.Write(newArea.Name);
                }
                else
                {
                    // Inventory To Inventory
                    // ItemId[int];OldInventoryId[int];NewInventoryId[int]
                    writer.Write((byte)MessageType.ServerMoveInventoryToInventory);
                    writer.Write((short)0);
                    writer.Write(item.Id);
                    writer.Write((oldInventory as Item).Id);
                    writer.Write((newInventory as Item).Id);
                }
            }

            int contentend = (int)writerStream.Position;
            writerStream.Seek(1, SeekOrigin.Begin);
            writer.Write((short)(contentend - 3));
            writerStream.Seek(contentend, SeekOrigin.Begin);

            Flush();
        }
        /// <summary>
        /// Sendet einen Insert-Auftrag an den Client.
        /// </summary>
        /// <param name="item">Item.</param>
        /// <param name="area">Area.</param>
        /// <param name="inventory">Inventory.</param>
        public void SendInsert(Item item, Area area, IInventory inventory)
        {
            try
            {
                if (area != null)
                {
                    // Area[string];Type[string];Id[int];Payload[byte[]]
                    writer.Write((byte)MessageType.ServerInsertItemToArea);
                    writer.Write((short)0);
                    writer.Write(area.Name);
                }
                else
                {
                    // InventoryId[int];Type[string];Id[int];Payload[byte[]]
                    writer.Write((byte)MessageType.ServerInsertItemToArea);
                    writer.Write((short)0);
                    writer.Write((inventory as Item).Id);
                }

                // Type ermitteln
                writer.Write(item.GetType().FullName);
                writer.Write(item.Id);

                // Payload ermitteln und erstellen
                item.SerializeInsert(writer);
                int contentend = (int)writerStream.Position;

                // Content Länge eintragen
                writerStream.Seek(1, SeekOrigin.Begin);
                writer.Write((short)(contentend - 3));
                writerStream.Seek(contentend, SeekOrigin.Begin);

                Flush();
            }
            catch (Exception ex)
            {
                Close(ex, false);
            }
        }
        /// <summary>
        /// Verarbeitet den Zustandsabgleich eines Items.
        /// </summary>
        /// <param name="item">Item referenz</param>
        /// <param name="area">Area in der das Item liegt (oder null, falls Inventar)</param>
        /// <param name="inventory">Inventar in dem sich das Item befindet (oder null, falls Area)</param>
        private void HandleItem(Item item, Area area, IInventory inventory)
        {
            ItemCacheEntry entity;
            if (items.TryGetValue(item.Id, out entity))
            {
                // Frame Update
                entity.LastUpdate = currentFrame;

                // Item move
                if (entity.Area != area || entity.Inventory != inventory)
                {
                    foreach (var client in clients.ToArray())
                        client.SendMove(entity.Item, entity.Area, area, entity.Inventory, inventory);
                    entity.Area = area;
                    entity.Inventory = inventory;
                }

                // Updates
                if (currentFrame % KEYFRAME == 0)
                {
                    // Großes Update
                    foreach (var client in clients.ToArray())
                        client.SendKeyUpdate(item);
                }
                else if (currentFrame % UPDATEFRAME == 0)
                {
                    // Kleines Update
                    foreach (var client in clients.ToArray())
                        client.SendUpdate(item);    
                }
            }
            else
            {
                // Item fehlt -> Insert
                items.Add(item.Id, new ItemCacheEntry()
                    { 
                        Item = item, 
                        Area = area, 
                        Inventory = inventory,
                        LastUpdate = currentFrame
                    });
                            
                foreach (var client in clients.ToArray())
                    client.SendInsert(item, area, inventory);                    
            }
        }
Exemple #10
0
 public abstract void OnUpdate(Area area, GameTime gameTime);
        /// <summary>
        /// Rendert die Spielelemente der aktuellen Szene
        /// </summary>
        private void RenderItems(Area area, Point offset, GameTime gameTime)
        {
            // Items von hinten nach vorne rendern
            foreach (var item in area.Items.OrderBy(i => i.Position.Y))
            {
                // Renderer ermitteln und ggf. neu erzeugen
                ItemRenderer renderer;
                if (!itemRenderer.TryGetValue(item, out renderer))
                {
                    // ACHTUNG: Hier können potentiell neue Items nachträglich hinzu kommen zu denen die Textur noch fehlt
                    // Das muss geprüft und ggf nachgeladen werden.
                    Texture2D texture = GetItemTexture(item.Texture);
                    
                    if (item is Character)
                        renderer = new CharacterRenderer(item as Character, Camera, texture, font);
                    else
                        renderer = new SimpleItemRenderer(item, Camera, texture, font);

                    itemRenderer.Add(item, renderer);
                }

                // Ermitteln, ob Item im Interaktionsbereich ist
                bool highlight = false;
                if (item is IInteractable && game.Local.Player.InteractableItems.Contains(item as IInteractable) ||
                    item is IAttackable && game.Local.Player.AttackableItems.Contains(item as IAttackable))
                    highlight = true;

                // Item rendern
                renderer.Draw(spriteBatch, offset, gameTime, highlight);
            }

            // TODO: Nicht mehr verwendete Renderer entfernen
        }
        /// <summary>
        /// Rendert einen Layer der aktuellen Szene
        /// </summary>
        private void RenderLayer(Area area, Layer layer, Point offset)
        {
            // TODO: Nur den sichtbaren Bereich rendern
            for (int x = 0; x < area.Width; x++)
            {
                for (int y = 0; y < area.Height; y++)
                {
                    // Prüfen, ob diese Zelle ein Tile enthält
                    int tileId = layer.Tiles[x, y];
                    if (tileId == 0)
                        continue;

                    // Tile ermitteln
                    Tile tile = area.Tiles[tileId];
                    Texture2D texture = GetTileset(tile.Texture);

                    // Position ermitteln
                    int offsetX = (int)(x * Camera.Scale) - offset.X;
                    int offsetY = (int)(y * Camera.Scale) - offset.Y;

                    // Zelle mit der Standard-Textur (Gras) ausmalen
                    spriteBatch.Draw(texture, new Rectangle(offsetX, offsetY, (int)Camera.Scale, (int)Camera.Scale), tile.SourceRectangle, Color.White);
                }
            }
        }
        public override void Update(GameTime gameTime)
        {
            // Nur wenn Komponente aktiviert wurde.
            if (!Enabled)
                return;

            // Nur arbeiten, wenn es eine Welt, einen Player und eine aktive Area gibt.
            Area area = game.Local.GetCurrentArea();
            if (game.Simulation.World == null || game.Local.Player == null || area == null)
                return;

            if (currentArea != area)
            {
                // Aktuelle Area wechseln
                currentArea = area;

                // Initiale Kameraposition (temporär)
                Vector2 areaSize = new Vector2(currentArea.Width, currentArea.Height);
                Camera.SetFocusExplizit(game.Local.Player.Position, areaSize);
            }

            // Platziert den Kamerafokus auf den Spieler.
            Camera.SetFocus(game.Local.Player.Position);
        }
        /// <summary>
        /// Lädt die angegebene Datei in der Hoffnung um eine Area.
        /// </summary>
        public static Area LoadFromJson(string file, ref int nextId)
        {
            FileInfo info = new FileInfo(file);
            using (Stream stream = File.OpenRead(file))
            {
                using (StreamReader sr = new StreamReader(stream))
                {
                    // json Datei auslesen
                    string json = sr.ReadToEnd();

                    // Deserialisieren
                    FileArea result = JsonConvert.DeserializeObject<FileArea>(json);

                    // Neue Area öffnen und mit den Root-Daten füllen
                    FileLayer[] tileLayer = result.layers.Where(l => l.type == "tilelayer").ToArray();
                    FileLayer objectLayer = result.layers.Where(l => l.type == "objectgroup").FirstOrDefault();
                    Area area = new Area(tileLayer.Length, result.width, result.height);
                    area.Name = info.Name.Substring(0, info.Name.Length - 5);

                    // Song auslesen
                    if (result.properties != null)
                        area.Song = result.properties.Song;

                    // Hintergrundfarbe interpretieren
                    area.Background = new Color(128, 128, 128);
                    if (!string.IsNullOrEmpty(result.backgroundcolor))
                    {
                        // Hexwerte als Farbwert parsen
                        area.Background = new Color(
                            Convert.ToInt32(result.backgroundcolor.Substring(1, 2), 16),
                            Convert.ToInt32(result.backgroundcolor.Substring(3, 2), 16),
                            Convert.ToInt32(result.backgroundcolor.Substring(5, 2), 16));
                    }

                    // Tiles zusammen suchen
                    for (int i = 0; i < result.tilesets.Length; i++)
                    {
                        FileTileset tileset = result.tilesets[i];

                        int start = tileset.firstgid;
                        int perRow = tileset.imagewidth / tileset.tilewidth;
                        int width = tileset.tilewidth;

                        for (int j = 0; j < tileset.tilecount; j++)
                        {
                            int x = j % perRow;
                            int y = j / perRow;

                            // Block-Status ermitteln
                            bool block = false;
                            if (tileset.tileproperties != null)
                            {
                                FileTileProperty property;
                                if (tileset.tileproperties.TryGetValue(j, out property))
                                    block = property.Block;
                            }

                            // Tile erstellen
                            Tile tile = new Tile()
                            { 
                                Texture = tileset.image,
                                SourceRectangle = new Rectangle(x * width, y * width, width, width),
                                Blocked = block
                            };

                            // In die Auflistung aufnehmen
                            area.Tiles.Add(start + j, tile);
                        }
                    }

                    // TileLayer erstellen
                    for (int l = 0; l < tileLayer.Length; l++)
                    {
                        FileLayer layer = tileLayer[l];

                        for (int i = 0; i < layer.data.Length; i++)
                        {
                            int x = i % area.Width;
                            int y = i / area.Width;
                            area.Layers[l].Tiles[x, y] = layer.data[i];
                        }
                    }

                    // Object Layer analysieren
                    if (objectLayer != null)
                    {
                        // Portals - Übertragungspunkte zu anderen Karten
                        foreach (var portal in objectLayer.objects.Where(o => o.type == "Portal"))
                        {
                            Rectangle box = new Rectangle(
                                                portal.x / result.tilewidth,
                                                portal.y / result.tileheight,
                                                portal.width / result.tilewidth,
                                                portal.height / result.tileheight
                                            );

                            area.Portals.Add(new Portal() { DestinationArea = portal.name, Box = box });
                        }

                        // Items (Spielelemente)
                        foreach (var item in objectLayer.objects.Where(o => o.type == "Item"))
                        {
                            Vector2 pos = new Vector2(
                                (item.x + (item.width / 2f)) / result.tilewidth,
                                (item.y + (item.height / 2f)) / result.tileheight);

                            switch (item.name)
                            {
                                case "coin": area.Items.Add(new Coin(nextId++) { Position = pos }); break;
                                case "goldencoin": area.Items.Add(new GoldenCoin(nextId++) { Position = pos }); break;
                                case "decard": area.Items.Add(new Decard(nextId++) { Position = pos }); break;
                                case "heidi": area.Items.Add(new Heidi(nextId++) { Position = pos }); break;
                                case "orc": area.Items.Add(new Orc(nextId++) { Position = pos }); break;
                                case "trader": 
                                    Trader trader = new Trader(nextId++) { Position = pos };
                                    trader.Inventory.Add(new IronSword(nextId++) { });
                                    trader.Inventory.Add(new WoodSword(nextId++) { });
                                    trader.Inventory.Add(new Gloves(nextId++) { });
                                    area.Items.Add(trader);
                                    break;
                            }
                        }

                        // Player (Startpunkte)
                        foreach (var player in objectLayer.objects.Where(o => o.type == "Player"))
                        {
                            Vector2 pos = new Vector2(
                                (player.x + (player.width / 2)) / result.tilewidth,
                                (player.y + (player.height / 2)) / result.tileheight);

                            area.Startpoints.Add(pos);
                        }
                    }

                    return area;
                }
            }
        }