这是一个多人联网实时碰撞小游戏,因为这个比较简单所以就选择做这个。不过感觉好难搞啊,对于我来说搞了快要一年了!都快搞到放弃了。明天不知道能不能回一个包子钱。
真是让人期待啊
微信平台
头条,刚刚上线
##广告也打了,是时候讨论一下技术了或者与到的坑了
- 头条审核太慢,比较严格,一般一个星期最多给你审核两次(我的是这样),工作人员周末不上班,录屏功能必须要,交互提示也不能有bug
- 实时游戏数据传输问题,自己写了一个 MiniBuffer,应该算是模仿Protobuffer 的取名了,意喻微小的,微小的字节,希望在网络传输中不浪费一个字节。为什么不用Protobuffer,因为想优化到比Protobuffer更小更快。所以自己动手写了这个工具包。上上前端核心代码,大家看看就会明白了。
export enum ByteType {
Bool = 0,
Int8 = 1,
UInt8 = 2,
Int16 = 3,
UInt16 = 4,
Int32 = 5,
UInt32 = 6,
String = 9,
Object = 10,
//数组
BoolArray = 19,
Int8Array = 20,
UInt8Array = 21,
Int16Array = 23,
UInt16Array = 24,
Int32Array = 25,
UInt32Array = 26,
StringArray = 29,
ObjectArray = 30,
//新增int24
Int24 = 31,
UInt24 = 32,
Int24Array = 33,
UInt24Array = 34,
}
3.2 如何使用
/* 定义消息体类*/
@BtyeContract
export class MoveTop_SMsg implements ServerMsg {
/// <summary>
/// 服务器消息类型
/// </summary>
@ByteMember(0, ByteType.Uint8)
public ServerMsgType: ServerMsgType = ServerMsgType.MoveTop;
/// <summary>
/// 实体id
/// </summary>
@ByteMember(1, ByteType.Uint16)
public Id: number;
/// <summary>
/// 坐标 x
/// </summary>
@ByteMember(2, ByteType.Int16)
public PX: number;
/// <summary>
/// 坐标 y
/// </summary>
@ByteMember(3, ByteType.Int16)
public PY: number;
/// <summary>
/// 速度 x
/// </summary>
@ByteMember(4, ByteType.Int16)
public VX: number;
/// <summary>
/// 速度 y
/// </summary>
@ByteMember(5, ByteType.Int16)
public VY: number;
}
//具体消息
var msg=new MoveTop_SMsg();
msg.Id=100;
msg.PX=20;
.......
//写为 arraybuffer,
var arrayBuffer= Buffer.WirteObject(msg);
//从 arraybuffer 中读
var msg=Buffer.ReadObject<MoveTop_SMsg>(MoveTop_SMsg,arrayBuffer);
3.3 如何实现的
看看代码,主要是装饰器,然后就是对 DataView 的读写了,我就写的思路,写下面也是最核心的代码,剩下的就交给你自己思考了。
/**属性修饰
* ByteMember
* @param order
* @param type
*/
export function ByteMember(order: number, type: ByteType, fun: Function = null) {
return function (target: any, propertyKey: string) {
var byteInfo = new ByteInfo(propertyKey, order, type, fun)
var byteInfoArray = Buffer.ClassInfoMap.get(target.constructor.name);
if (!byteInfoArray) {
byteInfoArray = Array<ByteInfo>();
byteInfoArray.push(byteInfo);
Buffer.ClassInfoMap.set(target.constructor.name, byteInfoArray);
} else {
byteInfoArray.push(byteInfo);
byteInfoArray.sort((a, b) => a.Order - b.Order)//排序
}
}
}
/**类修饰
* 需要序列化的类的 标识
*/
export function BtyeContract(target: any) {
Buffer.ClassMap.set(target.name, target);
}
/**byte 类型
* 要写入的
*/
export class ByteInfo {
public Order: number;
public Type: ByteType;
public Function: Function;
public PropertyKey: string;
constructor(propertyKey: string, order: number, type: ByteType, fun: Function = null) {
this.PropertyKey = propertyKey;
this.Order = order;
this.Type = type;
this.Function = fun;
}
}
export class Buffer {
/**
* 名称与构造器
*/
public static ClassMap = new Map<string, Function>();
/**
* 名称与属性
*/
public static ClassInfoMap = new Map<string, Array<ByteInfo>>();
//#region read method
/**
* 从 buffer 中反射 出 一个 classType 实例
* @param classType
* @param buffer
*/
public static ReadObject<T>(classType: Function, buffer: ArrayBuffer): T {
var offSet = 0;
var object = new classType.prototype.constructor();//也可以 new (<any>classType())
var dataView = new DataView(buffer);
var byteInfoArray = Buffer.ClassInfoMap.get(classType.name);
for (let i = 0; i < byteInfoArray.length; i++) {
let byteInfo = byteInfoArray[i];
let byteLength = this.readProperty(dataView, offSet, byteInfo, object, byteInfo.PropertyKey);
offSet += byteLength;
}
return object;
}
//#region write method
public static WirteObject(obj: Object) {
var offSet = 0;
var cacheBuffer = new ArrayBuffer(128);
var dataView = new DataView(cacheBuffer);
var byteInfoArray = Buffer.ClassInfoMap.get(obj.constructor.name);
for (let i = 0; i < byteInfoArray.length; i++) {
let byteInfo = byteInfoArray[i];
let byteLength = this.writeProperty(dataView, offSet, byteInfo.Type, obj[byteInfo.PropertyKey]);
offSet += byteLength;
}
var buffer = cacheBuffer.slice(0, offSet);
return buffer;
}
剩下的就是对 各种属性 使用 dataview 读写了
.............