2017 年,我做了一个名为“人工生命”的项目,该项目使用 8x8 独角兽矩阵来显示人工生命形式的网格,这些生命形式会相互繁殖和战斗。
2022 年,我将项目更新为Artificial Life HD——它使用了 16x16 Unicorn 矩阵以及增强代码、错误修复和一些额外功能。
因此,我们将在 2023 年与 64x32 LED 面板兼容,并通过人工生命 2 进行大量额外的错误修复、增强/添加功能和优化!
让我们开始吧。
这可以与Unicorn HAT 、Unicorn HAT HD或大型 LED 面板一起使用。
它还内置了一个Unicorn HAT 模拟器,因此它可以在没有 LED 硬件的情况下运行。
从我的 GitHub克隆 repo 代码:
git clone https://github.com/LordofBone/Artificial_Life --recurse-submodules
然后运行:
pip install -r requirements.txt
然后到这里安装 Unicorn HAT 。
对于此处的Unicorn HAT HD 安装。
最后,这里是 LED 面板安装。
通过我在 RPi OS Bullseye 64 位上找到的 LED 面板安装,我发现我还必须安装 Pillow 并更改 python 的调度权限:
pip install Pillow
sudo setcap 'cap_sys_nice=eip' /usr/bin/python3.9
然后可以运行模拟:
python artifical_life.py
默认情况下,这应该会启动一个 16x16 的模拟独角兽帽子。这与模拟的其他参数一起可以配置。
您可以通过设置来设置模拟 HAT 的自定义大小:
hat_model = "CUSTOM"
unicorn_simulator = True
hat_simulator_or_panel_size = x, y
尽管应该注意模拟器中存在一个错误,该错误不允许 x 和 y 值彼此不同。
如果您安装了 Unicorn HAT,您可以更改参数:
hat_model = "HD"
对于 Unicorn HD:
hat_model = "HD"
独角兽帽子迷你:
hat_model = "MINI"
LED面板:
hat_model = "PANEL"
Unicorn HAT 很可能需要以超级用户身份运行模拟:
sudo python artificial_life.py
这些也都可以通过 args 传递——查看所有可用的 args(下面也提供完整的 args 列表):
python artificial_life.py -h
保持像素沉着:
我完全重新设计了将生命体写入屏幕/面板/独角兽 HAT 的方式——之前的工作方式是:
当事情运行顺利时,它工作得很好;但是循环开始运行缓慢的运动,即任何低于每秒 10 帧的运动,显示将变得难以看到每个单独实体的实际情况,因为整个屏幕会立即改变。
现在有一个完全不同的子模块与主程序一起检出:Pixel Composer 。
注意:使用 Pixel Composer 更改值时请小心,它可能会导致闪光,尤其是在非常明亮的 LED 面板上。
这由现在被写入包含它们的位置和颜色的“世界空间”字典的实体起作用(现在保存为 R、G、B 的浮点值而不是 0-255),然后将其复制到“渲染平面”中' 在 Pixel Composer 中,然后异步运行以将渲染平面中当前的内容显示到帧缓冲区,然后将其写出到屏幕。
从本质上讲,这意味着不必等待整个过程循环完成才显示出来,每个生命形式的位置将在显示上同时移动,同时它们在所有生命形式的循环中移动——即使整个循环需要 10 秒来处理所有事情,您仍然能够清楚地看到生命形式的每一个动作,而不是每一个都同时移动。
最重要的是,这还允许一些很酷的额外效果,例如运动模糊、照明和背景着色器,例如雨效果和其他类似的时髦东西。
还有全屏着色器——我无意中发现它允许通过传递一个数字来显示各种很酷的图案:
class FullScreenPatternShader(ConfigurableShaderSuper):
def __init__(self, count_number=0, count_number_max=32, count_number_step_up=1, count_number_step_down=1,
addition_shader=True, invert_count=True, shader_colour=(0.5, 0.5, 0.5)):
super().__init__(count_number, count_number_max, count_number_step_up, count_number_step_down, addition_shader,
invert_count, shader_colour)
# found this accidentally; I am not entirely sure how this works, but changing the max number that can be stepped
# to will result in various cool effects as well as plus/minus stepping and whether the stepping will reset
# when maxed or count back the other way
def run_shader(self, pixel):
if self.addition_shader:
self.number_count_step_plus()
else:
self.number_count_step_minus()
pixel_alpha = (self.count_number / self.count_number_max) * self.max_float
shaded_colour = self.blend_colour_alpha(pixel, self.shader_colour, pixel_alpha)
return shaded_colour
通过更改count_number_max变量和 shader_colour,可以从看起来像恶魔城游戏背景的静止列中制作出各种很酷的图案,或者可以产生看起来像雨等的移动图案。
还有支柱:
还如前所述 - 它现在使用浮点数来表示颜色,这基本上允许进行 HDR 渲染;例如光照着色器;仅限于计算 0-255 范围内的照明效果效果不佳。在此处和此处详细了解为什么会发生这种情况。我想我的实现与正确的实现相比有很大的缺陷和简单,但它至少允许更好的颜色/照明模型。
这些浮点值被色调映射到 0-1 范围内,并最终从浮点变为 RGB,以最终输出到屏幕/LED。这给了它一些非常漂亮的颜色,并允许单独设置亮度 - 总的来说它看起来更漂亮。
所有这些设置都可以修改并添加到 artificial_life.py 代码本身,覆盖 rasterizer.py 文件中的类
现在可以按下 Shift + F 来暂停和取消暂停渲染,而逻辑在后台继续进行。
Shift + G 还将在模拟期间启用/禁用重力。
Thanos 捕捉现在通过 Shift + T 激活,这是一种随机移除棋盘上 50% 生命形式的快速方法。
未来的迭代将添加更多命令。
它是作为一个单独的子模块制作的,因为我认为这对其他项目很有帮助,所以我可能会在某个时候为此单独写一篇文章,进一步详细说明和修改,以使其更容易集成到其他项目中。
有一种方法可以绕过 Pixel Composer,通过将 -ff 参数传递到 artificial_life.py 主代码或进入配置/参数并设置:
fixed_function = True
这将运行得更快,但看起来不那么漂亮。一旦它们被处理,它将立即保持生命形式的运动——然而,不必等待所有生命形式循环处理。
现在还可以通过按 Shift + S 显示当前统计数据,这也将显示当前模拟的开始时间。
即使在 8x8 Unicorn HAT 上,原始 AL 代码也可能变得非常缓慢和滞后,通过一系列优化,我能够添加功能并使其即使在 16x16 板上运行也更加流畅。现在已经进行了进一步的优化,以允许在 64x32 板上更快地运行并具有新功能。
一个主要的优化是改变碰撞/生成代码的工作方式,以前这是通过以下方式工作的:
这行得通,但它意味着处理可能会在一个生命形式上保留相当长的一段时间,因为所有主要方向都被搜索以寻找一个可以移动到的自由位置。当生命体聚集在一个角落里都在寻找周围的无碰撞区域时,这会导致一些延迟。这也类似于寻找新的位置来产生新的生命体。
所以我改变了它,以便将碰撞重新检查推送到循环的下一次迭代。这样一来,无论生命形式如何聚集,它都不必在每个循环中检查它周围的所有方向,这会导致速度减慢,因为每个生命形式都会在屏幕上的所有生命形式的循环中占用处理时间。
所以现在它像这样工作:
这意味着循环将继续并且其他生命形式将被处理,从而很好地加快速度并导致更平滑的运动,同时还保持生命形式碰撞和弹开屏幕/其他物体边缘的能力。反弹功能在功能上是相同的,而且运行速度更快。凉爽的。
此外,我还使 DNA 混沌代码更加高效,以便在繁殖另一种生命形式时,来自任何一种生命形式的 DNA 仍然是父生命形式的混合体,但希望运行速度更快的代码,从而减少非常繁忙区域的滞后。
我还尝试将尽可能多的代码移动到一个函数“进程”中,以尝试避免函数调用的时间损失——我相信函数调用可以加起来,并且在这样的程序中,任何时候都可以进行生命形式处理越快越好——虽然我对这件事可能是错的,但到目前为止,连同其他优化,这让事情运行得更好;特别是对于 64x32 板,它可以完全填充 2048 种生命形式,所有这些都需要处理。
我还删除了允许生命形式相互堆叠的设置(因此每个像素有多个生命形式),因为这既昂贵又缓慢,但如果我能找到更优化的方法,我可能会返回此功能。
Minecraft 模式也已被删除,因为 MC 似乎不再与 Raspberry Pi OS 打包在一起,即便如此,该功能仍需要大量工作和改进,这是未来将要研究的内容。
我还添加了:
新的辐射系统在模拟中增加了另一层,辐射设置可以通过 args 或通过 parameters.py 文件设置:
initial_dna_chaos_chance = 10
initial_radiation = 0
max_radiation = 90
change_of_base_radiation_chance = 0.001
radiation_dmg_multiplier = 1000
radiation_change = True
DNA 混沌变量设置在传递给生命形式后代时存在的 3 个 DNA 片段中随机创建新 DNA 的几率百分比。这现在也受到新辐射水平的影响,辐射越高,随机 DNA 传递的机会就越高——基于这个初始数字和辐射水平的函数。
可以设置最大和初始辐射 - 如果辐射变化处于活动状态,数字将在这两个设置之间随机选择。在模拟过程中,可以分别使用 Shift+R 和 R 增加和减少最大辐射。
如果随机更改辐射设置未打开,则这些键将调整当前辐射而不是最大值 - 在这两种设置下,当前辐射将在曲线内上下移动,根据当前水平给出一点点变化。
更改设置受更改机会变量的影响,在处理所有生命形式的每个循环中,辐射都会发生变化(保持在最大辐射变量设置范围内)的可能性百分比。
伤害倍数设置会影响辐射对生命形式造成的伤害程度;每次处理生命形式时,都会进行一次计算 - 没有辐射,生命形式的生命有 1 次起飞。但是,对于辐射,可以进行以下计算:
self.time_to_live_count -= percentage(current_session.radiation * args.radiation_dmg_multi, 1)
其中当前辐射乘以辐射伤害乘数并用作正常 1 伤害的百分比。例如:100 * 1000 的辐射导致百分比为 100000,默认百分比为 1000 - 导致生命形式受到的伤害。
使用以下参数,可以在首次运行时在随机位置生成许多墙和资源,以及可供生命形式开采的资源——为它们四处导航添加更多有趣的环境。
在这里你可以看到“采矿设施”,那里的生命形式群体记得采矿事件发生的地点,并试图回到那个地方;所以你会看到他们成群结队地坐在采矿资源周围,看到其他一些人在建造围墙周围飞来飞去。
还有一个设置可以让生命形式建造自己的墙以及一个倍增器——设置越高,生命形式建造墙的频率就越高。
walls = 0
resources = 0
entities_build_walls = True
wall_chance_multiplier = 512
An
模拟开始时生成的一些墙的示例:
还有一整套参数,可以编辑以更改模拟中的各种内容,这些参数位于 config/parameters.py 下:
max_trait_number = 1000000
initial_lifeforms_count = 10
population_limit = 50
max_enemy_factor = 8
logging_level = 'INFO'
initial_dna_chaos_chance = 10
initial_radiation = 0
max_radiation = 90
change_of_base_radiation_chance = 0.001
radiation_dmg_multiplier = 1000
retries_on = False
led_brightness = 0.3
hat_model = "HD"
hat_simulator_or_panel_size = 8, 8
hat_buffer_refresh_rate = 60
refresh_logic_link = True
fixed_function = False
unicorn_simulator = False
radiation_change = True
gravity_on = False
trails_on = False
combine_mode = True
walls = 0
resources = 0
entities_build_walls = True
wall_chance_multiplier = 512
所有这些也可以通过将 args 传递给程序来设置:
-m MAX_NUM, --max-num MAX_NUM
Maximum number possible for any entity traits
-ilc LIFE_FORM_TOTAL, --initial-lifeforms-count LIFE_FORM_TOTAL
Number of lifeforms to start with
-s LOOP_SPEED, --refresh-rate LOOP_SPEED
The refresh rate for the buffer processing, also sets
a maximum speed for the main loop processing, if sync
is enabled (this is to prevent the display falling
behind the logic loop)
-p POP_LIMIT, --population-limit POP_LIMIT
Limit of the population at any one time
-me MAX_ENEMY_FACTOR, --max-enemy-factor MAX_ENEMY_FACTOR
Factor that calculates into the maximum breed
threshold of an entity
-dc DNA_CHAOS_CHANCE, --dna-chaos DNA_CHAOS_CHANCE
Percentage chance of random DNA upon breeding of
entities
-shs CUSTOM_SIZE_SIMULATOR [CUSTOM_SIZE_SIMULATOR ...], --simulator-hat-size CUSTOM_SIZE_SIMULATOR [CUSTOM_SIZE_SIMULATOR ...]
Size of the simulator HAT in pixels; to use pass in
'-shs 16 16' for 16x16 pixels (x and y)
-c, --combine-mode Enables life forms to combine into bigger ones
-tr, --trails Stops the HAT from being cleared, resulting in trails
of entities
-g, --gravity Gravity enabled, still entities will fall to the floor
-rc, --radiation-change
Whether to adjust radiation levels across the
simulation or not
-w WALL_NUMBER, --walls WALL_NUMBER
Number of walls to randomly spawn that will block
entities
-rs RESOURCES_NUMBER, --resources RESOURCES_NUMBER
Number of resources to begin with that entities can
mine
-r RADIATION, --radiation RADIATION
Radiation enabled, will increase random mutation
chance and damage entities
-mr MAX_RADIATION, --max-radiation MAX_RADIATION
Maximum radiation level possible
-rm RADIATION_DMG_MULTI, --radiation-multi RADIATION_DMG_MULTI
Maximum radiation level possible
-rbc RADIATION_BASE_CHANGE_CHANCE, --radiation-base-change RADIATION_BASE_CHANGE_CHANCE
The percentage chance that the base radiation level
will change randomly.
-be, --building-entities
Whether lifeforms can build static blocks on the board
-wc WALL_CHANCE_MULTIPLIER, --wall-chance WALL_CHANCE_MULTIPLIER
Whether lifeforms can build static blocks on the board
-rt, --retry Whether the loop will automatically restart upon the
expiry of all entities
-sim, --unicorn-hat-sim
Whether to use the Unicorn HAT simulator or not
-hm {SD,HD,MINI,PANEL,CUSTOM}, --hat-model {SD,HD,MINI,PANEL,CUSTOM}
What type of HAT the program is using. CUSTOM only
works with Unicorn HAT Simulator
-l {CRITICAL,ERROR,WARNING,INFO,DEBUG,NOTSET}, --log-level {CRITICAL,ERROR,WARNING,INFO,DEBUG,NOTSET}
Logging level
-sl, --sync-logic Whether to sync the logic loop to the refresh rate of
the screen
-ff, --fixed-function
Whether to bypass pixel composer and use fixed
function for drawing (faster, less pretty)
允许完全自定义体验和更轻松地分发代码,而无需传递任何参数,同时还允许在必要时通过 args 快速命令行级别调整。
更有趣的运动
随着新的记忆系统的到位导致生命形式返回“奖励区域”,运动变得更加多样化,而不仅仅是最终变成半可预测的结束状态的随机模式,生命形式现在移动并以真正出乎意料的方式重新安排自己方法。
撞墙
当开始模拟有墙的地方时,它可以真正改变生命形式的移动位置,并可以形成单独的区域,在那里它们被隔离或必须在结构周围导航。
辐射 23
辐射系统为生命形式提供了另一个可选级别,因此现在随着辐射影响 DNA 的传递以及每种生命形式的寿命,模拟比以前更难预测。
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
全部0条评论
快来发表一下你的评论吧 !