1. 程式人生 > >PyGame彈珠遊戲雙人改良版

PyGame彈珠遊戲雙人改良版

#   _*_ coding:utf-8 _*_
import pygame
from pygame.locals import *
from sys import exit

__author__ = 'admin'

'''
    彈珠遊戲設計擴充套件,改良版
'''

pygame.init()
#   設定螢幕寬度
SCREEN_SIZE = (320, 400)

#   初始化得分
score_playerA = 0
score_playerB = 0

#   顏色
WHITE = (255, 255, 255)
BLUE = (0, 255, 255)
GREEN = (0, 255, 0)
BLACK = (0, 0, 0)
RED = (255, 0, 0)

#   初始化遊戲狀態:1/遊戲開始介面 2/遊戲進行中 3/遊戲結束
status = 1

#   初始化贏家
winner = ''

screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32)

class Baffle():
    def __init__(self):
        #   設定上擋板的大小
        self.BAFFLE_SIZE_U = (40, 5)
        #   設定上擋板左上角初始位置
        self.BAFFLE_POS_U = ((SCREEN_SIZE[0] / 2 - self.BAFFLE_SIZE_U[0] / 2), 0)
        #   獲取上擋板左上角座標初始值
        self.BAFFLE_POS_U_x, self.BAFFLE_POS_U_y = self.BAFFLE_POS_U

        #   設定下擋板的大小
        self.BAFFLE_SIZE_D = (40, 5)
        #   設定下擋板左上角初始位置
        self.BAFFLE_POS_D = ((SCREEN_SIZE[0] / 2 - self.BAFFLE_SIZE_D[0] / 2), (SCREEN_SIZE[1] - self.BAFFLE_SIZE_D[1]))
        #   獲取下擋板左上角座標初始值
        self.BAFFLE_POS_D_x, self.BAFFLE_POS_D_y = self.BAFFLE_POS_D

        #   設定擋板移速
        self.BAFFLE_SPEED = 5

    #   下檔位左移處理
    def BAFFLE_D_move_left(self):
        self.BAFFLE_POS_D_x -= self.BAFFLE_SPEED
        self.BAFFLE_POS_D_x = max(0, self.BAFFLE_POS_D_x)

    #   下擋板右移處理
    def BAFFLE_D_move_right(self):
        self.BAFFLE_POS_D_x += self.BAFFLE_SPEED
        self.BAFFLE_POS_D_x = min(SCREEN_SIZE[0] - self.BAFFLE_SIZE_D[0], self.BAFFLE_POS_D_x)

    #   上擋板左移處理
    def BAFFLE_U_move_left(self):
        self.BAFFLE_POS_U_x -= self.BAFFLE_SPEED
        self.BAFFLE_POS_U_x = max(0, self.BAFFLE_POS_U_x)

    #   上擋板右移處理
    def BAFFLE_U_move_right(self):
        self.BAFFLE_POS_U_x += self.BAFFLE_SPEED
        self.BAFFLE_POS_U_x = min(SCREEN_SIZE[0] - self.BAFFLE_SIZE_U[0], self.BAFFLE_POS_U_x)

    #   畫出擋板
    def draw(self):
        #   畫出下擋板
        pygame.draw.rect(screen, GREEN, pygame.Rect((self.BAFFLE_POS_D_x, self.BAFFLE_POS_D_y), self.BAFFLE_SIZE_D))
        #   畫出上擋板
        pygame.draw.rect(screen, BLUE, pygame.Rect((self.BAFFLE_POS_U_x, self.BAFFLE_POS_U_y), self.BAFFLE_SIZE_U))

    def reset(self):
        self.BAFFLE_POS_U = ((SCREEN_SIZE[0] / 2 - self.BAFFLE_SIZE_U[0] / 2), 0)
        self.BAFFLE_POS_D = ((SCREEN_SIZE[0] / 2 - self.BAFFLE_SIZE_D[0] / 2), (SCREEN_SIZE[1] - self.BAFFLE_SIZE_D[1]))
        self.draw()


baffle = Baffle()


class Ball():
    def __init__(self):
        #   設定彈珠的大小
        self.BALL_SIZE = (10, 10)
        #   設定彈珠左上角初始位置
        self.BALL_POS = ((SCREEN_SIZE[0] / 2 - self.BALL_SIZE[0] / 2), (SCREEN_SIZE[1] - baffle.BAFFLE_SIZE_D[1] - self.BALL_SIZE[1]))
        #   獲取彈珠左上角座標初始值
        self.BALL_POS_x, self.BALL_POS_y = self.BALL_POS

        #   設定彈珠彈速
        self.BALL_SPEED = 5

        #   設定彈珠的座標位移量
        self.BALL_x_mobility = -2
        self.BALL_y_mobility = -3

    def draw(self):
        #   延遲彈珠重新整理速度
        pygame.time.delay(int(100 / self.BALL_SPEED))
        #   畫出彈珠
        pygame.draw.rect(screen, WHITE, pygame.Rect((self.BALL_POS_x, self.BALL_POS_y), self.BALL_SIZE))

    def reset(self):
        self.BALL_POS = ((SCREEN_SIZE[0] / 2 - self.BALL_SIZE[0] / 2), (SCREEN_SIZE[1] - baffle.BAFFLE_SIZE_D[1] - self.BALL_SIZE[1]))
        self.draw()

    #   輸出結果
    def CheckResult(self, score_A, score_B):
        global winner
        if score_A > score_B:
            winner = u"PlayerA Win!"
            print("PlayerA 勝利!")
        elif score_A == score_B:
            winner = u"It's a draw!"
            print("打成平局!")
        else:
            winner = u"PlayerB Win!"
            print("PlayerB 勝利!")

    def edge_detection(self):
        global score_playerA, score_playerB, status
        # 彈珠在螢幕內的左邊緣檢測
        if self.BALL_POS_x <= 0:
            self.BALL_x_mobility = 2
        # 彈珠在螢幕內的右邊緣檢測
        if self.BALL_POS_x >= SCREEN_SIZE[0]:
            self.BALL_x_mobility = -2

        #   彈珠在螢幕內的上邊緣檢測
        #   獲取上擋板底部的縱座標
        baffle.BAFFLE_U_bottom_y = baffle.BAFFLE_POS_U_y + baffle.BAFFLE_SIZE_U[1]
        if 0 <= ball.BALL_POS_y < baffle.BAFFLE_U_bottom_y:
            #   如果彈珠和座標在擋板長度內
            if baffle.BAFFLE_POS_U_x - self.BALL_SIZE[0] <= self.BALL_POS_x <= (baffle.BAFFLE_POS_U_x + baffle.BAFFLE_SIZE_U[0]):
                self.BALL_y_mobility = 3
                score_playerA += 1
                print("score_playerA:", score_playerA)
            # 不符合以上情況,說明這個球你肯定接不住了
            else:
                self.CheckResult(score_playerA, score_playerB)
                # exit()
                status = 3

        # 彈珠在螢幕內的下邊緣檢測
        #   獲取彈珠底部的縱座標
        self.BALL_bottom_y = self.BALL_POS_y + self.BALL_SIZE[1]
        #   如果彈珠底部在擋板內部
        if SCREEN_SIZE[1] >= self.BALL_bottom_y > baffle.BAFFLE_POS_D_y:
            #   如果彈珠和座標在擋板長度內
            if baffle.BAFFLE_POS_D_x - self.BALL_SIZE[0] <= self.BALL_POS_x <= (baffle.BAFFLE_POS_D_x + baffle.BAFFLE_SIZE_D[0]):
                self.BALL_y_mobility = -3
                score_playerB += 1
                print("score_playerB:", score_playerB)
            # 不符合以上情況,說明這個球你肯定接不住了
            else:
                self.CheckResult(score_playerA, score_playerB)
                # exit()
                status = 3

        # 獲取彈珠新的位置
        self.BALL_POS_x += ball.BALL_x_mobility
        self.BALL_POS_y += ball.BALL_y_mobility

ball = Ball()

def GameBody():
    #   退出檢測函式
    def checkForOut():
        global status, ball, baffle, score_playerA, score_playerB
        for event in pygame.event.get():
            #   點選×
            if event.type == 12:
                exit()
            if event.type == 2:
                #   按鍵為Esc
                if event.key == 27:
                    exit()
                #   按鍵為Space
                if event.key == 32:
                    #   當前狀態為遊戲開始介面
                    if status == 1:
                        status = 2
                    #   當前狀態為遊戲結束介面
                    elif status == 3:
                        #   初始化玩家分數以及擋板和彈珠的位置
                        score_playerA, score_playerB = (0, 0)
                        ball = Ball()
                        baffle = Baffle()
                        status = 2

    def divide():
        font = pygame.font.SysFont("arial", 20)
        text_sur1 = font.render(u"A", True, BLUE)
        text_sur2 = font.render(u"B", True, GREEN)
        pos_A = (SCREEN_SIZE[0] / 2 - text_sur1.get_width() / 2, SCREEN_SIZE[1] / 4)
        pos_B = (SCREEN_SIZE[0] / 2 - text_sur1.get_width() / 2, SCREEN_SIZE[1] * 3 / 4)
        #   寫入文字"A"、"B"
        screen.blit(text_sur1, pos_A)
        screen.blit(text_sur2, pos_B)
        #   畫出區域中介線
        pygame.draw.line(screen, WHITE, (0, SCREEN_SIZE[1] / 2), (SCREEN_SIZE[0], SCREEN_SIZE[1] / 2))

    #   遊戲開始選單的設計
    def start_menu():
        font = pygame.font.SysFont("arial", 30)
        text_surWarn = font.render(u"START", True, BLUE)
        warn_width = text_surWarn.get_width()
        warn_height = text_surWarn.get_height()
        pos_warn = (SCREEN_SIZE[0] / 2 - warn_width / 2, SCREEN_SIZE[1] / 2 - warn_height / 2)
        screen.blit(text_surWarn, pos_warn)

    #   遊戲結束選單的設計
    def end_menu():
        font_winner = pygame.font.SysFont("arial", 30)
        font_warn = pygame.font.SysFont("arial", 30, 5)
        text_surWinner = font_winner.render(winner, True, RED)
        text_surWarn = font_warn.render(u"RESTART", True, RED)

        winner_width = text_surWinner.get_width()
        winner_height = text_surWinner.get_height()
        warn_width = text_surWarn.get_width()
        warn_height = text_surWarn.get_height()

        rect_width = max(winner_width, warn_width)
        rect_height = winner_height + warn_height
        rect_y = SCREEN_SIZE[1] / 2 - rect_height / 2
        rect_x = SCREEN_SIZE[0] / 2 - rect_width / 2
        pygame.draw.rect(screen, GREEN, pygame.Rect((rect_x, rect_y), (rect_width, rect_height)))

        #   顯示居中處理
        winner_x = SCREEN_SIZE[0] / 2 - winner_width / 2
        winner_y = rect_y
        screen.blit(text_surWinner, (winner_x, winner_y))

        #   顯示居中處理
        pos_warn_x = SCREEN_SIZE[0] / 2 - warn_width / 2
        pos_warn_y = rect_y + winner_height
        screen.blit(text_surWarn, (pos_warn_x, pos_warn_y))

    while True:
        checkForOut()

        if status == 1:
            #   彈出遊戲開始介面
            start_menu()
        if status == 2:
            #   獲取按鍵情況
            key_pressed = pygame.key.get_pressed()
            #   如果按下LEFT鍵,執行擋板左移
            if key_pressed[276]:
                baffle.BAFFLE_D_move_left()
            # 如果按下RIGHT鍵,執行擋板右移
            elif key_pressed[275]:
                baffle.BAFFLE_D_move_right()
            # 如果按下a鍵,執行擋板左移
            elif key_pressed[97]:
                baffle.BAFFLE_U_move_left()
            # 如果按下d鍵,執行擋板右移
            elif key_pressed[100]:
                baffle.BAFFLE_U_move_right()

            #   彈珠的邊緣檢測
            ball.edge_detection()

            #   填充螢幕顏色,相當於重新整理介面
            screen.fill((0, 0, 0))

            #   劃分雙方區域
            divide()
            #   畫出擋板
            baffle.draw()
            #   畫出彈珠
            ball.draw()
        if status == 3:
            # 彈出遊戲結束介面選單
            end_menu()

        pygame.display.flip()

GameBody()