赞 | 1 |
VIP | 357 |
好人卡 | 24 |
积分 | 1 |
经验 | 14896 |
最后登录 | 2022-12-23 |
在线时间 | 1641 小时 |
Lv1.梦旅人
- 梦石
- 0
- 星屑
- 66
- 在线时间
- 1641 小时
- 注册时间
- 2011-9-26
- 帖子
- 313
|
1.
RM 使用了双缓冲,Graphics#freeze 执行的是锁定屏幕缓存,而后台缓存仍可继续更新。
在调用 Graphics#transition 后,先进行屏幕截图(屏幕缓存拷贝),然后解锁屏幕缓存。如果不指定渐变图,则屏幕缓存拷贝叠加在后台缓存上,然后降低屏幕缓存拷贝的透明度。如果指定了渐变图,则以渐变图的灰度为优先级,更改屏幕缓存拷贝对应位置的透明度。
以上是原理,所以在不修改 Graphics#transition 实现的前提下,答案是:没办法。
2.
以下是 SINRGE2 的实现,供参考
void MRbSinCore::Freeze() { if (pHGE->freezeTex) pHGE->Texture_Free(pHGE->freezeTex); pHGE->freezeTex = 0; pHGE->freezeTex = pHGE->Texture_CreateFromScreen(); pHGE->bFreeze = true; } void MRbSinCore::Transition(int duration, const wchar_t * filename, float vague) { if (!pHGE->freezeTex || !pHGE->bFreeze) return; if (duration <= 0) { pHGE->bFreeze = false; GetAppPtr()->GraphicsUpdate(); return; } HTEXTURE newTex = pHGE->Texture_CreateFromScreen(); if (!newTex) return; float tempx1, tempy1, tempx2, tempy2; tempx1 = 0; tempy1 = 0; tempx2 = pHGE->nScreenWidth; tempy2 = pHGE->nScreenHeight; hgeQuad frzQuad, newQuad; frzQuad.tex = pHGE->freezeTex; QUAD_INIT(frzQuad); QUAD_SET_VRECT(frzQuad, tempx1, tempy1, tempx2, tempy2); newQuad.tex = newTex; QUAD_INIT(newQuad); QUAD_SET_VRECT(newQuad, tempx1, tempy1, tempx2, tempy2); if (filename[0]) { int suffix_idx; HTEXTURE midTex = CRbBitmap::LoadTexture(filename, 0, suffix_idx); int mw = pHGE->Texture_GetWidth(midTex); int mh = pHGE->Texture_GetHeight(midTex); float a2, gray = 0, rate = (float)(255.0 / duration); int dw = pHGE->nScreenWidth < mw ? pHGE->nScreenWidth : mw; int dh = pHGE->nScreenHeight < mh ? pHGE->nScreenHeight : mh; int wrate = pHGE->nScreenWidth / mw; int hrate = pHGE->nScreenHeight / mh; BYTE a1, r1, g1, b1, r2; DWORD * pMidTexData = pHGE->Texture_Lock(midTex, true); pHGE->bFreeze = false; if (vague > 1) { do { DWORD* pNewTexData = pHGE->Texture_Lock(newTex, false); for (int ly = 0; ly < dh; ++ly) { int tempW1 = ly * mw; for (int lx = 0; lx < dw; ++lx) { r2 = GET_ARGB_R(pMidTexData[tempW1 + lx]); if ((BYTE)gray < r2) { // 计算透明度,这算法我自己都不知道如何吐槽了 = =b a2 = 255.0 - 255.0 / vague * (r2 - gray); if (vague < 24) a2 += (12 + rate * rate) * (16 - vague); else a2 += 12 + rate * rate; a2 = SinBound(a2, 0, 255); if (wrate && hrate) { for (int j = 0; j < hrate + 1; ++j) { if ((pHGE->nScreenHeight - mh * j) > ly) { int tempH2 = (ly + mh * j) * pHGE->nScreenWidth; GET_ARGB_8888(pNewTexData[tempH2 + lx], a1, r1, g1, b1); pNewTexData[tempH2 + lx] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1); for (int i = 1; i < wrate + 1; ++i) { int tempW3 = mw * i; if ((pHGE->nScreenWidth - tempW3) > lx) { GET_ARGB_8888(pNewTexData[tempH2 + lx + tempW3], a1, r1, g1, b1); pNewTexData[tempH2 + lx + tempW3] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1); } } } } } else if (wrate) { int tempH2 = ly * pHGE->nScreenWidth; GET_ARGB_8888(pNewTexData[tempH2 + lx], a1, r1, g1, b1); pNewTexData[tempH2 + lx] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1); for (int i = 1; i < wrate + 1; ++i) { int tempW3 = mw * i; if ((pHGE->nScreenWidth - tempW3) > lx) { GET_ARGB_8888(pNewTexData[tempH2 + lx + tempW3], a1, r1, g1, b1); pNewTexData[tempH2 + lx + tempW3] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1); } } } else if (hrate) { for (int j = 0; j < hrate + 1; ++j) { if ((pHGE->nScreenHeight - mh * j) > ly) { int tempH2 = (ly + mh * j) * pHGE->nScreenWidth; GET_ARGB_8888(pNewTexData[tempH2 + lx], a1, r1, g1, b1); pNewTexData[tempH2 + lx] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1); GET_ARGB_8888(pNewTexData[tempH2 + lx], a1, r1, g1, b1); pNewTexData[tempH2 + lx] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1); } } } else { int tempH2 = ly * pHGE->nScreenWidth; GET_ARGB_8888(pNewTexData[tempH2 + lx], a1, r1, g1, b1); pNewTexData[tempH2 + lx] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1); } } } } pHGE->Texture_Unlock(newTex); GetAppPtr()->SystemUpdate(); if(pHGE->bActive || pHGE->bDontSuspend) { pHGE->Gfx_BeginScene(); pHGE->Gfx_RenderQuad(&frzQuad); pHGE->Gfx_RenderQuad(&newQuad); pHGE->Gfx_EndScene(); if (pHGE->bShowFps) { wsprintfW(pHGE->szTitleFps, L"%s - %d FPS", pHGE->szWinTitle, GetAppPtr()->GetRealFps()); SetWindowText(pHGE->hwnd, pHGE->szTitleFps); } } GetAppPtr()->LimitFps(pHGE->nHGEFPS); duration--; gray += rate; } while (duration); } else { do { gray += rate; DWORD * pFrzTexData = pHGE->Texture_Lock(pHGE->freezeTex, false); for (int ly = 0; ly < dh; ++ly) { int tempW1 = ly * mw; int tempW2 = ly * pHGE->nScreenWidth; for (int lx = 0; lx < mw; ++lx) { r2 = GET_ARGB_R(pMidTexData[tempW1 + lx]); if ((BYTE)gray > r2) { pFrzTexData[tempW2 + lx] = 0; if ((pHGE->nScreenWidth - mw) > lx) { pFrzTexData[tempW2 + lx + mw] = 0; } if ((pHGE->nScreenHeight - mh) > ly) { pFrzTexData[(ly + mh) * pHGE->nScreenWidth + lx] = 0; if ((pHGE->nScreenWidth - mw) > lx) pFrzTexData[(ly + mh) * pHGE->nScreenWidth + lx + mw] = 0; } } } } pHGE->Texture_Unlock(pHGE->freezeTex); GetAppPtr()->SystemUpdate(); if(pHGE->bActive || pHGE->bDontSuspend) { pHGE->Gfx_BeginScene(); pHGE->Gfx_RenderQuad(&newQuad); pHGE->Gfx_RenderQuad(&frzQuad); pHGE->Gfx_EndScene(); if (pHGE->bShowFps) { wsprintfW(pHGE->szTitleFps, L"%s - %d FPS", pHGE->szWinTitle, GetAppPtr()->GetRealFps()); SetWindowText(pHGE->hwnd, pHGE->szTitleFps); } } GetAppPtr()->LimitFps(pHGE->nHGEFPS); duration--; } while (duration); } pHGE->Texture_Free(midTex); } else { float rate = 255.0 / duration; float al = 0; pHGE->bFreeze = false; do { al += rate; newQuad.v[0].col = newQuad.v[1].col = newQuad.v[2].col = newQuad.v[3].col = 0x00ffffff + ((BYTE)al << 24); GetAppPtr()->SystemUpdate(); if(pHGE->bActive || pHGE->bDontSuspend) { pHGE->Gfx_BeginScene(); //pHGE->Gfx_Clear(0); pHGE->Gfx_RenderQuad(&frzQuad); pHGE->Gfx_RenderQuad(&newQuad); pHGE->Gfx_EndScene(); if (pHGE->bShowFps) { wsprintfW(pHGE->szTitleFps, L"%s - %d FPS", pHGE->szWinTitle, GetAppPtr()->GetRealFps()); SetWindowText(pHGE->hwnd, pHGE->szTitleFps); } } GetAppPtr()->LimitFps(pHGE->nHGEFPS); duration--; } while (duration); } pHGE->Texture_Free(newTex); newTex = 0; pHGE->Texture_Free(pHGE->freezeTex); pHGE->freezeTex = 0; }
void MRbSinCore::Freeze()
{
if (pHGE->freezeTex) pHGE->Texture_Free(pHGE->freezeTex);
pHGE->freezeTex = 0;
pHGE->freezeTex = pHGE->Texture_CreateFromScreen();
pHGE->bFreeze = true;
}
void MRbSinCore::Transition(int duration, const wchar_t * filename, float vague)
{
if (!pHGE->freezeTex || !pHGE->bFreeze) return;
if (duration <= 0)
{
pHGE->bFreeze = false;
GetAppPtr()->GraphicsUpdate();
return;
}
HTEXTURE newTex = pHGE->Texture_CreateFromScreen();
if (!newTex) return;
float tempx1, tempy1, tempx2, tempy2;
tempx1 = 0;
tempy1 = 0;
tempx2 = pHGE->nScreenWidth;
tempy2 = pHGE->nScreenHeight;
hgeQuad frzQuad, newQuad;
frzQuad.tex = pHGE->freezeTex;
QUAD_INIT(frzQuad);
QUAD_SET_VRECT(frzQuad, tempx1, tempy1, tempx2, tempy2);
newQuad.tex = newTex;
QUAD_INIT(newQuad);
QUAD_SET_VRECT(newQuad, tempx1, tempy1, tempx2, tempy2);
if (filename[0])
{
int suffix_idx;
HTEXTURE midTex = CRbBitmap::LoadTexture(filename, 0, suffix_idx);
int mw = pHGE->Texture_GetWidth(midTex);
int mh = pHGE->Texture_GetHeight(midTex);
float a2, gray = 0, rate = (float)(255.0 / duration);
int dw = pHGE->nScreenWidth < mw ? pHGE->nScreenWidth : mw;
int dh = pHGE->nScreenHeight < mh ? pHGE->nScreenHeight : mh;
int wrate = pHGE->nScreenWidth / mw;
int hrate = pHGE->nScreenHeight / mh;
BYTE a1, r1, g1, b1, r2;
DWORD * pMidTexData = pHGE->Texture_Lock(midTex, true);
pHGE->bFreeze = false;
if (vague > 1)
{
do
{
DWORD* pNewTexData = pHGE->Texture_Lock(newTex, false);
for (int ly = 0; ly < dh; ++ly)
{
int tempW1 = ly * mw;
for (int lx = 0; lx < dw; ++lx)
{
r2 = GET_ARGB_R(pMidTexData[tempW1 + lx]);
if ((BYTE)gray < r2)
{
// 计算透明度,这算法我自己都不知道如何吐槽了 = =b
a2 = 255.0 - 255.0 / vague * (r2 - gray);
if (vague < 24) a2 += (12 + rate * rate) * (16 - vague);
else a2 += 12 + rate * rate;
a2 = SinBound(a2, 0, 255);
if (wrate && hrate)
{
for (int j = 0; j < hrate + 1; ++j)
{
if ((pHGE->nScreenHeight - mh * j) > ly)
{
int tempH2 = (ly + mh * j) * pHGE->nScreenWidth;
GET_ARGB_8888(pNewTexData[tempH2 + lx], a1, r1, g1, b1);
pNewTexData[tempH2 + lx] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1);
for (int i = 1; i < wrate + 1; ++i)
{
int tempW3 = mw * i;
if ((pHGE->nScreenWidth - tempW3) > lx)
{
GET_ARGB_8888(pNewTexData[tempH2 + lx + tempW3], a1, r1, g1, b1);
pNewTexData[tempH2 + lx + tempW3] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1);
}
}
}
}
}
else if (wrate)
{
int tempH2 = ly * pHGE->nScreenWidth;
GET_ARGB_8888(pNewTexData[tempH2 + lx], a1, r1, g1, b1);
pNewTexData[tempH2 + lx] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1);
for (int i = 1; i < wrate + 1; ++i)
{
int tempW3 = mw * i;
if ((pHGE->nScreenWidth - tempW3) > lx)
{
GET_ARGB_8888(pNewTexData[tempH2 + lx + tempW3], a1, r1, g1, b1);
pNewTexData[tempH2 + lx + tempW3] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1);
}
}
}
else if (hrate)
{
for (int j = 0; j < hrate + 1; ++j)
{
if ((pHGE->nScreenHeight - mh * j) > ly)
{
int tempH2 = (ly + mh * j) * pHGE->nScreenWidth;
GET_ARGB_8888(pNewTexData[tempH2 + lx], a1, r1, g1, b1);
pNewTexData[tempH2 + lx] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1);
GET_ARGB_8888(pNewTexData[tempH2 + lx], a1, r1, g1, b1);
pNewTexData[tempH2 + lx] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1);
}
}
}
else
{
int tempH2 = ly * pHGE->nScreenWidth;
GET_ARGB_8888(pNewTexData[tempH2 + lx], a1, r1, g1, b1);
pNewTexData[tempH2 + lx] = MAKE_ARGB_8888((BYTE)a2, r1, g1, b1);
}
}
}
}
pHGE->Texture_Unlock(newTex);
GetAppPtr()->SystemUpdate();
if(pHGE->bActive || pHGE->bDontSuspend)
{
pHGE->Gfx_BeginScene();
pHGE->Gfx_RenderQuad(&frzQuad);
pHGE->Gfx_RenderQuad(&newQuad);
pHGE->Gfx_EndScene();
if (pHGE->bShowFps)
{
wsprintfW(pHGE->szTitleFps, L"%s - %d FPS", pHGE->szWinTitle, GetAppPtr()->GetRealFps());
SetWindowText(pHGE->hwnd, pHGE->szTitleFps);
}
}
GetAppPtr()->LimitFps(pHGE->nHGEFPS);
duration--;
gray += rate;
} while (duration);
}
else
{
do
{
gray += rate;
DWORD * pFrzTexData = pHGE->Texture_Lock(pHGE->freezeTex, false);
for (int ly = 0; ly < dh; ++ly)
{
int tempW1 = ly * mw;
int tempW2 = ly * pHGE->nScreenWidth;
for (int lx = 0; lx < mw; ++lx)
{
r2 = GET_ARGB_R(pMidTexData[tempW1 + lx]);
if ((BYTE)gray > r2)
{
pFrzTexData[tempW2 + lx] = 0;
if ((pHGE->nScreenWidth - mw) > lx)
{
pFrzTexData[tempW2 + lx + mw] = 0;
}
if ((pHGE->nScreenHeight - mh) > ly)
{
pFrzTexData[(ly + mh) * pHGE->nScreenWidth + lx] = 0;
if ((pHGE->nScreenWidth - mw) > lx)
pFrzTexData[(ly + mh) * pHGE->nScreenWidth + lx + mw] = 0;
}
}
}
}
pHGE->Texture_Unlock(pHGE->freezeTex);
GetAppPtr()->SystemUpdate();
if(pHGE->bActive || pHGE->bDontSuspend)
{
pHGE->Gfx_BeginScene();
pHGE->Gfx_RenderQuad(&newQuad);
pHGE->Gfx_RenderQuad(&frzQuad);
pHGE->Gfx_EndScene();
if (pHGE->bShowFps)
{
wsprintfW(pHGE->szTitleFps, L"%s - %d FPS", pHGE->szWinTitle, GetAppPtr()->GetRealFps());
SetWindowText(pHGE->hwnd, pHGE->szTitleFps);
}
}
GetAppPtr()->LimitFps(pHGE->nHGEFPS);
duration--;
} while (duration);
}
pHGE->Texture_Free(midTex);
}
else
{
float rate = 255.0 / duration;
float al = 0;
pHGE->bFreeze = false;
do
{
al += rate;
newQuad.v[0].col =
newQuad.v[1].col =
newQuad.v[2].col =
newQuad.v[3].col = 0x00ffffff + ((BYTE)al << 24);
GetAppPtr()->SystemUpdate();
if(pHGE->bActive || pHGE->bDontSuspend)
{
pHGE->Gfx_BeginScene();
//pHGE->Gfx_Clear(0);
pHGE->Gfx_RenderQuad(&frzQuad);
pHGE->Gfx_RenderQuad(&newQuad);
pHGE->Gfx_EndScene();
if (pHGE->bShowFps)
{
wsprintfW(pHGE->szTitleFps, L"%s - %d FPS", pHGE->szWinTitle, GetAppPtr()->GetRealFps());
SetWindowText(pHGE->hwnd, pHGE->szTitleFps);
}
}
GetAppPtr()->LimitFps(pHGE->nHGEFPS);
duration--;
} while (duration);
}
pHGE->Texture_Free(newTex);
newTex = 0;
pHGE->Texture_Free(pHGE->freezeTex);
pHGE->freezeTex = 0;
}
3.
两个 Sprite 可以实现不指定 filename 的 Graphics#transition 效果,指定 filename 的 Graphics#transition 效果需要 Bitmap 像素操作,效率不用期待。 |
评分
-
查看全部评分
|