티스토리 뷰
Flutter 서터디. . ?!
인턴십을 참여했던 회사에서 매주 수요일마다 개발팀 스터디를 진행했었다. 그리고 개발팀 스터디 주제 중 하나가 바로 리드님이 만드신 Flutter Game Engine를 이용한 Flutter 스터디였다:) 게임엔진 코드는 오픈소스로 공개되어 있으며 아래 링크를 통해 Flutter Game Engine과 Shooting Game Study에 대해 더 자세한 정보를 확인할 수 있다.
Flutter Game Engine으로 슈팅 게임 만들기
요즘 플러터가 뜨고 있기도 하고 ... ^__^ 안드로이드와 유니티 게임 엔진을 각각 접해본 경험이 있어 설레는 마음으로 스터디를 참여했다. 하지만.. Flutter는 찍먹하기엔 체감상 진입장벽이 높았고, Flutter보다 게임을 인터페이스 계층으로 설계하는 과정이 더 흥미로웠기 때문에 인터페이스 계층 설계를 중점으로 스터디 회고를 작성하였다.
코드
기획
스터디에서 만드는 게임은 매우 간단했다.
1. 빨간색의 배가 스크린 하단에 고정되어 있다.
2. 배 양 옆에 위치한 버튼을 눌러 배를 움직일 수 있다.
3. 배를 꾹 탭하면 미사일이 나가며, 미사일이 소행성과 부딪치면 소행성이 파괴된다.
4. 소행성은 스크린 상단에서 무작위로 생성되며 아래로 점점 내려온다.
5. 배가 소행성과 충돌하면 게임이 끝난다.
PBS
PBS는 Project Breakdown Structure의 약자로 프로젝트를 더 작은 요소로 분해해 각 요소의 업무를 분업하는 구조를 의미한다. 우리가 제작할 슈팅 게임에서 각 인터페이스 계층이 어떤 업무를 맡는지 분석해보았다. 그 결과는 아래 그림과 같다.
Job Flow
그 다음, PBS에서 그대로 Job Flow를 구현하였다. (일부 빠진 기능이 있을 수 있음)
슈팅 게임에는 Joystick, Ship, Missiles, Asteroids 라는 4개의 인터페이스( + 이 4개를 관리하는 Spaceship)가 필요하며 각각의 인터페이스는 분리되어 서로 의존하지 않는다. 위의 그림과 같이 인터페이스 계층을 먼저 설계해 전체적인 구조를 파악하면 객체 지향 원칙을 준수하는 이상적인 코드를 작성할 수 있다. 그러면 실제 코드를 통해 살펴보도록 하자.
Joystick
Flutter 프로젝트 코드를 간단한 의사코드로 변형해 가져왔다.
먼저 Joystick 클래스를 구현해보겠다. Joystick은 왼쪽과 오른쪽, 총 두 개의 버튼을 관리한다. 각각의 버튼을 유저가 꾹 누르거나 뗐을 때, 해당하는 값을 onMove 리스너에 전달하였다. (양수: 왼쪽, 음수: 오른쪽, 0: 멈춤)
ship
Ship 클래스 역시 Job Flow를 토대로 구현했다. 배를 움직이는 move 메소드와 배를 꾹 눌렀을 때 미사일을 발사하기 위해 작동할 onFire 리스너를 구현한다. tick()은 게임 엔진에 내장된 메소드로 약 1초를 주기로 실행되어 화면 위의 컴포넌트들을 다시 그린다. 마지막으로 checkCollissionAndExplode() 메소드를 통해 충돌한 물체가 있으면 배가 파괴되도록 한다.
missiles
Missiles 클래스는 여러 개의 미사일 객체들을 관리하는 역할을 담당한다. 먼저 외부로부터 미사일을 발사하라는 신호가 들어오면 미사일을 발사하는 releaseMissile() 메소드를 실행하도록 한다. 매 초마다 tick() 메소드를 통해 배가 직진하는 방향으로 미사일이 나아가도록 화면을 재구성하며, 만약 소행성과 충돌한 경우에는 미사일이 폭발하도록 한다.
asteroids
Asteroids 또한 missiles와 마찬가지로 여러 개의 소행성 객체를 관리하는 클래스이다. tick() 메소드에서 주기적으로 소행성을 생성하며 위의 의사코드에는 생략되어 있지만 무작위 좌표에 소행성이 생성된다.
asteroids 클래스가 관리할 asteroid 클래스 내부에서 소행성이 다른 물체와 충돌하는 경우 폭발하도록 구현하였다.
spaceship
마지막으로 각 인터페이스 계층을 연결하는 Spaceship을 구현하였다. Job Flow에서 인터페이스 계층을 잇는 화살표 부분을 spaceship 클래스가 관리한다고 보면 된다. Joystick의 onMove 리스너를 Ship의 move() 메소드와 연결한다. 그 다음 Ship의 onFire 리스너를 Missiles의 releaseMissile() 메소드와 연결한다. 마지막으로 Asteroids의 onCheckCollision 리스너를 Ship 클래스의 checkCollisionAndExplode() 메소드와 연결하면 슈팅 게임 프로젝트가 끝이 난다.
회고
프로젝트를 하거나, 일이 주어질 때마다 바로 코드부터 작성해왔기에 Flutter보다는 인터페이스 계층 설계 방식이 흥미로웠다. 이미 작성한 코드를 인터페이스 분리 원칙에 맞게 리팩터링하는 건 정말 어렵게 느껴졌는데 처음부터 설계를 탄탄하게 해놓으니 코드 짜기가 수월했고 악취가 나는 코드도 훨씬 적었다. 단순히 여러 프레임워크, 라이브러리 스터디를 할 것이 아니라 근본적인 소프트웨어공학에 대한 지식이 필요하다는 걸 크게 느꼈다.
'DIARY' 카테고리의 다른 글
[헤드퍼스트 디자인패턴] 3. 데코레이터 패턴 (0) | 2022.07.28 |
---|---|
[헤드퍼스트 디자인패턴] 2. 옵저버 패턴 (0) | 2022.07.27 |
혼자 공부하는 머신러닝+딥러닝 2장 리뷰 (0) | 2022.04.13 |
자바로 배우는 리팩토링 입문 - 유키 히로시 리뷰 (3) [END] (0) | 2022.04.12 |
자바로 배우는 리팩토링 입문 - 유키 히로시 리뷰 (2) (0) | 2022.04.12 |
- Total
- Today
- Yesterday
- 코테
- GithubAPI
- Linux
- 백준27211
- 백준27219
- baekjoon
- cron시스템
- Baekjoon27219
- whatis
- linuxgedit
- Baekjoon27211
- virtualbox
- 쇼미더코드
- linux파일
- atq
- 리눅스
- linuxtouch
- SELECT #SELECTFROM #WHERE #ORDERBY #GROUPBY #HAVING #EXISTS #NOTEXISTS #UNION #MINUS #INTERSECTION #SQL #SQLPLUS
- linuxawk
- E_FAIL
- cat
- 사용자ID
- 버추억박스에러
- 버추억박스오류
- 백준
- awk프로그램
- 리눅스cron
- OnActivityForResult
- GitHubAPIforJava
- api문서
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |