Монеты сведениями на время игрCoin Time game details

Здесь вы найдете сведения о реализации в игре времени разработки, включая работе с картами плитки, создание сущностей, анимация спрайтов и реализации эффективного конфликтов.This guide discusses implementation details in the Coin Time game, including working with tile maps, creating entities, animating sprites, and implementing efficient collision.

Время монеты — полный платформер, игры для iOS и Android.Coin Time is a full platformer game for iOS and Android. Цель игры — собрать все монеты уровня и, обратитесь к двери выхода избегая монстров и препятствия.The goal of the game is to collect all of the coins in a level and then reach the exit door while avoiding enemies and obstacles.

Здесь вы найдете сведения о реализации монеты времени, будут рассмотрены следующие темы:This guide discusses implementation details in Coin Time, covering the following topics:

Содержимого вовремя монетыContent in Coin Time

Время монеты — пример проекта, который представляет, как может быть организовано полного проекта CocosSharp.Coin Time is a sample project that represents how a full CocosSharp project might be organized. Coin Time's структуры призван упростить добавление и обслуживания содержимого.Coin Time’s structure aims to simplify the addition and maintenance of content. Она использует .tmx файлы, созданные копиями для уровней и XML-файлы для определения анимаций.It uses .tmx files created by Tiled for levels and XML files to define animations. Изменения или добавления нового содержимого может осуществляться с минимальными усилиями.Modifying or adding new content can be achieved with minimal effort.

Хотя такой подход делает время монеты проекте, действующие для обучения и службы "Экспериментирование", они также отражают как профессиональных игр выполняются.While this approach makes Coin Time an effective project for learning and experimentation, it also reflects how professional games are made. В этом руководстве описываются некоторые подходы, необходимое для упрощения добавления и изменения содержимого.This guide explains some of the approaches taken to simplify adding and modifying content.

Работа с файлами tmxWorking with tmx files

Временные уровни монеты определяются с помощью форматом файла .tmx выходной копиями плитки карты редактора.Coin Time levels are defined using the .tmx file format, which is output by the Tiled tile map editor. Подробное описание работы с копиями, см. в разделе использование Tiled с Cocos четкие руководства.For a detailed discussion of working with Tiled, see the Using Tiled with Cocos Sharp guide.

Каждый уровень определяется в отдельном файле .tmx, содержащихся в CoinTime/ресурсы/Content/уровни папки.Each level is defined in its own .tmx file contained in the CoinTime/Assets/Content/levels folder. Все уровни монеты время совместно использовать один файл tileset, который определен в mastersheet.tsx файла.All Coin Time levels share one tileset file, which is defined in the mastersheet.tsx file. Этот файл определяет пользовательские свойства для каждого мозаичного элемента, например сплошная конфликтов плитки, имеет ли или ли плитку следует заменить экземпляр сущности.This file defines the custom properties for each tile, such as whether the tile has solid collision or whether the tile should be replaced by an entity instance. Файл mastersheet.tsx позволяет свойства определен только один раз и использовать их на всех уровнях.The mastersheet.tsx file allows properties to be defined only once and used across all levels.

Редактирование плитки картыEditing a tile map

Чтобы изменить карту плитку, откройте файл .tmx в копиями, дважды щелкнув файл .tmx или открыв его через меню "файл" в копиями.To edit a tile map, open the .tmx file in Tiled by double-clicking the .tmx file or opening it through the File menu in Tiled. Coin Time уровня плитки карты содержат три уровня:Coin Time level tile maps contain three layers:

  • Сущности – этот уровень содержит плитки, которые будут заменены экземпляров сущностей во время выполнения.Entities – this layer contains tiles which will be replaced with instances of entities at runtime. Примеры включают проигрыватель, монет, противников и окончания из уровня на двери.Examples include the player, coins, enemies, and the end-of-level door.
  • Ландшафта – этот уровень содержит плитки, которые обычно имеют сплошной конфликтов.Terrain – this layer contains tiles which typically have solid collision. Сплошной конфликтов игрок может пройти на этих плитках без дальше.Solid collision allows the player to walk on these tiles without falling through. Плитки с сплошной конфликтов также может служить стен и перекрытия.Tiles with solid collision can also act as walls and ceilings.
  • Фон — фон содержит плитки, которые используются в качестве статического фона.Background – the Background layer contains tiles that are used as the static background. Этот уровень не прокручивается при перемещении камеры на протяжении всего уровне, создается внешний вид глубины через фокусировки.This layer does not scroll when the camera moves throughout the level, creating the appearance of depth through parallax.

Мы рассмотрим позже, уровень загрузки кода ожидает, что эти три слоя на всех уровнях монеты времени.As we will explore later, the level-loading code expects these three layers in all Coin Time levels.

Редактирование ландшафтаEditing terrain

Плитки можно поместить, щелкнув в mastersheet tileset, а затем щелкните плитку, схемы.Tiles can be placed by clicking in the mastersheet tileset and then clicking on the tile map. Например, для закрашивания новые поверхности в пределах уровня:For example, to paint new terrain in a level:

  1. Выберите слой ландшафтаSelect the Terrain layer

  2. Щелкните плитку для рисованияClick on the tile to draw

  3. Нажмите кнопку или Push-уведомлений и перетащите на карту, чтобы рисовать плиткиClick or push and drag over the map to paint the tile

Левого верхнего угла tileset содержит все ландшафта монеты времени.The top-left of the tileset contains all of the terrain in Coin Time. Включает в себя ландшафта, который является сплошная заливка, SolidCollision свойства, как показано в свойства плитки в левой части экрана:Terrain, which is solid, includes the SolidCollision property, as shown in the tile properties on the left of the screen:

Редактирование сущностейEditing entities

Сущности можно добавлять или удалять из уровня — так же, как ландшафта.Entities can be added or removed from a level – just like terrain. Mastersheet tileset имеет все сущности, поместить о посередине по горизонтали, поэтому они могут не отображаться без прокрутки вправо:The mastersheet tileset has all entities placed about halfway horizontally, so they may not be visible without scrolling to the right:

Новые сущности должны размещаться на сущностей слоя.New entities should be placed on the Entities layer.

Ищет код CoinTime EntityType при загрузке уровнем для идентификации плитки, которые должны быть заменены сущностей:CoinTime code looks for the EntityType when a level is loaded to identify tiles which should be replaced by entities:

После изменения и сохранения файла, изменения будут автоматически отображаться построения и запуска проекта:Once the file has been modified and saved, the changes will automatically show up if the project is built and run:

Добавление новых уровнейAdding new levels

Процесс добавления уровней монеты время требуется без изменения кода, а только небольшие изменения в проект.The process of adding levels to Coin Time requires no code changes, and only a few small changes to the project. Чтобы добавить новый уровень:To add a new level:

  1. Откройте папку уровня, расположенный <CoinTime корневой > \CoinTime\Assets\Content\levelsOpen the level folder located at <CoinTime Root>\CoinTime\Assets\Content\levels

  2. Скопируйте и вставьте один из уровней, такие как level0.tmxCopy and paste one of the levels, such as level0.tmx

  3. Присвойте новому файлу .tmx, поэтому она продолжает уровня последовательности чисел с существующие уровни, такие как level8.tmxRename the new .tmx file so it continues the level number sequence with existing levels, such as level8.tmx

  4. В Visual Studio или Visual Studio для Mac добавьте новый файл .tmx в папку уровнях Android.In Visual Studio or Visual Studio for Mac, add the new .tmx file to the Android levels folder. Убедитесь, что файл использует AndroidAsset действие при сборке.Verify that the file uses the AndroidAsset build action.

  5. Добавьте новый файл .tmx в папку iOS уровней.Add the new .tmx file to the iOS levels folder. Убедитесь, что связывание файла из исходного расположения и убедитесь, что он использует BundleResource действие при сборке.Be sure to link the file from its original location and verify that it uses the BundleResource build action.

Новый уровень должны отображаться на экране выберите уровня как уровень 9 (имена файлов на уровне начинаются с 0, но кнопки уровня начинается с номера 1):The new level should appear in the level select screen as level 9 (level file names start at 0, but the level buttons begin with the number 1):

Уровень загрузкиLevel loading

Как было показано ранее, новые уровни не требуют изменений в коде – игра автоматически обнаруживает уровни, если они будут правильно назван и добавлены уровни папки с действием правильную сборку (BundleResourceили AndroidAsset).As shown earlier, new levels require no changes in code – the game automatically detects the levels if they are named correctly and added to the levels folder with the correct build action (BundleResource or AndroidAsset).

Логика для определения количества уровней, содержится в LevelManager класса.The logic for determining the number of levels is contained in the LevelManager class. При создании экземпляра класса LevelManager создается (с помощью одноэлементного шаблона), DetermineAvailbleLevels вызывается метод:When an instance of the LevelManager is constructed (using the singleton pattern), the DetermineAvailbleLevels method is called:

private void DetermineAvailableLevels()
{
    // This game relies on levels being named "levelx.tmx" where x is an integer beginning with
    // 1. We have to rely on MonoGame's TitleContainer which doesn't give us a GetFiles method - we simply
    // have to check if a file exists, and if we get an exception on the call then we know the file doesn't
    // exist. 
    NumberOfLevels = 0;
    while (true)
    {
        bool fileExists = false;
        try
        {
            using(var stream = TitleContainer.OpenStream("Content/levels/level" + NumberOfLevels + ".tmx"))
            {
            }
            // if we got here then the file exists!
            fileExists = true;
        }
        catch
        {
            // do nothing, fileExists will remain false
        }
        if (!fileExists)
        {
            break;
        }
        else
        {
            NumberOfLevels++;
        }
    }
}

CocosSharp не предоставляет кроссплатформенный подход для обнаружения, если файлы отсутствуют, поэтому нам приходится полагаться на TitleContainer классы к попытке открыть поток.CocosSharp does not provide a cross-platform approach for detecting if files are present, so we have to rely on the TitleContainer class to attempt to open a stream. Если код для открытия потока порождает исключение, то файл существует и разрывов цикл while.If the code for opening a stream throws an exception, then the file does not exist and the while loop breaks. После завершения цикла NumberOfLevels свойство сообщает, сколько допустимые уровни: часть проекта.Once the loop finishes, the NumberOfLevels property reports how many valid levels are part of the project.

LevelSelectScene Класс использует LevelManager.NumberOfLevels чтобы определить, сколько кнопок для создания в CreateLevelButtons метод:The LevelSelectScene class uses the LevelManager.NumberOfLevels to determine how many buttons to create in the CreateLevelButtons method:

private void CreateLevelButtons()
{
    const int buttonsPerPage = 6;
    int levelIndex0Based = buttonsPerPage * pageNumber;
    int maxLevelExclusive = System.Math.Min (levelIndex0Based + 6, LevelManager.Self.NumberOfLevels);
    int buttonIndex = 0;
    float centerX = this.ContentSize.Center.X;
    const float topRowOffsetFromCenter = 16;
    float topRowY = this.ContentSize.Center.Y + topRowOffsetFromCenter;
    for (int i = levelIndex0Based; i < maxLevelExclusive; i++)
    {
        ...
    }
}

NumberOflevels Свойство используется для определения того, кнопки, которые должен будет создан.The NumberOflevels property is used to determine which buttons should be created. Этот код считает, что страницу пользователь просматривает в настоящее время и создает только до шести кнопок на одной странице.This code considers which page the user is currently viewing and only creates a maximum of six buttons per page. При нажатии кнопки экземпляров вызов HandleButtonClicked метод:When clicked, the button instances call the HandleButtonClicked method:

private void HandleButtonClicked(object sender, EventArgs args)
{
    // levelNumber is 1-based, so subtract 1:
    var levelIndex = (sender as Button).LevelNumber - 1;
    LevelManager.Self.CurrentLevel = levelIndex;
    CoinTime.GameAppDelegate.GoToGameScene ();
}

Этот метод назначает CurrentLevel свойство, которое используется GameScene при загрузке уровнем.This method assigns the CurrentLevel property which is used by the GameScene when loading a level. После задания CurrentLevel, GoToGameScene вызывается метод, переключение сцены LevelSelectScene для GameScene.After setting the CurrentLevel, the GoToGameScene method is raised, switching the scene from LevelSelectScene to GameScene.

GameScene Конструктор вызывает GoToLevel, который выполняет логику уровень загрузки:The GameScene constructor calls GoToLevel, which performs the level-loading logic:

private void GoToLevel(int levelNumber)
{
    LoadLevel (levelNumber);
    CreateCollision();
    ProcessTileProperties ();
    touchScreen = new TouchScreenInput(gameplayLayer);
    secondsLeft = secondsPerLevel;
}

Далее мы рассмотрим краткий обзор методов, вызываемых в GoToLevel.Next we’ll take a look at methods called in GoToLevel.

LoadLevelLoadLevel

LoadLevel Метод отвечает за загрузку файла .tmx и добавления его в GameScene.The LoadLevel method is responsible for loading the .tmx file and adding it to the GameScene. Этот метод не создает любые интерактивные объекты, такие как конфликт или сущности — он просто создает визуальные элементы для уровня, называемый также среды.This method does not create any interactive objects such as collision or entities – it simply creates the visuals for the level, also referred to as the environment.

private void LoadLevel(int levelNumber)
{
    currentLevel = new CCTileMap ("level" + levelNumber + ".tmx");
    currentLevel.Antialiased = false;
    backgroundLayer = currentLevel.LayerNamed ("Background");
    // CCTileMap is a CCLayer, so we'll just add it under all entities
    this.AddChild (currentLevel);
    // put the game layer after
    this.RemoveChild(gameplayLayer);
    this.AddChild(gameplayLayer);
    this.RemoveChild (hudLayer);
    this.AddChild (hudLayer);
}

CCTileMap Конструктор принимает имя файла, который создается с помощью номер уровня, передаваемые в LoadLevel.The CCTileMap constructor takes a file name, which is created using the level number passed in to LoadLevel. Дополнительные сведения о создании и работе с CCTileMap экземпляров, см. в разделе использование Tiled с CocosSharp руководство.For more information on creating and working with CCTileMap instances, see the Using Tiled with CocosSharp guide.

В настоящее время CocosSharp не допускает изменение порядка слоев без удаления и повторного добавления их к родительскому CCScene (который является GameScene в данном случае), поэтому для изменения порядка слоев требуются последние несколько строк метода.Currently, CocosSharp does not allow reordering of layers without removing and re-adding them to their parent CCScene (which is the GameScene in this case), so the last few lines of the method are required to reorder the layers.

CreateCollisionCreateCollision

CreateCollision Конструкции метод LevelCollision экземпляр, который используется для выполнения сплошной конфликтов между проигрывателя и средой.The CreateCollision method constructs a LevelCollision instance which is used to perform solid collision between the player and environment.

private void CreateCollision()
{
    levelCollision = new LevelCollision();
    levelCollision.PopulateFrom(currentLevel);
}

Без такой коллизии проигрыватель будет передаваться уровень и игра будет воспроизводиться.Without this collision, the player would fall through the level and the game would be unplayable. Сплошной конфликтов позволяет стека на землю проигрывателя и запрещает проигрывателю прохода сквозь стены или переходить вверх через перекрытия.Solid collision lets the player walk on the ground and prevents the player from walking through walls or jumping up through ceilings.

Конфликт монеты времени могут добавляться без дополнительных кода — только изменения в файлы мозаики.Collision in Coin Time can be added with no additional code – only modifications to tiled files.

ProcessTilePropertiesProcessTileProperties

После того как уровень загружается и создания конфликт ProcessTileProperties вызывается для выполнения операции на основании свойства мозаики.Once a level is loaded and the collision is created, ProcessTileProperties is called to perform logic based on tile properties. Включает в себя время монеты PropertyLocation структуры для определения свойств и координаты плитки со следующими свойствами:Coin Time includes a PropertyLocation struct for defining properties and the coordinates of the tile with these properties:

public struct PropertyLocation
{
    public CCTileMapLayer Layer;
    public CCTileMapCoordinates TileCoordinates;
    public float WorldX;
    public float WorldY;
    public Dictionary<string, string> Properties;
}

Эта структура используется для создания создания экземпляров сущности и удалить ненужные плитки в ProcessTileProperties метод:This struct is used to construct create entity instances and remove unnecessary tiles in the ProcessTileProperties method:

private void ProcessTileProperties()
{
    TileMapPropertyFinder finder = new TileMapPropertyFinder (currentLevel);
    foreach (var propertyLocation in finder.GetPropertyLocations())
    {
        var properties = propertyLocation.Properties;
        if (properties.ContainsKey ("EntityType"))
        {
            float worldX = propertyLocation.WorldX;
            float worldY = propertyLocation.WorldY;
            if (properties.ContainsKey ("YOffset"))
            {
                string yOffsetAsString = properties ["YOffset"];
                float yOffset = 0;
                float.TryParse (yOffsetAsString, out yOffset);
                worldY += yOffset;
            }
            bool created = TryCreateEntity (properties ["EntityType"], worldX, worldY);
            if (created)
            {
                propertyLocation.Layer.RemoveTile (propertyLocation.TileCoordinates);
            }
        }
        else if (properties.ContainsKey ("RemoveMe"))
        {
            propertyLocation.Layer.RemoveTile (propertyLocation.TileCoordinates);
        }
    }
}

Цикл по каждому элементу оценивает каждого свойства плитки, проверки, если ключ EntityType или RemoveMe.The foreach loop evaluates each tile property, checking if the key is either EntityType or RemoveMe. EntityType Указывает, что должен создаваться экземпляр сущности.EntityType indicates that an entity instance should be created. RemoveMe Указывает, что элемент следует полностью удалить во время выполнения.RemoveMe indicates that the tile should be completely removed at runtime.

Если свойство с EntityType ключ найден, затем TryCreateEntity вызывается которых пытается создать сущность с помощью соответствующего свойства EntityType ключ:If a property with the EntityType key is found, then TryCreateEntity is called, which attempts to create an entity using the property matching the EntityType key:

private bool TryCreateEntity(string entityType, float worldX, float worldY)
{
    CCNode entityAsNode = null;
    switch (entityType)
    {
    case "Player":
        player = new Player ();
        entityAsNode = player;
        break;
    case "Coin":
        Coin coin = new Coin ();
        entityAsNode = coin;
        coins.Add (coin);
        break;
    case "Door":
        door = new Door ();
        entityAsNode = door;
        break;
    case "Spikes":
        var spikes = new Spikes ();
        this.damageDealers.Add (spikes);
        entityAsNode = spikes;
        break;
    case "Enemy":
        var enemy = new Enemy ();
        this.damageDealers.Add (enemy);
        this.enemies.Add (enemy);
        entityAsNode = enemy;
        break;
    }
    if(entityAsNode != null)
    {
        entityAsNode.PositionX = worldX;
        entityAsNode.PositionY = worldY;
        gameplayLayer.AddChild (entityAsNode);
    }
    return entityAsNode != null;
}

Добавление новых сущностейAdding new entities

Время монеты использует шаблон сущности для своих игр объектов (который рассматривается в руководство по сущности в CocosSharp).Coin Time uses the entity pattern for its game objects (which is covered in the Entities in CocosSharp guide). Все сущности являются производными от CCNode, что означает, что они добавляются как дочерние элементы gameplayLayer.All entities inherit from CCNode, which means they can be added as children of the gameplayLayer.

Каждый тип сущности также указывается напрямую через список или одного экземпляра.Each entity type is also referenced directly through a list or single instance. Например Player ссылается player поля и все Coin экземпляры указываются в coins списка.For example, the Player is referenced by the player field, and all Coin instances are referenced in a coins list. Сохранение прямые ссылки на сущности (в отличие от создания ссылок на них через gameLayer.Children списка) позволяет выполнять код, который обращается к эти сущности более удобными для чтения и позволяет избежать потенциально затратной тип приведения.Keeping direct references to entities (as opposed to referencing them through the gameLayer.Children list) makes code which accesses these entities easier to read and eliminates potentially expensive type casting.

Существующий код предоставляет несколько типов сущностей в качестве примеров того, как создавать новые сущности.The existing code provides a number of entity types as examples of how to create new entities. Чтобы создать новую сущность можно использовать следующие действия:The following steps can be used to create a new entity:

1 — Определение нового класса, используя шаблон сущности1 - Define a new class using the entity pattern

Единственным требованием для создания сущности является создание класса, который наследуется от CCNode.The only requirement for creating an entity is to create a class which inherits from CCNode. Большинство сущностей имеют некоторые визуальный элемент, такой как CCSprite, который необходимо добавить в качестве дочернего объекта в его конструктор.Most entities have some visual, such as a CCSprite, which should be added as a child of the entity in its constructor.

Предоставляет CoinTime AnimatedSpriteEntity класс, который упрощает создание анимированных сущностей.CoinTime provides the AnimatedSpriteEntity class which simplifies the creation of animated entities. Анимация будет рассматриваться более подробно в раздела анимировано сущностей.Animations will be covered in more detail in the Animated Entities section.

2 — добавьте новую запись в блоке switch TryCreateEntity2 – Add a new entry to the TryCreateEntity switch statement

Надо создавать экземпляры новой сущности в TryCreateEntity.Instances of the new entity should be instantiated in the TryCreateEntity. Если сущность требует логики каждый кадр как конфликт, искусственного Интеллекта или чтения входных данных, а затем GameScene необходимо хранить ссылку на объект.If the entity requires every-frame logic like collision, AI, or reading input, then the GameScene needs to keep a reference to the object. Если требуется несколько экземпляров (такие как Coin или Enemy экземпляров), затем новый List должны добавляться к GameScene класса.If multiple instances are needed (such as Coin or Enemy instances), then a new List should be added to the GameScene class.

3 — изменение свойства мозаики новой сущности3 – Modify tile properties for the new entity

После кода поддерживает создание новой сущности, новая сущность должен быть добавлен к tileset.Once the code supports the creation of the new entity, the new entity needs to be added to the tileset. Tileset можно изменить, открыв любого уровня .tmx файл.The tileset can be edited by opening any level .tmx file.

Tileset хранится отдельно от .tmx в mastersheet.tsx файла, поэтому он должен быть импортирован, прежде чем его можно изменить:The tileset is stored separate from the .tmx in the mastersheet.tsx file, so it must be imported before it can be edited:

После импорта свойства выбранных плиток можно редактировать, а тип EntityType могут быть добавлены:Once imported, properties on selected tiles are editable, and the EntityType can be added:

После создания свойства его значение можно задать в соответствии с новой case в TryCreateEntity:After the property is created, its value can be set to match the new case in TryCreateEntity:

После изменения tileset, его необходимо экспортировать – это сделает изменения доступными для всех уровней:After the tileset has been changed, it must be exported – this makes the changes available for all other levels:

Перезаписать существующую tileset mastersheet.tsx tileset:The tileset should overwrite the existing mastersheet.tsx tileset:

Удаление плитки сущностиEntity tile removal

При загрузке мозаики карты в игру, отдельные плитки — это статические объекты.When a tile map is loaded into a game, the individual tiles are static objects. Поскольку сущности требуется пользовательское поведение, такие как перемещение, кода во время монеты удаляет плитки при создании сущности.Since entities require custom behavior such as movement, Coin Time code removes tiles when entities are created.

ProcessTileProperties содержит логику для удаления плитки, которые создают сущностей с помощью RemoveTile метод:ProcessTileProperties includes logic to remove tiles which create entities using the RemoveTile method:

private void ProcessTileProperties()
{
    TileMapPropertyFinder finder = new TileMapPropertyFinder (currentLevel);
    foreach (var propertyLocation in finder.GetPropertyLocations())
    {
        var properties = propertyLocation.Properties;
        if (properties.ContainsKey ("EntityType"))
        {
            ...
            bool created = TryCreateEntity (properties ["EntityType"], worldX, worldY);
            if (created)
            {
                propertyLocation.Layer.RemoveTile (propertyLocation.TileCoordinates);
            }
        }
        ...
    }
}

Это автоматическое удаление плиток достаточно для сущностей, которые занимают только одна Плитка в tileset, такие как монеты и противников.This automatic removal of tiles is sufficient for entities which occupy only one tile in the tileset, such as coins and enemies. Больших сущностей требуется дополнительная логика и свойства.Larger entities require additional logic and properties.

Дверца требуются две плитки для отображения полностью:The Door requires two tiles to be drawn completely:

На плитке нижней в дверь содержит свойства для создания сущности (EntityType присвоено дверь):The bottom tile in the door contains the properties for creating an entity (EntityType set to Door):

Так как только на нижней плитку в дверь удаляется при создании экземпляра двери, дополнительной логики необходим для удаления в первом элементе, во время выполнения.Since only the bottom tile in the door is removed when the Door instance is created, additional logic is needed to remove the top tile at runtime. Top Плитка содержит RemoveMe свойство значение true:The top tile has a RemoveMe property set to true:

Это свойство используется для удаления плитки в ProcessTileProperties:This property is used to remove tiles in ProcessTileProperties:

private void ProcessTileProperties()
{
    TileMapPropertyFinder finder = new TileMapPropertyFinder (currentLevel);
    foreach (var propertyLocation in finder.GetPropertyLocations())
    {
        var properties = propertyLocation.Properties;
        ...
        else if (properties.ContainsKey ("RemoveMe"))
        {
            propertyLocation.Layer.RemoveTile (propertyLocation.TileCoordinates);
        }
    }
}

Смещения сущностиEntity offsets

Сущности, созданные из плиток располагаются путем выравнивания center сущности с помощью центра плитки.Entities created from tiles are positioned by aligning the center of the entity with the center of the tile. Большего размера сущности, такие как Door, использовать дополнительные свойства и логика должна быть помещена правильно.Larger entities, like Door, use additional properties and logic to be placed correctly.

Плитке двери, нижней, определяющий Door указывает размещение сущности смещение значение 4.The bottom door tile, which defines the Door entity placement, specifies a YOffset value of 4. Без этого свойства Door экземпляр помещается в центре плитки:Without this property, the Door instance is placed at the center of the tile:

Это исправляется путем применения смещение значение в ProcessTileProperties:This is corrected by applying the YOffset value in ProcessTileProperties:

private void ProcessTileProperties()
{
    TileMapPropertyFinder finder = new TileMapPropertyFinder (currentLevel);
    foreach (var propertyLocation in finder.GetPropertyLocations())
    {
        var properties = propertyLocation.Properties;
        if (properties.ContainsKey ("EntityType"))
        {
            float worldX = propertyLocation.WorldX;
            float worldY = propertyLocation.WorldY;
            if (properties.ContainsKey ("YOffset"))
            {
                string yOffsetAsString = properties ["YOffset"];
                float yOffset = 0;
                float.TryParse (yOffsetAsString, out yOffset);
                worldY += yOffset;
            }
            bool created = TryCreateEntity (properties ["EntityType"], worldX, worldY);
            ...
        }
...
    }
}

Анимированный сущностейAnimated entities

Время монеты включает несколько анимированных сущностей.Coin Time includes several animated entities. Player И Enemy сущностей воспроизводить анимацию стека и Door сущности играет анимации после собраны все монеты.The Player and Enemy entities play walk animations and the Door entity plays an opening animation once all coins have been collected.

файлы .achx.achx files

В файлах .achx определяются монеты время анимации.Coin Time animations are defined in .achx files. Каждой анимации определяется между AnimationChain тегов, как показано в следующем анимации, определенные в propanimations.achx:Each animation is defined between AnimationChain tags, as shown in the following animation defined in propanimations.achx:

<AnimationChain>
  <Name>Spikes</Name>
  <ColorKey>0</ColorKey>
  <Frame>
    <FlipHorizontal>false</FlipHorizontal>
    <FlipVertical>false</FlipVertical>
    <TextureName>..\images\mastersheet.png</TextureName>
    <FrameLength>0.1</FrameLength>
    <LeftCoordinate>1152</LeftCoordinate>
    <RightCoordinate>1168</RightCoordinate>
    <TopCoordinate>128</TopCoordinate>
    <BottomCoordinate>144</BottomCoordinate>
    <RelativeX>0</RelativeX>
    <RelativeY>0</RelativeY>
  </Frame>
</AnimationChain> 

Эта анимация содержит только один кадр, приводит к сущности пик, отображение статическое изображение.This animation only contains a single frame, resulting in the Spike entity displaying a static image. Сущности можно использовать файлы .achx ли они отображают одним или несколькими кадрами анимации.Entities can use .achx files whether they display single or multi-frame animations. Дополнительные кадры могут добавляться к файлам .achx без каких-либо изменений в коде.Additional frames can be added to .achx files without requiring any changes in code.

Кадры определить какие изображения для отображения в TextureName параметра и координаты, отображаемое в LeftCoordinate, RightCoordinate, TopCoordinate, и BottomCoordinate теги.Frames define which image to display in the TextureName parameter, and the coordinates of the display in the LeftCoordinate, RightCoordinate, TopCoordinate, and BottomCoordinate tags. Они представляют собой координаты точки кадра анимации, в которой используется — mastersheet.png в данном случае.These represent the pixel coordinates of the frame of animation in the image which is being used – mastersheet.png in this case.

FrameLength Свойство определяет количество секунд, которые должны отображаться кадр анимации.The FrameLength property defines the number of seconds that a frame in an animation should be displayed. Это значение будет игнорироваться однокадровой анимации.Single-frame animations ignore this value.

Все остальные свойства AnimationChain в файле .achx игнорируются монеты времени.All other AnimationChain properties in the .achx file are ignored by Coin Time.

AnimatedSpriteEntityAnimatedSpriteEntity

Анимация логика содержится в AnimatedSpriteEntity класс, который служит в качестве базового класса для большинства объектов, используемой в GameScene.Animation logic is contained in the AnimatedSpriteEntity class, which serves as the base class for most entities used in the GameScene. Эта служба предоставляет следующие возможности:It provides the following functionality:

  • Загрузка .achx файловLoading of .achx files
  • Анимация кэша загруженных анимацийAnimation cache of loaded animations
  • Экземпляр CCSprite для отображения анимацииCCSprite instance for displaying the animation
  • Логика для изменения текущего кадраLogic for changing the current frame

Конструктор пики приведен простой пример того, как загрузить и использовать анимации:The Spikes constructor provides a simple example of how to load and use animations:

public Spikes ()
{
    LoadAnimations ("Content/animations/propanimations.achx");
    CurrentAnimation = animations [0];
}

PropAnimations.achx содержит только одна анимация, поэтому конструктор обращается к данной анимации по индексу.The propAnimations.achx only contains one animation, so the constructor accesses this animation by index. Если файл .achx содержит несколько анимаций, а затем анимации можно ссылаться по имени, как показано в Enemy конструктор:If a .achx file contains multiple animations, then animations can be referenced by name, as shown in the Enemy constructor:

walkLeftAnimation = animations.Find (item => item.Name == "WalkLeft");
walkRightAnimation = animations.Find (item => item.Name == "WalkRight");

СводкаSummary

Данное руководство содержит сведения о времени монеты реализации.This guide covers the implementation details of coin time. Время монеты создается как полный игру, но также является проектом, который можно легко изменить и развернуть.Coin Time is created to be a complete game, but is also a project which can be easily modified and expanded. Читатели, рекомендуется потратить время внесением изменений уровней, добавление новых уровней и создание новых сущностей, чтобы лучше разобраться, как реализуется монеты времени.Readers are encouraged to spend time making modifications to levels, adding new levels, and creating new entities to further understand how Coin Time is implemented.