dh_0e

[Project] 타워 디펜스 온라인 (팀 프로젝트) 본문

내일배움캠프/Project

[Project] 타워 디펜스 온라인 (팀 프로젝트)

dh_0e 2024. 7. 19. 21:17

이번 팀 프로젝트는 저번에 팀 프로젝트로 만든 타워 디펜스 게임 클라이언트를 조금 변형시켜 멀티 플레잉 게임으로 만드는 것이다. 마찬가지로 웹소켓으로 서버를 열고, 다양한 기능을 추가하였다.

 

서버 기능 명세 (필수 구현)

더보기

🛠 클라이언트 기능 명세 (필수 구현)

  1. WebSocket 기반의 코드 완성하기
    1. 제가 지금 여러분들에게 제공드리는 클라이언트 코드는 전부 WebSocket 기반으로만 서버와 통신을 할 수 있는 코드입니다.
    2. 하지만, 대부분의 코드가 비어있거나 TODO로 처리된 부분이 많기 때문에 이 부분을 완성해주셔야 합니다!
  2. 클라이언트에 하드코딩 된 게임 서버 주소 변경
    1. 클라이언트 코드 곳곳에 http://15.165.15.118:3000 가 하드코딩이 되어있는데요. 이 하드코딩 된 테스트 서버 주소를 여러분들의 게임 서버 주소로 전부 변경해주셔야 합니다!

 🛠 서버 기능 명세 (필수 구현)

🔥 이번 서버 기능 구현의 핵심은 대부분의 로직 및 데이터를 서버에서 주관해서 다룬다는 것입니다!

  1. 회원가입 (요청 패킷 + 응답 패킷)
  2. 로그인 (요청 패킷 + 응답 패킷)
    1. 로그인 성공 시 Access Token을 발급받도록 해주세요.
  3. 대결 신청 (요청 패킷)
    1. “connect" 이벤트 쪽 코드를 참고해주세요.
    2. 다른 유저와 대결하기 버튼을 누를 경우에 대결 신청을 하기 위해 서버로 보내는 패킷입니다.
    3. 서버는 해당 패킷을 수신하면 해당 유저를 대기열에 넣습니다.
    4. 대기열에 대결을 할 유저가 이미 있다면 바로 대기열에서 해당 유저들을 인출하고 대결을 합니다!
  4. 대결 시작 (통지 패킷)
    1. “matchFound” 이벤트 쪽 코드를 참고해주세요.
    2. 큐가 잡힌 경우에 대결의 시작을 알리는 통지 패킷입니다.
    3. 클라이언트에서는 해당 패킷을 받으면 게임에 필요한 데이터들을 초기화를 하고 게임을 시작합니다.
  5. 상태 동기화 (통지 패킷)
    1. 서버에서 유저의 상태에 변화가 생길때마다 알려주는 패킷입니다.
    2. 어떤 경우에 서버에서 유저의 상태를 변화시킬 수 있고 변화가 되었을 때 어떤 데이터들을 동기화를 해야되는지에 대해서는 여러분들이 판단을 하고 결정해보시기 바랍니다!
    3. 잘 모르겠다면 저번 팀 프로젝트 때 어떻게 상태 동기화를 하였는지 코드를 참고하시면서 해보시길 바랍니다!
  6. 타워 구입 (요청 패킷)
    1. placeNewTower 함수를 참고해주세요.
    2. 게임 중에 타워 구입 버튼으로 타워를 구입하는 경우에 서버로 보내는 패킷입니다.
    3. 타워 추가와는 다르게 타워 구입은 일단 편의상 클라이언트 주도로 생성된 타워의 x, y 좌표만 서버에 보내주도록 합시다.
  7. 적 타워 추가 배치 (통지 패킷)
    1. 서버로부터 적 타워의 x, y 좌표를 전달받습니다.
    2. 해당 좌표를 기반으로 타워를 새로 생성한 후에 적 타워 목록에 추가합니다.
  8. 몬스터 생성 (요청 패킷)
    1. spawnMonster 함수를 참고해주세요.
    2. 유저의 맵에서 몬스터 생성 시 monsterNumber를 서버로 보내는 패킷입니다.
  9. 적 몬스터 생성 (통지 패킷)
    1. 서버로부터 적이 monsterNumber에 해당하는 몬스터를 스폰했다는 사실을 전달받습니다.
    2. 이 사실을 통지받으면 적 몬스터를 그대로 화면에 생성해주어야겠죠?
  10. 타워가 몬스터를 공격 (요청 패킷)
    1. gameLoop 함수에서 tower.attack(monster); 코드를 참고해주세요. 이게 공격 함수입니다.
    2. 공격한 타워의 인덱스와 공격당한 몬스터의 인덱스를 서버에 넘겨주도록 합시다.
  11. 적 타워가 적의 몬스터를 공격 (통지 패킷)
    1. 서버로부터 적 타워의 인덱스 및 적 몬스터 인덱스를 전달 받습니다.
    2. 실제로 적 타워가 해당 적 몬스터를 공격할 수 있도록 합니다.
  12. 몬스터가 기지를 공격 (요청 패킷)
    1. gameLoop 함수에서 monsters로 for 문을 도는 코드쪽을 잘 보세요.
    2. 기지를 공격하면 몬스터의 공격 데미지를 서버에게 알려주도록 합시다.
  13. 기지 HP 업데이트 (통지 패킷)
    1. 몬스터가 기지를 공격하여 기지의 HP가 깎이면 깎이고 남은 HP를 전달합니다.
    2. 해당 통지 패킷은 공격받은 유저 / 반대편 유저에게 모두 통지를 하도록 합시다.
    3. 어떤 유저에게 통지하느냐에 따라서 HP를 세팅하는 기지가 달라야 합니다.
      1. base 변수와 opponentBase 변수가 있죠.
  14. 게임 오버 (통지 패킷)
    1. “gameOver” 이벤트를 참고해주세요.
    2. 몬스터가 기지를 공격하여 기지의 HP가 깎였는데 0보다 작거나 같으면 게임 오버입니다.
    3. 해당 통지 패킷은 공격받은 유저 / 반대편 유저에게 isWin 여부를 모두 통지를 하도록 합시다.
      1. 누군가가 이겼으면 누군가는 졌다고 통지를 해야겠죠?
  15. 게임 종료 (요청 패킷)
    1. “gameOver” 이벤트를 참고해주세요.
    2. 클라이언트가 결과를 확인하고 게임 종료를 하겠다는 패킷을 서버에 전달합니다.
    3. 서버는 해당 패킷을 받으면 최고 스코어 갱신 및 유저 상태 삭제와 같은 후처리 작업을 진행합니다.
  16. 몬스터가 사망 (요청 패킷)
    1. gameLoop 함수에서 monsters로 for 문을 도는 코드쪽을 잘 보세요.
    2. 기지를 공격하기 전에 몬스터의 HP가 0보다 작거나 같을 때 사망 이벤트를 서버에게 알려주도록 합시다.
  17. 적 몬스터가 사망 (통지 패킷)
    1. 서버로부터 적 몬스터 인덱스를 전달 받습니다.
    2. 전달받은 몬스터 인덱스를 바탕으로 실제로 적의 몬스터 목록에서 해당되는 적의 몬스터를 삭제해줍시다.
  18. 데이터 관리
  19.  
// 게임 데이터
let towerCost = 0; // 타워 구입 비용
let monsterSpawnInterval = 0; // 몬스터 생성 주기

// 유저 데이터
let userGold = 0; // 유저 골드
let base; // 기지 객체
let baseHp = 0; // 기지 체력
let monsterLevel = 0; // 몬스터 레벨
let monsterPath; // 몬스터 경로
let initialTowerCoords; // 초기 타워 좌표
let basePosition; // 기지 좌표
const monsters = []; // 유저 몬스터 목록
const towers = []; // 유저 타워 목록
let score = 0; // 게임 점수
let highScore = 0; // 기존 최고 점수

// 상대 데이터
let opponentBase; // 상대방 기지 객체
let opponentMonsterPath; // 상대방 몬스터 경로
let opponentInitialTowerCoords; // 상대방 초기 타워 좌표
let opponentBasePosition; // 상대방 기지 좌표
const opponentMonsters = []; // 상대방 몬스터 목록
const opponentTowers = []; // 상대방 타워 목록

 

더 재밌는 게임을 만들기 위한 도전! (도전 과제)

더보기
  • Protocol Buffers 적용하기
    • WebSocket 기반으로 멀티 플레이가 전부 잘 되면 이제 Protocol Buffers를 활용하여 데이터를 주고 받는 것을 해보도록 하시죠!
  • 채팅 기능 만들기
    온라인 게임의 꽃은 채팅이죠. 이번 도전 과제는 난이도가 크게 높지는 않습니다만 채팅을 구현해주시면 좋겠습니다! 게임 실제로 테스트하면서 서로 채팅하면서 놀면 재밌으니까요!

 

게임 시연 영상

 

 

프로젝트 Github URL: https://github.com/injune200/Tower_Defence_Online

 

GitHub - injune200/Tower_Defence_Online

Contribute to injune200/Tower_Defence_Online development by creating an account on GitHub.

github.com

 

  • Readme 파일에 게임 설명, AWS 배포 링크, 기능, 패킷 구조,Handler 구조, ERD DIAGRAM, 폴더 구조 등이 나와있다.

 

Trouble Shooting

문제: 골드 부족, 타워 개수 제한 등 경고 메세지를 Alert를 통해서 보낼 경우 게임이 정지됨. 때문에 상대방의 화면과 불일치 하는 경우가 발생

해결: 경고 메시지를 채팅창으로 출력하도록 만들어 게임 정지되는 경우의 수를 제거

 

문제: 마녀와 타워 공격에 관한 데이터를 전달하고, 상대 클라이언트에서 해당 몬스터와 타워를 찾는 과정에서 못 찾는 경우가 생기는 오류 문제가 발생

해결: 해당 몬스터와, 타워의 Index값을 넘겨서 찾는 과정을 줄임

 

 

소감

확실히 싱글 플레이 게임보다 멀티 플레이 게임이 하는 것도, 만드는 것도 재밌다는 것을 느꼈고, 작업하는 내내 다양한 기능들이 떠올랐지만, 시간과 사람이 많지 않아 모두 구현하지 못한 것이 아쉬웠고 즐거운 프로젝트였다.