在上两篇js自定义事件介绍下,我尝试利用事件实验一个人与食物的游戏。
游戏规则:
1.人在饥饿值小于30时,需要进食,食物减少,饥饿值增加,当饥饿值达到100时饱和,开始工作。
2.人在工作时,饥饿值减少。
4.食物随着时间缓慢增长。
5.人饥饿值为0时死亡。
其实,刚开始时有点无从下手,代码虽然能看懂,但是理解不够到位。
1.接下来,我说说我对这个事件类的理解,先上我重写的事件类代码:
var $Event=function(){
this.handlers = {};
}
$Event.prototype = {
addHandler: function (type, handler) {
if (typeof this.handlers[type] == "undefined")
{
this.handlers[type] = [];
}
this.handlers[type].push(handler);
},
exe: function (event) {
if (typeof this.handlers[event.type] != "undefined")
{
for (var i = 0, len = this.handlers[event.type].length; i < len; i++) {
this.handlers[event.type][i](event);
}
}
},
removeHanlder: function (type, handler) {
if (typeof this.handlers[type] != "undefined") {
var handlers = this.handlers[type];
for (var i = 0, len = handlers.length; i < len; i++)
{
if (handlers[i] === handler)
{
this.handlers[type].splice(i, 1);
break;
}
}
}
}
}
{
manHungryChanged:[HungryChangedHandle,...],
foodNumberChanged:[...]
}
从面相对象角度分析,$Event是一个专门存储事件类型与该类型所绑定的方法的对象,该对象提供了三个原生方法addHandler,exe,removeHandler。
addHandler和removeHandler不用多说,大家都明白。exe中的event可能理解有点难,可以这样理解:exe方法体执行为触发某个事件的方法,那么则需告知触发的方法类型,以及触发回调事件所需的参数。如:
var EventParam =
{ type: "manHungryChanged", food: food, man: man };
类似这样的EventParam可作为event参数传入。
2.理解了事件类的作用,那么就可以开始考虑解决上边的游戏了。
首先游戏设计:人物对象,有两个持续性动作--工作和进食,当饥饿值变化时改变人物的动作状态。那么模型如下:
var Man = function () {
//Hungry代表饥饿度,0位饥饿,100为不饥饿
this.Hungry = 100;
this.event = new $Event();
this.Play = function (man) {
}
this.Eat = function (man) {
}
this.StopPlay = function (man) {
}
this.StopEat = function (man)
{
}
this.HungryChangedHandle = function (e) {
}
}
注意:如我这般初学者,一定要理解,处理事件的方法一定是当事件发生时刻所执行的方法,该方法影响主体对象接下来的持续性动作。所以当你很难判断对象中的哪个方法是处理事件的方法时一定要注意!
显然,上边我想用HungryChangedHandle来处理饥饿值改变事件。
食物对象,有两个持续性动作-自动增加食物和被进食,模型如下
var Food = function () {
//Number代表食物数量
this.Number = 0;
this.event = new $Event();
this.Product = function (food) {
}
this.Eated = function (food,number) {
}
}
创建好了两个对象,接下来应该完善方法体,代码如下
var Man = function () {
//Hungry代表饥饿度,0位饥饿,100为不饥饿
this.Hungry = 100;
this.event = new $Event();
this.Playid;
this.Eatid;
this.food = new Food();
this.Play = function (man) {
//玩的时候,饥饿值减少
document.write("开始玩工作...<br/>" );
this.Playid = setInterval(function () {
document.write("当前饥饿值:" + man.Hungry + "<br/>");
man.reduce(8, man.food, man);
}, 5000);
}
this.Eat = function (man) {
//吃的时候,饥饿增加
document.write("开始吃食物..." + "<br/>");
this.Eatid = setInterval(function () {
document.write("当前饥饿值:" + man.Hungry + "<br/>");
man.add(10, man.food, man);
}, 1000);
}
this.StopPlay = function (man) {
document.write("停止玩游戏..." + "<br/>");
clearInterval(man.Playid);
}
this.StopEat = function (man)
{
document.write("停止吃食物..." + "<br/>");
clearInterval(man.Eatid);
}
this.HungryChangedHandle = function (e) {
if (e.man.Hungry < 30 && e.food.Number > 0) {
document.write("饿了!当前饥饿值为:" + e.man.Hungry + ",当前食物数量为:" + e.food.Number + ",可以吃食物了。" + "<br/>");
e.man.StopPlay(e.man);
e.man.Eat(e.man);
e.food.Eated(e.food, 10);
return;
} else if (e.man.Hungry < 30 && e.food.Number <= 0) {
if (e.man.Hungry == 0)
{
document.write("死亡,游戏结束。");
e.man.StopEat(e.man);
e.man.StopPlay(e.man);
return;
}
document.write("好饿啊,没有食物了。");
}
if (e.food.Number <= 0 || e.man.Hungry >= 100)
{
document.write("吃好了,可以工作了。" + "<br/>");
e.man.StopEat(e.man);
e.man.Play(e.man);
return;
}
}
}
Man.prototype = {
add: function (number, food, man) {
this.Hungry += number;
this.Hungry = this.Hungry > 100 ? 100 : this.Hungry;
var EventParam = { type: "manHungryChanged", food: food, man: man };
this.event.exe(EventParam);
},
reduce: function (number, food, man) {
this.Hungry -= number;
this.Hungry = this.Hungry < 0 ? 0 : this.Hungry;
var EventParam = { type: "manHungryChanged", food: food, man: man };
this.event.exe(EventParam);
}
}
var Food = function () {
//Number代表食物数量
this.Number = 0;
this.event = new $Event();
this.Product = function (food) {
setInterval(function () {
food.add(3);
document.write("当前食物数量:" + food.Number + "<br/>");
}, 2000);
}
this.Eated = function (food,number) {
food.reduce(number);
document.write("当前食物数量:" + food.Number + "<br/>");
}
}
Food.prototype = {
add: function (number) {
//先添加食物,然后触发事件
this.Number+=number;
//EventParam,type为食物数量改变事件,Food为食物对象实例
var EventParam = { type: "foodNumberChanged" };
this.event.exe(EventParam);
},
reduce: function (number) {
//先减食物,然后触发事件
this.Number -= number;
this.Number = this.Number < 0 ? 0 : this.Number;
var EventParam = { type: "foodNumberChanged" };
this.event.exe(EventParam);
}
}
在Man对象和Food对象添加了几个原生方法,其实不用也可以。
3.现在对象和事件方法都写好了,接下来就该进行事件绑定和执行游戏了,代码如下:
<html>
<head>
<title>
</title>
</head>
<body>
</body>
</html>
<script type="text/javascript" src="Event.js"></script>
<script type="text/javascript" src="observer.js"></script>
<script type="text/javascript">
var Init = function () {
var man = new Man();
var food = new Food();
man.food = food;
man.event.addHandler("manHungryChanged", man.HungryChangedHandle);
food.event.addHandler("foodNumberChanged", function () { });
man.Play(man);
food.Product(food);
}
Init();
</script>
实验大概就是这样,初学者,代码漏洞多,大神请绕道,欢迎沟通。