欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

如何利用pygame实现打飞机小游戏

程序员文章站 2022-06-23 08:52:21
效果预览最近上实训课,写了这么一个简单的小玩意。运行效果如下:(这个是有音效的,不过这个展示不了因为这里只能上传gif)项目结构游戏对屏幕的适配由于我使用的是笔记本所以对于屏幕来说是进行了缩放的,例如...

效果预览

最近上实训课,写了这么一个简单的小玩意。运行效果如下:(这个是有音效的,不过这个展示不了因为这里只能上传gif)

如何利用pygame实现打飞机小游戏

项目结构

如何利用pygame实现打飞机小游戏

游戏对屏幕的适配

由于我使用的是笔记本所以对于屏幕来说是进行了缩放的,例如,我的笔记本缩放了125%

如何利用pygame实现打飞机小游戏

但是问题在于我们的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实现打飞机小游戏
如何利用pygame实现打飞机小游戏
如何利用pygame实现打飞机小游戏

飞机类的实现

这个我是自己定义的所以的话,没有办法直接使用那个自带的碰撞检测,我还定义了一个碰撞检测方法。

如何利用pygame实现打飞机小游戏

飞机的移动

这个和游戏类的事件检测配合。

具体思路是用pygame.event.get()进行事件检测。之后检测到按下某一个按键,例如向前移动是,就会设置向前移动的信号,那么这个时候飞机就会一直往前走。当松开后,那么设置信号为假,那么飞机就会停下来。由于飞机会一直在循环里面检测有没有按下那个向前,所以当你长按往前时,飞机会一直往前,直到你松开。

如何利用pygame实现打飞机小游戏
如何利用pygame实现打飞机小游戏
如何利用pygame实现打飞机小游戏

子弹与敌机类

这个子弹和敌机都是精灵派生类的子类。所以的话就一起说一下。

重点要说的时子弹类的碰撞检测,和敌机的碰撞检测。这里主要说一下子弹类,因为这个和敌机类似。只是有些细节不一样。

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的事件检测(自带的)

敌机的爆炸

这个其实又和飞机的爆炸类似。

主要是检测有没有撞到飞机,之后通过切换图片就好了。当然这个时候我是开了线程的。不然会很快闪过去,换了和没换一样你看不到效果。

切换图片的函数,切换完毕,删除这个敌机类减少内存消耗

如何利用pygame实现打飞机小游戏
如何利用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((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()

#敌机类
class enemy(gamesprite):
    def __init__(self,hero_plane,screen,image_path="./plane_img/enemy0.png"):
        self.speed = random.randint(1,3)
        self.image_path =image_path
        self.screen = screen
        self.hero_plane = hero_plane
        self.hero_bullet = self.hero_plane.bullet_group

        self.fire_interval = false
        #通过这个和另一个计时线程配合来实现子弹的间断发射

        self.collied_with_plan = []

        super().__init__(self.image_path,self.speed)
        self.screen_height = getreal.getreal_xy(800)
        self.screen_width = getreal.getreal_xy(500)
        self.turn_l_flag = true
        self.boom_path = "./plane_img/enemy0_down{}.png"

        self.rect.y = getreal.getreal_xy(self.rect.top-self.rect.bottom)

        self.rect.x = random.randint(0, self.screen_width - self.rect.width)

        self.bullet_group = pygame.sprite.group()

    def __boom(self):
        #这里还可以对以后飞机击落敌机的数量计数

        #敌机应该检测自己有没有和飞机的子弹相撞
        flag_killed_by_bullet = pygame.sprite.spritecollide(self,self.hero_bullet,true)

        if flag_killed_by_bullet or self.__is_collied_with_plan():

            #被用户撞了hp值减少20
            global  hero_plane_hp
            if len(self.collied_with_plan)==1:
                hero_plane_hp -=20


            t = threading.thread(target=self.boom_ing)
            t.start()


        pass
    def boom_ing(self):


        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.2)
        self.kill()


    def __is_collied_with_plan(self):


        #碰撞检查是否与用户飞机碰撞


        center_enemy_x = self.rect.x +int(self.rect.width/2)
        center_enemy_y = self.rect.y +int(self.rect.height/2)

        center_plane_x = self.hero_plane.rect.x+int(self.hero_plane.rect.width/2)
        center_plane_y = self.hero_plane.rect.y+int(self.hero_plane.rect.height/2)

        subtract_y = abs(int(center_enemy_y-center_plane_y))
        subtract_x = abs(int(center_enemy_x-center_plane_x))

        if subtract_y <= int((self.rect.height+self.hero_plane.rect.height)/2) and\
            subtract_x <= int((self.rect.width+self.hero_plane.rect.height)/2):

            self.collied_with_plan.append(1)

            return true




    def __bullet_building(self):
        if self.rect.y% 50 ==0:

                buttle = bullet(self.rect,bullet_image="./plane_img/bullet-1.gif",hero_rect=self.hero_plane.rect)
                self.bullet_group.add(buttle)





    def __shut(self):
        self.bullet_group.update()
        self.bullet_group.draw(self.screen)


    def update(self):


        super().update()
        #定义敌机的出现

        self.__boom()#监听是否碰撞和子弹被射击

        self.__bullet_building()
        self.__shut()



        if self.rect.top >= self.screen_height + 3:
            #//越界判断
            # self.rect.y = -20
            self.kill()


        if self.turn_l_flag:
            self.rect.x += random.randint(1,2)
            if self.rect.right >= self.screen_width - 3:
                self.turn_l_flag = false
        else:
            self.rect.x -= random.randint(2, 3)
            if self.rect.left <= 3:
                self.turn_l_flag = true

class playgame(object):
    def __init__(self):
        pygame.init()
        self.screen_x, self.screen_y = getreal.getreal_xy(500), getreal.getreal_xy(800)
        self.screen = pygame.display.set_mode((self.screen_x, self.screen_y))
        self.flush_clcok = pygame.time.clock()
        pygame.display.set_caption('英雄无敌!!!')


        self.enemy_group = pygame.sprite.group()

        self.hero_palne = planer(200, 500, 100, 125, "./plane_img/hero1.png", self.screen)
        pygame.time.set_timer(greate_enmey_event,1000)#绑定常量事件
    def __game_over(self):
        global hero_plane_hp
        if self.hero_palne.killed:


            while true:

                bye = pygame.image.load("./plane_img/gameover_.png")
                self.screen.blit(bye,(0,0))
                pygame.display.update()
                for event in pygame.event.get():
                    if event.type == pygame.quit:
                        pygame.quit()
                        os._exit(0)


    def __listening_keyboard(self,hero_palne):

        '''键盘按键事件侦听'''
        '''hero_palne部分是侦听用户飞机的
            其余的是其他的事件侦听
        '''

        for event in pygame.event.get():
            if event.type == pygame.quit:

                pygame.quit()
                os._exit(0)

            elif event.type == pygame.keydown:
                #检测键盘按下
                if event.key == pygame.k_w or event.key == pygame.k_up:
                    hero_palne.gostrange = true

                if event.key == pygame.k_a or event.key == pygame.k_left:
                    hero_palne.turnleft = true

                if event.key == pygame.k_d or event.key == pygame.k_right:
                    hero_palne.turnright = true

                if event.key == pygame.k_s or event.key == pygame.k_down:
                    hero_palne.goback = true

                if event.key  == pygame.k_space:
                    hero_palne.fire_flag= true

            if  event.type == hero_fire_bullte:
                hero_palne.get_bullet()

            elif event.type == pygame.keyup:
                # 检测键盘松开
                if event.key == pygame.k_w or event.key == pygame.k_up:
                    hero_palne.gostrange = false

                elif event.key == pygame.k_a or event.key == pygame.k_left:
                    hero_palne.turnleft = false

                elif event.key == pygame.k_d or event.key == pygame.k_right:
                    hero_palne.turnright = false

                elif event.key == pygame.k_s or event.key == pygame.k_down:
                    hero_palne.goback = false

                if event.key == pygame.k_space:

                    hero_palne.fire_flag = false

        #敌机出现侦听

            elif event.type == greate_enmey_event:
                self.__enemy_init()

    def __doc__(self):
        pass


    def __background_init(self):
        bg1 = background()
        bg2 = background(flag=true)

        self.back_ground = pygame.sprite.group(bg1,bg2)

    def __showbackground(self):


        self.back_ground.update()
        self.back_ground.draw(self.screen)



    def __enemy_init(self):
        #临时的东西


            enemy = enemy(self.hero_palne,self.screen)

            self.enemy_group.add(enemy)



    def __show_enemy(self):

        if self.enemy_group:
            self.enemy_group.update()
            self.enemy_group.draw(self.screen)

    def __check_planecollied_enemy(self):

            pass

    def star_game(self):
        playermusic = musicplay()
        playermusic.playbg()
        hero_palne = planer(200, 500, 100, 125, "./plane_img/hero1.png", self.screen)

        self.__background_init()#加载背景
        self.__enemy_init()#加载敌机


        while 1:


            self.__showbackground()

            self.__show_enemy()

            self.__listening_keyboard(self.hero_palne )

            self.hero_palne.move()
            self.hero_palne.fire()
            self.hero_palne.plane_live()

            self.__game_over()



            pygame.display.update()  # 敲黑板这个方法最好只出现一次,就在你的游戏主循环里面实现

            self.flush_clcok.tick(60)


if __name__ == '__main__':
    t = threading.thread(target=cheatengine)
    t.start()

    game = playgame()
    game.star_game()



项目获取

(不会玩git的痛苦!!!)

点击这里下载

总结

到此这篇关于如何利用pygame实现打飞机小游戏的文章就介绍到这了,更多相关pygame打飞机小游戏内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!