pygame实现打飞机小游戏
Posted HUTEROX
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了pygame实现打飞机小游戏相关的知识,希望对你有一定的参考价值。
效果预览
最近上实训课,写了这么一个简单的小玩意。运行效果如下:(这个是有音效的,不过这个展示不了因为这里只能上传GIF)
项目结构
游戏对屏幕的适配
由于我使用的是笔记本所以对于屏幕来说是进行了缩放的,例如,我的笔记本缩放了125%
但是问题在于我们的pygame和其他的一些库例如selenium其实是按照100%显示的像素来算的。所以这个时候我们需要进行一个换算。
这个也好算: 当前显示像素比 = 100%显示像素比 X 缩放比
我们只需要换算一下就好了。这里我定义了一个类,来实现我们的需求,自动检测我们的电脑的屏幕缩放比,之后换算。
from win32 import win32api, win32gui, win32print
from win32.lib import win32con
from win32.win32api import GetSystemMetrics
class ChangeRealSize(object):
'''
该类主要对屏幕进行像素适配,按照缩放比对像素进行换算为100%显示
示例:
RealSize = ChangeRealSize()
x=RealSize.getreal_xy(500)
此时就可以换算为当前屏幕的像素
'''
def get_real_resolution(self):
"""获取真实的分辨率"""
hDC = win32gui.GetDC(0)
w = win32print.GetDeviceCaps(hDC, win32con.DESKTOPHORZRES)
h = win32print.GetDeviceCaps(hDC, win32con.DESKTOPVERTRES)
return w, h
def get_screen_size(self):
"""获取缩放后的分辨率"""
w = GetSystemMetrics (0)
h = GetSystemMetrics (1)
return w, h
def getreal_xy(self,x):
'''返回按照100%来算的真实的像素值'''
real_resolution = self.get_real_resolution()
screen_size = self.get_screen_size()
screen_scale_rate = round(real_resolution[0] / screen_size[0], 2)
try:
x = x/screen_scale_rate
except:
#对笔记本进行适配,一般而言在100%比的机器上x不会出错
x=1.25
return int(x)
游戏屏幕的绘制与飞机创建
屏幕绘制直接使用pygame.display.set_mode()的bitl()绘制方法,进行绘制。当然这里的背景是会动的。所以使用到了一个精灵的派生类。
import pygame,random
from ChangeRealSize import ChangeRealSize
GetReal = ChangeRealSize()
class GameSprite(pygame.sprite.Sprite):
def __init__(self,image_path,speed=1):
super().__init__()
self.image = pygame.image.load(image_path)
self.rect = self.image.get_rect()
self.speed = speed
def update(self):
self.rect.y+=self.speed
class Background(GameSprite):
def __init__(self, image_path="./Plane_Img/background1.png",flag=False):
super().__init__(image_path)
if flag:
self.rect.y = -self.rect.height
def update(self):
self.rect.y+=1
if self.rect.y >= self.rect.height:
self.rect.y = -self.rect.height
实现的具体方法如下:
飞机类的实现
这个我是自己定义的所以的话,没有办法直接使用那个自带的碰撞检测,我还定义了一个碰撞检测方法。
飞机的移动
这个和游戏类的事件检测配合。
具体思路是用pygame.event.get()进行事件检测。之后检测到按下某一个按键,例如向前移动是,就会设置向前移动的信号,那么这个时候飞机就会一直往前走。当松开后,那么设置信号为假,那么飞机就会停下来。由于飞机会一直在循环里面检测有没有按下那个向前,所以当你长按往前时,飞机会一直往前,直到你松开。
子弹与敌机类
这个子弹和敌机都是精灵派生类的子类。所以的话就一起说一下。
重点要说的时子弹类的碰撞检测,和敌机的碰撞检测。这里主要说一下子弹类,因为这个和敌机类似。只是有些细节不一样。
class Bullet(GameSprite):
def __init__(self,P_rect,is_hero=False,bullet_image = "./Plane_Img/bullet-3.gif",hero_rect=None):
self.hero_rect = hero_rect
self.bullet_image = bullet_image
self.speed = 4
self.is_hero = is_hero
self.P_rect = P_rect
self.screen_height = GetReal.getreal_xy(800)
self.screen_width = GetReal.getreal_xy(500)
self.actarct_plan = False
self.actract_hero=[]
super().__init__(self.bullet_image,self.speed)
self.rect.x = self.P_rect.x+((self.P_rect.width-self.rect.width)/2)
self.rect.y = self.P_rect.y
def enemy_bullet(self):
#可以在这里计算飞机被击中了多少次
#被击中减少5点
if not self.is_hero:
bullet_x = self.rect.x + int(self.rect.width / 2)
bullet_y = self.rect.y + int(self.rect.height / 2)
hero_plane_x = self.hero_rect.x + int(self.hero_rect.width / 2)
hero_plane_y = self.hero_rect.y + int(self.hero_rect.height / 2)
subtract_y = abs(int(bullet_y - hero_plane_y))
subtract_x = abs(int(bullet_x - hero_plane_x))
if subtract_y <= int((self.rect.height + self.hero_rect.height) / 2) and \\
subtract_x <= int((self.rect.width + self.hero_rect.height) / 2):
self.actract_hero.append(1)
return True
def update(self):
if self.enemy_bullet():
#直接在这里计算数字一次减少5
global HERO_PLANE_HP
HERO_PLANE_HP-=5
# print(HERO_PLANE_HP)
self.kill()
if self.is_hero:
self.rect.y-=self.speed
else:
super().update()
if self.rect.bottom >=self.screen_height-3 :
self.kill()
子弹的话分两种,一个是飞机子弹,一个是敌机子弹,敌机的自带检测碰撞。一方面是方便分数统计(敌机击中飞机几次)了另一方面也是因为飞机是自定义的没有办法用pygame的事件检测(自带的)
敌机的爆炸
这个其实又和飞机的爆炸类似。
主要是检测有没有撞到飞机,之后通过切换图片就好了。当然这个时候我是开了线程的。不然会很快闪过去,换了和没换一样你看不到效果。
切换图片的函数,切换完毕,删除这个敌机类减少内存消耗
游戏小彩蛋
这个其实就是一个自己的后面
具体作用就是修改自己的飞机的HP值为99万
当然这个小游戏还没有做完,无敌也有点无聊,玩久了的话。
def CheatEngine():
global HERO_PLANE_HP
print("HP is %d" % HERO_PLANE_HP)
while 1:
key = input("maybe you can input something:")
if key=='break':
print("enjoy your game please Bye~")
return
elif key=="Huterox is best":
HERO_PLANE_HP=999999
print("Now your HP is %d!!!"%HERO_PLANE_HP)
return
完整代码
import pygame,random
from ChangeRealSize import ChangeRealSize
GetReal = ChangeRealSize()
class GameSprite(pygame.sprite.Sprite):
def __init__(self,image_path,speed=1):
super().__init__()
self.image = pygame.image.load(image_path)
self.rect = self.image.get_rect()
self.speed = speed
def update(self):
self.rect.y+=self.speed
class Background(GameSprite):
def __init__(self, image_path="./Plane_Img/background1.png",flag=False):
super().__init__(image_path)
if flag:
self.rect.y = -self.rect.height
def update(self):
self.rect.y+=1
if self.rect.y >= self.rect.height:
self.rect.y = -self.rect.height
········································································································
import pygame,random,time,threading,os
from ChangeRealSize import ChangeRealSize
from GameSprite import GameSprite,Background
GetReal = ChangeRealSize()
GREATE_ENMEY_EVENT = pygame.USEREVENT#只能出现一次
HERO_FIRE_BULLTE = pygame.USEREVENT+1 #第二个事件
HERO_PLANE_HP = 300
def CheatEngine():
global HERO_PLANE_HP
print("HP is %d" % HERO_PLANE_HP)
while 1:
key = input("maybe you can input something:")
if key=='break':
print("enjoy your game please Bye~")
return
elif key=="Huterox is best":
HERO_PLANE_HP=999999
print("Now your HP is %d!!!"%HERO_PLANE_HP)
return
class Base():
'''飞机的初始化样式,位置'''
def __init__(self,x,y,width,height,path):
self.x = GetReal.getreal_xy(x)
self.y = GetReal.getreal_xy(y)
self.width = GetReal.getreal_xy(width)
self.height = GetReal.getreal_xy(height)
self.image = pygame.image.load(path)
self.rect = pygame.Rect(self.x,self.y,self.height,self.width)
class Planer(Base):
def __init__(self,x,y,width,height,path,screen):
Base.__init__(self,x,y,width,height,path)
self.Killed = False
self.screen = screen
self.GoStrange=False
self.TurnLeft = False
self.TurnRight =False
self.GoBack = False
self.Fire_flag = False
self.Boom_path="./Plane_Img/hero_blowup_n{}.png"
self.bullet_group=pygame.sprite.Group()
pygame.time.set_timer(HERO_FIRE_BULLTE,250)
self.Plane_need_Killed=[]#由于会重复执行只能去用列表的数量来判断
def Move(self):
if self.Killed:
self.rect=pygame.Rect(0,0,0,0)
return
if self.GoStrange:
if self.rect.bottom <= 300:
self.show()
return
else:
self.rect.y -= 3
self.show()
if self.TurnLeft:
if self.rect.x<=3:
self.show()
return
else:
self.rect.x-=2
self.show()
if self.TurnRight:
if self.rect.x>=Game.screen_x-self.rect.width-3:
self.show()
return
else:
self.rect.x+=2
self.show()
if self.GoBack:
if self.rect.bottom>=Game.screen_y-30:
self.show()
return
else:
self.rect.y +=2
self.show()
self.show()
def Get_bullet(self):
#子弹加载
if self.Killed:
return
if self.Fire_flag:
MusicPlay().PlayPlanSound()
bullet = Bullet(self.rect,True)
self.bullet_group.add(bullet)
def Fire(self):
#子弹发射
if self.Killed:
return
self.bullet_group.update()
self.bullet_group.draw(self.screen)
def Goal(self):
pass
def show(self):
if self.Killed:
return
Game.screen.blit(self.image,self.rect)
# pygame.display.update()
def __plane_Boom(self):
if self.Killed:
return
for i in range(1, 5):
self.image_path = self.Boom_path.format(i)
self.image = pygame.image.load(self.image_path)
time.sleep(0.3)
time.sleep(1)
self.Killed =True
def Plane_Live(self):
if self.Killed:
return
global HERO_PLANE_HP
if HERO_PLANE_HP<=0:
HERO_PLANE_HP =0
self.Plane_need_Killed.append(1)
if len(self.Plane_need_Killed)==1:
t = threading.Thread(target=self.__plane_Boom)
t.start()
#音乐播放类
class MusicPlay():
def __init__(self):
self.bgmusic = pygame.mixer.music
def PlayBg(self):
self.bgmusic.load("./music/PlaneWarsBackgroundMusic.mp3")
self.bgmusic.set_volume(0.3)
self.bgmusic.play(-1)
def StarBg(self):
self.bgmusic.stop()
def PlayPlanSound(self):
self.PlayPlaneMusic = pygame.mixer.Sound("./music/hero_fire.wav")
self.PlayPlaneMusic.set_volume(0.2)
self.PlayPlaneMusic.play()
def StopPlayPlanSound(self):
pass
#子弹类
class Bullet(GameSprite):
def __init__(self,P_rect,is_hero=False,bullet_image = "./Plane_Img/bullet-3.gif",hero_rect=None):
self.hero_rect = hero_rect
self.bullet_image = bullet_image
self.speed = 4
self.is_hero = is_hero
self.P_rect = P_rect
self.screen_height = GetReal.getreal_xy(800)
self.screen_width = GetReal.getreal_xy(500)
self.actarct_plan = False
self.actract_hero=[]
super().__init__(self.bullet_image,self.speed)
self.rect.x = self.P_rect.x+((self.P_rect.width-self.rect.width)/2)
self.rect.y = self.P_rect.y
def enemy_bullet(self):
#可以在这里计算飞机被击中了多少次
#被击中减少5点
if not self.is_hero:
bullet_x = self.rect.x + int(self.rect.width / 2)
bullet_y = self.rect.y + int(self.rect.height / 2)
hero_plane_x = self.hero_rect.x + int(self.hero_rect.width / 2)
hero_plane_y = self.hero_rect.y + int(self.hero_rect.height / 2)
subtract_y = abs(int(bullet_y - hero_plane_y))
subtract_x = abs(int(bullet_x - hero_plane_x))
if subtract_y <= int(以上是关于pygame实现打飞机小游戏的主要内容,如果未能解决你的问题,请参考以下文章