from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class WindowClass(QWidget):
def __init__(self):
super().__init__()
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.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.initUI()
def initUI(self):
self.setFixedSize(720, 540) # 창 크기 고정
self.setWindowTitle('Draw maze')
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.end()
if __name__ == "__main__":
app = QApplication(sys.argv)
main_W = WindowClass()
main_W.show()
sys.exit(app.exec_())
맵 칩을 이용해서 맵을 윈도우에 표시한다.
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class WindowClass(QWidget):
def __init__(self):
super().__init__()
self.key = None
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\pen03.png') # 캐릭터 이미지
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.DIR_UP = 0 # 캐릭터 방향 정의 변수(위쪽)
self.DIR_DOWN = 1 # 캐릭터 방향 정의 변수(아래쪽)
self.DIR_LEFT = 2 # 캐릭터 방향 정의 변수(왼쪽)
self.DIR_RIGHT = 3 # 캐릭터 방향 정의 변수(오른쪽)
self.pen_x = 60 # 캐릭터 X 좌표
self.pen_y = 60 # 캐릭터 Y 좌표
self.initUI()
timer = QTimer(self)
timer.setInterval(100)
timer.timeout.connect(self.main_proc) # 50밀리초마다 main_proc 실행
timer.start()
def initUI(self):
self.setFixedSize(720, 540) # 창 크기 고정
self.setWindowTitle('Move PenPen')
def check_wall(self, cx, cy, di): # 지정한 방향에 벽 존재 여부 확인 함수
chk = False # chk에 False 대입
if di == self.DIR_UP: # 위쪽일 경우
mx = int(cx / 60) # mx와 my에 리스트의 위쪽 방향 확인용 값 대입
my = int((cy - 60) / 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 + 60) / 60)
if self.map_data[my][mx] <= 1:
chk = True
if di == self.DIR_LEFT: # 왼쪽일 경우
mx = int((cx - 60) / 60) # mx와 my에 리스트의 왼쪽 방향 확인용 값 대입
my = int(cy / 60)
if self.map_data[my][mx] <= 1:
chk = True
if di == self.DIR_RIGHT: # 오른쪽일 경우
mx = int((cx + 60) / 60) # mx와 my에 리스트의 오른쪽 방향 확인용 값 대입
my = int(cy / 60)
if self.map_data[my][mx] <= 1:
chk = True
return chk # chk 값 반환
def move_penpen(self): # PenPen(캐릭터) 이동 함수
if self.key == Qt.Key_Up: # 위쪽 방향키를 눌렀다면
if self.check_wall(self.pen_x, self.pen_y, self.DIR_UP) == False: # 해당 방향이 벽이 아니라면
self.pen_y = self.pen_y - 60 # 위쪽으로 이동
if self.key == Qt.Key_Down: # 아래쪽
if self.check_wall(self.pen_x, self.pen_y, self.DIR_DOWN) == False:
self.pen_y = self.pen_y + 60
if self.key == Qt.Key_Left: # 왼쪽
if self.check_wall(self.pen_x, self.pen_y, self.DIR_LEFT) == False:
self.pen_x = self.pen_x - 60
if self.key == Qt.Key_Right: # 오른쪽
if self.check_wall(self.pen_x, self.pen_y, self.DIR_RIGHT) == False:
self.pen_x = self.pen_x + 60
def main_proc(self):
self.move_penpen()
self.update()
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) # PenPen 표시
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_())
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class WindowClass(QWidget):
def __init__(self):
super().__init__()
self.key = None
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.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.DIR_UP = 0 # 캐릭터 방향 정의 변수(위쪽)
self.DIR_DOWN = 1 # 캐릭터 방향 정의 변수(아래쪽)
self.DIR_LEFT = 2 # 캐릭터 방향 정의 변수(왼쪽)
self.DIR_RIGHT = 3 # 캐릭터 방향 정의 변수(오른쪽)
self.ANIMATION = [0, 1, 0, 2]
self.tmr = 0
self.pen_x = 60 # 펜펜의 X 좌표
self.pen_y = 60 # 펜펜의 Y 좌표
self.pen_d = 0 # 펜펜의 방향
self.pen_a = 0 # 펜펜의 이미지 번호
self.initUI()
timer = QTimer(self)
timer.setInterval(300)
timer.timeout.connect(self.main_proc) # 50밀리초마다 main_proc 실행
timer.start()
def initUI(self):
self.setFixedSize(720, 540) # 창 크기 고정
self.setWindowTitle('Animate PenPen')
def check_wall(self, cx, cy, di): # 지정한 방향에 벽 존재 여부 확인 함수
chk = False # chk에 False 대입
if di == self.DIR_UP: # 위쪽일 경우
mx = int(cx / 60) # mx와 my에 리스트의 위쪽 방향 확인용 값 대입
my = int((cy - 60) / 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 + 60) / 60)
if self.map_data[my][mx] <= 1:
chk = True
if di == self.DIR_LEFT: # 왼쪽일 경우
mx = int((cx - 60) / 60) # mx와 my에 리스트의 왼쪽 방향 확인용 값 대입
my = int(cy / 60)
if self.map_data[my][mx] <= 1:
chk = True
if di == self.DIR_RIGHT: # 오른쪽일 경우
mx = int((cx + 60) / 60) # mx와 my에 리스트의 오른쪽 방향 확인용 값 대입
my = int(cy / 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) == False: # 해당 방향이 벽이 아니라면
self.pen_y = self.pen_y - 60 # 위쪽으로 이동
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) == False:
self.pen_y = self.pen_y + 60
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) == False:
self.pen_x = self.pen_x - 60
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) == False:
self.pen_x = self.pen_x + 60
self.pen_a = self.pen_d * 3 + self.ANIMATION[self.tmr % 4] # 펜펜 애니메이션(이미지) 번호 계산
def main_proc(self):
self.tmr = self.tmr + 1 # 타이머 값 증가
self.move_penpen()
self.update()
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.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_())
펜펜(캐릭터)가 걸어가는 것처럼 방향에 따라 이미지를 다르게하고, 애니메이션화한다.
pen_a의 계산식을 해설하겠다.
self.pen_a = self.pen_d * 3 + self.ANIMATION[self.tmr % 4] # 펜펜 애니메이션(이미지) 번호 계산
각 방향마다 3장의 이미지를 사용하기 때문에 pen_d * 3에 ANIMATION[tmr % 4]을 더한 것이다.
0002는 위, 0305는 아래, 0608은 왼쪽, 0911은 오른쪽으로 움직일 때 사용하는 이미지들이다.
이를 알고 아래로 이동할 때로 계산하면, pen_d는 1이기 때문에 결과는 3 -> 4 -> 3 -> 5로 03~05번의 이미지를 사용하는 것을 알 수 있다.
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class WindowClass(QWidget):
def __init__(self):
super().__init__()
self.key = None
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.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.DIR_UP = 0 # 캐릭터 방향 정의 변수(위쪽)
self.DIR_DOWN = 1 # 캐릭터 방향 정의 변수(아래쪽)
self.DIR_LEFT = 2 # 캐릭터 방향 정의 변수(왼쪽)
self.DIR_RIGHT = 3 # 캐릭터 방향 정의 변수(오른쪽)
self.ANIMATION = [0, 1, 0, 2]
self.tmr = 0
self.pen_x = 60 # 펜펜의 X 좌표
self.pen_y = 60 # 펜펜의 Y 좌표
self.pen_d = 0 # 펜펜의 방향
self.pen_a = 0 # 펜펜의 이미지 번호
self.initUI()
timer = QTimer(self)
timer.setInterval(100)
timer.timeout.connect(self.main_proc) # 50밀리초마다 main_proc 실행
timer.start()
def initUI(self):
self.setFixedSize(720, 540) # 창 크기 고정
self.setWindowTitle('Smooth move PenPen')
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] # 펜펜 애니메이션(이미지) 번호 계산
def main_proc(self):
self.tmr = self.tmr + 1 # 타이머 값 증가
self.move_penpen()
self.update()
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.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_())
전의 코드에서보다 부드럽게 움직이게 하기 위해 20 픽셀씩 움직이게 바꿨다. 이렇게 바꾸면서 check_wall 함수까지 바꿔야 했다.
벽에 대한 판정 부분만 보자
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 값 반환
좌측으로 이동할 떄를 예로 들어 설명하자면 좌측으로 이동할 때 이동 가능한 조건은 펜펜의 머리끝과 발끝이 모두 칸 안에 들어갈 수 있는 것이다.
즉, 머리끝의 좌표는 왼쪽으로 20 픽셀만큼 이동할 수 있어도, 발은 왼쪽에 벽이 있어서 20픽셀만큼 이동할 수 없다면 펜펜은 이동할 수 없는 것이다.