×

使用8x8独角兽矩阵来显示人工生命形式的网格

消耗积分:0 | 格式:zip | 大小:0.00 MB | 2023-07-13

廉鼎琮

分享资料个

描述

之前...

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 的方式——之前的工作方式是:

  • 逻辑循环运行
  • 每个循环在显示器上写入一个实体位置以及 RGB 值
  • 在循环结束时,显示器立即写出并显示所有写入的位置和 RGB 值

当事情运行顺利时,它工作得很好;但是循环开始运行缓慢的运动,即任何低于每秒 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,可以从看起来像恶魔城游戏背景的静止列中制作出各种很酷的图案,或者可以产生看起来像雨等的移动图案。

pYYBAGSBS2yAPm3MAAJIXm3TEGM618.png
 

还有支柱:

pYYBAGSBS2-AELb1AAId9RlxT-w533.png
 

还如前所述 - 它现在使用浮点数来表示颜色,这基本上允许进行 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 打包在一起,即便如此,该功能仍需要大量工作和改进,这是未来将要研究的内容。

我还添加了:

  • 可开采资源,在棋盘上被视为红色方块,包含大量可以开采的“资源”,从中开采的生命体可以保留资源并用它们建造城墙
  • 可以由生命形式建造的墙将保持静止,除非足够强大的生命形式将它们击倒并获得资源,这些墙也需要资源来建造;这样生命形式就可以推倒墙壁并从收集到的资源中建造新的墙壁。如果它们不够坚固,它们会从墙上弹开
  • 添加了额外的动量和弹跳力,因此当重力打开并且生命形式从某物上反弹时,动量将被考虑在内,动量也会从一种生命形式转移到另一种
  • 此外,我还对生命形式在尝试改变方向之前可以移动多远进行了一些更改,以确保它们可以在棋盘空间内移动,而不是仅仅不断地从墙上弹开,因为它们移动变量的时间设置得太高了
  • 辐射,影响生命形式的生存时间以及繁殖时随机 DNA 变化的机会
  • 生命形式繁殖的能力,然后等待它们周围的自由空间,所以你可以让一个人在没有空间的情况下产生新的生命形式,但是当有自由空间时,产生后代;这也适用于墙体建筑
  • 现在有一个 BaseEntity 类,生命形式、资源和墙壁用作超类;这意味着将来当我向模拟中添加更多东西时,我可以使用这个超类并在子类中必要时覆盖它
  • 如上所述,添加了键盘命令,例如能够引起 Thanos Snap 和随机擦除棋盘上 50% 的生命形式(由于 Pixel Composer,还具有很酷的淡入淡出效果)。还有能力提​​高/降低辐射、启用/禁用重力、冻结渲染和显示当前统计数据
  • 有一个重试功能,以便当所有生命形式都过期时模拟重新启动 - 我现在添加了一个会话开始日期时间戳,可以在统计数据中看到。因此,您可以将模拟打开一段时间然后再回来,查看当前会话持续了多长时间以及它是否仍然是您开始的原始会话
  • 在我尝试保存/加载模拟的当前状态的那一刻,代码中有一些 WIP 的东西,但事实证明这很耗时才能正常工作;这很可能会添加到下一个版本中,但请随时查看现有代码
  • 一种记忆系统,生命形式将在其中繁殖/挖掘/赢得战斗并记住发生的位置并尝试返回到该点。如果在该位置发生另一个事件,它将在该点的记忆数量上加 1,如果没有发生,它将在该点的记忆数量上减 1。他们总会回到记忆最积极的那个点。这是为了给生命体一些更有趣的运动行为。记忆也会传递给下一代生命体,除非他们‘叛逆’,然后他们从一个干净的记忆开始;这与“健忘”一起由生命形式的 DNA 决定
  • 还有一个'bad memories' dict 变量,目前未使用,但未来会有一个系统,生命形式将尝试避开发生过不好事情的区域
  • 将 HAT 控制器和 LED 面板控制器代码从屏幕输出代码分离到单独的模块中——这是为了允许更多的模块化添加额外的屏幕/LED 显示器,而无需更改主代码/Pixel Composer 中的任何内容,并且只有一个在屏幕控制器中实例化不同类的小改动

新的辐射系统在模拟中增加了另一层,辐射设置可以通过 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 - 导致生命形式受到的伤害。

使用以下参数,可以在首次运行时在随机位置生成许多墙和资源,以及可供生命形式开采的资源——为它们四处导航添加更多有趣的环境。

在这里你可以看到“采矿设施”,那里的生命形式群体记得采矿事件发生的地点,并试图回到那个地方;所以你会看到他们成群结队地坐在采矿资源周围,看到其他一些人在建造围墙周围飞来飞去。

poYBAGSBS3GAVOvoAAC1vrYWkLI334.png
 

还有一个设置可以让生命形式建造自己的墙以及一个倍增器——设置越高,生命形式建造墙的频率就越高。

walls = 0
resources = 0
entities_build_walls = True
wall_chance_multiplier = 512

An模拟开始时生成的一些墙的示例:

poYBAGSBS3WAX-I5AAA8q6-wIAw153.png
 

还有一整套参数,可以编辑以更改模拟中的各种内容,这些参数位于 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)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.obk20.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'使用8x8独角兽矩阵来显示人工生命形式的网格',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.obk20.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);