i_wanna_be_the_guy吧 关注:62,553贴子:1,119,305

回复:【i wanna】论1024<=y<2048时单次取消情况下ya绕路的可行性探究

只看楼主收藏回复

五、改变出正常跳跃所能得到范围外的ya的一些尝试和又一个令人吃惊的结论
上文我们得出了原地起跳所能够得到的ya,令我们很高兴的是,它只涵盖了多位小数形成的大量组合中的极小部分。那么接下来,我们只需要找到不能通过正常跳跃所得到的ya,就能满足上面“前置知识”所述的ya绕的重要条件。
而实现非原地跳跃可达ya的思路有两种:
1.改变起跳点。
2.使kid获得不正常的纵向速度。
针对1号思路,我们可以有如下选项:
* 从低处跳往高处。
* 从高处跳往低处。
* 蹭板跳、蹭藤跳......
针对2号思路,我们还有一些方法:
* 在水中下落。
* 磕藤的底部......


IP属地:湖南16楼2021-08-12 11:52
回复
    然而,在尝试了一堆方法后,我们发现:不管如何去跳,最后所得到的ya还是都能在上面程序的结果中找到!也就是说,在1024<=y<2048范围内,可以通过正常方式得到的ya也只有3277种。
    这启示我们,正常起跳得到的ya范围如此之小,可能还是float本身的运算精度问题;更重要的是,改变起跳点、使kid获得非正常纵向速度等方式获得的ya在1024<=y<2048范围内不具有特殊性。


    IP属地:湖南17楼2021-08-12 11:52
    回复
      六、在单次取消情况下通过限制kid起跳高度达到ya绕的效果
      首先定义一个maxheight参数,在模拟跳跃的过程中,如果pos和startfloor的距离差小于该参数的值,则该跳跃失败,返回-1(可以理解为撞到刺了,之类的)
      接着在搜索函数中特判一下,若调用该函数的值为-1,则不压入队列。
      const float startfloor=2000;
      const float maxheight=37-21;//注意这里要减去21,因为kid碰撞箱高为21,而我们进行跳跃模拟时其实是基于kid的“脚底”部分进行操作的
      float getValign(float valignBefore,int singleJump,int pause,int doubleJump)
      {
      int i;
      float pos=startfloor+valignBefore;
      float vspeed=-8.5f;
      if (singleJump>0)
      {
      for (i=1;i<=singleJump-1;i++)
      {
      vspeed+=0.4f;
      pos+=vspeed;
      if (startfloor-round(pos)>maxheight)
      return -1;
      }
      if (vspeed<0)
      vspeed*=0.45f;
      }
      for (i=1;i<=pause;i++)
      {
      vspeed+=0.4f;
      pos+=vspeed;
      if (startfloor-round(pos)>maxheight)
      return -1;
      }
      if (doubleJump>0)
      {
      vspeed=-7.0f;
      for (i=1;i<=doubleJump-1;i++)
      {
      vspeed+=0.4f;
      pos+=vspeed;
      if (startfloor-round(pos)>maxheight)
      return -1;
      }
      if (vspeed<0)
      {
      vspeed*=0.45f;
      }
      }
      while (1)
      {
      vspeed+=0.4f;
      if (round(pos+vspeed)>startfloor)
      {
      if (vspeed==0.4f)
      break;
      vspeed=0.0f;
      while (round(pos+1)<=startfloor)
      pos++;
      }
      else
      {
      pos+=vspeed;
      if (startfloor-round(pos)>maxheight)
      return -1;
      }
      }
      return pos-(int)pos;
      }


      IP属地:湖南18楼2021-08-12 11:53
      回复
        同时我们也注意到,我们忽视了bh的情况,事实上只要kid以当前速度继续下坠会碰到方块的时候,就能够进行bh,相当于多了一种跳跃的情况。
        基于以上考虑,我们把getValign原先的float返回值改为std::vector<float>,标志着包括bh在内的多种“ya”情况。另外在getValign函数内部,我们也要注意如果是bh的情况下,当valignBefore大于0.5时,起跳点要比正常情况下高一格,即pos=startfloor+valignBefore-1.


        IP属地:湖南19楼2021-08-12 11:54
        回复
          最终代码:
          #include <cmath>
          #include <cstdlib>
          #include <cstdio>
          #include <queue>
          #include <vector>
          #include <map>
          using namespace std;
          const float startfloor=2000;
          const float maxheight=37-21;
          vector<float> getValign(float valignBefore,int singleJump,int pause,int doubleJump)
          {
          int i;
          float pos=startfloor+valignBefore;
          if (valignBefore>=0.5f)
          pos--;
          float vspeed=-8.5f;
          vector<float> res;
          if (singleJump>0)
          {
          for (i=1;i<=singleJump-1;i++)
          {
          vspeed+=0.4f;
          pos+=vspeed;
          if (startfloor-round(pos)>maxheight)
          return {};
          }
          if (vspeed<0)
          {
          vspeed*=0.45f;
          }
          }
          for (i=1;i<=pause;i++)
          {
          vspeed+=0.4f;
          pos+=vspeed;
          if (startfloor-round(pos)>maxheight)
          return {};
          }
          if (doubleJump>0)
          {
          vspeed=-7.0f;
          for (i=1;i<=doubleJump-1;i++)
          {
          vspeed+=0.4f;
          pos+=vspeed;
          if (startfloor-round(pos)>maxheight)
          return {};
          }
          if (vspeed<0)
          {
          vspeed*=0.45f;
          }
          }
          while (1)
          {
          vspeed+=0.4f;
          if (round(pos+vspeed)>startfloor)
          {
          if (vspeed==0.4f)
          break;
          vspeed=0.0f;
          while (round(pos+1)<=startfloor)
          pos++;
          res.push_back(pos-(int)pos);
          }
          else
          {
          pos+=vspeed;
          if (startfloor-round(pos)>maxheight)
          return {};
          }
          }
          res.push_back(pos-(int)pos);
          return res;
          }
          int getMaxPause(float valignBefore,int singleJump)
          {
          int i;
          int res=0;
          float pos=startfloor+valignBefore;
          float vspeed=-8.5f;
          if (singleJump>0)
          {
          for (i=1;i<=singleJump-1;i++)
          {
          vspeed+=0.4f;
          pos+=vspeed;
          }
          if (vspeed<0)
          {
          vspeed*=0.45f;
          }
          }
          while (1)
          {
          res++;
          vspeed+=0.4f;
          if (round(pos+vspeed+1)>startfloor)
          return res-1;
          else pos+=vspeed;
          }
          }
          map<float,int> vis;
          void bfs()
          {
          queue<float> Q;
          vector<float>::iterator iter;
          float t=startfloor+0.4f;
          Q.push(t-(int)t);
          vis[t-(int)t]=1;
          int i,j,k,m;
          float x;
          vector<float> ya;
          while (!Q.empty())
          {
          x=Q.front();
          Q.pop();
          printf("%d\n",vis[x]);
          for (i=1;i<=23;i++)//singleJump
          {
          ya=getValign(x,i,0,0);
          for (iter=ya.begin();iter!=ya.end();iter++)
          {
          if (vis[(*iter)])
          continue;
          vis[(*iter)]=vis[x]+1;
          Q.push(*iter);
          }
          }
          for (i=1;i<=23;i++)
          {
          m=getMaxPause(x,i);
          for (j=1;j<=m;j++)
          for (k=1;k<=19;k++)
          {
          ya=getValign(x,i,j,k);
          for (iter=ya.begin();iter!=ya.end();iter++)
          {
          if (vis[(*iter)])
          continue;
          vis[(*iter)]=vis[x]+1;
          Q.push(*iter);
          }
          }
          }
          }
          }
          int main()
          {
          bfs();
          map<float,int>::iterator i;
          printf("start writing to file:\n");
          freopen("valign_1024-2048_result.out","w",stdout);
          int tot=0;
          for (i=vis.begin();i!=vis.end();i++)
          if (round((startfloor+i->first)+0.4f)>startfloor&&i->first<0.5f)
          tot++;
          printf("Total num:%d\n",tot);
          for (i=vis.begin();i!=vis.end();i++)
          if (round((startfloor+i->first)+0.4f)>startfloor&&i->first<0.5f)
          printf("ya=%.14f\n",i->first);
          fclose(stdout);
          system("valign_1024-2048_result.out");
          return 0;
          }


          IP属地:湖南20楼2021-08-12 11:54
          回复
            通过多次修改maxheight并运行代码,我们可以发现:当maxheight<=34-21的时候,只能到达一种ya(即初始ya);当maxheight为(35-21)时,可以到达2867种ya;只要限制高度为36以上,就可到达所有的3277种ya。


            IP属地:湖南21楼2021-08-12 11:55
            回复

              打开jtool,在playerstart上方的适当位置放上刺(如上图所示)。在单次取消的条件下,当刺的高度为34px时,kid怎么跳都会撞到刺;当刺的高度为35px时,只有一种跳法不会撞到刺:1+1+1(没错不是一段1帧)。当刺的高度为36px时,仍然只有1+1+1能够通过,但允许更广范围的bh了。我们可以吃惊地发现,只需要全面允许bh,就可以得到所有能够到达的ya了。
              我们也可以发现,如果排除bh的情况,在刺的高度为35-36时,可以到达ya的范围就小得多了。(见下图)

              由上图也可以看到,在限制可达ya个数方面,限制刺的高度<=35px时比较稳妥。
              当限制刺的高度<=35px时,我们就可以实现前文中提到的“使kid经过同一地点时有着不同的ya”,从而为ya绕打下了基础。


              IP属地:湖南22楼2021-08-12 11:56
              回复
                为了表述方便,我们不妨定义:在1024<=y<2048范围内,1+1+1能够到达的ya为“一级ya”;1+1+1不能到达但无限制情况下能够到达的ya称为“二级ya”。
                把上面的代码改一下,很容易能求出具体的一级ya和二级ya。


                IP属地:湖南23楼2021-08-12 11:56
                回复
                  七、关于第六点的一些实践

                  如图,kid起始点位于A点,左下角刺阵P同时限xa和限ya,当ya为二级ya:0.27539062500000时才可过。(由于起跳点上方的35px限高,kid只能跳出1+1+1,且为了够到传送门只能一直往左走,所以这种要求的刺阵是很容易造出来的)
                  一开始,kid的状态为“一级ya+坏墙”,为了得到好墙,只有去右下方的B点去贴playerstart右下角的墙。而为了得到好ya,需要先到达C点,利用板子重置一下ya,再原地进行一次(1+1+1)跳,接着直接向右走下去,在快要碰到小刺的最后一帧时进行一次一帧跳。这样当kid回到起点时,就获得了一个好的二级ya(0.27539062500000)。
                  kid的路线图:A->B->A->C->A->P。我们可以看到,A点周围的局部利用率达到了300%.


                  IP属地:湖南24楼2021-08-12 11:57
                  收起回复
                    八、结语和附件
                    今天,我们对于1024<=y<2048中的ya情况进行了简单探索,并对单次取消情况下ya绕的实现提出了设想(并做了简单实践)。可以看到,由于35px限高情况下单次取消所能到达ya的不完全性,为实现ya绕提供了良好的基础。然而,在单次取消情况下,一些可以通过仙人掌、最小jc可以跳过去的美妙单刺变成了无解。
                    作者们在摆刺时要根据自己的意愿,谨慎选择是否开启单次取消:如果你要摆1px的ya绕的话,一定要开启单次取消模式:如果你要摆16px、32px的美(yin)妙(jian)单刺的话,最好关闭单次取消模式。
                    (开启单次取消模式,只要再添加一个变量,在引擎中keyboard_check_pressed/released(global.jumpbutton)根据变量加以赋值和判断即可)


                    IP属地:湖南25楼2021-08-12 11:58
                    回复
                      为了方便作者们摆ya绕的方便,我把前文代码的输出文件和一个跳跃改变ya的文件放了出来,供各位参考。
                      链接:https://pan.baidu.com/s/1aGdAQDEPPwNcv1GRh1guUg
                      提取码:ldja


                      IP属地:湖南26楼2021-08-12 11:59
                      收起回复
                        可以预见到,在不久的将来,1px量子摆刺会越来越多,成为iw摆刺界不可忽视的力量之一!(bushi
                        -----End
                        SC
                        2021-8-12


                        IP属地:湖南27楼2021-08-12 12:00
                        回复
                          哦我的上帝


                          IP属地:天津28楼2021-08-12 12:19
                          回复
                            ??前排膜拜大佬


                            IP属地:江苏29楼2021-08-12 12:22
                            回复


                              IP属地:江苏30楼2021-08-12 12:22
                              回复