安装环境
1 | yum install epel-release centos-release-scl scl-utils scl-utils-build |
查看完整列表(scl为源可更改)
1 | yum --disablerepo="*" --enablerepo="scl" list available |
搜索 安装
1 | yum --disablerepo="*" --enablerepo="scl" search **** |
我总觉得对你的爱很美
1 | yum install epel-release centos-release-scl scl-utils scl-utils-build |
1 | yum --disablerepo="*" --enablerepo="scl" list available |
1 | yum --disablerepo="*" --enablerepo="scl" search **** |
I’ve seen things you people wouldn’t believe.
我所见过的事物,你们人类绝对无法置信。
Attack ships on fire off the shoulder of Orion.
我目睹战船在猎户星座的端沿起火燃烧
I’ve watched c-beams glitter in the dark near the Tannhauser Gate.
我见过C射线 在唐怀瑟之门附近的黑暗中闪烁
All those … moments will be lost in time, like tears…in rain.
所有这些时刻 终将流逝在时光中
一如眼泪
消失在雨中
Time to die………
GLM默认使用右手坐标系,如果要改成默认左手坐标系,使用:
1 | GLM_FORCE_LEFT_HANDED |
<glm/trigonometric.hpp>
GLM_FUNC_DECL GLM_CONSTEXPR vec< L, T, Q > radians (vec< L, T, Q > const °rees)
将角度转化为弧度。
<glm/gtx/transform.hpp>
GLM_FUNC_DECL mat< 4, 4, T, Q > rotate (T angle, vec< 3, T, Q > const &v)
使用一个用弧度(radians)表示的角度(degrees),以及一个用3个标量(scalar)表示的坐标(axis),来构建一个4X4的旋转矩阵(rotate matrix)。
<glm/gtc/matrix_transform.hpp>
GLM_FUNC_DECL mat<4, 4, T, Q> lookAt (vec<3, T, Q> const &eye, vec<3, T, Q> const ¢er, vec<3, T, Q> const &up)
基于默认的偏手坐标系来构建一个给定视图矩阵(view matrix)的视角(look)
GLM_FUNC_DECL mat<4, 4, T, defaultp> perspective (T fovy, T aspect, T near, T far)
为一个对称透视图截锥(symmetric perspective-view frustum)创建矩阵,基于默认的偏手坐标系和默认的近剪裁面距离、远剪裁面距离
参数说明:
fovy 相机视角宽度
aspect 长宽比率
near 近面裁剪距离
far 远面裁剪距离
如果要修改默认的近/远剪裁面,使用:
GLM_FORCE_DEPTH_ZERO_TO_ONE
win32diskimager
把下载的镜像通过这个工具烧录到tf卡中
这里唯一要注意的是如果有多个U盘设备 要正确选择好
树莓派有一个集成的wifi和一个网络端口 默认情况下wifi的配置是ap热点并且处于关闭(系统第一次启动不插网线应该是打开状态)
因此要想让树莓派能连外网并且可以连ssh 至少有一个网卡连我们的电脑 另外一个网卡连外网路由器
这里使用的方法是先通过网线连接树莓派 然后开启wireless并且设置为sta客户端模式连外网
修改/etc/config/network 添加Wwan
1 | config interface 'Wwan' |
修改后如下:
1 | config interface 'loopback' |
修改/etc/config/wireless
默认为AP热点:
1 | config wifi-device 'radio0' |
修改为STA连接我们的wifi
1 | config wifi-device 'radio0' |
执行/etc/init.d/network restart重启网络服务
通过路由器的管理页面此时应当发现连接上了路由器
如果这一步存在问题 可以先设置disable ‘0’在不该AP mod类型的情况下看看作为ap热点模式是否能正常搜索到
ssh登录后尝试ping一下看看是否能正常连网
和上面不同 这个是用网线连接外网 ap热点保留
先用网线连接树莓派 修改wireless的disable为0 重启网络服务
需要重启树莓派
network
1 |
|
wireless
1 | config wifi-device 'radio0' |
1 | opkg update |
此时可以通过opkg list查看所有支持的包
手动安装可以opkg install 命令
这里推荐先安装luci web管理服务
1 | pokg install luci |
进入后台页面http://192.168.1.1/
账号root 密码空
设置主题为bootstrap
1 | opkg install fdisk |
安装完毕此时应该改还剩余80M空间
可以通过df -h
命令查看
通过命令fdisk -l
查看当前TF卡的挂载情况
对空闲硬盘进行分区
1 | fdisk /dev/mmcblk0 |
1 | opkg install kcptun-client |
编辑/etc/config/kcptun 进行配置
删除多余参数,修改关键option, 注意启用
1 | config client |
使用luci后台或者opkg安装:
1 | opkg install shadowsocks-libev-ss-local shadowsocks-libev-ss-rules shadowsocks-libev-ss-redir shadowsocks-libev-ss-tunnel shadowsocks-libev-config iptables-mod-conntrack-extra luci-app-shadowsocks-libev |
shadowsocks-libev-ss-local
shadowsocks-libev-ss-rules
shadowsocks-libev-ss-redir
shadowsocks-libev-ss-tunnel
shadowsocks-libev-config
iptables-mod-conntrack-extra
luci-app-shadowsocks-libev
此时启动了一个1080的ss端口连接服务器 (socks5端口)
点击Save&Apply进行保存
然后在本地电脑上使用chrome+switchyOmega新建一个socks5代理连接youtube进行测试 .
启用Local Instances ss_redir.hi 启用Redir Rules并更改Local-out default为forward
可能问题
检查IP转发
cat /proc/sys/net/ipv4/ip_forward
若为0
echo ‘net.ipv4.ip_forward = 1’ >> /etc/sysctl.conf
sysctl -p
可能问题 DNS污染
需要开启resole固定
以及转发
https://wangchujiang.com/linux-command/c/iptables.html
https://gist.github.com/wen-long/8644243
可能导致找不到wifi信号或者连上去后很快断开
修改/etc/config/system
1 | config system |
修改/etc/config/wireless
1 | option country 'CN' |
中国开放的5G频道为
36, 40, 44, 48, 52, 56, 60, 64, 149,153, 157, 161, 165
opkg安装iw iwinfo命令
通过iwinfo wlan0 ***
可以查看无线网卡的当前信息 以及支持的信号强度 模式等
例如通过iwinfo wlan0 htmodelist
可以查看支持的htmode
例如通过iwinfo wlan0 freqlist
可以查看支持的频段
通过iw list查看设备支持的工作模式
iw wlan0 info
iw phy0 info
iw reg get 获取频段和信道宽度
https://openwrt.org/docs/guide-user/network/wifi/basic#htmodethe_wi-fi_channel_width
HT20 High Throughput 20MHz, 802.11n
HT40 High Throughput 40MHz, 802.11n
HT40- High Throughput 40MHz, 802.11n, control channel is bellow extension channel.
HT40+ High Throughput 40MHz, 802.11n, control channel is above extension channel.
VHT20 Very High Throughput 20MHz, Supported by 802.11ac
VHT40 Very High Throughput 40MHz, Supported by 802.11ac
VHT80 Very High Throughput 80MHz, Supported by 802.11ac
VHT160 Very High Throughput 160MHz, Supported by 802.11ac
NOHT disables 11n
可能得组合
1 | config wifi-device 'radio0' |
1 | config wifi-device 'radio0' |
1 | config wifi-device 'radio0' |
如果安装的是快照版本 会有以下几个问题:
快照版本的好处是可以刷完TF卡后直接启动而不需要任何引导步骤(通常至少需要一个USB键盘和HDMI+显示器)
官方地址https://openwrt.org/
根据硬件下载
例如树莓派的分支可以再Brand分支中查找关键字Raspberry Pi
快速上手推荐直接安装镜像 即跳过系统安装部分直接启动就可以使用, 带来的问题是 一般我们使用的tf卡可能至少32G 但是烧录的镜像只能用到其中的几百M 需要利用工具进行额外的mount挂载.
这里有几个关键字 factory指的的是安装固件 sysupgrade是指的更新专用镜像文件 snapshots是快照镜像文件
1 | wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.25.2.tar.gz |
在之前的文章我比较全面的介绍了一个完整的resume机制的阐述, 也提到了一些开发成本和三方库移植的问题, 这篇文章主要介绍如何在共享内存上实现一套可动态扩容的通用内存分配器, 以及如何利用通用内存分配器进行三方库包括stl中容器类的快速resumable化.
通用动态内存分配器的实现可以很好的对共享内存RESUME机制进行一个补充, 例如可以简单的基于分配器实现stl的allocator, 从而直接得到resumable的vector, list, queue, map, multi_map, unorder_map等; 也可以简单的将一些本身就比较容易resumable化的三方库和算法替换其allocator来简单快速的完成移植工作而非重写他们. 例如常见的资源解析rapidxml 移动避免算法库rvo等 .
当然, 处理易用性和快速移植三方库这些优点外, 从项目角度考虑也有一些缺点需要关注并进行合理范围的使用.
相比静态内存机制下的resumable方案
较难估算内存峰值用量
内存安全性不如静态内存
static_list
; static_list<Buff, MAX_BUFF_SIZE> buffs;
Buff* act = &受击BUFF;
在受击结束时候在移除act; 这里虽然用到了指针 但是在使用的时候, static_list中所有的元素都在一个连续的静态内存区域内, 并且该指针可以通过偏移检测和bitmap计算是否是有效的obj指针, obj是不是有效的buff等, 并不会因为是指针出现越界访问问题. 定位一些内存访问相关的问题可能会更麻烦一些
性能相比静态方案一般会有性能上的损失, 动态内存的分配和回收有一个适配的成本开销.
长期运行可能有内存碎片问题
共享内存RESUME机制是指的: 通过将游戏状态数据保存在共享内存中, 当游戏进程crash后通过重启游戏服务器并attach已有的共享内存来恢复游戏状态, 以此达到玩家游戏体验在出现宕机时的连贯性, 提升游戏的容灾能力.
在web领域中, 业务和数据分离, 从而达成’业务无状态化’, 开发人员专注于业务本身, 状态数据的一致性问题和容灾问题转移到可以较为独立解决的数据存储领域, 这个领域有非常多的论文和解决方案, 以及成熟的服务等.
而对于游戏领域来说, 互联网成熟的解决的方案很难在这个地方应用, 当然 对于外围系统来说, 我们仍然可以按照互联网成熟的解决方案进行布局, 例如聊天系统, 好友系统, 邮件系统, 日志系统, 或者一些游戏中的公会系统等.
本文中所有内容默认都基于逻辑描述, 逻辑状态,逻辑处理的逻辑游戏世界, 纯本地表现类, 总是通过逻辑世界单向导出的渲染计算等, 均不在本篇文章讨论范畴.
在多人游戏或者基于CS网络模型的游戏中, 玩家所在的游戏世界并非全由本地生成和修改, 必须不断从服务器或者其他玩家获得最新的信息来完成游戏世界的共享体验, 在多人实时交互的游戏中, 相当于每个人都维护一个’完整世界’的副本, 并保证每个人维护的副本之间一致性和实时性, 不同游戏对副本的规模复杂度以及对一致性和实时性的要求不同, 并随着网络环境的变化在不同的历史时期下演化出了多种同步方案.
在所有的同步方案中, 有两种最基础也最常见的同步机制, 即状态同步和帧同步, 其基本机制和区别为:
帧同步: 泛指通过一致的初始状态, 一致的输入事件和一致的逻辑处理, 从而得到相同的计算结果来保证游戏世界副本的一致性的同步方案
该术语为泛指, 所有通过确定性算法,以保证输入一致来得出相同游戏流程结果的同步均可泛称为帧同步.
最早有对等网络的锁步同步, 发展为非对等网络的主机锁步同步, 再到后来的bucket同步以及现在比较流行的定时不等待乐观帧同步
锁步同步:
定时不等待:
这两种同步模型本质上并不冲突, 并且在细节上会相互补充优化, 常见的为在状态同步这种弱一致性框架下添加确定性演算来增加同步的准确性, 在确定性的帧同步下隔离出来部分状态进行优化增加流畅性, 从模型角度来说, 在复杂的同步需求中, 状态同步总是比帧同步有更多的扩展和调优空间, 典型的案例如UE4和UNITY中的DS服务器.
战斗属性属于战斗单位的简单数据字段, 提供基础的数据读写操作(相对于magic state而言).
在实践中 一般战斗属性还包含从配置文件中load数据, 一级战斗属性到二级战斗属性的封装, 以及按照功能,战斗单位层级的划分等.
字段表在设计上隶属于’接口层’这个概念, 简单直接, 易于访问和同步处理时目的.
在C++中 通常考虑用一块静态数组的内存来表示
A | A | A | A | A | A | A | A | A |
---|---|---|---|---|---|---|---|---|
字段名 | HP | MP | ATK | CRIT | RESIST CRIT | HIT RATE | MISS RATE | … |
转换类型 | INT | INT | INT | INT | INT | FLOAT | FLOAT | … |
这种字段表的设计有以下优点和特性:
对于一个大规模系统的建模 一定离不开常见的分类手段, 而分类要根据系统中的元素以及元素之间的关系来作为划分依据, 从而采用不同策略
技能系统中的配置以’技能’和’效果’作为完整的配置单位, 所有的技能和效果之间的关系则是多维的图的拓扑关系的, 例如:
眩晕BUFF: 禁止普通移动, 禁止常规技能释放,
定身BUFF: 禁止普通移动
金身BUFF: 禁止普通移动, 禁止所有技能释放, 不可被眩晕/禁止所有效果(受击, 伤害, debuff/buff等)
冰冻BUFF: 禁止普通移动, 禁止所有技能释放除了解控技能, 可能禁止受击
沉默BUFF: 禁止所有(部分)技能释放
无敌BUFF: 不接受任何伤害
霸体BUFF: 打断受击状态并免控
灯笼BUFF: 可困住霸体BUFF单位
解控技能: 接触被控状态但无法接触部分例如灯笼BUFF
净化技能: 移除DEBUFF
破盾技能: 移除带有指定盾效果的BUFF
致命一击: 突破所有防御包括部分无敌BUFF .
引导技能A: 可被强控技能打断
引导技能B: 可被移动取消
连招技能: 需要前置技能成功释放完成
千斤坠技能: 需要飞行状态可释放
几乎所有的技能和buff之间都需要定义好他们的交互关系, 包括依赖条件, 禁止状态, 打断逻辑, 替换规则, 触发节奏, 否则在不断的引入新的技能时, 很容易导致已有的系统出现局部甚至整体的错误流程和功能表现.
而作为一个灵动丰富的多样性的技能系统, 在具体的状态关系上往往不会是简单的禁止打断逻辑, 而是分梯度, 计数, 浮动值的不同而有不同的分支策略, 需要对这样的一个规模和结构复杂的系统进行井井有条的管理和维护, 则需要一套完善灵活的拆分理念和管理机制.