Skip to content

PotatoCapstoneTeam/stellon

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

STELLON

image

demo

https://www.stellon.io

개발 목표

웹 기반 게임으로 방향을 정했으며 최대 4 VS 4 까지 가능한 데스매치 슈팅 게임입니다. 웹 게임인 만큼 접근성을 쉽게 하기 위해 간단한 회원가입만 마치면 누구나 즐길 수 있는 게임을 기획했습니다.

기술 스택

Common

  • NX: monorepo 관리 툴

Client & Game

  • Node.js
  • Typescript
  • React
  • Three.js
  • Phaser: Game Engine

Server

  • Spring boot JPA
  • QueryDSL
  • H2 Hibernate (Local ver.)
  • Postman
  • AWS
    • AWS EC2
    • AWS S3
    • AWS RDS (MySQL)

Stellon 프로젝트 개요도

프로젝트 전체 조직도


  • Client ↔ Main Server 동작표

프론트, 백엔드 도식도웹소켓 기능


  • 게임 시작 시 동작표

202321310-f95f1091-7891-4a6c-8b15-3b130ce95d4d

📋 파트별 주요 기능

Client

  • 우주 배경

image

  • 인트로 페이지

signup final

  • React-Hook-Form을 이용하여 렌더링 및 코드 최적화
  • 정규식과 Hook-Form라이브러리를 이용하여 유효성 검사
  • 로비 페이지

로비

  • 게임룸

image

  • 배포

S3의 정적 웹 사이트 호스팅 기능을 사용

S3 + CloudFront + Route53 연동

2차 배포 업데이트 및 변경사항 (23.03.30)

로비페이지

  • 정렬 기능
  • 빠른 시작
  • 방 비번방 설정
  • 도움말
  • 로비방 새로고침 눌러야 방 업데이트 되는 로직으로 변경
  • 게임중인 방 구별할 수 있게 색 변경
  • 오디오

게임룸페이지

  • 방장 처리
  • 시작버튼 여러번 클릭 시 에러 수정
  • 팀 변경
  • 방에 입장할 수 없는 방 에러 처리

유저

  • 전적 정보

Main Server


파트별 백엔드 자료 백엔드 DB

  • 위 타입 중 가장 중요한 START 타입을 받으면 아래처럼 실행된다.
    1. 인원 수를 확인 후 짝수일 경우 실행, 아닐 시 인원 수를 체크해달라고 메시지를 보낸다.
    2. 게임이 시작되면 RestTemplate를 통해 게임 서버로 방 id, 유저 정보, callback 주소 등을 담아서 보낸다.
    3. 게임 서버에 데이터가 잘 도착하면 Response로 Stage id와 유저 id 및 시크릿 코드를 메인 서버로 보낸다.
    4. 메인 서버는 위 데이터를 잘 받은 뒤 Client에게 각 유저마다 해당하는 시크릿 코드를 보내준다.
    5. 게임이 끝나면 게임 서버가 메인 서버의 RESTful API를 호출하여 결과 데이터를 보내준다. 메인 서버는 이것을 DB에 저장하고 종료된다.

Game

  • Room & Stage

image

기존 구조

image

현재 구조

  • 통신
export type JoinEvent = {
  //
};

export type InputEvent = {
  horizontalAxis: number;
  verticalAxis: number;
  fire: boolean;
};

export type ClientEventMap = {
  join: JoinEvent;
  input: InputEvent;
};

emit<K extends keyof ClientEventMap>(name: K, event: ClientEventMap[K]) {
  this.channel?.emit(name, event);
}

on<K extends keyof ServerEventMap>(
  name: K,
  callback: (event: ServerEventMap[K]) => void
) {
  this.channel?.on(name, callback as any);
}

image

메인 서버와 연동 전 진행한 통신 부분 리팩토링. 라이브러리 의존성을 정리하여 후에 쉽게 변경하도록 함. Typescript를 적극 활용하여 이벤트 네임에 따라 페이로드 타입을 확인할 수 있도록 함.

  • 동기화

image

  • 직렬화 & 역직렬화
export class Player extends Entity {
  serialize(): EntityData {
    return {
      id: this.id,
      x: this.x,
      y: this.y,
      angle: this.angle,
      nickname: this.nickname,
      team: this.team,
      speed: this.speed,
      angularSpeed: this.angularSpeed,
      hp: this.hp,
    };
  }

  deserialize(data: EntityData) {
    this.x = +(data['x'] ?? this.x);
    this.y = +(data['y'] ?? this.y);
    this.angle = +(data['angle'] ?? this.angle);
    this.nickname = data['nickname'] + '';
    this.team = data['team'] === 'RED_TEAM' ? 'RED_TEAM' : 'BLUE_TEAM';
    this.speed = +(data['speed'] ?? this.speed);
    this.angularSpeed = +(data['angularSpeed'] ?? this.angularSpeed);
    this.hp = +(data['hp'] ?? this.hp);
  }
}

모든 Entity는 위 함수 두개를 구현하고 있음. Scene를 동기화 할 때 활용 함.

🍀 아쉬운점

웹 소켓 설계

image

chat과 message를 분리해서 MessageHandler를 사용한건 좋았는데 로비같은 경우는 chat 부분만 stomp 통신을 사용하다 보니 게임방과 로비 사이의 괴리감이 생겨 게임적으로 유연하지 못한 점이 많았음. 예를 들면 로비 입장 시에는 채팅을 제외한 다른 데이터를 REST 통신으로 가져와서 방목록이나 대기실 유저 목록 같은 경우 새로고침을 해줘야 최신화가 됐고, disconnect 이벤트가 발생할 때도 로비는 chat 부분만 사용하므로 chat인지 message인지 확인해서 처리해야 되는 기이한 구조를 갖게 됐음.

세 줄 요약

  • 로비에서 웹소켓이 필요한 부분을 REST 통신으로 진행해 게임방과의 괴리감 발생
  • /sub에도 prefix를 추가해 chat과 message에 대한 구독을 분리시켜 관리하거나
  • 로비도 게임방처럼 chat과 message prefix를 통한 전반적인 stomp 통신 기반으로 설계 했어야 함.

About

캡스톤 디자인 프로젝트 2팀 - Stellon (Server)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published