wxPython和pycairo练习记录6

wxPython和pycairo练习记录6

这次想要实现障碍物。

6.1 障碍类

90坦克游戏里障碍有砖墙、草地、铁块、冰面、水面。

砖墙:不能穿行,能打破
草地:能穿行,不能打破,坦克能躲在草里,视觉上坦克在草地下面一层
铁块:不能穿行,不能打破,特殊子弹能打破
冰面:能穿行,不能打破,视觉上坦克在冰面上一层,坦克通过时会滑行
水面:不能穿行,不能打破,子弹能穿过

再编几个:
反弹墙:坦克碰撞就被反弹一段距离
碉堡:给障碍加载之前写的武器系统
动感超人:坦克靠近一定距离就发射动感光波

障碍本身是单帧的,选择继承 Sprite ,按上面的分析,抽象出障碍类。

class Obstacle(Sprite):
    def __init__(self, x, y, surface):
        # 重写 Sprite 的构造函数, 直接传入 surface
        self._x = x
        self._y = y
        self._destroyed = False # 销毁状态
        self._surface = surface
        # 获取图像尺寸
        self._width = self._surface.get_width()
        self._height = self._surface.get_height()

        self._canCross = False # 是否可穿行
        self._canDestroy = False # 是否可打破
        self._layer = 0 # 层级,0 和坦克同一层,-1 下层, 1 上层
        self._canBulletCross = False # 是否子弹可穿行
        self._buff = False # 是否有为有特殊效果的

    def CanCross(self):
        return self._canCross

    def CanDestroy(self):
        return self._canDestroy

    def GetLayer(self):
        return self._layer

    def CanBulletCross(self):
        return self._canBulletCross

    def HasBuff(self):
        return self._buff

    def Act(self, tank=None):
        # 与坦克的交互行为,比如加滑行 _buff,比如碉堡直接开火
        pass

    def Update(self, times, speed):
        # 用于被定时器处理函数调用刷新,静态障碍不需要重写
        pass

6.2 砖墙

砖墙如果使用图片素材比较简单,只需要设置几项属性。砖墙应该不算复杂,这里使用 pycairo 绘制试试。

class Brick(Obstacle):
    # 砖墙
    def __init__(self, x, y):
        surface = self.Draw() # 直接绘制砖墙
        super(Brick, self).__init__(x, y, surface)
        self._canCross = False # 不可穿行
        self._canDestroy = True # 可打破
        self._layer = 0 # 层级,0 和坦克同一层
        self._canBulletCross = False # 子弹不可穿行
        self._buff = False # 没有特殊效果

    def Draw(self):
        # 绘制砖墙
        # 按坦克尺寸48创建图像,颜色不需要透明
        surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 48, 48)

        # 砖块是错落砌在一起的,先建一个2倍障碍宽度的矩形,作为一行砖块
        rect1 = cairo.ImageSurface(cairo.FORMAT_RGB24, 96, 12)

        # 画一个小24*12的矩形砖块,然后重复平铺
        rect2 = cairo.ImageSurface(cairo.FORMAT_RGB24, 24, 12)
        ctx = cairo.Context(rect2)
        # 填充灰色作底,水泥
        ctx.set_source_rgb(0.4, 0.4, 0.4)
        ctx.paint()
        # 画矩形,填充砖红色,砖
        ctx.set_source_rgb(0.6, 0.3, 0)
        ctx.rectangle(2, 2, 20, 8)
        ctx.fill()
        # 画线,更深的砖色,阴影
        ctx.set_source_rgb(0.42, 0.02, 0)
        ctx.set_line_width(4)
        ctx.move_to(3, 10)
        ctx.line_to(3, 3)
        ctx.line_to(22, 3)
        ctx.stroke()

        # 以 rect2 重复填充 rect1
        ctx = cairo.Context(rect1)
        pattern = cairo.SurfacePattern(rect2)
        pattern.set_extend(cairo.Extend.REPEAT)
        ctx.set_source(pattern)
        ctx.paint()

        # 把 rect1 错位绘制到 surface
        ctx = cairo.Context(surface)
        ctx.set_source_surface(rect1, -12, 0)
        ctx.paint()
        ctx.set_source_surface(rect1, 0, 12)
        ctx.paint()
        ctx.set_source_surface(rect1, -12, 24)
        ctx.paint()
        ctx.set_source_surface(rect1, 0, 36)
        ctx.paint()

        return surface

不考虑属性做下测试,碰撞检测,需要检测子弹和砖墙碰撞,坦克和砖墙碰撞。砖墙是静止的,所以坦克和它碰撞只能是在前进方向。换个简单环境,只保留玩家坦克。
在这里插入图片描述

玩家坦克和砖墙碰撞,期望的效果是直接停止,这里有像塑料一样弹回来的感觉。在理想情况下,先碰撞检测更新数据,然后绘制,这样是不会出现问题的。

这里用 print 分别在绘制前、碰撞检测前后输出玩家坦克矩形 wx.Rect(x, y, width, height)。

碰撞检测 (60, 60, 48, 48)
检测到碰撞 (60, 60, 48, 48)
碰撞重置为 (60, 50, 48, 48)
绘制 (60, 50, 48, 48)
碰撞检测 (60, 50, 48, 48)
绘制 (60, 60, 48, 48)

已经知道玩家坦克的移动速度是10像素。理想流程:坦克移动,碰撞检测,绘制。从上面的最后两条输出可以发现,实际发生的流程:坦克移动,碰撞检测,坦克移动,绘制。

网上查询是说 wxPython 控件的 Refresh 方法,不会立即执行重绘,强制立即重绘可以使用 Update 方法。改为 Update 倒是没有出现Q弹的效果,但是坐标又会出现问题。这里暂时就保留这种弹的效果吧。

# -*- coding: utf-8 -*-
# example3.py

import random
import math
import wx
import wx.lib.wxcairo
import cairo
import board
from display import MovieClip
from tank import Player, Enemy
from weapon import Weapon, Bullet
from obstacle import Brick

class cv(board.cv):
    """
    常量,用类属性避免使用全局变量
    """
    # 面板尺寸
    BOARD_WIDTH = 600
    BOARD_HEIGHT = 400


class Board(board.Board):
    def DrawBackground(self, ctx):
        super().DrawBackground(ctx)

        text = "SmileBasic"
        ctx.set_font_size(40)
        _, _, w, h, _, _ = ctx.text_extents(text)
        x = (cv.BOARD_WIDTH - w) // 2
        y = (cv.BOARD_HEIGHT - h) // 2

        # 文字是以首个字左下角坐标定位,而矩形是以左上角定位,y轴相差文字的高度,不需要考虑线条宽度。
        # 另外PaintDC是不含标题栏的。
        ctx.rectangle(x - 10, y - 10 - h, w + 20, h + 20)
        ctx.set_source_rgb(1, 0, 0)
        ctx.stroke()

        ctx.move_to(x, y)
        ctx.set_source_rgb(1, 1, 1)
        ctx.show_text(text)

    def InitSceneObjects(self):
        super().InitSceneObjects()

        self.player = Player(60, 50) # 实例化一个玩家坦克
        self.sceneObjects.append(self.player)

        # 初始武器系统,并装弹
        self.bullets = []
        weapon = Weapon(capacity=100, speed=2)
        for i in range(50):
            bullet = Bullet(type=3) # 装载第4行子弹
            weapon.AddBullet(bullet)
            self.bullets.append(bullet)
            self.sceneObjects.append(bullet)

            bullet = Bullet(type=6) # 装载第7行子弹
            weapon.AddBullet(bullet)
            self.bullets.append(bullet)
            self.sceneObjects.append(bullet)
        self.player.LoadWeapon(weapon) # 玩家坦克加载武器系统

        # 生成4个砖墙
        self.bricks = []
        brick1 = Brick(10, 50)
        brick2 = Brick(58, 98)
        brick3 = Brick(106, 98)
        brick4 = Brick(230, 220)
        self.bricks += [brick1, brick2, brick3, brick4]
        self.sceneObjects += [brick1, brick2, brick3, brick4]

    def DrawSceneObjects(self, ctx):
        print("绘制", self.player.GetRect())
        for so in self.sceneObjects:
            if not so.IsDestroyed():
                ctx.set_source_surface(so.GetSurface(), so.GetX(), so.GetY())
                ctx.paint()

    def OnKeyDown(self, e):
        self.player.OnKeyDown(e)
        self.Refresh()

    def OnKeyUp(self, e):
        self.player.OnKeyUp(e)

    def CheckStrategies(self):
        self.CheckCollisions()

    def CheckCollisions(self):
        # 检测子弹砖墙碰撞,碰撞后都销毁
        print("碰撞检测", self.player.GetRect())
        for brick in self.bricks[:]:
            rect = brick.GetRect()
            for bullet in self.bullets[:]:
                if rect.Intersects(bullet.GetRect()):
                    brick.Destroy()
                    self.bricks.remove(brick)
                    self.sceneObjects.remove(brick)

                    bullet.Destroy()
                    self.bullets.remove(bullet)
                    self.sceneObjects.remove(bullet)
                    break

            # 检测坦克和砖墙碰撞,碰撞后坦克位置重置
            if rect.Intersects(self.player.GetRect()):
                print("检测到碰撞", self.player.GetRect())
                direction = self.player.GetDirection()
                x, y, w, h = rect
                _, _, pw, ph = self.player.GetRect()
                if direction == wx.WXK_UP:
                    self.player.SetY(y + h)
                elif direction == wx.WXK_DOWN:
                    self.player.SetY(y - ph)
                elif direction == wx.WXK_LEFT:
                    self.player.SetX(x + w)
                elif direction == wx.WXK_RIGHT:
                    self.player.SetX(x - pw)
                print("碰撞重置为", self.player.GetRect())


6.3 草地和水面

草地在坦克和子弹上层,水面在子弹下层,用来测试层级的问题。用 pycairo 绘制的时候,后绘制的图像在上层,用 set_operator(cairo.Operator.DEST_OVER) 没有达到想要的调整图层效果。这样只能用简单粗暴的办法,在坦克绘制前后各加一个绘制障碍的操作,用障碍的属性 layer 来判断是否绘制。
在这里插入图片描述

class Grass(Obstacle):
    # 草地
    def __init__(self, x, y, path="wall_grass.png"):
        # 从文件加载 surface
        try:
            surface = cairo.ImageSurface.create_from_png(path)
        except IOError as e:
            print(e.message)

        super(Grass, self).__init__(x, y, surface)

        self._canCross = True # 可穿行
        self._canDestroy = False # 不可打破
        self._layer = 1 # 层级,0 和坦克同一层
        self._canBulletCross = True # 子弹可穿行
        self._buff = False # 没有特殊效果


class Water(Obstacle):
    # 水面
    def __init__(self, x, y, path="wall_water.png"):
        # 从文件加载 surface
        try:
            surface = cairo.ImageSurface.create_from_png(path)
        except IOError as e:
            print(e.message)

        super(Water, self).__init__(x, y, surface)

        self._canCross = False # 不可穿行
        self._canDestroy = False # 不可打破
        self._layer = -1 # 子弹可以在水面上层飞过
        self._canBulletCross = True # 子弹可穿行
        self._buff = False # 没有特殊效果
        
    def DrawSceneObjects(self, ctx):
        # print("绘制", self.player.GetRect())
        # 后绘制的对象在上层显示
        for obstacle in self.obstacles:
            if obstacle.GetLayer() == -1:
                self.DrawSprite(ctx, obstacle)

        self.DrawSprite(ctx, self.player)

        for bullet in self.bullets:
            self.DrawSprite(ctx, bullet)

        for obstacle in self.obstacles:
            if obstacle.GetLayer() >= 0:
                self.DrawSprite(ctx, obstacle)

6.4 冰面

冰面能带给坦克滑行 buff,而坦克可穿行,之前写的是可穿行就不做坦克和障碍的碰撞检测。需要搞清楚的逻辑是,障碍 buff 是对坦克作用的,所以必须检测和坦克的碰撞,不管是直接碰撞还是接近障碍范围碰撞。
在这里插入图片描述

class Ice(Obstacle):
    # 冰面
    def __init__(self, x, y):
        surface = self.Draw()
        super(Ice, self).__init__(x, y, surface)
        self._canCross = True # 可穿行
        self._canDestroy = False # 不可打破
        self._layer = -1 # 层级,0 和坦克同一层
        self._canBulletCross = True # 子弹可穿行
        self._buff = True # 有特殊效果
        self._distance = 20 # 滑行距离

    def Draw(self):
        surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 48, 48)
        ctx = cairo.Context(surface)
        # 填充底色
        ctx.set_source_rgb(0.1, 0.85, 0.95)
        ctx.paint()

        # 以中心逆向旋转45度
        ctx.translate(24, 24)
        ctx.rotate(math.pi * 3 / 4)
        ctx.translate(-24, -24)

        # 画几条表示冰面纹理的线
        ctx.set_source_rgb(0, 0.64, 0.8)
        for i in range(10):
            if i % 2 == 0:
                ctx.set_dash([5, 1])
            else:
                ctx.set_dash([10, 15])

            ctx.move_to(-10, 6 * i)
            ctx.line_to(70, 6 * i)
            ctx.stroke()

        return surface

    def Act(self, tank=None):
        # 与坦克的交互行为,比如加滑行 _buff,比如碉堡直接开火
        direction = tank.GetDirection()
        x = tank.GetX()
        y = tank.GetY()
        if direction == wx.WXK_UP:
            tank.SetY(y - self._distance)
        elif direction == wx.WXK_DOWN:
            tank.SetY(y + self._distance)
        elif direction == wx.WXK_LEFT:
            tank.SetX(x - self._distance)
        elif direction == wx.WXK_RIGHT:
            tank.SetX(x + self._distance)

6.5 代码及效果

在这里插入图片描述

# -*- coding: utf-8 -*-
# obstacle.py

import math
import wx
import cairo
from display import Sprite


class Obstacle(Sprite):
    def __init__(self, x, y, surface):
        # 重写 Sprite 的构造函数, 直接传入 surface
        self._x = x
        self._y = y
        self._destroyed = False # 销毁状态
        self._surface = surface
        # 获取图像尺寸
        self._width = self._surface.get_width()
        self._height = self._surface.get_height()

        self._canCross = False # 是否可穿行
        self._canDestroy = False # 是否可打破
        self._layer = 0 # 层级,0 和坦克同一层,-1 下层, 1 上层
        self._canBulletCross = False # 是否子弹可穿行
        self._buff = False # 是否有为有特殊效果的

    def CanCross(self):
        return self._canCross

    def CanDestroy(self):
        return self._canDestroy

    def GetLayer(self):
        return self._layer

    def CanBulletCross(self):
        return self._canBulletCross

    def HasBuff(self):
        return self._buff

    def Act(self, tank=None):
        # 与坦克的交互行为,比如加滑行 _buff,比如碉堡直接开火
        pass

    def Update(self, times, speed):
        # 用于被定时器处理函数调用刷新,静态障碍不需要重写
        pass


class Brick(Obstacle):
    # 砖墙
    def __init__(self, x, y):
        surface = self.Draw() # 直接绘制砖墙
        super(Brick, self).__init__(x, y, surface)
        self._canCross = False # 不可穿行
        self._canDestroy = True # 可打破
        self._layer = 0 # 层级,0 和坦克同一层
        self._canBulletCross = False # 子弹不可穿行
        self._buff = False # 没有特殊效果

    def Draw(self):
        # 绘制砖墙
        # 按坦克尺寸48创建图像,颜色不需要透明
        surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 48, 48)

        # 砖块是错落砌在一起的,先建一个2倍障碍宽度的矩形,作为一行砖块
        rect1 = cairo.ImageSurface(cairo.FORMAT_RGB24, 96, 12)

        # 画一个小24*12的矩形砖块,然后重复平铺
        rect2 = cairo.ImageSurface(cairo.FORMAT_RGB24, 24, 12)
        ctx = cairo.Context(rect2)
        # 填充灰色作底,水泥
        ctx.set_source_rgb(0.4, 0.4, 0.4)
        ctx.paint()
        # 画矩形,填充砖红色,砖
        ctx.set_source_rgb(0.6, 0.3, 0)
        ctx.rectangle(2, 2, 20, 8)
        ctx.fill()
        # 画线,更深的砖色,阴影
        ctx.set_source_rgb(0.42, 0.02, 0)
        ctx.set_line_width(4)
        ctx.move_to(3, 10)
        ctx.line_to(3, 3)
        ctx.line_to(22, 3)
        ctx.stroke()

        # 以 rect2 重复填充 rect1
        ctx = cairo.Context(rect1)
        pattern = cairo.SurfacePattern(rect2)
        pattern.set_extend(cairo.Extend.REPEAT)
        ctx.set_source(pattern)
        ctx.paint()

        # 把 rect1 错位绘制到 surface
        ctx = cairo.Context(surface)
        ctx.set_source_surface(rect1, -12, 0)
        ctx.paint()
        ctx.set_source_surface(rect1, 0, 12)
        ctx.paint()
        ctx.set_source_surface(rect1, -12, 24)
        ctx.paint()
        ctx.set_source_surface(rect1, 0, 36)
        ctx.paint()

        return surface


class Grass(Obstacle):
    # 草地
    def __init__(self, x, y, path="wall_grass.png"):
        # 从文件加载 surface
        try:
            surface = cairo.ImageSurface.create_from_png(path)
        except IOError as e:
            print(e.message)

        super(Grass, self).__init__(x, y, surface)

        self._canCross = True # 可穿行
        self._canDestroy = False # 不可打破
        self._layer = 1 # 层级,0 和坦克同一层
        self._canBulletCross = True # 子弹可穿行
        self._buff = False # 没有特殊效果


class Water(Obstacle):
    # 水面
    def __init__(self, x, y, path="wall_water.png"):
        # 从文件加载 surface
        try:
            surface = cairo.ImageSurface.create_from_png(path)
        except IOError as e:
            print(e.message)

        super(Water, self).__init__(x, y, surface)

        self._canCross = False # 不可穿行
        self._canDestroy = False # 不可打破
        self._layer = -1 # 子弹可以在水面上层飞过
        self._canBulletCross = True # 子弹可穿行
        self._buff = False # 没有特殊效果

class Ice(Obstacle):
    # 冰面
    def __init__(self, x, y):
        surface = self.Draw()
        super(Ice, self).__init__(x, y, surface)
        self._canCross = True # 可穿行
        self._canDestroy = False # 不可打破
        self._layer = -1 # 层级,0 和坦克同一层
        self._canBulletCross = True # 子弹可穿行
        self._buff = True # 有特殊效果
        self._distance = 20 # 滑行距离

    def Draw(self):
        surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 48, 48)
        ctx = cairo.Context(surface)
        # 填充底色
        ctx.set_source_rgb(0.1, 0.85, 0.95)
        ctx.paint()

        # 以中心逆向旋转45度
        ctx.translate(24, 24)
        ctx.rotate(math.pi * 3 / 4)
        ctx.translate(-24, -24)

        # 画几条表示冰面纹理的线
        ctx.set_source_rgb(0, 0.64, 0.8)
        for i in range(10):
            if i % 2 == 0:
                ctx.set_dash([5, 1])
            else:
                ctx.set_dash([10, 15])

            ctx.move_to(-10, 6 * i)
            ctx.line_to(70, 6 * i)
            ctx.stroke()

        return surface

    def Act(self, tank=None):
        # 与坦克的交互行为,比如加滑行 _buff,比如碉堡直接开火
        direction = tank.GetDirection()
        x = tank.GetX()
        y = tank.GetY()
        if direction == wx.WXK_UP:
            tank.SetY(y - self._distance)
        elif direction == wx.WXK_DOWN:
            tank.SetY(y + self._distance)
        elif direction == wx.WXK_LEFT:
            tank.SetX(x - self._distance)
        elif direction == wx.WXK_RIGHT:
            tank.SetX(x + self._distance)

# -*- coding: utf-8 -*-
# example3.py

import random
import math
import wx
import wx.lib.wxcairo
import cairo
import board
from display import MovieClip
from tank import Player, Enemy
from weapon import Weapon, Bullet
from obstacle import Brick, Grass, Water, Ice

class cv(board.cv):
    """
    常量,用类属性避免使用全局变量
    """
    # 面板尺寸
    BOARD_WIDTH = 600
    BOARD_HEIGHT = 400


class Board(board.Board):
    def DrawBackground(self, ctx):
        super().DrawBackground(ctx)

        text = "SmileBasic"
        ctx.set_font_size(40)
        _, _, w, h, _, _ = ctx.text_extents(text)
        x = (cv.BOARD_WIDTH - w) // 2
        y = (cv.BOARD_HEIGHT - h) // 2

        # 文字是以首个字左下角坐标定位,而矩形是以左上角定位,y轴相差文字的高度,不需要考虑线条宽度。
        # 另外PaintDC是不含标题栏的。
        ctx.rectangle(x - 10, y - 10 - h, w + 20, h + 20)
        ctx.set_source_rgb(1, 0, 0)
        ctx.stroke()

        ctx.move_to(x, y)
        ctx.set_source_rgb(1, 1, 1)
        ctx.show_text(text)

    def InitSceneObjects(self):
        super().InitSceneObjects()
        self.InitPlayer()
        self.InitObstacles()

    def InitPlayer(self):
        self.player = Player(60, 50) # 实例化一个玩家坦克
        self.sceneObjects.append(self.player)

        # 初始武器系统,并装弹
        self.bullets = []
        weapon = Weapon(capacity=100, speed=2)
        for i in range(50):
            bullet = Bullet(type=3) # 装载第4行子弹
            weapon.AddBullet(bullet)
            self.bullets.append(bullet)
            self.sceneObjects.append(bullet)

            bullet = Bullet(type=6) # 装载第7行子弹
            weapon.AddBullet(bullet)
            self.bullets.append(bullet)
            self.sceneObjects.append(bullet)
        self.player.LoadWeapon(weapon) # 玩家坦克加载武器系统

    def InitObstacles(self):
        self.obstacles = []
        # 生成4个砖墙
        brick1 = Brick(10, 50)
        brick2 = Brick(58, 98)
        brick3 = Brick(106, 98)
        brick4 = Brick(230, 220)
        # 生成1个草地
        grass = Grass(300, 50)
        # 生成1个水面
        water = Water(360, 50)
        # 生成1个冰面
        ice = Ice(230, 50)
        self.obstacles += [brick1, brick2, brick3, brick4, grass, water, ice]
        self.sceneObjects += [brick1, brick2, brick3, brick4, grass, water, ice]

    def DrawSceneObjects(self, ctx):
        # print("绘制", self.player.GetRect())
        # 后绘制的对象在上层显示
        for obstacle in self.obstacles:
            if obstacle.GetLayer() == -1:
                self.DrawSprite(ctx, obstacle)

        self.DrawSprite(ctx, self.player)

        for bullet in self.bullets:
            self.DrawSprite(ctx, bullet)

        for obstacle in self.obstacles:
            if obstacle.GetLayer() >= 0:
                self.DrawSprite(ctx, obstacle)

    def DrawSprite(self, ctx, sprite):
        ctx.set_source_surface(sprite.GetSurface(), sprite.GetX(), sprite.GetY())
        ctx.paint()

    def OnKeyDown(self, e):
        self.player.OnKeyDown(e)
        self.Refresh()

    def OnKeyUp(self, e):
        self.player.OnKeyUp(e)

    def CheckStrategies(self):
        self.CheckCollisions()

    def CheckCollisions(self):
        # 检测子弹砖墙碰撞
        # print("碰撞检测", self.player.GetRect())
        for obstacle in self.obstacles[:]:
            # 子弹可穿行,则跳过检测
            if obstacle.CanBulletCross():
                continue

            rect = obstacle.GetRect()
            for bullet in self.bullets[:]:
                if rect.Intersects(bullet.GetRect()):
                    # 如果可摧毁,则碰撞后子弹和障碍都销毁
                    if obstacle.CanDestroy():
                        obstacle.Destroy()
                        self.obstacles.remove(obstacle)
                        self.sceneObjects.remove(obstacle)

                    bullet.Destroy()
                    self.bullets.remove(bullet)
                    self.sceneObjects.remove(bullet)
                    break

        # 检测坦克和砖墙碰撞,碰撞后坦克位置重置
        for obstacle in self.obstacles[:]:
            # 坦克可穿行并且没有特殊效果,则跳过检测
            if obstacle.CanCross() and not obstacle.HasBuff():
                continue

            rect = obstacle.GetRect()
            if rect.Intersects(self.player.GetRect()):
                # print("检测到碰撞", self.player.GetRect())

                # 如果有特殊效果则只不执行后续位置重置
                if obstacle.HasBuff():
                    obstacle.Act(self.player)
                    continue

                direction = self.player.GetDirection()
                x, y, w, h = rect
                _, _, pw, ph = self.player.GetRect()
                if direction == wx.WXK_UP:
                    self.player.SetY(y + h)
                elif direction == wx.WXK_DOWN:
                    self.player.SetY(y - ph)
                elif direction == wx.WXK_LEFT:
                    self.player.SetX(x + w)
                elif direction == wx.WXK_RIGHT:
                    self.player.SetX(x - pw)
                # print("碰撞重置为", self.player.GetRect())


猜你喜欢

转载自blog.csdn.net/SmileBasic/article/details/126397548