from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
import random
class WindowClass(QWidget):
def __init__(self):
super().__init__()
self.key = None
self.img_title = QImage('Python_workspace/python_game/image/dot_eat/title.png')
self.img_bg = [ # 맵 칩
QImage('Python_workspace\python_game\image\dot_eat\chip00.png'),
QImage('Python_workspace\python_game\image\dot_eat\chip01.png'),
QImage('Python_workspace\python_game\image\dot_eat\chip02.png'),
QImage('Python_workspace\python_game\image\dot_eat\chip03.png')
]
self.img_pen = [ # 캐릭터 이미지
QImage('Python_workspace\python_game\image\dot_eat\pen00.png'), # 위쪽
QImage('Python_workspace\python_game\image\dot_eat\pen01.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen02.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen03.png'), # 아래쪽
QImage('Python_workspace\python_game\image\dot_eat\pen04.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen05.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen06.png'), # 왼쪽
QImage('Python_workspace\python_game\image\dot_eat\pen07.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen08.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen09.png'), # 오른쪽
QImage('Python_workspace\python_game\image\dot_eat\pen10.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen11.png')
]
self.img_red = [
QImage('Python_workspace/python_game/image/dot_eat/red00.png'),
QImage('Python_workspace/python_game/image/dot_eat/red01.png'),
QImage('Python_workspace/python_game/image/dot_eat/red02.png'),
QImage('Python_workspace/python_game/image/dot_eat/red03.png'),
QImage('Python_workspace/python_game/image/dot_eat/red04.png'),
QImage('Python_workspace/python_game/image/dot_eat/red05.png'),
QImage('Python_workspace/python_game/image/dot_eat/red06.png'),
QImage('Python_workspace/python_game/image/dot_eat/red07.png'),
QImage('Python_workspace/python_game/image/dot_eat/red08.png'),
QImage('Python_workspace/python_game/image/dot_eat/red09.png'),
QImage('Python_workspace/python_game/image/dot_eat/red10.png'),
QImage('Python_workspace/python_game/image/dot_eat/red11.png')
]
self.DIR_UP = 0 # 캐릭터 방향 정의 변수(위쪽)
self.DIR_DOWN = 1 # 캐릭터 방향 정의 변수(아래쪽)
self.DIR_LEFT = 2 # 캐릭터 방향 정의 변수(왼쪽)
self.DIR_RIGHT = 3 # 캐릭터 방향 정의 변수(오른쪽)
self.ANIMATION = [0, 1, 0, 2]
self.idx = 0
self.tmr = 0
self.stage = 1 # 스테이지 수
self.score = 0 # 점수
self.candy = 0 # 각 스테이지에 있는 사탕 수
self.pen_x = 0 # 펜펜의 X 좌표
self.pen_y = 0 # 펜펜의 Y 좌표
self.pen_d = 0 # 펜펜의 방향
self.pen_a = 0 # 펜펜의 이미지 번호
self.red_x = 0 # 레드의 X 좌표
self.red_y = 0 # 레드의 Y 좌표
self.red_d = 0 # 레드의 방향
self.red_a = 0 # 레드의 이미지 번호
self.red_sx = 0 # 레드 시작 위치 X 좌표
self.red_sy = 0 # 레드 시작 위치 Y 좌표
self.map_data = []
self.initUI()
timer = QTimer(self)
timer.setInterval(100)
timer.timeout.connect(self.main_proc) # 100밀리초마다 main_proc 실행
timer.start()
def initUI(self):
self.setFixedSize(720, 540) # 창 크기 고정
self.setWindowTitle('PenPen\'s Maze Adventure')
self.set_stage()
self.set_chara_pos()
def set_stage(self): # 스테이지 데이터 설정 함수
if self.stage == 1:
self.map_data = [ # 미로 데이터
[0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0],
[0, 2, 3, 3, 2, 1, 1, 2, 3, 3, 2, 0],
[0, 3, 0, 0, 3, 3, 3, 3, 0, 0, 3, 0],
[0, 3, 1, 1, 3, 0, 0, 3, 1, 1, 3, 0],
[0, 3, 2, 2, 3, 0, 0, 3, 2, 2, 3, 0],
[0, 3, 0, 0, 3, 1, 1, 3, 0, 0, 3, 0],
[0, 3, 1, 1, 3, 3, 3, 3, 1, 1, 3, 0],
[0, 2, 3, 3, 2, 0, 0, 2, 3, 3, 2, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
self.candy = 32 # 사탕 수
self.red_sx = 600
self.red_sy = 420
if self.stage == 2:
self.map_data = [
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 0],
[0, 3, 3, 0, 2, 1, 1, 2, 0, 3, 3, 0],
[0, 3, 3, 1, 3, 3, 3, 3, 1, 3, 3, 0],
[0, 2, 1, 3, 3, 3, 3, 3, 3, 1, 2, 0],
[0, 3, 3, 0, 3, 3, 3, 3, 0, 3, 3, 0],
[0, 3, 3, 1, 2, 1, 1, 2, 1, 3, 3, 0],
[0, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
self.candy = 38
self.red_sx = 600
self.red_sy = 60
if self.stage == 3:
self.map_data = [
[0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0],
[0, 2, 1, 3, 1, 2, 2, 3, 3, 3, 3, 0],
[0, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 0],
[0, 2, 1, 1, 1, 2, 2, 1, 1, 1, 1, 0],
[0, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, 0],
[0, 1, 1, 2, 0, 2, 2, 0, 1, 1, 2, 0],
[0, 3, 3, 3, 1, 1, 1, 0, 3, 3, 3, 0],
[0, 3, 3, 3, 2, 2, 2, 0, 3, 3, 3, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
self.candy = 23
self.red_sx = 600
self.red_sy = 420
def set_chara_pos(self): # 캐릭터 시작 위치 설정 함수
self.pen_x = 60 # 펜펜의 시작 x, y 좌표 대입
self.pen_y = 60
self.pen_d = self.DIR_DOWN # 펜펜의 방향을 아래로
self.pen_a = 3 # 펜펜 그림 번호 대입
self.red_x = self.red_sx # 레드의 시작 x, y 좌표 대입
self.red_y = self.red_sy
self.red_d = self.DIR_DOWN # 레드의 방향을 아래로
self.red_a = 3 # 레드 그림 번호 대입
def check_wall(self, cx, cy, di, dot): # 지정한 방향에 벽 존재 여부 확인 함수
chk = False # chk에 False 대입
if di == self.DIR_UP: # 위쪽일 경우
mx = int(cx / 60) # mx와 my에 리스트의 좌상 방향 확인용 값 대입
my = int((cy - dot) / 60)
if self.map_data[my][mx] <= 1: # 좌상
chk = True # chk에 True 대입
mx = int((cx + 59) / 60) # 리스트의 우상 방향 확인용 값 대입
if self.map_data[my][mx] <= 1: # 우상
chk = True # chk에 True 대입
if di == self.DIR_DOWN: # 아래쪽일 경우
mx = int(cx / 60) # mx와 my에 리스트의 좌하 방향 확인용 값 대입
my = int((cy + 59 + dot) / 60)
if self.map_data[my][mx] <= 1: # 좌하
chk = True
mx = int((cx + 59) / 60) # 리스트의 우하 방향 확인용 값 대입
if self.map_data[my][mx] <= 1: # 우하
chk = True
if di == self.DIR_LEFT: # 왼쪽일 경우
mx = int((cx - dot) / 60) # mx와 my에 리스트의 좌상 방향 확인용 값 대입
my = int(cy / 60)
if self.map_data[my][mx] <= 1: # 좌상
chk = True
my = int((cy + 59) / 60) # 리스트의 좌하 방향 확인용 값 대입
if self.map_data[my][mx] <= 1: # 좌하
chk = True
if di == self.DIR_RIGHT: # 오른쪽일 경우
mx = int((cx + 59 + dot) / 60) # mx와 my에 리스트의 우상 방향 확인용 값 대입
my = int(cy / 60)
if self.map_data[my][mx] <= 1: # 우상
chk = True
my = int((cy + 59) / 60) # 리스트의 우하 방향 확인용 값 대입
if self.map_data[my][mx] <= 1: # 우하
chk = True
return chk # chk 값 반환
def move_penpen(self): # 펜펜(캐릭터) 이동 함수
if self.key == Qt.Key_Up: # 위쪽 방향키를 눌렀다면
self.pen_d = self.DIR_UP # 펜펜의 방향을 위쪽으로
if self.check_wall(self.pen_x, self.pen_y, self.pen_d, 20) == False: # 해당 방향이 벽이 아니라면
self.pen_y = self.pen_y - 20 # 위쪽으로 이동
if self.key == Qt.Key_Down: # 아래쪽
self.pen_d = self.DIR_DOWN # 펜펜의 방향을 아래쪽으로
if self.check_wall(self.pen_x, self.pen_y, self.pen_d, 20) == False:
self.pen_y = self.pen_y + 20
if self.key == Qt.Key_Left: # 왼쪽
self.pen_d = self.DIR_LEFT # 펜펜의 방향을 왼쪽으로
if self.check_wall(self.pen_x, self.pen_y, self.pen_d, 20) == False:
self.pen_x = self.pen_x - 20
if self.key == Qt.Key_Right: # 오른쪽
self.pen_d = self.DIR_RIGHT # 펜펜의 방향을 오른쪽으로
if self.check_wall(self.pen_x, self.pen_y, self.pen_d, 20) == False:
self.pen_x = self.pen_x + 20
self.pen_a = self.pen_d * 3 + self.ANIMATION[self.tmr % 4] # 펜펜 애니메이션(이미지) 번호 계산
mx = int(self.pen_x / 60) # mx, my에 펜펜이 있는 위치의 리스트로 확인할 값 대입
my = int(self.pen_y / 60)
if self.map_data[my][mx] == 3: # 사탕 위치에 들어가면
self.score = self.score + 100 # 점수 추가
self.map_data[my][mx] = 2 # 사탕 삭제
self.candy = self.candy - 1 # 사탕 개수 감소
def move_enemy(self): # 레드(적) 이동 함수
speed = 10 # 레드의 이동 속도
if self.red_x % 60 == 0 and self.red_y % 60 == 0: # 칸의 정확한 위치에 있는 경우
self.red_d = random.randint(0, 6) # 무작위로 방향 변경
if self.red_d >= 4: # 난수가 4 이상인 경우 주인공 추적
if self.pen_y < self.red_y: # 펜펜이 위쪽에 있다면
self.red_d = self.DIR_UP # 레드의 방향을 위쪽으로
if self.pen_y > self.red_y:
self.red_d = self.DIR_DOWN
if self.pen_x < self.red_x:
self.red_d = self.DIR_LEFT
if self.pen_x > self.red_x:
self.red_d = self.DIR_RIGHT
if self.red_d == self.DIR_UP: # 레드가 위쪽을 향한 경우
if self.check_wall(self.red_x, self.red_y, self.red_d, speed) == False: # 해당 방향이 벽이 아니라면
self.red_y = self.red_y - speed # 이동
if self.red_d == self.DIR_DOWN:
if self.check_wall(self.red_x, self.red_y, self.red_d, speed) == False:
self.red_y = self.red_y + speed
if self.red_d == self.DIR_LEFT:
if self.check_wall(self.red_x, self.red_y, self.red_d, speed) == False:
self.red_x = self.red_x - speed
if self.red_d == self.DIR_RIGHT:
if self.check_wall(self.red_x, self.red_y, self.red_d, speed) == False:
self.red_x = self.red_x + speed
self.red_a = self.red_d * 3 + self.ANIMATION[self.tmr % 4] # 레드의 애니메이션 번호 계산
if abs(self.red_x - self.pen_x) <= 40 and abs(self.red_y - self.pen_y) <= 40: # 펜펜과 접촉했는지 판단해서 접촉했다면
self.idx = 2 # 게임 오버 처리로 이동
self.tmr = 0
def main_proc(self):
self.tmr = self.tmr + 1 # 타이머 값 증가
if self.idx == 0: # 인덱스 0 처리(타이틀 화면)
if self.key == Qt.Key_Space: # [SPACE]키를 누르면
self.stage = 1
self.score = 0 # 점수 0 대입
self.set_stage() # 스테이지 데이터 세트
self.set_chara_pos() # 각 캐릭터 시작 위치 설정
self.idx = 1 # 인덱스를 1로 변경, 게임 시작
if self.idx == 1: # 인덱스 1 처리(게임 플레이)
self.move_penpen() # 펜펜 이동
self.move_enemy() # 레드 이동
if self.candy == 0: # 사탕을 모두 먹었다면
self.idx = 4 # 스테이지 클리어 처리로 이동
self.tmr = 0
if self.idx == 2: # 인덱스 2 처리(게임 오버)
if self.tmr == 50:
self.idx = 0 # 타이틀 화면으로 이동
if self.idx == 4: # 인덱스 4 처리(스테이지 클리어)
if self.tmr == 30:
if self.stage < 3:
self.stage = self.stage + 1
self.set_stage()
self.set_chara_pos()
self.idx = 1
else:
self.idx = 0 # 타이틀 화면으로 이동
self.update()
def draw_text(self, qp, txt, x, y, siz, col): # 그림자를 포함한 문자열을 표시
qp.setFont(QFont('Times New Roman', siz, QFont.Bold)) # 폰트 정의
qp.setPen(Qt.black) # 문자열 그림자(2픽셀 어긋나게 검게 표시)
qp.drawText(x + 2, y + 2, txt)
qp.setPen(col) # 지정한 색으로 문자열 표시
qp.drawText(x, y, txt)
def paintEvent(self, e):
qp = QPainter()
qp.begin(self)
for y in range(9):
for x in range(12):
qp.drawImage(QRect(x * 60, y * 60, 60, 60), self.img_bg[self.map_data[y][x]]) # 맵 칩으로 미로 그리기
qp.drawImage(QRect(self.pen_x, self.pen_y, 60, 60), self.img_pen[self.pen_a]) # PenPen 표시
qp.drawImage(QRect(self.red_x, self.red_y, 60, 60), self.img_red[self.red_a]) # 레드 표시
self.draw_text(qp, 'SCORE ' + str(self.score), 100, 30, 30, Qt.white) # 점수 표시
self.draw_text(qp, 'STAGE ' + str(self.stage), 440, 30, 30, QColor(191, 255, 0)) # 스테이지 수 표시
if self.idx == 0: # 타이틀 화면 표시
qp.drawImage(QRect(35, 100, self.img_title.width(), self.img_title.height()), self.img_title)
if self.tmr % 10 < 5: # 문자열이 깜빡거리는 처리
self.draw_text(qp, 'Press SPACE !', 250, 380, 30, Qt.yellow)
if self.idx == 2: # 게임 오버 문자 표시
self.draw_text(qp, 'GAME OVER', 200, 270, 40, Qt.red)
if self.idx == 4: # 스테이지 클리어 문자 표시
if self.stage < 3:
self.draw_text(qp, 'STAGE CLEAR', 180, 270, 40, QColor(255, 170, 170))
else:
self.draw_text(qp, 'ALL STAGE CLEAR!', 80, 270, 40, QColor(210, 168, 212))
qp.end()
def keyPressEvent(self, e):
self.key = e.key()
def keyReleaseEvent(self, e):
self.key = None
if __name__ == "__main__":
app = QApplication(sys.argv)
main_W = WindowClass()
main_W.show()
sys.exit(app.exec_())
스테이지의 모든 사탕을 주우면 다음 스테이지로 넘어간다. 최종 스테이지인 3 스테이지를 클리어하면 타이틀 화면으로 돌아간다.
set_stage 함수는 stage 값에 따라 map_data에 미로 데이터를 대입한다. 추가로 게임 시작시 레드의 좌표를 red_sx, red_sy에 대입한다.
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
import random
class WindowClass(QWidget):
def __init__(self):
super().__init__()
self.key = None
self.img_title = QImage('Python_workspace/python_game/image/dot_eat/title.png')
self.img_bg = [ # 맵 칩
QImage('Python_workspace\python_game\image\dot_eat\chip00.png'),
QImage('Python_workspace\python_game\image\dot_eat\chip01.png'),
QImage('Python_workspace\python_game\image\dot_eat\chip02.png'),
QImage('Python_workspace\python_game\image\dot_eat\chip03.png')
]
self.img_pen = [ # 캐릭터 이미지
QImage('Python_workspace\python_game\image\dot_eat\pen00.png'), # 위쪽
QImage('Python_workspace\python_game\image\dot_eat\pen01.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen02.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen03.png'), # 아래쪽
QImage('Python_workspace\python_game\image\dot_eat\pen04.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen05.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen06.png'), # 왼쪽
QImage('Python_workspace\python_game\image\dot_eat\pen07.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen08.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen09.png'), # 오른쪽
QImage('Python_workspace\python_game\image\dot_eat\pen10.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen11.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen_face.png')
]
self.img_red = [
QImage('Python_workspace/python_game/image/dot_eat/red00.png'),
QImage('Python_workspace/python_game/image/dot_eat/red01.png'),
QImage('Python_workspace/python_game/image/dot_eat/red02.png'),
QImage('Python_workspace/python_game/image/dot_eat/red03.png'),
QImage('Python_workspace/python_game/image/dot_eat/red04.png'),
QImage('Python_workspace/python_game/image/dot_eat/red05.png'),
QImage('Python_workspace/python_game/image/dot_eat/red06.png'),
QImage('Python_workspace/python_game/image/dot_eat/red07.png'),
QImage('Python_workspace/python_game/image/dot_eat/red08.png'),
QImage('Python_workspace/python_game/image/dot_eat/red09.png'),
QImage('Python_workspace/python_game/image/dot_eat/red10.png'),
QImage('Python_workspace/python_game/image/dot_eat/red11.png')
]
self.DIR_UP = 0 # 캐릭터 방향 정의 변수(위쪽)
self.DIR_DOWN = 1 # 캐릭터 방향 정의 변수(아래쪽)
self.DIR_LEFT = 2 # 캐릭터 방향 정의 변수(왼쪽)
self.DIR_RIGHT = 3 # 캐릭터 방향 정의 변수(오른쪽)
self.ANIMATION = [0, 1, 0, 2]
self.idx = 0
self.tmr = 0
self.stage = 1 # 스테이지 수
self.score = 0 # 점수
self.candy = 0 # 각 스테이지에 있는 사탕 수
self.life = 3 # 펜펜의 목숨 수
self.pen_x = 0 # 펜펜의 X 좌표
self.pen_y = 0 # 펜펜의 Y 좌표
self.pen_d = 0 # 펜펜의 방향
self.pen_a = 0 # 펜펜의 이미지 번호
self.red_x = 0 # 레드의 X 좌표
self.red_y = 0 # 레드의 Y 좌표
self.red_d = 0 # 레드의 방향
self.red_a = 0 # 레드의 이미지 번호
self.red_sx = 0 # 레드 시작 위치 X 좌표
self.red_sy = 0 # 레드 시작 위치 Y 좌표
self.map_data = []
self.initUI()
timer = QTimer(self)
timer.setInterval(100)
timer.timeout.connect(self.main_proc) # 100밀리초마다 main_proc 실행
timer.start()
def initUI(self):
self.setFixedSize(720, 540) # 창 크기 고정
self.setWindowTitle('PenPen\'s Maze Adventure')
self.set_stage()
self.set_chara_pos()
def set_stage(self): # 스테이지 데이터 설정 함수
if self.stage == 1:
self.map_data = [ # 미로 데이터
[0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0],
[0, 2, 3, 3, 2, 1, 1, 2, 3, 3, 2, 0],
[0, 3, 0, 0, 3, 3, 3, 3, 0, 0, 3, 0],
[0, 3, 1, 1, 3, 0, 0, 3, 1, 1, 3, 0],
[0, 3, 2, 2, 3, 0, 0, 3, 2, 2, 3, 0],
[0, 3, 0, 0, 3, 1, 1, 3, 0, 0, 3, 0],
[0, 3, 1, 1, 3, 3, 3, 3, 1, 1, 3, 0],
[0, 2, 3, 3, 2, 0, 0, 2, 3, 3, 2, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
self.candy = 32 # 사탕 수
self.red_sx = 600
self.red_sy = 420
if self.stage == 2:
self.map_data = [
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 0],
[0, 3, 3, 0, 2, 1, 1, 2, 0, 3, 3, 0],
[0, 3, 3, 1, 3, 3, 3, 3, 1, 3, 3, 0],
[0, 2, 1, 3, 3, 3, 3, 3, 3, 1, 2, 0],
[0, 3, 3, 0, 3, 3, 3, 3, 0, 3, 3, 0],
[0, 3, 3, 1, 2, 1, 1, 2, 1, 3, 3, 0],
[0, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
self.candy = 38
self.red_sx = 600
self.red_sy = 60
if self.stage == 3:
self.map_data = [
[0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0],
[0, 2, 1, 3, 1, 2, 2, 3, 3, 3, 3, 0],
[0, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 0],
[0, 2, 1, 1, 1, 2, 2, 1, 1, 1, 1, 0],
[0, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, 0],
[0, 1, 1, 2, 0, 2, 2, 0, 1, 1, 2, 0],
[0, 3, 3, 3, 1, 1, 1, 0, 3, 3, 3, 0],
[0, 3, 3, 3, 2, 2, 2, 0, 3, 3, 3, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
self.candy = 23
self.red_sx = 600
self.red_sy = 420
def set_chara_pos(self): # 캐릭터 시작 위치 설정 함수
self.pen_x = 60 # 펜펜의 시작 x, y 좌표 대입
self.pen_y = 60
self.pen_d = self.DIR_DOWN # 펜펜의 방향을 아래로
self.pen_a = 3 # 펜펜 그림 번호 대입
self.red_x = self.red_sx # 레드의 시작 x, y 좌표 대입
self.red_y = self.red_sy
self.red_d = self.DIR_DOWN # 레드의 방향을 아래로
self.red_a = 3 # 레드 그림 번호 대입
def check_wall(self, cx, cy, di, dot): # 지정한 방향에 벽 존재 여부 확인 함수
chk = False # chk에 False 대입
if di == self.DIR_UP: # 위쪽일 경우
mx = int(cx / 60) # mx와 my에 리스트의 좌상 방향 확인용 값 대입
my = int((cy - dot) / 60)
if self.map_data[my][mx] <= 1: # 좌상
chk = True # chk에 True 대입
mx = int((cx + 59) / 60) # 리스트의 우상 방향 확인용 값 대입
if self.map_data[my][mx] <= 1: # 우상
chk = True # chk에 True 대입
if di == self.DIR_DOWN: # 아래쪽일 경우
mx = int(cx / 60) # mx와 my에 리스트의 좌하 방향 확인용 값 대입
my = int((cy + 59 + dot) / 60)
if self.map_data[my][mx] <= 1: # 좌하
chk = True
mx = int((cx + 59) / 60) # 리스트의 우하 방향 확인용 값 대입
if self.map_data[my][mx] <= 1: # 우하
chk = True
if di == self.DIR_LEFT: # 왼쪽일 경우
mx = int((cx - dot) / 60) # mx와 my에 리스트의 좌상 방향 확인용 값 대입
my = int(cy / 60)
if self.map_data[my][mx] <= 1: # 좌상
chk = True
my = int((cy + 59) / 60) # 리스트의 좌하 방향 확인용 값 대입
if self.map_data[my][mx] <= 1: # 좌하
chk = True
if di == self.DIR_RIGHT: # 오른쪽일 경우
mx = int((cx + 59 + dot) / 60) # mx와 my에 리스트의 우상 방향 확인용 값 대입
my = int(cy / 60)
if self.map_data[my][mx] <= 1: # 우상
chk = True
my = int((cy + 59) / 60) # 리스트의 우하 방향 확인용 값 대입
if self.map_data[my][mx] <= 1: # 우하
chk = True
return chk # chk 값 반환
def move_penpen(self): # 펜펜(캐릭터) 이동 함수
if self.key == Qt.Key_Up: # 위쪽 방향키를 눌렀다면
self.pen_d = self.DIR_UP # 펜펜의 방향을 위쪽으로
if self.check_wall(self.pen_x, self.pen_y, self.pen_d, 20) == False: # 해당 방향이 벽이 아니라면
self.pen_y = self.pen_y - 20 # 위쪽으로 이동
if self.key == Qt.Key_Down: # 아래쪽
self.pen_d = self.DIR_DOWN # 펜펜의 방향을 아래쪽으로
if self.check_wall(self.pen_x, self.pen_y, self.pen_d, 20) == False:
self.pen_y = self.pen_y + 20
if self.key == Qt.Key_Left: # 왼쪽
self.pen_d = self.DIR_LEFT # 펜펜의 방향을 왼쪽으로
if self.check_wall(self.pen_x, self.pen_y, self.pen_d, 20) == False:
self.pen_x = self.pen_x - 20
if self.key == Qt.Key_Right: # 오른쪽
self.pen_d = self.DIR_RIGHT # 펜펜의 방향을 오른쪽으로
if self.check_wall(self.pen_x, self.pen_y, self.pen_d, 20) == False:
self.pen_x = self.pen_x + 20
self.pen_a = self.pen_d * 3 + self.ANIMATION[self.tmr % 4] # 펜펜 애니메이션(이미지) 번호 계산
mx = int(self.pen_x / 60) # mx, my에 펜펜이 있는 위치의 리스트로 확인할 값 대입
my = int(self.pen_y / 60)
if self.map_data[my][mx] == 3: # 사탕 위치에 들어가면
self.score = self.score + 100 # 점수 추가
self.map_data[my][mx] = 2 # 사탕 삭제
self.candy = self.candy - 1 # 사탕 개수 감소
def move_enemy(self): # 레드(적) 이동 함수
speed = 10 # 레드의 이동 속도
if self.red_x % 60 == 0 and self.red_y % 60 == 0: # 칸의 정확한 위치에 있는 경우
self.red_d = random.randint(0, 6) # 무작위로 방향 변경
if self.red_d >= 4: # 난수가 4 이상인 경우 주인공 추적
if self.pen_y < self.red_y: # 펜펜이 위쪽에 있다면
self.red_d = self.DIR_UP # 레드의 방향을 위쪽으로
if self.pen_y > self.red_y:
self.red_d = self.DIR_DOWN
if self.pen_x < self.red_x:
self.red_d = self.DIR_LEFT
if self.pen_x > self.red_x:
self.red_d = self.DIR_RIGHT
if self.red_d == self.DIR_UP: # 레드가 위쪽을 향한 경우
if self.check_wall(self.red_x, self.red_y, self.red_d, speed) == False: # 해당 방향이 벽이 아니라면
self.red_y = self.red_y - speed # 이동
if self.red_d == self.DIR_DOWN:
if self.check_wall(self.red_x, self.red_y, self.red_d, speed) == False:
self.red_y = self.red_y + speed
if self.red_d == self.DIR_LEFT:
if self.check_wall(self.red_x, self.red_y, self.red_d, speed) == False:
self.red_x = self.red_x - speed
if self.red_d == self.DIR_RIGHT:
if self.check_wall(self.red_x, self.red_y, self.red_d, speed) == False:
self.red_x = self.red_x + speed
self.red_a = self.red_d * 3 + self.ANIMATION[self.tmr % 4] # 레드의 애니메이션 번호 계산
if abs(self.red_x - self.pen_x) <= 40 and abs(self.red_y - self.pen_y) <= 40: # 펜펜과 접촉했는지 판단해서 접촉했다면
self.idx = 2 # 게임 오버 처리로 이동
self.tmr = 0
def main_proc(self):
self.tmr = self.tmr + 1 # 타이머 값 증가
if self.idx == 0: # 인덱스 0 처리(타이틀 화면)
if self.key == Qt.Key_Space: # [SPACE]키를 누르면
self.stage = 1
self.score = 0 # 점수 0 대입
self.life = 3 # 남은 목숨 3 대입
self.set_stage() # 스테이지 데이터 세트
self.set_chara_pos() # 각 캐릭터 시작 위치 설정
self.idx = 1 # 인덱스를 1로 변경, 게임 시작
if self.idx == 1: # 인덱스 1 처리(게임 플레이)
self.move_penpen() # 펜펜 이동
self.move_enemy() # 레드 이동
if self.candy == 0: # 사탕을 모두 먹었다면
self.idx = 4 # 스테이지 클리어 처리로 이동
self.tmr = 0
if self.idx == 2: # 인덱스 2 처리(적에게 당한 처리)
if self.tmr == 1:
self.life = self.life - 1 # 잔여 수 1 감소
if self.tmr == 30:
if self.life == 0: # 잔여 수가 0이면
self.idx = 3 # 게임 오버 처리로 이동
self.tmr = 0
else: # 그렇지 않으면
self.set_chara_pos() # 캐릭터를 초기 위치로 이동
self.idx = 1 # 다시 플레이
if self.idx == 3: # 인덱스 3 처리(게임 오버)
if self.tmr == 50:
self.idx = 0 # 타이틀 화면으로 이동
if self.idx == 4: # 인덱스 4 처리(스테이지 클리어)
if self.tmr == 30:
if self.stage < 3:
self.stage = self.stage + 1
self.set_stage()
self.set_chara_pos()
self.idx = 1
else:
self.idx = 0 # 타이틀 화면으로 이동
self.update()
def draw_text(self, qp, txt, x, y, siz, col): # 그림자를 포함한 문자열을 표시
qp.setFont(QFont('Times New Roman', siz, QFont.Bold)) # 폰트 정의
qp.setPen(Qt.black) # 문자열 그림자(2픽셀 어긋나게 검게 표시)
qp.drawText(x + 2, y + 2, txt)
qp.setPen(col) # 지정한 색으로 문자열 표시
qp.drawText(x, y, txt)
def paintEvent(self, e):
qp = QPainter()
qp.begin(self)
for y in range(9):
for x in range(12):
qp.drawImage(QRect(x * 60, y * 60, 60, 60), self.img_bg[self.map_data[y][x]]) # 맵 칩으로 미로 그리기
qp.drawImage(QRect(self.pen_x, self.pen_y, 60, 60), self.img_pen[self.pen_a]) # PenPen 표시
qp.drawImage(QRect(self.red_x, self.red_y, 60, 60), self.img_red[self.red_a]) # 레드 표시
self.draw_text(qp, 'SCORE ' + str(self.score), 100, 30, 30, Qt.white) # 점수 표시
self.draw_text(qp, 'STAGE ' + str(self.stage), 440, 30, 30, QColor(191, 255, 0)) # 스테이지 수 표시
for i in range(self.life): # 펜펜의 남은 목숨 수만큼 반복
qp.drawImage(QRect(60 + i * 50, 500, self.img_pen[12].width(), self.img_pen[12].height()), self.img_pen[12]) # 펜펜의 남은 목숨 표시
if self.idx == 0: # 타이틀 화면 표시
qp.drawImage(QRect(35, 100, self.img_title.width(), self.img_title.height()), self.img_title)
if self.tmr % 10 < 5: # 문자열이 깜빡거리는 처리
self.draw_text(qp, 'Press SPACE !', 250, 380, 30, Qt.yellow)
if self.idx == 2: # 적에게 당했을 때 문자 표시
self.draw_text(qp, 'MISS', 295, 270, 40, Qt.red)
if self.idx == 3: # 게임 오버 문자 표시
self.draw_text(qp, 'GAME OVER', 200, 270, 40, Qt.red)
if self.idx == 4: # 스테이지 클리어 문자 표시
if self.stage < 3:
self.draw_text(qp, 'STAGE CLEAR', 180, 270, 40, QColor(255, 170, 170))
else:
self.draw_text(qp, 'ALL STAGE CLEAR!', 80, 270, 40, QColor(210, 168, 212))
qp.end()
def keyPressEvent(self, e):
self.key = e.key()
def keyReleaseEvent(self, e):
self.key = None
if __name__ == "__main__":
app = QApplication(sys.argv)
main_W = WindowClass()
main_W.show()
sys.exit(app.exec_())
life라는 변수로 펜펜의 남은 목숨 수를 관리한다. 만약 레드에게 닿았다면 idx를 2로 변경한다.
idx 2에서는 life를 감소시키고, 0이되면 게임 오버인 idx 3으로 이동 시키고, 남은 목숨이 있다면 set_chara_pos 함수를 통해 캐릭터 좌표를 시작 위치로 되돌리고 게임을 다시 시작한다.
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
import random
class WindowClass(QWidget):
def __init__(self):
super().__init__()
self.key = None
self.img_title = QImage('Python_workspace/python_game/image/dot_eat/title.png')
self.img_bg = [ # 맵 칩
QImage('Python_workspace\python_game\image\dot_eat\chip00.png'),
QImage('Python_workspace\python_game\image\dot_eat\chip01.png'),
QImage('Python_workspace\python_game\image\dot_eat\chip02.png'),
QImage('Python_workspace\python_game\image\dot_eat\chip03.png')
]
self.img_pen = [ # 캐릭터 이미지
QImage('Python_workspace\python_game\image\dot_eat\pen00.png'), # 위쪽
QImage('Python_workspace\python_game\image\dot_eat\pen01.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen02.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen03.png'), # 아래쪽
QImage('Python_workspace\python_game\image\dot_eat\pen04.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen05.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen06.png'), # 왼쪽
QImage('Python_workspace\python_game\image\dot_eat\pen07.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen08.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen09.png'), # 오른쪽
QImage('Python_workspace\python_game\image\dot_eat\pen10.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen11.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen_face.png')
]
self.img_red = [
QImage('Python_workspace/python_game/image/dot_eat/red00.png'),
QImage('Python_workspace/python_game/image/dot_eat/red01.png'),
QImage('Python_workspace/python_game/image/dot_eat/red02.png'),
QImage('Python_workspace/python_game/image/dot_eat/red03.png'),
QImage('Python_workspace/python_game/image/dot_eat/red04.png'),
QImage('Python_workspace/python_game/image/dot_eat/red05.png'),
QImage('Python_workspace/python_game/image/dot_eat/red06.png'),
QImage('Python_workspace/python_game/image/dot_eat/red07.png'),
QImage('Python_workspace/python_game/image/dot_eat/red08.png'),
QImage('Python_workspace/python_game/image/dot_eat/red09.png'),
QImage('Python_workspace/python_game/image/dot_eat/red10.png'),
QImage('Python_workspace/python_game/image/dot_eat/red11.png')
]
self.img_kuma = [
QImage('Python_workspace\python_game\image\dot_eat\kuma00.png'),
QImage('Python_workspace\python_game\image\dot_eat\kuma01.png'),
QImage('Python_workspace\python_game\image\dot_eat\kuma02.png')
]
self.pen_face_width = self.img_pen[12].width()
self.pen_face_height = self.img_pen[12].height()
self.kuma_width = self.img_kuma[0].width()
self.kuma_height = self.img_kuma[0].height()
self.DIR_UP = 0 # 캐릭터 방향 정의 변수(위쪽)
self.DIR_DOWN = 1 # 캐릭터 방향 정의 변수(아래쪽)
self.DIR_LEFT = 2 # 캐릭터 방향 정의 변수(왼쪽)
self.DIR_RIGHT = 3 # 캐릭터 방향 정의 변수(오른쪽)
self.ANIMATION = [0, 1, 0, 2]
self.idx = 0
self.tmr = 0
self.stage = 1 # 스테이지 수
self.score = 0 # 점수
self.candy = 0 # 각 스테이지에 있는 사탕 수
self.life = 3 # 펜펜의 목숨 수
self.pen_x = 0 # 펜펜의 X 좌표
self.pen_y = 0 # 펜펜의 Y 좌표
self.pen_d = 0 # 펜펜의 방향
self.pen_a = 0 # 펜펜의 이미지 번호
self.red_x = 0 # 레드의 X 좌표
self.red_y = 0 # 레드의 Y 좌표
self.red_d = 0 # 레드의 방향
self.red_a = 0 # 레드의 이미지 번호
self.red_sx = 0 # 레드 시작 위치 X 좌표
self.red_sy = 0 # 레드 시작 위치 Y 좌표
self.kuma_x = 0 # 쿠마의 X, Y 좌표
self.kuma_y = 0
self.kuma_d = 0 # 쿠마의 방향
self.kuma_a = 0 # 쿠마의 이미지 번호
self.kuma_sx = 0 # 쿠마의 시작 X, Y 좌표
self.kuma_sy = 0
self.kuma_sd = 0 # 시작 시 쿠마의 방향
self.map_data = []
self.initUI()
timer = QTimer(self)
timer.setInterval(100)
timer.timeout.connect(self.main_proc) # 100밀리초마다 main_proc 실행
timer.start()
def initUI(self):
self.setFixedSize(720, 540) # 창 크기 고정
self.setWindowTitle('PenPen\'s Maze Adventure')
self.set_stage()
self.set_chara_pos()
def set_stage(self): # 스테이지 데이터 설정 함수
if self.stage == 1:
self.map_data = [ # 미로 데이터
[0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0],
[0, 2, 3, 3, 2, 1, 1, 2, 3, 3, 2, 0],
[0, 3, 0, 0, 3, 3, 3, 3, 0, 0, 3, 0],
[0, 3, 1, 1, 3, 0, 0, 3, 1, 1, 3, 0],
[0, 3, 2, 2, 3, 0, 0, 3, 2, 2, 3, 0],
[0, 3, 0, 0, 3, 1, 1, 3, 0, 0, 3, 0],
[0, 3, 1, 1, 3, 3, 3, 3, 1, 1, 3, 0],
[0, 2, 3, 3, 2, 0, 0, 2, 3, 3, 2, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
self.candy = 32 # 사탕 수
self.red_sx = 600
self.red_sy = 420
self.kuma_sd = -1 # 쿠마가 출현하지 않음
if self.stage == 2:
self.map_data = [
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 0],
[0, 3, 3, 0, 2, 1, 1, 2, 0, 3, 3, 0],
[0, 3, 3, 1, 3, 3, 3, 3, 1, 3, 3, 0],
[0, 2, 1, 3, 3, 3, 3, 3, 3, 1, 2, 0],
[0, 3, 3, 0, 3, 3, 3, 3, 0, 3, 3, 0],
[0, 3, 3, 1, 2, 1, 1, 2, 1, 3, 3, 0],
[0, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
self.candy = 38
self.red_sx = 600
self.red_sy = 60
self.kuma_sx = 300
self.kuma_sy = 240
self.kuma_sd = self.DIR_LEFT
if self.stage == 3:
self.map_data = [
[0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0],
[0, 2, 1, 3, 1, 2, 2, 3, 3, 3, 3, 0],
[0, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 0],
[0, 2, 1, 1, 1, 2, 2, 1, 1, 1, 1, 0],
[0, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, 0],
[0, 1, 1, 2, 0, 2, 2, 0, 1, 1, 2, 0],
[0, 3, 3, 3, 1, 1, 1, 0, 3, 3, 3, 0],
[0, 3, 3, 3, 2, 2, 2, 0, 3, 3, 3, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
self.candy = 23
self.red_sx = 600
self.red_sy = 420
self.kuma_sx = 300
self.kuma_sy = 240
self.kuma_sd = self.DIR_RIGHT
def set_chara_pos(self): # 캐릭터 시작 위치 설정 함수
self.pen_x = 60 # 펜펜의 시작 x, y 좌표 대입
self.pen_y = 60
self.pen_d = self.DIR_DOWN # 펜펜의 방향을 아래로
self.pen_a = 3 # 펜펜 그림 번호 대입
self.red_x = self.red_sx # 레드의 시작 x, y 좌표 대입
self.red_y = self.red_sy
self.red_d = self.DIR_DOWN # 레드의 방향을 아래로
self.red_a = 3 # 레드 그림 번호 대입
self.kuma_x = self.kuma_sx
self.kuma_y = self.kuma_sy
self.kuma_d = self.kuma_sd
self.kuma_a = 0
def check_wall(self, cx, cy, di, dot): # 지정한 방향에 벽 존재 여부 확인 함수
chk = False # chk에 False 대입
if di == self.DIR_UP: # 위쪽일 경우
mx = int(cx / 60) # mx와 my에 리스트의 좌상 방향 확인용 값 대입
my = int((cy - dot) / 60)
if self.map_data[my][mx] <= 1: # 좌상
chk = True # chk에 True 대입
mx = int((cx + 59) / 60) # 리스트의 우상 방향 확인용 값 대입
if self.map_data[my][mx] <= 1: # 우상
chk = True # chk에 True 대입
if di == self.DIR_DOWN: # 아래쪽일 경우
mx = int(cx / 60) # mx와 my에 리스트의 좌하 방향 확인용 값 대입
my = int((cy + 59 + dot) / 60)
if self.map_data[my][mx] <= 1: # 좌하
chk = True
mx = int((cx + 59) / 60) # 리스트의 우하 방향 확인용 값 대입
if self.map_data[my][mx] <= 1: # 우하
chk = True
if di == self.DIR_LEFT: # 왼쪽일 경우
mx = int((cx - dot) / 60) # mx와 my에 리스트의 좌상 방향 확인용 값 대입
my = int(cy / 60)
if self.map_data[my][mx] <= 1: # 좌상
chk = True
my = int((cy + 59) / 60) # 리스트의 좌하 방향 확인용 값 대입
if self.map_data[my][mx] <= 1: # 좌하
chk = True
if di == self.DIR_RIGHT: # 오른쪽일 경우
mx = int((cx + 59 + dot) / 60) # mx와 my에 리스트의 우상 방향 확인용 값 대입
my = int(cy / 60)
if self.map_data[my][mx] <= 1: # 우상
chk = True
my = int((cy + 59) / 60) # 리스트의 우하 방향 확인용 값 대입
if self.map_data[my][mx] <= 1: # 우하
chk = True
return chk # chk 값 반환
def move_penpen(self): # 펜펜(캐릭터) 이동 함수
if self.key == Qt.Key_Up: # 위쪽 방향키를 눌렀다면
self.pen_d = self.DIR_UP # 펜펜의 방향을 위쪽으로
if self.check_wall(self.pen_x, self.pen_y, self.pen_d, 20) == False: # 해당 방향이 벽이 아니라면
self.pen_y = self.pen_y - 20 # 위쪽으로 이동
if self.key == Qt.Key_Down: # 아래쪽
self.pen_d = self.DIR_DOWN # 펜펜의 방향을 아래쪽으로
if self.check_wall(self.pen_x, self.pen_y, self.pen_d, 20) == False:
self.pen_y = self.pen_y + 20
if self.key == Qt.Key_Left: # 왼쪽
self.pen_d = self.DIR_LEFT # 펜펜의 방향을 왼쪽으로
if self.check_wall(self.pen_x, self.pen_y, self.pen_d, 20) == False:
self.pen_x = self.pen_x - 20
if self.key == Qt.Key_Right: # 오른쪽
self.pen_d = self.DIR_RIGHT # 펜펜의 방향을 오른쪽으로
if self.check_wall(self.pen_x, self.pen_y, self.pen_d, 20) == False:
self.pen_x = self.pen_x + 20
self.pen_a = self.pen_d * 3 + self.ANIMATION[self.tmr % 4] # 펜펜 애니메이션(이미지) 번호 계산
mx = int(self.pen_x / 60) # mx, my에 펜펜이 있는 위치의 리스트로 확인할 값 대입
my = int(self.pen_y / 60)
if self.map_data[my][mx] == 3: # 사탕 위치에 들어가면
self.score = self.score + 100 # 점수 추가
self.map_data[my][mx] = 2 # 사탕 삭제
self.candy = self.candy - 1 # 사탕 개수 감소
def move_enemy(self): # 레드(적) 이동 함수
speed = 10 # 레드의 이동 속도
if self.red_x % 60 == 0 and self.red_y % 60 == 0: # 칸의 정확한 위치에 있는 경우
self.red_d = random.randint(0, 6) # 무작위로 방향 변경
if self.red_d >= 4: # 난수가 4 이상인 경우 주인공 추적
if self.pen_y < self.red_y: # 펜펜이 위쪽에 있다면
self.red_d = self.DIR_UP # 레드의 방향을 위쪽으로
if self.pen_y > self.red_y:
self.red_d = self.DIR_DOWN
if self.pen_x < self.red_x:
self.red_d = self.DIR_LEFT
if self.pen_x > self.red_x:
self.red_d = self.DIR_RIGHT
if self.red_d == self.DIR_UP: # 레드가 위쪽을 향한 경우
if self.check_wall(self.red_x, self.red_y, self.red_d, speed) == False: # 해당 방향이 벽이 아니라면
self.red_y = self.red_y - speed # 이동
if self.red_d == self.DIR_DOWN:
if self.check_wall(self.red_x, self.red_y, self.red_d, speed) == False:
self.red_y = self.red_y + speed
if self.red_d == self.DIR_LEFT:
if self.check_wall(self.red_x, self.red_y, self.red_d, speed) == False:
self.red_x = self.red_x - speed
if self.red_d == self.DIR_RIGHT:
if self.check_wall(self.red_x, self.red_y, self.red_d, speed) == False:
self.red_x = self.red_x + speed
self.red_a = self.red_d * 3 + self.ANIMATION[self.tmr % 4] # 레드의 애니메이션 번호 계산
if abs(self.red_x - self.pen_x) <= 40 and abs(self.red_y - self.pen_y) <= 40: # 펜펜과 접촉했는지 판단해서 접촉했다면
self.idx = 2 # 게임 오버 처리로 이동
self.tmr = 0
def move_enemy2(self): # 쿠마 이동 함수
speed = 5
if self.kuma_sd == -1: # kuma_sd 값이 -1이면 함수 이탈
return
if self.kuma_d == self.DIR_UP: # 쿠마가 위쪽을 향한 경우
if self.check_wall(self.kuma_x, self.kuma_y, self.kuma_d, speed) == False: # 해당 방향이 벽이 아니라면
self.kuma_y = self.kuma_y - speed # 이동
else: # 벽이라면
self.kuma_d = self.DIR_DOWN # 아래쪽으로 방향 변경
elif self.kuma_d == self.DIR_DOWN:
if self.check_wall(self.kuma_x, self.kuma_y, self.kuma_d, speed) == False:
self.kuma_y = self.kuma_y + speed
else:
self.kuma_d = self.DIR_UP
elif self.kuma_d == self.DIR_LEFT:
if self.check_wall(self.kuma_x, self.kuma_y, self.kuma_d, speed) == False:
self.kuma_x = self.kuma_x - speed
else:
self.kuma_d = self.DIR_RIGHT
elif self.kuma_d == self.DIR_RIGHT:
if self.check_wall(self.kuma_x, self.kuma_y, self.kuma_d, speed) == False:
self.kuma_x = self.kuma_x + speed
else:
self.kuma_d = self.DIR_LEFT
self.kuma_a = self.ANIMATION[self.tmr % 4] # 레드의 애니메이션 번호 계산
if abs(self.kuma_x - self.pen_x) <= 40 and abs(self.kuma_y - self.pen_y) <= 40: # 펜펜과 접촉했는지 판단해서 접촉했다면
self.idx = 2 # 게임 오버 처리로 이동
self.tmr = 0
def main_proc(self):
self.tmr = self.tmr + 1 # 타이머 값 증가
if self.idx == 0: # 인덱스 0 처리(타이틀 화면)
if self.key == Qt.Key_Space: # [SPACE]키를 누르면
self.stage = 1
self.score = 0 # 점수 0 대입
self.life = 3 # 남은 목숨 3 대입
self.set_stage() # 스테이지 데이터 세트
self.set_chara_pos() # 각 캐릭터 시작 위치 설정
self.idx = 1 # 인덱스를 1로 변경, 게임 시작
if self.idx == 1: # 인덱스 1 처리(게임 플레이)
self.move_penpen() # 펜펜 이동
self.move_enemy() # 레드 이동
self.move_enemy2()
if self.candy == 0: # 사탕을 모두 먹었다면
self.idx = 4 # 스테이지 클리어 처리로 이동
self.tmr = 0
if self.idx == 2: # 인덱스 2 처리(적에게 당한 처리)
if self.tmr == 1:
self.life = self.life - 1 # 잔여 수 1 감소
if self.tmr == 30:
if self.life == 0: # 잔여 수가 0이면
self.idx = 3 # 게임 오버 처리로 이동
self.tmr = 0
else: # 그렇지 않으면
self.set_chara_pos() # 캐릭터를 초기 위치로 이동
self.idx = 1 # 다시 플레이
if self.idx == 3: # 인덱스 3 처리(게임 오버)
if self.tmr == 50:
self.idx = 0 # 타이틀 화면으로 이동
if self.idx == 4: # 인덱스 4 처리(스테이지 클리어)
if self.tmr == 30:
if self.stage < 3:
self.stage = self.stage + 1
self.set_stage()
self.set_chara_pos()
self.idx = 1
else:
self.idx = 0 # 타이틀 화면으로 이동
self.update()
def draw_text(self, qp, txt, x, y, siz, col): # 그림자를 포함한 문자열을 표시
qp.setFont(QFont('Times New Roman', siz, QFont.Bold)) # 폰트 정의
qp.setPen(Qt.black) # 문자열 그림자(2픽셀 어긋나게 검게 표시)
qp.drawText(x + 2, y + 2, txt)
qp.setPen(col) # 지정한 색으로 문자열 표시
qp.drawText(x, y, txt)
def paintEvent(self, e):
qp = QPainter()
qp.begin(self)
for y in range(9):
for x in range(12):
qp.drawImage(QRect(x * 60, y * 60, 60, 60), self.img_bg[self.map_data[y][x]]) # 맵 칩으로 미로 그리기
qp.drawImage(QRect(self.pen_x, self.pen_y, 60, 60), self.img_pen[self.pen_a]) # PenPen 표시
qp.drawImage(QRect(self.red_x, self.red_y, 60, 60), self.img_red[self.red_a]) # 레드 표시
if self.kuma_sd != -1: # kuma_sd 값이 -1이 아니면 쿠마 표시
qp.drawImage(QRect(self.kuma_x, self.kuma_y, self.kuma_width, self.kuma_height), self.img_kuma[self.kuma_a])
self.draw_text(qp, 'SCORE ' + str(self.score), 100, 30, 30, Qt.white) # 점수 표시
self.draw_text(qp, 'STAGE ' + str(self.stage), 440, 30, 30, QColor(191, 255, 0)) # 스테이지 수 표시
for i in range(self.life): # 펜펜의 남은 목숨 수만큼 반복
qp.drawImage(QRect(60 + i * 50, 500, self.pen_face_width, self.pen_face_height), self.img_pen[12]) # 펜펜의 남은 목숨 표시
if self.idx == 0: # 타이틀 화면 표시
qp.drawImage(QRect(35, 100, self.img_title.width(), self.img_title.height()), self.img_title)
if self.tmr % 10 < 5: # 문자열이 깜빡거리는 처리
self.draw_text(qp, 'Press SPACE !', 250, 380, 30, Qt.yellow)
if self.idx == 2: # 적에게 당했을 때 문자 표시
self.draw_text(qp, 'MISS', 295, 270, 40, Qt.red)
if self.idx == 3: # 게임 오버 문자 표시
self.draw_text(qp, 'GAME OVER', 200, 270, 40, Qt.red)
if self.idx == 4: # 스테이지 클리어 문자 표시
if self.stage < 3:
self.draw_text(qp, 'STAGE CLEAR', 180, 270, 40, QColor(255, 170, 170))
else:
self.draw_text(qp, 'ALL STAGE CLEAR!', 80, 270, 40, QColor(210, 168, 212))
qp.end()
def keyPressEvent(self, e):
self.key = e.key()
def keyReleaseEvent(self, e):
self.key = None
if __name__ == "__main__":
app = QApplication(sys.argv)
main_W = WindowClass()
main_W.show()
sys.exit(app.exec_())
변경 및 추가된 부분 : move_enemy2, paintEvent, set_chara_pos, set_stage
스테이지 2부터 쿠마가 나타나서 좌우로 왕복을 계속한다. move_enemy2가 쿠마의 이동 함수인데 보면 벽에 부딪히면 kuma_d에 반대 방향의 값을 대입해 같은 경로를 왕복하게 한다.
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
import random
class WindowClass(QWidget):
def __init__(self):
super().__init__()
self.key = None
self.img_title = QImage('Python_workspace/python_game/image/dot_eat/title.png')
self.img_bg = [ # 맵 칩
QImage('Python_workspace\python_game\image\dot_eat\chip00.png'),
QImage('Python_workspace\python_game\image\dot_eat\chip01.png'),
QImage('Python_workspace\python_game\image\dot_eat\chip02.png'),
QImage('Python_workspace\python_game\image\dot_eat\chip03.png')
]
self.img_pen = [ # 캐릭터 이미지
QImage('Python_workspace\python_game\image\dot_eat\pen00.png'), # 위쪽
QImage('Python_workspace\python_game\image\dot_eat\pen01.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen02.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen03.png'), # 아래쪽
QImage('Python_workspace\python_game\image\dot_eat\pen04.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen05.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen06.png'), # 왼쪽
QImage('Python_workspace\python_game\image\dot_eat\pen07.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen08.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen09.png'), # 오른쪽
QImage('Python_workspace\python_game\image\dot_eat\pen10.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen11.png'),
QImage('Python_workspace\python_game\image\dot_eat\pen_face.png')
]
self.img_red = [
QImage('Python_workspace/python_game/image/dot_eat/red00.png'),
QImage('Python_workspace/python_game/image/dot_eat/red01.png'),
QImage('Python_workspace/python_game/image/dot_eat/red02.png'),
QImage('Python_workspace/python_game/image/dot_eat/red03.png'),
QImage('Python_workspace/python_game/image/dot_eat/red04.png'),
QImage('Python_workspace/python_game/image/dot_eat/red05.png'),
QImage('Python_workspace/python_game/image/dot_eat/red06.png'),
QImage('Python_workspace/python_game/image/dot_eat/red07.png'),
QImage('Python_workspace/python_game/image/dot_eat/red08.png'),
QImage('Python_workspace/python_game/image/dot_eat/red09.png'),
QImage('Python_workspace/python_game/image/dot_eat/red10.png'),
QImage('Python_workspace/python_game/image/dot_eat/red11.png')
]
self.img_kuma = [
QImage('Python_workspace\python_game\image\dot_eat\kuma00.png'),
QImage('Python_workspace\python_game\image\dot_eat\kuma01.png'),
QImage('Python_workspace\python_game\image\dot_eat\kuma02.png')
]
self.img_ending = QImage('Python_workspace\python_game\image\dot_eat\ending.png')
self.pen_face_width = self.img_pen[12].width()
self.pen_face_height = self.img_pen[12].height()
self.kuma_width = self.img_kuma[0].width()
self.kuma_height = self.img_kuma[0].height()
self.DIR_UP = 0 # 캐릭터 방향 정의 변수(위쪽)
self.DIR_DOWN = 1 # 캐릭터 방향 정의 변수(아래쪽)
self.DIR_LEFT = 2 # 캐릭터 방향 정의 변수(왼쪽)
self.DIR_RIGHT = 3 # 캐릭터 방향 정의 변수(오른쪽)
self.ANIMATION = [0, 1, 0, 2]
self.BLINK = ['#fff', '#ffc', '#ff8', '#fe4', '#ff8', '#ffc']
self.idx = 0
self.tmr = 0
self.stage = 1 # 스테이지 수
self.score = 0 # 점수
self.candy = 0 # 각 스테이지에 있는 사탕 수
self.life = 3 # 펜펜의 목숨 수
self.pen_x = 0 # 펜펜의 X 좌표
self.pen_y = 0 # 펜펜의 Y 좌표
self.pen_d = 0 # 펜펜의 방향
self.pen_a = 0 # 펜펜의 이미지 번호
self.red_x = 0 # 레드의 X 좌표
self.red_y = 0 # 레드의 Y 좌표
self.red_d = 0 # 레드의 방향
self.red_a = 0 # 레드의 이미지 번호
self.red_sx = 0 # 레드 시작 위치 X 좌표
self.red_sy = 0 # 레드 시작 위치 Y 좌표
self.kuma_x = 0 # 쿠마의 X, Y 좌표
self.kuma_y = 0
self.kuma_d = 0 # 쿠마의 방향
self.kuma_a = 0 # 쿠마의 이미지 번호
self.kuma_sx = 0 # 쿠마의 시작 X, Y 좌표
self.kuma_sy = 0
self.kuma_sd = 0 # 시작 시 쿠마의 방향
self.map_data = []
self.initUI()
timer = QTimer(self)
timer.setInterval(100)
timer.timeout.connect(self.main_proc) # 100밀리초마다 main_proc 실행
timer.start()
def initUI(self):
self.setFixedSize(720, 540) # 창 크기 고정
self.setWindowTitle('PenPen\'s Maze Adventure')
self.set_stage()
self.set_chara_pos()
def set_stage(self): # 스테이지 데이터 설정 함수
if self.stage == 1:
self.map_data = [ # 미로 데이터
[0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0],
[0, 2, 3, 3, 2, 1, 1, 2, 3, 3, 2, 0],
[0, 3, 0, 0, 3, 3, 3, 3, 0, 0, 3, 0],
[0, 3, 1, 1, 3, 0, 0, 3, 1, 1, 3, 0],
[0, 3, 2, 2, 3, 0, 0, 3, 2, 2, 3, 0],
[0, 3, 0, 0, 3, 1, 1, 3, 0, 0, 3, 0],
[0, 3, 1, 1, 3, 3, 3, 3, 1, 1, 3, 0],
[0, 2, 3, 3, 2, 0, 0, 2, 3, 3, 2, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
self.candy = 32 # 사탕 수
self.red_sx = 600
self.red_sy = 420
self.kuma_sd = -1 # 쿠마가 출현하지 않음
if self.stage == 2:
self.map_data = [
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 0],
[0, 3, 3, 0, 2, 1, 1, 2, 0, 3, 3, 0],
[0, 3, 3, 1, 3, 3, 3, 3, 1, 3, 3, 0],
[0, 2, 1, 3, 3, 3, 3, 3, 3, 1, 2, 0],
[0, 3, 3, 0, 3, 3, 3, 3, 0, 3, 3, 0],
[0, 3, 3, 1, 2, 1, 1, 2, 1, 3, 3, 0],
[0, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
self.candy = 38
self.red_sx = 600
self.red_sy = 60
self.kuma_sx = 300
self.kuma_sy = 240
self.kuma_sd = self.DIR_LEFT
if self.stage == 3:
self.map_data = [
[0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0],
[0, 2, 1, 3, 1, 2, 2, 3, 3, 3, 3, 0],
[0, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 0],
[0, 2, 1, 1, 1, 2, 2, 1, 1, 1, 1, 0],
[0, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, 0],
[0, 1, 1, 2, 0, 2, 2, 0, 1, 1, 2, 0],
[0, 3, 3, 3, 1, 1, 1, 0, 3, 3, 3, 0],
[0, 3, 3, 3, 2, 2, 2, 0, 3, 3, 3, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
self.candy = 23
self.red_sx = 600
self.red_sy = 420
self.kuma_sx = 300
self.kuma_sy = 240
self.kuma_sd = self.DIR_RIGHT
if self.stage == 4:
self.map_data = [
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0],
[0, 3, 0, 3, 3, 1, 3, 0, 3, 0, 3, 0],
[0, 3, 1, 0, 3, 3, 3, 0, 3, 1, 3, 0],
[0, 3, 3, 0, 1, 1, 1, 0, 3, 3, 3, 0],
[0, 3, 0, 1, 3, 3, 3, 1, 3, 1, 1, 0],
[0, 3, 1, 3, 3, 1, 3, 3, 3, 3, 3, 0],
[0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0]
]
self.candy = 50
self.red_sx = 120
self.red_sy = 240
self.kuma_sx = 480
self.kuma_sy = 240
self.kuma_sd = self.DIR_UP
if self.stage == 5:
self.map_data = [
[0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 2, 0, 3, 3, 3, 3, 3, 3, 3, 3, 0],
[0, 2, 0, 3, 0, 1, 3, 3, 1, 0, 3, 0],
[0, 2, 0, 3, 0, 3, 3, 3, 3, 0, 3, 0],
[0, 2, 1, 3, 1, 1, 3, 3, 1, 1, 3, 0],
[0, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 0],
[0, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 0],
[0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
self.candy = 40
self.red_sx = 600
self.red_sy = 420
self.kuma_sx = 360
self.kuma_sy = 180
self.kuma_sd = self.DIR_RIGHT
def set_chara_pos(self): # 캐릭터 시작 위치 설정 함수
self.pen_x = 60 # 펜펜의 시작 x, y 좌표 대입
self.pen_y = 60
self.pen_d = self.DIR_DOWN # 펜펜의 방향을 아래로
self.pen_a = 3 # 펜펜 그림 번호 대입
self.red_x = self.red_sx # 레드의 시작 x, y 좌표 대입
self.red_y = self.red_sy
self.red_d = self.DIR_DOWN # 레드의 방향을 아래로
self.red_a = 3 # 레드 그림 번호 대입
self.kuma_x = self.kuma_sx
self.kuma_y = self.kuma_sy
self.kuma_d = self.kuma_sd
self.kuma_a = 0
def check_wall(self, cx, cy, di, dot): # 지정한 방향에 벽 존재 여부 확인 함수
chk = False # chk에 False 대입
if di == self.DIR_UP: # 위쪽일 경우
mx = int(cx / 60) # mx와 my에 리스트의 좌상 방향 확인용 값 대입
my = int((cy - dot) / 60)
if self.map_data[my][mx] <= 1: # 좌상
chk = True # chk에 True 대입
mx = int((cx + 59) / 60) # 리스트의 우상 방향 확인용 값 대입
if self.map_data[my][mx] <= 1: # 우상
chk = True # chk에 True 대입
if di == self.DIR_DOWN: # 아래쪽일 경우
mx = int(cx / 60) # mx와 my에 리스트의 좌하 방향 확인용 값 대입
my = int((cy + 59 + dot) / 60)
if self.map_data[my][mx] <= 1: # 좌하
chk = True
mx = int((cx + 59) / 60) # 리스트의 우하 방향 확인용 값 대입
if self.map_data[my][mx] <= 1: # 우하
chk = True
if di == self.DIR_LEFT: # 왼쪽일 경우
mx = int((cx - dot) / 60) # mx와 my에 리스트의 좌상 방향 확인용 값 대입
my = int(cy / 60)
if self.map_data[my][mx] <= 1: # 좌상
chk = True
my = int((cy + 59) / 60) # 리스트의 좌하 방향 확인용 값 대입
if self.map_data[my][mx] <= 1: # 좌하
chk = True
if di == self.DIR_RIGHT: # 오른쪽일 경우
mx = int((cx + 59 + dot) / 60) # mx와 my에 리스트의 우상 방향 확인용 값 대입
my = int(cy / 60)
if self.map_data[my][mx] <= 1: # 우상
chk = True
my = int((cy + 59) / 60) # 리스트의 우하 방향 확인용 값 대입
if self.map_data[my][mx] <= 1: # 우하
chk = True
return chk # chk 값 반환
def move_penpen(self): # 펜펜(캐릭터) 이동 함수
if self.key == Qt.Key_Up: # 위쪽 방향키를 눌렀다면
self.pen_d = self.DIR_UP # 펜펜의 방향을 위쪽으로
if self.check_wall(self.pen_x, self.pen_y, self.pen_d, 20) == False: # 해당 방향이 벽이 아니라면
self.pen_y = self.pen_y - 20 # 위쪽으로 이동
if self.key == Qt.Key_Down: # 아래쪽
self.pen_d = self.DIR_DOWN # 펜펜의 방향을 아래쪽으로
if self.check_wall(self.pen_x, self.pen_y, self.pen_d, 20) == False:
self.pen_y = self.pen_y + 20
if self.key == Qt.Key_Left: # 왼쪽
self.pen_d = self.DIR_LEFT # 펜펜의 방향을 왼쪽으로
if self.check_wall(self.pen_x, self.pen_y, self.pen_d, 20) == False:
self.pen_x = self.pen_x - 20
if self.key == Qt.Key_Right: # 오른쪽
self.pen_d = self.DIR_RIGHT # 펜펜의 방향을 오른쪽으로
if self.check_wall(self.pen_x, self.pen_y, self.pen_d, 20) == False:
self.pen_x = self.pen_x + 20
self.pen_a = self.pen_d * 3 + self.ANIMATION[self.tmr % 4] # 펜펜 애니메이션(이미지) 번호 계산
mx = int(self.pen_x / 60) # mx, my에 펜펜이 있는 위치의 리스트로 확인할 값 대입
my = int(self.pen_y / 60)
if self.map_data[my][mx] == 3: # 사탕 위치에 들어가면
self.score = self.score + 100 # 점수 추가
self.map_data[my][mx] = 2 # 사탕 삭제
self.candy = self.candy - 1 # 사탕 개수 감소
def move_enemy(self): # 레드(적) 이동 함수
speed = 10 # 레드의 이동 속도
if self.red_x % 60 == 0 and self.red_y % 60 == 0: # 칸의 정확한 위치에 있는 경우
self.red_d = random.randint(0, 6) # 무작위로 방향 변경
if self.red_d >= 4: # 난수가 4 이상인 경우 주인공 추적
if self.pen_y < self.red_y: # 펜펜이 위쪽에 있다면
self.red_d = self.DIR_UP # 레드의 방향을 위쪽으로
if self.pen_y > self.red_y:
self.red_d = self.DIR_DOWN
if self.pen_x < self.red_x:
self.red_d = self.DIR_LEFT
if self.pen_x > self.red_x:
self.red_d = self.DIR_RIGHT
if self.red_d == self.DIR_UP: # 레드가 위쪽을 향한 경우
if self.check_wall(self.red_x, self.red_y, self.red_d, speed) == False: # 해당 방향이 벽이 아니라면
self.red_y = self.red_y - speed # 이동
if self.red_d == self.DIR_DOWN:
if self.check_wall(self.red_x, self.red_y, self.red_d, speed) == False:
self.red_y = self.red_y + speed
if self.red_d == self.DIR_LEFT:
if self.check_wall(self.red_x, self.red_y, self.red_d, speed) == False:
self.red_x = self.red_x - speed
if self.red_d == self.DIR_RIGHT:
if self.check_wall(self.red_x, self.red_y, self.red_d, speed) == False:
self.red_x = self.red_x + speed
self.red_a = self.red_d * 3 + self.ANIMATION[self.tmr % 4] # 레드의 애니메이션 번호 계산
if abs(self.red_x - self.pen_x) <= 40 and abs(self.red_y - self.pen_y) <= 40: # 펜펜과 접촉했는지 판단해서 접촉했다면
self.idx = 2 # 게임 오버 처리로 이동
self.tmr = 0
def move_enemy2(self): # 쿠마 이동 함수
speed = 5
if self.kuma_sd == -1: # kuma_sd 값이 -1이면 함수 이탈
return
if self.kuma_d == self.DIR_UP: # 쿠마가 위쪽을 향한 경우
if self.check_wall(self.kuma_x, self.kuma_y, self.kuma_d, speed) == False: # 해당 방향이 벽이 아니라면
self.kuma_y = self.kuma_y - speed # 이동
else: # 벽이라면
self.kuma_d = self.DIR_DOWN # 아래쪽으로 방향 변경
elif self.kuma_d == self.DIR_DOWN:
if self.check_wall(self.kuma_x, self.kuma_y, self.kuma_d, speed) == False:
self.kuma_y = self.kuma_y + speed
else:
self.kuma_d = self.DIR_UP
elif self.kuma_d == self.DIR_LEFT:
if self.check_wall(self.kuma_x, self.kuma_y, self.kuma_d, speed) == False:
self.kuma_x = self.kuma_x - speed
else:
self.kuma_d = self.DIR_RIGHT
elif self.kuma_d == self.DIR_RIGHT:
if self.check_wall(self.kuma_x, self.kuma_y, self.kuma_d, speed) == False:
self.kuma_x = self.kuma_x + speed
else:
self.kuma_d = self.DIR_LEFT
self.kuma_a = self.ANIMATION[self.tmr % 4] # 레드의 애니메이션 번호 계산
if abs(self.kuma_x - self.pen_x) <= 40 and abs(self.kuma_y - self.pen_y) <= 40: # 펜펜과 접촉했는지 판단해서 접촉했다면
self.idx = 2 # 게임 오버 처리로 이동
self.tmr = 0
def main_proc(self):
self.tmr = self.tmr + 1 # 타이머 값 증가
if self.idx == 0: # 인덱스 0 처리(타이틀 화면)
if self.key == Qt.Key_Space: # [SPACE]키를 누르면
self.stage = 1
self.score = 0 # 점수 0 대입
self.life = 3 # 남은 목숨 3 대입
self.set_stage() # 스테이지 데이터 세트
self.set_chara_pos() # 각 캐릭터 시작 위치 설정
self.idx = 1 # 인덱스를 1로 변경, 게임 시작
if self.idx == 1: # 인덱스 1 처리(게임 플레이)
self.move_penpen() # 펜펜 이동
self.move_enemy() # 레드 이동
self.move_enemy2()
if self.candy == 0: # 사탕을 모두 먹었다면
self.idx = 4 # 스테이지 클리어 처리로 이동
self.tmr = 0
if self.idx == 2: # 인덱스 2 처리(적에게 당한 처리)
if self.tmr == 1:
self.life = self.life - 1 # 잔여 수 1 감소
if self.tmr == 30:
if self.life == 0: # 잔여 수가 0이면
self.idx = 3 # 게임 오버 처리로 이동
self.tmr = 0
else: # 그렇지 않으면
self.set_chara_pos() # 캐릭터를 초기 위치로 이동
self.idx = 1 # 다시 플레이
if self.idx == 3: # 인덱스 3 처리(게임 오버)
if self.tmr == 50:
self.idx = 0 # 타이틀 화면으로 이동
if self.idx == 4: # 인덱스 4 처리(스테이지 클리어)
if self.tmr == 30:
if self.stage < 5:
self.stage = self.stage + 1
self.set_stage()
self.set_chara_pos()
self.idx = 1
else:
self.idx = 5 # 엔딩 처리로 이동
self.tmr = 0
if self.idx == 5: # 엔딩 처리
if self.tmr == 300:
self.idx = 0 # 타이틀 화면으로 이동
self.update()
def draw_text(self, qp, txt, x, y, siz, col): # 그림자를 포함한 문자열을 표시
qp.setFont(QFont('Times New Roman', siz, QFont.Bold)) # 폰트 정의
qp.setPen(Qt.black) # 문자열 그림자(2픽셀 어긋나게 검게 표시)
qp.drawText(x + 2, y + 2, txt)
qp.setPen(col) # 지정한 색으로 문자열 표시
qp.drawText(x, y, txt)
def paintEvent(self, e):
qp = QPainter()
qp.begin(self)
for y in range(9):
for x in range(12):
qp.drawImage(QRect(x * 60, y * 60, 60, 60), self.img_bg[self.map_data[y][x]]) # 맵 칩으로 미로 그리기
qp.drawImage(QRect(self.pen_x, self.pen_y, 60, 60), self.img_pen[self.pen_a]) # PenPen 표시
qp.drawImage(QRect(self.red_x, self.red_y, 60, 60), self.img_red[self.red_a]) # 레드 표시
if self.kuma_sd != -1: # kuma_sd 값이 -1이 아니면 쿠마 표시
qp.drawImage(QRect(self.kuma_x, self.kuma_y, self.kuma_width, self.kuma_height), self.img_kuma[self.kuma_a])
self.draw_text(qp, 'SCORE ' + str(self.score), 100, 30, 30, Qt.white) # 점수 표시
self.draw_text(qp, 'STAGE ' + str(self.stage), 440, 30, 30, QColor(191, 255, 0)) # 스테이지 수 표시
for i in range(self.life): # 펜펜의 남은 목숨 수만큼 반복
qp.drawImage(QRect(60 + i * 50, 500, self.pen_face_width, self.pen_face_height), self.img_pen[12]) # 펜펜의 남은 목숨 표시
if self.idx == 0: # 타이틀 화면 표시
qp.drawImage(QRect(35, 100, self.img_title.width(), self.img_title.height()), self.img_title)
if self.tmr % 10 < 5: # 문자열이 깜빡거리는 처리
self.draw_text(qp, 'Press SPACE !', 250, 380, 30, Qt.yellow)
if self.idx == 2: # 적에게 당했을 때 문자 표시
self.draw_text(qp, 'MISS', 295, 270, 40, Qt.red)
if self.idx == 3: # 게임 오버 문자 표시
self.draw_text(qp, 'GAME OVER', 200, 270, 40, Qt.red)
if self.idx == 4: # 스테이지 클리어 문자 표시
if self.stage < 5:
self.draw_text(qp, 'STAGE CLEAR', 180, 270, 40, QColor(255, 170, 170))
else:
self.draw_text(qp, 'ALL STAGE CLEAR!', 80, 270, 40, QColor(210, 168, 212))
if self.idx == 5: # 엔딩 표시
if self.tmr < 60:
xr = 8 * self.tmr # 타원의 반지름 계산
yr = 6 * self.tmr
qp.setPen(Qt.black)
qp.setBrush(Qt.black)
qp.drawEllipse(360 - xr, 270 - yr, xr * 2, yr * 2) # 점점 커지는 타원 그리기
else:
qp.setBrush(Qt.black)
qp.drawRect(-1, -1, 721, 541) # 화면을 검은 색으로 칠함
qp.drawImage(QRect(240, 220, 240, 160), self.img_ending) # 엔딩 화면 표시
self.draw_text(qp, 'Congratulations!', 185, 160, 40, QColor(self.BLINK[self.tmr % 6])) # 반짝거리는 'Congratulations!' 문자 표시
qp.end()
def keyPressEvent(self, e):
self.key = e.key()
def keyReleaseEvent(self, e):
self.key = None
if __name__ == "__main__":
app = QApplication(sys.argv)
main_W = WindowClass()
main_W.show()
sys.exit(app.exec_())
변경 및 추가된 부분 : 스테이지 추가, main_proc에 엔딩 처리 추가, paintEvent에 엔딩 표시 부분 추가