如何在 javascript 中创建具有不同变量的可重用函数
How to create a reusable function with different variables in javascript
我正在使用 javascript/html 开发游戏。我有很多按钮,它们都使用相同的功能,但它们内部的值不同。
我有 32 个按钮,这意味着 32 个功能,这些功能完全相同,只是它们使用不同的 variables/values。
我正在考虑使用 objects/arrays,并将一个函数放入一个对象中,然后重新使用它来更改其变量,但我不知道这是否可行,或者这是否是个好主意。
我对此还是个新手。这些按钮用于 "attack" 怪物,每个按钮都是不同的,即 "stats/health/damage"。
我的按钮名为 "attack1/attack2/",功能为 "attack1/attack2"。每次我想添加一个怪物时,我都会复制整个函数并更改它的值,这并不难,但考虑到我想更改伤害公式,我需要更改所有 32 个函数,这不是我想要做的。
我已经创建了一个对象,我使用数组在其中存储所有怪物数据。
最后,我的母语不是英语,如果您听不懂我的意思,请见谅。如果有任何方法可以帮助您更好地理解它,请告诉我。
谢谢
var monsterStats = {
killed: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
hp: [10, 30, 70, 130, 190, 280, 380, 500, 700, 900, 1300, 1600, 2200, 2600,
3000, 4000, 5000, 7000, 9000, 12000, 15000, 18000, 22000, 28000, 34000, 40000,
48000, 570000, 65000, 72000, 80000, 88000],
maxHp: [10, 30, 70, 130, 190, 280, 380, 500, 700, 900, 1300, 1600, 2200,
2600, 3000, 4000, 5000, 7000, 9000, 12000, 15000, 18000, 22000, 28000, 34000,
40000, 48000, 570000, 65000, 72000, 80000, 88000],
def: [0, 2, 4, 6, 9, 13, 18, 25, 30, 38, 45, 53, 65, 75, 88, 95, 120, 140,
170, 200, 220, 250, 300, 400, 500, 700, 1000, 1200, 2000, 2500, 3000],
minDmg: [2, 2, 4, 6, 9, 13, 18, 25, 32, 40, 50, 60, 75, 86, 96, 105, 140,
160, 200, 230, 260, 290, 350, 420, 500, 900, 1200, 1700, 2500, 3200, 4500,
6000],
maxDmg: [3, 5, 7, 10, 14, 19, 23, 30, 37, 45, 58, 67, 80, 92, 100, 110,
160, 185, 215, 250, 275, 320, 380, 550, 700, 1200, 1500, 2200, 3000, 4000,
5500, 8000],
baseExp:[5, 10, 30, 50, 90, 140, 190, 260, 340, 450, 560, 700, 810, 940,
1060, 1200, 1600, 2150, 2600, 3400, 5000, 7000, 10000, 15000, 23000, 35000,
70000, 120000, 180000, 290000, 430000, 680000, 1000000]
};
function attack(number) {
if (monsterStats.hp[0] >= 1) {
var damage = Math.floor(Math.random() * (maxdamage - mindamage + 1)) +
mindamage;
damage = Math.floor(damage - monsterStats.def[0] * 1.2);
if (damage > 1) {
monsterStats.hp[0] -= damage;
document.getElementById("hp1").innerHTML = monsterStats.hp[0];
Log("You deal " + damage + " <span style=\"color:blue\">damage</span>");
} else Log("<span style=\"color:blue\">Enemy block your attack! </span>");
var dmg = Math.floor(Math.random() * (monsterStats.maxDmg[0] - monsterStats.minDmg[0] + 1)) + monsterStats.minDmg[0];
dmg = Math.floor(dmg - defense * 1.2);
if (dmg > 1) {
health = health - dmg;
document.getElementById("health").innerHTML = health;
Log("Enemy hit you for " + dmg + " <span style=\"color:red\">damage</span>");
} else Log("<span style=\"color:green\">You blocked enemy attack! </span>");
if (health < 1) {
monsterStats.hp[0] = monsterStats.maxHp[0];
health = maxhealth;
document.getElementById("hp1").innerHTML = monsterStats.hp[0];
document.getElementById("health").innerHTML = health;
Log("<span style=\"color:blue\">You have lost!</span>");
}
if (monsterStats.hp[0] < 1) {
monsterStats.killed[0] = monsterStats.killed[0] + 1;
monsterStats.hp[0] = monsterStats.maxHp[0];
document.getElementById("hp1").innerHTML = monsterStats.hp[0];
document.getElementById("kills1").innerHTML = monsterStats.killed[0];
var expgain = monsterStats.baseExp[0] / (level / 5);
if (experience < maxexperience) {
experience = Math.floor(experience + expgain);
if (experience >= maxexperience) {
level += 1;
stats += 2;
experience = experience - maxexperience;
maxexperience = Math.floor(maxexperience * 1.2);
Log("You leveled up! Your current level is: " + level);
document.getElementById("maxexperience").innerHTML = maxexperience;
document.getElementById("level").innerHTML = level;
document.getElementById("stats").innerHTML = stats;
document.getElementById("experience").innerHTML = experience;
} else Log("You gain: " + Math.floor(expgain) + "experience!");
document.getElementById("experience").innerHTML = experience;
}
var goldLog = 0;
var golddrop = Math.floor((Math.random() * 100) + 1);
if (golddrop > 95) {
golddrop = Math.floor((Math.random() * 20) + 1);
gold = gold + golddrop;
Log("You loot: " + golddrop + "gold!");
document.getElementById("gold").innerHTML = gold;
} else if (golddrop >= 75) {
golddrop = Math.floor((Math.random() * 10) + 1);
gold = gold + golddrop;
Log("You loot: " + golddrop + "gold!");
document.getElementById("gold").innerHTML = gold;
} else if (golddrop >= 60) {
golddrop = Math.floor((Math.random() * 5) + 1);
gold = gold + golddrop;
Log("You loot: " + golddrop + "gold!");
document.getElementById("gold").innerHTML = gold;
}
"This is <span style=\"color:red\">RED</span> text.";
var itemdrop = Math.floor((Math.random() * 100) + 1);
if (itemdrop < 33) {
var fusiondrop = Math.floor((Math.random() * 100) + 1);
if (fusiondrop < 70) {
common = common + 1;
Log("You loot:<span style=\"color:grey\">Common</span> Fusion stone!");
document.getElementById("common").innerHTML = common;
} else if (fusiondrop <= 100) {
rare = rare + 1;
Log("You loot:<span style=\"color:blue\">Rare</span> Fusion stone!");
document.getElementById("rare").innerHTML = rare;
}
} else if (itemdrop < 66) {
var expdrop = Math.floor((Math.random() * 100) + 1);
if (expdrop < 70) {
commonexp = commonexp + 1;
Log("You loot:<span style=\"color:grey\">Common</span> Exp orb!");
document.getElementById("commonexp").innerHTML = commonexp;
} else if (expdrop <= 100) {
rareexp = rareexp + 1;
Log("You loot:<span style=\"color:blue\">Rare</span> Exp orb!");
document.getElementById("rareexp").innerHTML = rareexp;
}
} else {
var golddrop = Math.floor((Math.random() * 100) + 1);
if (golddrop < 70) {
commongold = commongold + 1;
Log("You loot:<span style=\"color:grey\">Common</span> Gold orb!");
document.getElementById("commongold").innerHTML = commongold;
} else if (golddrop <= 100) {
raregold = raregold + 1;
Log("You loot:<span style=\"color:blue\">Rare</span> Gold orb!");
document.getElementById("raregold").innerHTML = raregold;
}
}
}
}
}
那是代码的一部分,我使用这段代码 32 次。
假设您创建一个 Monster
"objects" 的数组,如下所示:
var Monsters = {
"foo": {"name":"Foo the foot", "hp":125, "power":3},
"bar": {"name":"Barbarian the bar", "hp":25, "power":9001}
};
您也可以编写按钮标记,这样每个按钮都可以与一个怪物相关联。例如:
<button rel="attack" data-monster_id="foo">Attack</button>
<button rel="attack" data-monster_id="bar">Attack</button>
现在,您可以 link 他们这样说:
var btns = document.querySelectorAll('button[rel="attack"]');
for (var i=0; i<btns.length; i++) {
this.addEventListener('click', function(){
attack(this.dataset.monster_id);
}, false);
}
最后,假设一个 attack
方法是这样的:
function attack(id) {
Monsters[id].hp -= currentDamage;
// whatever consequences the attack may have
}
希望这能给您带来灵感,祝您游戏顺利:)
不确定您的意思,但我认为使用 event delegation 可能有助于重用函数。在代码片段示例中,data-*
属性用于存储带有按钮的分数。此外,事件委托使您能够创建新按钮而无需分配新的处理程序。
document.querySelector('#testbuttons').addEventListener('click', testdemo);
document.querySelector('#testcreate').addEventListener('click', newbttn);
// handler for all buttons within div#testbutton
function testdemo(e) {
var from = e.target || e.srcElement
,score = from.getAttribute('data-score')
,kills = JSON.parse(from.getAttribute('data-kills'));
if (!score) { return true; }
Helpers.log2Screen('score clicked button: ', score,
', kills: <code>[', kills, ']</code>',
{clear: true});
}
function newbttn() {
var score = Math.floor(1+Math.random()*200);
document.querySelector('#testbuttons').innerHTML +=
'<br><button data-score="'+score+'" data-kills="[]">button '+score+'</button>';
Helpers.log2Screen('Created new button with score ', score, {clear: true});
}
button {
margin-top: 3px;
}
<!-- a few helpers -->
<script src="http://kooiinc.github.io/JSHelpers/Helpers-min.js"></script>
<div id="result"><p>Awaiting action ...</p></div>
<div id="testbuttons">
<button data-score="12" data-kills="[2,5,3]">bttn 12</button><br>
<button data-score="122" data-kills="[0,2,8]">bttn 122</button>
</div>
<button id="testcreate">create new button</button>
我想你正在寻找这样的东西:
function createAttack1(damage) {
return function() {
... Your attack1 logic using 'damage'
}
}
然后你可以用它来连接你的按钮:
button1.addEventListener("click", createAttack1(5));
button2.addEventListener("click", createAttack1(10));
button3.addEventListener("click", createAttack1(15));
这允许您重复使用相同的核心逻辑,同时拥有不同的统计数据,而不需要您一直在做的所有 copy/paste。
我正在使用 javascript/html 开发游戏。我有很多按钮,它们都使用相同的功能,但它们内部的值不同。
我有 32 个按钮,这意味着 32 个功能,这些功能完全相同,只是它们使用不同的 variables/values。
我正在考虑使用 objects/arrays,并将一个函数放入一个对象中,然后重新使用它来更改其变量,但我不知道这是否可行,或者这是否是个好主意。
我对此还是个新手。这些按钮用于 "attack" 怪物,每个按钮都是不同的,即 "stats/health/damage"。
我的按钮名为 "attack1/attack2/",功能为 "attack1/attack2"。每次我想添加一个怪物时,我都会复制整个函数并更改它的值,这并不难,但考虑到我想更改伤害公式,我需要更改所有 32 个函数,这不是我想要做的。
我已经创建了一个对象,我使用数组在其中存储所有怪物数据。
最后,我的母语不是英语,如果您听不懂我的意思,请见谅。如果有任何方法可以帮助您更好地理解它,请告诉我。
谢谢
var monsterStats = {
killed: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
hp: [10, 30, 70, 130, 190, 280, 380, 500, 700, 900, 1300, 1600, 2200, 2600,
3000, 4000, 5000, 7000, 9000, 12000, 15000, 18000, 22000, 28000, 34000, 40000,
48000, 570000, 65000, 72000, 80000, 88000],
maxHp: [10, 30, 70, 130, 190, 280, 380, 500, 700, 900, 1300, 1600, 2200,
2600, 3000, 4000, 5000, 7000, 9000, 12000, 15000, 18000, 22000, 28000, 34000,
40000, 48000, 570000, 65000, 72000, 80000, 88000],
def: [0, 2, 4, 6, 9, 13, 18, 25, 30, 38, 45, 53, 65, 75, 88, 95, 120, 140,
170, 200, 220, 250, 300, 400, 500, 700, 1000, 1200, 2000, 2500, 3000],
minDmg: [2, 2, 4, 6, 9, 13, 18, 25, 32, 40, 50, 60, 75, 86, 96, 105, 140,
160, 200, 230, 260, 290, 350, 420, 500, 900, 1200, 1700, 2500, 3200, 4500,
6000],
maxDmg: [3, 5, 7, 10, 14, 19, 23, 30, 37, 45, 58, 67, 80, 92, 100, 110,
160, 185, 215, 250, 275, 320, 380, 550, 700, 1200, 1500, 2200, 3000, 4000,
5500, 8000],
baseExp:[5, 10, 30, 50, 90, 140, 190, 260, 340, 450, 560, 700, 810, 940,
1060, 1200, 1600, 2150, 2600, 3400, 5000, 7000, 10000, 15000, 23000, 35000,
70000, 120000, 180000, 290000, 430000, 680000, 1000000]
};
function attack(number) {
if (monsterStats.hp[0] >= 1) {
var damage = Math.floor(Math.random() * (maxdamage - mindamage + 1)) +
mindamage;
damage = Math.floor(damage - monsterStats.def[0] * 1.2);
if (damage > 1) {
monsterStats.hp[0] -= damage;
document.getElementById("hp1").innerHTML = monsterStats.hp[0];
Log("You deal " + damage + " <span style=\"color:blue\">damage</span>");
} else Log("<span style=\"color:blue\">Enemy block your attack! </span>");
var dmg = Math.floor(Math.random() * (monsterStats.maxDmg[0] - monsterStats.minDmg[0] + 1)) + monsterStats.minDmg[0];
dmg = Math.floor(dmg - defense * 1.2);
if (dmg > 1) {
health = health - dmg;
document.getElementById("health").innerHTML = health;
Log("Enemy hit you for " + dmg + " <span style=\"color:red\">damage</span>");
} else Log("<span style=\"color:green\">You blocked enemy attack! </span>");
if (health < 1) {
monsterStats.hp[0] = monsterStats.maxHp[0];
health = maxhealth;
document.getElementById("hp1").innerHTML = monsterStats.hp[0];
document.getElementById("health").innerHTML = health;
Log("<span style=\"color:blue\">You have lost!</span>");
}
if (monsterStats.hp[0] < 1) {
monsterStats.killed[0] = monsterStats.killed[0] + 1;
monsterStats.hp[0] = monsterStats.maxHp[0];
document.getElementById("hp1").innerHTML = monsterStats.hp[0];
document.getElementById("kills1").innerHTML = monsterStats.killed[0];
var expgain = monsterStats.baseExp[0] / (level / 5);
if (experience < maxexperience) {
experience = Math.floor(experience + expgain);
if (experience >= maxexperience) {
level += 1;
stats += 2;
experience = experience - maxexperience;
maxexperience = Math.floor(maxexperience * 1.2);
Log("You leveled up! Your current level is: " + level);
document.getElementById("maxexperience").innerHTML = maxexperience;
document.getElementById("level").innerHTML = level;
document.getElementById("stats").innerHTML = stats;
document.getElementById("experience").innerHTML = experience;
} else Log("You gain: " + Math.floor(expgain) + "experience!");
document.getElementById("experience").innerHTML = experience;
}
var goldLog = 0;
var golddrop = Math.floor((Math.random() * 100) + 1);
if (golddrop > 95) {
golddrop = Math.floor((Math.random() * 20) + 1);
gold = gold + golddrop;
Log("You loot: " + golddrop + "gold!");
document.getElementById("gold").innerHTML = gold;
} else if (golddrop >= 75) {
golddrop = Math.floor((Math.random() * 10) + 1);
gold = gold + golddrop;
Log("You loot: " + golddrop + "gold!");
document.getElementById("gold").innerHTML = gold;
} else if (golddrop >= 60) {
golddrop = Math.floor((Math.random() * 5) + 1);
gold = gold + golddrop;
Log("You loot: " + golddrop + "gold!");
document.getElementById("gold").innerHTML = gold;
}
"This is <span style=\"color:red\">RED</span> text.";
var itemdrop = Math.floor((Math.random() * 100) + 1);
if (itemdrop < 33) {
var fusiondrop = Math.floor((Math.random() * 100) + 1);
if (fusiondrop < 70) {
common = common + 1;
Log("You loot:<span style=\"color:grey\">Common</span> Fusion stone!");
document.getElementById("common").innerHTML = common;
} else if (fusiondrop <= 100) {
rare = rare + 1;
Log("You loot:<span style=\"color:blue\">Rare</span> Fusion stone!");
document.getElementById("rare").innerHTML = rare;
}
} else if (itemdrop < 66) {
var expdrop = Math.floor((Math.random() * 100) + 1);
if (expdrop < 70) {
commonexp = commonexp + 1;
Log("You loot:<span style=\"color:grey\">Common</span> Exp orb!");
document.getElementById("commonexp").innerHTML = commonexp;
} else if (expdrop <= 100) {
rareexp = rareexp + 1;
Log("You loot:<span style=\"color:blue\">Rare</span> Exp orb!");
document.getElementById("rareexp").innerHTML = rareexp;
}
} else {
var golddrop = Math.floor((Math.random() * 100) + 1);
if (golddrop < 70) {
commongold = commongold + 1;
Log("You loot:<span style=\"color:grey\">Common</span> Gold orb!");
document.getElementById("commongold").innerHTML = commongold;
} else if (golddrop <= 100) {
raregold = raregold + 1;
Log("You loot:<span style=\"color:blue\">Rare</span> Gold orb!");
document.getElementById("raregold").innerHTML = raregold;
}
}
}
}
}
那是代码的一部分,我使用这段代码 32 次。
假设您创建一个 Monster
"objects" 的数组,如下所示:
var Monsters = {
"foo": {"name":"Foo the foot", "hp":125, "power":3},
"bar": {"name":"Barbarian the bar", "hp":25, "power":9001}
};
您也可以编写按钮标记,这样每个按钮都可以与一个怪物相关联。例如:
<button rel="attack" data-monster_id="foo">Attack</button>
<button rel="attack" data-monster_id="bar">Attack</button>
现在,您可以 link 他们这样说:
var btns = document.querySelectorAll('button[rel="attack"]');
for (var i=0; i<btns.length; i++) {
this.addEventListener('click', function(){
attack(this.dataset.monster_id);
}, false);
}
最后,假设一个 attack
方法是这样的:
function attack(id) {
Monsters[id].hp -= currentDamage;
// whatever consequences the attack may have
}
希望这能给您带来灵感,祝您游戏顺利:)
不确定您的意思,但我认为使用 event delegation 可能有助于重用函数。在代码片段示例中,data-*
属性用于存储带有按钮的分数。此外,事件委托使您能够创建新按钮而无需分配新的处理程序。
document.querySelector('#testbuttons').addEventListener('click', testdemo);
document.querySelector('#testcreate').addEventListener('click', newbttn);
// handler for all buttons within div#testbutton
function testdemo(e) {
var from = e.target || e.srcElement
,score = from.getAttribute('data-score')
,kills = JSON.parse(from.getAttribute('data-kills'));
if (!score) { return true; }
Helpers.log2Screen('score clicked button: ', score,
', kills: <code>[', kills, ']</code>',
{clear: true});
}
function newbttn() {
var score = Math.floor(1+Math.random()*200);
document.querySelector('#testbuttons').innerHTML +=
'<br><button data-score="'+score+'" data-kills="[]">button '+score+'</button>';
Helpers.log2Screen('Created new button with score ', score, {clear: true});
}
button {
margin-top: 3px;
}
<!-- a few helpers -->
<script src="http://kooiinc.github.io/JSHelpers/Helpers-min.js"></script>
<div id="result"><p>Awaiting action ...</p></div>
<div id="testbuttons">
<button data-score="12" data-kills="[2,5,3]">bttn 12</button><br>
<button data-score="122" data-kills="[0,2,8]">bttn 122</button>
</div>
<button id="testcreate">create new button</button>
我想你正在寻找这样的东西:
function createAttack1(damage) {
return function() {
... Your attack1 logic using 'damage'
}
}
然后你可以用它来连接你的按钮:
button1.addEventListener("click", createAttack1(5));
button2.addEventListener("click", createAttack1(10));
button3.addEventListener("click", createAttack1(15));
这允许您重复使用相同的核心逻辑,同时拥有不同的统计数据,而不需要您一直在做的所有 copy/paste。