跟着老杨学python
微信打飞机这个简单的小游戏曾经风靡全国,霸占朋友圈,既然python如此强大,今天老杨就用python来搞定它。
快速弄懂一件事物的核心就在乎知道它的本质和规律。我们制作微信打飞机,那我们就先了解一下游戏的原理到底是什么。
其实,游戏的原理很简单,首先要有一个窗口用来运行你的游戏,然后准备一个素材资源,以微信打飞机为例,就是把背景图,飞机图等图片资源,粘贴到窗口上,你可以把它理解成创建一个毛坯房(这就是你的游戏的窗口),再准备一些墙纸或装饰品,把它们填充到房子里面。既然把物品放到某个地方,我们需要知道物体的位置,而如何确定一个平面的目标,就是坐标了,但编程中和数学不太一样的一点是,我们起点是在左上角的。到这里我们就知道,其实游戏中角色的运动就是图片资源坐标的变化。那运行中会有各种操作,这就是事件,比如我们按下键盘的某个键或按下鼠标,都会捕获到一个事件,根据这些事件,我们执行对应的代码即是执行对应操作,而我们游戏的连贯运行,是动态的,其实就是将不同的页面显示,当刷新的足够快,间隔足够短,就可以达到连贯运行的目的,其实这是不停地将不同的页面显示出来而已(可以参考手翻书的原理)。而代码是从上往下,顺序执行,执行完毕即退出,所以我们的游戏部分代码需要不停的循环进行,只到一个退出事件,退出循环,退出游戏。
好,懂了原理之后,我们就用代码搞定吧
这里我们需要先安装一个第三方库,pygame
,这个库主要用于2D游戏的开发
pip install pygame
先实现第一部分:
#!/usr/bin/python3
# @Time : 2019/7/9 15:22
# @Author : 老杨
# @FileName : start1.py
# @Software : PyCharm
"""
游戏的原理就是视觉欺骗
1.首先要有个窗口,显示出界面
2,然后需要资源(图片)充当背景,角色等,再让他们显示
关于角色会动:
角色的移动就是图片的移动,移动的本质是什么呢?就是坐标的变化
关于运行游戏:
那我们怎么运行游戏呢,当我们用手机去触摸,或者说在电脑的键盘上按下某个键盘,其实都是一个事件,我们定义什么事件做什么事情,比方说按下键盘上的左箭头就控制飞机的图片左滑等等
游戏退出和不停地运行:
代码是执行一遍就完了,那我们的游戏不能一打开就没了把,所以我们需要一个死循环,(不停地去执行代码),然后定义一个事件来退出
关于游戏是连贯的:(手翻书)
为什么游戏会动呢?原理也很简单,只要动的足够快,中间的间隔短,在我们人眼看来这就是连贯,就是在动的,在我们人眼中,只要间隔低于1/60秒,我们就感觉不出来。所以说只要我们画几幅图,只要他们的出现的间隔足够短,那我们看来这就是连贯的,运动的
#####在实际开发中,不管图片时什么样子,实际是哪个一定是个矩形。只是部分透明而已。不管在任何操作系统,图片一定是个矩形
总结:
开发一个游戏,首先得先创建一个窗口,然后准备资源,再填充上。就像房子,首先你得有个毛坯房,然后再刷油漆,或者贴墙纸。
然后游戏中角色的运动其实就是图片资源坐标的变化,不停的去刷新页面,(把多个不同的图片以很短的间隔出现旧图片覆盖新图片)就是我们看到的角色在运动)
"""
# 第一步:导入pygame
# 主要用于2D游戏的开发
import pygame
# 初始化pygame
pygame.init()
# 创建一个窗口 毛坯房
#X,Y轴,对应宽和高
screen = pygame.display.set_mode((450, 600))
# 设置标题
pygame.display.set_caption('飞机大战')
# 准备资源背景图 毛坯房有了,现在就要贴墙纸了,贴墙纸首先要准备好选择好墙纸
# convert_alpha()的意思:修改图像(Surface 对象)的像素格式,包含 alpha 通道
# 可以理解为保留了透明的部分,这样图片才可以是不规则的
background = pygame.image.load('./resources/background.png').convert_alpha()
#设置游戏是否结束
gameOver = True
# 设置字体 使用自定义字体 传None即使用系统字体,
# 如果是使用中文的话,使用 Unicode 来表示文字内容,即 u'中文文字'
# font = pygame.font.Font(None, 32)
# 使用指定字体
font = pygame.font.Font("./ziti/miaowu.ttf",32)
# 分数
score = 0
while True:
# 设定需要显示的背景图 blit填充的意思 第一个参数为要贴的图片,第二个为开始的坐标
screen.blit(background,(0, 0))
# 获取事件,比如按键等
for event in pygame.event.get():
# 判断是否点击了退出按钮
if event.type == pygame.QUIT:
# 退出pygame
pygame.quit()
# 退出程序
exit()
# 如果游戏结束,且鼠标松开,就重新开始
if gameOver and event.type == pygame.MOUSEBUTTONUP:
# 积分重新计算
score = 0
# 设置游戏开始
gameOver = False
# 如果游戏没有结束
if not gameOver:
pass
else:
# 准备文字
# # 参数分别为 显示内容、是否消除锯齿、字体颜色、背景颜色
# 第二个参数antialias:字体的边缘是否平滑,true表示平滑,false表示带有毛边。
text = font.render("Socre:%d"%score,True, (0, 0, 0))
# 填充资源
screen.blit(text, (150, 300))
text = font.render("点击鼠标开始游戏",True, (0, 0, 0))
screen.blit(text, (100, 330))
#更新(刷新)需要显示的内容
pygame.display.update()
接下来,我们创建飞机,子弹,和敌机
#!/usr/bin/python3
# @Time : 2019/7/9 15:24
# @Author : 老杨
# @FileName : start2.py
# @Software : PyCharm
# 第一步:导入pygame
# 主要用于2D游戏的开发
import pygame
import random
#************** 创建一个飞机类 **************
class Plane():
# 因为游戏重新开始,飞机又要回到原点,所以抽离出来
def restart(self):
self.x = 200
self.y = 450
# 先写初始化方法,创建对象时会自动调用
def __init__(self):
# 先自动调用方法,设置飞机的起始坐标
self.restart()
# 准备飞机的图片资源
self.image = pygame.image.load('./resources/hero1.png').convert_alpha()
# 飞机的移动方法
def move(self):
# 我们让飞机随着鼠标的移动而移动
# 得到鼠标的坐标,返回鼠标的x,y的坐标
x, y = pygame.mouse.get_pos()
# 因为粘贴都是左上角开始粘贴的,分别除以2等于水平和垂直居中
x -= self.image.get_width()/2
y -= self.image.get_height()/2
# 重新设置坐标
self.x = x
self.y = y
#************** 创建一个飞机类 **************
##*******************子弹类***********************##
class Bullet:
def __init__(self):
self.image = pygame.image.load('./resources/bullet.png').convert_alpha()
##*******************子弹类***********************##
##*******************敌机类***********************##
class Enemy():
# 因为游戏重新开始,飞机又要回到原点,所以抽离出来
# 因为敌机都是从下面落下来的,却不确定所以利用随机数指定X轴坐标
def start(self):
self.x = random.randint(0, 400)
self.y = 0
def __init__(self):
self.start()
self.image = pygame.image.load('./resources/enemy0.png').convert_alpha()
##*******************敌机类***********************##
# 初始化pygame
pygame.init()
# 创建一个窗口 毛坯房
#X,Y轴,对应宽和高
screen = pygame.display.set_mode((450, 600))
# 设置标题
pygame.display.set_caption('飞机大战')
# 准备资源背景图 毛坯房有了,现在就要贴墙纸了,贴墙纸首先要准备好选择好墙纸
# convert_alpha()的意思:修改图像(Surface 对象)的像素格式,包含 alpha 通道
# 可以理解为保留了透明的部分,这样图片才可以是不规则的
background = pygame.image.load('./resources/background.png').convert_alpha()
#设置游戏是否结束
gameOver = True
# 设置字体 使用自定义字体 传None即使用系统字体,
# 如果是使用中文的话,使用 Unicode 来表示文字内容,即 u'中文文字'
# font = pygame.font.Font(None, 32)
# 使用指定字体
font = pygame.font.Font("./ziti/miaowu.ttf",32)
# 分数
score = 0
# 第二部分*********
# 创建飞机类
plane = Plane()
# 创建子弹类
bullet = Bullet()
# 创建多架敌机类
# enemy = Enemy()
enemys = []
for i in range(5):
enemys.append(Enemy())
while True:
# 设定需要显示的背景图 blit填充的意思 第一个参数为要贴的图片,第二个为开始的坐标
screen.blit(background,(0, 0))
# 获取事件,比如按键等
for event in pygame.event.get():
# 判断是否点击了退出按钮
if event.type == pygame.QUIT:
# 退出pygame
pygame.quit()
# 退出程序
exit()
# 如果游戏结束,且鼠标松开,就重新开始
if gameOver and event.type == pygame.MOUSEBUTTONUP:
# 积分重新计算
score = 0
# 设置游戏开始
gameOver = False
# 如果游戏没有结束
if not gameOver:
# # 让飞机移动
plane.move()
# 将飞机的图片填充 ,参数为飞机的图片资源,粘贴的坐标
screen.blit(plane.image, (plane.x, plane.y))
# 子弹肯定是出现飞机的前面的,那子弹的粘贴坐标就以飞机的坐标为基础来表达
x = plane.x + plane.image.get_width()/2-bullet.image.get_width()/2
y = plane.y - 100
# 准备子弹的图片
screen.blit(bullet.image, (x, y))
# 多架敌机都需要在不同的地点显示
for enemy in enemys:
screen.blit(enemy.image, (enemy.x, enemy.y))
else:
# 准备文字
# # 参数分别为 显示内容、是否消除锯齿、字体颜色、背景颜色
# 第二个参数antialias:字体的边缘是否平滑,true表示平滑,false表示带有毛边。
text = font.render("Socre:%d"%score,True, (0, 0, 0))
# 填充资源
screen.blit(text, (150, 300))
text = font.render("点击鼠标开始游戏",True, (0, 0, 0))
screen.blit(text, (100, 330))
#更新(刷新)需要显示的内容
pygame.display.update()
最后,完成让子弹移动和击中敌机的功能,大功告成
#!/usr/bin/python3
# @Time : 2019/7/9 15:52
# @Author : 老杨
# @FileName : start3.py
# @Software : PyCharm
# 第一步:导入pygame
# 主要用于2D游戏的开发
import pygame
import random
import time
#************** 创建一个飞机类 **************
class Plane():
# 因为游戏重新开始,飞机又要回到原点,所以抽离出来
def restart(self):
self.x = 200
self.y = 450
# 先写初始化方法,创建对象时会自动调用
def __init__(self):
# 先自动调用方法,设置飞机的起始坐标
self.restart()
# 准备飞机的图片资源
self.image = pygame.image.load('./resources/hero1.png').convert_alpha()
# 飞机的移动方法
def move(self):
# 我们让飞机随着鼠标的移动而移动
# 得到鼠标的坐标,返回鼠标的x,y的坐标
x, y = pygame.mouse.get_pos()
# 因为粘贴都是左上角开始粘贴的,分别除以2等于水平和垂直居中
x -= self.image.get_width()/2
y -= self.image.get_height()/2
# 重新设置坐标
self.x = x
self.y = y
# 炸毁了
def ruin(self):
self.ruin_image = pygame.image.load('./resources/hero_blowup_n1.png').convert_alpha()
screen.blit(self.ruin_image, (self.x, self.y))
pygame.display.update()
#************** 创建一个飞机类 **************
##*******************子弹类***********************##
class Bullet:
def __init__(self):
self.image = pygame.image.load('./resources/bullet.png').convert_alpha()
##*******************子弹类***********************##
##*******************敌机类***********************##
class Enemy():
# 因为游戏重新开始,飞机又要回到原点,所以抽离出来
# 因为敌机都是从下面落下来的,却不确定所以利用随机数指定X轴坐标
def start(self):
self.x = random.randint(0, 400)
self.y = 0
def __init__(self):
self.start()
self.image = pygame.image.load('./resources/enemy0.png').convert_alpha()
# 让敌机运动,运动的本质就是坐标发生变化,在极短的时间内刷新,达到动态的效果
# 让敌机每次运动一点,Y轴的坐标加0.1等于就是像下移动一点
def move(self):
# 判断如果小于高度就继续向下,如果大于高度,则回归起点
if self.y < 600:
self.y += 0.1
if self.y > 600:
self.start()
# # 炸毁了
# def ruin(self):
# self.ruin_image = pygame.image.load('./resources/enemy0_down2.png').convert_alpha()
# screen.blit(self.ruin_image, (self.x, self.y))
# pygame.display.update()
##*******************敌机类***********************##
##*******************碰撞***********************##
def Crash(plane,enemy):
# 表示撞上了
if (plane.x+plane.image.get_width()>enemy.x) and (plane.xenemy.y) and (plane.y=12:
a = 1
# 多架敌机都需要在不同的地点显示
for enemy in enemys:
# 让每一个敌机都运动
enemy.move()
screen.blit(enemy.image, (enemy.x, enemy.y))
# 当任意一个敌机撞上飞机,就游戏结束
if Crash(plane,enemy):
gameOver = True
plane.ruin()
time.sleep(1)
if Shoot(x,y,enemy):
score += 100
# enemy.ruin()
# time.sleep(0.1)
# 准备文字
text = font.render("Socre: %d" % score, 1, (0, 0, 0))
# 填充资源
screen.blit(text, (0, 0))
else:
# 准备文字
# # 参数分别为 显示内容、是否消除锯齿、字体颜色、背景颜色
# 第二个参数antialias:字体的边缘是否平滑,true表示平滑,false表示带有毛边。
text = font.render("Socre:%d"%score,True, (0, 0, 0))
# 填充资源
screen.blit(text, (150, 300))
text = font.render("点击鼠标开始游戏",True, (0, 0, 0))
screen.blit(text, (100, 330))
#更新(刷新)需要显示的内容
pygame.display.update()