wxPython和pycairo练习记录18

还是继续找文件依赖少的代码,有些必要的被依赖文件也需要先完成。

Font.py 中 Font 类居然继承 Spritesheet 类来加载字符对应图片,还和 Sprites 类的功能差不多,总感觉哪里不太对。https://github.com/mx0c/super-mario-python/blob/5623213c2eb001d8dabd95eb7035d7545e86ccf6/classes/Font.py

Math.py 中写了名为二维向量的类,但只是简单记录了坐标。

Tile.py 只是画红色边框矩形,实际用途未知。

GaussianBlur.py 高斯模糊,其视觉效果就像是经过一个毛玻璃在观察图像。来源:https://baike.baidu.com/item/%E9%AB%98%E6%96%AF%E6%A8%A1%E7%B3%8A/10885810 。wxPython 提供了方便的接口,直接调用 wx.Image.Blur 方法即可实现。

entities 目录中 EntityBase.py 主要实现了实体的状态的记录和更新。几个状态走跳跑都在 traits 目录单独创建了类,每个类方法还都不一样,这是丐版有限状态机吧。

Camera.py 摄像机,这里的功能是记录坐标,跟随实体移动坐标。

类图

基本都没法写测试啊,后面待完成的是声音、鼠标键盘输入、碰撞检测、实体和主要显示类:面板、关卡、菜单、暂停画面。

代码:

# Font.py
from mario.classes.SpriteSheet import SpriteSheet


class Font(SpriteSheet):
    def __init__(self, file_path, size):
        SpriteSheet.__init__(self, filename=file_path)
        self.chars = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
        # 字符与字符图片 Sprite 对象组成的键值对
        self.char_sprites = self.load_font()

    def load_font(self):
        font = {}
        row = 0
        column = 0

        for char in self.chars:
            # 字符图片中字符有 16 列
            if column == 16:
                column = 0
                row += 1
            font.update(
                {
                    char: self.image_at(
                        column,
                        row,
                        scale=2,
                        color_key=(0, 0, 0),
                        tile_width=8,
                        tile_height=8
                    )
                }
            )
            column += 1
        return font

# Maths.py
class Vec2D:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

# Tile.py
from cairo import Context


class Tile:
    def __init__(self, sprite, rect):
        self.sprite = sprite
        self.rect = rect

    def draw_rect(self, screen):
        try:
            # 等定义 screen 后再修改
            ctx = Context(screen)
            # 创建矩形路径,只是在 Context 中当前路径添加一个矩形描述,并不会实际绘制
            ctx.rectangle(*self.rect)
            # 设置绘制颜色,后续描边和填充都会用到,rgb 取值 0 到 1
            ctx.set_source_rgb(1, 0, 0)
            # 后续绘制的线条宽度
            ctx.set_line_width(1)
            # 描边,实际绘制矩形
            ctx.stroke()
        except Exception:
            pass

# GaussianBlur.py
import wx
import wx.lib.wxcairo


class GaussianBlur:
    def __init__(self, blur_radius=2):
        self.blur_radius = blur_radius

    def filter(self, original_surface):
        # 将原始 wx.ImageSurface 对象转为 wx.Image 对象
        image = wx.lib.wxcairo.BitmapFromImageSurface(original_surface).ConvertToImage()
        # 调用模糊方法
        blurred_image = image.Blur(self.blur_radius)
        # 转回 Surface
        blurred_surface = wx.lib.wxcairo.ImageSurfaceFromBitmap(blurred_image.ConvertToBitmap())

        return blurred_surface

# EntityBase.py
from wx import Rect
from mario.classes.Maths import Vec2D


class EntityBase(object):
    def __init__(self, x, y, gravity):
        self.vel = Vec2D()
        self.rect = Rect(x * 32, y * 32, 32, 32)  # 标准 tile 尺寸
        self.gravity = gravity  # 重力
        self.traits = None  # 状态
        self.alive = True
        self.active = True
        self.bouncing = False
        self.time_after_death = 5
        self.timer = 0
        self.type = ""
        self.on_ground = False
        self.obey_gravity = True

    def apply_gravity(self):
        # 下落的纵轴量更大,相当于添加了重力加速度
        if self.obey_gravity:
            self.vel.y += self.gravity

    def update_traits(self):
        # 几个状态走跳跑都单独创建了类,每个类方法还都不一样,这是丐版有限状态机吧
        for trait in self.traits.values():
            try:
                trait.update()
            except AttributeError:
                pass

    def get_pos_index(self):
        # 按 32 * 32 尺寸划分网格的索引
        return Vec2D(self.rect.x // 32, self.rect.y // 32)

    def get_pos_index_float(self):
        return Vec2D(self.rect.x / 32.0, self.rect.y / 32.0)

# Camera.py
from mario.classes.Maths import Vec2D


class Camera:
    def __init__(self, pos, entity):
        self.pos = Vec2D(pos.x, pos.y)
        self.entity = entity  # EntityBase 对象
        self.x = self.pos.x * 32
        self.y = self.pos.y * 32

    def move(self):
        # 跟随实体移动
        xpos_float = self.entity.get_pos_index_float().x
        if 10 < xpos_float < 50:
            self.pos.x = -xpos_float + 10
        self.x = self.pos.x * 32
        self.y = self.pos.y * 32

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值