2015/11/9用Python寫遊戲,pygame入門(8):按鈕和遊戲結束

昨天沒有更新內容,今天相對多寫一些。程序員

由於咱們已經基本完成遊戲框架,可是遊戲結束後,並不知道怎樣比較好開始。我原本本着懶的原則,想結束後顯示一個黑屏,而後你從新點一下鼠標就從新開始。可是那樣實在太不像個熱愛生活的程序員了,因此我決定用更合適的方法解決這個問題。app

爲此,我決定實現一個相對比較過得去的按鈕。框架


爲了實現按鈕,我先建立一個測試程序體。而後在上面先實現一個按鈕類的功能。dom

具體的測試程序,我就不詳說了,反正就是你去建立一個這樣的小窗口:測試

而後在上面完成一個按鈕的類。動畫

我設想的按鈕應該是這樣的,當我把鼠標移動上去的時候,它會將白底顯示成灰底,移開後,又顯示回白底。這其實就是兩張圖片的切換,因此,第一步要作的是,製做兩張圖,一張是白底的按鈕,一張是灰底的按鈕:ui

好了,接下來開始碼這個類的功能了,首先是它的數據對象,必須得有兩張圖。spa

而後它還得有個安置它的位置座標。rest

因此,它的初始化應該是這樣定義的:code

def __init__(self, upimage, downimage,position):
    self.imageUp = pygame.image.load(upimage).convert_alpha()
    self.imageDown = pygame.image.load(downimage).convert_alpha()
self.position
= position

而後,它應該有個方法來判斷,鼠標是否是在這個按鈕的上面:

def isOver(self):
    point_x,point_y = pygame.mouse.get_pos()
    x, y = self. position
    w, h = self.imageUp.get_size()

    in_x = x - w/2 < point_x < x + w/2
    in_y = y - h/2 < point_y < y + h/2
    return in_x and in_y

還有一個用於判斷顯示哪張圖的方法:

def render(self):
    w, h = self.imageUp.get_size()
x, y
= self.position if self.isOver(): screen.blit(self.imageDown, (x-w/2,y-h/2)) else: screen.blit(self.imageUp, (x-w/2, y-h/2))

好了,至此咱們就作好了一個類。

將它跟咱們的測試程序放在一塊兒而且執行它:

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

pygame.init()
screen = pygame.display.set_mode((300,200),0,32)
upImageFilename = 'game_again.png'
downImageFilename = 'game_again_down.png'

class Button(object):
    def __init__(self, upimage, downimage,position):
        self.imageUp = pygame.image.load(upimage).convert_alpha()
        self.imageDown = pygame.image.load(downimage).convert_alpha()
        self.position = position

    def isOver(self):
        point_x,point_y = pygame.mouse.get_pos()
        x, y = self. position
        w, h = self.imageUp.get_size()

        in_x = x - w/2 < point_x < x + w/2
        in_y = y - h/2 < point_y < y + h/2
        return in_x and in_y

    def render(self):
        w, h = self.imageUp.get_size()
        x, y = self.position
        
        if self.isOver():
            screen.blit(self.imageDown, (x-w/2,y-h/2))
        else:
            screen.blit(self.imageUp, (x-w/2, y-h/2))

button = Button(upImageFilename,downImageFilename, (150,100))
    
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
    screen.fill((200, 200, 200))
    button.render()
    pygame.display.update()

就能獲得一個顯示按鈕:

能夠實現了咱們的功能。

可是,等一下,咱們沒有寫按鈕的做用啊,也就是按下去就要執行的做用。

好吧,這件事反而是簡單的。咱們只須要判斷event的時候調用isOver()方法就行了。

 


 

接下來咱們來完成遊戲框架了。

我想要一個開始界面,有開始按鈕,遊戲過程當中,我想讓它計分,遊戲結束後能夠顯示最高分和我此次的分數,而且有個結束遊戲和從新開始的按鈕。

整個功能其實我都已經實現過了。

一步步地構造邏輯我就很少講了,直接放代碼。你們能夠本身完成它。

此次代碼裏,我把本身的飛機也用了類實現,便於之後的拓展,有了計分模塊,整個遊戲用全屏模式打開。

固然整個代碼仍是有些亂的,不過因爲大多數類和邏輯在以前已經講過,相信仍是易懂的

#-*- coding:utf-8-*-
import pygame
from sys import exit
from random import randint
from math import sqrt
pygame.init()
SCREEN_SIZE = (480,766)
screen = pygame.display.set_mode(SCREEN_SIZE,pygame.FULLSCREEN,32)
pygame.display.set_caption(" Plane Fight!")

count_b = 7
count_e = 50
fps = 100

ufo = pygame.image.load('ufo2.png').convert_alpha()
background = pygame.image.load('background.png').convert_alpha()
gameover_image = pygame.image.load('gameover.png').convert_alpha()
plane_image = pygame.image.load('hero.png').convert_alpha()
bullet_image = pygame.image.load('bullet.png').convert_alpha()
enemy_image = pygame.image.load('enemy2.png').convert_alpha()
logo = pygame.image.load('shoot_copyright.png').convert_alpha()
bomb_num = pygame.image.load('bomb_num.png').convert_alpha()
bomb_image = pygame.image.load('bomb.png').convert_alpha()
loading = []
loading.append(pygame.image.load('game_loading1.png').convert_alpha())
loading.append(pygame.image.load('game_loading2.png').convert_alpha())
loading.append(pygame.image.load('game_loading3.png').convert_alpha())
enemydown=[]
enemydown.append(pygame.image.load('enemy2_down1.png').convert_alpha())
enemydown.append(pygame.image.load('enemy2_down2.png').convert_alpha())
enemydown.append(pygame.image.load('enemy2_down3.png').convert_alpha())
enemydown.append(pygame.image.load('enemy2_down4.png').convert_alpha())
boom = []
boom.append(pygame.image.load('boom0.png').convert_alpha())
boom.append(pygame.image.load('boom1.png').convert_alpha())
boom.append(pygame.image.load('boom1.png').convert_alpha())
boom.append(pygame.image.load('boom2.png').convert_alpha())
boom.append(pygame.image.load('boom2.png').convert_alpha())

backmusic=pygame.mixer.Sound('game_music.ogg')
buttonmusic = pygame.mixer.Sound('button.ogg')
bulletmusic = pygame.mixer.Sound('bullet.wav')
enemydownmusic = pygame.mixer.Sound('enemy1_down.wav')
gameovermusic = pygame.mixer.Sound('game_over.ogg')
getbombmusic = pygame.mixer.Sound('get_bomb.wav')
usebombmusic = pygame.mixer.Sound('use_bomb.wav')

buttonmusic.set_volume(0.2)
bulletmusic.set_volume(0.04)
gameovermusic.set_volume(0.5)
enemydownmusic.set_volume(0.1)
channel = backmusic.play(-1)
channel.set_volume(0.1,0.1)
channel.pause()

font1 = pygame.font.Font(None,64)
font2 = pygame.font.Font(None,128)
clock = pygame.time.Clock()


def showLoading(count,pos):
    n = count/50
    x, y = pos
    w, h = loading[2].get_size()
    x -= w/2
    y -= h/2
    if n <3:
        screen.blit(loading[n],(x,y))

class Button(object):
    def __init__(self, upimage, downimage, position):
        self.image_up = pygame.image.load(upimage).convert_alpha()
        self.image_down = pygame.image.load(downimage).convert_alpha()
        self.position = position
        self.button_out = True

    def is_over(self):
        point_x, point_y = pygame.mouse.get_pos()
        x, y = self.position
        w, h = self.image_up.get_size()
        x -= w/2
        y -= h/2

        in_x = x < point_x < x + w
        in_y = y < point_y < y + h
        return in_x and in_y
     
    def render(self, surface):
        x, y = self.position
        w, h = self.image_up.get_size()
        x -= w/2
        y -= h/2
        if self.is_over():
            surface.blit(self.image_down, (x, y))
            if self.button_out == True:
                buttonmusic.play()
                self.button_out = False
        else:
            surface.blit(self.image_up, (x, y))
            self.button_out = True

class Hero(object):
    def restart(self):
        self.x = 200
        self.y = 600
    def __init__(self):
        self.restart()
        self.image = plane_image
    def move(self, time_passed_seconds):
        mouseX, mouseY = pygame.mouse.get_pos()
        self.x = mouseX - self.image.get_width()/2
        self.y = mouseY - self.image.get_height()/2
    
        
class Bullet(object):    
    def __init__(self):
        self.x = 0
        self.y = -1
        self.image = bullet_image
        self.active = False
    def move(self,time_passed_seconds):
        if self.active :
            self.y -= 700 * time_passed_seconds
        if self.y < 0:
            self.active = False
            
    def restart(self,flag):
        mouseX, mouseY = pygame.mouse.get_pos()
        if flag == 1:
            self.x = mouseX - self.image.get_width()/2 
            self.y = mouseY - self.image.get_height()/2
        if flag == 2:
            self.x = mouseX - self.image.get_width()/2 + 33
            self.y = mouseY - self.image.get_height()/2
        self.active = True
class Enemy(object):
    def restart(self, score):
        self.x = randint(-30,440)
        self.y = randint(-200,-100)
        self.speed = randint(min(200+score/80,400),min(400+score/40,700))
        self.active = True
        self.count = -1
    def __init__(self,):
        self.restart(0)
        self.image = enemy_image
        self.active = False
        
    def move(self,time_passed_seconds):
        if self.y < SCREEN_SIZE[1]:
            self.y += self.speed * time_passed_seconds
        else:
            self.active = False
    def showDown(self):
        n = self.count/10
        screen.blit(enemydown[n],(self.x,self.y))
        self.count += 1
        if self.count >= 39:
            self.count = -1

class Bomb(object):
    def __init__(self):
        self.image = bomb_image
        (self.x , self.y) = (-100,-100)
        self.boom_x, self.boom_y = 0,0
        self.speed = 800
        self.active = False
        self.is_boom = False
        self.boomcount = 0
    def shoot(self):
        self.x, self.y = pygame.mouse.get_pos()
        self.x -= self.image.get_width()/2
        self.y -= self.image.get_height()/2
        self.active = True
    def move(self,time_passed_seconds):
        if self.y > 250:
            self.y -= self.speed*time_passed_seconds
        else:
            self.active = False
            self.is_boom = True
            self.boom_x, self.boom_y = self.x , self.y
            usebombmusic.play()
    def checkBoom(self,enemy):
        if enemy.x - 60 < self.x < enemy.x + enemy.image.get_width()+60\
           and enemy.y < self.y < enemy.y + enemy.image.get_height():
            self.active = False
            self.is_boom = True
            self.boom_x, self.boom_y = self.x , self.y
            usebombmusic.play()
    def checkHit(self,enemy):
        a = float(self.x - (enemy.x + enemy.image.get_width()/2))
        b = float(self.y - (enemy.y + enemy.image.get_height()/2))
        l = sqrt(a**2 + b**2)
        if l < 250:
            enemy.active = False
            enemy.count = 1
            return True
        else:
            return False
    def boom(self):
        n = self.boomcount/10
        screen.blit(boom[n],(self.boom_x-boom[n].get_width()/2, self.boom_y-boom[n].get_height()/2))
        self.boomcount += 1
        if self.boomcount >= 49:
            self.is_boom = False
            self.boomcount = 0

class Ufo(object):
    def restart(self):
        self.x = randint(-30,440)
        self.y = -107
        self.speed = 250
    def __init__(self):
        self.image = ufo
        self.restart()
        self.active = False
    def move(self,time_passed_seconds):
        if self.y < SCREEN_SIZE[1]:
            self.y += self.speed * time_passed_seconds
        else:
            self.active = False
    def checkGet(self,plane):
        if plane.x - 60 < self.x < plane.x + plane.image.get_width()+60\
           and plane.y -80 < self.y < plane.y + plane.image.get_height():
            self.active = False
            getbombmusic.play()
            return True
        else:
            return False
        

def checkHit(enemy,bullet):
    if enemy.x < bullet.x < enemy.x + enemy.image.get_width() \
       and enemy.y < bullet.y < enemy.y + enemy.image.get_height():
        enemy.active = False
        bullet.active = False
        enemydownmusic.play()
        enemy.count+=1
        return True
    else:
        return False

def checkCrash(enemy,plane):
    if plane.x + 0.3*plane.image.get_width()< enemy.x + enemy.image.get_width() and\
       enemy.x  < plane.x + 0.7*plane.image.get_width() and \
       plane.y + 0.3*plane.image.get_height() < enemy.y + enemy.image.get_height()and\
       enemy.y < plane.y + 0.7*plane.image.get_height():
        return True
    else:
        return False

def showWelcome(gameStart,gameOver):
    for event in pygame.event.get():
        if event.type in (pygame.QUIT,pygame.KEYDOWN):
              pygame.quit()
              exit()
        if event.type == pygame.MOUSEBUTTONUP:
            if gameStart.is_over():
                return False
            elif gameOver.is_over():
                pygame.quit()
                exit()
    screen.blit(background, (0,0))
    screen.blit(logo, ((SCREEN_SIZE[0]-logo.get_width())/2,100))
    gameStart.render(screen)
    gameOver.render(screen)
    return True

def run():
    sound = True
    gameStart = Button('game_start.png','game_start_down.png',(SCREEN_SIZE[0]/2,SCREEN_SIZE[1]*8/12))
    gameOver = Button('game_over.png','game_over_down.png',(SCREEN_SIZE[0]/2,SCREEN_SIZE[1]*11/12))
    gameAgain = Button('game_again.png','game_again_down.png',(SCREEN_SIZE[0]/2,SCREEN_SIZE[1]*10/12))
    gameContinue = Button('game_continue.png','game_continue_down.png',(SCREEN_SIZE[0]/2,SCREEN_SIZE[1]*9/12))
    loadingCount = 0
    while showWelcome(gameStart,gameOver):
        time_passed = clock.tick(100)
        loadingCount = (loadingCount+1) % 200
        showLoading(loadingCount,(SCREEN_SIZE[0]/2,SCREEN_SIZE[1]*19/24))
        pygame.display.update()

    pygame.mouse.set_visible(False)
    plane = Hero() 
    bullets1 = []
    bullets2 = []
    for i in range(count_b):
        bullets1.append(Bullet())
        bullets2.append(Bullet())
    index_b1 = 0
    interval_b1 = 0
    #index_b2 = 0
    #interval_b2 = 0
    enemies = []
    for i in range(count_e):
        enemies.append(Enemy())
    index_e = 0
    interval_e = 0
    ufo = Ufo()
    
    SCORE = 15000
    maxScore = 0
    BOMBnum = 3
    bomb = Bomb()
    gameover = False
    gamePause = False
    bombflag = True
    event = pygame.event.wait()
    while True:       
        time_passed = clock.tick(fps)
        time_passed_seconds = time_passed / 1000.0
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    exit()
                if event.key == pygame.K_SPACE:
                    gamePause = True
            
        if gamePause:
            channel.pause()
            pygame.mouse.set_visible(True)
            screen.blit(background,(0,0))
            screen.blit(logo, ((SCREEN_SIZE[0]-logo.get_width())/2,100))
            gameOver.render(screen)
            gameAgain.render(screen)
            gameContinue.render(screen)
            bombflag = True
            if event.type == pygame.MOUSEBUTTONUP:
                if gameOver.is_over():
                    pygame.quit()
                    exit()
                elif gameAgain.is_over():
                    pygame.mouse.set_visible(False)
                    gamePause = False
                    SCORE = 0
                    for e in enemies:
                        e.active = False
                elif gameContinue.is_over():
                    pygame.mouse.set_visible(False)
                    gamePause = False    
        elif not gameover:
            if randint(1,1000)==1 and ufo.active == False:
                ufo.active = True
                ufo.restart()
            channel.unpause()
            screen.blit(background,(0,0))
            screen.blit(bomb_num,(SCREEN_SIZE[0]-160,SCREEN_SIZE[1]-65))
            text = font1.render(" x %d"%BOMBnum,1,(80,80,80))
            screen.blit(text,(SCREEN_SIZE[0]-100,SCREEN_SIZE[1]-60))
            interval_b1 -= 1
           # interval_b2 -= 1
            interval_e -= 1
            if interval_b1 < 0:
                bullets1[index_b1].restart(1)
                interval_b1 = fps/count_b
                index_b1 = (index_b1 + 1)% count_b
                bulletmusic.play()
 
            for b in bullets1:
                if b.active:
                    b.move(time_passed_seconds)
                    screen.blit(b.image, (b.x,b.y))
                    for e in enemies:
                        if e.active:
                            if checkHit(e, b):
                                SCORE += 100
                                
 
            if interval_e < 0:
                enemies[index_e].restart(SCORE)
                interval_e = randint(max(0,30-SCORE/250),max(7,50-SCORE/700))
                index_e = (index_e + 1)% count_e
            if event.type == pygame.MOUSEBUTTONUP and BOMBnum>0 :
                if bombflag == False and bomb.active == False:
                    bomb.active = True
                    bomb.shoot()
                    BOMBnum -= 1
                    bombflag = True
            else:
                bombflag = False        
                
            if bomb.active:
                for e in enemies:
                    if e.active:
                        bomb.checkBoom(e)
                bomb.move(time_passed_seconds)
                screen.blit(bomb.image,(bomb.x,bomb.y))
            if bomb.is_boom:
                bomb.boom()
                for e in enemies:
                    if e.active:
                        if bomb.checkHit(e):
                            SCORE += 100
            for e in enemies:
                if e.active:
                    if checkCrash(e,plane):
                        gameover = True
                    e.move(time_passed_seconds)
                    screen.blit(e.image, (e.x, e.y))
                if e.count != -1:
                    e.showDown()
            if ufo.active:
                ufo.move(time_passed_seconds)
                if ufo.checkGet(plane):
                    BOMBnum += 1
                screen.blit(ufo.image,(ufo.x,ufo.y))
                
            plane.move(time_passed_seconds)
            screen.blit(plane.image, (plane.x,plane.y))
            text = font1.render("Score: %d"%SCORE,1,(0,0,0))
            screen.blit(text,(0,0))
        else:
            bombflag = True
            channel.pause()
            if sound == True:
                gameovermusic.play()
                sound = False
            if SCORE > maxScore:
                maxScore = SCORE
            Score = font2.render(str(SCORE),1,(50,50,50))
            mScore = font1.render(str(maxScore),1,(50,50,50))
            screen.blit(gameover_image,(0,0))
            screen.blit(mScore,(150,40))
            screen.blit(Score,(240-Score.get_width()/2, 375))
            gameAgain.render(screen)
            gameOver.render(screen)
            pygame.mouse.set_visible(True)
            if event.type == pygame.MOUSEBUTTONUP:
                if gameAgain.is_over():    
                    pygame.mouse.set_visible(False)
                    ufo.active = False
                    gameover = False
                    plane.restart()
                    SCORE = 0
                    sound = True
                    BOMBnum = 3
                    for e in enemies:
                        e.active = False
                elif gameOver.is_over():
                    pygame.quit()
                    exit()
            
        pygame.display.update()


if __name__ == '__main__':
    run()

 

pygame的這部份內容到這裏也差很少了。這個蹩腳的飛機大戰的基本功能也算是勉強實現了。

不過我還會再寫一篇添加音樂和擊毀動畫的部分。

寫的東西很基礎,適合初學者看,能給你們以幫助的話,那是最好不過了。

可是本身底子太薄,沒辦法說更多的東西,因此我會學更多的東西,纔可能分享更多的東西。

一樣,分享的過程也是知識梳理的一個過程。挺棒的。

相關文章
相關標籤/搜索