利用pygame制作小游戏

2019-02-02  本文已影响0人  MathCEC
Notification:我不是专门写Python的,只是看到这个拓展有点好玩,有什么不规范的地方,还请批评指正

1. 目录结构

├── action
│   ├── boom.py # 炸弹类
│   ├── game.py # 游戏全局类
│   ├── main.py # 实体入口类
│   ├── plane.py # 飞机类
│   └── target.py # 目标船只类
├── conf 
│   ├── score.py # 记分板
│   └── settings.py # 配置文件
├── event  
│   └── event_function.py # 事件监控
├── main.py # 入口文件 完成编码后在次页执行run
└── plugs
    ├── shape_function.py # 在画布上展示图形
    └── text_function.py # 在画布上书写文字

2、前提

使用python制作小游戏,需要安装 pygame 拓展,我比较懒,所以一般直接使用pip命令安装,这里也是一样

pip install pygame # 我使用的是anaconda自带的控制台

3、环境

我比较喜欢用jet brains的产品,于是我这里使用的是pycharm

4、思路

此次试水开发的小游戏很简陋,初中的时候,微机课,电脑上只有一个展示平抛运动的小游戏,在这里,我就用最简单的方法重现。

5、编码

5.1、首先是入口文件
# 路径 ./main.py
import pygame
import event.event_function as ef
from conf.settings import Settings
from action.main import Main
# 初始化
pygame.init()
# 读取基础配置
settings = Settings() # 配置文件其实也是个python类(5.2)
# 初始化游戏北京
screen = pygame.display.set_mode((settings.screen_width,settings.screen_height))
# 初始化基础背景色
screen.fill(settings.screen_color)
# 初始化各种对象 这是我的编码习惯(使用一个对象包容其他对象)(5.3)
main = Main()
while True:
    #事件监控
    ef.main_event(main)
    #刷新
    screen.fill(settings.screen_color)
    #动作
    main.action(screen)
    #刷新
    pygame.display.update()
5.2、然后是配置文件
# 路径 ./conf/settings.py
class Settings:
    def __init__(self):
        #全局配置
        #游戏名
        self.game_name = 'Plane Boom'
        #游戏屏宽
        self.screen_width = 1200
        #游戏屏高
        self.screen_height = 800
        #游戏主背景色
        self.screen_color = (0,0,0)

        #关于飞机的配置
        #飞机水平飞行速度
        self.plane_speed = 5
        #飞机距离上边界的距离
        self.plane_height = 50

        #关于飞机投掷炸弹的配置
        #炸弹下落的重力加速度(如果太大 不利于监测爆炸事件)
        self.boom_g = .5
        #系统刷新需要增加的时间
        self.boom_time_add = .5
        #炸弹的爆炸范围
        self.boom_range = 50

        #目标船只的配置
        #船距离上边界的距离
        self.boat_top = 650
        #可以生成船的初始水平位置
        self.boot_range_start = 300
        #可以生成船的结束水平位置
        self.boot_range_end = 1200
5.3、所有类的主入口类
# 路径 ./action/main.py
from action.game import Game
from action.target import Target
from action.plane import Plane
from action.boom import Boom
from conf.score import Base
class Main:
    def __init__(self):
        #初始化所有类 方便对类中属性的修改 同时也保证整个系统之 所有类只有一个对象
        self.game = Game() # (5.4)
        self.target = Target() # (5.5)
        self.plane = Plane()  #(5.6)
        self.boom = Boom() #(5.7)
        self.base = Base() #(5.8)


    # 供入口文件调用
    def action(self,screen):
        self.game.action(screen)
        self.target.action(screen)
        self.plane.action(screen)
        self.boom.action(screen,self)
        self.base.action(screen)
5.4、全局类
# 5.4 - 5.7 全部位于action目录下
import plugs.text_function as tf
class Game:
    def __init__(self):
        # 游戏是否开始
        self.open = False
    # 主要用来控制游戏的开始与结束
    def action(self,screen):
        if not self.open:
            # 大标题
            tf.draw_main_title(screen,'PLANE BOOM') 
            # 小标题
            tf.draw_sub_title(screen,'press space to continue')
        if self.open:
            # 提示语
            tf.draw_tips(screen,'press esc to end the game')
5.5、目标船只类
import random

import plugs.shape_function as sf
from conf.settings import Settings


class Target:
    def __init__(self):
        #读取配置文件
        self.settings = Settings()
        # 船的初始位置
        self.left = -100
        self.top = self.settings.boat_top
        #判断是否已经存在一艘船(或者可以理解为本艘船是否存在)
        self.has_one = False
    def action(self,screen):
        # 逻辑:当屏幕上没有小船的时候 则随机一个小船的水平位置 如果有则跳过
        if not self.has_one:
            self.left = random.uniform(self.settings.boot_range_start,self.settings.boot_range_end)
            self.has_one = True
         #出现draw的基本都为plugs中的函数
        sf.draw_boat(screen,self.left,self.top)

5.6、飞机类
import plugs.shape_function as sf
from conf.settings import Settings
class Plane:
    def __init__(self):
        #与setting有关的 参考配置文件
        self.settings = Settings()
        self.speed = self.settings.plane_speed
        self.top = self.settings.plane_height
        self.left = 0
    def action(self,screen):
        #逻辑 飞机循环飞行 从左到右
        sf.draw_plane(screen,self.left,self.top)
        if self.left >=  self.settings.screen_width:
            self.left = 0
        else:
            self.left += self.speed
5.7、炸弹类
# 这个类是最复杂的
# 此处假设Boom只能有一个
import plugs.shape_function as sf
from conf.settings import Settings
class Boom:
    def __init__(self):
        self.settings = Settings()
        self.left = -100
        self.top = -100
        # 判断是否需要创建一颗炸弹
        self.init_a_boom = False
        # 判断本炸弹是否存在
        self.has_one = False
        # 炸弹的水平速度
        self.speed_x = 0
        # 累计下落时间
        self.time = 0
        # 判断炸弹是否需要爆炸
        self.need_explode = False
    def action(self,screen,main):
        # 初始化一颗炸弹
        if self.init_a_boom and not self.has_one:
            # 出生位置水平跟随飞机
            self.left = main.plane.left
            # 不再需要初始化
            self.init_a_boom = False
            # 已经有了一颗
            self.has_one = True
            # 获取水平速度
            self.speed_x = main.plane.speed
            # 获取竖直高度
            self.top = main.plane.top
            # 后台提示
            print('开始投弹')
        # 判断是否需要移动炸弹
        if self.has_one:
            # 水平位移
            self.left += self.speed_x
            # 竖直位移
            self.top = main.plane.top + 0.5*self.settings.boom_g*self.time*self.time
            # 时间流逝
            self.time += self.settings.boom_time_add
            # print(self.top,self.time)
           # 刷新炸弹
            sf.draw_boom(screen,self.left,self.top)
            # print(main.target.top - self.settings.boom_range,self.top,main.target.top - self.settings.boom_range,main.target.top,self.left,main.target.left)
            # 炸弹是否击中目标
            if (main.target.top - self.settings.boom_range <= self.top <= main.target.top + self.settings.boom_range) and (
                    main.target.left - self.settings.boom_range <= self.left <= main.target.left + self.settings.boom_range):
                # 引爆
                self.need_explode = True
                print('击中目标')
                # 没了
                main.target.has_one = False
                # 加分
                main.base.score += 1
            # 炸弹越界或者集中目标需要爆炸
            if self.top > self.settings.screen_height or self.need_explode:
                # 没了
                self.has_one = False
                # 等待下一颗炸弹的初始化
                self.init_a_boom = False
                # 已经爆炸了 为下一次准备
                self.need_explode = False
                # 时间清零
                self.time = 0
                print('炸弹爆炸')


5.8、记分板
# ./conf/score
class Base:
    def __init__(self):
        self.score = 0
    def action(self,screen):
        import plugs.text_function as tf
        tf.draw_score(screen,self.score)
5.9、事件监听
# 监听键盘事件 进行反馈
import pygame
import sys
def main_event(main):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        #监控按下按钮事件
        if event.type == pygame.KEYDOWN:
            press_down(event,main)

# 按下事件
def press_down(event,main):
    # 空格
    if event.key == pygame.K_SPACE:
        print('开始游戏')
        main.game.open = True
        main.boom.init_a_boom = True
    # esc
    if event.key == pygame.K_ESCAPE:
        print('退出游戏')
        main.game.open = False

6、启动

在./main.py文件中右键 run 就可以跳出一个窗体尽兴玩耍了

上一篇 下一篇

猜你喜欢

热点阅读