코드 분석 - HY-CtrlS/Invaders-SDP GitHub Wiki
개요
- 게임에서의 쿨타임과 같은 역할을 하는 클래스
변수
- int milliseconds
- 쿨타임 지속 시간
- int variance
- 쿨타임의 변동성
- int duration
- 변동성이 추가된 최종 지속시간
- long time
- 쿨다운의 시작 시간(시스템 시간)
생성자 1 milliseconds만 받음
- 변동성은 0으로 초기화
- 따라서 duration은 그냥 milliseconds가 됨
생성자 2 milliseconds와 variance 둘 다 받음
- duration은 정해지지 않음
메서드
- checkFinished
- 쿨다임이 다 돌았는지 여부를 반환
- 쿨타임에 기록된 시작시간과 현재 시간을 비교
- 시작시간에 쿨타임을 더한 시간이 지금 시간보다 작다면, 쿨타임이 다 돈 것
- 쿨다임이 다 돌았는지 여부를 반환
- reset
- 쿨타임 객체의 시간을 reset을 수행한 시간으로 저장(시작)
- 변동성이 있다면, 변동성에 따라 랜덤하게 duration 설정
상수
- int WIDTH = 448
- 현재 화면의 너비
- int HEIGHT = 520
- 현재 화면이 높이
- int FPS = 60
- 화면의 최대 프레임 수
- int MAX_LIVES = 3
- 최대 생명 수
- int EXTRA_LIFE_FRECUENCY = 3
- 추가 생명을 받을 수 있는 레벨 간격
- int NUM_LEVELS = 7
- 총 레벨의 수
- GameSettings
- 각 레벨에 대한 난이도 설정
- Logger LOGGER = Logger.getLogger(Core.class.getSimpleName())
- Core라는 이름을 갖는 Logger
변수
- Frame frame
- screen이 올라갈 frame
- Screen currentScreen
- 현재 올라가있는 스크린
- List gameSettings
- 난이도 설정의 리스트
- Handler fileHandler
- 로그를 디스크에 기록하는 핸들러
- ConsoleHandler consolHandler
- 로그를 콘솔에 출력하는 핸들러
생성자
- LOGGER 설정
- LOGGER의 부모 핸들러 사용 하지 않게 함
- “log” 이름의 파일에 로그를 기록하는 파일 핸들러 생성
- 로그 형식을 MinimalFormatter로 지정
- 로그 메시지를 콘솔에 출력하는 콘솔 핸들러 생성
- 로그 형식을 MinimalFormatter로 지정
- LOGGER에 파일핸들러와 콘솔핸들러 추가
- 모든 로그 레벨을 기록하도록 레벨 설정
- frame 설정
- frame을 생성하고, DrawManager에게 setFrame을 함
- frame에서 여백을 제거한 width와 height를 받아 Core의 변수로 설정
- gameSetting 리스트 초기화
- 총 7단계의 설정들을 리스트에 추가
- 게임 실행
- returnCode를 1로 초기화(메인 메뉴)
- gameState를 초기화
- 레벨 1
- 점수 0
- 목숨 MAX_LIVES
- 총알 발사 수 0
- 파괴 함선 수 0
- returnCode에 따라 분기
- 1인 경우 (메인 메뉴)
- 현재 스크린을 titleScreen으로 설정
- frame.setScreen으로 현재 스크린을 run함
- 현재 스크린이 종료되면 그 값이 returnCode로 들어가고 break
- 2인 경우 (게임, 점수화면)
- bonusLife 제공 여부 계산
- 현재 레벨이 추가 생명 빈도의 배수이고
- 최대 생명이 아닌 경우
- gameScreen 객체 생성후 currentScreen으로 저장
- gameState는 계속 업데이트
- gameSetting은 gameSettings 리스트에서 가져옴
- frame.setScreen으로 현재 스크린 run
- run이 종료되면, gameState를 최신화
- 종료된 gameState에서 레벨만 1개 증가시켜 저장
- 반복 여부 확인
- 남아있는 생명이 0 이상이고, 마지막 레벨을 넘기지 않았다면
- 반복이 종료되면 ScoreScreen 실행
- gameState를 입력해 ScoreScreen 생성해 currentScreen으로 저장
- frame.setScreen(currentScreen)을 통해 ScoreScreen을 run함
- 종료되면 returnCode를 받음
- break
- bonusLife 제공 여부 계산
- 3인 경우(최고 기록 화면)
- 최고기록 화면을 생성해 currentScreen으로 설정
- frame.setScreen으로 최고기록 화면 실행
- 실행 종료되면 returnCode를 받음
- break
- returnCode가 0이 발생한 경우
- while문을 탈출
- 버퍼에 있는 모든 로그 데이터를 파일에 기록
- fileHandler를 닫음
- 프로그램 종료
- 1인 경우 (메인 메뉴)
- Logger, DrawManager, InputManager, FileManager, Cooldown, VariableCooldown getter 관리
생성자
- fileManager, logger를 Core의 것으로 초기화
- spriteMap을 만들고, boolean 배열의 값들을 fileManager.loadSprite()를 통해 초기화
- fileManager.loadFont()를 통해, fontRegular, fontBig 초기화
Set Frame
Frame 타입을 하나 입력받아 frame속성에 저장
initDrawing
screen을 입력받아 screen의 width와 height를 이용해서
- backBuffer
- graphics
- backBufferGraphics 초기화
CompleteDrawing
backBuffer에 다 그려진 것을 한 번에 frame의 graphics에 그린다
drawCenteredRegularString, drawCenteredBigString
입력
- 스크린
- 쓸 문자
- 높이
중앙 정렬해서, 높이만큼 위에서 떨어진 위치에 쓸 문자를 그림 GameScreen에 사용되는 것들
drawEntity(개체, x좌표, y좌표)
- 개체의 spriteType을 받아 해당하는 spriteMap을 찾음
- 개체의 color를 받아 spriteMap에 맞게 그림
- 실제로 그릴 땐 한 픽셀이 2x2크기의 픽셀이다
drawScore(스크린, 점수)

- 흰색, 4자리, 보통 폰트로
- 우측 상단의 점수 그림
drawLives(스크린, 목숨 수)
 목숨 수를 쓰고, 그 수만큼 우주선을 그림
Title Screen에 사용되는 것들
drawTitle(스크린) 
- 시작 화면 메시지 그리기
- “INVADERS”는 화면의 1/3 지점
- 설명글은 화면의 1/2 지점
drawMenu (스크린, 옵션 번호)  옵션 번호에 따라 한 가지 항목을 초록색으로 표시
- play: 2
- 화면의 2/3지점
- Hight Scores: 3
- 화면의 2/3지점 + 글자 높이 두 칸
- Exit: 0
- 화면의 2/3지점 + 글자 높이 네 칸
ScoreScreen에 사용되는 것들
drawResult (스크린, 점수, 남은 목숨, 부순 함선 수, 정확도, 신기록 여부)
신기록인 경우 
- 화면의 1/4 지점에서 시작
신기록이 아닌 경우 
- 화면의 1/2 지점에서 시작
drawNameInput (스크린, 이름, 선택된 글자 번호)

- 이름에 해당하는 글자 그리기
- 선택된 글자 번호의 글자를 초록색으로 표시
- 0, 1, 2 순서
drawGameOver(스크린, 입력 가능 여부, 신기록 여부)
신기록인 경우 
- 입력이 가능한 상태이면 밑에 문장을 초록색으로 표시
- 아니라면 회색으로 표시
HighScoreScreen에 사용되는 것들
drawHighScoreMenu (스크린) 
drawHighScores (스크린, 스코어 목록)  스코어 목록에서 이름과 점수를 받아 그리기
생성자
private FileManager() { logger = Core.getLogger(); }
- private이므로 FileManager 클래스에서만 접근 가능
- logger를 Core의 것으로 초기화
- 객체에 접근할 땐 getInstance() 메소드를 사용해야 함
getInstance()
protected static FileManager getInstance() { if (instance == null) instance = new FileManager(); return instance; }
- protected이므로 같은 패키지 내에서 접근 가능
- instance가 존재할 경우, 그것을 반환
- 존재하지 않는 경우, 새로 생성 따라서, 인스턴스를 하나만 생성해서 사용함
loadSprite(spriteMap)
- SpriteType과 boolean 2차원 배열의 맵을 입력 받음
- “graphics” 파일에서 그래픽 정보(0, 1)를 읽어와 실제 2차원 배열에 초기화
- boolean[i][j]에서
- i: 가로 크기
- j: 세로 크기
- “graphics”의 숫자 정보(0011010110….)은 세로 단위로 끊김
loadFont(size)
- 폰트 size를 입력받아 그 size의 font 객체 반환
- font는 “font.ttf” 파일을 사용함
loadDefaultHighScores
- loadHighScores()에서 사용자 점수를 찾지 못한 경우 생성됨
- Score의 배열을 반환
- 기본 파일의 점수들을 Score 객체로 읽고, 이들을 Scores라는 리스트로 만들어 반환
loadHighScores()
- 사용자 점수를 찾고, 찾지 못하면 loadDefaultHighScores 실행후 결과를 highScores로 받아옴
- 사용자 점수를 찾으면 거기서 점수를 받아옴
- 받아온 highScores를 정렬한 뒤, 반환
saceHighScores(highScores)
- Score의 리스트를 입력 받음
- 7개 이하라면, 그 갯수만큼만 파일에 점수로 작성하고 사용자 점수로 저장
- 7개 초과라면, 7개까지만 파일에 점수로 작성하고 저장
JFrame을 상속함
속성
- int width
- int height
- Screen currentScreen
생성자(width, height) 1.
- 창의 크기(입력받은 크기)
- 크기 조절 여부
- 창의 위치
- 최소화 여부
- 제목 을 설정함
- width와 height를 여백 제거해서 다시 저장
- KeyListener를 InputManager로 설정
setScreen(screen)
- screen을 입력받아, 그것을 currentScreen으로 지정
- currentScreen을 초기화
- currentScreen 실행
개요
- 적 함선 집단의 설정을 모아놓은 클래스
필드
- int formationWidth
- 가로로 몇 개의 함선이 있는지
- int formationHeight
- 세로로 몇 개의 함선이 있는지
- int baseSpeed
- 집단의 기본 이동 속도
- int shootingFrecuency
- 집단의 총알 발사 빈도
생성자
- 필드를 입력받아 초기화
매서드
- 필드들의 getter
개요
- 레벨의 정보를 저장하는 클래스
필드
- int level
- 현재 게임 레벨
- int score
- 현재 스코어
- int livesRemaning
- 현재 남은 목숨
- int bulletsShot
- 지금까지의 총알 발사 횟수
- int shipsDestryed
- 지금까지 부순 함선 수
생성자
- 필드를 입력받아 초기화
매서드
- 필드들의 getter
개요
- 키보드의 입력을 관리하는 클래스
- 싱글톤 클래스
상수
- final int NUM_KEYS = 256
- 인식 가능한 키의 수
- 키 배열의 크기 속성
- boolean[] keys
- 인덱스에 해당하는 키가 눌려있으면 true값을 가지는 배열
- InputManager instance
- 클래스의 싱글톤 인스턴스
생성자
- private 생성자
- keys 배열을 NUM_KEYS의 크기를 갖는 boolean 배열로 초기화
메서드
- getInstance
- 객체가 생성되어있으면 그걸 반환
- 없으면 새로 생성 후 반환
- isKeyDown(keyCode)
- keyCode에 해당하는 키가 눌려있는지 여부를 반환
개요
- 로그에 작성할 포맷에 맞는 String 생성
속성
- DateFormat FORMAT = new SimpleDateFormat(“h:mm:ss”)
- 시, 분, 초 형식의 포맷을 지정해주는 formater
- String LINE_SEPARATOR
- 개행 문자를 저장
- Windows에선 \r, \n이 될 수 있음
- 유닉스/ 리눅스 / 맥에선 \n이 됨
- 어느 운영체제에서든 호환 가능하도록 함
생성자
- 기본 생성자
메서드
- format(logRecord)
- logRecord의 정보로 로그에 찍힐 한 줄을 작성함
- 문자 끝엔 공백 문자 하나와 개행 문자가 들어감
- Score 클래스는 String 타입의 이름과 int 타입의 점수를 속성으로 갖는다.
- 생성될 때 이름과 점수를 받아 초기화를 하고, 이는 수정 불가능하다.
- 이름과 점수엔 getter만 존재한다.
compareTo()
- 또 다른 Score 타입을 입력받아 두 Score를 비교한다.
- A.compareTo(B)
- A < B: 1
- A > B: -1
- A == B: 0
##Bullet
개요
- Entity 클래스를 상속하는 총알의 개체
속성
- int speed
- 총알의 속도
- 클 수록 빠름
생성자
- 위치, 속도를 입력받음(크기와 색상은 정해져 있음)
- 속도를 속도로 설정
- 속도에 따라 SpriteType을 결정(위로가면 아군꺼, 아래로 가면 적꺼)
메서드
- setSprite()
- 속도가 음수 -> 위로 가면
- spriteType을 Bullet으로(아군)
- 속도가 음수가 아님 -> 아래로 가면
- spriteType을 EnemyBullet(적군)
- 속도가 음수 -> 위로 가면
- update()
- 총알의 y좌표를 speed에 따라 업데이트
- setSpeed()
- 총알의 속도 설정
- getSpeed()
- 총알의 속도 반환
개요
- 총알 객체(Bullet)를 관리하는 풀
- Static 메서드와 Static 필드만 있어 인스턴스를 생성할 필요가 없음
속성
- Set pool
- 총알들의 집합인 pool 속성
- 중복된 총알 객체가 추가되지 않음을 보장
생성자
- private이므로 외부에서 이 클래스를 생성할 수 없음
메서드
- getBullet(x좌표, y좌표, 속도)
- 재사용 가능한 pool에 총알이 있다면
- 그 총알을 bullet에 저장, pool에서 제거
- bullet을 입력받은 위치와 속도로 설정
- 속도에 따라 spriteType을 설정
- pool에 총알이 없다면
- 새로운 bullet을 생성한 뒤 초기화
- 이후 bullet을 반환
- 재사용 가능한 pool에 총알이 있다면
- recycle
- 총알 집합을 입력받아, 그걸 pool에 추가함
개요
- 적함선 개체를 만드는 클래스
상수
- int A_TYPE_POINTS = 10
- int B_TYPE_POINTS = 20
- int C_TYPE_POINTS = 30
- int BONUS_TYPE_POINTS = 100
- 적 함선의 종류에 따라 점수 다르게 설정
속성
- Cooldown animationCooldown
- 움직임의 쿨타임
- boolean isDestroyed
- 이 함선이 파괴되었는지 여부
- int pointValue
- 이 함선이 파괴되었을때 얻는 점수
생성자
- 위치, 함선 종류 입력 받아 초기화 (크기와 색상은 자동으로 초기화)
- spriteType 초기화
- animationCooldown 초기화
- isDestroyed=false로 초기화
- spriteType에 따라 pointValue 초기화
인수 없는 생성자
- 위치, 함선 종류 없이 넘긴 경우
- Special 함선이 됨
메서드
- getPointValue
- 파괴되었을 때 얻는 점수 반환
- move
- 이 함선을 x, y칸만큼 이동
- update
- animationCooldown이 돌았다면,
- 1 모양에서 2 모양으로
- 2 모양에서 1 모양으로
- animationCooldown이 돌았다면,
- destroy
- 함선 파괴
- isDestroyed=true로 설정
- spriteType을 Explosion으로 설정
- isDestroyed
- 파괴 여부를 반환
개요
- 적군 우주선의 집단을 관리하는 클래스
상수
- int INIT_POS_X = 20
- int INIT_POS_Y = 100
- 우주선 집단의 초기 좌표
- int SEPARATION_DISTANCE = 40
- 우주선 사이의 간격
- double PROPORTION_C = 0.2
- double PROPORTION_B = 0.4
- 우주선 타입의 비율
- int X_SPEED = 8
- int Y_SPEED = 4
- 우주선 집단의 이동속도
- 클 수록 빠름
- int BULLET_SPEED = 4
- 우주선이 발사하는 총알의 이동 속도
- double SHOOTING_VARIANCE = 0.2
- 총알 발사 간격의 변동성
- int SIDE_MARGIN = 20
- int BOTTOM_MARGIN = 80
- 우주선 집단이 넘어가지 못하는 좌, 우, 하단 여백
- int DESCENT_DISTANCE = 20
- 각 패스마다 내려가는 거리
- int MINIMUM_SPEED
- 집단의 최소 이동 속도
- 작을 수록 빠름
인스턴스
- drawManager
- logger
- screen
- draw할 화면
속성
- enemyShips
- 적 함선으로 된 2차원 배열
- nShipsWide
- nShipsHigh
- 적 함선의 가로 세로 갯수
- shootingInterval
- 총알 발사하는 시간 간격
- shootingVariance
- 발사 간격의 변동성
- shootingCooldown
- 발사 시간 간격 Cooldown 객체
- shootingInterval과 shootingVariance를 통해 구해짐
- baseSpeed
- 집단의 기본 이동 속도
- 작을 수록 빠름
- movementSpeed
- 현재 집단의 이동 속도
- baseSpeed + 기타 요인에 의해 결정됨
- 작을 수록 빠름
- movementInterval
- 이동의 카운터
- 스택이 쌓이면 이동이 일어남
- 0으로 초기화되어 매 프레임마다 1씩 증가
- currentDirection
- previousDirection
- 집단의 이전, 현재 이동 방향
- Direction 타입
- 왼쪽
- 오른쪽
- 아래
- width
- height
- 집단이 차지하는 가로 세로 픽셀 크기
- positionX
- positionY
- 집단의 좌측 상단의 좌표
- shipWidth
- shipHeight
- 함선 하나의 크기
- shooters
- 총알을 발사할 수 있는 함선들의 리스트
- shipCount
- 남아있는 함선의 수
생성자
- gameSettings을 입력으로 받음
- drawManager, logger를 Core의 것으로 초기화
- 이동 방향 오른쪽으로 초기화
- movementInterval = 0 으로 초기화
- 집단의 함선 수를 gameSettings대로 초기화
- 발사 간격과 변동성 초기화
- 집단의 기본 속도를 gameSetting대로 초기화
- 현재 이동속도를 기본 속도로 초기화
- 집단의 위치 초기화
- enemyShips 2차원 배열에 실제 함선들 객체 생성(함선 종류 비율에 따라
- 함선 하나의 크기 초기화
- 집단 전체의 크기 초기화
- 각 열의 가장 마지막에 있는 함선으로 shooters 초기화
메서드
- attach
- screen을 입력받아 그것을 screen변수에 등록
- draw
- enemyShips에서 한 함선씩 꺼내어 backBuffer에 함선 그리기
- update
- 최초 실행시 shootingCooldown을 shootingInterval, shootingVariance대로 초기화한 후 reset해서 실행
- cleanUp() 실행
- 남아있는 함선의 비율을 계산
- movementSpeed를 baseSpeed(gameSetting꺼)에다 남아있는 함선 비율의 제곱으로 곱해서 설정한 뒤, MINIMUM_SPEED를 더한 값으로 설정
- 처음엔 baseSpeed + MINUM_SPEED이지만
- 함선의 비율이 줄어들 수록 MINIMUM_SPEED에 가까워짐
- movementInterval을 update할 때마다 1씩 증가시킴
- movementSpeed에 도달한 경우, 실제 이동이 일어남
- 이동 방향 설정
- 내려가는 중인 경우
- 내려가는 이동이 끝났는지 확인(y좌표가 간격의 배수인지 확인)
- 이동이 끝났다면, 현재 이동방향을 이전 이동방향의 반대로 설정
- 왼쪽으로 이동중에 왼쪽 벽을 만난 경우
- 밑으로 내려갈 수 있다면
- 이전 이동방향을 왼쪽으로 설정
- 현재 이동방향을 아래로 설정
- 밑으로 갈 수 없다면
- 현재 이동방향을 오른쪽으로 설정
- 밑으로 내려갈 수 있다면
- 오른쪽으로 이동중에 오른쪽 벽을 만난 경우
- 밑으로 내려갈 수 있다면
- 이전 이동방향을 오른쪽으로 설정
- 현재 이동 방향을 아래로 설정
- 밑으로 갈 수 없다면
- 왼쪽으로 이동 시작
- 밑으로 내려갈 수 있다면
- 이동 값 설정
- movementX, movementY만큼 이동하게 됨
- 오른쪽으로 이동중인 경우
- movementX = X_SPEED로 설정
- 왼쪽으로 이동중인 경우
- movementX = -X_SPEED로 설정
- 아래로 이동중인 경우
- movementY = Y_SPEED로 설정
- 집단의 위치 값을 갱신
- poisitionX, positionY를 movementX, movementY만큼 추가
- 파괴된 함선 수거
- enemyShips에서 한 열씩 검사
- 한 열에서 하나의 함선씩 꺼내어 검사
- 함선이 파괴되었다면, 파괴된 함선 리스트에 추가
- 파괴된 함선 리스트에 있는 함선을 열에서 제거
- 한 열에서 하나의 함선씩 꺼내어 검사
- enemyShips에서 한 열씩 검사
- 집단의 모든 함선을 이동시키고 업데이트
- 내려가는 중인 경우
- cleanUp
- 집단에서 빈 열을 제거
- 한 열씩 꺼내어 비어있다면 그 열의 인덱스를 emptyColumns에 추가
- 모든 열을 확인한 뒤 emptyColumns에 해당하는 열을 enemyShips에서 실제로 제거
- 집단의 너비와 높이 재조정
- 가장 먼저 나오는 열의 함선의 x좌표가 집단의 왼쪽 끝 점
- 가장 마지막에 있는 열의 함선의 x좌표가 집단의 오른쪽 끝 점의 베이스
- 집단의 너비 = 왼쪽 끝 점과 오른쪽 끝 점의 차이 + 한 함선의 너비
- 집단의 높이 = 열들 중 가장 긴 열의 높이
- 집단의 x, y좌표 재조정
- 집단에서 빈 열을 제거
- shoot
- 집단에서 총알 발사
- 슈터들 중 랜덤으로 하나 선택
- 쿨다운이 완료되었다면 총알 발사한 뒤 쿨다운 다시 시작
- bullets: 현재 화면에 있는 총알
- BulletPool에서 getBullet을 하여 총알을 받아 bullets에 추가
- destroy
- 함선 하나를 입력받아 그 함선을 파괴된 상태로 변경
- 입력받은 함선을 enemyShips에서 찾아 파괴 처리
- 그 함선이 shooters에 있던 경우 새로운 Shooter 지정
- 파괴된 함선이 포함된 열을 찾는다
- 그 열에서 nextShooter를 찾아 nextShooter로 지정
- nextShooter가 있는 경우
- 파괴된 함선이 있던 Shooters 자리에 새로운 함선 넣기
- 없는 경우
- Shooters의 크기가 줄어듦
- 전체 함선 개수 하나 감소
- 함선 하나를 입력받아 그 함선을 파괴된 상태로 변경
- getNextShooter
- EnemyShip의 한 열에서 다음 파괴되지 않은 함선이 있는지 확인
- nextShooter를 찾지 못한 경우 null 반환
- 찾은 경우 그 함선의 객체 반환
- EnemyShip의 한 열에서 다음 파괴되지 않은 함선이 있는지 확인
- isEmpty
- 집단이 비어있는지 여부 반환
-
Bullet, Ship, EnemyShip의 상위 클래스
-
위치(positionX, positionY)
-
개체의 크기(width, height)
-
색상
-
spriteType
개요
- 아군 함선의 개체
상수
- int SHOOTING_INTERVAL = 750
- 총알 발사 간격(밀리초 단위)
- int BULLET_SPEED = -6
- 함선에서 발사된 총알의 속도
- 절댓값이 클 수록 빠름
- int SPEED
- 함선의 이동 속도
- 클 수록 빠름
속성
- Cooldown shootingCooldown
- 발사 간격의 쿨다운 변수
- Cooldown destructionCooldown
- 피격시 비활성화 되는 쿨다운 변수
생성자 입력: x좌표, y좌표
- 크기와 색상은 고정된 값으로 설정됨
- spriteType을 Ship으로 설정
- shootingCooldown을 SHOOTING_INTERVAL의 길이를 갖는 Cooldown 객체로 설정
- destructionCooldown을 1000ms 쿨다운으로 설정
메서드
- moveRight()
- 이동 속도만큼 함선의 X좌표를 오른쪽으로 이동
- moveLeft()
- 이동 속도만큼 함선의 X좌표를 왼쪽으로 이동
- boolean shoot(final Set bullets)
- 발사 여부에 따라 boolean 값 반환
- 발사 성공: true
- 발사 실패: false
- bullets: 화면 상에 있는 총알들의 리스트
- BulletPool.getBullet으로 아군 함선이 발사한 총알 객체 생성
- bullets 리스트에 추가
- 발사 여부에 따라 boolean 값 반환
- update()
- 함선 피격 상태라면
- spriteType을 피격된 함선으로
- 피격 상태가 아니라면
- spriteType을 그냥 함선으로
- 함선 피격 상태라면
- destroy()
- 피격되었다면 destructionCooldown을 초기화
- boolean isDestroyed()
- 피격된 상태인지 여부를 반환
- 총알을 맞고 1초동안은 피격된 상태임
- int getSpeed()
- 함선의 속도 반환
상수
- int INPUT_DELAY = 6000(6초)
- 게임 화면이 유저 입력을 받기까지 시간
- 이 시간을 기준으로 카운트 다운이 시작됨
- int LIFE_SCORE
- 레벨이 끝날 때 여분 목숨 하나당 추가 점수
- 예시) 목숨 3개로 스테이지 클리어 -> 100*2점 추가
- int BONUS_SHIP_INTERVAL = 20000(20초)
- 스페셜 함선의 발생 시간 간격
- int BONUS_SHIP_VARIANCE = 10000(10초)
- 스페셜 함선의 발생 시간 간격의 편차
- int BONUS_SHIP_EXPLOSION = 500(0.5초)
- 스페셜 함선의 폭발 애니메이션 지속 시간
- int SCREEN_CHANGE_INTERVAL = 1500(1.5초)
- 레벨이 끝나고(적 함선이 모두 파괴됨) 화면이 전환되기 까지의 시간
- int SEPARATION_LINE_HEIGHT
- 게임 내부에서 상단 초록색 가로줄의 y좌표
- 아군 총알이 이부분에 도달하면 끝에 도달한 것으로 판단
변수
- GameSettings gameSettings
- 생성할 때 인수로 입력받아 초기화 됨
- 이후 EnemyShipFormation에 인수로 넘겨짐
- int level
- 현재 게임의 level을 저장하는 변수
- EnemyShipFormation enemyShipFormation
- 적 함선의 집단 변수
- Ship ship
- 플레이어의 함선
- EnemyShip enemyShipSpecial
- 스페셜 함선
- Cooldown enemyShipSpecialCooldown
- 스페셜 함선의 등장 쿨다운
- Cooldown enemyShipSpecialExplosionCooldown
- 스페셜 함선의 폭발 애니매이션 쿨다운
- Cooldown screenFinishedCooldown
- 레벨 종료 후 화면 전환까지의 쿨다운
- Set bullets
- 화면 상에 존재하는 총알들의 집합
- int score
- 현재 점수
- int lives
- 현재 남은 목숨
- int bulletsShot
- 총 발사한 총알 수
- int shipsDestroyed
- 총 파괴한 함선 수
- long gameStartTime
- 게임이 시작한 시간
- boolean levelFinished
- 레벨이 종료되었는지 여부
- boolean bonusLife
- 보너스 라이프 지급 여부
생성자
- gameState와 gameSettings, width, height, fps 입력
- 값들을 모두 초기화
메서드
- initialize()
- enemyShipFormation 생성
- enemyShipFormation의 screen을 이 gameScreen으로 설정
- 아군 함선 생성
- 특별 함선 쿨다운 초기화후 시작
- 특별함선 폭발 쿨다운 초기화
- 스크린 종료 쿨다운 초기화
- bullets 집합 초기화
- 게임 시작 시간을 지금으로 설정
- inputDealy을 실행
- run()
- super.run()을 실행
- 이후 종료되면 남은 목숨과 LIFE_SCORE에 따라 점수 추가
- returnCode를 반환
- update(): 매 프레임마다 수행되는 작업
- 이동 및 총알 발사
- inputDelay가 끝났고, 레벨이 진행중일 때만 실행
- 함선이 멀쩡한 상태라면
- moveRight: 오른쪽키 or D키 눌려있으면 ture
- moveLeft: 왼쪽 키 or A키 눌려있으면 true
- isRightBorder: 아군 함선의 x좌표 + 함선의 너비 + 이동할때 가는 픽셀이 너비를 초과하는지
- isLeftBorder: 아군 함선의 x좌표 + 이동할 때 가는 위치가 1픽셀보다 작은지
- 오른쪽으로 가는 명령에 끝이 아니라면,
- 오른쪽으로 이동
- 왼쪽으로 가는 명령에 끝이 아니라면,
- 왼쪽으로 이동
- 스페이스 바가 눌려 있다면
- ship.shoot으로 총알 발사 해보고
- 발사가 되었다면 총 발사한 총알 수 +1
- inputDelay가 끝났고, 레벨이 진행중일 때만 실행
- manageCollision() 실행
- cleanBullets 실행
- draw()실행
- 레벨이 종료되었는지 확인(적 함선이 비어있거나, 목숨이 0)
- levelFinished를 true로 설정
- 스크린 종료 쿨다운 시작
- 레빌이 종료되었고 스크린 종료 쿨다운이 끝났다면
- 화면 실행 종료
- 이동 및 총알 발사
- draw()
- drawManager가 GameScreen을 그리도록 초기화
- 아군 함선 하나 그리기
- 스페셜 함선이 있다면,
- 스페셜 함선 그리기
- 적 함선 집단 그리기
- bullets(화면상의 총알들 리스트)에 있는 총알들 하나씩 그리기
- Score, Lives, HorizontalLine 그리기
- inputDelay 시간중이라면,
- INPUT_DELAY에서 현재 시간을 빼서 countdown 변수에 넣고
- countdown을 통해 drawCountDown 실행
- copleteDrawing을 통해 backBuffer에 있는 것을 한번에 그림
- cleanBullets()
- recyclable: 재활용할 총알들 모아두는 리스트
- bullets: 화면상에 있는 총알들
- bullets에서 하나씩 꺼내어 업데이트
- 만약 총알이 화면 밖에 나갔다면(상단 초록선 위로 갔거나, 하단으로 나갔거나)
- 재활용할 총알에 추가
- bullets에서 재활용할 총알들 전부 삭제
- BulletPool에 재활용할 총알들 전부 넣기
- manageCollisions()
- recyclable: 재활용할 총알들의 리스트
- bullets에서 총알을 하나씩 꺼내어 확인
- 적군 총알이면(Speed가 양수)
- 이 총알과 아군 함선의 collision이 확인 되고 레벨이 진행중이라면
- 총알을 재활용 가능한 총알에 추가
- 아군 함선이 안 부숴진 상태라면
- 함선을 파괴 상태로 전환
- 목숨 1감소
- 아군 함선이 안 부숴진 상태라면
- 아군 총알이면
- enemyShipFormation에서 적 함선 하나씩 꺼내어서 확인
- 적 함선이 부숴지지 않았는데, 이 총알과 부딛혔다면
- 적 함선의 점수만큼 점수에 추가
- 파괴한 함선 수 1 증가
- 그 적 함선을 파괴 처리
- 총알을 재활용에 추가
- 적 함선이 부숴지지 않았는데, 이 총알과 부딛혔다면
- 특별 함선이 나와있고, 파괴되어 있지 않고, 총알과 특별 함선이 부딛혔다면
- 특별 함선의 점수만큼 점수에 추가
- 파괴한 적 함선의 수 증가
- 특별 함선 파괴 처리
- 특별 함선의 파괴 애니매이션 쿨다운 시작
- 총알을 재활용 가능한 총알에 추가
- enemyShipFormation에서 적 함선 하나씩 꺼내어서 확인
- 적군 총알이면(Speed가 양수)
- 재활용 가능 총알을 bullets에서 모두 삭제
- BulletPool.recycle에 전부 추가
- checkCollision(개체 a, 개체 b): 두 개체간의 충돌 확인
- A와 B의 중심 좌표를 구함
- 두 객체의 닿기 직전의 거리를 구함
- 두 객체의 실제 거리를 구함
- X, Y 모두에서 두 객체의 거리가 닿기 직전의 거리보다 작다면 충돌이 일어난 것 -> true 반환
- getGameState
- 현재 게임 상태를 반환
- level
- score
- lives
- bulletsShot
- shipsDestroyed
개요
- 메인메뉴에서 HighScore 탭에 들어가면 나오는 화면
변수
- List highScores
- Score타입의 리스트
생성자
- 너비, 높이, fps 입력 받아 객체 생성
- returnCode=1로 설정
- highScores 변수를 fileManager를 통해 불러와서 저장
메서드
- run()
- 화면을 실행 시킴
- 실행이 종료되면 returnCode를 반환
- update()
- 매 프레임마다 수행되는 동작
- 화면을 그림(draw())
- 스페이스바가 눌렸고, 입력 쿨다운이 끝나있다면 화면 실행을 종료(isRunning=false)
- draw()
- initDrawing으로 이 화면에 그릴 준비를 함
- drawHighScoreMenu
- 설명 글 그리기
- drawHighScores
- highScores를 넘겨서
- 그 점수들 그리기
- completeDrawing
- backBuffer에 있던 내용을 실제로 그리기
개요
- 게임 종료 후 점수가 나오는 화면
상수
- int SELECTION_TIME = 200(0.2초)
- 입력 사이의 시간 간격
- int MAX_HIGH_SCORE_NUM = 7
- 최고 점수의 최대 개수
- int FIRST_CHAR = 65
- int LAST_CHAR = 90
- 신기록 입력시 사용할 이름의 첫 글자와 마지막 글자
변수
- int scroe
- 종료 점수
- int livesRemaining
- 남은 목숨
- int bulletsShot
- 총 발사한 총알 수
- int shipsDestroyed
- 총 파괴한 함선 수
- List highScores
- 점수들의 리스트
- boolean isNewRecord
- 종료 점수가 신기록인지 여부
- char[] name
- 기록에 입력할 플레이어 이름
- int nameCharSelected
- 이름에서 몇 번째 글자가 선택되었는지(0, 1, 2)
- Cooldown selectioncooldown
- 입력 사이의 시간 간격 쿨다운
생성자
- 너비, 높이, fps, gameState를 입력받음
- gameState의 정보로 score, livesRemaining, bulletsShot, shipsDestroyed 초기화
- isNewRecord=false로 초기화
- name = [‘A’, ‘A’, ‘A’]로 초기화
- nameCharSelected = 0으로 초기화
- selectionCooldown을 SELECTION_TIME으로 Cooldown 객체 생성 후 실행
- fileManager.loadHighScores를 통해 highScores를 불러옴
- highScore가 최대 신기록 수보다 작거나,
- highScore의 가장 작은 값보다 종료 점수가 큰 경우
- isNewRecord = true로 설정
메서드
- run()
- super.run()을 실행
- 종료되면 returnCode를 반환
- draw()
- initDrawing
- 이 화면에 그릴 준비
- drawGameOver
- 입력받을 준비 여부와 같이 넘김
- 입력 받을 준비가 되면 설명글을 초록색으로 해야하기 때문에
- drawResults
- 게임 종료 정보를 인자로 넘김
- 게임 정보를 그림
- if isNewRecord라면,
- drawNameInput
- 이름 입력 화면을 그림
- 현재 골라진 이름과, 현재 이름을 같이 넘긴다
- drawNameInput
- completeDrawing
- backBuffer에 있는 내용을 화면에 그린다
- initDrawing
- update(): 매 프레임마다 수행되는 작업들
- draw()
- 화면 요소들을 그린다
- 화면이 유저 입력 기다리는 시간이 끝났다면
- ESC키가 눌려있다면
- returnCode=1로 설정(메인메뉴)
- isRunning=false(화면 종료)
- 만약 신기록이라면
- saveScore로 기록 저장
- 스페이스바가 눌려있다면
- returnCode=2로 설정(재시작)
- isRunning=false (화면 종료)
- 만약 신기록이라면
- saveScore로 점수 저장
- 신기록이고, 입력 시간 사이 쿨다운이 돌았다면
- 오른쪽 방향키 입력시
- nameCharSelected를 다음 것으로 설정
- 0 > 1 > 2 > 0 …
- 입력 쿨다운 시작
- 왼쪽 방향키 입력시
- nameCharSelected를 이전 것으로 설정
- 0 > 2 > 1 > 0 …
- 입력 쿨다운 시작
- 위 방향키 입력시
- name에서 선택된 글자에 하나 위 글자 입력
- 마지막 글자였다면, 첫 번째 글자 입력
- 아니라면, 현재 글자 + 1 입력
- 입력 쿨다운 시작
- 아래 방향키 입력시
- name에서 선택된 글자에 하나 아래 글자 입력
- 첫 번째 글자였다면, 마지막 글자 입력
- 아니라면, 현재 글자 - 1 입력
- 입력 쿨다운 시작
- 오른쪽 방향키 입력시
- ESC키가 눌려있다면
- draw()
- saveScore()
- highScores(loadHighScores를 통해 불려옴)리스트에 종료된 기록 추가 후 정렬
- highScores가 최대 신기록 개수를 넘어가면
- 가장 마지막 기록을 삭제
- fileManager를 통해 업데이트된 highScores를 파일로 저장
상수
- int INPUT_DELAY = 1000(1초)
- 화면이 입력을 받아들이기까지의 시간
인스턴스
- drawManager
- inputManager
- logger
변수
- int width
- int height
- 화면의 크기
- int fps
- 화면의 fps
- Insets insets
- 화면의 상하좌우 여백
- Cooldown inputDelay
- 화면이 입력을 받아들이는 쿨다운
- boolean isRunning
- 화면이 실행중인지 여부
- int returnCode
- 화면이 종료되면 다음에 넘어갈 화면의 코드
생성자 입력: 너비, 높이, fps
- 입력받은 너비, 높이 , fps로 초기화
- drawManager, inputManager, logger를 Core의 것으로 초기화
- inputDelay 쿨다운 객체를 INPUT_DELAY 값으로 초기화 후 reset
- returnCode=0으로 초기화
메서드
- run()
- isRunning = true로 변경
- isRunning인 동안 while문 실행
- time을 현재 시간으로 저장
- 화면 업데이트
- —————— 여기까지 1/fps 의 시간보다 짧게 걸렸다면, 나머지 시간을 재움
- 결론적으로 한 번의 while문은 최소 1/fps 초만큼 시간이 걸림
- isRunning이 false가 되면 0을 return하고 종료
- update()
- 상속해서 사용
- getWidth
- getHeight
- 너비와 높이 반환
개요
- 메인 메뉴 화면
상수
- int SELECTION_TIME = 200(0.2초)
- 입력 사이의 시간 간격 변수
- Cooldown selectionCooldown
- 입력 사이의 시간 간격 쿨다운
생성자
- 너비, 높이, fps 입력받아 super의 것으로 초기화
- returnCode=2
- 입력 사이 간격 쿨다운 설정 후 시작
메서드
- draw
- initDrawing
- 이 화면에 그릴 준비 시작
- drawTitle
- 타이틀과 설명글 그리기
- drawMenu
- 이 화면의 returnCode를 넘겨서 선택된 메뉴를 초록색으로 표시
- completeDrawing
- backBuffer에 있는 내용을 한 번에 그리기
- initDrawing
- nextMenuItem()
- returnCode를 다음 메뉴 숫자로 바꾸기(3 > 0 > 2 > 3 …)
- previousMenuItem()
- returnCode를 이전 메뉴 숫자로 바꾸기 (0 > 3 > 2 > 0 …)
- update()
- draw를 한 번 한다
- 입력 간격 쿨다운이 다 돌고, 입력 쿨다운이 다 돌았을 때
- 위 방향키 or W키 눌려있으면
- previousMenuItem 실행
- 입력 간격 쿨다운 시작
- 아래 방향키 or S키 눌려 있으면
- nextMenuItem 실행
- 입력 간격 쿨다운 시작
- 스페이스바 눌렸으면
- isRunning = false로 설정
- 바로 다음 프레임에서 이 창이 닫히고 returnCode가 반환됨
- 위 방향키 or W키 눌려있으면
returnCode
- play: 2
- High Scores: 3
- Exit: 0
- 메인 화면: 1