軟體實習專案2——貪吃喵(貓吃魚版貪吃蛇)(代碼實作)
- 類變數的定義以及類的初始化__init__
- 一、游戲的邏輯
- 1、貓頭的生成
- 2、魚的生成
- 3、貓頭和魚骨的移動
- 4、按下鍵盤,改變方向
- 二、主視窗的繪制
- 三、游戲開始與結束界面,以及主視窗的按鈕
- 1、開始游戲
- 2、游戲速度設定
- 3、貓咪選項設定
- 4、結束游戲
- 5、視窗中的按鈕:暫停/開始、重來/退出
- 四、游戲背景音樂
類變數的定義以及類的初始化__init__
class CatWindow(QWidget):
row = 0 # 行數
column = 0 # 列數
direction = 0 # 貓頭方向
head_row = 0 # 貓頭的行
head_column = 0 # 貓頭的列
head_position = '' # 貓頭位置
coordinate = [] # 貓頭和魚骨的位置串列
fish_row = 0 # 魚的行
fish_column = 0 # 魚的列
fish_position = '' # 魚的位置
score = 0 # 計分
# 速度默認值為500
speed = 500
# 貓咪型別默認值是英短藍白
head_pic = 'head.png'
dead_pic = 'dead.png'
# 設定幾個字體
font1 = QtGui.QFont("Calibri", 20)
font2 = QtGui.QFont("Calibri", 15)
font3 = QtGui.QFont("Calibri", 13)
font4 = QtGui.QFont("幼圓", 20)
font5 = QtGui.QFont("幼圓", 13)
# 所有按鈕都按照這個樣式
buttons_style = "QPushButton{background-color: rgb(255, 255, 255); border-radius:10px}" \
"QPushButton:hover{Background-color:qlineargradient(x1:0,y1:0,x2:0,y2:1,stop:0 #cdced1, stop:1 #f6f7fa);}" \
"QPushButton:pressed{Background-color:qlineargradient(x1:0,y1:0,x2:0,y2:1,stop:0 #f6f7fa, stop:1 #cdced1);}"
# 初始化
def __init__(self):
QWidget.__init__(self)
self.setWindowTitle('貪吃喵') # 視窗標題
self.setStyleSheet('background-color:#deebf7') # 游戲背景顏色
self.setWindowIcon(QIcon('head.png')) # 設定視窗圖示
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("myappid") # 任務欄圖示
self.resize(850, 850) # 游戲視窗大小
self.row = 12 # 行數
self.column = 12 # 列數
pygame.mixer.init() # 初始化背景音樂
self.GameStart()
self.windowButton()
self.timer = QTimer() # 計時器
self.timer.start(self.speed) # 開始計時
self.timer.timeout.connect(self.moveCat) # 超時即呼叫moveCat方法
一、游戲的邏輯
1、貓頭的生成
# 隨機生成貓頭位置
def head(self):
self.backgroundMuisc()
self.score = 0 # 分數清零
self.coordinate.clear() # 坐標清空
self.head_row = random.randint(2, self.row - 2) # 隨機選取貓頭的行
self.head_column = random.randint(1, self.column - 2) # 隨機選取貓頭的列
self.coordinate = [str(self.head_row) + "," + str(self.head_column)] # 把貓頭位置寫入坐標串列中
self.fish() # 呼叫生成魚的函式
self.direction = random.randrange(0, 4) # 隨機選擇方向
self.update()
2、魚的生成
# 生成魚的位置
def fish(self):
while True:
self.fish_row = random.randint(1, self.row - 1) # 隨機選取魚的行
self.fish_column = random.randint(0, self.column - 1) # 隨機選取魚的列
self.fish_position = str(self.fish_row) + "," + str(self.fish_column)
# 若隨機生成的魚的位置不在貓頭和魚骨的坐標串列中,則回傳魚的位置,否則重新生成
if self.fish_position not in self.coordinate:
return self.fish_position # 回傳魚的位置
3、貓頭和魚骨的移動
# QTimer的timeout觸發的方法
def moveCat(self):
if self.direction == 0:
self.head_row -= 1 # 貓頭的行數-1
elif self.direction == 1:
self.head_row += 1 # 貓頭的行數+1
elif self.direction == 2:
self.head_column -= 1 # 貓頭的列數-1
elif self.direction == 3:
self.head_column += 1 # 貓頭的列數+1
# 貓頭位置
self.head_position = str(self.head_row) + "," + str(self.head_column)
# 1、若吃到魚了
if self.head_position == self.fish_position:
self.coordinate.insert(0, self.head_position) # 魚骨位置不變,在串列最前面插入貓頭位置
self.score += 10 # 每吃到一條魚就加10分
self.fish() # 生成魚
# 2、若沒吃到魚
else:
# 若貓頭和魚骨沒有相撞且貓頭沒有出界
if 1 <= self.head_row < self.row and 0 <= self.head_column < self.column and self.head_position not in self.coordinate[1:]:
# 1)移動所有魚骨
for i in range(len(self.coordinate) - 1, 0, -1): # range函式的引數(start, stop, step)
self.coordinate[i] = self.coordinate[i - 1] # 所有坐標等于它的前一個坐標(往前一個移動)
# 2)更新貓頭位置
self.coordinate[0] = self.head_position
# 若貓頭和魚骨相撞或貓頭出界,則游戲結束
else:
self.GameOver(True)
return
self.update()
4、按下鍵盤,改變方向
# 按下鍵盤,改變方向
def keyPressEvent(self, event):
QWidget.keyPressEvent(self, event)
key = event.key()
# 1、按了↑
if key == Qt.Key_W:
self.direction = 0
# 2、按了↓
elif key == Qt.Key_S:
self.direction = 1
# 3、按了←
elif key == Qt.Key_A:
self.direction = 2
# 4、按了→
elif key == Qt.Key_D:
self.direction = 3
二、主視窗的繪制
# 繪制主視窗中的所有物體
def paintEvent(self, event):
QWidget.paintEvent(self, event)
painter = QPainter(self)
row_space = self.height() / self.row # 行間距
column_space = self.width() / self.column # 列間距
# 顯示背景圖片
painter.drawImage(QRectF(0, 0, self.width(), self.height()), QImage('bg.jpg'))
# 繪制行線和列線
pen = QPen(QColor(255, 255, 255), 1, Qt.DotLine) # 畫筆顏色、粗細、線型
painter.setPen(pen)
for n in range(self.row + 1):
painter.drawLine(QPointF(0, row_space * n), QPointF(self.width(), row_space * n))
for n in range(self.column + 1):
painter.drawLine(QPointF(column_space * n, column_space), QPointF(column_space * n, self.height()))
# 顯示分數
text_painter = QPainter(self)
text_pen = QPen(QColor(0, 0, 0)) # 畫筆顏色、粗細、線型
text_painter.setPen(text_pen)
text_painter.setFont(self.font1)
text_painter.drawText(350, 50, 'Score: ' + str(self.score))
# 畫貓頭、魚骨、魚
index = 0 # 記錄coordinate的索引,為0時畫貓頭,大于0時畫魚骨
for n in self.coordinate:
row = int(n[:n.find(',')])
column = int(n[n.find(',') + 1:])
# 若貓頭沒出界且沒有與魚骨相撞,畫貓頭和魚骨
if 1 <= self.head_row < self.row and 0 <= self.head_column < self.column and self.head_position not in self.coordinate[
1:]:
# 貓頭
if index == 0:
painter.drawImage(QRectF(column * column_space, row * row_space, column_space, row_space),
QImage(self.head_pic))
# 畫魚骨
else:
painter.drawImage(QRectF(column * column_space, row * row_space, column_space, row_space),
QImage('bone.png'))
index += 1
# 若貓頭出界了或與魚骨相撞,畫死亡貓頭和魚骨
else:
# 貓頭
if index == 0:
painter.drawImage(QRectF(column * column_space, row * row_space, column_space, row_space),
QImage(self.dead_pic))
# 畫魚骨
else:
painter.drawImage(QRectF(column * column_space, row * row_space, column_space, row_space),
QImage('bone.png'))
index += 1
# 畫魚
painter.drawImage(QRectF(self.fish_column * column_space, self.fish_row * row_space, column_space, row_space),
QImage('fish.png'))
三、游戲開始與結束界面,以及主視窗的按鈕
1、開始游戲
# 開始游戲
def GameStart(self):
# 訊息框的大小和樣式
message_box = QMessageBox()
message_box.setStyleSheet('width: 500; height: 70')
message_box.setWindowTitle('WELCOME')
message_box.setFont(self.font4)
message_box.setText("歡迎來到貪吃喵🐱")
message_box.setWindowIcon(QIcon('head.png')) # 設定訊息框圖示
message_box.setStyleSheet('background-color:#deebf7')
# click to start按鈕
message_box.setStandardButtons(QMessageBox.Yes)
yes = message_box.button(QMessageBox.Yes)
yes.setText("Click to Start")
yes.setFont(self.font2)
yes.setStyleSheet(self.buttons_style)
# 下拉框速度選項
items = ['Speed:', 'Low', 'Middle', 'High']
cb = QComboBox(message_box)
cb.addItems(items) # 添加下拉框選項
cb.setGeometry(400, 5, 120, 40)
cb.setFont(self.font3)
cb.setStyleSheet('background-color: rgb(255, 255, 255); border-radius:10px')
cb.currentIndexChanged.connect(self.speedChanging) # 下拉框選項改變即觸發
self.speedChanging(cb.currentIndex()) # 將下拉框此時的選項索引傳遞給speedChanging函式
# 下拉框貓咪選項
items = ['喵喵:', '英短藍白', '銀漸層', '橘貓', '奶牛貓', '三花貓']
cb1 = QComboBox(message_box)
cb1.addItems(items) # 添加下拉框選項
cb1.setGeometry(400, 50, 120, 40)
cb1.setFont(self.font5)
cb1.setStyleSheet('background-color: rgb(255, 255, 255); border-radius:10px')
cb1.currentIndexChanged.connect(self.catChoosing) # 下拉框選項改變即觸發
self.catChoosing(cb1.currentIndex()) # 將下拉框此時的選項索引傳遞給speedChanging函式
# 退出游戲開始訊息框,進入游戲主界面
message_box.exec()
self.show()
self.backgroundMuisc() # 調出背景音樂
self.head()
2、游戲速度設定
# GameStart方法中下拉框選項改變時呼叫的槽函式,用來設定速度
def speedChanging(self, index):
if index == 1:
self.speed = 500
elif index == 2:
self.speed = 300
elif index == 3:
self.speed = 200
3、貓咪選項設定
# GameStart方法中貓咪下拉框選項改變時呼叫的槽函式,用來選擇自己喜歡的貓咪
def catChoosing(self, index):
if index == 1:
self.head_pic = 'head.png'
self.dead_pic = 'dead.png'
elif index == 2:
self.head_pic = 'head1.png'
self.dead_pic = 'dead1.png'
elif index == 3:
self.head_pic = 'head2.png'
self.dead_pic = 'dead2.png'
elif index == 4:
self.head_pic = 'head3.png'
self.dead_pic = 'dead3.png'
elif index == 5:
self.head_pic = 'head4.png'
self.dead_pic = 'dead4.png'
4、結束游戲
# 結束游戲
def GameOver(self, gameover):
pygame.mixer.music.stop()
message_box = QMessageBox()
message_box.setStyleSheet('width: 300; height: 70')
message_box.setWindowTitle('END')
message_box.setFont(self.font1)
message_box.setWindowIcon(QIcon('head.png')) # 設定訊息框圖示
message_box.setWindowOpacity(0.75) # 透明度
if gameover:
message_box.setText("Game Over! Your Score: " + str(self.score))
else:
message_box.setText("YOU WIN! Your Score: " + str(self.score))
# 設定游戲結束訊息框的兩個按鈕
message_box.setStandardButtons(QMessageBox.Retry | QMessageBox.Abort)
retry = message_box.button(QMessageBox.Retry)
retry.setText("Retry")
retry.setFont(self.font2)
retry.setStyleSheet(self.buttons_style)
abort = message_box.button(QMessageBox.Abort)
abort.setText("Exit")
abort.setFont(self.font2)
abort.setStyleSheet(self.buttons_style)
abort.clicked.connect(QCoreApplication.instance().quit) # 點擊此按鈕則退出程式
message_box.exec()
self.head()
5、視窗中的按鈕:暫停/開始、重來/退出
# 視窗中的按鈕:暫停/開始、重來/退出
def windowButton(self):
# 暫停
pause = QPushButton(self)
pause.setGeometry(10, 10, 100, 50)
pause.setText('Pause')
pause.setFont(self.font3)
pause.setStyleSheet(self.buttons_style)
pause.show()
pause.clicked.connect(self.windowPause) # 點擊暫停按鈕則觸發windowPause方法
# 繼續
start = QPushButton(self)
start.setGeometry(120, 10, 120, 50)
start.setText('Continue')
start.setFont(self.font3)
start.setStyleSheet(self.buttons_style)
start.show()
start.clicked.connect(self.windowContinue) # 點擊繼續按鈕則觸發windowContinue方法
# 退出
exit_button = QPushButton(self)
exit_button.setGeometry(740, 10, 100, 50)
exit_button.setText('Exit')
exit_button.setFont(self.font3)
exit_button.setStyleSheet(self.buttons_style)
exit_button.show()
exit_button.clicked.connect(QCoreApplication.instance().quit) # 點擊退出按鈕則退出程式
# 重新開始
restart_button = QPushButton(self)
restart_button.setGeometry(630, 10, 100, 50)
restart_button.setText('Restart')
restart_button.setFont(self.font3)
restart_button.setStyleSheet(self.buttons_style)
restart_button.show()
restart_button.clicked.connect(self.head) # 點擊重新開始則重新生成貓頭,游戲重新開始
# 按下暫停按鈕后呼叫的方法
def windowPause(self):
self.timer.stop() # 計時器暫停計時
pygame.mixer.music.pause() # 暫停播放音樂
self.update()
# 按下繼續按鈕后呼叫的方法
def windowContinue(self):
self.timer.start() # 計時器重新開始計時
pygame.mixer.music.unpause()
self.update()
四、游戲背景音樂
# 背景音樂
def backgroundMuisc(self):
pygame.mixer.music.load("bgmusic.mp3")
pygame.mixer.music.set_volume(0.3) # 設定音量
pygame.mixer.music.play(-1) # 回圈播放
——2020/12/16(殷越)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/236666.html
標籤:其他
