Разработка игрового приложения

Обзор операционных систем. Разработка сцены игрового процесса. Настройка режима свободной игры в жанре лабиринт. Основные требования к игровому приложению. Выбор текстуры игрового персонажа. Разработка архитектуры и кода. Диаграммы классов обработки меню.

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык русский
Дата добавления 14.12.2019
Размер файла 1,9 M

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

private static readonly Single activationDistance;

public static Boolean Swiped { private set; get; }

public static Direction LastDirection { private set; get; }

static SwipeManager()

{

activationDistance = Mathf.Min(Screen.width, Screen.height) * 0.05f;

}

public static void Update(MazeSystem mazeSystem)

{

Swiped = false;

if (Input.touchCount == 1)

{

Touch touch = Input.GetTouch(0);

switch(touch.phase)

{

case TouchPhase.Began:

firstPosition = touch.position;

break;

case TouchPhase.Ended:

lastPosition = touch.position;

Vector3 delta = lastPosition - firstPosition;

if (delta.magnitude >= activationDistance)

{

Swiped = true;

Single angle = Mathf.Atan2(delta.y, delta.x) - mazeSystem.TilePrefab.transform.rotation.eulerAngles.z / 180.0f * Mathf.PI;

if (angle < -Mathf.PI)

{

angle += 2 * Mathf.PI;

}

LastDirection = null;

for (Int32 i = 0; i < mazeSystem.DirectionCount; i++)

{

Direction direction = mazeSystem.GetDirection(i);

Single relativeAngle = Mathf.Abs(angle - direction.Angle);

if (relativeAngle > Mathf.PI)

{

relativeAngle = Mathf.Abs(relativeAngle - 2 * Mathf.PI);

}

if (relativeAngle < mazeSystem.HalfDirectionSegment)

{

LastDirection = direction;

break;

}

}

}

break;

}

}

}

}

}

#endif

Move.cs

using System;

using UnityEngine;

namespace Maze.Animations.Players

{

public class Move : StateMachineBehaviour

{

public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, Int32 layerIndex)

{

Single time = animator.GetFloat("InMoveNormalizedTime");

Single delta = Time.deltaTime / stateInfo.length;

if (animator.GetBool("Direct Order"))

{

time += delta;

if (time > 1.0f)

{

time -= (Int32)time;

}

}

else

{

time -= delta;

if (time < 0.0f)

{

time -= (Int32)time;

}

}

animator.SetFloat("InMoveNormalizedTime", time);

}

}

}

Win.cs

using System;

using UnityEngine;

using UnityEngine.SceneManagement;

namespace Maze.Animations.Players

{

public class Win : StateMachineBehaviour

{

public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, Int32 layerIndex)

{

if (Properties.IsFreePlay)

{

animator.GetComponentInParent<Reals.Maze>().Restart();

}

else

{

Properties.MenuState = Properties.IsFreePlay ? Menu.MenuStates.FreePlay : Menu.MenuStates.Campaign;

SceneManager.LoadScene("Menu", LoadSceneMode.Single);

}

}

}

}

Appearance.cs

using System;

using UnityEngine;

namespace Maze.Animations.Tiles

{

public class Appearance : Disappearance

{

protected override Boolean MakeVisible => true;

protected override Single StartValue => 0.0f;

protected override Single EndValue => 1.0f;

}

}

Disappearance.cs

using System;

using UnityEngine;

namespace Maze.Animations.Tiles

{

public class Disappearance : Visible

{

protected override Boolean MakeVisible => false;

protected virtual Single EndValue => 0.0f;

public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, Int32 layerIndex)

{

SetOpacity(tile.Opacity);

}

public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, Int32 layerIndex)

{

SetOpacity(EndValue);

}

}

}

Invisible.cs

using System;

using UnityEngine;

namespace Maze.Animations.Tiles

{

public class Invisible : Visible

{

protected override Boolean MakeVisible => false;

protected override Single StartValue => 0.0f;

}

}

Visible.cs

using Maze.Helpers;

using Maze.Reals;

using System;

using System.Collections.Generic;

using UnityEngine;

namespace Maze.Animations.Tiles

{

public class Visible : StateMachineBehaviour

{

protected Tile tile;

protected List<SpriteRenderer> renderers;

protected virtual Boolean MakeVisible => true;

protected virtual Single StartValue => 1.0f;

public override void OnStateEnter(Animator animator, AnimatorStateInfo animatorStateInfo, Int32 layerIndex)

{

Initialize(animator);

SetOpacity(StartValue);

tile.Visible = MakeVisible;

}

protected void Initialize(Animator animator)

{

tile = animator.GetComponentInParent<Tile>();

renderers = TileHelper.GetRenderers(tile, MakeVisible);

}

protected void SetOpacity(Single opacity)

{

if (!tile.OpacityUpdated)

{

return;

}

foreach (SpriteRenderer renderer in renderers)

{

Color color = renderer.color;

color.a = opacity;

renderer.color = color;

}

}

}

}

Direction.cs

using System;

using UnityEngine;

namespace Maze.Commons

{

public class Direction

{

public readonly Int32 Id;

public readonly Vector3 Vector;

public readonly Single Angle;

public readonly Quaternion Quaternion;

private readonly Direction[] directions;

private Direction(Int32 id, Vector3 vector, Single angle, Quaternion quaternion, Direction[] directions)

{

Id = id;

Vector = vector;

Angle = angle;

Quaternion = quaternion;

this.directions = directions;

}

public static Direction[] CreateDirections(Int32 count)

{

Direction[] directions = new Direction[count];

for (Int32 i = 0; i < count; i++)

{

Single angle = Mathf.PI * 2 * i / count;

if (angle > Mathf.PI)

{

angle -= 2 * Mathf.PI;

}

directions[i] = new Direction(

i,

new Vector3(Mathf.Cos(angle), Mathf.Sin(angle)),

angle,

Quaternion.Euler(0.0f, 0.0f, 360.0f * i / count),

directions);

}

return directions;

}

public override Boolean Equals(System.Object obj)

{

return obj is Direction direction && Id == direction.Id;

}

public override Int32 GetHashCode()

{

return Id.GetHashCode();

}

public static Boolean operator ==(Direction left, Direction right)

{

if (left is null)

{

return right is null;

}

return left.Equals(right);

}

public static Boolean operator !=(Direction left, Direction right)

{

return !(left == right);

}

public Direction Next()

{

return directions[(Id + 1) % directions.Length];

}

public Direction Previous()

{

return directions[(Id - 1 + directions.Length) % directions.Length];

}

public Direction Opposite()

{

return directions[(Id + directions.Length / 2) % directions.Length];

}

}

}

MazeSystem.cs

using Maze.Reals;

using System;

using UnityEngine;

namespace Maze.Commons

{

public class MazeSystem : MonoBehaviour

{

// Количество направлений, в которых можно перемещаться из ячейки

public Int32 DirectionCount;

// Максимальное количество ячеек в углу ячейки

public Int32 WallEdgeTileCount { private set; get; }

public Single HalfDirectionSegment { private set; get; }

private Direction[] directions;

public Polygon Polygon { private set; get; }

public Tile TilePrefab;

public Wall WallPrefab;

public WallEdge WallEdgePrefab;

public KeyCode[] keys;

public void Initialize()

{

WallEdgeTileCount = 2 + 4 / (DirectionCount - 2);

Polygon = new Polygon(DirectionCount, 0.5f);

directions = Direction.CreateDirections(DirectionCount);

Single wallThikness = Polygon.DistanceBetweenCenters / 15.0f;

Single angle = Mathf.PI * (WallEdgeTileCount - 2) / WallEdgeTileCount;

Single distance = wallThikness / (2.0f * Mathf.Cos(angle / 2.0f));

Vector3 wallEdgeScale = WallEdgePrefab.transform.localScale;

wallEdgeScale.x = distance * 2.0f;

wallEdgeScale.y = distance * 2.0f;

WallEdgePrefab.transform.localScale = wallEdgeScale;

Vector3 wallScale = WallPrefab.transform.localScale;

wallScale.x = Polygon.DistanceBetweenCenters / 15.0f;

wallScale.y = Polygon.SideSize - 2.0f * distance * Mathf.Sin(angle / 2.0f);

WallPrefab.transform.localScale = wallScale;

HalfDirectionSegment = Mathf.PI / DirectionCount;

TilePrefab.Visible = Properties.IsHiddenMode;

}

public Direction GetDirection(Int32 index)

{

return directions[index];

}

public Direction GetInputDirection()

{

#if UNITY_ANDROID || UNITY_IOS

if (SwipeManager.Swiped)

{

return SwipeManager.LastDirection;

}

return null;

#else

for (Int32 i = 0; i < DirectionCount; i++)

{

if (Input.GetKey(keys[i]))

{

return GetDirection(i);

}

}

return null;

#endif

}

}

}

Polygon.cs

using System;

using UnityEngine;

namespace Maze.Commons

{

public class Polygon

{

// Количество сторон

public readonly Int32 SideCount;

// Величина одного угла вершины в градусах

public readonly Single AngleDeg;

// Величина одного угла вершины в радианах

public readonly Single AngleRad;

// Угол между двумя вершинами относительно центра

public readonly Single AngleBetweenTwoVertexFromCenterDeg;

// Расстояние между центрами двух полигонов

public readonly Single DistanceBetweenCenters;

// Размер стороны

public readonly Single SideSize;

// Расстояние от центра до вершины

public readonly Single DistangeFromCenterToVertex;

public Polygon(Int32 sideCount, Single distanceFromCenterToVertex)

{

SideCount = sideCount;

AngleDeg = 180.0f * (SideCount - 2) / SideCount;

AngleRad = Mathf.PI * (SideCount - 2) / SideCount;

AngleBetweenTwoVertexFromCenterDeg = 360.0f / SideCount;

DistangeFromCenterToVertex = distanceFromCenterToVertex;

DistanceBetweenCenters = 2.0f * Mathf.Sin(AngleRad / 2.0f) * DistangeFromCenterToVertex;

SideSize = 2.0f * Mathf.Cos(AngleRad / 2.0f) * DistangeFromCenterToVertex;

}

}

}

TileHelper.cs

using Maze.Commons;

using Maze.Reals;

using System;

using System.Collections.Generic;

using System.Linq;

using UnityEngine;

namespace Maze.Helpers

{

public static class TileHelper

{

public static void SetVisible(Tile tile, Boolean visible)

{

if (tile.Visible != visible)

{

tile.Animator.ResetTrigger(visible ? "Disappearance" : "Appearance");

tile.Animator.SetTrigger(visible ? "Appearance" : "Disappearance");

}

}

public static void InitVisible(Tile tile, Boolean visible)

{

tile.Animator.ResetTrigger(visible ? "Invisible" : "Visible");

tile.Animator.SetTrigger(visible ? "Visible" : "Invisible");

}

public static List<SpriteRenderer> GetRenderers(Tile tile, Boolean newVisible)

{

if (tile.Visible == newVisible)

{

return new List<SpriteRenderer>();

}

var renderers = new List<SpriteRenderer>();

renderers.AddRange(tile.GetComponentsInChildren<SpriteRenderer>());

foreach (var direction in tile.Walls.Keys)

{

if (!tile.NearTiles.ContainsKey(direction) || !tile.NearTiles[direction].Visible)

{

renderers.AddRange(tile.Walls[direction].GetComponentsInChildren<SpriteRenderer>());

}

}

foreach (var direction in tile.WallEdges.Keys)

{

if (GetAllTiles(direction, tile).Except(new [] { (direction, tile) }).All(tuple => !tuple.Item2.Visible))

{

renderers.AddRange(tile.WallEdges[direction].GetComponentsInChildren<SpriteRenderer>());

}

}

return renderers;

}

public static HashSet<(Direction, Tile)> GetAllTiles(Direction edgeDirection, Tile tile)

{

var set = new HashSet<(Direction, Tile)> { (edgeDirection, tile) };

AddRightsToSet(set, edgeDirection, tile);

AddLeftsToSet(set, edgeDirection, tile);

return set;

}

private static void AddRightsToSet(HashSet<(Direction, Tile)> set, Direction direction, Tile tile)

{

while (tile.NearTiles.ContainsKey(direction))

{

tile = tile.NearTiles[direction];

direction = direction.Opposite().Previous();

if (set.Contains((direction, tile)))

{

break;

}

set.Add((direction, tile));

}

}

private static void AddLeftsToSet(HashSet<(Direction, Tile)> set, Direction direction, Tile tile)

{

direction = direction.Next();

while (tile.NearTiles.ContainsKey(direction))

{

tile = tile.NearTiles[direction];

direction = direction.Opposite().Next();

if (set.Contains((direction.Previous(), tile)))

{

break;

}

set.Add((direction.Previous(), tile));

}

}

public static void MakeActionInDirections(Tile tile, Action<Tile> action)

{

action(tile);

foreach (Direction direction in tile.ConnectedTiles.Keys)

{

ContinueAction(tile, direction, action);

}

}

private static void ContinueAction(Tile tile, Direction direction, Action<Tile> action)

{

do

{

tile = tile.ConnectedTiles[direction];

action(tile);

}

while (tile.ConnectedTiles.ContainsKey(direction));

}

public static void ShowTile(Tile tile)

{

MakeActionInDirections(tile, t => SetVisible(t, true));

}

public static void ForceShowTile(Tile tile)

{

MakeActionInDirections(tile, t => InitVisible(t, true));

}

// TODO: write method HideTile()

}

}

CampaignInfo.cs

using System;

namespace Maze.IO

{

[Serializable]

public class CampaignInfo

{

public LevelInfo[] Campaign;

}

}

IOManager.cs

using UnityEngine;

namespace Maze.IO

{

public static class IOManager

{

public static CampaignInfo LoadLevels()

{

TextAsset textAsset = Resources.Load<TextAsset>("Campaign");

var levels = JsonUtility.FromJson<CampaignInfo>(textAsset.text);

return levels;

}

}

}

LevelInfo.cs

using System;

namespace Maze.IO

{

[Serializable]

public class LevelInfo

{

public String Type;

public Int32 Width;

public Int32 Height;

public Int32 Seed;

public Boolean HiddenMode;

}

}

LevelButton.cs

using System;

using UnityEngine;

using UnityEngine.UI;

namespace Maze.Menu

{

public class LevelButton : MonoBehaviour

{

public Text Text;

protected Int32 level;

public Int32 Level

{

get => level;

set

{

level = value;

Text.text = level.ToString();

}

}

}

}

MenuStates.cs

namespace Maze.Menu

{

public enum MenuStates

{

MainMenu,

FreePlay,

Campaign,

Default = MainMenu

}

}

SliderHandler.cs

using System;

using UnityEngine;

using UnityEngine.UI;

namespace Maze.Menu

{

public class SliderHandler : MonoBehaviour

{

public Slider slider;

public Text valueText;

public Int32 minValue;

public Int32 maxValue;

public Int32 step;

public Int32 value;

public void Start()

{

slider.minValue = minValue;

slider.maxValue = maxValue;

slider.value = value;

valueText.text = value.ToString();

}

public void OnValueChanged()

{

value = (Int32)Mathf.Round(slider.value);

value = (value - minValue) / step * step + minValue;

slider.value = value;

valueText.text = value.ToString();

}

}

}

CampaignHandler.cs

using Maze;

using Maze.Commons;

using Maze.IO;

using Maze.Menu;

using System;

using UnityEngine;

using UnityEngine.SceneManagement;

using UnityEngine.UI;

public class CampaignHandler : MenuHandler

{

public GameObject MainMenu;

public Transform LevelButtonsTransform;

public LevelButton LevelButtonPrefab;

public LevelButton[] levelButtons;

public void Start()

{

levelButtons = new LevelButton[15];

for (Int32 i = 0; i < 3; i++)

{

for (Int32 j = 0; j < 5; j++)

{

LevelButton levelButton = levelButtons[i * 5 + j] = Instantiate(LevelButtonPrefab, LevelButtonsTransform);

levelButton.Level = i * 5 + j + 1;

levelButton.transform.localPosition = new Vector3(-440 + 220 * j, 220 - 220 * i);

var clickedEvent = new Button.ButtonClickedEvent();

clickedEvent.AddListener(() => LevelOnClick(levelButton));

levelButton.GetComponent<Button>().onClick = clickedEvent;

}

}

}

public void Update()

{

if (Input.GetKeyDown(KeyCode.Escape))

{

Forward(MainMenu);

}

}

public void BackOnClick()

{

Forward(MainMenu);

}

public void LevelOnClick(LevelButton levelButton)

{

LevelInfo level = Properties.Campaign[levelButton.Level - 1];

Properties.IsHiddenMode = level.HiddenMode;

Properties.MazeWidth = level.Width;

Properties.MazeHeight = level.Height;

Properties.MazeSeed = level.Seed;

Properties.IsRectangularMazeSystem = level.Type == "R";

Properties.IsFreePlay = false;

SceneManager.LoadScene("GamePlay", LoadSceneMode.Single);

}

}

FreePlayHandler.cs

using Maze.Menu;

using UnityEngine;

using UnityEngine.SceneManagement;

using UnityEngine.UI;

namespace Maze

{

public class FreePlayHandler : MenuHandler

{

public GameObject MainMenu;

public SliderHandler widthHandler;

public SliderHandler heightHandler;

public Toggle hiddenModeToggle;

public Toggle rectangularToggle;

public void Update()

{

if (Input.GetKeyDown(KeyCode.Escape))

{

Forward(MainMenu);

}

}

public void PlayOnClick()

{

Properties.IsHiddenMode = hiddenModeToggle.isOn;

Properties.IsRectangularMazeSystem = rectangularToggle.isOn;

Properties.MazeWidth = widthHandler.value;

Properties.MazeHeight = heightHandler.value;

Properties.IsFreePlay = true;

SceneManager.LoadScene("GamePlay", LoadSceneMode.Single);

}

public void RectangularOnValueChanged(Text text)

{

text.text = rectangularToggle.isOn ? "Rectangular Maze" : "HexagonalMaze";

}

public void BackOnClick()

{

Forward(MainMenu);

}

}

}

MainMenuHandler.cs

using UnityEngine;

namespace Maze

{

public class MainMenuHandler : MenuHandler

{

public GameObject Campaign;

public GameObject FreePlay;

private void Start()

{

switch (Properties.MenuState)

{

case Menu.MenuStates.Campaign:

Forward(Campaign);

break;

case Menu.MenuStates.FreePlay:

Forward(FreePlay);

break;

}

Properties.MenuState = Menu.MenuStates.Default;

}

public void CampaignOnClick()

{

Forward(Campaign);

}

public void FreePlayOnClick()

{

Forward(FreePlay);

}

public void ExitOnClick()

{

Application.Quit();

}

}

}

MenuHandler.cs

using UnityEngine;

public abstract class MenuHandler : MonoBehaviour

{

protected void Forward(GameObject nextMenu)

{

gameObject.SetActive(false);

nextMenu.SetActive(true);

}

}

IMoveSystem.cs

using Maze.Commons;

using Maze.Reals;

using System.Collections.Generic;

namespace Maze.MoveSystems

{

public interface IMoveSystem

{

LinkedList<Tile> Move(Tile tile, Direction direction);

}

}

PathMoveSystem.cs

using Maze.Commons;

using Maze.Reals;

using System.Collections.Generic;

namespace Maze.MoveSystems

{

public class PathMoveSystem : IMoveSystem

{

public LinkedList<Tile> Move(Tile tile, Direction direction)

{

var tiles = new LinkedList<Tile>();

tiles.AddFirst(tile);

while(tile.ConnectedTiles.ContainsKey(direction))

{

tile = tile.ConnectedTiles[direction];

tiles.AddLast(tile);

if (tile.ConnectedTiles.Count != 2)

{

break;

}

foreach (Direction newDirection in tile.ConnectedTiles.Keys)

{

if (newDirection != direction.Opposite())

{

direction = newDirection;

break;

}

}

}

return tiles;

}

}

}

StepMoveSystem.cs

using Maze.Commons;

using Maze.Reals;

using System.Collections.Generic;

namespace Maze.MoveSystems

{

public class StepMoveSystem : IMoveSystem

{

public LinkedList<Tile> Move(Tile tile, Direction direction)

{

var positions = new LinkedList<Tile>();

positions.AddFirst(tile);

if (tile.ConnectedTiles.ContainsKey(direction))

{

positions.AddLast(tile.ConnectedTiles[direction]);

}

return positions;

}

}

}

Exit.cs

namespace Maze.Reals

{

public class Exit : TileContent

{

public override void Run(Maze maze)

{

maze.Player.Animator.SetTrigger("Win");

}

}

}

Maze.cs

using Maze.Commons;

using Maze.Helpers;

using Maze.MoveSystems;

using System;

using System.Collections.Generic;

using System.Linq;

using UnityEngine;

using UnityEngine.SceneManagement;

namespace Maze.Reals

{

public class Maze : MonoBehaviour

{

public Player PlayerPrefab;

public Exit ExitPrefab;

public Player Player;

public Transform TilesTransform;

public Transform WallsTransform;

public Transform WallEdgesTransform;

public List<Tile> Tiles;

public List<Wall> Walls;

public List<WallEdge> WallEdges;

public MazeSystem RectangularMazeSystemPrefab;

public MazeSystem HexagonalMazeSystemPrefab;

public MazeSystem MazeSystem;

public Int32? Seed;

public void Start()

{

Seed = Properties.MazeSeed;

MazeSystem = Instantiate(Properties.IsRectangularMazeSystem ? RectangularMazeSystemPrefab : HexagonalMazeSystemPrefab, transform);

MazeSystem.Initialize();

CreateMaze();

}

public void Update()

{

#if UNITY_ANDROID || UNITY_IOS

SwipeManager.Update(MazeSystem);

#endif

if (Input.GetKeyDown(KeyCode.Escape))

{

Properties.MenuState = Properties.IsFreePlay ? Menu.MenuStates.FreePlay : Menu.MenuStates.Campaign;

SceneManager.LoadScene("Menu", LoadSceneMode.Single);

}

}

private void CreateMaze()

{

CreateField();

ConnectTiles();

CreateWalls();

CreateWallEdges();

ApplyHiddenMode();

CreatePlayer();

SetPlayerAndExitTiles();

}

public void Restart()

{

Destroy(Player.gameObject);

Destroy(MazeSystem);

foreach (Tile tile in Tiles)

{

Destroy(tile.gameObject);

}

foreach(Wall wall in Walls)

{

Destroy(wall.gameObject);

}

foreach(WallEdge wallEdge in WallEdges)

{

Destroy(wallEdge.gameObject);

}

CreateMaze();

}

private void CreateField()

{

Tiles = new List<Tile>();

if (MazeSystem.DirectionCount == 4)

{

CreateRectangularField();

}

else if (MazeSystem.DirectionCount == 6)

{

CreateHexagonalField();

}

}

private void CreateRectangularField()

{

Int32 width = Properties.MazeWidth;

Int32 height = Properties.MazeHeight;

Tile[,] tiles = new Tile[width, height];

for (Int32 i = 0; i < width; i++)

{

for (Int32 j = 0; j < height; j++)

{

tiles[i, j] = Instantiate(MazeSystem.TilePrefab, TilesTransform);

Tiles.Add(tiles[i, j]);

}

}

for (Int32 i = 0; i < width; i++)

{

for (Int32 j = 0; j < height; j++)

{

if (i > 0 && !tiles[i, j].NearTiles.ContainsKey(MazeSystem.GetDirection(2)))

{

MakeNear(2, tiles[i, j], tiles[i - 1, j]);

}

if (j > 0 && !tiles[i, j].NearTiles.ContainsKey(MazeSystem.GetDirection(1)))

{

MakeNear(1, tiles[i, j], tiles[i, j - 1]);

}

if (i < width - 1 && !tiles[i, j].NearTiles.ContainsKey(MazeSystem.GetDirection(0)))

{

MakeNear(0, tiles[i, j], tiles[i + 1, j]);

}

if (j < height - 1 && !tiles[i, j].NearTiles.ContainsKey(MazeSystem.GetDirection(3)))

{

MakeNear(3, tiles[i, j], tiles[i, j + 1]);

}

}

}

}

private void CreateHexagonalField()

{

Int32 width = Properties.MazeWidth;

Int32 height = Properties.MazeHeight;

Tile[,] tiles = new Tile[width, height];

for (Int32 i = 0; i < width; i++)

{

for (Int32 j = 0; j < height; j++)

{

tiles[i, j] = Instantiate(MazeSystem.TilePrefab, TilesTransform);

Tiles.Add(tiles[i, j]);

}

}

for (Int32 i = 0; i < width; i++)

{

for (Int32 j = 0; j < height; j++)

{

if (i > 0 && !tiles[i, j].NearTiles.ContainsKey(MazeSystem.GetDirection(3)))

{

MakeNear(3, tiles[i, j], tiles[i - 1, j]);

}

if (i < width - 1 && !tiles[i, j].NearTiles.ContainsKey(MazeSystem.GetDirection(0)))

{

MakeNear(0, tiles[i, j], tiles[i + 1, j]);

}

if (j % 2 == 0)

{

if (j > 0)

{

if (!tiles[i, j].NearTiles.ContainsKey(MazeSystem.GetDirection(2)))

{

MakeNear(2, tiles[i, j], tiles[i, j - 1]);

}

if (i < width - 1 && !tiles[i, j].NearTiles.ContainsKey(MazeSystem.GetDirection(1)))

{

MakeNear(1, tiles[i, j], tiles[i + 1, j - 1]);

}

}

if (j < height - 1)

{

if (!tiles[i, j].NearTiles.ContainsKey(MazeSystem.GetDirection(4)))

{

MakeNear(4, tiles[i, j], tiles[i, j + 1]);

}

if (i < width - 1 && !tiles[i, j].NearTiles.ContainsKey(MazeSystem.GetDirection(5)))

{

MakeNear(5, tiles[i, j], tiles[i + 1, j + 1]);

}

}

}

else

{

if (j > 0)

{

if (!tiles[i, j].NearTiles.ContainsKey(MazeSystem.GetDirection(1)))

{

MakeNear(1, tiles[i, j], tiles[i, j - 1]);

}

if (i > 0 && !tiles[i, j].NearTiles.ContainsKey(MazeSystem.GetDirection(2)))

{

MakeNear(2, tiles[i, j], tiles[i - 1, j - 1]);

}

}

if (j < height - 1)

{

if (!tiles[i, j].NearTiles.ContainsKey(MazeSystem.GetDirection(5)))

{

MakeNear(5, tiles[i, j], tiles[i, j + 1]);

}

if (i > 0 && !tiles[i, j].NearTiles.ContainsKey(MazeSystem.GetDirection(4)))

{

MakeNear(4, tiles[i, j], tiles[i - 1, j + 1]);

}

}

}

}

}

}

private void ConnectTiles()

{

var random = Seed is null ? new System.Random() : new System.Random(Seed.Value);

var activeTiles = new List<Tile> { Tiles[random.Next(Tiles.Count)] };

var createdTiles = new HashSet<Tile> { activeTiles[0] };

while (activeTiles.Count > 0)

{

Tile activeTile = activeTiles[random.Next(10) < 8 ? activeTiles.Count - 1 : random.Next(activeTiles.Count)];

var freeDirections = new List<Direction>();

foreach (Direction direction in activeTile.NearTiles.Keys)

{

Tile nearTileObject = activeTile.NearTiles[direction];

if (!createdTiles.Contains(nearTileObject))

{

freeDirections.Add(direction);

}

}

if (freeDirections.Count == 0)

{

activeTiles.Remove(activeTile);

continue;

}

Direction selectedDirection = freeDirections[random.Next(freeDirections.Count)];

Tile selectedTileObject = activeTile.NearTiles[selectedDirection];

createdTiles.Add(selectedTileObject);

activeTiles.Add(selectedTileObject);

MakeConnected(selectedDirection, activeTile, selectedTileObject);

}

}

private void MakeNear(Int32 index, Tile tile1, Tile tile2)

{

tile1.NearTiles[MazeSystem.GetDirection(index)] = tile2;

tile2.NearTiles[MazeSystem.GetDirection(index).Opposite()] = tile1;

tile2.transform.localPosition = tile1.transform.localPosition + tile1.transform.rotation * MazeSystem.GetDirection(index).Vector * MazeSystem.Polygon.DistanceBetweenCenters;

}

private void MakeConnected(Direction direction, Tile tile1, Tile tile2)

{

tile1.ConnectedTiles[direction] = tile2;

tile2.ConnectedTiles[direction.Opposite()] = tile1;

}

private void CreateWalls()

{

Walls = new List<Wall>();

foreach (Tile tile in Tiles)

{

for (Int32 i = 0; i < MazeSystem.DirectionCount; i++)

{

Direction direction = MazeSystem.GetDirection(i);

if (!tile.NearTiles.ContainsKey(direction))

{

Wall wall = Instantiate(MazeSystem.WallPrefab, WallsTransform);

wall.transform.localPosition = tile.transform.localPosition + tile.transform.rotation * direction.Vector * MazeSystem.Polygon.DistanceBetweenCenters / 2.0f;

wall.transform.rotation = Quaternion.Euler(0.0f, 0.0f, tile.transform.rotation.eulerAngles.z + direction.Quaternion.eulerAngles.z);

tile.Walls[direction] = wall;

Walls.Add(wall);

}

else if (!tile.ConnectedTiles.ContainsKey(direction) && !tile.Walls.ContainsKey(direction))

{

Wall wall = Instantiate(MazeSystem.WallPrefab, WallsTransform);

wall.transform.localPosition = tile.transform.localPosition + tile.transform.rotation * direction.Vector * MazeSystem.Polygon.DistanceBetweenCenters / 2.0f;

wall.transform.rotation = Quaternion.Euler(0.0f, 0.0f, tile.transform.rotation.eulerAngles.z + direction.Quaternion.eulerAngles.z);

tile.Walls[direction] = wall;

tile.NearTiles[direction].Walls[direction.Opposite()] = wall;

Walls.Add(wall);

}

}

}

}

private void CreateWallEdges()

{

WallEdges = new List<WallEdge>();

foreach(Tile tile in Tiles)

{

for (Int32 i = 0; i < MazeSystem.DirectionCount; i++)

{

Direction direction = MazeSystem.GetDirection(i);

if (tile.Walls.ContainsKey(direction))

{

Wall wall = tile.Walls[direction];

if (!tile.WallEdges.ContainsKey(direction))

{

WallEdge wallEdge = Instantiate(MazeSystem.WallEdgePrefab, WallEdgesTransform);

WallEdges.Add(wallEdge);

wallEdge.transform.rotation = Quaternion.Euler(0.0f, 0.0f, tile.transform.rotation.eulerAngles.z + direction.Quaternion.eulerAngles.z);

wallEdge.transform.localPosition = wall.transform.localPosition + Quaternion.Euler(0.0f, 0.0f, tile.transform.rotation.eulerAngles.z + 90.0f) * direction.Vector * MazeSystem.Polygon.SideSize / 2.0f;

SetWallEdgeForNearWalls(direction, tile, wallEdge);

}

if (!tile.WallEdges.ContainsKey(direction.Previous()))

{

WallEdge wallEdge = Instantiate(MazeSystem.WallEdgePrefab, WallEdgesTransform);

WallEdges.Add(wallEdge);

wallEdge.transform.rotation = Quaternion.Euler(0.0f, 0.0f, tile.transform.rotation.eulerAngles.z + direction.Previous().Quaternion.eulerAngles.z);

wallEdge.transform.localPosition = wall.transform.localPosition + Quaternion.Euler(0.0f, 0.0f, tile.transform.rotation.eulerAngles.z + 270.0f) * direction.Vector * MazeSystem.Polygon.SideSize / 2.0f;

SetWallEdgeForNearWalls(direction.Previous(), tile, wallEdge);

}

}

}

}

}

private void ApplyHiddenMode()

{

foreach (Tile tile in Tiles)

{

TileHelper.InitVisible(tile, !Properties.IsHiddenMode);

}

}

private void SetWallEdgeForNearWalls(Direction edgeDirection, Tile tile, WallEdge wallEdge)

{

foreach((Direction direction, Tile setTile) in TileHelper.GetAllTiles(edgeDirection, tile))

{

setTile.WallEdges[direction] = wallEdge;

}

}

private void SetPlayerAndExitTiles()

{

var endTiles = new HashSet<Tile>(Tiles.Where(tile => tile.ConnectedTiles.Count == 1));

var forkTiles = new HashSet<Tile>(Tiles.Where(tile => tile.ConnectedTiles.Count >= 3));

Int32 maxCount = 0;

Tile playerTile = Tiles[0];

Tile exitTile = Tiles[Tiles.Count - 1];

foreach (Tile endTile in endTiles)

{

var stack = new Stack<(Tile tile, Direction source, Int32 count)>();

stack.Push((endTile, (Direction)null, 0));

while (stack.Count > 0)

{

(Tile tile, Direction source, Int32 count) = stack.Pop();

if (tile.ConnectedTiles.Count == 1 && count > maxCount)

{

maxCount = count;

playerTile = endTile;

exitTile = tile;

}

foreach (Direction direction in tile.ConnectedTiles.Keys)

{

if (direction != source)

{

Tile pushTile = tile.ConnectedTiles[direction];

stack.Push((pushTile, direction.Opposite(), pushTile.ConnectedTiles.Count >= 3 ? count + 1 : count));

}

}

}

}

exitTile.Content = Instantiate(ExitPrefab, exitTile.transform);

Player.Tile = playerTile;

}

private void CreatePlayer()

{

Player = Instantiate(PlayerPrefab, transform);

Player.Maze = this;

if (Properties.IsStepMoveSystem)

{

Player.MoveSystem = new StepMoveSystem();

}

else

{

Player.MoveSystem = new PathMoveSystem();

}

}

}

}

Player.cs

using Maze.Commons;

using Maze.Helpers;

using Maze.MoveSystems;

using System.Collections.Generic;

using UnityEngine;

namespace Maze.Reals

{

public class Player : MonoBehaviour

{

private Tile tile;

public Maze Maze;

public IMoveSystem MoveSystem;

public MoveSequence MoveSequence;

public Animator Animator;

public Tile Tile

{

get => tile;

set

{

tile = value;

transform.localPosition = tile.transform.localPosition;

tile.RunAction(Maze);

}

}

public void Start()

{

if (Properties.IsHiddenMode)

{

TileHelper.ForceShowTile(Tile);

}

}

public void Update()

{

Direction direction = Maze.MazeSystem.GetInputDirection();

if (direction != null)

{

if (MoveSequence.IsFinished())

{

LinkedList<Tile> tiles = MoveSystem.Move(Tile, direction);

if (tiles.Count != 1)

{

MoveSequence.SetTiles(tiles);

}

}

}

}

}

}

Tile.cs

using Maze.Commons;

using Maze.Helpers;

using System;

using System.Collections.Generic;

using UnityEngine;

namespace Maze.Reals

{

public class Tile : MonoBehaviour

{

public readonly Dictionary<Direction, Tile> NearTiles = new Dictionary<Direction, Tile>();

public readonly Dictionary<Direction, Tile> ConnectedTiles = new Dictionary<Direction, Tile>();

public readonly Dictionary<Direction, Wall> Walls = new Dictionary<Direction, Wall>();

public readonly Dictionary<Direction, WallEdge> WallEdges = new Dictionary<Direction, WallEdge>();

public TileContent Content;

private Single prevOpacity = -1.0f;

public Single Opacity;

public Boolean OpacityUpdated { private set; get; }

public Boolean Visible;

public Animator Animator;

public void Update()

{

if (prevOpacity != Opacity)

{

OpacityUpdated = true;

prevOpacity = Opacity;

}

else

{

OpacityUpdated = false;

}

}

public void RunAction(Maze maze)

{

Content?.Run(maze);

if (Properties.IsHiddenMode)

{

TileHelper.ShowTile(this);

}

}

}

}

TileContent.cs

using UnityEngine;

namespace Maze.Reals

{

public abstract class TileContent : MonoBehaviour

{

public Tile Tile;

public abstract void Run(Maze maze);

}

}

Wall.cs

using UnityEngine;

namespace Maze.Reals

{

public class Wall : MonoBehaviour

{

}

}

WallEdge.cs

using UnityEngine;

namespace Maze.Reals

{

public class WallEdge : MonoBehaviour

{

}

}

campaign.json

{

"Campaign":

[

{

"Type": "R",

"Width": "5",

"Height": "5",

"Seed": "327120579",

"HiddenMode": "false"

},

{

"Type": "R",

"Width": "8",

"Height": "8",

"Seed": "689058995",

"HiddenMode": "false"

},

{

"Type": "R",

"Width": "11",

"Height": "11",

"Seed": "1638027807",

"HiddenMode": "false"

},

{

"Type": "R",

"Width": "14",

"Height": "14",

"Seed": "1212451611",

"HiddenMode": "false"

},

{

"Type": "H",

"Width": "10",

"Height": "10",

"Seed": "4648563",

"HiddenMode": "false"

},

{

"Type": "H",

"Width": "14",

"Height": "14",

"Seed": "1225465750",

"HiddenMode": "false"

},

{

"Type": "H",

"Width": "18",

"Height": "18",

"Seed": "791343374",

"HiddenMode": "false"

},

{

"Type": "R",

"Width": "10",

"Height": "10",

"Seed": "145830520",

"HiddenMode": "true"

},

{

"Type": "R",

"Width": "20",

"Height": "20",

"Seed": "1651845122",

"HiddenMode": "true"

},

{

"Type": "H",

"Width": "10",

"Height": "10",

"Seed": "1947139214",

"HiddenMode": "true"

},

{

"Type": "H",

"Width": "20",

"Height": "20",

"Seed": "577089526",

"HiddenMode": "true"

},

{

"Type": "R",

"Width": "50",

"Height": "50",

"Seed": "1390792027",

"HiddenMode": "false"

},

{

"Type": "H",

"Width": "50",

"Height": "50",

"Seed": "1238724014",

"HiddenMode": "false"

},

{

"Type": "R",

"Width": "50",

"Height": "50",

"Seed": "124233181",

"HiddenMode": "true"

},

{

"Type": "H",

"Width": "50",

"Height": "50",

"Seed": "291371660",

"HiddenMode": "true"

}

]

}

Размещено на Allbest.ru

...

Подобные документы

  • Изучение существующих подходов к использованию компьютерных игр в образовательном процессе. Разработка и реализация проекта игрового обучающего приложения на мобильной платформе. Выбор платформы и средств реализации игрового обучающего приложения.

    дипломная работа [3,4 M], добавлен 12.08.2017

  • Анализ игровых жанров для мобильных устройств и целевой аудитории. Разработка концепции игрового приложения, основной механики, меню и интерфейса игры. Описание переменных скриптов. Реализация выбора цели и стрельбы. Настройка работоспособности игры.

    дипломная работа [1,4 M], добавлен 19.01.2017

  • Сбор и анализ сведений по предметной области по дисциплине "Астрономия" с целью разработки обучающего игрового приложения. Исследование алгоритмов и характеристик существующих программных систем аналогов. Разработка архитектуры программной системы.

    курсовая работа [4,1 M], добавлен 27.11.2014

  • Структура Android-приложений. Особенности игрового движка. Алгоритмизация и программирование. Список игровых состояний. Настройка, отладка и тестирование программы. Разработка руководства пользователя. Тестирование инсталляции и отображения элементов.

    дипломная работа [4,5 M], добавлен 19.01.2017

  • Преимущества операционной системы Android. Проектирование интерфейса приложений. Визуальные редакторы и средства кроссплатформенной разработки. Оптимизация игрового процесса, выбор фреймворка и библиотек. Классификация и характеристика игр по жанрам.

    дипломная работа [2,6 M], добавлен 10.07.2017

  • Написание игры "Lines" на языке Object Pascal в среде Delphi. Алгоритм работы программы. Описание метода генерации поля. Используемые константы и переменные. Форма приложения после старта игрового процесса. Основные элементы формы и обработки событий.

    курсовая работа [225,0 K], добавлен 12.04.2012

  • Разработка программного продукта, предназначенного для имитации физического взаимодействия между объектами на основе игрового симулятора. Проектирование программы "LonelySpaceRanger", код которой представлен на языке VisualС++. Разработка интерфейса.

    дипломная работа [3,2 M], добавлен 30.11.2011

  • Разработка игрового проекта на игровом движке Unity 3D в среде программирования MS Visual Studio 2017. Блок-схема алгоритма работы приема сообщений с сервера на клиенте с упрощенным описанием выполняемых команд. Реализация пользовательского интерфейса.

    курсовая работа [1,5 M], добавлен 10.07.2017

  • История создания компьютерных игр. Обзор современных игровых жанров. Выбор используемых инструментов. Руководство пользователя. Разработка игры в жанре 3D шутера от первого лица. Конструктор игр Game Maker. Создание уровня с несколькими регионами.

    курсовая работа [961,8 K], добавлен 22.06.2015

  • Обзор системного и прикладного программного обеспечения используемого в ООО "Игровые системы". Описание компьютерной сети предприятия. Разработка игрового продукта для планшетов Apple iPad. Реализация визуального интерфейса и алгоритма работы модуля.

    отчет по практике [1,4 M], добавлен 18.01.2015

  • Изучение существующих подходов к использованию компьютерных игр в образовательном процессе. Особенности использования мобильного обучения. Методика и этапы закрепления полученных ранее знаний с использованием игрового приложения на мобильной платформе.

    дипломная работа [813,0 K], добавлен 27.10.2017

  • Разработка компьютерных игр как зрелищная и наиболее сложная отрасль программирования. Рассмотрение основных особенностей конструирования классов CGame и Players, а также алгоритмов вычисления траектории полета снаряда. Анализ алгоритма PassivePlayer.

    курсовая работа [5,1 M], добавлен 22.02.2013

  • Знакомство с особенностями и этапами разработки приложения для платформы Android. Рассмотрение функций персонажа: бег, прыжок, взаимодействие с объектами. Анализ блок-схемы алгоритма генерации платформ. Способы настройки функционала рабочей области.

    дипломная работа [3,4 M], добавлен 19.01.2017

  • Анализ деятельности группы компаний "Инрэко ЛАН". Общая характеристика, основы проектирования и разработка операционной системы Android. Этапы разработки программного игрового приложения с использованием физики. Скриншоты, отображающие игровой процесс.

    отчет по практике [2,7 M], добавлен 19.07.2012

  • История судоку, правила игры и цель головоломки. Разработка диаграммы классов. Реализация программы в объектно-ориентированном стиле по принципам модульности, иерархичности, ограничения доступа. Алгоритм генерации случайного игрового поля судоку.

    курсовая работа [315,9 K], добавлен 01.02.2013

  • Разработка компьютерной игры "Эволюция" с помощью игрового движка Unit. Сравнение критериев игры-аналога и разрабатываемой игры. Разработка графического интерфейса пользователя. Настройки камеры в редакторе Unity. Структура файла сохранения игры.

    дипломная работа [3,6 M], добавлен 11.02.2017

  • Анализ целевой аудитории. Функциональные характеристики пользовательского приложения. Разработка алгоритмов и интерфейса программного продукта, функций рабочей области. Написание скриптов на языке C#. Тестирование программы методом чёрного ящика.

    дипломная работа [1,5 M], добавлен 09.11.2016

  • Многообразие мини-игр и возможности языка Visual basic 6.0 для их реализации. Понятие мини-игр и их классификация. Элементы управления мини-игры "Реверси". Разработка прикладной программы. Создание игрового интерфейса. Написание программного кода.

    курсовая работа [1,5 M], добавлен 03.06.2014

  • Рассмотрение игр, схожих по жанру и модели распространения с разрабатываемым приложением. Выбор среды разработки и сторонних библиотек. Проектирование интерфейса и подготовка графических материалов приложения. Особенности введения в игру микротрансакций.

    дипломная работа [3,1 M], добавлен 18.11.2017

  • Разработка клиент-серверного игрового приложения на примере игры в шашки для мобильных устройств на базе операционной системы Android. Обзор мобильных платформ. Экраны приложения и их взаимодействие. Графический интерфейс, руководство пользователя.

    курсовая работа [2,6 M], добавлен 15.06.2013

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.