在期末考试时高数(su)退学的我决定写一篇博客来消解准备回高三复读的心情。
本打算把所有代码都贴出来并对代码作一番详细的解释。但是回想一下,如果你是外行,那么我必须讲很多。内容太多就算是我也懒得看,还不如直接推荐你去读这本书:《Python编程:从入门到实(入)践(坟)》;如果你是内行,说不定你比我更精通,那我跟你讲那么多干嘛?
#coding=gbk #这个软件的编译器检测到注释里有中文时会报错,加上这条语句就好了
#我用来敲python的软件是那本书里推荐的Geany,并不像Visual Studio,Jupyter那么高级,豪华
#但是挺好用的,好像还能写C,C++,Java和D,Vala,Erlang,Pascal,HTML,PHP等一些我没学过的语言
#不过这个软件的编译报错非常不友好:无法显示中文文字,找bug只能根据traceback
import pygame
from pygame.sprite import Group
from settings import Settings #游戏的各种属性设置(你可以在这里把游戏变成容易或非常难)
#比如把子弹宽带调到非常大,一下子击中好几个”外星人“
from ship import Ship
from ship2 import Ship2 #只能一个人玩的游戏有什么意思?我这个可是双人游戏
#当然了,完全可以把这个游戏变成十人游戏
from game_stats import GameStats #跟踪游戏的统计信息
from button import Button #PLAY按钮
from scoreboard import Scoreboard #显示得分的类
import game_functions as gf #游戏的绝大多数函数都在此模组中
#from ball import Ball #这个ball类的灵感来源是某一个“动手试一试”,让我再创一个接球游戏,
#而我把它与这个游戏融合了,每当飞船接到球时飞船数加一(在不超过上限的情况下)
#由于Ball类在game_function中才发挥作用,所以这里最好省略,下同
#from bullet import Bullet #一个对ship发射的子弹进行管理的类
#from bullet2 import Bullet2 #一个对ship2发射的子弹进行管理的类
#from alien import Alien #表示单个”外星人“的类,我随便找了一张图片来充当。。。
def run_game():
#初始化pygame,设置和屏幕对象。不作解释,具体请看书
pygame.init()
ai_settings=Settings()
screen=pygame.display.set_mode(
(ai_settings.screen_width,ai_settings.screen_height))
pygame.display.set_caption("Alien Invasion")
#创建Play按钮
play_button=Button(ai_settings,screen,"Play")
#创建一艘飞船
ship=Ship(ai_settings,screen)
#创建一个用于储存游戏统计信息的实例,并创建记分牌
stats=GameStats(ai_settings)
sb=Scoreboard(ai_settings,screen,stats,ship)
#创建ship2
ship2=Ship2(ai_settings,screen,ship)
#创建一个用于储存子弹的编组
bullets=Group()
#创建一个用于储存子弹的编组
bullets2=Group()
#创建一个”外星人“编组
aliens=Group()
#创建”外星人“群
gf.create_fleet(ai_settings,screen,ship,ship2,aliens)
#创建一个球编组
balls=Group()
#创建一个球群
gf.create_balls(ai_settings,screen,balls)
#开始游戏的主循环
while True: #C,C++等编译器省略缩进,但python就不一样了
gf.check_events(ai_settings,screen,stats,sb,ship,ship2,aliens,bullets,
bullets2,play_button)
if stats.game_active: #仅当游戏处于活跃状态时才更新这些
#游戏在未开始或GAMEOVER时处于非活跃状态
ship.update()
ship2.update()
gf.update_bullets(ai_settings,screen,stats,sb,ship,ship2,aliens,
bullets,balls)
gf.update_bullets2(ai_settings,screen,stats,sb,ship,ship2,aliens,
bullets2,balls)
gf.update_aliens(ai_settings,screen,stats,sb,ship,ship2,aliens,
bullets,bullets2)
gf.update_ball(ai_settings,screen,sb,ship,ship2,balls,stats)
gf.update_screen(ai_settings,screen,stats,sb,ship,ship2,aliens,bullets,
bullets2,balls,play_button)
run_game() #前面只是对函数进行定义,直到这里程序才开始运行
python的语法比较简单,语法高亮自然也比较单调,一眼看上去就跟没有差不多。
ship2模组真的不简单,第二个飞船位于屏幕的左端,其初始位置和运动范围由屏幕和第一个飞船的高度共同决定。
#coding=gbk
import pygame
from pygame.sprite import Sprite
class Ship2(Sprite):
"""创建一个ship2类"""
def __init__(self,ai_settings,screen,ship):
"""初始化飞船并设置其初始位置"""
super().__init__()
self.screen=screen #为了后面避免后面频繁地传参,这里让screen与self(即ship2)关联起来,下同
self.ai_settings=ai_settings
self.ship=ship
#加载飞船2图像并获取其外接矩形
self.image=pygame.image.load('images/ship2.bmp')
self.rect=self.image.get_rect()
self.screen_rect=self.screen.get_rect() #这里也可以写成self.screen_rect=screen.get_rect()
#将飞船放在屏幕左下方
self.rect.bottom=self.screen_rect.bottom-ship.rect.height
self.rect.left=self.screen_rect.left
#在飞船的bottom属性中储存小数值
self.bottom=float(self.rect.bottom)
#移动标志
self.moving_up=False
self.moving_down=False
def update(self):
"""根据移动标志调整飞船位置"""
#更新bottom属性而不是rect
if self.moving_up and self.rect.top>0: #在game_function函数中若玩家按下相应的按键,则self.moving_up会变为True,下同
self.bottom-=self.ai_settings.ship2_speed_factor
if self.moving_down and self.rect.bottom<=self.screen_rect.bottom-self.ship.rect.height:
self.bottom+=self.ai_settings.ship2_speed_factor
#根据bottom更新rect
self.rect.bottom=self.bottom
def blitme(self):
"""在指定位置绘制ship2"""
self.screen.blit(self.image,self.rect) #在这里前面把screen与self关联起来的作用就体现出来了
#如果这里想写成screen.blit(...),那么必须再
#传递一个参数screen,像这样:def blitme(self,screen)
def center_ship2(self):
"""让飞船2居中"""
self.bottom=self.screen_rect.bottom-self.ship.rect.height
既然ship2位于屏幕左端,那么它发射的子弹bullet2当然不是向上而是向右的了。
#coding=gbk
import pygame
from pygame.sprite import Sprite
class Bullet2(Sprite):
"""一个对飞船2发射的子弹进行管理的类"""
def __init__(self,ai_settings,screen,ship2):
"""在飞船2所处的位置创建一个子弹对象"""
super().__init__()
self.screen=screen
#在(0,0)处创建一个表示子弹的矩形,再设置正确的位置
self.rect=pygame.Rect(0,0,ai_settings.bullet2_width,
ai_settings.bullet2_height)
self.rect.centery=ship2.rect.centery #这里centery不是一个单词,而是表示对象中心坐标(center)中的纵坐标(y)
self.rect.right=ship2.rect.right
#储存用小数表示的子弹位置
self.x=float(self.rect.x)
self.color=ai_settings.bullet2_color
self.speed_factor=ai_settings.bullet2_speed_factor
def update(self):
"""向右移动子弹"""
#更新表示子弹位置的小数值
self.x+=self.speed_factor
#更新表示子弹的rect的位置
self.rect.x=self.x
def draw_bullet2(self):
"""在屏幕上绘制子弹"""
# pygame.draw.rect(self.screen,self.color,self.rect)
self.screen.fill(self.color,self.rect)
接下来是这本书里面完全没有介绍的ball模组
import pygame
from pygame.sprite import Sprite
from random import randint #球的初始横坐标是随机的,需要借助randint
class Ball(Sprite):
"""表示单个球的类"""
def __init__(self,ai_settings,screen):
"""初始化球并设置其初始位置"""
super().__init__()
self.screen=screen
self.ai_settings=ai_settings
#加载球图像并获取其外接矩形
self.image=pygame.image.load('images/ball.bmp')
self.rect=self.image.get_rect()
self.screen_rect=screen.get_rect()
#将球放在屏幕顶部随机位置
self.rect.x=randint(self.screen_rect.x,self.ai_settings.screen_width-self.rect.width+1)
self.rect.y=self.screen_rect.top
#在球的位置属性中储存小数值
self.x=float(self.rect.x)
self.y=float(self.rect.y)
def blitme(self):
"""在指定位置绘制球"""
self.screen.blit(self.image,self.rect)
def update(self):
"""向下移动球"""
self.y+=self.ai_settings.ball_speed_factor
self.rect.y=self.y
就讲到这吧,还有问题你就看那本书,也可以在评论区留言,我会尽力解答。