Jump

GitHub 소스 바로가기

이전 공룡게임에서는 점프를 할때 선형계산을 하여 처리하였습니다.
이번장에서는 중력공식을 이용하여 좀더 실감나는 점프를 구현해 보겠습니다.
또한 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 좌표를 움직여주는 메서드 추가, 점프하는 것
..........

또 다시 멋진 게임이 하나 탄생했습니다.

평점을 남겨주세요
평점 : 2.5
총 투표수 : 1