基本上是按照课本给的路线和代码。
一:安装pip:点击打开链接 点击里面的getpip.py。则出来get-pip.py的代码在浏览器里面,复制代码到编辑器中运行则pip安装完成。
二:安装pygame:点击打开链接 找到pygame一系列 我的电脑是win10 64位 则下载 pygame-1.9.3-cp36-cp36m-win_amd64.whl 下载到项目文件夹中 运行cmd 用python pip运行
输入:python -m pip install --user pygame-1.9.3-cp36-cp36m-win_amd64.whl
不出意外安装完成,出了意外 可能是pygame的版本不对,或者pip安装失败。
三:开始游戏项目
1:创建空屏幕
import sys #用以退出程序
import pygame #import库
def run_game():
pygame.init() #初始化
screen = pygame.display.set_mode((1000,800)) #返回一个屏幕 此时出现一个窗口
pygame.display.set_caption("ship") #设置窗口的标题
while True:#死循环
for event in pygame.event.get():#检测用户的键盘鼠标等输入
if event.type == pygame.QUIT:#此处仅检测是否退出
sys.exit()#退出
pygame.display.flip()#绘制一个新屏幕 并擦去旧屏幕 以形成平滑移动
run_game()
利用pygame 终于能够不再黑框框里面运行程序了。
当初写个贪吃蛇写出来的效果巨差。。。
简单的解释 pygame.display.set_mode((int,int))返回一个屏幕 screen就是这个屏幕 ,两个参数是屏幕的长宽
pygame.display.filp()是刷新屏幕
2:设置背景颜色
bg_color = (230,230,230)
screen.fill(bg_color)
screen是屏幕,fill是填充颜色。也就是改变背景色。
此处需要注意,该条代码应该在显示其它元素的前面,否则其他元素会被覆盖。
在pygame中,颜色是用RGB(red,green,blue)指定的。详细可参考百度百科:点击打开链接
3: 加载飞船
#import pygame
class Ship():
def __init__(self,screen):
self.screen = screen
self.image = pygame.image.load('images/ship.bmp')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
self.rect.x = self.screen_rect.centerx
self.rect.y = self.screen_rect.bottom
def blitme(self):
self.screen.blit(self.image,self.rect)
windows环境下pygame默认加载bmp,想要加载别的格式类型需要一定的操作,暂时还没学会。
不过可以将jpg,png等图片格式转化为bmp。
简单的解释: pygame.image.load(路径) 是加载一个bmp图片。
self.image.get_rect() 返回这个bmp图片的矩形
self.rect.x/y是该矩形的x,y轴坐标。注意,pygame中左上角为(0,0) 右下角为(∞,∞)
screen_rect.centerx 是screen这个矩形(屏幕就是个矩形)的中间的坐标
screen_rect.bottom 类似,是底部的坐标
这样ship这个飞船的图片就定义好了,下面在screen中绘制出来即可
函数blitme目的是绘制该图片,
screen.blit(self.image,self.rect) 第一个参数是 之前加载的bmp图片,第二个参数是之前设置好的x,y轴。该函数会在指定位置绘制指定图片。
ship = Ship(screen)
ship.blitme()
在主函数中调用相应函数就可以绘制出飞船图片。
4:重构函数
重构函数的具体内容不多赘述,因为不涉及到python或者pygame内容,而是全部编程语言共同的点。在此只是提示要进行重构函数~~~
5:移动飞船
移动飞船的过程就是通过按键,不断移动图片,并重新绘制屏幕的过程。
首先按一下→,向右移动一下:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWM:
if event.key == pygame.K_RIGHT:
ship.rect.x +=1
在之前的检测按键和鼠标模块中,添加部分代码即可
简单的解释: event.type是检测到的按键的类型,如果检测到是QUIT就退出,
当然最经典的是pygame.KEYDOWN和pygame.KEYUP。 这里检测的是按下 而不是松开 。
如果检测到按下就比较按下的是什么按键 也就是event.key()的值 pygame.K_RIGHT 就是方向右键 类似的有K_LEFT K_SPACE K_UP K_DOWN。
如果检测到按下方向右键 那么飞船的矩形的x轴坐标+1 ,那么在重新绘制屏幕的时候就可以看到飞船向右移动了一格。在感官效果上就实现了移动飞船
然后要实现不断移动飞船,也就是按下方向右键之后不松开,飞船能不断移动。有点难懂,换句话说就简单了,按下右键就不断移动,松开右键就停止移动。
为了实现这个目标,需要添加一个flag,就是一个标志,设为moving_right 如果为真 就一直向右移动,如果为假就不移动
如果按下右键该标志就为真,如果松开右键该标志就为假。
到了这里思路就很清晰了。
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWM:
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.type == pygame.KEYUP:#key up
if event.key == pygame.K_RIGHT:
ship.moving_right = False
在ship类中新增函数
def update(self):
if self.moving_right
self.rect.x += 1
并在更新屏幕的时候调用该函数。
ship.update()
screen.fill(ai_settings.bg_color)
pygame.display.flip()
到此为止,飞船就能一直向右移动,但是在实际操作中还有一个问题,飞船会一直飞一直飞,甚至会飞出屏幕。
这个问题加一行代码即可
def update(self):
if self.moving_right and self.rect.right < self.screen_rect.right:
self.rect.x += 1
self.rect.right是矩形的右边界,代码作用很显然。出界的时候不准出界。
到此为止,飞船就能完成向右移动的全部程序。其它三个方向完全同理。
6:控制飞船的移动速度
本来控制飞船的移动速度只需要更改每次调用函数的时候x坐标的幅度 从1变成2 ,2变成3,设置为一个变量,并控制即可,但是这样子不能够很细致的改变的飞船的移动,也就是2太快,1太慢,需要1.5 然而,pygame里面矩形的坐标只能够储存整数。
为了解决这个问题,可以引入中间变量
在ship类中新增变量设置为浮点数格式
self.center_x=float(self.rect.centerx)
self.center_y=float(self.rect.centerx)
self.ship_speed_factor = 0.5
在更改x坐标的时候
if self.moving_right and self.rect.right < self.screen_rect.right:
self.center_x += self.ship_speed_factor
self.rect.x = self.center_x
到这里,飞船能上下左右动,也能细腻的调整速度,那么飞船的内容就差不多了。
7.发射子弹
子弹的定义是什么呢?为了简单起见,应该是一个矩形,然后按空格(开火)会从飞船中间顶部出现,然后会一直向上移动,会有很多个子弹,到达顶部后删除该子弹(否则会造成使用内存boom),为了调整难度,还应该限制子弹数量。
也就是有那么几个要点:矩形图像/按空格出现/出现在飞船中间顶部/出现之后一直向上移动/移动到顶部被删除/子弹的数量应该有限制/
和飞船是有很多地方相似的
好的,一起来~
import pygame
from pygame.sprite import Sprite
class Bullet(Sprite):#通过使用精灵,可以对对象进行编组,进而同时操作编组中的所有元素。
def __init__(self , screen , ship):
super().__init__()#超类的构造函数
self.screen = screen
self.width = 3
self.height = 10
self.rect = pygame.Rect(0,0,self.width,self.height)#定义左边为屏幕的左上角出现一个长宽固定的矩形
self.rect.x = ship.rect.x + 29#
self.rect.y = ship.rect.y - 3#更改坐标位置,让它出现在飞船那边
self.y = float(self.rect.y)#为了能够细腻的移动子弹,采用浮点数,跟飞船同理
self.color = 6,60,160 #设置颜色
self.speed_factor = 1 #设置速度
def update(self):
self.y -= self.speed_factor
self.rect.y = self.y #子弹向上移动 跟飞船类似
def draw_bullet(self):
pygame.draw.rect(self.screen,self.color,self.rect) #三个参数,屏幕,颜色,生成的矩形 便在指定位置绘制出一个矩形
这是buttets类的内容,剩下的要在主函数和功能函数里面进行调度。
from pygame.sprite import Group #需额外import
bullets = Group()#在主函数死循环外创造一个编组
在更新屏幕内容时记得绘制子弹
for i in bullets:
i.update()
i.draw_bullet()
同时记得让子弹向上运动
然后再检测键盘和鼠标输入的时候,类似于按方向右键,按下空格键即生成一个新的子弹在编组中,如果子弹数量太多,则不生成,便可以限制子弹的数量
elif event.key == pygame.K_SPACE:
if len(bullets) < ship.bullets_allowed:
new_bullet = Bullet(screen , ship)
bullets.add(new_bullet)
再随便写个函数删除掉子弹的y轴<0的子弹并调用
def remove_bullet(bullets):
for i in bullets.copy():
if i.rect.bottom <= 0:
bullets.remove(i)
到这里,整个事情就做完了,核心思路是完善的,简单的,但是代码不完善,不过不要紧,所有代码如下:
Ship 类
import pygame
class Ship():
def __init__(self,screen):
self.screen = screen
self.image = pygame.image.load('images/ship.bmp')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
self.rect.x = self.screen_rect.centerx
self.rect.y = self.screen_rect.bottom
self.moving_right = False
self.moving_left = False
self.moving_up = False
self.moving_down = False
self.ship_speed_factor = 0.5
self.bullets_allowed = 3
self.center_x=float(self.rect.centerx)
self.center_y=float(self.rect.centerx)
def blitme(self):
self.screen.blit(self.image,self.rect)
def update(self):
if self.moving_right and self.rect.right < self.screen_rect.right:
self.center_x += self.ship_speed_factor
if self.moving_left and self.rect.left > self.screen_rect.left:
self.center_x -= self.ship_speed_factor
self.rect.x = self.center_x
if self.moving_up and self.rect.top > self.screen_rect.top:
self.center_y -= self.ship_speed_factor
if self.moving_down and self.rect.bottom < self.screen_rect.bottom:
self.center_y += self.ship_speed_factor
self.rect.y = self.center_y
setting类 #没什么用,课本硬是有
class Settings():
"""A class to store all settings for Alien Invasion."""
def __init__(self):
"""Initialize the game's settings."""
# Screen settings.
self.screen_width = 1000
self.screen_height = 650
self.bg_color = (230, 230, 230)
Bullet类
import pygame
from pygame.sprite import Sprite
class Bullet(Sprite):
def __init__(self , screen , ship):
super().__init__()
self.screen = screen
self.width = 3
self.height = 10
self.rect = pygame.Rect(0,0,self.width,self.height)
self.rect.x = ship.rect.x + 29
self.rect.y = ship.rect.y - 3
self.y = float(self.rect.y)
self.color = 6,60,160
self.speed_factor = 1
def update(self):
self.y -= self.speed_factor
self.rect.y = self.y
def draw_bullet(self):
pygame.draw.rect(self.screen,self.color,self.rect)
主代码
import sys
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf
from pygame.sprite import Group
def run_game():
pygame.init()
ai_settings = Settings()
screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
pygame.display.set_caption("Alien Invasion")
ship = Ship(screen)
bullets = Group()
while True:
gf.check_events(ship , screen , bullets)
gf.remove_bullet(bullets)
gf.update_screen(ai_settings , screen , ship , bullets)
run_game()
功能函数类
import pygame
import sys
from bullet import Bullet
def check_events(ship , screen , bullets):
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:#key down
if event.key == pygame.K_LEFT:
ship.moving_left = True
elif event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_UP:
ship.moving_up = True
elif event.key == pygame.K_DOWN:
ship.moving_down = True
elif event.key == pygame.K_SPACE:
if len(bullets) < ship.bullets_allowed:
new_bullet = Bullet(screen , ship)
bullets.add(new_bullet)
elif event.type == pygame.KEYUP:#key up
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False
elif event.key == pygame.K_UP:
ship.moving_up = False
elif event.key == pygame.K_DOWN:
ship.moving_down = False
def update_screen(ai_settings , screen , ship , bullets):
ship.update()
screen.fill(ai_settings.bg_color)
for i in bullets:
i.update()
i.draw_bullet()
ship.blitme()
pygame.display.flip()
def remove_bullet(bullets):
for i in bullets.copy():
if i.rect.bottom <= 0:
bullets.remove(i)