游戏编程gist

  • 从源头去做事件通知 谁改变谁去通知 (并未避免初始化的问题)
  • 事件分发两种 异步和同步 同步可能出现连续触发导致诡异的调用层级,异步则可能需要更多的代码检查上下文
  • 客户端以服务端时间线为准,那如果时间线客户端先于服务端执行,不可避免的会碰到回滚的问题。但等待服务端时间线执行之后客户端再执行,延迟就会比较高。
  • 逻辑与表现分离,对表现来说可以多帧渲染不影响逻辑,对逻辑来说可以跨双端跑。
  • 为什么要有我的概念,因为网络游戏两者并不能算是对等实体,其他玩家行为是服务器转发来的合法数据,本地玩家行为是体验优先本地立即响应却不具有一致性的。
  • 数据热更要比代码热更来得更加方便,但依旧可能读取不一致的数据出错
  • 字面量不具有逻辑,逻辑交由上下文管理,因此是上下文无关的,可以方便在不同逻辑之间做交换
  • 字面量之间要做出区分,即需要传给逻辑后表现出多态行为,就得包含自解释数据
  • 编辑器编辑策划配置数据要么通过表格的语义来决定,要么就像编程一样通过“元数据”增加表达语义能力,来组织关系
  • 事件注册这种异步调用需要注意不同 Entity 上的使用,这种事件监听转换为单次的消息通知,然后自己分发事件监听可以避免异步逻辑
  • 组合 ~ 波粒二象性 组合机制
  • 继承 ~ 子类能在所有父类上下文中使用
  • Python 每一个函数都是一个多态,最好相同的名字有一致的语义,结构性子类型系统依赖于类型中隐式的模式,困难的是维护重要的隐式模式
  • Python 多重继承 可以用来解决冲突的问题,但更适合层次需要经常调整的逻辑,一次函数调用就像是走过一个协议栈
  • 注意代码(或系统上的)中的相互指涉以及自我指涉,逻辑上的不完备会导致死循环或者悖论导致错误
  1. 首先考虑目标是什么,这个目标会有什么性质,这些性质会约束原语语义,以及定下整个框架模型
  2. 团队人员需要统一概念,需要有相似的惯用法,这样代码沟通成本会降低
  3. 代码风格最后跟语言风格尽量一致,能最大的利用生态,而且就像顺着纹理下刀一样,会更省力

调度gist

对于实时性要求高的服务器:

  • 提前做 准备好做
  • 整理做 独立做(减少重复)
  • 慢慢做
  • 攒批做
  • 并行做 事务做 选择策略做
  • 不做了(择机再做)延迟做

Async

怎样好的异步编程?

阅读更多

const语义

执行一段非法C++代码时出现了问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>
using namespace std;
int main(void){
const int a = 1;
int *p = (int *) &a;
// cout << "Before:\n";
// cout << p << " " << &a << endl;
// cout << *p << " " << a << endl;
*p = 100;
// cout << "After:\n";
// cout << p << " " << &a << endl;
// cout << *p << " " << a << endl;
return 0;
}

输出为:

1
2
3
4
5
6
Before:
0x6ffe44 0x6ffe44
1 1
After:
0x6ffe44 0x6ffe44
100 1

地址&ap是相等的,然而a*p的值却不相同。原因在于C++编译器在编译时会采用一种叫做变量折叠的技术。

变量折叠:在编译器里进行语法分析的时候,将常量表达式计算求值,并用求得的值来替换表达式,放入常量表。

将上述代码转换为C语言之后,地址相同值不同的问题没有发生.

查询到这是种编译器优化之后,开启-O0依旧无法避免.

最后发现是因为C和C++的const实际执行的语义不同而引起的.

C语言中,const修饰变量将被放在.rodata段中,不代表是个常量,单纯意味着只读,是一种运行时const.

C++语言中,const修饰变量将在编译时直接将变量引用位置替换成对应常量,相当于具有类型保护的define,是一种编译期const.

在C和C++中,const变量确实会被上述代码所改变,但是C++在运行时改变const,再次读取的还是编译器符号表中的常量数据.

解决方法是在变量前加上volatile,volatile告诉编译器每次调用变量都需要从内存重新取值,从而解决问题.

参考

C++ 常量折叠问题的理解

Variably modified array at file scope

Coding

编程,将逻辑编码成机器的’灵魂’

阅读更多