본문 바로가기

대학교 게임 개발 포트폴리오/1학년 1학기

1학년 1학기 웹파이썬 프로그래밍 텀프로젝트 게임 개발기 - 1

파이썬, 파이게임을 이용한 게임을 개발하였습니다.

과제 제출을 완료하였지만 보완하면 좋을 점이 많기에 보완할 점들을 보완하여 완료 시까지 추가로 업데이트 할 예정이며,

현재 개발 완료된 기능과 코드를 보여드리겠습니다.

 

 

실제 게임 플레이 영상

위의 영상은 실제 게임 플레이 영상입니다.

 

 

 

인게임 화면을 통해 기능에 대해 소개하겠습니다.

① 왼쪽위에 플레이 시간을 표기합니다.

② 플레이어 x 좌표는 고정되어있으며, y좌표는 ↑↓ 방향키를 통해 컨트롤 가능합니다.

③ 하늘을 나는 적들로, y[0~600]사이에 랜덤으로 스폰됩니다.

④ 바닥을 걷는 적들로, y[700]에서만 움직입니다.

  • 배경은 왼쪽에서 오른쪽으로 움직이며, 플레이어가 적과 충돌할 경우 화면 가운데에 GAMEOVER 멘트 출력 후 2초후 게임 창은 꺼집니다.

깃허브에 전체 코드와 이미지가 업로드 되어 있습니다.

https://github.com/DoJiSeon/1-1_webpython_termproject

 

 

 

 

코드를 설명 드리겠습니다. 저는 수업시간에 배운 클래스와 여러 자료들을 이용하여 코드를 작성했습니다.

 

 

파이게임 제작 시 가장 먼저 오는 코드를 소개하겠습니다.

import pygame # 1. pygame 선언
import random
pygame.init() # 2. pygame 초기화
pygame.display.set_caption("다람쥐의 모험")


flying_enemies = []
walking_enemies = []
player_walk = [pygame.image.load('sprite\squirrel\walk1.png'),pygame.image.load('sprite\squirrel\walk2.png'),
               pygame.image.load('sprite\squirrel\walk3.png'),pygame.image.load('sprite\squirrel\walk4.png'),
               pygame.image.load('sprite\squirrel\walk5.png'),pygame.image.load('sprite\squirrel\walk6.png'),
               pygame.image.load('sprite\squirrel\walk7.png'),pygame.image.load('sprite\squirrel\walk8.png')]
enemy1_move = [pygame.image.load('sprite\enemy1\img2.png'),pygame.image.load('sprite\enemy1\img4.png'),
               pygame.image.load('sprite\enemy1\img6.png'),pygame.image.load('sprite\enemy1\img8.png'),
               pygame.image.load('sprite\enemy1\img10.png'),pygame.image.load('sprite\enemy1\img14.png'),
               pygame.image.load('sprite\enemy1\img14.png'),pygame.image.load('sprite\enemy1\img16.png')]

1~2번 코드에서 파이게임과 랜덤 모듈을 임포트 합니다.

3번줄 에서 파이게임을 초기화 한 후,

4번 줄에서 게임 실행 창의 이름을 정하여 넣어줍니다.

7~8번 줄에 하늘을 날아다니는 적과, 땅을 걸어다니는 적을 넣을 리스트를 생성합니다.

9~16번 줄에서는 캐릭터와 적 애니메이션에 이용할 이미지들을 리스트 형태로 저장합니다.

 

 

 

그 다음 이 게임에서 필요한 클래스들을 생성합니다. 먼저 게임에서 제일 중요한

플레이어 클래스를 생성합니다.

class Player(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        
        self.image = pygame.image.load('sprite\squirrel\walk1.png')
        self.image = pygame.transform.scale(self.image, (100, 100)) # 넓이, 높이
        self.rect = self.image.get_rect()
        self.rect.centerx = player_posX
        self.rect.centery = player_posY
        self.walkcount = 0
        
    def get_rect(self):
        return self.rect
    
    def plus_walk_point(self):
        self.walkcount += 1
        if self.walkcount == 8:
            self.walkcount = 0
            self.image = player_walk[self.walkcount]
        else:
            self.image = pygame.transform.scale(self.image, (100,100))
            self.image = player_walk[self.walkcount]

19번 메소드는 클래스 생성시 초기 값을 넣어줄 수 있는 메소드 입니다. 생성 시 자동으로 실행됩니다.

20번 줄은 무조건 넣어주어야 합니다!!

22번 self.image = 플레이어의 이미지 나타내는 변수

23번 위에서 self.image에 넣어준 사진의 크기가 제각기 다를 수 있기 때문에 넓이와 높이를 100,100으로 지정합니다.

24번 self.rect = 플레이어의 위치 보관하는 변수입니다. 이미지의 위치 값을 받아옵니다.
25~26번 self.rect.centerx, self.rect.centery = 플레이어의 위치를 (사진)이미지의 위치에 넣어줍니다.
27번 self.walkcount = 순차적으로 1씩 변해 player_walk 리스트의 플레이어 이미지를 가져옵니다. 초기 설정값은 0으로 맞추어 둡니다.
29~30번 get_rect() = 현재 플레이어의 위치를 리턴해주는 함수 입니다. 
32~33번 plus_walk_point() = walkcount를 1씩 추가 합니다.

34~36번 player_walk의 리스트 수(8)를 넘어가면 다시 0으로 초기화한 후, self.image에 player_walk[self.walkcount] 값을 넣어줍니다.

37~39번 리스트 범위를 넘어가지 않을 경우 walkcount의 값에 따라 이미지를 바꿔줍니다.

 

 

다음으로 날아다니는 적 객체를 생성하기 위해

FlyingEnemy 클래스를 만듭니다.

class FlyingEnemy(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.FlyingEnemy_x = screen_width
        self.FlyingEnemy_y = random.randrange(0,7)*100
        self.x = screen_width
        enemy1 = pygame.image.load('sprite\enemy1\img2.png')
        enemy1 = pygame.transform.scale(enemy1,(100,100))
        enemy2 = pygame.image.load('sprite\enemy2\img2.png')
        enemy2 = pygame.transform.scale(enemy2,(100,100))
        enemy3 = pygame.image.load('sprite\enemy3\img2.png')
        enemy3= pygame.transform.scale(enemy3,(100,100))
        enemy4 = pygame.image.load('sprite\enemy4\img2.png')
        enemy4 = pygame.transform.scale(enemy4,(100,100))
        flying_enemies.append(enemy1)
        flying_enemies.append(enemy2)
        flying_enemies.append(enemy3)
        flying_enemies.append(enemy4)
        self.random_num = random.randrange(0,4)
        self.image = flying_enemies[self.random_num]
        self.image = pygame.transform.scale(self.image,(100,100))
        self.rect = self.image.get_rect()
        self.rect.centerx = self.FlyingEnemy_x
        self.rect.centery = self.FlyingEnemy_y
        
        # 적 이미지 랜덤 변경
    def change_flyingEnemy(self):
        random.shuffle(flying_enemies)
        self.image = flying_enemies[0]
        # 적 이미지 움직이기
    def randomSpeed(self):
        self.x -= random.randrange(45,95) # enemy의 속도를 랜덤으로 조절 -> 적들이 불규칙적으로 등장하도록 한다.
        self.FlyingEnemy_x = self.x
        
        # 적이 화면 끝에 도달하면 위치 초기화
    def returnAndreset(self):
        self.FlyingEnemy_x = screen_width
        self.FlyingEnemy_y = random.randrange(0,7)*100
        
        # 적의 현재 x 좌표 넘기기
    def get_pos(self):
        return self.x
        
        # 적 그리기
    def draw_flyingEnemy(self):
        screen.blit(self.image,(self.FlyingEnemy_x,self.FlyingEnemy_y))
        
    def check_enemy_position(self):
        if self.FlyingEnemy_x <= 0 :
            self.return_enemy()
        else:
            screen.blit(self.image,(self.FlyingEnemy_x,self.FlyingEnemy_y))
            
    def return_enemy(self):
        self.x = 1600
        self.FlyingEnemy_y = random.randrange(0,7)*100
        random.shuffle(flying_enemies)
        self.image = flying_enemies[0]
        
    def get_rect(self):
        return self.rect

42~43번 __init__메소드를 이용해 클래스의 초기값을 설정합니다.

44번 self.FlyingEnemy_x = 적의 위치를 화면의 오른쪽 끝으로 선언 해줍니다.
45번 self.FlyingEnemy_y = 적의 위치를 화면 안, 바닥에서 100 정도 띄어진 위치에 랜덤 선언해줍니다.
46번 self.x = 적의 위치를 계산하는 변수, 적의 위치는 처음에는 화면 맨 오른쪽 끝으로 설정해줍니다.
47~54번 enemy1~4 = 날아다니는 적의 스프라이트들을 변수에 넣어 준 후, 크기를 (100,100)으로 일정하게 만듭니다.
55~58번 위에서 생성한 날아다니는 적 리스트에 넣어줍니다. 

59번 self.random_num = 랜덤으로 수를 생성해 flying_enemies 리스트 안의 적을 고르는 변수입니다.

60번 위에서 랜덤으로 생성한 수를 이용해 리스트 안에서 랜덤한 이미지를 골라 self.image에 넣어줍니다.

61번 그 후 이미지의 크기를 (100,100)으로 일정하게 바꿉니다.

62~64번 이미지의 위치를 받아와 이 객체의 위치에 넣어줍니다.

67~69번 change_flyingEnemy()메소드는 flying_enemies 리스트를 섞고, self.image에 새로운 적 이미지를 넣습니다.
71~73번 randomSpeed()메소드는 랜덤으로 45~95 사이의 숫자를 생성하고, self.x 에 랜덤값을 빼서 적의 x 좌표가 움직이도록 한다. (속도를 조절하는 함수입니다. 적 객체들이 각각 다른 속도값을 가지도록 해줍니다.)
76~78번 returnAndreset()메소드는 객체의 x,y좌표값을 초기값으로 바꿔주는 함수입니다. self.FlyingEnemy_x의 값을 화면 끝으로 재설정 하고, self.FlyingEnemy_y 랜덤으로 재설정합니다.
81~82번 get_pos()메소드는 현재 적의 x 좌표값을 리턴해줍니다.
85~86번 draw_flyingEnemy()메소드는 현재 적의 self.image, self.FlyingEnemy_x, self.FlyingEnemy_y 값을 이용하여 화면에 그려줍니다.
88~92번 check_enemy_position()메소드는 만약 self.FlyingEnemy_x의 x좌표값이 0보다 작다면(객체가 화면밖으로 벗어났다면), return_enemy() 변수를 실행합니다. 만약 0보다 값이 크다면(적이 화면 안에 있다면) 적 이미지를 그린다.
94~98번 return_enemy()메소드는 적의 x,y좌표값을 초기화하고, flying_enemies리스트를 섞은 후 랜덤으로 self.image에 새로운 적 이미지를 넣어줍니다.
100~101번 get_rect()메소드는 현재 적의 좌표값을 전달합니다.

 

 

 

다음으로 바닥에 걸어다니는 적 객체 생성을 위해

walkingEnemy 클래스를 만듭니다.

class walkingEnemy(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.WalkingEnemy_x = screen_width
        self.WalkingEnemy_y = 700
        self.x = screen_width

        enemy5 = pygame.image.load('sprite\enemy5\img2.png')
        enemy5 = pygame.transform.scale(enemy5,(100,100))
        enemy6 = pygame.image.load('sprite\enemy6\img2.png')
        enemy6 = pygame.transform.scale(enemy6,(100,100))

        walking_enemies.append(enemy5)
        walking_enemies.append(enemy6)
        
        self.random_num = random.randrange(0,2)
        self.image = walking_enemies[self.random_num]
        self.image = pygame.transform.scale(self.image,(100,100))
        self.rect = self.image.get_rect()
        self.rect.centerx = self.WalkingEnemy_x
        self.rect.centery = self.WalkingEnemy_y
        self.enemy_walkcount = 0
        
        # 적 이미지 랜덤 변경
    def change_walkingEnemy(self):
        random.shuffle(walking_enemies)
        self.image = walking_enemies[0]
        self.enemy_walkcount = 0
        # 적 이미지 움직이기
    def randomSpeed(self):
        self.x -= random.randrange(25,45)
        self.WalkingEnemy_x = self.x
        
        # 적이 화면 끝에 도달하면 위치 초기화
    def returnAndreset(self):
        self.WalkingEnemy_x = screen_width
        self.WalkingEnemy_y = 700
        
        # 적의 현재 x 좌표 넘기기
    def get_pos(self):
        return self.x
        
        # 적 그리기
    def draw_WalkingEnemy(self):
        screen.blit(self.image,(self.WalkingEnemy_x,self.WalkingEnemy_y))
        
    def check_enemy_position(self):
        if self.WalkingEnemy_x <= 0 :
            self.return_enemy()
        else:
            screen.blit(self.image,(self.WalkingEnemy_x,self.WalkingEnemy_y))
            
    def return_enemy(self):
        self.x = 1600
        self.WalkingEnemy_y = 700
        random.shuffle(walking_enemies)
        self.image = walking_enemies[0]
        
    def get_rect(self):
        return self.rect

FlyingEnemy 클래스와 구조가 거의 비슷합니다.

107번에서 바닥을 걸어다니는 적이므로 y좌표를 700으로 고정해줍니다.

110~116번에서 enemy5~6를 생성후 크기를 조정합니다. 그 후 walking_enemies 리스트에 넣어줍니다.

 

 

 

 

다음으로 게임에서 쓰이는 전역번수들을 소개하겠습니다.

# 3. pygame에 사용되는 전역변수 선언
WHITE = (255,255,255)
screen_height = 900
screen_width = 1600
size = [1600,900]
screen = pygame.display.set_mode(size)
done= False
clock= pygame.time.Clock()

#배경화면 생성
background = pygame.image.load('background1.png')
background = pygame.transform.scale(background, (1600,900))
background2 = background.copy()
backgorund1_x = 0
background2_x = 1600 # background width

#플레이어
is_jump_up =False
is_jump_down = False
player_posX = 300
player_posY = 700

165번은 화면의 색상을 지정하는 변수를 만든 것입니다.

166~169번은 화면의 가로, 세로 변수와 스크린의 사이즈를 지정하는 변수를 만든 것입니다.

170번 변수는 게임 종료 여부를 결정하는 변수입니다.

171번은 시간 변수입니다.

174~176번은 배경화면 변수를 생성후 스크린 사이즈에 맞추어 크기를 바꾸어줍니다.  그 후 카피하여 변수를 하나 더 만듭니다.

177~178번은 배경이미지1,2의 x좌표값을 나타내는 변수입니다. 게임 시작 시 화면을 움직이는 것처럼 보이기 위해 만듭니다.

181~184번은 플레이어의 점프와 x,y좌표를 나타내는 변수입니다. 플레이어의 x좌표는 고정돼 있습니다.

 

 

게임 시작 함수안에 쓰일 메소드들을 전체 코드에서 맨 아래에 위치하지만 쉬운 이해를 위해 먼저 소개하겠습니다.

게임 시작 메소드 안에서 쓰여질 전역 메소드입니다.

def draw_time(seconds):
    if done == False: # 게임 종료 시 호출 안함
        font_time = pygame.font.SysFont("FixedSsy",50,True,False)
        text_time = font_time.render("Time : " + str(seconds), True, (255,255,255))
        screen.blit(text_time,[30,30])
    
    
    
def moveback():
    global backgorund1_x, background2_x
    backgorund1_x -= 10 #배경화면 움직이는 세기
    background2_x -= 10 #배경화면 움직이는 세기
    if backgorund1_x == -1600 :
        backgorund1_x = 1600
    if background2_x == -1600:
        background2_x = 1600
    screen.blit(background, (backgorund1_x,0))
    screen.blit(background2, (background2_x,0))
    
    
def draw_gameover():
    font1 = pygame.font.SysFont("FixedSsy",150,True,False)
    gameoverscore = font1.render("GameOver",True,(255,0,0))
    text_rect = gameoverscore.get_rect()
    text_rect.centerx = round(screen_width/2)
    text_rect.centery = round(screen_height/2)
    screen.blit(gameoverscore,[text_rect.x,text_rect.y])

353번 메소드는 게임에서 플레이 시간을 나타내는 메소드입니다.

354번에서 만약 done 변수가 True일 경우 게임이 종료되며, 게임 플레이 시간을 세지 않습니다.

355번에서 텍스트에 사용할 폰트 스타일을 변수에 미리 저장합니다. 폰트,텍스트 크기,굵기,기울기를 설정해줍니다.

356번에서 위에서 설정한 폰트와 스타일을 이용하여 추가로 (텍스트,안티엘리어싱,색상)을 지정합니다.

357번에서 생성한 텍스트와 위치를 지정하여 화면에 직접 생성하여 줍니다.

 

361번은 게임시작시 화면을 움직이는 것처럼 보여줄수있는 기능을 하는 메소드입니다.

362번에서 전역변수를 global을 이용하여 메소드 안에서 접근할 수 있도록 합니다.

363~364번에서 배경 1,2를 일정한 속도로 움직입니다. 배경이 이어지면서 움직이는 것처럼 보이기 위해 177~178번에서 두 배경을 겹치지 않게 미리 이어두었습니다.

365~367번에서 배경1,2가 화면 밖으로 벗어난다면 다시 화면에 보이는 위치로 돌아오도록 하는 if문을 생성합니다.

369~370번에서 배경1,2를 변경된 좌표값을 이용하여 생성합니다. y좌표의 변화는 없기 때문에 0을 넣어줍니다.

 

373번은 게임 종료시 폰트를 화면에 띄우는 메소드입니다. 위에서 설명한 시간을 띄우는 메소드와 비슷합니다.

374~375번에서 폰트를 생성한 후 폰트를 이용하여 원하는 텍스트를 생성합니다.

376번에서 텍스트의 크기, 좌표의 값을 받아옵니다.

377~378번에서 화면의 가로와 세로의 가운데 값을 계산하여 텍스트의 x,y좌표에 넣어줍니다.(결론적으로 화면 가운데에 오게 합니다.)

379번에서 가운데로 위치를 지정한 텍스트를 생성해줍니다.

 

 

이제 게임을 실행하는 메인 메소드를 소개해드리겠습니다. 코드가 길기에 절반으로 나누어 변수 먼저설명하겠습니다.

# 4. pygame 무한루프
def runGame():
    global done, screen_height, background, backgorund1_x, background2_x
    global flying_enemies, walking_enemies
    global player_posX, player_posY, is_jump_up,is_jump_down

    start_time_count = pygame.time.get_ticks()

    x = 300 # 주인공의 X 좌표
    y = 700 # 주인공의 Y 좌표
    
    # 캐릭터 생성
    flyingEnemy1 = FlyingEnemy()
    flyingEnemy1.change_flyingEnemy()
    
    flyingEnemy2 = FlyingEnemy()
    flyingEnemy2.change_flyingEnemy()
    
    flyingEnemy3 = FlyingEnemy()
    flyingEnemy3.change_flyingEnemy()
    
    walkingEnemy1 = walkingEnemy()
    walkingEnemy1.change_walkingEnemy()
    
    player = Player()
    
    #캐릭터들의 좌표 값
    
    flyingEnemy1_rect = flyingEnemy1.get_rect()
    flyingEnemy1_rect.left = flyingEnemy1.FlyingEnemy_x
    flyingEnemy1_rect.top = flyingEnemy1.FlyingEnemy_y
    
    flyingEnemy2_rect = flyingEnemy2.get_rect()
    flyingEnemy2_rect.left = flyingEnemy2.FlyingEnemy_x
    flyingEnemy2_rect.top = flyingEnemy2.FlyingEnemy_y
    
    flyingEnemy3_rect = flyingEnemy3.get_rect()
    flyingEnemy3_rect.left = flyingEnemy3.FlyingEnemy_x
    flyingEnemy3_rect.top = flyingEnemy3.FlyingEnemy_y
    
    walkingEnemy1_rect = walkingEnemy1.get_rect()
    walkingEnemy1_rect.left = walkingEnemy1.WalkingEnemy_x
    walkingEnemy1_rect.top = walkingEnemy1.WalkingEnemy_y
    
    player_rect = player.get_rect()
    player_rect.left = player_posX
    player_rect.top = player_posY
    
    gameover_font = pygame.font.SysFont('g마켓산스ttfmedium', 80)
    gameover_text = gameover_font.render('GAME OVER',True,(255,0,0))
    # Gameover 텍스트의 사이즈 가져오기 (화면 가운데 배치시키기 위해)
    size_text_width = gameover_text.get_rect().size[0] # 가로 크기
    size_text_height = gameover_text.get_rect().size[1] # 세로 크기
 
    # gameover의 좌표를 화면 가운데 배치
    x_pos_gameover = screen_width/2-size_text_width/2
    y_pos_gameover = screen_height/2-size_text_height/2

    player.image = pygame.transform.scale(player.image, (100,100))

 

먼저 게임에서 사용할 전역 변수들을 global을 이용하여 불러옵니다.

190번에서 스크린,배경,게임 실행여부를 판단할 변수를 불러옵니다.

191번에서 날아다니는 적과 걸어다니는 적을 담은 리스트를 불러옵니다.

192번에서 플레이어의 좌표를 담은 변수들을 불러옵니다.

194번에서 게임의 첫 시작 시간을 담을 변수를 생성합니다.

196~197번에서 주인공의 좌표를 담습니다.

200~210번에서 위에서 만든 클래스들을 이용하여 인스턴스들을 생성합니다. 그 후 랜덤으로 이미지를 넣어줍니다.

212번에서는 Player클래스를 이용하여 플레이어 객체를 하나 생성해줍니다.

216~230번에서는 객체들의 좌표를 받아와 변수 생성 후 넣어줍니다. 추후 충돌판정을 위해 생성하는 변수입니다.

232~234번에서는 플레이어 객체에서 좌표값을 받아와 변수 생성 후 넣어줍니다.

236~240번에서 게임 폰트를 생성 후 텍스트를 만들어줍니다. 그 후 텍스트의 가로,세로 크기를 변수 생성 후 넣어줍니다.

243~244번에서 게임의 크기와 스크린의 가로 세로 사이즈를 이용해 가운데 값을 받아옵니다.

246번에서는 플레이어의 이미지 크기를 한번더 100으로 맞추어줍니다.

 

 

 

 

다음으로 실제로 게임이 실행되는 while문을 설명하겠습니다.

    while not done:
        clock.tick(10) # 1초에 10번 화면 출력 의미
        screen.fill(WHITE) # 배경 채우기
        moveback() # 배경 움직이기
        
        for event in pygame.event.get(): # 해당 게임안에서 이벤트 가져온다 (이벤트는 리스트 형태로 받아오기 때문애 FOR 로 확인한다.)
            if event.type == pygame.QUIT:
                done=True

            # 방향키 입력에 대한 이벤트 처리
            if event.type == pygame.KEYDOWN:
                if event.key== pygame.K_UP: # 좌표상에서 Y + 할수록 아래로 가게되므로 - 해준다.
                    is_jump_up = True
                    is_jump_down = False
                elif event.key == pygame.K_DOWN:
                    is_jump_down = True
                    is_jump_up = False
            
        if is_jump_up == True:
            y -= 100
            player_posY = y
            y = 0
            is_jump_up = False
        if is_jump_down == True:
            y += 100
            player_posY = y
            y = 0
            is_jump_down = False
            
        
        player.plus_walk_point()
        player.image = pygame.transform.scale(player.image, (100,100))
            
        if player_posY >= 0:
            if player_posY <= 700:
                screen.blit(player.image, (player_posX, player_posY))
                y = player_posY
                
            else:
                screen.blit(player.image, (player_posX, 700))       
                player_posY = 700
                y = 700
        else:
            screen.blit(player.image, (player_posX, 0))
            y = 0
            
        # 캐릭터 움직이기 및 끝에 다다르면 다시 뒤로 가져오기
        flyingEnemy1.randomSpeed()
        flyingEnemy1.check_enemy_position()
        flyingEnemy2.randomSpeed()
        flyingEnemy2.check_enemy_position()
        flyingEnemy3.randomSpeed()
        flyingEnemy3.check_enemy_position()
        walkingEnemy1.randomSpeed()
        walkingEnemy1.check_enemy_position()
        
        # 바뀐 캐릭터들의 좌표값 알아보기
        player_rect = player.get_rect()
        player_rect.left = player_posX
        player_rect.top = player_posY
    
        flyingEnemy1_rect = flyingEnemy1.get_rect()
        flyingEnemy1_rect.left = flyingEnemy1.FlyingEnemy_x
        flyingEnemy1_rect.top = flyingEnemy1.FlyingEnemy_y
        
        flyingEnemy2_rect = flyingEnemy2.get_rect()
        flyingEnemy2_rect.left = flyingEnemy2.FlyingEnemy_x
        flyingEnemy2_rect.top = flyingEnemy2.FlyingEnemy_y\
            
        flyingEnemy3_rect = flyingEnemy3.get_rect()
        flyingEnemy3_rect.left = flyingEnemy3.FlyingEnemy_x
        flyingEnemy3_rect.top = flyingEnemy3.FlyingEnemy_y
        
        walkingEnemy1_rect = walkingEnemy1.get_rect()
        walkingEnemy1_rect.left = walkingEnemy1.WalkingEnemy_x
        walkingEnemy1_rect.top = walkingEnemy1.WalkingEnemy_y
        
        # 주인공과 적의 충돌 감지
        if player_rect.colliderect(flyingEnemy1_rect):
            draw_gameover()
            pygame.display.update()
            pygame.time.delay(2000)
            done = True
        elif player_rect.colliderect(flyingEnemy2_rect):
            draw_gameover()
            pygame.display.update()
            pygame.time.delay(2000)
            done = True            
        elif player_rect.colliderect(flyingEnemy3_rect):
            draw_gameover()
            pygame.display.update()
            pygame.time.delay(2000)
            done = True            
        
        elif player_rect.colliderect(walkingEnemy1_rect):
            draw_gameover()
            pygame.display.update()
            pygame.time.delay(2000)
            done = True
        seconds = (pygame.time.get_ticks()-start_time_count)/1000
        seconds = round(seconds)
        draw_time(seconds)
        pygame.display.flip() # 전체 surface 업데이트 하기
        pygame.display.update()

248번에서 done변수가 False일 경우 실행하도록 합니다.

249번에서 1초에 10번 화면 출력되도록 합니다.

250번에서 배경을 채웁니다.

251번에서 배경을 움직이도록 합니다.

253번에서 게임의 이벤트를 가져옵니다. 리스트로 이벤트를 가져오기 때문에 for문을 이용하여 이벤트를 확인합니다.

254~255번에서 게임창의 X표시를 눌렀을 경우 done변수를 True로 바꾸어줍니다. 그경우 while문이 멈추어 게임이 꺼집니다.

258번에서 방향키 입력이 있을 경우 실행합니다.

259~261번에서 위쪽 방향키를 실행하였을 경우 is_junp_up 변수를 트루로 바꾸어줍니다. 추후 플레이어 이동 판단에 쓰입니다.

262~264번에서 아래쪽 방향키를 실행하였을 경우 반대로 is_jump_down 변수를 트루로 바꾸어줍니다.

266~270번에서 is_jump_up이 True일 경우 y좌표를 100만큼 빼줍니다. 그 후 플레이어 y좌표 변수에 넣어줍니다. 그 후 다시 False로 바꾸어줍니다.

271~275번에서는 반대로 is_jump_down이 True일 경우 100만큼 빼주고, y좌표 변수에 넣어줍니다.

화면은 왼쪽 위를 기준으로 (0,0)이기 때문에 y좌표가 커질수록 아래 위치하고, y좌표가 작아질수록 위에 위치합니다.

278번에서 플레이어이미지가 시간에 따라 변경되는 메소드를 실행합니다.

279번에서 변경한 이미지 크기가 일정하도록 다시 사이즈를 재조정 해줍니다.

281번에서 플레이어 y좌표가 0보다 클 경우 실행합니다.

282~284번에서 플레이어 y좌표가 700보다 작거나 같을 경우 좌표값을 넣어 실행해줍니다.

286번에서 만약 y좌표가 700보다 클 경우 플레이어가 땅 아래로 움직이지 못하도록 y좌표값을 700으로 고정합니다.

290~292번에서 만약 플레이어가 화면(하늘)밖으로 벗어나려 한다면 y좌표를 0으로 고정하여 줍니다.

295~302번에서 적 객체들에게 랜덤으로 속력을 부여합니다. 또한 적 객체가 화면 왼쪽 끝으로 이동했다면 다시 오른쪽 끝으로 위치를 이동시켜줍니다. 끝에 다다르지 않았다면 그냥 생성해줍니다.

305~323번에서 적과 플레이어 객체들의 실시간으로 바뀌는  좌표값을 변수에 받아와 넣어줍니다.

326~346번에서 적 객체들과 플레이가 충돌했을 경우 게임오버 메소드를 실행한후 2초동안 있다가 게임을 종료합니다.

347번에서 게임에 표시할 시간을 재줍니다. 현재 플레이 시간에서 처음 시작 시간을 빼서 플레이 타임을 구합니다.

348번에서 소수점을 제거 해줍니다.

349번에서 측정한 시간을 이용해 메소드를 이용하여 플레이 타임을 표기합니다.

350~351번에서 전체 surface를 업데이트해 화면에 표시해줍니다.

 

 

이 게임의 전체 코드 입니다.

import pygame # 1. pygame 선언
import random
pygame.init() # 2. pygame 초기화
pygame.display.set_caption("다람쥐의 모험")


flying_enemies = []
walking_enemies = []
player_walk = [pygame.image.load('sprite\squirrel\walk1.png'),pygame.image.load('sprite\squirrel\walk2.png'),
               pygame.image.load('sprite\squirrel\walk3.png'),pygame.image.load('sprite\squirrel\walk4.png'),
               pygame.image.load('sprite\squirrel\walk5.png'),pygame.image.load('sprite\squirrel\walk6.png'),
               pygame.image.load('sprite\squirrel\walk7.png'),pygame.image.load('sprite\squirrel\walk8.png')]
enemy1_move = [pygame.image.load('sprite\enemy1\img2.png'),pygame.image.load('sprite\enemy1\img4.png'),
               pygame.image.load('sprite\enemy1\img6.png'),pygame.image.load('sprite\enemy1\img8.png'),
               pygame.image.load('sprite\enemy1\img10.png'),pygame.image.load('sprite\enemy1\img14.png'),
               pygame.image.load('sprite\enemy1\img14.png'),pygame.image.load('sprite\enemy1\img16.png')]

class Player(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        
        self.image = pygame.image.load('sprite\squirrel\walk1.png')
        self.image = pygame.transform.scale(self.image, (100, 100)) # 넓이, 높이
        self.rect = self.image.get_rect()
        self.rect.centerx = player_posX
        self.rect.centery = player_posY
        self.walkcount = 0
        
    def get_rect(self):
        return self.rect
    
    def plus_walk_point(self):
        self.walkcount += 1
        if self.walkcount == 8:
            self.walkcount = 0
            self.image = player_walk[self.walkcount]
        else:
            self.image = pygame.transform.scale(self.image, (100,100))
            self.image = player_walk[self.walkcount]

class FlyingEnemy(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.FlyingEnemy_x = screen_width
        self.FlyingEnemy_y = random.randrange(0,7)*100
        self.x = screen_width
        enemy1 = pygame.image.load('sprite\enemy1\img2.png')
        enemy1 = pygame.transform.scale(enemy1,(100,100))
        enemy2 = pygame.image.load('sprite\enemy2\img2.png')
        enemy2 = pygame.transform.scale(enemy2,(100,100))
        enemy3 = pygame.image.load('sprite\enemy3\img2.png')
        enemy3= pygame.transform.scale(enemy3,(100,100))
        enemy4 = pygame.image.load('sprite\enemy4\img2.png')
        enemy4 = pygame.transform.scale(enemy4,(100,100))
        flying_enemies.append(enemy1)
        flying_enemies.append(enemy2)
        flying_enemies.append(enemy3)
        flying_enemies.append(enemy4)
        self.random_num = random.randrange(0,4)
        self.image = flying_enemies[self.random_num]
        self.image = pygame.transform.scale(self.image,(100,100))
        self.rect = self.image.get_rect()
        self.rect.centerx = self.FlyingEnemy_x
        self.rect.centery = self.FlyingEnemy_y
        
        # 적 이미지 랜덤 변경
    def change_flyingEnemy(self):
        random.shuffle(flying_enemies)
        self.image = flying_enemies[0]
        # 적 이미지 움직이기
    def randomSpeed(self):
        self.x -= random.randrange(45,95) # enemy의 속도를 랜덤으로 조절 -> 적들이 불규칙적으로 등장하도록 한다.
        self.FlyingEnemy_x = self.x
        
        # 적이 화면 끝에 도달하면 위치 초기화
    def returnAndreset(self):
        self.FlyingEnemy_x = screen_width
        self.FlyingEnemy_y = random.randrange(0,7)*100
        
        # 적의 현재 x 좌표 넘기기
    def get_pos(self):
        return self.x
        
        # 적 그리기
    def draw_flyingEnemy(self):
        screen.blit(self.image,(self.FlyingEnemy_x,self.FlyingEnemy_y))
        
    def check_enemy_position(self):
        if self.FlyingEnemy_x <= 0 :
            self.return_enemy()
        else:
            screen.blit(self.image,(self.FlyingEnemy_x,self.FlyingEnemy_y))
            
    def return_enemy(self):
        self.x = 1600
        self.FlyingEnemy_y = random.randrange(0,7)*100
        random.shuffle(flying_enemies)
        self.image = flying_enemies[0]
        
    def get_rect(self):
        return self.rect

class walkingEnemy(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.WalkingEnemy_x = screen_width
        self.WalkingEnemy_y = 700
        self.x = screen_width

        enemy5 = pygame.image.load('sprite\enemy5\img2.png')
        enemy5 = pygame.transform.scale(enemy5,(100,100))
        enemy6 = pygame.image.load('sprite\enemy6\img2.png')
        enemy6 = pygame.transform.scale(enemy6,(100,100))

        walking_enemies.append(enemy5)
        walking_enemies.append(enemy6)
        
        self.random_num = random.randrange(0,2)
        self.image = walking_enemies[self.random_num]
        self.image = pygame.transform.scale(self.image,(100,100))
        self.rect = self.image.get_rect()
        self.rect.centerx = self.WalkingEnemy_x
        self.rect.centery = self.WalkingEnemy_y
        self.enemy_walkcount = 0
        
        # 적 이미지 랜덤 변경
    def change_walkingEnemy(self):
        random.shuffle(walking_enemies)
        self.image = walking_enemies[0]
        self.enemy_walkcount = 0
        # 적 이미지 움직이기
    def randomSpeed(self):
        self.x -= random.randrange(25,45)
        self.WalkingEnemy_x = self.x
        
        # 적이 화면 끝에 도달하면 위치 초기화
    def returnAndreset(self):
        self.WalkingEnemy_x = screen_width
        self.WalkingEnemy_y = 700
        
        # 적의 현재 x 좌표 넘기기
    def get_pos(self):
        return self.x
        
        # 적 그리기
    def draw_WalkingEnemy(self):
        screen.blit(self.image,(self.WalkingEnemy_x,self.WalkingEnemy_y))
        
    def check_enemy_position(self):
        if self.WalkingEnemy_x <= 0 :
            self.return_enemy()
        else:
            screen.blit(self.image,(self.WalkingEnemy_x,self.WalkingEnemy_y))
            
    def return_enemy(self):
        self.x = 1600
        self.WalkingEnemy_y = 700
        random.shuffle(walking_enemies)
        self.image = walking_enemies[0]
        
    def get_rect(self):
        return self.rect
        
# 3. pygame에 사용되는 전역변수 선언
WHITE = (255,255,255)
screen_height = 900
screen_width = 1600
size = [1600,900]
screen = pygame.display.set_mode(size)
done= False
clock= pygame.time.Clock()

#배경화면 생성
background = pygame.image.load('background1.png')
background = pygame.transform.scale(background, (1600,900))
background2 = background.copy()
backgorund1_x = 0
background2_x = 1600 # background width

#플레이어
is_jump_up =False
is_jump_down = False
player_posX = 300
player_posY = 700



# 4. pygame 무한루프
def runGame():
    global done, screen_height, background, backgorund1_x, background2_x
    global flying_enemies, walking_enemies
    global player_posX, player_posY, is_jump_up,is_jump_down

    start_time_count = pygame.time.get_ticks()

    x = 300 # 주인공의 X 좌표
    y = 700 # 주인공의 Y 좌표
    
    # 캐릭터 생성
    flyingEnemy1 = FlyingEnemy()
    flyingEnemy1.change_flyingEnemy()
    
    flyingEnemy2 = FlyingEnemy()
    flyingEnemy2.change_flyingEnemy()
    
    flyingEnemy3 = FlyingEnemy()
    flyingEnemy3.change_flyingEnemy()
    
    walkingEnemy1 = walkingEnemy()
    walkingEnemy1.change_walkingEnemy()
    
    player = Player()
    
    #캐릭터들의 좌표 값
    
    flyingEnemy1_rect = flyingEnemy1.get_rect()
    flyingEnemy1_rect.left = flyingEnemy1.FlyingEnemy_x
    flyingEnemy1_rect.top = flyingEnemy1.FlyingEnemy_y
    
    flyingEnemy2_rect = flyingEnemy2.get_rect()
    flyingEnemy2_rect.left = flyingEnemy2.FlyingEnemy_x
    flyingEnemy2_rect.top = flyingEnemy2.FlyingEnemy_y
    
    flyingEnemy3_rect = flyingEnemy3.get_rect()
    flyingEnemy3_rect.left = flyingEnemy3.FlyingEnemy_x
    flyingEnemy3_rect.top = flyingEnemy3.FlyingEnemy_y
    
    walkingEnemy1_rect = walkingEnemy1.get_rect()
    walkingEnemy1_rect.left = walkingEnemy1.WalkingEnemy_x
    walkingEnemy1_rect.top = walkingEnemy1.WalkingEnemy_y
    
    player_rect = player.get_rect()
    player_rect.left = player_posX
    player_rect.top = player_posY
    
    gameover_font = pygame.font.SysFont('g마켓산스ttfmedium', 80)
    gameover_text = gameover_font.render('GAME OVER',True,(255,0,0))
    # Gameover 텍스트의 사이즈 가져오기 (화면 가운데 배치시키기 위해)
    size_text_width = gameover_text.get_rect().size[0] # 가로 크기
    size_text_height = gameover_text.get_rect().size[1] # 세로 크기
 
    # gameover의 좌표를 화면 가운데 배치
    x_pos_gameover = screen_width/2-size_text_width/2
    y_pos_gameover = screen_height/2-size_text_height/2

    player.image = pygame.transform.scale(player.image, (100,100))
    
    while not done:
        clock.tick(10) # 1초에 10번 화면 출력 의미
        screen.fill(WHITE) # 배경 채우기
        moveback() # 배경 움직이기
        
        for event in pygame.event.get(): # 해당 게임안에서 이벤트 가져온다 (이벤트는 리스트 형태로 받아오기 때문애 FOR 로 확인한다.)
            if event.type == pygame.QUIT:
                done=True

            # 방향키 입력에 대한 이벤트 처리
            if event.type == pygame.KEYDOWN:
                if event.key== pygame.K_UP: # 좌표상에서 Y + 할수록 아래로 가게되므로 - 해준다.
                    is_jump_up = True
                    is_jump_down = False
                elif event.key == pygame.K_DOWN:
                    is_jump_down = True
                    is_jump_up = False
            
        if is_jump_up == True:
            y -= 100
            player_posY = y
            y = 0
            is_jump_up = False
        if is_jump_down == True:
            y += 100
            player_posY = y
            y = 0
            is_jump_down = False
            
        
        player.plus_walk_point()
        player.image = pygame.transform.scale(player.image, (100,100))
            
        if player_posY >= 0:
            if player_posY <= 700:
                screen.blit(player.image, (player_posX, player_posY))
                y = player_posY
                
            else:
                screen.blit(player.image, (player_posX, 700))       
                player_posY = 700
                y = 700
        else:
            screen.blit(player.image, (player_posX, 0))
            y = 0
            
        # 캐릭터 움직이기 및 끝에 다다르면 다시 뒤로 가져오기
        flyingEnemy1.randomSpeed()
        flyingEnemy1.check_enemy_position()
        flyingEnemy2.randomSpeed()
        flyingEnemy2.check_enemy_position()
        flyingEnemy3.randomSpeed()
        flyingEnemy3.check_enemy_position()
        walkingEnemy1.randomSpeed()
        walkingEnemy1.check_enemy_position()
        
        # 바뀐 캐릭터들의 좌표값 알아보기
        player_rect = player.get_rect()
        player_rect.left = player_posX
        player_rect.top = player_posY
    
        flyingEnemy1_rect = flyingEnemy1.get_rect()
        flyingEnemy1_rect.left = flyingEnemy1.FlyingEnemy_x
        flyingEnemy1_rect.top = flyingEnemy1.FlyingEnemy_y
        
        flyingEnemy2_rect = flyingEnemy2.get_rect()
        flyingEnemy2_rect.left = flyingEnemy2.FlyingEnemy_x
        flyingEnemy2_rect.top = flyingEnemy2.FlyingEnemy_y\
            
        flyingEnemy3_rect = flyingEnemy3.get_rect()
        flyingEnemy3_rect.left = flyingEnemy3.FlyingEnemy_x
        flyingEnemy3_rect.top = flyingEnemy3.FlyingEnemy_y
        
        walkingEnemy1_rect = walkingEnemy1.get_rect()
        walkingEnemy1_rect.left = walkingEnemy1.WalkingEnemy_x
        walkingEnemy1_rect.top = walkingEnemy1.WalkingEnemy_y
        
        # 주인공과 적의 충돌 감지
        if player_rect.colliderect(flyingEnemy1_rect):
            draw_gameover()
            pygame.display.update()
            pygame.time.delay(2000)
            done = True
        elif player_rect.colliderect(flyingEnemy2_rect):
            draw_gameover()
            pygame.display.update()
            pygame.time.delay(2000)
            done = True            
        elif player_rect.colliderect(flyingEnemy3_rect):
            draw_gameover()
            pygame.display.update()
            pygame.time.delay(2000)
            done = True            
        
        elif player_rect.colliderect(walkingEnemy1_rect):
            draw_gameover()
            pygame.display.update()
            pygame.time.delay(2000)
            done = True
        seconds = (pygame.time.get_ticks()-start_time_count)/1000
        seconds = round(seconds)
        draw_time(seconds)
        pygame.display.flip() # 전체 surface 업데이트 하기
        pygame.display.update()
        
def draw_time(seconds):
    if done == False: # 게임 종료 시 호출 안함
        font_time = pygame.font.SysFont("FixedSsy",50,True,False)
        text_time = font_time.render("Time : " + str(seconds), True, (255,255,255))
        screen.blit(text_time,[30,30])
    
    
    
def moveback():
    global backgorund1_x, background2_x
    backgorund1_x -= 10 #배경화면 움직이는 세기
    background2_x -= 10 #배경화면 움직이는 세기
    if backgorund1_x == -1600 :
        backgorund1_x = 1600
    if background2_x == -1600:
        background2_x = 1600
    screen.blit(background, (backgorund1_x,0))
    screen.blit(background2, (background2_x,0))
    
    
def draw_gameover():
    font1 = pygame.font.SysFont("FixedSsy",150,True,False)
    gameoverscore = font1.render("GameOver",True,(255,0,0))
    text_rect = gameoverscore.get_rect()
    text_rect.centerx = round(screen_width/2)
    text_rect.centery = round(screen_height/2)
    screen.blit(gameoverscore,[text_rect.x,text_rect.y])
runGame()
pygame.quit()

 

 

추후 게임을 더 업그레이드하여 업로드 하겠습니다.

파이썬 공부에 도움이 되었으면 좋겠습니다.~~

또봐요~~!