from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
import random
import time
from threading import Thread, Lock
class Ball_Bar_Block:
def __init__(self, parent):
# 공
self.ball_x = 0
self.ball_y = 0
self.ball_xp = 0
self.ball_yp = 0
# 바
self.bar_x = 0
self.bar_y = 540
# 블록
self.block = []
for i in range(5):
self.block.append([1] * 10)
for i in range(10):
self.block.append([0] * 10)
# 점수, 스테이지
self.score = 0
self.stage = 0
self.parent = parent
def move_ball(self):
self.ball_x = self.ball_x + self.ball_xp
if self.ball_x < 20:
self.ball_x = 20
self.ball_xp = -self.ball_xp
if self.ball_x > 780:
self.ball_x = 780
self.ball_xp = -self.ball_xp
x = int(self.ball_x / 80)
y = int(self.ball_y / 40)
if self.block[y][x] == 1:
self.block[y][x] = 0
self.ball_xp = -self.ball_xp
self.score = self.score + 10
self.ball_y = self.ball_y + self.ball_yp
if self.ball_y >= 600:
self.parent.idx = 2
self.parent.tmr = 0
return
if self.ball_y < 20:
self.ball_y = 20
self.ball_yp = -self.ball_yp
x = int(self.ball_x / 80)
y = int(self.ball_y / 40)
if self.block[y][x] == 1:
self.block[y][x] = 0
self.ball_yp = -self.ball_yp
self.score = self.score + 10
if self.bar_y - 40 <= self.ball_y and self.ball_y <= self.bar_y:
if self.bar_x - 80 <= self.ball_x and self.ball_x <= self.bar_x + 80:
self.ball_yp = -10
self.score = self.score + 1
elif self.bar_x - 100 <= self.ball_x and self.ball_x <= self.bar_x - 80:
self.ball_yp = -10
self.ball_xp = random.randint(-20, -10)
self.score = self.score + 2
elif self.bar_x + 80 <= self.ball_x and self.ball_x <= self.bar_x + 100:
self.ball_yp = -10
self.ball_xp = random.randint(10, 20)
self.score = self.score + 2
def key_press(self, key):
if key == Qt.Key_Space and self.parent.bGame == False and self.parent.idx == 0:
self.parent.thread.start()
self.parent.bGame = True
if key == Qt.Key_Backspace:
self.parent.idx = 4
if key == Qt.Key_Space and self.parent.stage_clear == True:
for y in range(5):
for x in range(10):
self.block[y][x] = 1
self.parent.idx = 0
self.parent.tmr = 1
self.stage = self.stage + 1
self.parent.stage_clear = False
if key == Qt.Key_R and self.parent.game_over == True:
self.score = 0
self.parent.idx = 0
self.parent.tmr = 1
self.parent.game_over = False
if key == Qt.Key_N and self.parent.game_over == True:
for y in range(5):
for x in range(10):
self.block[y][x] = 1
self.parent.idx = 0
self.parent.tmr = 0
self.parent.game_over = False
if key == Qt.Key_Left and self.bar_x > 80:
self.bar_x = self.bar_x - 40
if key == Qt.Key_Right and self.bar_x < 720:
self.bar_x = self.bar_x + 40
def block_color(self, x, y):
col = QColor(15 - x - int(y / 3), x + 1, y * 3 + 3)
return col
class CMap:
def __init__(self, parent):
super().__init__()
self.thread = Thread(target = self.playgame)
self.bRun = True
self.bGame = False
self.is_clr = True
self.game_over = False
self.stage_clear = False
self.idx = 0
self.tmr = 0
self.ball = Ball_Bar_Block(self)
self.parent = parent
def draw(self, qp):
qp.setFont(QFont('Times New Roman', 20, QFont.Bold))
if self.bGame == False:
qp.setPen(QPen(Qt.cyan))
self.start_txt = 'Press [Space] to Play'
else:
self.start_txt = ''
qp.drawText(275, 300, self.start_txt)
if self.game_over == True:
self.gameover_txt = 'GAME OVER'
self.replay_txt = '[R]eplay'
self.newgame_txt = '[N]ew game'
else:
self.gameover_txt = ''
self.replay_txt = ''
self.newgame_txt = ''
qp.setPen(QPen(Qt.red))
qp.drawText(325, 260, self.gameover_txt)
qp.setPen(QPen(Qt.cyan))
qp.drawText(200, 340, self.replay_txt)
qp.setPen(QPen(Qt.yellow))
qp.drawText(500, 340, self.newgame_txt)
if self.stage_clear == True:
self.stageclear_txt = 'STAGE CLEAR'
self.nextstage_txt = 'NEXT [SPACE]'
else:
self.stageclear_txt = ''
self.nextstage_txt = ''
qp.setPen(QPen(QColor(204, 255, 0)))
qp.drawText(325, 260, self.stageclear_txt)
qp.setPen(QPen(Qt.cyan))
qp.drawText(325, 340, self.nextstage_txt)
self.is_clr = True
for y in range(15):
for x in range(10):
gx = x * 80
gy = y * 40
if self.ball.block[y][x] == 1:
qp.setBrush(self.ball.block_color(x, y))
qp.setPen(QPen(Qt.black))
qp.drawRect(gx + 1, gy + 4, 78, 31)
self.is_clr = False
qp.setFont(QFont('Times New Roman', 20, QFont.Bold))
qp.setPen(QPen(Qt.white))
self.stage_txt = 'STAGE ' + str(self.ball.stage)
qp.drawText(150, 30, self.stage_txt)
self.score_txt = 'SCORE ' + str(self.ball.score)
qp.drawText(550, 30, self.score_txt)
qp.setBrush(QColor(255, 228, 73))
qp.drawEllipse(self.ball.ball_x - 20, self.ball.ball_y - 20, 40, 40)
qp.setPen(QColor(255, 235, 65))
qp.setBrush(QColor(255, 244, 50))
qp.drawEllipse(self.ball.ball_x - 16, self.ball.ball_y - 16, 28, 28)
qp.setBrush(QColor(181, 181, 189))
qp.drawRect(self.ball.bar_x - 80, self.ball.bar_y - 12, 160, 24)
qp.setBrush(QColor(181, 181, 189))
qp.drawRect(self.ball.bar_x - 78, self.ball.bar_y - 14, 156, 28)
qp.setBrush(QColor(230, 230, 233))
qp.drawRect(self.ball.bar_x - 78, self.ball.bar_y - 12, 156, 24)
def playgame(self):
while self.bRun:
if self.idx == 0:
self.tmr = self.tmr + 1
if self.tmr == 1:
self.ball.stage = 1
self.ball.score = 0
if self.tmr == 2:
self.ball.ball_x = 160
self.ball.ball_y = 240
self.ball.ball_xp = 10
self.ball.ball_yp = 10
self.ball.bar_x = 400
self.idx = 1
elif self.idx == 1:
self.ball.move_ball()
if self.is_clr == True:
self.idx = 3
self.tmr = 0
elif self.idx == 2:
self.tmr = self.tmr + 1
if self.tmr == 1:
self.game_over = True
elif self.idx == 3:
self.tmr = self.tmr + 1
if self.tmr == 1:
self.stage_clear = True
elif self.idx == 4:
self.bGame = False
self.bRun = False
break
self.parent.update()
time.sleep(0.03)
if not self.bGame:
self.parent.endSignal.emit()
class WindowClass(QWidget):
endSignal = pyqtSignal()
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle('Block game')
self.setGeometry(100, 100, 800, 600)
pal = QPalette()
pal.setColor(QPalette.Background, QColor(0, 0, 0))
self.setAutoFillBackground(True)
self.setPalette(pal)
self.game = CMap(self)
self.endSignal.connect(self.ExitGame)
def paintEvent(self, e):
qp = QPainter()
qp.begin(self)
self.game.draw(qp)
qp.end()
def keyPressEvent(self, e):
self.game.ball.key_press(e.key())
def ExitGame(self):
self.close()
if __name__ == "__main__":
app = QApplication(sys.argv)
main_W = WindowClass()
main_W.show()
sys.exit(app.exec_())
어느 정도 마무리되었다.
일단 게임에 필요한 시작, 게임오버, 재시작, 새 게임, 다음 스테이지, 게임 종료 같은 핵심 기능들은 GUI로도 구현이 되었고 문제가 있다면 블럭을 그리는데 색을 함수로 QColor 객체를 반환해서 setBrush에 넣고 있는데 아주 희미하게 보이는 문제가 발생했다. 이를 빠르게 해결하고 다음으로 넘어갈 예정이다.