查看: 4667|回复: 18

[有事请教] 写了个物品介绍界面方法,不知道哪里出了问题(已解决)

[复制链接]
梦石
0
星屑
2381
在线时间
169 小时
注册时间
2017-4-25
回帖
185
发表于 2019-3-15 12:27:52 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有账号?注册会员

×
本帖最后由 rexuegg123 于 2019-3-16 19:55 编辑

写了些物品介绍界面显示的方法,其中一个界面删除的方法不知道哪里出了问题,请大神们看看

就是这个定时删除介绍图片的方法用上后出了问题
无标题.png

没引用用这个方法时,用的这行代码:
setTimeout(function(){for (var i=101;i<=110;i++){$gameScreen.erasePicture(i);};},6000);
除了不能刷新删除介绍的计时外一切正常。(当然也有个小问题,就是多点几次物品,会发现介绍界面删除地越来越快……)
无标题2.png

引用这个方法后(itemshow_clean ();),游戏占用内存在20多秒的时间内暴涨了几十倍……
无标题1.png



我的作品5.gif



感谢bule_ku大神的提示和耐心讲解!
问题已解决:达到延迟并有刷新延迟清除时间的功能

我的作品4.gif

修改代码如下:
引用函数部分
[pre lang="javascript"]
//格子的交互方法
//根据包裹状态(关闭,开启,对接等),点击每格物品时所作的动作
function Backpack_lattice (Num) {
    var n = Num;
    var m = WY_Bpack_sate;
        switch (m) {
           case 0:break;   //关闭状态,不动作
           case 1:           //包裹开启,但没有对接其他界面
                  lattice_mesage_show (n);    //点击物品时执行的事件:显示物品介绍
                  $gameSwitches.setValue(17,true);        //显示物品介绍计时的开关                 
                  if (WY_i ==0) {itemshow_clean ();} else {WY_i=1;}; //判断:是否引用延迟清除的方法(不能重复引用),不引用时重置计时变量WY_i为1。
                break;
           case '采集':   //对接采集界面
          lattice_click_Collect (n);  // 点击物品时执行的事件:采集工具就位           
                break;
        };       
};[/pre]

方法定义部分

[pre lang="javascript"]
//用于计时清除物品介绍图片
//功能:定时6秒后清除,若6秒内点击(不同)物品会重新计时
function itemshow_clean () {
        WY_i=1;    //全局变量,初始值为0,在上一级函数的操作中重置为1,以达到刷新延迟(清除物品介绍时间)目的              
        function itemshow_clean_sto () {               
                if (WY_i<=60) {
                        var w = WY_i*100;
                    if (w>=6000) {                                 
                           for (var i=101;i<=110;i++){$gameScreen.erasePicture(i);};//循环清除物品介绍图片
                           WY_i=0;
                    } else {
                       setTimeout(function(){WY_i++;itemshow_clean_sto ();},100);
                    };
                };               
        };
    itemshow_clean_sto ();
};[/pre]

问题总结:
1、我不该用for循环情况下还要用延迟执行……for循环是不会等待延迟的
2、重复引用相同函数会开启多个实例,使计时加快(同时对WY_i进行累加),反而达不到刷新(重置)延迟时间的目的。所以我在上一级的操作中用if判断了itemshow_clean ()是否已被引用,若没被引用并在实例中运行的话就直接引用,已引用的话只需重置WY_i=1就可以了。




梦石
0
星屑
538
在线时间
37 小时
注册时间
2017-12-16
回帖
29
发表于 2019-3-15 16:54:21 | 显示全部楼层
执行完了 if 语句之后不执行else, WY_i 一直 == 60;
在 if 嵌套内的 for 下面加上一句 WY_i++;

点评

在if嵌套内的for语句下面加WY_i++,是没用的吧!因为WY_i>=60才会执行这部分的语句  发表于 2019-3-15 18:27
这样的话,不会等到6秒才删除图片,而是马上就删除  发表于 2019-3-15 17:01
爆ぜろリアル!弾けろシナプス!パニッシュメント......ディス、ワールド!
回复

使用道具 举报

梦石
0
星屑
2381
在线时间
169 小时
注册时间
2017-4-25
回帖
185
 楼主| 发表于 2019-3-15 16:55:23 | 显示全部楼层
本帖最后由 rexuegg123 于 2019-3-15 17:06 编辑

大概知道问题出处了:
[pre lang="javascript"]
function itemshow_clean () {
  WY_i=1;//定义一个全局变量,初始为1
  for (;WY_i<=60;) {
    var w = WY_i*100;
    if (w>=6000) {                          
      for (var i=101;i<=110;i++){$gameScreen.erasePicture(i);};//循环清除物品介绍图片
    } else {
      setTimeout(function(){WY_i++;},100);
    };
  };
};
[/pre]

代码中“setTimeout(function(){WY_i++;},100);”,这句延迟了WY_i++的执行,但for循环并不会停下来,它会在WY_i>60之前极快地循环n多次,但这是否造成占用内存暴涨的原因还不确定
回复

使用道具 举报

梦石
0
星屑
538
在线时间
37 小时
注册时间
2017-12-16
回帖
29
发表于 2019-3-15 19:02:35 | 显示全部楼层
本帖最后由 blue_ku 于 2019-3-15 19:21 编辑
rexuegg123 发表于 2019-3-15 16:55
大概知道问题出处了:

function itemshow_clean () {


function(){pass}的意思是定义一个函数,里面的内容其实还未执行。
要想定义完马上执行需要把函数体用括号括起来,再尾随一个圆括号;
参考以下代码:
[pre lang="javascript"](function(){pass})();[/pre]
[pre lang="javascript"]setTimeout((function(){pass})(), 100)[/pre]

不过你这样子写虽然可以,但是很耗内存的,因为它反复定义了一个匿名函数。
其实你直接可以写成:
[pre lang="javascript"]setTimeout(WY_i++, 100)[/pre]

点评

但我还是不明白,每秒才执行十次这个语句。就算30秒才执行300次,他为什么会占用那么多内存(3个多G)。  发表于 2019-3-15 21:24
嗯,对,按你说的调整以后,确实解决了这个内存暴涨的问题。  发表于 2019-3-15 21:22
爆ぜろリアル!弾けろシナプス!パニッシュメント......ディス、ワールド!
回复

使用道具 举报

梦石
0
星屑
538
在线时间
37 小时
注册时间
2017-12-16
回帖
29
发表于 2019-3-16 00:18:53 | 显示全部楼层
本帖最后由 blue_ku 于 2019-3-16 00:42 编辑

那是个死循环,一直在执行else语句块。
前面说的if那块应该也是出不去的,你可以在函数后面写个alert(0)看看有没有弹框输出,没有就是因为出不去。

其实你可以写成:
  1. function itemshow_clean (){
  2.         for(var i = 101; i <= 110; i++){
  3.                 setTimeout($gameScreen.erasePicture(i), 6000);
  4.         }
  5. }
复制代码
爆ぜろリアル!弾けろシナプス!パニッシュメント......ディス、ワールド!
回复

使用道具 举报

梦石
0
星屑
2381
在线时间
169 小时
注册时间
2017-4-25
回帖
185
 楼主| 发表于 2019-3-16 10:02:39 | 显示全部楼层
本帖最后由 rexuegg123 于 2019-3-16 10:10 编辑
blue_ku 发表于 2019-3-16 00:18
那是个死循环,一直在执行else语句块。
前面说的if那块应该也是出不去的,你可以在函数后面写个alert(0) ...


确实,if下面不加  "WY_i++"的话,无法跳出最大那个for循环,WY_i++的值达到60后,if的前半部分部分会一直执行……

如果加 "WY_i++"就成了秒删,因为 setTimeout(WY_i++,100); 这句的延迟累加,根本没有延迟……

但直接用 setTimeout(function(){for (var i=101;i<=110;i++){$gameScreen.erasePicture(i);};},6000); 的话,连续点击物品时,游戏似乎会创建多个延迟6秒删除图片的实例,无法达到刷新延迟时间的效果。

最后重新写成下面这样的代码……除了不会生成更多延迟删除的实例秒删外,还是无法达到刷新延迟删除时间的效果。
[pre lang="javascript"]
//用于计时清除物品介绍图片
//功能:定时6秒后清除,若6秒内点击(不同)物品会重新计时
function itemshow_clean () {
        WY_i=1;//定义一个全局变量,初始为1   ————————在上一级操作下WY_i值被重新设置为1,已达到刷新延迟时间的效果
        function itemshow_clean_sto () {
                if (WY_i<=60) {
                        var w = WY_i*100;
                    if (w>=6000) {                          
                           for (var i=101;i<=110;i++){$gameScreen.erasePicture(i);};//循环清除物品介绍图片
                    } else {
                       setTimeout(function(){WY_i++;itemshow_clean_sto ();},100);
                    };
                };               
        };
    itemshow_clean_sto ();
};[/pre]
回复

使用道具 举报

梦石
0
星屑
538
在线时间
37 小时
注册时间
2017-12-16
回帖
29
发表于 2019-3-16 15:01:22 | 显示全部楼层
本帖最后由 blue_ku 于 2019-3-17 14:57 编辑

晕了@_@
setTimeout() 传入的第一个参数要求是字符串。

setTimeout(func(), 6000); 情况下,func()会立即执行,不管延时设定多少。
setTimeout(“func()”, 6000); ←这样子写才会在设定延时后执行。


另外,你没搞懂定义函数跟调用函数的区别啊。

functino funcName(){
        pass
}//这样子是定义函数

funcName();//←这样子才会执行函数定义的内容

换句话说,要让一个自己定义的函数运行,要写的代码有两部分。
第一部分是函数定义代码,第二部分是函数执行代码。
当然,觉得这样子很麻烦的程序员不止你一个,所以js提供了定义完函数马上执行的写法;
像这样:

(functon(){
        pass
})();

    ↑函数定义部分要用括号括起来,在这部分外面还要尾随一个括号。

这样子直接执行,所以连funcName都省了,这种省了函数名的函数就叫“匿名函数”。
不过,匿名函数只能用一次,因为没有函数名,想要再使用它也不知道该调用什么东西。
所以要是想让函数在其他地方再次调用的话,就要加上函数名。

此外,在面向对象过程中,“方法”的本质就是函数,而且可以用方法来调用函数,所以给对象添加方法时,定义的函数一般没有函数名。
你可以经常见到这样子写的:

delayedCleaner.method = function(){
        pass
}

调用时就写成:

delayedCleaner.method();

定义函数时也可以这样写:

var funcName = function(){
        pass
}

调用:

funcName();



//==============================================
// 2019年3月17日 14点53分 纠正:
//==============================================
setTimeout() 用法:

  1. setTimeout(func, delay);        //正确/               
  2. setTimeout(function(){pass}, delay);        //正确
  3. setTimeout(func(), delay);        //错误
  4. setTimeout("func()", delay);        //正确
  5. setTimeout(i++, delay);        //错误
  6. setTimeout("i++", delay);        //正确
复制代码


我也才看了js没几天,懂的不多,犯了错误还请见谅

点评

还好啊,你说的东西解决了我好几个问题。  发表于 2019-3-19 10:52
爆ぜろリアル!弾けろシナプス!パニッシュメント......ディス、ワールド!
回复

使用道具 举报

梦石
0
星屑
2381
在线时间
169 小时
注册时间
2017-4-25
回帖
185
 楼主| 发表于 2019-3-16 17:09:39 | 显示全部楼层
本帖最后由 rexuegg123 于 2019-3-16 19:53 编辑
blue_ku 发表于 2019-3-16 15:01
晕了@_@
setTimeout() 传入的第一个参数要求是字符串。


谢谢大佬,花了那么多时间来讲解,涨了不少知识……再次十分感谢!!!
我这里的问题已经解决了(具体在1楼已经更新):
1、我不该用for循环情况下还要用延迟执行……for循环是不会等待延迟的
2、重复引用相同函数会开启多个实例,使计时加快(同时对WY_i进行累加),反而达不到刷新(重置)延迟时间的目的。所以我在上一级的操作中用if判断了itemshow_clean ()是否已被引用,若没被引用进而在实例中运行的话就直接引用,已引用的话只需重置WY_i=1就可以了。


回复

使用道具 举报

梦石
0
星屑
3922
在线时间
1198 小时
注册时间
2016-8-9
回帖
2355

开拓者

发表于 2019-3-18 13:40:46 | 显示全部楼层
期待楼主的飞天历险早点问世,炒鸡怀念
酸酸甜甜就④哇噢
回复

使用道具 举报

梦石
0
星屑
2381
在线时间
169 小时
注册时间
2017-4-25
回帖
185
 楼主| 发表于 2019-3-19 10:51:24 | 显示全部楼层
本帖最后由 rexuegg123 于 2019-3-19 10:56 编辑
白嫩白嫩的 发表于 2019-3-18 13:40
期待楼主的飞天历险早点问世,炒鸡怀念


我也跟期待,不过唉,一个人弄……怎一个慢字了得。
对了,你那里有高级物品的素材没?我这里在飞天国际版里面没有大号……很多素材不全。

点评

我的账号都忘记了,十来年了,哎  发表于 2019-3-19 13:36
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部