分段#
在一个简单的游戏中,整个视区都用来显示游戏的“地图”。在更高级的游戏中,将此视口分成不同的“部分”并使用不同的用法是很正常的。显示和处理不同信息的区域。例如,你可以在顶部有一个菜单,在右边有一些信息面板,游戏主“屏幕”(“地图”)覆盖了视区的其余部分。
为了实现这种游戏逻辑的分离,您需要使用几个部分。一个 Section
是一种将一个 View
将空间分成更小的部分,然后每个部分将根据配置和占用的视图空间接收重定向的事件。节可以隔离原本打包在一起的代码 View
。这样,代码就会保持在它所属的位置,而不会与程序的其他部分的代码混合在一起。
通过配置 Section
您可以捕获某些事件,或者例如仅捕获键盘事件中的某些键。您还可以配置将哪些事件传播到其他底层部分,甚至传播到视图本身。
部分也可以是“模式”的,这意味着它们将首先捕获所有事件,但最后绘制,并且还将阻止其他视图接收 on_update
事件。
还要注意的是,如果在代码中不使用节,则不会发生任何变化。即使是 SectionManager
如果不添加横断面,则不会创建。
Key features of Sections:
将屏幕划分为逻辑组件(部分)。
事件调度:A
Section
将根据视图中占用的空间来捕获鼠标事件。此外,还将根据配置捕获键盘事件。阻止派单:A
Section
可以配置为防止调度捕获的事件或让事件流向下面的其他部分。事件捕获顺序:基于
Section
插入顺序您可以配置节捕获事件的顺序。绘制顺序:您可以配置绘制部分的顺序(部分可以重叠!)。
Section
“Enable”属性以显示或隐藏节。你可以用谷歌搜索这个。模态节:最后绘制但捕获所有事件并阻止其他节更新的节。
自动相机切换:当在不同的分区之间切换时,分区将尝试激活和停用摄像头。
Important: You don't need to cover 100% of the View with sections. Sections can work with the View as well. Also, Sections can overlap.
一个简单的例子#
没有使用节的小程序需要在 on_mouse_release
事件根据鼠标位置知道要执行的操作。
例如,如果鼠标位于地图的顶部,您可能想要执行某些操作,但如果鼠标位于其他位置,则可能需要执行其他操作。
这就是在不考虑部分的情况下的情况:
class MyView(arcade.View):
# ...
def on_mouse_release(x: int, y: int, *args, **kwargs):
if x > 700:
# click in the side
do_some_logic_when_side_clicking()
else:
# click on the game map
do_something_in_the_game_map()
这段代码可能并且经常变得很长,并且需要进行大量检查才能知道要做什么。
通过使用节,您可以改进此代码并自动执行此简单检查。
下面是使用小节时的样子:
class Map(arcade.Section):
# ...
def on_mouse_release(x: int, y: int, *args, **kwargs):
# clicks on the map are handled here
pass
class Side(arcade.Section):
# ...
def on_mouse_release(x: int, y: int, *args, **kwargs):
# clicks on the side of the screen are handled here
pass
class MyView(arcade.View):
def __init__(self, *args, **kwargs):
self.map_section = Map(0, 0, 700, self.window.height)
self.side_section = SideSpace(700, 0, 100, self.window.height)
self.add_section(self.map_section)
self.add_section(self.side_section)
# ...
如何使用节#
要使用节,您首先需要具有 View
。节视图而定,并由特殊的 SectionManager
内部 View
。别担心,99%的情况下您不需要与 SectionManager
。
要创建 Section
从继承开始 arcade.Section
。
基于 Section
配置您的分区将开始从视图接收事件 SectionManager
。一个 Section
是否将所有事件都作为 View
有喜欢的 on_draw
, on_update
, on_mouse_press
等
实例化时定义节的位置参数(左、下、宽、高)。这些是非常重要的属性 Section
:因为他们定义了事件捕获矩形区域。
对象的属性 Section
:
- position: (left, bottom, width, height) :
这是实例化
Section
。这一点非常重要,因为此矩形位置将决定鼠标相关事件的事件捕获空间。这也将帮助您确定类内部的空间,例如,当您想要绘制某些东西或计算坐标时。- name:
A
Section
可以有选择地获得一个名称,这样就更容易调试和索引What Section正在做什么。例如,当记录时,记录Section
在开头命名,这样您就可以从生成日志的位置进行引用。- accept_keyboard_keys:
This allows to tell if a
Section
can receive keyboard events (accept_keyboard_keys=False) or to tell which keyboard keys are captured in thisSection
(accept_keyboard_keys={arade.key.UP, arcade.key.DOWN})- accept_mouse_events:
This allows to tell if a
Section
can receive mouse events or which mouse events are accepted. For example: accept_mouse_events={'on_mouse_move'} means only mouse move events will be captured.- prevent_dispatch:
这告诉我们一个
Section
如果它应该阻止将某些事件调度到事件捕获流下游的其他部分。默认情况下,Section
将阻止调度所有已处理的事件。通过路过prevent_dispatch={'on_mouse_press'}
所有事件都将沿事件捕获流向下传播,但on_mouse_press
事件。请注意,传球prevent_dispatch=None
(缺省值)与通过prevent_dispatch={True}
这意味着“阻止所有事件”调度到其他部分。您还可以设置prevent_dispatch={False}
将所有事件分派到其他部分。- prevent_dispatch_view:
这允许告诉一个
Section
如果不应将事件(以及哪些事件)调度到基础View
。如果要在中执行某些操作,这将非常方便View
是否由另一个事件处理的代码Section
。默认情况下,Section
将阻止将所有已处理的事件调度到View
。请注意,传球prevent_dispatch=None
(缺省值)与通过prevent_dispatch={True}
这意味着“阻止所有事件”调度到视图。您还可以设置prevent_dispatch={False}
将所有事件分派到其他部分。 Also note that in order for the view to receive any event, ALL the sections need to allow the dispatch of that particular event. If at least one section prevents it, the event will not be delivered to the view.- local_mouse_coordinates:
如果为True,则分区鼠标事件将收到与分区尺寸和位置相关的x,y坐标分区(与屏幕无关)。 Note that although this seems very usefull, section local coordinates doesn't work with arcade collision methods. You can use Section ``get_xy_screen_relative`` to transform local mouse coordinates to screen coordinates that work with arcade collision methods
- enabled:
默认情况下,启用所有部分。这使我们可以判断这个粒子是否
Section
应启用或未启用。如果一个Section
未启用,它将不会捕获任何事件、绘制、更新等。它将作为它不存在。您可以随时启用和禁用部分,从而产生一些很酷的效果。请注意,设置此属性将触发该部分on_show_section
或on_hide_section
事件。- modal:
这将告诉
SectionManager
这件事Section
是模式化的。这意味着Section
将首先捕获所有事件,而不向基础部分或视图传递任何事件。此外,它将画在最后(在其他on_draw
呼叫)。启用模式时Section
将阻止所有其他分区接收on_update
事件。- draw_order:
这样就可以定义绘制顺序
Section
会有的。数字越小,这一部分就会越早抽签。当您有重叠的部分并且需要一些时,这是很方便的Section
画在另一个上面。默认情况下,将按照添加的顺序绘制节段(除了模式节段,无论最后绘制的是什么)。注意,这可以不同于事件捕获顺序或ON_UPDATE顺序,后者由SectionManager
。
其他便携设备 Section
属性:
BLOCK_UPDATES:如果为True,则该节将不包含
on_update
方法已调用。摄像机:这是用来装一个
arcade.Camera
但默认情况下,它是没有的。SectionManager会在需要时自动触发摄像头的使用。
很方便 Section
:方法:
Overlaps_With:这将告诉您另一个
Section
与这张重叠。MICUE_IS_ON_TOP:这将告诉我们,如果给定x,y坐标,则鼠标位于该部分的顶部。
Get_xy_Screen_Relative:从x,y部分坐标获取屏幕x,y坐标。
GET_XY_SECTION_Relative:从x,y屏幕坐标获取x,y部分坐标。
用一个例子说明配置和逻辑#
想象一个游戏,其中你有这样的基本组件:
800x600屏幕视区
一张游戏地图
屏幕顶部的菜单栏
右侧面板显示游戏中的数据
弹出消息(对话框)
使用此配置,您可以将此逻辑划分为具有某种配置的部分。
让我们看看此配置可能是什么样子:
import arcade
class Map(arcade.Section):
#... define all the section logic
class Menu(arcade.Section):
#... define all the section logic
class Panel(arcade.Section):
#... define all the section logic
class PopUp(arcade.Section):
def __init__(message, *args, **kwargs):
super().__init(*args, **kwargs)
self.message = message
# define draw logic, etc...
class MyView(arcade.View):
def __init__(self, *args, **kwargs):
self.map = Map(left=0, bottom=0, width=600, height=550,
name='Map', draw_order=2)
self.menu = Menu(left=0, bottom=550, width=800, height=50,
name='Menu', accept_keyboard_keys=False,
accept_mouse_events={'on_mouse_press'})
self.panel = Panel(left=600, bottom=0, width=200, height=550,
name='Panel', accept_keyboard_keys=False,
accept_mouse_events=False)
popup_left = (self.view.window.width // 2) - 200
popup_bottom = (self.view.window.height // 2) - 100
popup_width = 400
popup_height = 200
self.popup = PopUp(message='', popup_left, popup_bottom, popup_width,
popup_height, enabled=False, modal=True)
self.add_section(self.map)
self.add_section(self.menu)
self.add_section(self.panel)
self.add_section(self.popup)
def close():
self.popup.message = 'Are you sure you want to close the view?'
self.popup.enabled = True
让我们一步一步地走。首先,我们配置一个保存地图的Map部分。此部分将从左侧开始,底部=0,0,并且不会占据整个屏幕。Map事件处理程序不会处理发生在此坐标之外的鼠标事件。因此,Map只需要处理地图内部发生的事情。
其次,我们配置一个包含一些按钮的菜单部分。此菜单占据地图已离开的屏幕顶部空间。地图+菜单将占据100%的屏幕高度。菜单部分配置为不接收任何键盘事件,仅接收ON_MOUSE_PRESS事件,忽略所有其他类型的鼠标事件。
第三,面板也不会接收键盘事件。因此,Map是目前唯一处理键盘事件的工具。此外,面板中不允许发生任何鼠标事件。此面板仅用于显示数据。
对于最后一部分,请注意,我们定义了一个部分,它将首先被禁用,这就是模式。这一部分将呈现带有消息的内容。在调用视图的Close方法时使用该节。因为弹出窗口是一个模式节,当启用它时,它会呈现在所有内容的顶部。此外,所有其他节停止更新,所有事件都由模式节捕获。因此,简而言之,我们是在“阻止”弹出窗口之外的世界。
区段独有事件#
有几个属于部分的独特事件,它们的触发方式有某种特殊之处:
on_mouse_enter
和on_mouse_leave
:这些事件在两种情况下触发:当鼠标进入/离开视图时以及当
SectionManager
通过鼠标移动(或拖动)检测鼠标是否已进入/离开截面尺寸。
on_show_section
和on_hide_section
:只有在以下情况下才触发这些事件 is enabled 在某些情况下,必须知道:
在添加节或从
SectionManager
以及View
目前正在上映启用或禁用该部分时
当窗口调用时
on_show_view
或on_hide_view
科长#
在幕后,当节添加到 View
这个 SectionManager
是将处理所有事件而不是 View
它本身。
您可以访问 SectionManager
通过访问 View.section_manager
。请注意,如果不使用节,则不会使用或创建视图中的节管理器。
通常,您不需要使用 SectionManager
,但在某些情况下,您需要使用它。
您通常使用以下命令来添加部分 View.add_section
但同样的方法也存在于 SectionManager
。此外,您还拥有一个 remove_section
以及一个 clear_sections
方法。
你可以的 enable
或 disable
这个 SectionManager
一次完全启用或禁用所有部分。
中公开的一些其他功能。 SectionManager
喜欢 get_section_by_name
这也可能是有用的。查看API以了解这些内容。
还可以在中配置三个属性 SectionManager
有时是有用和重要的。
默认情况下, on_draw
, on_update
和 on_resize
是将始终在 View
在任何部门触发它们之前。这是默认设置,但您可以使用以下属性对其进行配置:
view_draw_first
view_update_first
view_resize_first
这三种工作方式都是相同的:
True(默认值),以在
View
在各部分之前。FALSE,因此它在
View
后各节有相应的方法。中不触发该事件。
View
完全没有。