pygame编程“大战外星人”(二)

Words
592
Reading
3 min
5y
Listen to this post
~4 min

动画.gif

继续进行“大战外星人”的游戏编程实践,今天主要完成敌人的运动方式和子弹的编程。完成后的效果见题图。

一、游戏效果

外星人飞船在边界之间来回飞行,每碰到边界一次就下降一段距离,玩家可以发射导弹攻击外星人飞船,试图在外星人到达底部前击中它。击中后外星人飞船会消失然后在屏幕上方重新出现。

二、敌人的编程

敌人的行动逻辑,上文已经说了,代码基本上复制player的代码就行了,把原代码中的player换成enemy。在while循环内部增加这一段代码,实现外星飞船碰到边界后就反向(enemyx_change改变符号),同时下降一段距离

    enemyx += enemyx_change        
    if enemyx <= 0.8:
        enemyx_change=0.3
        enemyy += 4
    if enemyx >= 704:
        enemyx_change=-0.3
        enemyy += 4

三、子弹编程

子弹的逻辑就是取玩家飞机当前所在的位置,然后每个循环y坐标减少,实现向上飞行。同时设定一个状态变量,分为“fire”开火状态,“ready”预备状态,当按下空格键后,状态改为开火状态,只有处于开火状态,子弹才在屏幕上显示。与子弹有关的代码:

bulletImg=pygame.image.load('bullet.png')
bulletx=370
bullety=460
bullety_change=0.8
bullet_state='ready'

def bullet(x,y):
    global bullet_state
    bullet_state='fire'
    screen.blit(bulletImg,(x+5,y+10))
...
running=True
while running:
 ....
    if bullet_state == 'fire':
        bullet(bulletx,bullety)
        bullety -= bullety_change
    if bullety <= 0:
        bullet_state = 'ready'
        bullety=460

四、碰撞检测

当子弹击中外星飞船时,外星飞船会消失,然后从屏幕上方重新出现。这个过程需要进行碰撞检测。碰撞检测的原理很简单,就是计算子弹和外星飞船之间的距离,当距离小于一个数值时就认为两者发生了碰撞。基于勾股定理的两点间距离公式:

与碰撞检测有关的代码:

def isCollision(enemyx,enemyy,bulletx,bullety):
    distance=math.sqrt((enemyx+52.5-bulletx)**2+(enemyy+60-bullety)**2)
    if distance <50 :
        return True
    else :
        return False

....
    if isCollision(enemyx,enemyy,bulletx,bullety) :
        bullet_state = 'ready'
        bullety=460
        score += 1
        enemyx=randint(0,704)
        enemyy=randint(50,150)
        print(score)

从上面的代码中可以看出,当检测到碰撞发生,子弹的状态会变为“ready”预备状态,不再显示,而敌人也会在屏幕上部重新出现,同时还有一个用来计分的变量score会加一。后面会学习如何在屏幕上显示分数。

五、目前程序的源代码和部分素材

enemy.png
外星敌人

bullet.png
导弹

background.jpg
游戏背景

程序源代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pygame
from random import randint
import math
# init
pygame.init()
# create screen 
screen=pygame.display.set_mode((800,600))

#title and icon
pygame.display.set_caption('大战外星人')
icon=pygame.image.load('ufo.png')
pygame.display.set_icon(icon)

#player 
playerImg=pygame.image.load('f18.png')
playerx=370
playery=460
playerx_change=0

def player(x,y):
    screen.blit(playerImg,(x,y))

#background
backgroundImg=pygame.image.load('background.jpg')




#enemy
enemyImg=pygame.image.load('enemy.png')
enemyx=randint(0,704)
enemyy=randint(50,150)
enemyx_change=0.2

score = 0

def enemy(x,y):
    screen.blit(enemyImg,(x,y))

#bullet
bulletImg=pygame.image.load('bullet.png')
bulletx=370
bullety=460
bullety_change=0.8
bullet_state='ready'

def bullet(x,y):
    global bullet_state
    bullet_state='fire'
    screen.blit(bulletImg,(x+5,y+10))

def isCollision(enemyx,enemyy,bulletx,bullety):
    distance=math.sqrt((enemyx+52.5-bulletx)**2+(enemyy+60-bullety)**2)
    if distance <50 :
        return True
    else :
        return False


running=True
while running:
    screen.fill((0,0,128))
    screen.blit(backgroundImg,(0,0))

#检查左右键是否被按下
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running=False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                playerx_change -= 0.4
            if event.key == pygame.K_RIGHT:
                playerx_change += 0.4
            if event.key == pygame.K_SPACE and bullet_state == 'ready':
                bullet(playerx,bullety)
                bulletx=playerx

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                playerx_change=0
            
    playerx += playerx_change        
    if playerx <= 0.8:
        playerx=0.8
    if playerx >= 704:
        playerx=704

    player(playerx,playery)

    enemyx += enemyx_change        
    if enemyx <= 0.8:
        enemyx_change=0.3
        enemyy += 4
    if enemyx >= 704:
        enemyx_change=-0.3
        enemyy += 4

    enemy(enemyx,enemyy)

    if bullet_state == 'fire':
        bullet(bulletx,bullety)
        bullety -= bullety_change
    if bullety <= 0:
        bullet_state = 'ready'
        bullety=460
    if isCollision(enemyx,enemyy,bulletx,bullety) :
        bullet_state = 'ready'
        bullety=460
        score += 1
        enemyx=randint(0,704)
        enemyy=randint(50,150)
        print(score)


    pygame.display.update()

pygame编程“大战外星人”(二) | Ecency