这一篇我们来讨论讨论牛。
牛的性状有:牛的初始位置,牛的速度,牛的强壮度,牛的血量。
牛的强壮度在直观表现上会体现出Cube的大小,同时也会影响减血的速度,越强壮,每秒减血的就越慢。
CowObject.class:
public class CowObject:GAObject { public float mStrongRate; public float mVelocity; public int mLife; public int mTempLife; public static Vector3 mpos_leftdown; public static Vector3 mpos_rightup; public float timer = 0.0f; public SimpleAI mGlassTarget = null; public float RoundTimer = 0.0f; public float EatTimer = 0.0f; public int lastTime = 0; public Vector3 RoundTarget = Vector3.zero; public override void Decode () { bool[][] mAllBitBunch = FreedomAIEncoderAndDecoder.BreakBitBunch (mbitbunch,mBreakPoint); string s = ""; mStrongRate = FreedomAIEncoderAndDecoder.BitBunch2float (mAllBitBunch[0],0.0f,1.0f); mVelocity = FreedomAIEncoderAndDecoder.BitBunch2float (mAllBitBunch[1],1.5f,6.0f); mLife = FreedomAIEncoderAndDecoder.BitBunch2int (mAllBitBunch[2],100,1000);mTempLife = mLife; float tx = FreedomAIEncoderAndDecoder.BitBunch2float (mAllBitBunch[3],0.0f,1.0f);tx = (mpos_rightup.x - mpos_leftdown.x) * tx + mpos_leftdown.x; float ty = FreedomAIEncoderAndDecoder.BitBunch2float (mAllBitBunch[4],0.0f,1.0f);ty = (mpos_rightup.y - mpos_leftdown.y) * ty + mpos_leftdown.y; float tz = FreedomAIEncoderAndDecoder.BitBunch2float (mAllBitBunch [5], 0.0f, 1.0f);tz = (mpos_rightup.z - mpos_leftdown.z) * tz + mpos_leftdown.z; mPosition = new Vector3 (tx,ty,tz); } public override void Encode () { bool[] tStrongRate_bit = FreedomAIEncoderAndDecoder.float2BitBunch (mStrongRate,0.0f,1.0f,10); bool[] tVelocity_bit = FreedomAIEncoderAndDecoder.float2BitBunch (mVelocity,1.5f,6.0f,10); bool[] tLife = FreedomAIEncoderAndDecoder.int2BitBunch (mLife,100,1000,10); bool[] mPosition_X = FreedomAIEncoderAndDecoder.float2BitBunch ((mPosition.x-mpos_leftdown.x)/(mpos_rightup.x-mpos_leftdown.x),0.0f,1.0f,11); bool[] mPosition_Y = FreedomAIEncoderAndDecoder.float2BitBunch ((mPosition.y-mpos_leftdown.y)/(mpos_rightup.y-mpos_leftdown.y),0.0f,1.0f,11); bool[] mPosition_Z = FreedomAIEncoderAndDecoder.float2BitBunch ((mPosition.z-mpos_leftdown.z)/(mpos_rightup.z-mpos_leftdown.z),0.0f,1.0f,11); mbitbunch = FreedomAIEncoderAndDecoder.JointBitBunch (tStrongRate_bit,tVelocity_bit,tLife,mPosition_X,mPosition_Y,mPosition_Z); } public override void InitBreakPoint () { mBreakPoint.Clear (); mBreakPoint.Add (10); mBreakPoint.Add (10); mBreakPoint.Add (10); mBreakPoint.Add (11); mBreakPoint.Add (11); mBreakPoint.Add (11); } public override float Evaluate () { return (float)mTempLife / (float)1000; } public override void RandomData () { System.Random srd = new System.Random (); mStrongRate = Random.Range (0.0f,1.0f); mVelocity = Random.Range (3.0f,6.5f); mLife = Random.Range (0,1000);mTempLife = mLife; mPosition = new Vector3 (); mPosition.x = Random.Range (mpos_leftdown.x,mpos_rightup.x); mPosition.y = Random.Range (mpos_leftdown.y,mpos_rightup.y); mPosition.z = Random.Range (mpos_leftdown.z,mpos_rightup.z); } public override string ToString () { return mStrongRate.ToString () + " " + mVelocity.ToString () + " " + mLife.ToString() + " " + mPosition.ToString(); } }
牛的行为会相对稍微复杂一些,牛有三种状态,一种是死亡,血量低于0就有消亡。第二种是巡逻,闲逛,吃饱了就会去闲逛。第三种是吃草,首先是对草的选择,会优先选择近的且高的草。
public class CowRunner:SimpleAIRunner { public void DoRun(SimpleAI sAI,string code) { string s = code; ((CowObject)sAI.mCharacter).timer += Time.deltaTime; if (((int)((CowObject)sAI.mCharacter).timer) - ((CowObject)sAI.mCharacter).lastTime > 0) { ((CowObject)sAI.mCharacter).mTempLife -= 30 + (int)(15*((CowObject)sAI.mCharacter).mStrongRate); ((CowObject)sAI.mCharacter).lastTime = ((int)((CowObject)sAI.mCharacter).timer); } if (code == "Die") { sAI.Destroy (); } else if (code == "Round") { ((CowObject)sAI.mCharacter).mGlassTarget = null; if (((CowObject)sAI.mCharacter).RoundTimer > 0.0f && (((CowObject)sAI.mCharacter)).RoundTarget != Vector3.zero) { float distance = Vector3.Distance(sAI.mAIRT.transform.position,((CowObject)sAI.mCharacter).RoundTarget); if (distance > 1.5f) { sAI.GetComponent<AIMove> ().mDirection = ((CowObject)sAI.mCharacter).RoundTarget - sAI.mAIRT.transform.position; sAI.GetComponent<AIMove> ().mDirection.y = 0.0f; sAI.GetComponent<AIMove> ().mVelocity = ((CowObject)sAI.mCharacter).mVelocity; } else { sAI.GetComponent<AIMove> ().mVelocity = 0.0f; } ((CowObject)sAI.mCharacter).RoundTimer -= Time.deltaTime; } else { ((CowObject)sAI.mCharacter).RoundTimer = 2.5f; ((CowObject)sAI.mCharacter).RoundTarget = sAI.GeneratePos + new Vector3 (Random.Range(-10,10),0,Random.Range(-10,10)); } } else { ((CowObject)sAI.mCharacter).RoundTarget = Vector3.zero; ((CowObject)sAI.mCharacter).RoundTimer = 0.0f; if (((CowObject)sAI.mCharacter).mGlassTarget == null||((CowObject)sAI.mCharacter).mGlassTarget.mAIRT==null) { SimpleAI[] SimpleAIs = SimpleAISetSingleton.getInstance ().GetComponent<SimpleAISet> ().FindAIsWithRiaus (sAI.mAIRT.transform.position,20.0f,1<<LayerMask.NameToLayer("Default"),"Glass"); int startIndex = Random.Range (0,SimpleAIs.Length); for (int i = startIndex; i < SimpleAIs.Length; i++) { float f2 = ((glassObject)SimpleAIs [i].mCharacter).mHeight; f2 = (f2 - 1.0f) / 1.5f; if (Random.Range (0.0f, 1.0f) < f2) { ((CowObject)sAI.mCharacter).mGlassTarget = SimpleAIs [i]; break; } } s+="Finding"; } else { float distance = Vector3.Distance(sAI.mAIRT.transform.position,((CowObject)sAI.mCharacter).mGlassTarget.mAIRT.transform.position); if (distance>1.5f) { sAI.GetComponent<AIMove> ().mDirection = ((CowObject)sAI.mCharacter).mGlassTarget.mAIRT.transform.position - sAI.mAIRT.transform.position; sAI.GetComponent<AIMove> ().mDirection.y = 0.0f; sAI.GetComponent<AIMove> ().mVelocity = ((CowObject)sAI.mCharacter).mVelocity; } else { sAI.GetComponent<AIMove> ().mVelocity = 0.0f; if (((CowObject)sAI.mCharacter).EatTimer < 1.0f) { ((CowObject)sAI.mCharacter).EatTimer += Time.deltaTime; } else { ((CowObject)sAI.mCharacter).mTempLife += 40; ((CowObject)sAI.mCharacter).mTempLife = Mathf.Min (((CowObject)sAI.mCharacter).mTempLife,((CowObject)sAI.mCharacter).mLife); ((glassObject)((CowObject)sAI.mCharacter).mGlassTarget.mCharacter).mHp -= 40; } } } } } };
运行结果:
第一代:
第二代:
第三代:
我们可以注意到,首先是草的生长位置向左下偏移,草的高度,草的颜色偏接近矮绿,这是因为,绿的加血更多,活的更健康,高的更容易被吃掉,而右上的草里牛群近,也容易被吃掉,所以就进化出了这样的结果。
而我们可以把玩家当作这里的牛,不同的是,玩家的选择是不固定的,他可能选择砍任何位置的草,可能旋转砍任何颜色的草,可能选择砍任何高矮的草,也就是草进化空间是我们事先未设置好的由玩家做了什么来决定,也就是给到了玩家事先未设置好的游戏机制反馈。