wxPython和pycairo练习记录12

滚动字幕 Python 实现 在本文中,我将介绍如何使用 Python 创建一个滚动字幕效果。我们将使用 Python 的 tkinter 模块来实现这个效果。在上述代码中,我们使用了一个 while 循环来不断更新标签的位置。当 x 坐标小于 -200 时,我们将其重置为 400,以实现无缝滚动的效果。运行以上代码,你将会看到一个带有滚动字幕效果的窗口。滚动字幕将从窗口的右侧开始,向左滚动,当滚动到窗口的左侧时,会重新回到窗口的右侧,形成一个无限滚动的效果。接下来,我们定义一个函数来实现滚动字幕的效果。如果你有任何问题,请随时提问。 阅读详情

wxPython 实现滚动字幕效果

过年在家刷视频号直播时发现弹幕互动游戏,挺有意思的,刚好诠释了“反射”(一种基于字符串的事件驱动)的用法。想要自己也做一个弹幕游戏,于是就有了这个基本的需求,先让弹幕滚动显示出来,直播时可以当作小挂件。

滚动文字功能

先查 API 文档和 demo 看有没相应的控件和例子,发现 wxPython 有滚动文字控件 wx.lib.ticker.Ticker (Ticker翻译:滚动条;收报机;心脏;跑马灯;断续器)。

类签名:
wx.lib.ticker.Ticker(parent, id=-1, text="", fgcolor = wx.BLACK, bgcolor = wx.WHITE, start=True, ppf=2, fps=20, direction="rtl", pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.NO_BORDER, name="Ticker")

参数:	
parent (wx.Window) – the parent
id (integer) – an identifier for the control: a value of -1 is taken to mean a default
text (string) – text in the ticker
fgcolor (wx.Colour) – text/foreground color
bgcolor (wx.Colour) – background color
start (boolean) – if True, the ticker starts immediately
ppf (int) – pixels per frame
fps (int) – frames per second
direction – direction of ticking, ‘rtl’ or ‘ltr’
pos (wx.Point) – the control position. A value of (-1, -1) indicates a default position, chosen by either the windowing system or wxPython, depending on platform
name – the control name

看看效果:
在这里插入图片描述

源码:

# -*- coding: utf-8 -*-
import wx
from wx.lib.ticker import Ticker


class MyFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super(MyFrame, self).__init__(*args, **kwargs)
        self.Center()

        self.ticker = Ticker(parent=self, id=-1, text="你好,世界!Hello World!😍 ",
                             fgcolor="#ff0000", bgcolor="#fff000", start=True,
                             ppf=2, fps=20, direction="rtl",
                             pos=wx.DefaultPosition, size=self.GetClientSize(), style=wx.NO_BORDER,
                             name="Ticker")
        self.ticker.SetFont(wx.Font(18, family=wx.SWISS, style=wx.NORMAL, weight=wx.BOLD, faceName=u"宋体"))
        self.ticker.Start()

        self.ticker.Bind(wx.EVT_RIGHT_UP, self.OnClose)
        self.ticker.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
        self.ticker.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
        self.ticker.Bind(wx.EVT_MOTION, self.OnMouseMove)

    def OnClose(self, event):
        self.Close()

    def OnLeftDown(self, evt):
        # CaptureMouse 把所有鼠标输入指向 self.ticker 控件窗口
        self.ticker.CaptureMouse()
        # ClientToScreen 把鼠标位置相对于程序窗口的坐标转换为相对于屏幕的坐标
        x, y = self.ClientToScreen(evt.GetPosition())
        originx, originy = self.GetPosition()
        dx = x - originx
        dy = y - originy
        self.delta = ((dx, dy))

    def OnLeftUp(self, evt):
        if self.ticker.HasCapture():
            self.ticker.ReleaseMouse()

    def OnMouseMove(self, evt):
        if evt.Dragging() and evt.LeftIsDown():
            x, y = self.ClientToScreen(evt.GetPosition())
            fp = (x - self.delta[0], y - self.delta[1])
            # Move 将窗口移动到指定坐标
            self.Move(fp)


class App(wx.App):
    def OnInit(self):
        frame = MyFrame(parent=None, size=(1075, 53), style=wx.NO_BORDER)
        frame.Show()
        return True

    def OnExit(self):
        return 0


if __name__ == "__main__":
    app = App()
    app.MainLoop()

滚动文字衔接问题

滚动循环,文字需要全部滚出才会重新滚入,有空白期。
在这里插入图片描述

原 Ticker 类中,滚动文字是用属性 self._text 来存储的,它是一个字符串。如果在字符串尾部附加其他新的字符串,并不能解决显示衔接问题,而且不便对指定字符串进行修改。那么直接继承 Ticker ,把 _text 改成 list,并修改相应方法。

本来是想像做动画一样,将 _text 复制一份,轮流滚动。但是因为后期还要动态添加字符串,并且不应该把所有文字都显示出来。

所以最后想到的解决办法是:另设一个列表 _show_text 用于存储要显示的字符串,_index 表示最后从 _text 添加到 _show_text 的字符串的_text 索引。 当 _show_text 头部节点滚出显示区时,从列表中去除,当尾节点尾部与显示区尾部相距超过设定间距时,则把 _text[_index+1] 附加到 _show_text。
在这里插入图片描述

效果,录像 GIF 帧率是 30 FPS:
在这里插入图片描述

源码:

# -*- coding: utf-8 -*-
# Author: SmileBasic
import wx
import wx.lib.ticker


class Ticker(wx.lib.ticker.Ticker):
    def __init__(self, *args, **kwargs):
        self._text = []  # 滚动字符串存储列表
        self._text_max = 500  # _text 最大可存储字符串数量
        self._show_text = []  # 显示字符串列表
        self._show_text_size = (-1, -1)
        self._gap = 0  # 滚动字符串之间间距
        self._gap_pixels = 0
        self._index = 0  # 最后进入显示区域的文字索引
        super(Ticker, self).__init__(*args, **kwargs)

    def SetText(self, text):
        """将字符串插入滚动字符串列表尾部"""
        if text.strip():
            if len(self._text) == self._text_max:
                self._text.pop(0)
                if self._index > 0:
                    self._index = self._index - 1
            self._text.append(text)
            if not self._show_text:
                self._show_text.append(text)
                self.Refresh()

    def SetGap(self, gap):
        """设置字符串显示间距"""
        self._gap = gap

    def UpdateExtent(self, dc):
        """更新字符串尺寸"""
        dc.SetFont(self.GetFont())
        self._gap_pixels = dc.GetTextExtent(self._gap * " ")[0]
        self._show_text_size = dc.GetTextExtent((self._gap * " ").join(self._show_text))
        if self._show_text:
            self._extent = dc.GetTextExtent(self._show_text[0])
        else:
            self._extent = (-1, -1)

    def OnTick(self, evt):
        """更新滚动文字坐标"""
        self._offset += self._ppf  # offset 偏移,ppf(pixels per frame) 每帧滚动的像素
        # 头节点滚出显示区
        if self._offset >= self.GetSize()[0] + self._extent[0]:
            self._offset = self._offset - self._extent[0] - self._gap_pixels
            self._show_text.pop(0)
            # 需要更新字符串尺寸
            self.UpdateExtent(wx.ClientDC(self))
        # 尾节点与显示区尾部相距超过指定间距
        if self._offset >= self._show_text_size[0] + self._gap_pixels and self._text:
            self._index = (self._index + 1) % len(self._text)
            self._show_text.append(self._text[self._index])
            self.UpdateExtent(wx.ClientDC(self))
        self.Refresh()

    def DrawText(self, dc):
        """绘制滚动文字"""
        dc.SetTextForeground(self.GetForegroundColour())
        dc.SetFont(self.GetFont())
        self.UpdateExtent(dc)
        if self._dir == "ltr":
            offx = self._offset - self._extent[0]
            fix_dir = -1
            fix_size = 1
        else:
            offx = self.GetSize()[0] - self._offset
            fix_dir = 1
            fix_size = 0
        offy = (self.GetSize()[1] - self._extent[1]) / 2
        for i, x in enumerate(self._show_text):
            dc.DrawText(x, int(offx), int(offy))
            if i < len(self._show_text) - 1:
                offx = offx + dc.GetTextExtent(self._show_text[i + fix_size])[0] * fix_dir + self._gap_pixels * fix_dir


class MyFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super(MyFrame, self).__init__(*args, **kwargs)
        self.Center()

        self.ticker = Ticker(parent=self, id=-1, text="你好,世界!Hello World!😍",
                             fgcolor="#ff0000", bgcolor="#ffff00", start=True,
                             ppf=2, fps=20, direction="rtl",
                             pos=wx.DefaultPosition, size=self.GetClientSize(), style=wx.NO_BORDER | wx.TRANSPARENT_WINDOW,
                             name="Ticker")
        self.ticker.SetFont(wx.Font(18, family=wx.SWISS, style=wx.NORMAL, weight=wx.BOLD, faceName=u"宋体"))
        self.ticker.SetGap(5)
        self.ticker.SetText("优快云")
        self.ticker.SetText("SmileBasic")
        self.ticker.Start()

        self.ticker.Bind(wx.EVT_RIGHT_UP, self.OnClose)
        self.ticker.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
        self.ticker.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
        self.ticker.Bind(wx.EVT_MOTION, self.OnMouseMove)

    def OnClose(self, event):
        self.Close()

    def OnLeftDown(self, evt):
        # CaptureMouse 把所有鼠标输入指向 self.ticker 控件窗口
        self.ticker.CaptureMouse()
        # ClientToScreen 把鼠标位置相对于程序窗口的坐标转换为相对于屏幕的坐标
        x, y = self.ClientToScreen(evt.GetPosition())
        originx, originy = self.GetPosition()
        dx = x - originx
        dy = y - originy
        self.delta = ((dx, dy))

    def OnLeftUp(self, evt):
        if self.ticker.HasCapture():
            self.ticker.ReleaseMouse()

    def OnMouseMove(self, evt):
        if evt.Dragging() and evt.LeftIsDown():
            x, y = self.ClientToScreen(evt.GetPosition())
            fp = (x - self.delta[0], y - self.delta[1])
            # Move 将窗口移动到指定坐标
            self.Move(fp)


class App(wx.App):
    def OnInit(self):
        frame = MyFrame(parent=None, size=(1075, 53), style=wx.NO_BORDER | wx.STAY_ON_TOP | wx.TRANSPARENT_WINDOW)
        frame.Show()
        return True

    def OnExit(self):
        return 0


if __name__ == "__main__":
    app = App()
    app.MainLoop()

修改

很明显,这样不断对列表 _show_text 头尾进行增删操作会造成资源浪费。另外,当 _text 存储超过数量时,也会陷入这种情况。

在某些场景下,我们需要频繁的对列表的头和尾进行操作,这时我们就可以使用双端队列collections.deque,这种数据结构被设计成能够在集合两端高效地增加和删除元素,在Python中,双端队列是以双向链表的方式实现的。来源:Python高性能计算之列表 https://zhuanlan.zhihu.com/p/342861939

但是使用索引读取时,列表时间复杂度是O(1),双端队列是O(n)。_text 需要频繁使用索引,不适合使用双端队列。

观察一下,_show_text 是 _text 中连续截取的元素,可以去掉,用头节点 索引 _index 和 显示数量 _num 代替。还有,字符串宽度一般是不变的,只在设置字体时会改变,可以在存储字符串的时候,把字符串尺寸也保存。
在这里插入图片描述

修改后源码:

# -*- coding: utf-8 -*-
# Author: SmileBasic
import wx
import wx.lib.ticker


class Ticker(wx.lib.ticker.Ticker):
    def __init__(self, *args, **kwargs):
        self._text = []  # 滚动字符串存储列表,格式[[字符串尺寸, 字符串], [(56, 22), "test"]]
        self._text_max = 500  # _text 最大可存储字符串数量
        self._gap = 0  # 滚动字符串之间间距
        self._gap_pixels = 0
        self._index = 0  # 显示字符串头节点
        self._num = 1  # 显示字符串数量
        self._dc = wx.MemoryDC()  # 用于获取文本尺寸
        super(Ticker, self).__init__(*args, **kwargs)

    def SetFont(self, font):
        """设置控件使用的字体"""
        wx.Control.SetFont(self, font)
        self._dc.SetFont(font)
        # 更新存储文本尺寸
        for text in self._text:
            text[0] = self._dc.GetTextExtent(text[1])

    def SetText(self, text):
        """将字符串插入滚动字符串列表尾部"""
        if text.strip():
            lens = len(self._text)
            if lens >= self._text_max:
                if self._index != 0:
                    self._text = self._text[self._index % lens:]
                    self._index = 0
                else:
                    self._text.pop(0)
            size = self._dc.GetTextExtent(text)
            self._text.append([size, text])
            self.Refresh()

    def SetGap(self, gap):
        """设置字符串显示间距"""
        self._gap = gap
        self._gap_pixels = self._dc.GetTextExtent(self._gap * " ")[0]

    def UpdateExtent(self, dc):
        """更新字符串尺寸"""
        pass

    def OnTick(self, evt):
        """更新滚动文字坐标"""
        if not self._text:
            return
        self._offset += self._ppf  # offset 偏移,ppf(pixels per frame) 每帧滚动的像素
        # 头节点滚出显示区
        w1 = self.GetSize()[0]
        w2 = self._text[self._index][0][0]
        if self._offset >= w1 + w2:
            self._offset = self._offset - w2 - self._gap_pixels
            self._index = (self._index + 1) % len(self._text)
            self._num -= 1
        # 尾节点与显示区尾部相距超过指定间距
        w3 = sum([self._text[i % len(self._text)][0][0] for i in range(self._index, self._index + self._num)])
        w3 = w3 + self._gap_pixels * self._num
        if self._offset >= w3:
            self._num += 1
        self.Refresh()

    def DrawText(self, dc):
        """绘制滚动文字"""
        if not self._text:
            return
        dc.SetTextForeground(self.GetForegroundColour())
        dc.SetFont(self.GetFont())
        if self._dir == "ltr":
            offx = self._offset - self._text[self._index][0][0]
            fix_dir = -1
            fix_size = 1
        else:
            offx = self.GetSize()[0] - self._offset
            fix_dir = 1
            fix_size = 0
        lens = len(self._text)
        for i in range(self._index, self._index + self._num):
            offy = (self.GetSize()[1] - self._text[i % lens][0][1]) / 2
            dc.DrawText(self._text[i % lens][1], int(offx), int(offy))
            if i < self._index + self._num - 1:
                offx = offx + self._text[(i + fix_size) % lens][0][0] * fix_dir + self._gap_pixels * fix_dir


class MyFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super(MyFrame, self).__init__(*args, **kwargs)
        self.Center()

        self.ticker = Ticker(parent=self, id=-1, text="你好,世界!Hello World!😍",
                             fgcolor="#ff0000", bgcolor="#ffff00", start=True,
                             ppf=2, fps=20, direction="rtl",
                             pos=wx.DefaultPosition, size=self.GetClientSize(), style=wx.NO_BORDER | wx.TRANSPARENT_WINDOW,
                             name="Ticker")
        self.ticker.SetFont(wx.Font(18, family=wx.SWISS, style=wx.NORMAL, weight=wx.BOLD, faceName=u"宋体"))
        self.ticker.SetGap(5)
        self.ticker.SetText("优快云")
        self.ticker.SetText("SmileBasic")
        self.ticker.Start()

        self.ticker.Bind(wx.EVT_RIGHT_UP, self.OnClose)
        self.ticker.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
        self.ticker.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
        self.ticker.Bind(wx.EVT_MOTION, self.OnMouseMove)

    def OnClose(self, event):
        self.Close()

    def OnLeftDown(self, evt):
        # CaptureMouse 把所有鼠标输入指向 self.ticker 控件窗口
        self.ticker.CaptureMouse()
        # ClientToScreen 把鼠标位置相对于程序窗口的坐标转换为相对于屏幕的坐标
        x, y = self.ClientToScreen(evt.GetPosition())
        originx, originy = self.GetPosition()
        dx = x - originx
        dy = y - originy
        self.delta = ((dx, dy))

    def OnLeftUp(self, evt):
        if self.ticker.HasCapture():
            self.ticker.ReleaseMouse()

    def OnMouseMove(self, evt):
        if evt.Dragging() and evt.LeftIsDown():
            x, y = self.ClientToScreen(evt.GetPosition())
            fp = (x - self.delta[0], y - self.delta[1])
            # Move 将窗口移动到指定坐标
            self.Move(fp)


class App(wx.App):
    def OnInit(self):
        frame = MyFrame(parent=None, size=(1075, 53), style=wx.NO_BORDER | wx.STAY_ON_TOP | wx.TRANSPARENT_WINDOW)
        frame.Show()
        return True

    def OnExit(self):
        return 0


if __name__ == "__main__":
    app = App()
    app.MainLoop()

Box2D-Lite源码阅读笔记(2) 0.初始化函数 static void InitDemo(int index) { world.Clear(); numBodies = 0; numJoints = 0; bomb = NULL; demoIndex = index; demos[index](bodies, joints); } 在这个初始化函数中,一般会默认执行index=0的函数,这个函数就是一个示例,因为示例比较简单,所以也便于研究,示例效果如下。 就是一个方块。 进入第一个示例函数。(忽略我加的注释) 阅读详情

相关推荐

Hi3516CV610开发板实战:从零搭建智能视觉监控系统

本文详细介绍了从零开始基于Hi3516CV610开发板搭建智能视觉监控系统的完整实战流程。涵盖硬件连接、系统配置、摄像头集成、网络设置、固件烧录到视频处理与智能分析功能开发,提供了丰富的实践经验和调试技巧,帮助开发者快速掌握嵌入式视觉系统开发。

vvv99的博客 565

wxPython:调用OCR模块实现图片识别

(读者电脑中应安装有Canopy) 先下载tesseract-ocr模块: 将其安装在Canopy那个盘。 安装了之后,下载代码:pytesser_v0.0.1.zip 将代码解压至......\Canopy\User\Lib\site-packages 然后在Canopy内运行pytesser.py即可。 注意:要将代码中11,237,301,311行的路径修改成读者本机路径。

每天都要进步哦~ 1377

win10安装openvpn客户端

进入C:\Program Files\TAP-Windows\bin目录,然后右键用管理员权限执行addtap.bat文件,此文件执行会创建一个网卡。链接:https://pan.baidu.com/s/1KAifTiP7qp1i5ZkfdnfwkA。4.2 进入安装目录的config下新建一个文件夹,将证书文件全部挪进去(不移动.ovpn文件)3.4 将拿到的ssl认证文件放入安装目录的config目录下。然后修改ovpn文件 “./”代表当前路径,第二个链接重复。3.1 一直下一步到这里打上勾。

qq_36200932的博客 3万+

wxPython和pycairo练习记录6

这次想要实现障碍物。

SmileBasic的博客 330

Habitat安装全网最详细教程,手把手带你跑通example.py(全网唯一)

全网最详细具身智能仿真平台habitat的安装教程

shannanshouyin的博客 2758

ArcGIS Pro新手避坑:从OpenStreetMap导入路网到创建拓扑关系全流程

本文详细解析了ArcGIS Pro中从OpenStreetMap导入路网数据到创建拓扑关系的全流程,涵盖OSM数据特性、几何完整性检查、属性强化及拓扑关系构建等关键步骤。特别针对路网数据预处理、网络数据集配置和常见问题提供了实用解决方案,帮助GIS新手高效完成网络分析任务。

weixin_33670786的博客 514

wxPython和pycairo练习记录18

Font.py 中 Font 类居然继承 Spritesheet 类来加载字符对应图片,还和 Sprites 类的功能差不多,总感觉哪里不太对。基本都没法写测试啊,后面待完成的是声音、鼠标键盘输入、碰撞检测、实体和主要显示类:面板、关卡、菜单、暂停画面。Camera.py 摄像机,这里的功能是记录坐标,跟随实体移动坐标。

SmileBasic的博客 396

解决宿主机Ping不通虚拟机的问题

在使用虚拟机的过程中,我们常常会遇到宿主机和虚拟机之间无法相互通信的问题。具体来说,我们要查看虚拟机和宿主机的 IP 地址,然后尝试进行 Ping 测试。在某些情况下,我们可能发现 Ping 虚拟机不通,接下来我将分享如何解决这个问题。

howard2005的专栏 7万+

wxPython和pycairo练习记录17

按理说素材图片虽然是位图但因为是纯色,手动缩放显示都没问题,不知道为什么会这样,网上解释说是"Cairo 默认使用线性插值算法进行缩放操作,而线性插值会导致图像像素的颜色被平滑地混合,从而造成图像的模糊效果。不要当过程完美主义者,很容易自我攻击。素材中的 characters.gif,用 wx.Image 加载后,调用 GetAlpha 方法发现得到不正确的透明通道值,而且 HasAlpha 得到的结果是 False,因为没有正确解释透明通道数据,RGB 数据也错了,加载后整个图片都变成了粉色。

SmileBasic的博客 897

智算中心建设项目初步设计方案

本项目面向区级政府、智算中心及文旅从业者,聚焦某区智算中心一期建设,响应数字经济与智慧城市建设政策,推动文旅产业升级。遵循统筹规划、数据驱动原则,目标打造智慧文旅样板。建设内容涵盖云网数据底座(以租代建)、数据中台(全生命周期管理)、智慧文旅平台(含“一机游”电商)及气象监测等配套,采用前后端架构与低代码开发,强化三级等保与纵深防御,实现安全可控。方案融合多类资源目录,提供从设计到运营的完整技术支撑,助力区域智算与文旅深度融合。

cdfunlove的博客 111

【unity游戏开发入门到精通——通用篇】Post Processing 后处理插件Post-process Volume 和 Volume最全基础使用说明

之前我已经实现了不少后处理功能,本文其实就是将他们归类整理,以便更好的查找和理解。在Unity中,后处理(Post-Processing)是在相机所捕捉的图像上应用一些特殊效果的过程,后处理会让图像视觉效果更好(前提是做的好)。这些效果的范围有非常细微的颜色调整,也包括整体的美术风格的大修,可以让场景看起来更加真实或风格化,或者只是变得更好看。就像我们都会用手机拍照,但很多时候我们拍的原始的相片都打不到我们想要的效果。比如照片可能亮度不够,颜色不饱和或者对比度不好等。

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 7900

wxPython和pycairo练习记录10

一开始考虑不全面,后面写的时候就只有一个心思,烂代码,完成就好。代码创建控件实例是个痛苦的过程,因为做的基本都是重复的事,能用循环的最好写进循环,熟悉控件后推荐用 wxFromBuilder。

SmileBasic的博客 568

Python爬虫实战:如何抓取旅游论坛上的帖子、旅行攻略和评论内容

无论是知名的旅游网站,还是地方性的旅游讨论区,用户发布的旅行贴文、攻略和评论往往包含着大量的宝贵信息。本文将详细介绍如何使用Python编写一个爬虫,抓取旅游论坛上的帖子、旅行攻略和评论内容,涵盖从获取页面内容、解析数据到处理动态加载等各个方面的技术。从基本的请求和网页解析,到动态加载页面的处理,再到数据存储和反爬虫技巧,我们详细讲解了抓取旅游论坛数据的全过程。通过本文的介绍,你可以将所学的爬虫技术应用到其他类似的网站抓取任务中,为后续的数据分析、机器学习等任务提供丰富的数据源。在这种情况下,传统的。

2201_76125261的博客 1557

wxPython和pycairo练习记录2

因为要实现图像的显示和交互,今天添加两个基础的图像容器类。

SmileBasic的博客 971

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

wxPython和pycairo练习记录8

经过障碍物的编写,发现需要停止前进并重新梳理一下。1.新的检测项加入时,已经在向混乱发展。是时候用上封装变化的编程工具,用策略模式或状态模式重写。2.显示,在基类引入层级和优先级,不同层低层级先绘制,同层高优先级先绘制。3.范围的碰撞和本身的碰撞的作用顺序。还有像已经实现的碉堡,只有一个外层碰撞区域,如果要多加几层呢,最外层出现坦克,射速为1,再近一层射速为5,最近一层射速达到20。

SmileBasic的博客 387

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

wxPython和pycairo练习记录1

学习,分为学和习,学完了不练习,让大脑觉得不重要,会忘记。所以,我决定练习并记录 wxPython 和 pycairo 的代码编写,如果你也想试试请自行配置环境。wxPython官网:https://www.wxpython.org/pycairo官网:https://cairographics.org/pycairo/本机环境:WIN10因为没有相关完整项目经验,所以不能把全局都设计好,先从基本的迭代。...

SmileBasic的博客 283

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

wxPython和pycairo练习记录3

现在的感觉像是学武功的人,对着一本秘籍瞎练,没有师父,也没有参照,不知对错。之前写的有很多混乱的地方,比如主 fps 对对象 fps 的作用,比如 MovieClip 对象 surface 的宽高及对继承方法 GetWidth 的影响,等等没有影响现有结果的地方。唯一检验的标准是,实现出想要的效果。这次想实现的是,在四个角生成敌方坦克,自动行驶,相互碰撞转向。...

SmileBasic的博客 354

wxPython和pycairo练习记录9

想要实现的效果是,同时按下多个方向,无论松开或按下其他键,总是响应剩余最近按下的键,这里直接用列表存储处在按下状态的按键代码。测试 wxPython 按下多个方向后松开最近按下的,之前保持按住的会失效。那就不能靠按键直接改变坐标,只改变速度方向,然后坐标的计算移动交给定时器刷新。射击按键行为也交给定时器,只改变状态,不执行操作。效果看起来还不错。之后可以看到,坦克和砖墙碰撞时的回弹问题也没有了。...

SmileBasic的博客 449

wxPython和pycairo练习记录19

pygame.mixer.Channel 这里的声道和音频文件的声道含义不一样,这里的声道是指播放通道,0 为第一个声道。在 wxPython 中 wx.adv.Sound 只能播放 WAV 格式的文件,或者在 UI 中调用 wx.media.MediaCtrl 控件,但素材里的音频还有 OGG 格式的,没法用 wxPython 在后台播放。测试的时候,只有设置同步播放 wx.adv.SOUND_SYNC 才有声音,后面再修改,所有代码都完成了如果还是这样就再创建一个线程来播放声音。

SmileBasic的博客 1044

wxPython和pycairo练习记录13

之前虽然通过设置窗口样式去掉了标题栏,但是背景看起来还是有些碍眼。通过 SetTransparent 只能调整整体透明度,文字和背景都透明了。希望实现的效果是背景透明,而文字不透明。

SmileBasic的博客 560

wxPython和pycairo练习记录4

继续写碰撞检测。

SmileBasic的博客 306

wxPython和pycairo练习记录11

了解事件机制是学习 wxPython 绕不过去的坎,结合各种资料和个人理解整理了一下,如果有问题请留言指出。

SmileBasic的博客 587

wxPython和pycairo练习记录14

继续之前的坦克游戏。碰撞检测技术像什么四叉树、凸包,看不懂啊,所以先从成熟的 pygame 框架里抠出几个能用到的。之前写坦克游戏并没有明确组合多个 Sprite 对象,还是先只考虑独立的 Sprite 吧。这样,需要用到和改写的方法只有 `collide_rect、collide_rect_ratio、collide_circle、collide_circle_ratio、collide_mask`。

SmileBasic的博客 263

wxPython和pycairo练习记录7

继续写障碍,选几个典型的来写。有个问题,有调用图片文件的类,每次生成新实例,都重新加载一次图片。应该把素材统一加载为全局变量,具体使用只需要引用素材变量。积重难返,记住这个教训,以后写其他的再注意吧。...

SmileBasic的博客 503

wxPython和pycairo练习记录15

像素:是指在由一个数字序列表示的图像中的一个最小单位,称为像素。这里的像素并非我们平时所说的眼睛看到的点,它更像是屏幕上的一个网格,不同的显示设备可能有不同大小的格子。在 Python 中,我们可以方便地通过一些库读取图像的某个像素值。这个例子中,返回的像素值是 RGBA 数值元组。

SmileBasic的博客 416

wxPython和pycairo练习记录5

先不管稀烂的坦克碰撞检测,开始添加武器系统。

SmileBasic的博客 232
上一篇: wordpress lnmp环境配置记录
下一篇: wxPython和pycairo练习记录13
SmileBasic
博客等级 码龄5年 347粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值