Skip to content

Latest commit

 

History

History
276 lines (242 loc) · 9.04 KB

211223.md

File metadata and controls

276 lines (242 loc) · 9.04 KB

Day 78

파이썬으로 배우는 게임 개발 입문편

블록 격파 게임

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에 넣고 있는데 아주 희미하게 보이는 문제가 발생했다. 이를 빠르게 해결하고 다음으로 넘어갈 예정이다.