位运算的定义:
通俗点说,位运算就是对一个整数在计算机中二进制进行操作。
位运算的原理是很简单的,百度百科里就能找到它的一些基本的用法,以及相关的运算符号。
大部分刚刚进入到游戏行业里的程序员,你问他什么叫位运算,他都懂,但实际中往往却不记得去使用它。
任何一个整数都可以用二进度的方式来表示的,不同类型的整数它的位数的长度也不一样,INT8或者char是由8个2进度位表示,INT16或者short是由16个2进度位表示,INT32是由32位状态位表示。
位运算在游戏中的应用
往往,在游戏开发中做位运算的时候,我关注的主要是某一位的值是0,还是1,而并不是去关注这个整数的值是多少。
比如:00100010,这个8位的整数从右到左,它的第一位为0,第二位为1,第三位为0,第六位为1。
怎么知道这个整数的某一位的值,怎样把一个整数的某一位由0变为1或由1变为0呢,看以下代码:
//检查state的第pos位是否为1 int bitCheck(int state, int pos) { return state & 1<< pos - 1; } //将state的第pos位的值设为1 int bitAdd(int state, int pos) { return state | (1 << (pos - 1)); } //将state的第pos位的值设为0 int bitDel(int state, int pos) { return state & (~(1 << (pos - 1))); }
位运算往往在游戏用来记录一些状态,一个32位的整数,就能记录32种状态,并且只需要一个int就够了。
例子:
假设一个NPC有以下几种状态,行走状态,站立状态,普通攻击状态,技能攻击状态,根据这个NPC的不同状态,客户端需要播放不同的动作。
很多同学马上联想到的是用枚举,然后就开始写代码,很快就把程序写好了。
这个时候,策划又提了一个新的需求,说攻击的时候可能会产生爆击,爆击的时候普通攻击和技能攻击都需要有不同的表现。
然后这个同学想了想,于是加了一个BOOL来记录这次攻击是否产生爆击,于是很快又把代码写好了。
策划又提一个需求,攻击的时候还有命中。
于是又加了一个BOOL来记录命中。
如果还有BUFF效果,这就坑爹了!
真的是大部分刚招进来的同学都是这么干的,一个模块万多个BOOL,关键很气人的是这些BOOL还用一个INT8的方式一个一个地发往客户端。
还遇到过这么干的,把攻击且爆击状态,技能攻击爆击状态,记录成一个新的枚举值。
解决方案:
用状态位来记录NPC的状态,一个8位的整数即可记录8种状态,16位,32位就可以记录更多的状态
//伪代码 #define STATE_ATTACK 1 //普通攻击 #define STATE_SKILL 2 //技能攻击 #define STATE_DODGE 3 //爆击 #define STATE_HIT 4 //命中 INT8 state = 0; //默认无任何状态 state = bitAdd(state,STATE_ATTACK); //发起普通攻击 state = bitAdd(state,STATE_HIT); //命中目标 state = bitAdd(state,STATE_DODGE); //产生爆击 if(bitCheck(state,STATE_HIT) == 0) //如果未命中目标 { }
位运算 与 类似枚举 的操作,主要的区别在于位运算可以用一个变量来记录多种状态共同存在的情况。
位运算在游戏开发领域是用到的很多的,比如在游戏中的奖励系统,游戏中有很多种奖励,每日登录,排位赛,竞技场,公会奖励,在线奖励,签到奖励等,策划需要每一种奖励可以领取的时候,客户端在相应的功能按钮都需要光效表现来引起玩家注意,让玩家知道某某奖励现在是可以领取的。我看到很多开发人员都是客户端把所有系统的数据都拿到了,然后再根据数据的相应情况来决定是否让这个按钮开启光效。其实我们只需要用一个整数,在服务器端算好每一种奖励是否可以被领取,客户端收到这个数据后,根据每一个状态的情况来开启相应的光效,让玩家点击进入相应的系统的时候,才去拿相应的数据。