코드 분석 - HY-CtrlS/Invaders-SDP GitHub Wiki

engine

Cooldown

개요

  • 게임에서의 쿨타임과 같은 역할을 하는 클래스

변수

  • int milliseconds
    • 쿨타임 지속 시간
  • int variance
    • 쿨타임의 변동성
  • int duration
    • 변동성이 추가된 최종 지속시간
  • long time
    • 쿨다운의 시작 시간(시스템 시간)

생성자 1 milliseconds만 받음

  • 변동성은 0으로 초기화
  • 따라서 duration은 그냥 milliseconds가 됨

생성자 2 milliseconds와 variance 둘 다 받음

  • duration은 정해지지 않음

메서드

  • checkFinished
    • 쿨다임이 다 돌았는지 여부를 반환
      • 쿨타임에 기록된 시작시간과 현재 시간을 비교
      • 시작시간에 쿨타임을 더한 시간이 지금 시간보다 작다면, 쿨타임이 다 돈 것
  • reset
    • 쿨타임 객체의 시간을 reset을 수행한 시간으로 저장(시작)
    • 변동성이 있다면, 변동성에 따라 랜덤하게 duration 설정

Core

상수

  • 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
      • 3인 경우(최고 기록 화면)
        • 최고기록 화면을 생성해 currentScreen으로 설정
        • frame.setScreen으로 최고기록 화면 실행
        • 실행 종료되면 returnCode를 받음
        • break
      • returnCode가 0이 발생한 경우
        • while문을 탈출
        • 버퍼에 있는 모든 로그 데이터를 파일에 기록
        • fileHandler를 닫음
        • 프로그램 종료
  • Logger, DrawManager, InputManager, FileManager, Cooldown, VariableCooldown getter 관리

DrawManager

생성자

  1. fileManager, logger를 Core의 것으로 초기화
  2. spriteMap을 만들고, boolean 배열의 값들을 fileManager.loadSprite()를 통해 초기화
  3. 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 (스크린, 스코어 목록)  스코어 목록에서 이름과 점수를 받아 그리기

FileManager

생성자

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개까지만 파일에 점수로 작성하고 저장

Frame

JFrame을 상속함

속성

  • int width
  • int height
  • Screen currentScreen

생성자(width, height) 1.

  • 창의 크기(입력받은 크기)
  • 크기 조절 여부
  • 창의 위치
  • 최소화 여부
  • 제목 을 설정함
  1. width와 height를 여백 제거해서 다시 저장
  2. KeyListener를 InputManager로 설정

setScreen(screen)

  • screen을 입력받아, 그것을 currentScreen으로 지정
  • currentScreen을 초기화
  • currentScreen 실행

GameSettings

개요

  • 적 함선 집단의 설정을 모아놓은 클래스

필드

  • int formationWidth
    • 가로로 몇 개의 함선이 있는지
  • int formationHeight
    • 세로로 몇 개의 함선이 있는지
  • int baseSpeed
    • 집단의 기본 이동 속도
  • int shootingFrecuency
    • 집단의 총알 발사 빈도

생성자

  • 필드를 입력받아 초기화

매서드

  • 필드들의 getter

GameState

개요

  • 레벨의 정보를 저장하는 클래스

필드

  • int level
    • 현재 게임 레벨
  • int score
    • 현재 스코어
  • int livesRemaning
    • 현재 남은 목숨
  • int bulletsShot
    • 지금까지의 총알 발사 횟수
  • int shipsDestryed
    • 지금까지 부순 함선 수

생성자

  • 필드를 입력받아 초기화

매서드

  • 필드들의 getter

InputManager

개요

  • 키보드의 입력을 관리하는 클래스
  • 싱글톤 클래스

상수

  • final int NUM_KEYS = 256
    • 인식 가능한 키의 수
    • 키 배열의 크기 속성
  • boolean[] keys
    • 인덱스에 해당하는 키가 눌려있으면 true값을 가지는 배열
  • InputManager instance
    • 클래스의 싱글톤 인스턴스

생성자

  • private 생성자
  • keys 배열을 NUM_KEYS의 크기를 갖는 boolean 배열로 초기화

메서드

  • getInstance
    • 객체가 생성되어있으면 그걸 반환
    • 없으면 새로 생성 후 반환
  • isKeyDown(keyCode)
    • keyCode에 해당하는 키가 눌려있는지 여부를 반환

MinimalFormatter

개요

  • 로그에 작성할 포맷에 맞는 String 생성

속성

  • DateFormat FORMAT = new SimpleDateFormat(“h:mm:ss”)
    • 시, 분, 초 형식의 포맷을 지정해주는 formater
  • String LINE_SEPARATOR
    • 개행 문자를 저장
    • Windows에선 \r, \n이 될 수 있음
    • 유닉스/ 리눅스 / 맥에선 \n이 됨
    • 어느 운영체제에서든 호환 가능하도록 함

생성자

  • 기본 생성자

메서드

  • format(logRecord)
    • logRecord의 정보로 로그에 찍힐 한 줄을 작성함
    • 문자 끝엔 공백 문자 하나와 개행 문자가 들어감

Score

  • Score 클래스는 String 타입의 이름과 int 타입의 점수를 속성으로 갖는다.
  • 생성될 때 이름과 점수를 받아 초기화를 하고, 이는 수정 불가능하다.
  • 이름과 점수엔 getter만 존재한다.

compareTo()

  • 또 다른 Score 타입을 입력받아 두 Score를 비교한다.
  • A.compareTo(B)
    • A < B: 1
    • A > B: -1
    • A == B: 0

entity

##Bullet

개요

  • Entity 클래스를 상속하는 총알의 개체

속성

  • int speed
    • 총알의 속도
    • 클 수록 빠름

생성자

  • 위치, 속도를 입력받음(크기와 색상은 정해져 있음)
  • 속도를 속도로 설정
  • 속도에 따라 SpriteType을 결정(위로가면 아군꺼, 아래로 가면 적꺼)

메서드

  • setSprite()
    • 속도가 음수 -> 위로 가면
      • spriteType을 Bullet으로(아군)
    • 속도가 음수가 아님 -> 아래로 가면
      • spriteType을 EnemyBullet(적군)
  • update()
    • 총알의 y좌표를 speed에 따라 업데이트
  • setSpeed()
    • 총알의 속도 설정
  • getSpeed()
    • 총알의 속도 반환

BulletPool

개요

  • 총알 객체(Bullet)를 관리하는 풀
  • Static 메서드와 Static 필드만 있어 인스턴스를 생성할 필요가 없음

속성

  • Set pool
    • 총알들의 집합인 pool 속성
    • 중복된 총알 객체가 추가되지 않음을 보장

생성자

  • private이므로 외부에서 이 클래스를 생성할 수 없음

메서드

  • getBullet(x좌표, y좌표, 속도)
    • 재사용 가능한 pool에 총알이 있다면
      • 그 총알을 bullet에 저장, pool에서 제거
      • bullet을 입력받은 위치와 속도로 설정
      • 속도에 따라 spriteType을 설정
    • pool에 총알이 없다면
      • 새로운 bullet을 생성한 뒤 초기화
    • 이후 bullet을 반환
  • recycle
    • 총알 집합을 입력받아, 그걸 pool에 추가함

EnemyShip

개요

  • 적함선 개체를 만드는 클래스

상수

  • 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 모양으로
  • destroy
    • 함선 파괴
    • isDestroyed=true로 설정
    • spriteType을 Explosion으로 설정
  • isDestroyed
    • 파괴 여부를 반환

EnemyShipFormation

개요

  • 적군 우주선의 집단을 관리하는 클래스

상수

  • 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을 입력으로 받음
  1. drawManager, logger를 Core의 것으로 초기화
  2. 이동 방향 오른쪽으로 초기화
  3. movementInterval = 0 으로 초기화
  4. 집단의 함선 수를 gameSettings대로 초기화
  5. 발사 간격과 변동성 초기화
  6. 집단의 기본 속도를 gameSetting대로 초기화
  7. 현재 이동속도를 기본 속도로 초기화
  8. 집단의 위치 초기화
  9. enemyShips 2차원 배열에 실제 함선들 객체 생성(함선 종류 비율에 따라
  10. 함선 하나의 크기 초기화
  11. 집단 전체의 크기 초기화
  12. 각 열의 가장 마지막에 있는 함선으로 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에서 한 열씩 검사
          • 한 열에서 하나의 함선씩 꺼내어 검사
            • 함선이 파괴되었다면, 파괴된 함선 리스트에 추가
          • 파괴된 함선 리스트에 있는 함선을 열에서 제거
      • 집단의 모든 함선을 이동시키고 업데이트
  • 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 반환
      • 찾은 경우 그 함선의 객체 반환
  • isEmpty
    • 집단이 비어있는지 여부 반환

Entity

  • Bullet, Ship, EnemyShip의 상위 클래스

  • 위치(positionX, positionY)

  • 개체의 크기(width, height)

  • 색상

  • spriteType

Ship

개요

  • 아군 함선의 개체

상수

  • 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 리스트에 추가
  • update()
    • 함선 피격 상태라면
      • spriteType을 피격된 함선으로
    • 피격 상태가 아니라면
      • spriteType을 그냥 함선으로
  • destroy()
    • 피격되었다면 destructionCooldown을 초기화
  • boolean isDestroyed()
    • 피격된 상태인지 여부를 반환
    • 총알을 맞고 1초동안은 피격된 상태임
  • int getSpeed()
    • 함선의 속도 반환

screen

GameScreen

상수

  • 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
    • 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 증가
            • 그 적 함선을 파괴 처리
            • 총알을 재활용에 추가
        • 특별 함선이 나와있고, 파괴되어 있지 않고, 총알과 특별 함선이 부딛혔다면
          • 특별 함선의 점수만큼 점수에 추가
          • 파괴한 적 함선의 수 증가
          • 특별 함선 파괴 처리
          • 특별 함선의 파괴 애니매이션 쿨다운 시작
          • 총알을 재활용 가능한 총알에 추가
    • 재활용 가능 총알을 bullets에서 모두 삭제
    • BulletPool.recycle에 전부 추가
  • checkCollision(개체 a, 개체 b): 두 개체간의 충돌 확인
    • A와 B의 중심 좌표를 구함
    • 두 객체의 닿기 직전의 거리를 구함
    • 두 객체의 실제 거리를 구함
    • X, Y 모두에서 두 객체의 거리가 닿기 직전의 거리보다 작다면 충돌이 일어난 것 -> true 반환
  • getGameState
    • 현재 게임 상태를 반환
    • level
    • score
    • lives
    • bulletsShot
    • shipsDestroyed

HighScoreScreen

개요

  • 메인메뉴에서 HighScore 탭에 들어가면 나오는 화면

변수

  • List highScores
    • Score타입의 리스트

생성자

  • 너비, 높이, fps 입력 받아 객체 생성
  • returnCode=1로 설정
  • highScores 변수를 fileManager를 통해 불러와서 저장

메서드

  • run()
    • 화면을 실행 시킴
    • 실행이 종료되면 returnCode를 반환
  • update()
    • 매 프레임마다 수행되는 동작
    • 화면을 그림(draw())
    • 스페이스바가 눌렸고, 입력 쿨다운이 끝나있다면 화면 실행을 종료(isRunning=false)
  • draw()
    • initDrawing으로 이 화면에 그릴 준비를 함
    • drawHighScoreMenu
      • 설명 글 그리기
    • drawHighScores
      • highScores를 넘겨서
      • 그 점수들 그리기
    • completeDrawing
      • backBuffer에 있던 내용을 실제로 그리기

ScoreScreen

개요

  • 게임 종료 후 점수가 나오는 화면

상수

  • 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
        • 이름 입력 화면을 그림
        • 현재 골라진 이름과, 현재 이름을 같이 넘긴다
    • completeDrawing
      • backBuffer에 있는 내용을 화면에 그린다
  • 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 입력
          • 입력 쿨다운 시작
  • saveScore()
    • highScores(loadHighScores를 통해 불려옴)리스트에 종료된 기록 추가 후 정렬
    • highScores가 최대 신기록 개수를 넘어가면
      • 가장 마지막 기록을 삭제
    • fileManager를 통해 업데이트된 highScores를 파일로 저장

Screen

상수

  • 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
    • 너비와 높이 반환

TitleScreen

개요

  • 메인 메뉴 화면

상수

  • int SELECTION_TIME = 200(0.2초)
    • 입력 사이의 시간 간격 변수
  • Cooldown selectionCooldown
    • 입력 사이의 시간 간격 쿨다운

생성자

  • 너비, 높이, fps 입력받아 super의 것으로 초기화
  • returnCode=2
  • 입력 사이 간격 쿨다운 설정 후 시작

메서드

  • draw
    • initDrawing
      • 이 화면에 그릴 준비 시작
    • drawTitle
      • 타이틀과 설명글 그리기
    • drawMenu
      • 이 화면의 returnCode를 넘겨서 선택된 메뉴를 초록색으로 표시
    • completeDrawing
      • backBuffer에 있는 내용을 한 번에 그리기
  • nextMenuItem()
    • returnCode를 다음 메뉴 숫자로 바꾸기(3 > 0 > 2 > 3 …)
  • previousMenuItem()
    • returnCode를 이전 메뉴 숫자로 바꾸기 (0 > 3 > 2 > 0 …)
  • update()
    • draw를 한 번 한다
    • 입력 간격 쿨다운이 다 돌고, 입력 쿨다운이 다 돌았을 때
      • 위 방향키 or W키 눌려있으면
        • previousMenuItem 실행
        • 입력 간격 쿨다운 시작
      • 아래 방향키 or S키 눌려 있으면
        • nextMenuItem 실행
        • 입력 간격 쿨다운 시작
      • 스페이스바 눌렸으면
        • isRunning = false로 설정
        • 바로 다음 프레임에서 이 창이 닫히고 returnCode가 반환됨

returnCode

  • play: 2
  • High Scores: 3
  • Exit: 0
  • 메인 화면: 1
⚠️ **GitHub.com Fallback** ⚠️