游戏编程----Python

 前言

我们将制作这样一个游戏,移动挡板挡住笑脸球,不让它掉到屏幕底部。

制作游戏的两个能力:绘制动画的能力和处理用户交互的能力。

设计游戏要考虑的要素(以Smiley Pong为例):

玩游戏的区域或游戏板        一个黑色的屏幕,表示一个Ping-Pong游戏板的一半。
目标和成就        玩家试图得分并避免丢掉命。
游戏部件(游戏角色和对象)         玩家有一个球和一个挡板。
规则        “如果球碰到了挡板,玩家得到1分;如果球碰到了屏幕的底部,玩家丢掉一条命。
机制         我们使用鼠标来左右移动挡板,守卫屏幕的底部;随着游戏的进行,球将会移动得更快。
资源         玩家将会有5条命,或者尽可能多地得分。

一、构建游戏框架-Smiley Pong 1.0 版

以下面的程序为基础(弹跳的笑脸程序) 

# SmileyBounce2.py
import pygame        # Setup
pygame.init()
screen = pygame.display.set_mode([800,600])
keep_going = True
pic = pygame.image.load("CrazySmile.bmp")
colorkey = pic.get_at((0,0))
pic.set_colorkey(colorkey)
picx = 0
picy = 0
BLACK = (0,0,0)
timer = pygame.time.Clock()
speedx = 5
speedy = 5
while keep_going:    # Game loop
    for event in pygame.event.get(): 
        if event.type == pygame.QUIT: 
            keep_going = False
    picx += speedx
    picy += speedy
    
    if picx <= 0 or picx + pic.get_width() >= 800:
        speedx = -speedx
    if picy <= 0 or picy + pic.get_height() >= 600:
        speedy = -speedy
    screen.fill(BLACK)    
    screen.blit(pic, (picx, picy))
    pygame.display.update()
    timer.tick(60)
    
pygame.quit()        # Exit

绘制挡板

挡板的设置:

WHITE = (255,255,255)    #挡板的颜色
paddlew = 200            #宽度
paddleh = 25             #高度
paddlex = 300            #起始x坐标
paddley = 550            #起始y坐标

我们让挡板跟随鼠标在屏幕底部左右移动,并让鼠标的x坐标位于挡板中央:

    paddlex = pygame.mouse.get_pos()[0]
    paddlex -= paddlew/2

绘制挡板:

pygame.draw.rect(screen, WHITE, (paddlex, paddley, paddlew, paddleh))

记录分数

设置分数和生命数的初始值:

points = 0
lives = 5

减少命数

为了游戏更具一般性,作如下设置:

screenw=800
screenh=600
screen = pygame.display.set_mode([screenw,screenh])
picw = 100    #笑脸球的宽度
pich = 100    #笑脸球的高度

 当笑脸球碰到屏幕底部时,笑脸球的y坐标等于screenh-pich,所以picy>=screenh-pich时,命数要减少,所以修改笑脸球碰到屏幕上下边缘时的代码:

    if picy <= 0:
        speedy = -speedy 
    if picy >= screenh-pich:
        lives -= 1
        speedy = -speedy

用挡板碰到球

游戏编程----Python_第1张图片

因为笑脸与挡板都是虚拟的,所以笑脸可以穿过挡板再反弹上来,那么也能符合上面的规定,但是不符合现实情况,所以我们要确保笑脸是向下运动的时候,符合上面的规定,所以得出挡板碰到球的条件:

    if picy + pich >= paddley and picy + pich <= paddley + paddleh \
       and speedy > 0:
        if picx + picw / 2 >= paddlex and picx + picw / 2 <= paddlex + \
           paddlew:

 反斜杠“\”的作用是连接代码,当代码太长时,我们分行写,用反斜杠连接。

添加一分并使球反弹

当挡板碰到球后,添加一分并使球反弹。

            points += 1
            speedy = -speedy

显示得分

我们在屏幕顶端中间向下走10个像素那里绘制得分和命数。

确定用哪种字体,多大字体来绘制文本:

font = pygame.font.SysFont("Times", 24)

在每次游戏循环中绘制文本: 

    # Draw text on screen
    draw_string = "Lives: " + str(lives) + " Points: " + str(points)
        
    text = font.render(draw_string, True, WHITE)
    text_rect = text.get_rect()
    text_rect.centerx = screen.get_rect().centerx
    text_rect.y = 10
    screen.blit(text, text_rect)

说明:

render(text, antialias, color, background=None) -> Surface

        draw text on a new Surface

        The antialias argument is a boolean: if True the characters will have smooth edges. 

整合

# SmileyBounce2.py
import pygame        # Setup
pygame.init()

screenw=800
screenh=600
screen = pygame.display.set_mode([screenw,screenh])
picw = 100
pich = 100

keep_going = True
pic = pygame.image.load("CrazySmile.bmp")
colorkey = pic.get_at((0,0))
pic.set_colorkey(colorkey)
picx = 0
picy = 0
BLACK = (0,0,0)
timer = pygame.time.Clock()
speedx = 5
speedy = 5

WHITE = (255,255,255)    #挡板的颜色
paddlew = 200            #宽度
paddleh = 25             #高度
paddlex = 300            #起始x坐标
paddley = 550            #起始y坐标

points = 0
lives = 5

font = pygame.font.SysFont("Times",24)
while keep_going:    # Game loop
    for event in pygame.event.get(): 
        if event.type == pygame.QUIT: 
            keep_going = False
    picx += speedx
    picy += speedy
    
    if picx <= 0 or picx + pic.get_width() >= screenw:
        speedx = -speedx
    if picy <= 0:
        speedy = -speedy 
    if picy >= screenh-pich:
        lives -= 1
        speedy = -speedy

    
    
    screen.fill(BLACK)    
    screen.blit(pic, (picx, picy))
    
    paddlex = pygame.mouse.get_pos()[0]
    paddlex -= paddlew/2
    pygame.draw.rect(screen, WHITE, (paddlex, paddley, paddlew, paddleh))
    # Check for paddle bounce
    if picy + pich >= paddley and picy + pich <= paddley + paddleh \
       and speedy > 0:
        if picx + picw / 2 >= paddlex and picx + picw / 2 <= paddlex + \
           paddlew:
            points += 1
            speedy = -speedy
    
    # Draw text on screen
    draw_string = "Lives: " + str(lives) + " Points: " + str(points)
        
    text = font.render(draw_string, True, WHITE)
    text_rect = text.get_rect()
    text_rect.centerx = screen.get_rect().centerx
    text_rect.y = 10
    
    screen.blit(text, text_rect)
    pygame.display.update()
    timer.tick(60)
    
pygame.quit()        # Exit

二、增加难度并结束游戏-Smiley Pong

游戏结束

在 draw_string = "Lives: " + str(lives) + " Points: " + str(points) 下面添加游戏结束要干嘛:

    # Check whether the game is over
    if lives < 1:  
        speedx = speedy = 0
        draw_string = "Game Over. Your score was: " + str(points)
        draw_string += ". Press F1 to play again. "

再玩一次

在处理事件的for循环中添加如下代码:

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_F1:    # F1 = New Game
                points = 0
                lives = 5
                picx = 0
                picy = 0
                speedx = 5
                speedy = 5

查找哪个键用什么表示:pygame.key — pygame v2.5.0 documentation 

更快

我们想要在笑脸回弹的时候增加笑脸的速度:

    if picx <= 0 or picx + pic.get_width() >= screenw:
        speedx = -speedx * 1.1
    if picy <= 0:
        speedy = -speedy + 1

每次玩家都掉一条性命的时候,我们将重新设置速度: 

    if picy >= screenh-pich:
        lives -= 1
        speedx = 5
        speedy = -5

随着挡板不断地挡住笑脸,speedy的值变得越来越大,假如我们不去挡笑脸并且当前帧笑脸的y坐标是screenh-pich-1,那么下一帧笑脸的y坐标可能是screenh,那么再下一帧就是screenh-5,那么笑脸(pich=100)并不能都在屏幕之上,而且又要减少生命,所以生命立即减少到0,所以在玩家丢掉一条生命的时候,我们设置:

picy = screenh-pich+1

整合

# SmileyBounce2.py
import pygame        # Setup
pygame.init()

screenw=800
screenh=600
screen = pygame.display.set_mode([screenw,screenh])
picw = 100
pich = 100

keep_going = True
pic = pygame.image.load("CrazySmile.bmp")
colorkey = pic.get_at((0,0))
pic.set_colorkey(colorkey)
picx = 0
picy = 0
BLACK = (0,0,0)
timer = pygame.time.Clock()
speedx = 5
speedy = 5

WHITE = (255,255,255)    #挡板的颜色
paddlew = 200            #宽度
paddleh = 25             #高度
paddlex = 300            #起始x坐标
paddley = 550            #起始y坐标

points = 0
lives = 5

font = pygame.font.SysFont("Times",24)
BLUE = (0,0,255)    #文本的背景色
while keep_going:    # Game loop
    for event in pygame.event.get(): 
        if event.type == pygame.QUIT: 
            keep_going = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_F1:    # F1 = New Game
                points = 0
                lives = 5
                picx = 0
                picy = 0
                speedx = 5
                speedy = 5
                
    picx += speedx
    picy += speedy
    
    if picx <= 0 or picx + pic.get_width() >= screenw:
        speedx = -speedx * 1.1
    if picy <= 0:
        speedy = -speedy + 100
    if picy >= screenh-pich:
        lives -= 1
        speedx = 5
        speedy = -5
        picy = screenh-pich+1    
    
    screen.fill(BLACK)    
    screen.blit(pic, (picx, picy))
    
    paddlex = pygame.mouse.get_pos()[0]
    paddlex -= paddlew/2
    pygame.draw.rect(screen, WHITE, (paddlex, paddley, paddlew, paddleh))
    # Check for paddle bounce
    if picy + pich >= paddley and picy + pich <= paddley + paddleh \
       and speedy > 0:
        if picx + picw / 2 >= paddlex and picx + picw / 2 <= paddlex + \
           paddlew:
            points += 1
            speedy = -speedy
    
    # Draw text on screen
    draw_string = "Lives: " + str(lives) + " Points: " + str(points)

    # Check whether the game is over
    if lives < 1:   
        speedx = speedy = 0
        draw_string = "Game Over. Your score was: " + str(points)
        draw_string += ". Press F1 to play again. "
        
    text = font.render(draw_string, True, WHITE, BLUE)
    text_rect = text.get_rect()
    text_rect.centerx = screen.get_rect().centerx
    text_rect.y = 10
    
    screen.blit(text, text_rect)
    pygame.display.update()
    timer.tick(60)
    
pygame.quit()        # Exit

三、添加更多的功能----SmileyPop 2.0版

以SmileyPop1.0版为基础 

使用 Pygame 添加声音

在程序的设置部分,初始化混合器,创建声音对象:

pygame.mixer.init()
pop = pygame.mixer.Sound("pop.wav")

如果有笑脸被点中,发出声音:

                if len(clicked_smileys) > 0:
                    pop.play()

跟踪和记录玩家进度

设置存储创建的笑脸数量和被击中的笑脸数量的变量:

WHITE = (255,255,255)
font = pygame.font.SysFont("Arial", 24)
count_smileys = 0
count_popped = 0

 计算创建的笑脸数:

    if mousedown:
        speedx = random.randint(-5, 5)
        speedy = random.randint(-5, 5)
        newSmiley = Smiley(pygame.mouse.get_pos(), speedx, speedy)
        sprite_list.add(newSmiley)
        count_smileys += 1

被点击的笑脸数:

                if len(clicked_smileys) > 0:
                    pop.play()
                    count_popped += len(clicked_smileys)

被点破笑脸所占百分比:

round(count_popped/count_smileys*100, 1)

 显示玩家进度等:

    draw_string = "Bubbles created: " + str(count_smileys)
    draw_string += " - Bubbles popped: " + str(count_popped)
    if (count_smileys > 0):
        draw_string += " - Percent: "
        draw_string += str(round(count_popped/count_smileys*100, 1))
        draw_string += "%" 
    text = font.render(draw_string, True, WHITE)
    text_rect = text.get_rect()
    text_rect.centerx = screen.get_rect().centerx
    text_rect.y = 10
    screen.blit (text, text_rect)

整合

# SmileyPop.py
import pygame
import random
BLACK = (0,0,0)
WHITE = (255,255,255)
pygame.init()
screen = pygame.display.set_mode([800,600])
pygame.display.set_caption("Pop a Smiley")
mousedown = False
keep_going = True
clock = pygame.time.Clock()
pic = pygame.image.load("CrazySmile.bmp")
colorkey = pic.get_at((0,0))
pic.set_colorkey(colorkey)
sprite_list = pygame.sprite.Group()
pygame.mixer.init()
pop = pygame.mixer.Sound("pop.wav")
font = pygame.font.SysFont("Arial", 24)
count_smileys = 0
count_popped = 0
class Smiley(pygame.sprite.Sprite):
    pos = (0,0)
    xvel = 1
    yvel = 1
    scale = 100
    def __init__(self, pos, xvel, yvel):
        pygame.sprite.Sprite.__init__(self)
        self.image = pic
        self.scale = random.randrange(10,100)
        self.image = pygame.transform.scale(self.image, (self.scale,self.scale))
        self.rect = self.image.get_rect()
        self.pos = pos
        self.rect.x = pos[0] - self.scale/2
        self.rect.y = pos[1] - self.scale/2
        self.xvel = xvel
        self.yvel = yvel
    def update(self):
        self.rect.x += self.xvel
        self.rect.y += self.yvel
        if self.rect.x <= 0 or self.rect.x > screen.get_width() - self.scale:
            self.xvel = -self.xvel
        if self.rect.y <= 0 or self.rect.y > screen.get_height() - self.scale:
            self.yvel = -self.yvel
while keep_going:
    for event in pygame.event.get(): 
        if event.type == pygame.QUIT: 
            keep_going = False
        if event.type == pygame.MOUSEBUTTONDOWN:
            if pygame.mouse.get_pressed()[0]:    # Regular left mouse button, draw
                mousedown = True
            elif pygame.mouse.get_pressed()[2]:  # Right mouse button, pop
                pos = pygame.mouse.get_pos()
                clicked_smileys = [s for s in sprite_list if s.rect.collidepoint(pos)]
                sprite_list.remove(clicked_smileys)
                if len(clicked_smileys) > 0:
                    pop.play()
                    count_popped += len(clicked_smileys)
        if event.type == pygame.MOUSEBUTTONUP:
            mousedown = False
    screen.fill(BLACK)
    sprite_list.update()
    sprite_list.draw(screen)
    clock.tick(60)
    draw_string = "Bubbles created: " + str(count_smileys)
    draw_string += " - Bubbles popped: " + str(count_popped)
    if (count_smileys > 0):
        draw_string += " - Percent: "
        draw_string += str(round(count_popped/count_smileys*100, 1))
        draw_string += "%" 
    text = font.render(draw_string, True, WHITE)
    text_rect = text.get_rect()
    text_rect.centerx = screen.get_rect().centerx
    text_rect.y = 10
    screen.blit (text, text_rect)
    pygame.display.update()
    if mousedown:
        speedx = random.randint(-5, 5)
        speedy = random.randint(-5, 5)
        newSmiley = Smiley(pygame.mouse.get_pos(),speedx,speedy)
        sprite_list.add(newSmiley)
        count_smileys += 1
        
pygame.quit()

四、本章小结

五、编程挑战

你可能感兴趣的:(python,游戏,python)