public Vector2int GetFrontCellPos(MoveDir dir)
        {
            Vector2int cellPos = CellPos;

            switch (dir)
            {
            case MoveDir.Up:
                cellPos += Vector2int.up;
                break;

            case MoveDir.Down:
                cellPos += Vector2int.down;
                break;

            case MoveDir.Left:
                cellPos += Vector2int.left;
                break;

            case MoveDir.Right:
                cellPos += Vector2int.right;
                break;
            }

            return(cellPos);
        }
Beispiel #2
0
        public bool ApplyMove(GameObject gameObject, Vector2int dest)
        {
            ApplyLeave(gameObject);

            if (gameObject.Room == null)
            {
                return(false);
            }
            if (gameObject.Room._Map != this)
            {
                return(false);
            }

            PositionInfo posinfo = gameObject.PosInfo;

            if (CanGo(dest, true) == false)
            {
                return(false);
            }

            {
                int x = dest.x - MinX;
                int y = MaxY - dest.y;
                _objects[y, x] = gameObject;
            }

            // 실제 좌표 이동
            posinfo.PosX = dest.x;
            posinfo.PosY = dest.y;

            return(true);
        }
Beispiel #3
0
        protected virtual void UpdateSkill()
        {
            if (_coolTick == 0)
            {
                // 유효한 타겟
                if (_target == null || _target.Room != Room || _target.HP <= 0)
                {
                    _target = null;
                    State   = CreatureState.Moving;
                    BroadCastMove();
                    return;
                }

                // 스킬이 아직 사용 가능한지
                Vector2int dir         = (_target.CellPos - CellPos);
                int        dist        = dir.cellDistFromZero;
                bool       canUseSkill = (dist <= _skillRange && (dir.x == 0 || dir.y == 0));
                if (canUseSkill == false)
                {
                    State = CreatureState.Moving;
                    BroadCastMove();
                    return;
                }

                // 타게팅 방향 주시
                MoveDir lookDir = GetDirFromVec(dir);
                if (Dir != lookDir)
                {
                    Dir = lookDir;
                    BroadCastMove();
                }

                SKill skilldata = null;
                DataManager.SkillDict.TryGetValue(1, out skilldata);

                // 데미지 판정
                _target.OnDamaged(this, skilldata.damage + Stat.Attack);

                // 스킬 사용 BroadCast
                S_Skill skillPacket = new S_Skill()
                {
                    Info = new SKillInfo()
                };
                skillPacket.ObjectId     = Id;
                skillPacket.Info.Skillid = skilldata.id;
                Room.BroadCast(skillPacket);

                // 스킬 쿨타임 적용
                int coolTick = (int)(1000 * skilldata.cooldown);
                _coolTick = Environment.TickCount64 + coolTick;
            }

            if (_coolTick > Environment.TickCount64)
            {
                return;
            }

            _coolTick = 0;
        }
Beispiel #4
0
        protected virtual void UpdateMoving()
        {
            if (_nextMoveTick > Environment.TickCount64)
            {
                return;
            }

            int moveTick = (int)(1000 / Speed);

            _nextMoveTick = Environment.TickCount64 + moveTick;

            if (_target == null || _target.Room != Room)
            {
                _target = null;
                State   = CreatureState.Idle;
                BroadCastMove();

                return;
            }

            Vector2int dir  = _target.CellPos - CellPos;
            int        dist = dir.cellDistFromZero;

            if (dist == 0 || dist > _chaseCellDist)
            {
                _target = null;
                State   = CreatureState.Idle;
                BroadCastMove();

                return;
            }

            List <Vector2int> path = Room._Map.FindPath(CellPos, _target.CellPos, checkObjects: false);

            if (path.Count < 2 || path.Count > _chaseCellDist)
            {
                _target = null;
                State   = CreatureState.Idle;
                BroadCastMove();

                return;
            }

            // 스킬로 넘어갈지 체크
            if (dist <= _skillRange && (dir.x == 0 || dir.y == 0))
            {
                _coolTick = 0;
                State     = CreatureState.Skill;
                return;
            }

            // 이동
            Dir = GetDirFromVec(path[1] - CellPos);
            Room._Map.ApplyMove(this, path[1]);

            BroadCastMove();
        }
Beispiel #5
0
        public override void Update()
        {
            if (Data == null || Owner == null || Room == null)
            {
                return;
            }

            if (Data.projectile == null)
            {
                return;
            }

            if (_nextMoveTick >= Environment.TickCount64)
            {
                return;
            }

            long tick = (long)(1000 / Data.projectile.speed);

            _nextMoveTick = Environment.TickCount64 + tick;

            Vector2int destPos = GetFrontCellPos();

            if (Room._Map.CanGo(destPos))
            {
                CellPos = destPos;

                S_Move movePacket = new S_Move();
                movePacket.ObjectId = Id;
                movePacket.PosInfo  = PosInfo;
                Room.BroadCast(movePacket);

                Console.WriteLine("Move Arrow");
            }
            else
            {
                GameObject target = Room._Map.Find(destPos);
                if (target != null)
                {
                    // 피격 판정
                    target.OnDamaged(this, Data.damage + Owner.Stat.Attack);
                    //Console.WriteLine($"damage : {Data.damage}");
                }

                // 소멸
                Room.Push(Room.LeaveGame, Id);
            }
        }
Beispiel #6
0
        public GameObject Find(Vector2int cellPos)
        {
            if (cellPos.x < MinX || cellPos.x > MaxX)
            {
                return(null);
            }

            if (cellPos.y < MinY || cellPos.y > MaxY)
            {
                return(null);
            }

            int x = cellPos.x - MinX;
            int y = MaxY - cellPos.y;

            return(_objects[y, x]);
        }
Beispiel #7
0
        public bool CanGo(Vector2int cellPos, bool bCheckObjects = true)
        {
            if (cellPos.x < MinX || cellPos.x > MaxX)
            {
                return(false);
            }

            if (cellPos.y < MinY || cellPos.y > MaxY)
            {
                return(false);
            }

            int x = cellPos.x - MinX;
            int y = MaxY - cellPos.y;

            return(!_collision[y, x] && (!bCheckObjects || _objects[y, x] == null));
        }
 public static MoveDir GetDirFromVec(Vector2int dir)
 {
     if (dir.x > 0)
     {
         return(MoveDir.Right);
     }
     else if (dir.x < 0)
     {
         return(MoveDir.Left);
     }
     else if (dir.y > 0)
     {
         return(MoveDir.Up);
     }
     else
     {
         return(MoveDir.Down);
     }
 }
Beispiel #9
0
        protected virtual void UpdateIdle()
        {
            if (_nextSearchTick > Environment.TickCount64)
            {
                return;
            }

            _nextSearchTick = Environment.TickCount64 + 1000;

            Player target = Room.FindPlayer(p =>
            {
                Vector2int dir = p.CellPos - CellPos;
                return(dir.cellDistFromZero <= _searchCellDist);
            });

            if (target == null)
            {
                return;
            }

            _target = target;
            State   = CreatureState.Moving;
        }
Beispiel #10
0
        public void HandleSkill(Player player, C_Skill skillPacket)
        {
            if (player == null)
            {
                return;
            }

            // 일단 서버에서 좌표 이동
            ObjectInfo info = player.Info;

            if (info.PosInfo.State != CreatureState.Idle)
            {
                return;
            }

            // 스킬 사용 가능 여부 체크

            info.PosInfo.State = CreatureState.Skill;

            S_Skill skill = new S_Skill()
            {
                Info = new SKillInfo()
            };

            skill.ObjectId     = info.ObjectId;
            skill.Info.Skillid = skillPacket.Info.Skillid;

            BroadCast(skill);

            Data.SKill SkillData = null;
            if (DataManager.SkillDict.TryGetValue(skillPacket.Info.Skillid, out SkillData) == false)
            {
                return;
            }

            switch (SkillData.skillType)
            {
            case SkillType.SkillAuto:
            {
                // 데미지 판정
                Vector2int skillPos = player.GetFrontCellPos(info.PosInfo.Movedir);
                GameObject target   = _Map.Find(skillPos);
                if (target != null)
                {
                    Console.WriteLine("Hit GameObject!");
                }
            }
            break;

            case SkillType.SkillProjectile:
            {
                // 화살 스킬
                Arrow arrow = ObjectManager.Instance.Add <Arrow>();
                if (arrow == null)
                {
                    return;
                }

                arrow.Owner           = player;
                arrow.Data            = SkillData;
                arrow.PosInfo.State   = CreatureState.Moving;
                arrow.PosInfo.Movedir = player.PosInfo.Movedir;
                arrow.PosInfo.PosX    = player.PosInfo.PosX;
                arrow.PosInfo.PosY    = player.PosInfo.PosY;
                arrow.Speed           = SkillData.projectile.speed;

                Push(EnterGame, arrow);
            }
            break;
            }
        }
Beispiel #11
0
 Pos Cell2Pos(Vector2int cell)
 {
     // CellPos -> ArrayPos
     return(new Pos(MaxY - cell.y, cell.x - MinX));
 }
Beispiel #12
0
        public List <Vector2int> FindPath(Vector2int startCellPos, Vector2int destCellPos, bool checkObjects = true)
        {
            List <Pos> path = new List <Pos>();

            // 점수 매기기
            // F = G + H
            // F = 최종 점수 (작을 수록 좋음, 경로에 따라 달라짐)
            // G = 시작점에서 해당 좌표까지 이동하는데 드는 비용 (작을 수록 좋음, 경로에 따라 달라짐)
            // H = 목적지에서 얼마나 가까운지 (작을 수록 좋음, 고정)

            // (y, x) 이미 방문했는지 여부 (방문 = closed 상태)
            bool[,] closed = new bool[SizeY, SizeX];             // CloseList

            // (y, x) 가는 길을 한 번이라도 발견했는지
            // 발견X => MaxValue
            // 발견O => F = G + H
            int[,] open = new int[SizeY, SizeX];             // OpenList
            for (int y = 0; y < SizeY; y++)
            {
                for (int x = 0; x < SizeX; x++)
                {
                    open[y, x] = Int32.MaxValue;
                }
            }

            Pos[,] parent = new Pos[SizeY, SizeX];

            // 오픈리스트에 있는 정보들 중에서, 가장 좋은 후보를 빠르게 뽑아오기 위한 도구
            PriorityQueue <PQNode> pq = new PriorityQueue <PQNode>();

            // CellPos -> ArrayPos
            Pos pos  = Cell2Pos(startCellPos);
            Pos dest = Cell2Pos(destCellPos);

            // 시작점 발견 (예약 진행)
            open[pos.Y, pos.X] = 10 * (Math.Abs(dest.Y - pos.Y) + Math.Abs(dest.X - pos.X));
            pq.Push(new PQNode()
            {
                F = 10 * (Math.Abs(dest.Y - pos.Y) + Math.Abs(dest.X - pos.X)), G = 0, Y = pos.Y, X = pos.X
            });
            parent[pos.Y, pos.X] = new Pos(pos.Y, pos.X);

            while (pq.Count > 0)
            {
                // 제일 좋은 후보를 찾는다
                PQNode node = pq.Pop();
                // 동일한 좌표를 여러 경로로 찾아서, 더 빠른 경로로 인해서 이미 방문(closed)된 경우 스킵
                if (closed[node.Y, node.X])
                {
                    continue;
                }

                // 방문한다
                closed[node.Y, node.X] = true;
                // 목적지 도착했으면 바로 종료
                if (node.Y == dest.Y && node.X == dest.X)
                {
                    break;
                }

                // 상하좌우 등 이동할 수 있는 좌표인지 확인해서 예약(open)한다
                for (int i = 0; i < _deltaY.Length; i++)
                {
                    Pos next = new Pos(node.Y + _deltaY[i], node.X + _deltaX[i]);

                    // 유효 범위를 벗어났으면 스킵
                    // 벽으로 막혀서 갈 수 없으면 스킵
                    if (next.Y != dest.Y || next.X != dest.X)
                    {
                        if (CanGo(Pos2Cell(next), checkObjects) == false)                         // CellPos
                        {
                            continue;
                        }
                    }

                    // 이미 방문한 곳이면 스킵
                    if (closed[next.Y, next.X])
                    {
                        continue;
                    }

                    // 비용 계산
                    int g = 0;                    // node.G + _cost[i];
                    int h = 10 * ((dest.Y - next.Y) * (dest.Y - next.Y) + (dest.X - next.X) * (dest.X - next.X));
                    // 다른 경로에서 더 빠른 길 이미 찾았으면 스킵
                    if (open[next.Y, next.X] < g + h)
                    {
                        continue;
                    }

                    // 예약 진행
                    open[dest.Y, dest.X] = g + h;
                    pq.Push(new PQNode()
                    {
                        F = g + h, G = g, Y = next.Y, X = next.X
                    });
                    parent[next.Y, next.X] = new Pos(node.Y, node.X);
                }
            }

            return(CalcCellPathFromParent(parent, dest));
        }