Sigma Project Number : 1

Game Name : Sigma : Summerfield / Run

Reference Game : Cookie Run

Start Date : 2020-12-11

 

==========

 

[Using Asset]

 

 

==========

 

youtu.be/C7cKV__zgP4

 

2020-12-14

  • Make to Lose when collide the zombie
    • Attatch colliders in Player and Zombies
    • Log lose status and Do animation die
  • Test & Fix something
    • Change zombie idle animation more dynamic
    • When player die, stop the moving tile maps

==========

Testing APK : Test Version 0.1 | Risnworlds on Patreon

블로그 이미지

RIsN

,

Sigma Project Number : 1

Game Name : Sigma : Summerfield / Run

Reference Game : Cookie Run

Start Date : 2020-12-11

 

==========

 

[Using Asset]

 

 

==========

 

 

2020-12-13

  • Decide Player character and Attach animation
    • Set up Assets(DoTween, Resources, Newtonsoft)
    • Decide Player character and Attach animation
  • Decide tile and design prototype map
    • Set 5 x 1 Line in Player tile map
    • Set 5 x 10 Line in Zombie tile map
  • Make to move tile map
    • Make to move Zombie tile map
    • Object pooling 3 Zombie tile maps
  • Make to move Player
    • Make button Left and Right
    • Make to move Player when button Clicked
  • Decide Zombie characters and Attach animation
    • Decide Zombie character and Attach animation
    • Make 2 Zombies
  • Make to show up zombies randomly
    • Show up Zombies randomly
    • Object pooling Zombies

 

==========

 

블로그 이미지

RIsN

,

Sigma Project Number : 1

Game Name : Sigma : Summerfield / Run

Reference Game : Cookie Run

Start Date : 2020-12-11

 

==========

 

1 Line Concept

This game is that character is running avoid the zombies.

Core Concept

The Character is running avoid the zombie.

There is Boss zombie.

Camera will be changed randomly for difficulty control.

 

==========

 

블로그 이미지

RIsN

,

[프로젝트명] S? : Charles VII

[장르] 전략

[목적] 스터디 전용 & 취업 포트폴리오

 

[사용 에셋]

 

 

 

 

일지 #1

<0> 시작
<1> 캐릭터 [0][0][0]에 출력
<2> 캐릭터 [1][-1][0]으로 이동 with DOTween
<3> 캐릭터 [4][-7][3]으로 이동 by AStar Algorithm

<1> 캐릭터 [0][0][0]에 출력

[A. 출력시 캐릭터 <-> 맵 상호간 오브젝트 보유]

// :: Connect Character and Tile
private void ConnectCharacterAndTile(GameObject character, GameObject tile)
{
    character.GetComponent<Battle_Class_Character>().SetTileObject(tile);
    tile.GetComponent<Battle_Class_Tile>().SetCharacterObject(character);
}

<2> 캐릭터 [1][-1][0]으로 이동 with DOTween

// :: Move Position
public void MovePosition(Vector3 position, System.Action action)
{
    // :: Rotation
    this.gameObject.transform.DOLookAt(position, ROTATION_SPEED)
        .onComplete = () =>
        {
            // :: Move
            this.gameObject.transform.DOMove(position, MOVING_SPEED)
            	.onComplete = () => { action?.Invoke(); };
    	};
}

<3> 캐릭터 [4][-7][3]으로 이동 by AStar Algorithm

[AStar Algorithm이란?]

: A* search algorithm

: 간단 설명 : 거리를 추정해서 가까운 곳 위주로 탐색해서 나아가는 알고리즘

: 참고 : よくわかるA*(A-star)アルゴリズム

: 쓰는 이유?

>> 길찾기를 할 때 쓰는 알고리즘으로 기본적인 알고리즘이라는 소문

 

youtu.be/ESLPnJmlvew

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Battle_GOFunc_Astar
{
    // :: Constructor
    public Battle_GOFunc_Astar() { }

    // :: Constant
    private int[,] DIRECTION = new int[6, 3] { { -1, 0, 1 }, { 0, -1, 1 }, { 1, -1, 0 }, { 1, 0, -1 }, { 0, 1, -1 }, { -1, 1, 0 } };

    // :: Variable : for Node
    private LinkedList<int[]> paths;
    private List<Astar_Node> listNode;
    private List<Astar_Node> listOpenNode;
    private List<Astar_Node> listClosedNode;

    // :: Initialise
    public void Init(List<Battle_Class_Tile> listTile)
    {
        // :: Use
        this.paths = new LinkedList<int[]>();
        this.listNode = new List<Astar_Node>();
        this.listOpenNode = new List<Astar_Node>();
        this.listClosedNode = new List<Astar_Node>();

        // :: Make Node and put it in list
        this.AddNodeList(listTile);
    }

    // :: Make Node
    private void AddNodeList(List<Battle_Class_Tile> listTile)
    {
        // :: Convert
        foreach (var itm in listTile)
        {
            // :: Make Node
            Astar_Node node = new Astar_Node();
            node.Init(itm.X, itm.Y, itm.Z);

            // :: Add it
            this.listNode.Add(node);
        }
    }

    // :: GET Path
    public LinkedList<int[]> GetPath(Battle_Class_Tile baseTile, Battle_Class_Tile targetTile)
    {
        // :: Set Base and Target Node
        Astar_Node baseNode = this.GetNode(baseTile.X, baseTile.Y, baseTile.Z);
        Astar_Node targetNode = this.GetNode(targetTile.X, targetTile.Y, targetTile.Z);

        // :: Find Min Path
        this.GetPathImplement(baseNode, targetNode);

        // :: Return
        return this.paths;
    }
    // :: Get Path Implement
    private void GetPathImplement(Astar_Node baseNode, Astar_Node targetNode)
    {
        // :: EXIT : Found Target
        if (baseNode == targetNode)
            return;

        // :: Status Open
        foreach (var itm in this.CheckDirectionNode(baseNode))
        {
            var openNode = itm.Open(targetNode);
            if(openNode != null)
                this.listOpenNode.Add(openNode);
        }

        // :: Find Min
        var minNode = this.FindMinCost();

        // :: Check Distance : And Turn Back When it's 2+
        this.TurnBackPath(baseNode, minNode);

        // :: Add Path
        this.paths.AddLast(new int[3] { minNode.x, minNode.y, minNode.z });

        // :: Close Min and Add Closed Node
        this.listClosedNode.Add(minNode.Closed());
        this.listOpenNode.Remove(minNode);

        // :: Return Self : When reach target Node
        this.GetPathImplement(minNode, targetNode);
    }
    // :: Turn Back Path : When distance is 2+
    private void TurnBackPath(Astar_Node baseNode, Astar_Node minNode)
    {
        // :: Check Distance and Same Distance
        var distance = this.CheckDistance(baseNode, minNode);
        var lastPathSameDistance = baseNode.estimateCost == minNode.estimateCost;

        if (distance == false)
        {
            // :: Close Base Node
            this.listClosedNode.Add(baseNode.Closed());
            this.listOpenNode.Remove(baseNode);

            // :: Delete Last Path
            this.paths.RemoveLast();

            // :: Return Path
            Astar_Node newBaseNode = this.GetNode(this.paths.Last.Value[0], this.paths.Last.Value[1], this.paths.Last.Value[2]);

            // :: Return Self : When distance <= 2 or Same Distance
            distance = this.CheckDistance(newBaseNode, minNode);
            lastPathSameDistance = newBaseNode.estimateCost == minNode.estimateCost;
            if (distance == false)
            {
                this.TurnBackPath(newBaseNode, minNode);
            }
            // :: or Same Distance
            else if (lastPathSameDistance)
            {
                // :: Close Base Node
                this.listClosedNode.Add(newBaseNode.Closed());
                this.listOpenNode.Remove(newBaseNode);

                // :: Delete Last Path
                this.paths.RemoveLast();

                Debug.LogFormat("마지막이 거리와 같을 때 {0},{1},{2} / {3},{4},{5}", newBaseNode.x, newBaseNode.y, newBaseNode.z, minNode.x, minNode.y, minNode.z);
            }
        }
        // :: or Same Distance
        else if (lastPathSameDistance)
        {
            // :: Close Base Node
            this.listClosedNode.Add(baseNode.Closed());
            this.listOpenNode.Remove(baseNode);

            // :: Delete Last Path
            this.paths.RemoveLast();

            Debug.LogFormat("마지막이 거리와 같을 때 {0},{1},{2} / {3},{4},{5}", baseNode.x, baseNode.y, baseNode.z, minNode.x, minNode.y, minNode.z);
        }
    }
    // :: Find Min Distance
    private Astar_Node FindMinCost()
    {
        // :: First Set
        Astar_Node minNode = this.listOpenNode[0];

        // :: Find
        foreach(var itm in this.listOpenNode)
        {
            if (minNode.estimateCost > itm.estimateCost)
                minNode = itm;
        }

        // :: Return
        return minNode;
    }
    // :: CheckDistance
    private bool CheckDistance(Astar_Node baseNode, Astar_Node targetNode)
    {
        var distance = Mathf.Abs(baseNode.x - targetNode.x) + Mathf.Abs(baseNode.y - targetNode.y) + Mathf.Abs(baseNode.z - targetNode.z);
        return distance <= 2;
    }

    // :: Check Direction and Return which isn't null
    private List<Astar_Node> CheckDirectionNode(Astar_Node baseNode)
    {
        // :: List Direction Node
        List<Astar_Node> listDirectionNode = new List<Astar_Node>();

        for(var i = 0; i < DIRECTION.GetLength(0); i++)
        {
            // :: Check Direction with Const
            Astar_Node node = this.GetNode(baseNode.x + DIRECTION[i,0], baseNode.y + DIRECTION[i, 1], baseNode.z + DIRECTION[i, 2]);
            if(node != null 
                && this.listOpenNode.Contains(node) == false
                && this.listClosedNode.Contains(node) == false)
            {
                listDirectionNode.Add(node);
            }
        }

        // :: Return
        return listDirectionNode;
    }
    // :: Get Node
    private Astar_Node GetNode(int x, int y, int z)
    {
        return this.listNode.Find(ele => ele.x == x && ele.y == y && ele.z == z);
    }

    // :: Node Status Enum
    private enum eNodeStatus
    {
        NONE,
        OPEN,
        CLOSED
    }
    // :: Node
    private class Astar_Node
    {
        // :: Constructor
        public Astar_Node() { }

        // :: XYZ
        public int x;
        public int y;
        public int z;

        // :: Status
        public eNodeStatus status;

        // :: Cost
        public int realCost;
        public int heuristicCost;
        public int estimateCost;

        // :: Initialise
        public void Init(int x, int y, int z)
        {
            // :: XYZ
            this.x = x;
            this.y = y;
            this.z = z;

            // :: Status
            this.status = eNodeStatus.NONE;

            // :: Cost
            this.realCost = 0;
            this.heuristicCost = 0;
            this.estimateCost = this.realCost + this.heuristicCost;
        }
        // :: Chagne Status
        public Astar_Node Open(Astar_Node targetNode)
        {
            // :: Don't Open this when Closed
            if (this.status == eNodeStatus.CLOSED)
                return null;

            // :: Open
            this.status = eNodeStatus.OPEN;

            // :: Calculate Cost
            this.realCost += 1;
            this.heuristicCost = Mathf.Abs(this.x - targetNode.x) + Mathf.Abs(this.y - targetNode.y) + Mathf.Abs(this.z - targetNode.z);
            this.estimateCost = this.realCost + this.heuristicCost;

            // :: Return this
            return this;
        }
        public Astar_Node Closed()
        {
            // :: Close
            this.status = eNodeStatus.CLOSED;

            // :: Return this
            return this;
        }
    }
}

[개선점]

>> 엄청 많음, 장애물일 때의 시험 등 여러가지 필요

>> 고려중

블로그 이미지

RIsN

,

[프로젝트명] S? : Charles VII

[장르] 전략

[목적] 스터디 전용 & 취업 포트폴리오

 

[사용 에셋]

 

 

 

 

 

일지 #0

<0> 시작
<1> Hex Grid 제작 : Cube 좌표 사용
<2> Hex Grid를 코드로 제어
<3> 캐릭터 [0][0][0]에 출력

<1> Hex Grid 제작 : Cube 좌표 사용

[Hex Grid란?]

: 사각형이 아닌 육각형으로 이루어진 맵

: 쓰는 이유?

사각형보다 전략적이라는 소문

 

[Cube 좌표란?]

: 3방향으로 나눠진 좌표

: 참고 : 배달아~ 배달 가는길 알려줘!(단호함) - 우아한형제들 기술 블로그 (woowabros.github.io)

>> x가 (+1) 되면 y가 (-1) 되는 게 조금 독특함

>> 한쪽 방향으로 진행하면 하나가 플러스 하나가 마이너스 되는 구조?

 

<1> Hex Grid 제작 : Cube 좌표 사용
<1> Hex Grid 제작 : Cube 좌표 사용

<2> Hex Grid를 코드로 제어

// :: Found All Tiles
var tiles = GameObject.FindObjectsOfType<Transform>().Where(ele => ele.gameObject.name.Contains("Tile"));

foreach (var itm in tiles)
{
    // :: Change name
    string[] tileString = itm.gameObject.name.Replace('[', ' ').Replace(']', ' ').Replace("  ", " ").Split(' ');

    // :: Init x, y, z
    int x = Int32.Parse(tileString[1]);
    int y = Int32.Parse(tileString[2]);
    int z = Int32.Parse(tileString[3]);

    // :: Make new Tile Class and Initialise
    Battle_Class_Tile tile = new Battle_Class_Tile();
    tile.Init(x, y, z);

    // :: Add List
    listTile.Add(tile);
}

Debug.LogFormat(":: [Battle:Init] All Tiles Found : {0}", listTile.Count);

<3> 캐릭터 [0][0][0]에 출력

youtu.be/0N8xmJOlGXo

 

블로그 이미지

RIsN

,