실감나는 게임 만들기! Class와 중력공식을 이용한 Jump 구현
Jump
이전 공룡게임에서는 점프를 할때 선형계산을 하여 처리하였습니다.
이번장에서는 중력공식을 이용하여 좀더 실감나는 점프를 구현해 보겠습니다.
또한 Class 에 대해 알아보면서 좀더 확장성 있는 프로그램에 대해 알아 보겠습니다.
점프할때의 위치 좌표 공식
F = 1/2 * m * v^2
- F = Force (위/아래 힘)
- m = mass (물체의 질량)
- v = velocity (속도)
클래스(Class)란 무엇인가
클래스란 함수의 집합입니다. 함수의 사용이 코드의 재사용 이었던 것처럼 클래스도 이와 동일합니다.
객체(Object), 인스턴스, 상속이라는 개념이 나오는데 이 부분은 별도의 문법에서 다루고 현재는 간단한 사용법만을 다루도록 하겠습니다.
[문법] Class 정의
class Car:
    def __init__(self):  # __init__ 를 생성자라고 한다.
                         # 생성자는 객제생성시 자동으로 호출(실행)되어지는 부분을 말한다.
        .............
    
    def func1(self):  # 클래스 내부에 함수가 들어오면 메소드(method)라고 일컽는다.
        .............
        
    def func2(self):
        .............
[문법] Class 호출
carObj = Car()  # 위에 정의된 Car()를 호출함으로서 carObj 라는 객체(Object)를 생성한다.
                # carObj는 Object이고 carObj는 Car()의 인스턴스이다.
carObj.func1()
[문법] 전역변수, 지역변수
변수에는 전역변수와 지역변수가 있습니다.
지역변수는 함수내에서만 사용하는 것이고 전역변수는 다른 함수에서도 사용가능한 것입니다.
[게임코드] 기본 구성
import sys
import pygame
# 게임 화면 크기
screen = None
screen_width = 800
screen_height = 500
# 색상
WHITE = (255, 255, 255)
class Car:
    def __init__(self):
        pass
def main():
    global screen, screen_width, screen_height  # 전역변수 설정
    # pygame 초기화 및 스크린 생성
    pygame.init()
    screen = pygame.display.set_mode((screen_width, screen_height))
    pygame.display.set_caption("Jump Test")
    clock = pygame.time.Clock()
    player = Car()  # 플레이어 자동차 생성
    playing = True
    while playing:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                playing = False
                pygame.quit()
                sys.exit()
        screen.fill(WHITE)  # 배경색을 흰색으로
        pygame.display.flip()
        clock.tick(60)  # 초당 60번 실행
if __name__ == '__main__':
    main()
구글공룡게임 과 비슷한 모습이다.
차이가 있다면 class를 정의한 것만이 다르다.
이제 자동차를 디스플레이 해 보자
[문법] self
self는 Class 내의 전역변수이다. self로 정의되어 있으면 class내의 어디에서나 self.변수명 으로서 호출 가능하다.
[게임코드] 자동차 화면에 디스플레이하기
class Car:
    def __init__(self):
        self.image = None
        self.rect = None
        
    def load_car(self):  # 자동차 이미지를 불러와 위치를 정한다.
        # 플레이어 차량
        self.image = pygame.image.load("assets/images/smallcar.png")
        # 크기 조정
        self.image = pygame.transform.scale(self.image, (150, 57))
        self.rect = self.image.get_rect()
        self.rect.bottom = screen_height
    def draw_car(self):  # 자동차를 스크린에 그리기
        screen.blit(self.image, [self.rect.x, self.rect.y])
..........
def main():
    ..........
    player = Car()  # 플레이어 자동차 생성
    player.load_car()  # 자동차 이미지 로드
    ..........
    while playing:
        ..........
        player.draw_car()  # 자동차를 그린다.
        ..........
이제 우리가 원하는 자동차가 화면상에 나타날 것이다.
이제 키보드 입력을 통해 좌우로 움직이게 구성해 보자.
[게임코드] 자동차 움직이기
class Car:
    def __init__(self):
        ..........
        self.dx = 0
    ..........
    # x 좌표 이동 - 플레이어 자동차의 움직임 제어할 때 필요
    def move_x(self):
        self.rect.x += self.dx
def main():
    ..........
    while playing:
        for event in pygame.event.get():
            ..........
            if event.type == pygame.KEYDOWN:  # 방향키를 눌렀을 경우 자동차의 위치를 바꾼다.
                if event.key == pygame.K_RIGHT:
                    player.dx = 5
                elif event.key == pygame.K_LEFT:
                    player.dx = -5
        ..........
        player.move_x()
..........
어라! 자동차가 멈추지 않고 화면 밖으로 나가번린다.
[게임코드] 자동차 멈추기 및 화면 밖으로 나가지 않게 처리하기
- 자동차 멈추기 기능 : 키보드에서 손을때면 화면 멈추기
- 화면밖으로 자동차 나가지 않게 하기
class Car:
    ..........
    def check_screen(self):  # 화면 밖으로 못 나가게 방지
        if self.rect.right > screen_width or self.rect.x < 0:
            self.rect.x -= self.dx
        if self.rect.bottom > screen_height or self.rect.y < 0:
            self.rect.y -= self.dy
def main():
    ..........
    while playing:
        for event in pygame.event.get():
            ..........
                    
            if event.type == pygame.KEYUP:  # 방향키에서 땔 경우 자동차를 멈춘다.
                if event.key == pygame.K_RIGHT:
                    player.dx = 0
                elif event.key == pygame.K_LEFT:
                    player.dx = 0
        ..........
        player.check_screen()  # 화면밖으로 나가지 않게 처리
..........
    
[게임코드] 점프
- 스페이스 바를 눌렀을때 자동차 점핑 기능 구현
..........
# 속도와 질량 기본 값
VELOCITY = 7  # 속도
MASS = 2  # 질량
class Car:
    def __init__(self):
        ..........
        self.dy = 0
        self.isJump = 0  # 바닥(0), 점프중 (1), 이중점프(2)
        self.v = VELOCITY  # 속도
        self.m = MASS  # 질량
    ..........
    
    def jump(self, j):  # 점프상태 변경
        self.isJump = j
        
    def doJump(self):
        # isJump 값이 0보다 큰지 확인
        if self.isJump > 0:
            # isJump 값이 2일 경우 속도를 리셋
            # 점프 한 상태에서 다시 점프를 위한 값
            # 이 코드를 주석처리하면 이중점프를 못한다.
            if self.isJump == 2:
                self.v = VELOCITY
            # 역학공식 계산 (F). F = 0.5 * mass * velocity^2.
            if self.v > 0:
                # 속도가 0보다 클때는 위로 올라감
                F = (0.5 * self.m * (self.v * self.v))
            else:
                # 속도가 0보다 작을때는 아래로 내려감
                F = -(0.5 * self.m * (self.v * self.v))
            # 좌표 수정 : 위로 올라가기 위해서는 y 좌표를 줄여준다.
            self.rect.y -= round(F)
            # 속도 줄여줌
            self.v -= 1
            # 바닥에 닿았을때, 변수 리셋
            if self.rect.bottom > screen_height:
                self.rect.bottom = screen_height
                self.isJump = 0
                self.v = VELOCITY
def main():
    ..........
    while playing:
        keys = pygame.key.get_pressed()  # 키가 눌린 상태 체크
        # 스페이스키가 눌려있고, isJump가 2라면 1로 변경한다.
        # 이 작업을 해주지 않으면 스페이스가 눌려있는 상태면 플레이어가 계속 위로 올라가게 된다.
        if (keys[pygame.K_SPACE]):
            if player.isJump == 2:
                player.jump(1)
        for event in pygame.event.get():
            ..........
                    
                # 스페이스키를 눌렀을 때,
                # 0이면 바닥인 상태 : 1로 변경
                # 1이면 점프를 한 상태 : 2로 변경, 점프한 위치에서 다시 점프를 하게 된다. 즉, 이중점프
                if event.key == pygame.K_SPACE:
                    if player.isJump == 0:  # 자동차가 바닥에 있으면
                        player.jump(1)
                    elif player.isJump == 1:  # 현재 점핑 중일 경우
                        player.jump(2)
                    
        ..........
        player.doJump()  # 플레이어의 y 좌표를 움직여주는 메서드 추가, 점프하는 것
..........
또 다시 멋진 게임이 하나 탄생했습니다.