본문 바로가기
  • Always Awake
프로젝트

[게임개발] 게임 회사 타이쿤(GameDevTycoon)

by NerdyBoy 2022. 1. 26.

DevGameTycoon

게임회사타이쿤을 주제로 한 2인 팀 프로젝트입니다.

 

프로젝트 진행 기간:

2020년 11월 2일 ~ 2020년 12월 11일

 

프로젝트 인원:

 

김성현, 정신우

 

Using Language/IDE

 

게임개발타이쿤

1.  서 론 

아래 그림 ‘City Game STUDIO’ 와 같은 게임개발회사 경영 시뮬레이션 게임에 영감을 받아,  ‘게임개발타이쿤’ 프로젝트를 진행하게 되었다. ‘게임개발타이쿤’은 일정 시간 동안 자본금을 사용해서 게임을 개발하는데 게임은 여러 가지 요소의 조합과 개발할 직원 선택, 개발 도중 이벤트 대응 등의 유저의 선택으로 재미있는 게임을 만들어낼 수 있다. 만들어진 게임을 판매하여 높은 수익을 올린다.

City Game Studio

 

2.  작품 개요 

아래 그림은 완성된 결과물에 대한 실행 모습이다. 개발자들이 회사에서 자체적으로 움직이는 모습을 볼 수 있고, 화면 왼쪽 상단에 진행바가 표시되어 개발 중인 게임을 볼 수 있다. 또 여러 가지 아이템으로 회사를 사용자가 직접 꾸밀 수 있다.

실제 실행 화면

3. 기능 및 요구사항 분석

아래는 본 게임의 Use-Case Diagram이다.

Use-case Diagram

l  게임 인트로, 기본적 게임 진행 모습

게임 프로그램을 구동하여 보이는 가장 첫 화면이다. 화면을 클릭하여 실제 게임 화면으로 이동할 수 있다. 오른쪽 그림은 게임을 시작하면 나타나는 화면이다. 기본적으로 텅 빈 1층 건물이 주어지고 이 건물을 배경으로 게임을 진행한다.

화면 상단에는 게임의 현재시간, 회사의 이름, 현재 회사의 자본금이 표시되는 상태바가 존 재한며, 우측 하단의메뉴버튼으로 메뉴 버튼 리스트를 토글 할 수 있다.

게임 시작 인트로 게임진행모습

l  아이템 구매

 건물에 배치할 수 있는 아이템을 구매할 수 있는아이템 구매버튼을 눌렀을 때 팝업 되는 창의 모습이다. 아이템의 종류로는 화면에 배치하여 개발자의 피로도 감소를 지연시키거나 개발자의 개발 효율을 높이는 아이템이 존재하고 아이템을 더 배치할 수 있는 공간을 늘려주는증축”, 개 발자가 자리할책상아이템이 존재한다. 판매 아이템들의 목록은 2주마다 한 번씩 랜덤으로 초기 화 되며, 한번 구매하면 판매 아이템 목록에서 사라진다. , 책상과 증축은 초기화되지 않고 언 제든 살 수 있다.

게임의 목표인 게임 개발을 하기 위해서 개발자가 필요하며, 개발자는 책상 아이템을 배치하고 자 리를 등록해야 개발에 참여할 수 있다. 이에 따라 모든 플레이어는 게임을 시작하면 아이템 구 매로책상을 구매하여 배치해야 한다.

아이템 구매 탭 아이템 구매 - 대체흐름 아이템 구매 후

l  회사 정보, 아이템 배치

아이템을 구매하면 구매한 아이템은 “회사 정보” 탭에서 확인할 수 있다. 회사 정보 탭에서 해당

하는 이미지 레이블을 클릭하고 게임 메인화면으로 돌아와 원하는 위치를 클릭하면 아이템을 해당 위치에 배치할 수 있다. 배치한 이후에는 회사 정보의 배치 가능한 아이템 목록에서 해당 아이템은 제 거 된다. 아이템이 배치되는 위치는 한층에 10(Width = 64p, 엘리베이터 제외)으로 제한된다.

회사 정보 탭(배치가능아이템, 직원) 아이템 선택 후 화면 클릭으로 배치

l  회사 정보, 아이템 배치

아래 그림 중 가장 왼편의 그림은 메뉴에서직원 고용을 눌렀을 때의 화면이다. UI에는 직원의 이름, 능력치, 체력이 표시되어있다. 사용자는 고용하고 싶은 직원 이름 라벨을 클릭하여 직원을 고용할 수 있다. 직원을 고용할 때 별도의 계약금은 없으며, 달마다 직원의 능력치에 비례하는 월급이 지출된다. 고용할 수 있는 직원의 목록은 아이템과 마찬가지로 2주마다 목록이 초기화된다.

아래 그림 중 가운데 그림과 오른쪽 그림은 게임 메인화면에서 배치된 빈 책상을 클릭하면 열 리는 화면으로, 현재 보유 중인 직원들의 이름이 보이며, 직원이름 레이블을 클릭하고 확인을 누 르면 해당 직원이 책상에 배치된다.

직원 고용 책상에 직원 배치 직원 배치 완료

l  회사 정보, 아이템 배치

아래 그림 중 왼쪽의 그림은 메뉴에서게임 개발버튼을 선택하였을 때 나타나는 탭으로, 해당 탭에서 게임 개발을 시작할 수 있다. 필수적으로 게임의 타이틀, 장르, 주제, 최소한 1명의 개발 가능한 직원을 선택하여야 개발이 시작된다.

게임의 주제와 장르를 선택함으로써 게임의 총 개발비용이 책정되는데, 초반에는 저렴한 조합의

주제와 장르를 선택해야 한다. 또 주제와 장르의 선택으로 게임의 흥미도가 결정되므로 주제와 장 르의 적절한 조합이 이 게임의 핵심이라 할 수 있다. 개발자 선택 콤보 박스에서 개발자를 클릭하여 팀에 추가할 수 있는데, 최소 1, 최대 3명을 한 팀으로 꾸려 게임 개발에 참여시킬 수 있다. 개발자는 개발에 참여하면 일정량씩 지속하여 체 력(또는 피로도)가 감소하는데 이 수치가 0이 되면 개발을 더 이상 진행하지 않고 집으로 퇴근한 다. 이 시간(퇴근과 출근하는 시간) 동안 해당 개발자분만큼은 게임 개발이 진행되지 않는다. 개발 중인 직원이 없다면 해당 개발은 일시적으로 정지된다.

아래 그림의 가운데와 오른쪽 그림은 게임 개발 중 발생하는 이벤트 탭이다. 게임 개발에 시작하면 전체 개발률이 20% 배수일 때마다 이벤트 탭이 발생할 수 있다. 이벤트에 적절히 대처하 면 개발률이 증가하고, 대처하지 못하면 개발률이 감소한다.

게임 개발탭 개별 이벤트 발생 이벤트 처리

l 파산, 게임 엔딩

아래 그림은 게임의 실패와 성공에 대한 예를 보인다. 왼쪽의 그림은 게임의 실패 예시로 회사

의 자본금이 마이너스로 60일 동안 지속하게 되면 파산하였다는 다이얼로그가 팝업 되며 게임이 종료된다. 이때 별도의 엔딩은 존재하지 않는다.

오른쪽의 그림은 게임을 성공적으로 수행하면 나오는 엔딩 크레디트이다. 게임의 성공 조건은 회사 가 게임의 총 판매량 과 인기도로 산출되는 일정 점수에 도달하면 만족한다.

파산 게임 클리어

4. 설 계

l  Class Diagram 아래는 본 게임의 Class Diagram이다. GameBoard Company의 사이를 기준으로 하여 좌

측은 GUI와 관련된 클래스들이며 우측은 게임의 내부 데이터 구조를 구성하는 클래스들이다. C lass Diagram에는 클래스들의 Getter또는 Setter 기능의 메소드들은 포함되어 있지 않다.

Class Diagram

l  알고리즘 설계

아래는 이 프로그램의 기본적인 흐름을 FlowChart로 나타낸 것이다. main에서 GameBoard

를 생성하고 GameBoard는 인트로가 담긴 StartGame객체를 생성한다. 이때 마우스 클릭이 발 생하면, 게임을 초기화하고 게임 메인화면으로 접어들며, 게임의 로직을 위한 스레드가 start메 소드로 시작하게 된다.

run에서의 반복문으로 일정 시간 주기로 무한 반복하며 게임시간을 진행시킨다. 또 개발 중인

게임의 개발을 진행시키는 메소드, 개발이 완료된 게임을 판매하는 메소드가 반복적으로 동작한다. 게임의 실패 조건이나 엔딩 조건을 만족하면 해당 쓰레드가 종료되며 흐름이 종료된다.

전반적인게임의흐름

l  기존 설계 구성요소

기존 목표 유저는 여러 가지 설정을 선택해 게임을 제작한다. 완성된 게임을 판매하여 수익을 얻고, 일정

수익에 달성하면 게임을 최종적으로 마무리 짓는다. 이 과정을 위해 다음을 구현해야 한다.

  • 게임 진행 시간 개념 턴(turn)을 도입하여 구현한다. 다채로운 게임을 위해 시간에 따라 게임에 변경되는 점이 있어야 한다.
  • 개발한 게임의 판매 가격은 유저의 선택에 따라 달라지게 구현해야 한다. ‘재미있는 게임’일 수 록 수익이 높아져 게임 개발 시 유저가 다양한 선택지를 고르는 재미를 느끼게 한다. 따라서 ‘재미있는 게임’이라는 것을 결정짓는 요소를 게임 객체가 가지게 한다.
  • 게임을 개발하는 개발 직원을 구현한다. 게임을 지속적으로 이어하기 위한 저장/불러오기 기능이 구현되어야 한다.

분석

턴 객체에 스레드를 적용시켜서 “게임 개발” 중에도 다른 작업(“직원 고용”, “새로운 게임 개발”)을 진행할 수 있도록 제작한다. 일정 턴 동안 게임 객체를 개발하고, 어떤 조건의 턴마다 이 벤트가 발생할 수 있도록 만든다. 턴은 유저가 이벤트를 처리 중이라면 유저에게 충분한 선택, 데이터 입력 시간을 주기 위해 정지되어야 하고 탭을 닫으면 다시 턴이 재게 되어야 한다.

재미있는 게임은 게임의 주제와 장르 속성의 조합으로 결정된다. 주제와 장르의 조합에 대한 테이블이 존재하여 이 테이블에 값으로 게임이 수치적인 재미의 정도, 흥미도를 가늠하게 한다.

게임을 개발할 개발 직원의 능력에 의해서도 게임의 흥미도가 변한다. 능력치가 높은 개발 직원 은 게임 개발에 투입될 때 게임에 흥미도를 높여준다. 개발 직원이 게임 개발에 참여할 때마다 개발 자의 능력치가 높아진다. 하지만 게임이 고착화되는 것을 방지하기 위해 개발 직원이 피로도 속성을 가지게 하여 연속적으로 개발에 투입되면 피로도가 감소하여 직원이 번 아웃되게 구현한다.

 

구현/제작

Java로 구현하며, 스레드를 고려해 유저가 게임 중 동시에 여러 가지 상황을 겪을 수 있도록 한다. 게임의 그래픽은 Eclipse의 플러그인 WindowBuilder를 사용해서 Java Swing으로 구현한 다. 게임에 필요한 스프라이트 이미지는 저해상도의 png확장자 도트 이미지를 사용한다.

 

시험/평가

게임이 턴 단위 진행될 때, 게임 시나리오에 따라서 게임 회사의 자본금, 인지도, 스코어, 발생하는 이벤트가 턴 단위로 달라지는 것을 확인해야 하고, 턴마다 업데이트되어야 할 그래픽 요소의 누락 등의 오류가 없는지 확인해야 한다.

턴 단위로 게임을 진행시켰을 때, 스레드 간 동기화 상태, 순서 관계 등의 오류가 없는지를 테

스트 코드를 넣어 우선 확인한다.

 

l 기존 설계 제한 요소

성능

필요한 객체만 최소한의 스레드를 두어 지연을 최소화한다. 게임의 자료를 다루는 메소드들은 게임시간 1 턴 안에 작업을 완료되어서, 자료들이 다음 턴이 시작할 때 이미 초기화되어 게임에 반영되어야 한다.

 

규격/표준

Windows에서 동작하며 JVM을 통해 구동된다. 또 게임의 해상도는 1280x720p로 고정한다.

위 해상도를 기준으로 세부 인터페이스를 제작한다.

 

신뢰성

게임의 진척도를 사용자가 직관적으로 관찰할 수 있도록 그래픽적으로 수치가 그려짐과 동시에 수치 그 자체도 화면에 표시하여 사용자가 게임의 진행상태를 실시간으로 관찰 수 있다. 예를 들어 게임 개발의 진행도, 회사의 현재 자본금, 게임의 턴 시간 등의 수치를 출력한다.

 

안정성/내구성

처리하지 못한 오류로 인해 게임 데이터가 손상되어 유저의 게임 진행 상황을 유실할 수 있다. 따라서 적절한 주기로 시스템에서 자동 저장을 실시하여 유저가 직접 저장을 하지 않더라도 최 근 시점으로 복구할 수 있게 한다.

 

l 기존 설계 구성요소와 설계 제한요소에 대한 수행 성과

턴 시스템

-  턴 시스템은 본 게임에 적절한 요소가 아니라고 판단되어 턴 시스템 대신 일반적인 타이머를 사용하였다.

 

유저의 작업 중 게임의 흐름 정지

-  해당 기능이 필요한 경우는 탭을 열어 유저가 작업을 하는 경우 유저가 임의로 게임을 잠 시 멈추고 싶어 메뉴 토글 버튼을 활성화하는 경우로 이에 대해 탭이 띄워져 있는 상태임을 확인해 게임의 흐름이 멈추게 만들었다.

 

주제와 장르의 조합

-  이 기능의 경우는 주제와 장르를 헤드로 하는 테이블을 만들어 주제와 장르를 인덱스로 접 근하면 해당되는 재미 수치를 얻을 수 있게 제작하였다.

 

직원의 능력에 따른 게임의 재미

-  직원의 능력(Ability)에 따라 완성되는 게임의 재미 수치가 변하는 것은, 게임의 벨런스 문제로 직원의 능력은 개발 속도에 영향을 미치게 변경하였다.

 

직원의 경험이 쌓일수록 높아지는 능력치

-  위의 경우와 비슷하게 벨런스의 문제로 구현하지 않았다. 직원의 번아웃

-  직원은 오래 일하면 번 아웃하여 개발 불가 상태가 되게 하도록 설계하였던 것 그대로 직원의 피로도가 다 닳게 되면 잠시 동안 퇴근해 피로도를 채워오게 실제로 구현하였다.

 

게임 화면 규격

-  기존에 1280 x 720p의 화면 해상도는 조금 더 작게 800 x 600p로 수정하였다.

 

5. 구 현

다음은 구현한 프로그램의 패키지별 클래스들의 설명이다.

class GameBoard implements ActionListener
개요

게임의 구동부 역할을 하는 핵심클래스 이다.

역할

-턴 방식에 따라 게임을 진행시킨다. 게임 진행에 따른 동작을 체크하는 함수를 작동시킨다.
-각종 창들, 패널들을 초기화 하여 그려준다.
-drawOperater 클래스를 이용하여 각종 물체를 그린다.
-마우스 모션, 클릭등의 이벤트 처리를 통해 게임 시점 변경, 물체배치 등을 한다.
-턴 진행 여부를 확인한다.
-게임의 엔딩을 체크하고, 엔딩장면을 연출한다.

주요 필드(변수)

private JFrame frame
private Company com private Point viewPoint

private JViewport view = new JViewport();
private int delinquencyStack = 0
private boolean isRun = true
private int sleepTime = 100

**Item 패키지

class Item implements GameUI, Updateable, Serializable
개요

각종 아이템생성에 필요한 필드, 이미지 등을 가진다

역할

-  아이템 의 위치 와 능력치 등을 필드값으로 가진다.
-  아이템이 생성될 때 필요한 능력치와 이미지 등을 입력해준다.

필드

private String name;
private String imgAdress;
private String tabImgAdress;
private int income;
private int recharge;
private int efficiency;
public int xPos=-1;
public int yPos=-1;

private boolean selectToggle = true;
private int cost = 2;
private String ItemList[] ;

그 외

class Desk extends Item implements Serializable

: 아이템 중 책상에 관한 클래스. 하나의 주인을 가진다.

 

**Struct 패키지

class Company implements Serializable
개요

회사에 관한 클래스로, 모든 게임에 관한 필드들을 객체화 해서 가진다.


역할

-회사에 관한 정보를 저장한다.
-전반적인 게임의 정보를 저장한다.
-회사의 소유물인 Game, Developer, DevGame, Item 클래스를 Vector 형태로 저장한다.
-
게임 판매, 출시, 개발 진행, 청구금 처리, 직원 정산에 대한 메소드 보유

주요 필드

private static final int MAX_PROJECT_COUNT = 3;
private String companyName;

private int money;
private Vector<Game> product = new Vector<Game>(100);
private Vector<DevGame> project = new Vector<DevGame>(3);
private int projectCount; private Rule rule;
private int score = 0;
private int time = 0;
private int devSpeed=0;
private int bill = 100;
private int floor = 1;
private int itemTabTime = -13;
private int devTabTime = -13;
private String loadFileName = null;
private int recharge=0;
ArrayList itemSellList = new ArrayList();
ArrayList devSellList = new ArrayList();
ArrayList itemList = new ArrayList();
ArrayList devList = new ArrayList();

 

class Developer
개요

게임 속 직원에 관한 클래스이다.

역할

-직원에 관한 정보를 저장한다.

필드

private String name
private int salary;
private int ability;//개발속도에 영향 10~50
private int maxHealth//30~60
private int health;
private boolean workable = false;
public Point deskPos = new Point(-1,-1);
private Thread thread;
private Image sprite; public int x = -1;
public int y = -1;
public int frameNum = 0;
public int direction = 1;
public int dst_x = -1;
public int dst_y = -1;

public boolean isMoving= false;
private boolean selectToggle=false//
직원의 선택여부를 나타낸다.

private int isPlaced = 0//직원배치변수
class DevGame implements Serializable
개요

게임 개발에 관한 클래스이다.

역할

-게임 개발에 참여하는 개발자들을 팀 형태로 저장한다.
-게임 개발 진행도를 저장한다. 

필드

private Game game;
private Developer[] team;
private float progress;
class Game implements Serializable
개요

게임 관한 클래스이다.

역할

-  게임에 관한 필드들을 저장한다.
-  게임에 개발자를 얼마나 투입할 것인지 설정할 수 있게 한다.

필드

private String title
private Subject subject;
private Genre genre;
private int interest;
private int price;
private int launchTime;
private int cumulativeSales =0;
class Rule implements Serializable
개요

게임을 개발할 때 그 게임의 특성을 지정해주는 클래스이다.


역할

-  게임의 속성인 흥미도를 설정한다.
-  장르, 주제에 따른 배열 인덱스를 생성한다.

필드

private String title
private Subject subject;
private Genre genre;
private int interest;
private int price;
private int launchTime;
private int cumulativeSales =0;

그 외

enum FirstNameSet, enum LastNameSet

: 각각 직원들의 성, 이름을 가진다 직원을 생성할 때 이 두 가지를 조합하여 생성한다. enum Genre, enum Subject

: 장르와 주제이다 각 테마에 맞는 비용을 가진다.

 

**UI 패키지

class DrawOperator extends JPanel implements GameUI
개요

JPanel을 상속하여 그림판 역할을 하는 클래스이다.

역할

- paint메소드를 오버라이드 하여 Graphics 클래스를 이용해서 각종 물체를 그 린다.

 

class EndCredit extends Thread implements Serializable, GameUI
개요

엔딩을 출력하는 클래스이다.

역할

엔딩 시에 마지막을 장식하는 엔딩크레딧을 출력한다.

주요 필드

private JPanel endPanel
private JPanel credit
private Company com
private Image image
private Thread thread
private int labelY=210
private int y = GAME_FRAME_HEIGHT
private int i=0
interface GameUI
개요

게임에 관한 각종 설정들을 가지고 있는 인터페이스 이다.

역할

-프레임의 크기, 각종 창의 크기, 크기를 필드로 가진다.
-UI에 관련된 대부분의 객체를 생성하여 사용할 수 있게한다.
interface GameUpdater
개요

즉시 업데이트 되어야할 상태 창 등의 업데이트를 도와준다.

역할

-시그널을 받으면 넘어오는 오브젝트에 따라 해당 객체의 업데이트를 진행한다.
class Menu implements GameUI
개요

메뉴 창을 구현하는 클래스이다.

역할

-메뉴 창에 필요한 필드들을 버튼으로 메뉴창에 띄워준다.
-메뉴버튼을 눌렀을 때 행해져야할 동작들을 정의한다.
class StartGame extends JPanel implements Runnable,GameUI
개요

게임 시작 전 팀 로고를 띄워주는 클래스이다.

역할

-Runnable 인터페이스를 상속하여 run 메소드를 오버라이딩해 위에서부터 팀 로고가 서서히 내려오도록 한다.
-팀 로고가 다 출력되면 아무버튼이나 눌러 게임을 시작할 수 있도록 한다.

 

class GameUpdater extends Thread implements GameUI
개요

즉시 업데이트 되어야할 상태 창 등의 업데이트를 도와준다.

역할

-시그널을 받으면 넘어오는 오브젝트에 따라 해당 객체의 업데이트를 진행한다.

그 외

class ProgressBar implements GameUI, class StatusBar implements GameUI

:각각 진행도 바, 상태바의 내용을 표시한다.

interface Updateable

:GameUpdater객체를 가지는 인터페이스

 

**Tab 패키지

abstract class Tab extends JInternalFrame implements GameUI
개요

메뉴 창에서 버튼을 클릭했을 때 띄워 주는 탭을 구현하는 추상클래스이다.

역할

-각 탭들에 필요한 프레임, 버튼들을 명시한다.
-내부 프레임의 상단, 중단, 하단 으로 나누어진 패널들을 생성하고 초기화한다.

주요 필드

protected Container container;
protected JPanel topPanel;
protected JPanel centerPanel;
protected JPanel bottomPanel;
protected Company com;
protected JButton btn_confirm = new JButton("
확인");
protected JButton btn_cancel = new JButton("
취소");

그 외

class CheatTab extends Tab implements GameUI

: 개발자 콘솔에 관한 내용을 가진다.

class DeskTab extends Tab

: 책상에 직원을 배치할 때 사용한다

class DevEventTab extends Tab implements GameUI

: 개발 도중 이벤트 발생 시 띄워주는 탭이다.

class GameDevTab extends Tab implements GameUI

: 게임 개발에 관한 탭이다.

class GameLaunchTab extends Tab implements GameUI

: 게임 출시에 관한 탭이다.

class InfoTab extends Tab

: 회사 정보에 관한 탭이다.

class ItemTab extends Tab implements GameUI

: 아이템 구매에 관한 탭이다.

class LoadTab extends Tab

: 불러오기 시 세이브 파일목록을 띄워준다.

enum EventScript, enum TabType

: 이벤트에 관한 스크립트와 결괏값을 저장해 놓은 Enum과 탭의 타입을 저장해놓은 Enum.

 

핵심 알고리즘 코드 부분 설명

  • class GameBoard의 run메소드 : 전체 게임의 로직
public void run() {
    int hour = 0
    try { while (true) {
        sleep(sleepTime);
        /*
        *일정 시간동안 sleep하며 sleep 한 시간은 1시간이 됩니다.
        *24시간이 합쳐지면 게임시간으로 하루가 지나갑니다.
        */
        System.out.println(layeredPane.getComponentCountInLayer(JLayeredPane.POPUP_LAYER)+"");
        if (isRun && !menu.isVisible() && layeredPane.getComponentCountInLayer(JLayeredPane.POPUP_LAYER) == 0) {
            /*
            layeredPane의 자식 컴포넌트의 개수가 0일 때 시간을 체크합니다. 창이 열리면 시간이 *가지않습니다.
            */
            if (++hour == 24) {
                // 시간추가
                com.setTime(1); com.sellGame();
                /*
                *직원이 자리에 없을 때, 직원의 체력이 없을때를 체크합니다.
                *체력이없다면 직원을 집으로 돌려보냅니다.
                /*
                for(Developer dev : com.getDevList()) {
                    if(!dev.isMoving && dev.x != dev.deskPos.x) dev.goDesk();
                    if(dev.getHealth() == 0) dev.goHome();
                }
                if(com.getMoney()<0) {
                    //돈이 0이하 일 때 파산스택이 쌓입니다.
                    delinquencyStack++;
                }else {
                    delinquencyStack = 0//회복하면 0으로 초기화 됩니다.
                }
                if (com.getTime() % 30 == 0) {
                // 청구금액(임대로+ 직원인건비+ 아이템유지비)
                com.adjustment();
                }
                // 진행중인프로젝트가존재한다면진행
                if (com.getProjectCount() != 0) {
                    com.progressProject();
                }
                if (delinquencyStack > 60) {//60일 연속 돈이 없다면 파산합니다.
                    JOptionPane.showMessageDialog(null, "파산했습니다.."); System.exit(0);
                }
                 /*
                 *아이탬 구매 탭의 시간이 현재 시간이랑 14일 이상 차이 나지않으면  *아이탬 탭의 아이템이 바뀌지 않습니                                다. 개발자 탭도 동일.
                 */
                if(com.getItemTabTime()+13<com.getTime()) {
                    com.setItemSellList();
                    com.setItemTabTime(com.getTime());
                    if(com.getDevTabTime()+13<com.getTime()){
                        com.setDevTabTime(com.getTime());
                    }
                    if(com.scoreCheck()) {
                        new EndCredit(com);
                    }  
                }
                hour = 0
           }
      }
   }
} catch (InterruptedException e) {
// TODO Auto-generated catch block
    e.printStackTrace();
  }
}

 

  • class Developer 의 일부 : 개발자 움직임 알고리즘
public void run() {
    int frmSpeed = 0
        while(isMoving) {
            try {
                Thread.sleep(20);//프레임속도
                //프레임변경
                if(++frmSpeed == 4) {
                    if(++this.frameNum == 4) this.frameNum = 0
                    frmSpeed = 0
                }
                //방향설정
                x += 4*direction
                //엘리베이터탑승
                if(x < 0 && direction < 0) {
                    direction = 1 x = 4 y = dst_y //-64
                    //집으로
                }
                else if(x > FRAME_WIDTH) {
                    this.isMoving = false
                    Thread.sleep(2000);
                    this.health = maxHealth
                    x = 800-64    
                    y = 2600
                    //목적지도착
                }
                else if(x == dst_x && y == dst_y) {
                    Thread.sleep(2000);
                    System.out.println("도착");
                    this.dst_x =-1
                    this.dst_y =-1
                    this.frameNum = 0
                    this.isMoving = false
                    this.rest(1);
                }
                draw.repaint();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                }
        }
    System.out.println("이동종료");
}

 

  • class Company 의 일부 : 게임 개발 알고리즘
// 0:성공 1:돈부족 2:팀원부족 3:타이틀 4:최대개발 5:주제 또는 장르 미선택
public int startDev(String gameTitle, Subject subject, Genre genre, Developer[] team){
    int cost;
/*
* enum 클래스에서 선택한 주제와 장르 에 해당하는 정보를 가져옵니다.
/*
    try {
        cost = subject.getCost() + genre.getCost();
    }catch(NullPointerException e){
        return 5;
    }

    if(this.money - cost < 0) return 1;
    for(Game game : this.product) //타이틀이 이미 존재
    if (game.getTitle().equals(gameTitle)) return 3;
    if(gameTitle.equals(""))// 타이틀이 공백 return 3; if(team[0] == null)//팀원 미선택 return 2; if(projectCount > 2)// 최대     프로젝트 수 제한 return 4;

    /*여기서 부터는 새로운 게임을 생성하고, 프로젝트에 추가합니다.*/
    this.appendMoney(-cost);//cost만큼 돈을 제합니다.
    Game newGame = new Game(gameTitle, subject, genre);
    project.add(new DevGame(newGame, team));
    projectCount++;
    for (Developer dev : team) {
        if(dev == null) break;
        dev.setWorkable(false);
    }
    gameUpdater.signal(this); // status 업데이트를 위한 신호 return 0;
}

 

시험/평가

1.  시험/평가 게임이 턴 단위 진행될 때. 게임 시나리오에 따라서 게임 회사의 자본금, 인지도, 스코어, 발 생하는 이벤트가 턴 단위로 달라지는 것을 확인한다.

2.  턴마다 업데이트되어야 할 그래픽 요소의 누락 등의 오류가 없는지 확인한다.

항목 결과 내용
1 O

스레드에 관련 필드를 관리하는 메소드가 매 턴 마다 업데이트를 해준다.
2 O

진행될 때마다 별도의 그리기를 관리하는 클래스의 그래픽 업데이트 확인

 

6. 결 론

개발 내용 및 실험 결과 요약, 분석, 결론

게임 시작 시 로고 화면을 구현하였다. 스레드를 이용하여 위에서부터 아래로 게발게발 팀의 로고가 내려온다.

로고 화면

게임의 시점은 사이드 뷰로 진행된다 원래는 대각선 상 위에서 내려다보는 쿼터뷰였지만, 구현 난이도를 고려하였을 때 사이드 뷰로 변경하였다. 화면 가장자리에 마우스를 가져다 대면 ViewPort가 패널을 보는 위치를 옮기며 다른 구역을 볼 수 있다. 초기의 스크롤 대신, 뷰포트로 변경하였다.

 

화면 상단에는 날짜와 회사의 자금이 표시되어있다. 스레드가 돌아감에 따라 날짜를 체크하고, 각종 변수

들을 변경한다.

 

또 오른쪽 메뉴에서 아이템 구매를 눌러 회사를 확장시키고, 아이템을 구매하면 이는 객체화되어 배치할 수 있다. 배치는 화면 선상의 마우스 포인터 값을 정렬해서 이미지를 그려주는 방식으로 진행되며, 개발 자와 아이템 모두 이런 방식으로 구현하였다.

날짜, 배치, 시점

게임 개발 탭을 구현하여, 주제와 장르를 입력받으면 미리 지정된 테이블에서 값을 추출하여 흥미도를 계 산하고, 금액을 산정한다. 개발이 시작되면 프로젝트 리스트에 지정한 게임 객체가 추가되고, 지정된 직원 들은 피로도가 소모된다.

 

직원의 피로도가 다 소모되면 스레드를 이용하여 오른쪽 하단으로 이동하며, 걷는 모션을 추가하였다. 기존에는 아이템 위치를 받아와서 아이템에서 쉬는 모션까지 추가하려고 했지만, 시간 관계상 생략했다.

 

직원의 이미지 스프라이트는 한 사람분 밖에 제작하지 못했다. 개발 중에는 개별 이벤트가 나타나며 이를 어떻게 처리하느냐에 따라 개발 진행속도가 달라지게 하였다. 현재는 게임 개발 중에 나타나는 이벤트만 보여주며, 기존에는 외주 이벤트. 회사 앞 시위 등 상당히 다양한 시나리오를 구현하여 틀에 갇힌 게임이 아닌 다양함을 주려고 했다.

게임개발 게임의 핵심인 게임개발

엔딩을 보기 위해서는 플레이어의 결과물인 스코어를 달성해야 한다. 현재는 이 엔딩을 보기 위해 책정된 값들을 올리기가 너무 쉬운 경향이 있고, 게임 중반 이상 가면 엔딩을 보기보다 파산하기가 더 어렵다는 점이 문제점이다. 엔딩 크레디트는 엔딩이 시작되면 아래서부터 위로 엔딩 크레디트가 서서히 올라온다. 이곳에는 각종 업적과 참여한 개발자들, 게임들을 띄워주려고 했으나, 생략하였다.

 

엔딩의 종류가 하나이기 때문에 이 엔딩을 달성하는 방향을 여러 가지로 나누면서 각종 업적 시스템을 추 가하는 쪽으로 게임성을 높이려는 시도를 했었다. 하지만 이는 기능 구현 쪽에 우선순위가 밀려 실현되지 못했다.

엔딩 크레딧

 

 

추후 개선 요소

UI 개선 게임성 개선
게임 과 조화가 잘 안 맞는 전반적인 인터페이스 를 튜닝 할 필요가 있어 보인다. 게임에 어울리 게 텍스트와 버튼, 창 등을 개선한다면 훨씬 게임과 잘맞을 것이다.

불러오기 화면은 불러오기 가능한 파일명들이 죽 늘어서 있습니다. 그래서 지저분해 보이고 수직 으로 정렬하여 깔끔하게 개선할 필요가 있다.

직원 고용 화면의 개선이 필요해 보인다. 직원들의 이미지를 따서 업데이트 시키고, 직원의 능력치나 급여 등을 명시적으로 표시하는 방향으로 개선이 필요하다.

회사 정보 UI도 마찬가지로 단순히  타입만 라벨링 되어있다.
이를 개선하여 타입별로 나타 낼 칸을 생성하여 그 안에 정보를 띄워주는 방향 으로 개선이 필요하다.
게임은 초반의 루즈함과 후반에는 돈을 벌기가 너무쉽다는 점이 있다.

이를 개선하기위해 스코어가 올라가기 위한 방식 을 회사에 관한 여러 시나리오를 구성하여 이를 어떻게 처리하느냐에 따라 평판이 바뀌고 또 어떠한 게임을 출시하고 사후대처 여부에 따라 처리 방식이 바뀌도록 스코어를 다양하게 올리는 방향으로 간다면 게임이 더 다채로워 질 것이다.
스프라이트 개선 업적, 희귀성 개선
직원을 움직이게 하고, 아이템과 상호 작용을 하 게 하기 위해서는 많은 스프라이트 이미지가 필 요하다. 초기에는 왼쪽과 같이 정면을 바라보고 있는 직원이미지를 여러장 그리려고 했다.

하지만 오른쪽과같이 움직이게 하는데만도 4장의 이미지가 필요하고, 책상에 앉고 일을 하는등 모 션 처리를 하려면 훨씬 많은 이미지가 필요했다.

시간이 없어 한사람분의 스프라이트 이미지만 사용했지만 이를 개선하여 여러 사람분의 스프라이 트 이미지를 만들고, 굳이 인간이 아닌 외계인이 나 동물 같은 직원도 만들어서 다채로움을 주는 방향으로 개선할 수 있다.
지금 게임개발 게임의 업적 시스템은 거의 없다 시피 하다. 이것을 희귀성 아이템, 직원, 게임 개 발 과 연계 하고, 또 시나리오 와 연계하여 업적 시스템을 구현해주는 것 만으로도 게임성을 크게 올리면서 큰 개선점이 될 것이다.

희귀성이란 것은 소위 레어아이템 따위를 말한 다. 지금 아이템 구매 탭에서 구매할수 있는 아 이템들은 모두 나올 확률이 다르며, 게임기 같은 것은 5프로 정도의 확률로 희귀 하게 출현한다.

하지만 이것은 아이템 구매 탭 한정이며, 앞선 글에 나와 있듯이 업적 시스템과 연계하여 희귀 아이템을 획득하거나, 업적을 달성 했을때만 나 오는 아이템을 추가하여 개선할 수 있다.

7. 개발 일지

(개발 기간 : 2020  11 2    ~    2020   12  11 )
  내용
1주차 -  검색을 통해 자료수집(이미지, 알고리즘 등), 실제게임을 통해 정보 수집
-  어떤 언어와 어떤 방식으로 개발할지 결정하고, 전체적인 프로그램 구조를 설계
2주차 -  게임의 시점을 쿼터뷰에서 사이드 뷰로 변경,
-  메인 프레임, 상태바, 메뉴버튼 등 기본적인 GUI틀을 제작
3주차 -  탭 들을 구현하고, 탭에 띄워줄 내부 구조 클래스의 정보로 테스트
-  유저가 맵의 일부분만 스크롤 하여 볼 수 있도록  ScrollPane 기반 view 제작
-  맵의 각종 설정의 저장하는 MapInfo 클래스를 만들의 아이템의 위치나 층의 개수 저장
-  화면의 일부를 클릭할 수 있게 모든 화면에 라벨을 달고 리스너를 부착해 아이템 배치 구현
4주차 -  테스트용 건물이미지를 넣어 증축 테스트
-  아이템이나 직원을 그리는 방식을 라벨을 띄워주는 방식에서 JPanel을 상속하여 패널에 
   Graphics클래스로 그림을 그려주는 방식으로 수정
-  개발자 치트콘솔을 열 수 있게 설정해 놓았다. 이것은 아직까지 게임시작후 한번만 쓸 수 있는 오류
-  스레드를 구현하여 날짜시스템을 도입하였고, 스레드가 진행됨에 따라서 변수값들이 바뀌고, 화면에 띄워주     는 값이 변경되게 구현
-  직원을 구현하여 게임 개발 테스트에 쓸 수 있도록 하였다.
게임 개발 기능 구현, 주제와 장르를 선택하고 개발 시작 시 진행도가 실시간으로 변경되어   화면에 보이게     구현. 개발에 드는 비용이나 직원의 능력에 영향 미구현
-  화면 뷰 ScrollPane제거 ViewPort만 부착하는 방식으로 변경, 마우스가 화면 가장자리에가 면 화면이 움직이     는 방식으로 수정하면서, Draw 패널에 리스너로 인해 view의 리스너사용 제 한,draw  라벨을 모두 제거하고     화면을 클릭시에 좌표를 가공해서 아이템이 있는지 없는지 판 별하고, 층이 있는지 판별후에 배치하도록 하     였다.
5주차 - enum으로 랜덤으로 성과 이름을 받아와 직원 객체 다양화 직원 구매 탭에서 직원을 고용 할 수 있고, 책상에    서 직원을 배치 할 수 있도록 하였으며, 게 임 개발에 참여할 수 있도록 구현
  아이템 탭에 아이템을 띄워주는 방식을 대폭 수정하였다. 아이템 이나 직원을 맵에 띄워 주는 방식을 변경하    였다.

- 맵의 설정을 저장하는 MapInfo클래스를 제거하고, 각각의 객체에 위치필드를 넣어 자기 자신 의 위치에 그려    주도록 하였다.

- 직원 스프라이트를 제작하였다. 직원에 개별적으로 스레드를 달아놓아 직원이 움직일 수 있게하였다. 직원이    피로도가 떨어지면 집에가고, 다시 자기자신의 책상으로 돌아올 수 있게하였다.
  직원과 아이템 탭이 누를 때마다 띄워주는 객체가 변경되지않고, 일정시간이 지날 때 마다 변 경되도록 하였다.
-  그래픽 구현
-  게임 시작 인트로와 엔딩구현

 

8. 참고문헌

[1]https://stackoverflow.com/

[2]https://docs.oracle.com/en/java/

[3]https://www.codingfactory.net/

[4]https://dojang.io/

[5]https://unikys.tistory.com/178

[6]https://offbyone.tistory.com/110

[7]https://cremazer.github.io/java-Class-and-Object/

[8]https://www.aseprite.org/

 

댓글