Project1

标题: 请教RGSS3的transition阻塞问题与模拟算法 [打印本页]

作者: test    时间: 2014-9-6 11:54
标题: 请教RGSS3的transition阻塞问题与模拟算法
Graphics.freeze在手册上是这样写的:
これ以後 transition メソッドを呼び出すまでは、一切の画面の書き換えが禁止されます。


也就是说,Graphics.freeze将画面固定之后,到呼出Graphics.transition为止,画面是被冻结的。
按照手册上说的话,应该是不会有阻塞问题,但事实上效果和手册上说的不一样的,
比如,在下雨效果开启的情况下,执行Graphics.transition(600)。
这时,在过渡中的600帧内,雨点是不会动的。
而不是像手册说的那样,执行到Graphics.transition语句的时候画面的冻结被解除。

这就说明,Graphics.transition执行完毕,画面冻结才会被解除。

问题1:如何让Graphics.transition执行中,画面不会被冻结?

然后,我把手册都翻了个遍也没发现有什么办法能解决。于是我想自己模拟过渡效果。

用Graphics.transition控制图片淡出淡入效果(第2个参数filename留空的情况),
可以通过改变图片透明度的方法来模拟。
但是,用Graphics.transition(同样参数filename留空)由一张图片过渡到另一张图片的时候,
用透明度的方法模拟起来好象很复杂……因为根据背景色的不同两张图片重叠部分的合成模式好象也不同的,
合成模式既不是“通常”也不是“加算”也不是“減算”。

还有,如果Graphics.transition指定了第2个参数filename之后,用改变图片透明度的方法根本模拟不了了。
我在想,不考虑效率,能不能通过Bitmap类的get_pixel和set_pixel方法来模拟,可是一点头绪都没有。

问题2:Graphics.transition的算法是怎样的?

问题3:或者有什么其他的方法能像Graphics.transition那样使一张图片(Sprite)过渡到另一张图片(Sprite)而不需要冻结整个画面?
作者: taroxd    时间: 2014-9-6 15:01
本帖最后由 taroxd 于 2014-9-6 15:05 编辑

关于那个雨点的事情。你执行了transition ,那么更改雨点坐标的语句就没有执行咯~ 不过我也不是特别清楚。

至于过渡的问题,既然不考虑效率的话,get_pixel 和 set_pixel 应该不会有什么问题才是。
作者: fux2    时间: 2014-9-6 15:11
transition会进入一个循环直到渐变完毕,而期间调用的Graphics.update是原始的update方法(即不受重定义影响)
循环过程中冻结的画面透明度算法如下
i : 循环迭代器
d : 渐变帧数
如果指定了第二个参数
  1. (i << 8) / d + 256
复制代码
如果没有指定第二个参数:
  1. 255 - 255 * i / d
复制代码
如果只是单纯的2张sprite过渡,用上面的算法即可。


黑掉transition的解决方法如下:(含测试代码,删除后半部分即可使用。)

代码


冻结时画面的截图spr优先级非常高,其余的请自己处理。
(PS:由于VA F12 RESET之后并不会重新载入一次脚本,所以不考虑F12之后产生的内存问题。
作者: test    时间: 2014-9-6 20:56
本帖最后由 test 于 2014-9-8 16:16 编辑

我试了下这个脚本,过渡方法虽然被成功地黑掉了,但用起来还是会有一些问题。
可能是因为过渡和冻结配对使用的关系,感觉要连冻结方法一起黑掉才行……
作者: Shy07    时间: 2014-9-16 13:40
1.
RM 使用了双缓冲,Graphics#freeze 执行的是锁定屏幕缓存,而后台缓存仍可继续更新。
在调用 Graphics#transition 后,先进行屏幕截图(屏幕缓存拷贝),然后解锁屏幕缓存。如果不指定渐变图,则屏幕缓存拷贝叠加在后台缓存上,然后降低屏幕缓存拷贝的透明度。如果指定了渐变图,则以渐变图的灰度为优先级,更改屏幕缓存拷贝对应位置的透明度。
以上是原理,所以在不修改 Graphics#transition 实现的前提下,答案是:没办法。

2.
以下是 SINRGE2 的实现,供参考
CPP 代码复制
  1. void MRbSinCore::Freeze()
  2. {
  3.         if (pHGE->freezeTex) pHGE->Texture_Free(pHGE->freezeTex);
  4.         pHGE->freezeTex = 0;
  5.         pHGE->freezeTex = pHGE->Texture_CreateFromScreen();
  6.         pHGE->bFreeze = true;
  7. }
  8.  
  9. void MRbSinCore::Transition(int duration, const wchar_t * filename, float vague)
  10. {
  11.         if (!pHGE->freezeTex || !pHGE->bFreeze) return;
  12.  
  13.         if (duration <= 0)
  14.         {
  15.                 pHGE->bFreeze = false;
  16.                 GetAppPtr()->GraphicsUpdate();
  17.                 return;
  18.         }
  19.  
  20.         HTEXTURE newTex = pHGE->Texture_CreateFromScreen();
  21.         if (!newTex) return;
  22.         float tempx1, tempy1, tempx2, tempy2;
  23.  
  24.         tempx1 = 0;
  25.         tempy1 = 0;
  26.         tempx2 = pHGE->nScreenWidth;
  27.         tempy2 = pHGE->nScreenHeight;
  28.  
  29.         hgeQuad frzQuad, newQuad;
  30.         frzQuad.tex = pHGE->freezeTex;
  31.         QUAD_INIT(frzQuad);
  32.         QUAD_SET_VRECT(frzQuad, tempx1, tempy1, tempx2, tempy2);
  33.  
  34.         newQuad.tex = newTex;
  35.         QUAD_INIT(newQuad);
  36.         QUAD_SET_VRECT(newQuad, tempx1, tempy1, tempx2, tempy2);
  37.  
  38.         if (filename[0])
  39.         {
  40.                 int suffix_idx;
  41.                 HTEXTURE midTex = CRbBitmap::LoadTexture(filename, 0, suffix_idx);
  42.  
  43.                 int mw = pHGE->Texture_GetWidth(midTex);
  44.                 int mh = pHGE->Texture_GetHeight(midTex);
  45.                 float a2, gray = 0, rate = (float)(255.0 / duration);
  46.                 int dw = pHGE->nScreenWidth < mw ? pHGE->nScreenWidth : mw;
  47.                 int dh = pHGE->nScreenHeight < mh ? pHGE->nScreenHeight : mh;
  48.                 int wrate = pHGE->nScreenWidth / mw;
  49.                 int hrate = pHGE->nScreenHeight / mh;
  50.  
  51.                 BYTE a1, r1, g1, b1, r2;
  52.                 DWORD * pMidTexData = pHGE->Texture_Lock(midTex, true);
  53.                 pHGE->bFreeze = false;
  54.                 if (vague > 1)
  55.                 {
  56.                         do
  57.                         {
  58.                                 DWORD* pNewTexData = pHGE->Texture_Lock(newTex, false);
  59.                                 for (int ly = 0; ly < dh; ++ly)
  60.                                 {
  61.                                         int tempW1 = ly * mw;
  62.                                         for (int lx = 0; lx < dw; ++lx)
  63.                                         {
  64.                                                 r2 = GET_ARGB_R(pMidTexData[tempW1 + lx]);
  65.                                                 if ((BYTE)gray < r2)
  66.                                                 {
  67.                                                         // 计算透明度,这算法我自己都不知道如何吐槽了 = =b
  68.                                                         a2 = 255.0 - 255.0 / vague * (r2 - gray);
  69.                                                         if (vague < 24) a2 += (12 + rate * rate) * (16 - vague);
  70.                                                         else a2 += 12 + rate * rate;
  71.                                                         a2 = SinBound(a2, 0, 255);
  72.  
  73.                                                         if (wrate && hrate)
  74.                                                         {
  75.                                                                 for (int j = 0; j < hrate + 1; ++j)
  76.                                                                 {
  77.                                                                         if ((pHGE->nScreenHeight - mh * j) > ly)
  78.                                                                         {
  79.                                                                                 int tempH2 = (ly + mh * j) * pHGE->nScreenWidth;
  80.                                                                                 GET_ARGB_8888(pNewTexData[tempH2 + lx], a1, r1, g1, b1);
  81.                                                                                 pNewTexData[tempH2 + lx] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1);
  82.  
  83.                                                                                 for (int i = 1; i < wrate + 1; ++i)
  84.                                                                                 {
  85.                                                                                         int tempW3 = mw * i;
  86.                                                                                         if ((pHGE->nScreenWidth - tempW3) > lx)
  87.                                                                                         {
  88.                                                                                                 GET_ARGB_8888(pNewTexData[tempH2 + lx + tempW3], a1, r1, g1, b1);
  89.                                                                                                 pNewTexData[tempH2 + lx + tempW3] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1);
  90.                                                                                         }
  91.                                                                                 }
  92.                                                                         }
  93.                                                                 }
  94.                                                         }
  95.                                                         else if (wrate)
  96.                                                         {
  97.                                                                 int tempH2 = ly * pHGE->nScreenWidth;
  98.                                                                 GET_ARGB_8888(pNewTexData[tempH2 + lx], a1, r1, g1, b1);
  99.                                                                 pNewTexData[tempH2 + lx] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1);
  100.  
  101.                                                                 for (int i = 1; i < wrate + 1; ++i)
  102.                                                                 {
  103.                                                                         int tempW3 = mw * i;
  104.                                                                         if ((pHGE->nScreenWidth - tempW3) > lx)
  105.                                                                         {
  106.                                                                                 GET_ARGB_8888(pNewTexData[tempH2 + lx + tempW3], a1, r1, g1, b1);
  107.                                                                                 pNewTexData[tempH2 + lx + tempW3] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1);
  108.                                                                         }
  109.                                                                 }
  110.                                                         }
  111.                                                         else if (hrate)
  112.                                                         {
  113.                                                                 for (int j = 0; j < hrate + 1; ++j)
  114.                                                                 {
  115.                                                                         if ((pHGE->nScreenHeight - mh * j) > ly)
  116.                                                                         {
  117.                                                                                 int tempH2 = (ly + mh * j) * pHGE->nScreenWidth;
  118.                                                                                 GET_ARGB_8888(pNewTexData[tempH2 + lx], a1, r1, g1, b1);
  119.                                                                                 pNewTexData[tempH2 + lx] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1);
  120.  
  121.                                                                                 GET_ARGB_8888(pNewTexData[tempH2 + lx], a1, r1, g1, b1);
  122.                                                                                 pNewTexData[tempH2 + lx] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1);
  123.                                                                         }
  124.                                                                 }
  125.                                                         }
  126.                                                         else
  127.                                                         {
  128.                                                                 int tempH2 = ly * pHGE->nScreenWidth;
  129.                                                                 GET_ARGB_8888(pNewTexData[tempH2 + lx], a1, r1, g1, b1);
  130.                                                                 pNewTexData[tempH2 + lx] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1);
  131.                                                         }
  132.                                                 }
  133.                                         }
  134.                                 }
  135.                                 pHGE->Texture_Unlock(newTex);
  136.  
  137.                                 GetAppPtr()->SystemUpdate();
  138.                                 if(pHGE->bActive || pHGE->bDontSuspend)
  139.                                 {
  140.                                         pHGE->Gfx_BeginScene();
  141.                                         pHGE->Gfx_RenderQuad(&frzQuad);
  142.                                         pHGE->Gfx_RenderQuad(&newQuad);
  143.                                         pHGE->Gfx_EndScene();
  144.  
  145.                                         if (pHGE->bShowFps)
  146.                                         {
  147.                                                 wsprintfW(pHGE->szTitleFps, L"%s - %d FPS", pHGE->szWinTitle, GetAppPtr()->GetRealFps());
  148.                                                 SetWindowText(pHGE->hwnd, pHGE->szTitleFps);
  149.                                         }
  150.                                 }
  151.                                 GetAppPtr()->LimitFps(pHGE->nHGEFPS);
  152.                                 duration--;
  153.                                 gray += rate;
  154.                         } while (duration);
  155.                 }
  156.                 else
  157.                 {
  158.                         do
  159.                         {
  160.                                 gray += rate;
  161.  
  162.                                 DWORD * pFrzTexData = pHGE->Texture_Lock(pHGE->freezeTex, false);
  163.                                 for (int ly = 0; ly < dh; ++ly)
  164.                                 {
  165.                                         int tempW1 = ly * mw;
  166.                                         int tempW2 = ly * pHGE->nScreenWidth;
  167.                                         for (int lx = 0; lx < mw; ++lx)
  168.                                         {
  169.                                                 r2 = GET_ARGB_R(pMidTexData[tempW1 + lx]);
  170.                                                 if ((BYTE)gray > r2)
  171.                                                 {
  172.                                                         pFrzTexData[tempW2 + lx] = 0;
  173.  
  174.                                                         if ((pHGE->nScreenWidth - mw) > lx)
  175.                                                         {
  176.                                                                 pFrzTexData[tempW2 + lx + mw] = 0;
  177.                                                         }
  178.  
  179.                                                         if ((pHGE->nScreenHeight - mh) > ly)
  180.                                                         {
  181.                                                                 pFrzTexData[(ly + mh) * pHGE->nScreenWidth + lx] = 0;
  182.  
  183.                                                                 if ((pHGE->nScreenWidth - mw) > lx)
  184.                                                                         pFrzTexData[(ly + mh) * pHGE->nScreenWidth + lx + mw] = 0;
  185.                                                         }
  186.                                                 }
  187.                                         }
  188.                                 }
  189.                                 pHGE->Texture_Unlock(pHGE->freezeTex);
  190.  
  191.                                 GetAppPtr()->SystemUpdate();
  192.                                 if(pHGE->bActive || pHGE->bDontSuspend)
  193.                                 {
  194.                                         pHGE->Gfx_BeginScene();
  195.                                         pHGE->Gfx_RenderQuad(&newQuad);
  196.                                         pHGE->Gfx_RenderQuad(&frzQuad);
  197.                                         pHGE->Gfx_EndScene();
  198.  
  199.                                         if (pHGE->bShowFps)
  200.                                         {
  201.                                                 wsprintfW(pHGE->szTitleFps, L"%s - %d FPS", pHGE->szWinTitle, GetAppPtr()->GetRealFps());
  202.                                                 SetWindowText(pHGE->hwnd, pHGE->szTitleFps);
  203.                                         }
  204.                                 }
  205.                                 GetAppPtr()->LimitFps(pHGE->nHGEFPS);
  206.                                 duration--;
  207.                         } while (duration);
  208.                 }
  209.                 pHGE->Texture_Free(midTex);
  210.         }
  211.         else
  212.         {
  213.                 float rate = 255.0 / duration;
  214.                 float al = 0;
  215.                 pHGE->bFreeze = false;
  216.                 do
  217.                 {
  218.                         al += rate;
  219.                         newQuad.v[0].col =
  220.                         newQuad.v[1].col =
  221.                         newQuad.v[2].col =
  222.                         newQuad.v[3].col = 0x00ffffff + ((BYTE)al << 24);
  223.  
  224.                         GetAppPtr()->SystemUpdate();
  225.                         if(pHGE->bActive || pHGE->bDontSuspend)
  226.                         {
  227.                                 pHGE->Gfx_BeginScene();
  228.                                 //pHGE->Gfx_Clear(0);
  229.                                 pHGE->Gfx_RenderQuad(&frzQuad);
  230.                                 pHGE->Gfx_RenderQuad(&newQuad);
  231.                                 pHGE->Gfx_EndScene();
  232.  
  233.                                 if (pHGE->bShowFps)
  234.                                 {
  235.                                         wsprintfW(pHGE->szTitleFps, L"%s - %d FPS", pHGE->szWinTitle, GetAppPtr()->GetRealFps());
  236.                                         SetWindowText(pHGE->hwnd, pHGE->szTitleFps);
  237.                                 }
  238.                         }
  239.                         GetAppPtr()->LimitFps(pHGE->nHGEFPS);
  240.                         duration--;
  241.                 } while (duration);
  242.         }
  243.         pHGE->Texture_Free(newTex);
  244.         newTex = 0;
  245.         pHGE->Texture_Free(pHGE->freezeTex);
  246.         pHGE->freezeTex = 0;
  247. }


3.
两个 Sprite 可以实现不指定 filename 的 Graphics#transition 效果,指定 filename 的 Graphics#transition 效果需要 Bitmap 像素操作,效率不用期待。




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1