iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 30
0

透過書本的幫助以及這30天的努力,以下就是我實作內容拉~/images/emoticon/emoticon42.gif

打磚塊遊戲

import pygame as pg, random, math, time

#建立球體
class Ball(pg.sprite.Sprite):
    dx = 0         #x位移量
    dy = 0         #y位移量
    x = 0          #球x坐標
    y = 0          #球y坐標
    direction = 0  #球移動方向
    speed = 0      #球移動速度
 
    def __init__(self, sp, srx, sry, radium, color):
        pg.sprite.Sprite.__init__(self)
        self.speed = sp
        self.x = srx
        self.y = sry
        #繪製球體
        self.image = pg.Surface([radium*2, radium*2])  
        self.image.fill((255,255,255))
        pg.draw.circle(self.image, color, (radium,radium), radium, 0)
        self.rect = self.image.get_rect()  #取得球體區域
        self.rect.center = (srx,sry)       #初始位置
        self.direction = random.randint(40,70)  #移動角度

 #球體移動 
    def update(self):         
        radian = math.radians(self.direction)    #角度轉為弳度
        self.dx = self.speed * math.cos(radian)  #球水平運動速度
        self.dy = -self.speed * math.sin(radian) #球垂直運動速度
        self.x += self.dx     #計算球新坐標
        self.y += self.dy
        self.rect.x = self.x  #移動球圖形
        self.rect.y = self.y
        #到達左右邊界
        if(self.rect.left <= 0 or self.rect.right >= screen.get_width()-10):  
            self.bouncelr()
        elif(self.rect.top <= 10):  #到達上邊界
            self.rect.top = 10
            self.bounceup()
        if(self.rect.bottom >= screen.get_height()-10):  #到達下邊界出界
            return True
        else:
            return False
 
    def bounceup(self):  #上邊界反彈
        self.direction = 360 - self.direction

    def bouncelr(self):  #左右邊界反彈
        self.direction = (180 - self.direction) % 360

#磚塊類別            
class Brick(pg.sprite.Sprite):
    def __init__(self, color, x, y):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface([38, 13])  #磚塊長寬38x13
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y

#板子類別
class Pad(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.image.load("media\\pad.png")  #滑板圖片
        self.image.convert()
        self.rect = self.image.get_rect()
        self.rect.x = int((screen.get_width() - self.rect.width)/2)  #滑板位置
        self.rect.y = screen.get_height() - self.rect.height - 30
        
#板子位置隨滑鼠移動 
    def update(self):  
        pos = pg.mouse.get_pos()  
        self.rect.x = pos[0]       #滑鼠x坐標
        #不要移出右邊界
        if self.rect.x > screen.get_width() - self.rect.width:
            self.rect.x = screen.get_width() - self.rect.width

#結束程式
def gameover(message): 
    global running
    #顯示訊息
    text = ffont.render(message, 1, (255,0,255))  
    screen.blit(text, (screen.get_width()/2-150,screen.get_height()/2-20))
    pg.display.update()  #更新畫面
    time.sleep(5)        #暫停5秒    
    running = False      #結束程式

pg.init()
score = 0  #得分
dfont = pg.font.SysFont("Arial", 20)    #下方訊息字體
ffont = pg.font.SysFont("SimHei", 32)   #結束程式訊息字體
soundhit = pg.mixer.Sound("media\\hit.wav")  #碰到磚塊音效
soundpad = pg.mixer.Sound("media\\pad.wav")  #碰到滑板音效
#背景
screen = pg.display.set_mode((600, 400))
pg.display.set_caption("Sean's Brick Game")
background = pg.Surface(screen.get_size())
background = background.convert()
background.fill((255,255,255))
allsprite = pg.sprite.Group()  #建立全部角色群組
bricks = pg.sprite.Group()     #建立磚塊角色群組
ball = Ball(15, 300, 350, 10, (255,123,188)) #建立粉球
allsprite.add(ball)  #加入全部角色群組
pad = Pad()          #建立滑板球物件
allsprite.add(pad)   #加入全部角色群組

#建立磚塊
for row in range(0, 5):          #5列方塊
    for column in range(0, 15):  #每列15磚塊
        if row == 1 or row == 0: 
            brick = Brick((153,205,255), column * 40 + 1, row * 15 + 1)   #位置為40*15
        if row == 2: 
            brick = Brick((94,175,254), column * 40 + 1, row * 15 + 1)    
        if row == 3 or row == 4:  
            brick = Brick((52,153,207), column * 40 + 1, row * 15 + 1)  
        bricks.add(brick)     #加入磚塊角色群組
        allsprite.add(brick)  #加入全部角色群組
        
clock = pg.time.Clock()        
downmsg = "Press Left Click Button to start game!"  #起始訊息
playing = False  #開始時球不會移動
running = True

#運行的程式碼
while running:
    clock.tick(40)
    for event in pg.event.get():
        if event.type == pg.QUIT:
            running = False
    buttons = pg.mouse.get_pressed()  #檢查滑鼠按鈕
    if buttons[0]:            #按滑鼠左鍵後球可移動       
        playing = True
        
    #遊戲進行中
    if playing == True:  
        screen.blit(background, (0,0))  #清除繪圖視窗
        fail = ball.update()  #移動球體
        if fail:              #球出界
            gameover("You failed!See you next time~")
        pad.update()          #更新滑板位置
        #檢查球和磚塊碰撞
        hitbrick = pg.sprite.spritecollide(ball, bricks, True)  
        if len(hitbrick) > 0:  #球和磚塊發生碰撞
            score += len(hitbrick)  #計算分數
            soundhit.play()    #球撞磚塊聲
            ball.rect.y += 20  #球向下移
            ball.bounceup()    #球反彈
            if len(bricks) == 0:  #所有磚塊消失
                gameover("Congratulations!!")
        #檢查球和滑板碰撞
        hitpad = pg.sprite.collide_rect(ball, pad)  
        if hitpad:  #球和滑板發生碰撞
            soundpad.play()  #球撞滑板聲
            ball.bounceup()  #球反彈
        allsprite.draw(screen)  #繪製所有角色
        downmsg = "Score: " + str(score)
    #繪製下方訊息    
    message = dfont.render(downmsg, 1, (255,0,255))
    screen.blit(message, (screen.get_width()/2-125,screen.get_height()-30))
    pg.display.update()
pg.quit()

遊戲截圖:

https://ithelp.ithome.com.tw/upload/images/20181114/20112078rFFPeuLQWo.png
https://ithelp.ithome.com.tw/upload/images/20181114/20112078qgSDeK8uHO.png
https://ithelp.ithome.com.tw/upload/images/20181114/20112078SydoG0B16s.png


上方程式碼我都有用註解註明意思,要理解就會變得很難易! 如果要拿出去測試的話,會缺少我這裡的圖檔跟音檔,所以那部分可能要再做修改。
其實寫完程式後,我一直想用pyinstaller將它打包成.exe執行檔,不過他一直出現no module named....的錯誤訊息,可能是在打包過程中,一些模組沒有被偵測到吧?QQ

總之謝謝能有這30天的自我挑戰跟老師的推薦,還有那些願意花時間在我文章上的人XD~讓我確確實實地學習Python,並成長了許多,同時期望未來我的實作內容能在更擴充,不要那麼單調無聊.../images/emoticon/emoticon38.gif
那麼各位下次見囉~/images/emoticon/emoticon41.gif


上一篇
Day29-PyGame動畫處理
系列文
Python 30天學習日誌30

尚未有邦友留言

立即登入留言