我已经为游戏创作制作了一个有趣的API。在代码中,我为Mover创建了一个原型,然后使用几个特定的原型(Gold,Monster和Hero)扩展它。每个都基于具有给定ID的img标签。我在构造函数中使用特定于类型的信息,并为每种类型使用单个模板方法。 Mover中的大多数功能代码都依赖于特定于类型的详细信息。为简单起见,我列举了一个例子。
我在单独的脚本中使用方法调用来创建和销毁Mover子类型的实例。当我一次创建并销毁一个实例时,一切都按预期工作。图像更新,声音播放,并在正确的延迟后删除。但是,如果我创建两个或更多,则只有最后一个按预期工作。所以,如果我做金,培养,英雄。只有英雄会正确删除。其他两个将播放音频,但似乎没有更新。
当我尝试将函数附加到多个实例的onclick事件时,我遇到了同样的问题。只有最后一个工作,其他人什么也没做。显然我对java处理方法赋值的方式缺一些了解。您可以提供任何解释都会有所帮助。 谢谢, BSD
function Mover()
{
}
Mover.prototype.InitTag = function()
{
this.HTMLtag.src=this.imageURL;
this.HTMLtag.style.position="absolute";
this.HTMLtag.style.width=characterSize;
this.HTMLtag.style.height=characterSize;
this.Position(Math.floor(Math.random()*(MaxW-characterSize)+(characterSize/2)),Math.floor(Math.random()*(MaxH-characterSize)+(characterSize/2)));
}
Mover.prototype.Destroy = function()
{
var disp = this.HTMLtag.display;
this.HTMLtag.src=this.destroyURL
this.HTMLtag.display = disp;
this.destroyAudio.play();
this.RemoveTag();
}
function Monster(id)
{
this.MonsterID = id;
this.HTMLtag = document.getElementById("monster"+id);
this.imageURL = "monster1.jpg";
this.destroyURL = "monster2.jpg";
this.destroyAudio = monsterAudio;
}
Monster.prototype = new Mover();
Monster.prototype.RemoveTag = function()
{
var mID = this.MonsterID;
setTimeout(function() {field.DeleteMonster(mID)}, 1000);
}
function Hero()
{
this.HTMLtag = document.getElementById("hero");
this.imageURL = "hero1.jpg";
this.destroyURL = "hero2.jpg";
this.destroyAudio = heroAudio;
}
Hero.prototype = new Mover();
Hero.prototype.RemoveTag = function()
{
setTimeout(function() {field.DeleteHero()}, 5000);
}
function Gold(id)
{
this.GoldID = id;
this.HTMLtag = document.getElementById("gold"+id);
this.imageURL = "gold1.jpg";
this.destroyURL = "gold2.jpg";
this.destroyAudio = goldAudio;
}
Gold.prototype = new Mover();
Gold.prototype.RemoveTag = function()
{
var mID = this.GoldID;
setTimeout(function() {field.DeleteGold(mID)}, 1000);
}
---------更新更新更新----------- 我至少部分解决了这个问题。我已经让它工作了,但我仍然不知道为什么它没有按预期运行。我注意到,虽然我的浏览器(Chrome)开发人员工具可以在视觉上识别出最近添加的Mover,但是它在任何其他推动者时都无法实现。
Tag of most recently added Mover can be identified in Chrome developer tools. 这表明Mover.HTMLtag实际上与document.getElementById('mover1')不同。我能够通过查看GoldField.DeleteMover中的变量来确认这一点。在指示的行mover.src没有改变,但是movers [id] .HTMLtag.src已经正确更新。在最近添加的案例中,它们都是相同的。
GoldField.prototype.DeleteMover = function(id)
{
var isHero = false;
if(this.Hero!=null && id==this.Hero.myID)
{
this.Hero = null;
isHero = true;
}
else if(this.Tower!=null && id==this.Tower.myID)
{
this.Tower = null;
}
var mover = document.getElementById("mover"+id);
if(!isHero)
{
this.tag.removeChild(mover);//<<< HERE HERE HERE HERE
delete this.movers[id];
}
}
所以,我在Mover.Destroy中更改了一行。通过ID查找标记并设置src。我能够做到可靠的行为。在添加第二个Mover之后,Mover.HTMLtag似乎不可靠。有什么解释吗?
Mover.prototype.Destroy = function()
{
document.getElementById(this.HTMLtag.id).src=this.destroyURL;
this.HTMLtag.src=this.destroyURL;//old method
this.destroyAudio.play();
this.RemoveTag();
}
由于怀疑这可能延伸到this.HTMLtag的其他更新,我设置了Hero的一些基本动作。它工作得很好,但是如果你添加一个额外的Mover,它就不再移动了。这大大缩小了这个问题。为什么构建第二个Mover导致原型成员改变?
答案 0 :(得分:1)
所以我调试你的代码,我找到了问题的原因。问题是当你创建一个新的怪物实例时,你在怪物var上存储了对它的引用。当您删除它时,您不会删除/更新对它的引用。所以你的删除函数myField.DeleteMover(id)尝试删除已删除的怪物。如何解决这个问题。
// create an array to keep ref to our instances
var monsters= [];
// var monster = null;
function addMonster()
{
// monster = goldField.AddMonster();⏎
// push every monster in array
monsters.push(goldField.AddMonster());
}
function killMonster()
{
// if array.length is true
if (monsters.length) {
// call the destroy function on the last ref
monsters[monsters.length - 1].Destroy();
// remove the last ref from array using pop
monsters.pop();
}
//monster.Destroy();
}
这是有效的,但我认为所有这些都应该在对象本身中完成。你不应该在乎它。
另一个建议是尝试使用更多array methods。避免在数组索引上使用delete因为它混乱了索引和计数而是使用splice(index,1)相同的数组使用push而不是任意索引添加项目。
无论如何有趣的游戏!祝你好运。
编辑,在你回答之后我回去测试。 为了使它工作,我这样做。
// First go inGoldField.prototype.DeleteMover and replace the ugly delete index by
this.movers.splice(id, 1);
// Then in the Mover.prototype.Destroy
// This part is a a little blurred for me.
// the current HTMLtag looks good but when I console.log like this
console.log('before', this.HTMLtag);
this.HTMLtag = document.querySelector("#mover" + this.myID);
console.log('after', this.HTMLtag);
// They are not equal look like the first is outdated
您应该将所有删除和添加转换为拼接和推送方法 这只是一个快速的调试,我不知道为什么选择器已经过时了。
答案 1 :(得分:0)
所以我再次检查代码并使其工作而不刷新选择器。问题是由使用innerHTML创建dom元素引起的。
首先重置
this.HTMLtag.src=this.destroyURL
然后代替
//Mover.prototype.Destroy
this.tag.innerHTML+="<img id='mover"+this.moverCount+"'>";
我创建了一个img dom el。
var img = document.createElement("img");
img.setAttribute('id', 'mover' + this.moverCount);
this.tag.appendChild(img);
现在所有怪物都被删除了 我没有检查英雄,但首先你应该更新你的innerHTML并回答是否还有问题。我不认为某些原型有任何问题。