Project1
标题: 怎样才能更改地图部分色调,部分不更改? [打印本页]
作者: CCD0645 时间: 2019-5-3 15:28
标题: 怎样才能更改地图部分色调,部分不更改?
如果使用默认的改变色调事件,那么整个画面都会改为同一色调,我想呈现下面的效果,主角周边保持颜色,其余的地方色调改变,该如何做
作者: SixRC 时间: 2019-5-3 22:53
这问题我大概能解决(假如只是周边变单色)
不过可能解决的不完善 因为我对默认脚本不熟
而且用途可能比较单一
因为我不知道变换色调的算法(能瞎写)
转黑白相对还是挺好做的
我想的是在渲染游戏画面后获取相关信息(角色位置什么的)
然后对将被显示的画面进行处理
比方从某处渐变变灰
(所以基本不涉及原脚本的修改
因为是修改rgss渲染好的结果)
不过五一我回家了 电脑在学校
我明天回去试下
作者: SixRC 时间: 2019-5-4 22:53
本帖最后由 SixRC 于 2019-5-4 22:57 编辑
做了一个大概
我做了一个接口 就是在显示画面前会调用一个ruby方法 这个方法自己定义(注意 这个方法中不能用 Graphics.update 因为死循环了 也不能用 p 因为它也会调用渲染那段导致死循环 用 messagebox 代替)
然后提供了将被显示的位图数据地址 这时候可以用c写个dll处理画面(效率高 用ruby也不是不可以) ruby传入必要信息
因为一个原因 请用我提供的 RGSS103J.dll (具体原因是原生的渲染是一段一段的 (640*8) 导致没法整体一次性修改)
假如目标分辨率不是原生的我再改下 因为动态改这个比较麻烦 就直接改dll了
然后这是ruby里的代码
module Graphics
module_function
CCBBSS_DLL = Win32API.new('kernel32','GetModuleHandleA','p','l').call('RGSS103J')
CCBBSS_WPMLP = Win32API.new('kernel32','WriteProcessMemory','llpll','l')
CCBBSS_WPMPL = Win32API.new('kernel32','WriteProcessMemory','lplll','l')
temp = "\0"*4
CCBBSS_WPMPL.call(-1, temp, CCBBSS_DLL + 0x12B6C4, 4, 0)
CCBBSS_WPMPL.call(-1, temp, temp.unpack("l")[0] + 0x134, 4, 0)
CCBBSS_WPMPL.call(-1, temp, temp.unpack("l")[0] + 0xB4, 4, 0)
CCBBSS_WPMPL.call(-1, temp, temp.unpack("l")[0] + 0x10, 4, 0)
CCBBSS_BITMAP = temp.unpack("l")[0]
CCBBSS_RUBY_CODE = "Graphics.ccbbss_update"
CCBBSS_CODE = [0x8B, 0x54,0x24, 0x10,
0x60, 0x68, CCBBSS_RUBY_CODE,
0xB8, CCBBSS_DLL + 0x31D70,
0xFF, 0xD0,
0x83, 0xC4, 0x04, 0x61,
0x68, 0xCC0020,
0x6A, 0x00, 0x6A, 0x00, 0x57,
0xBF, CCBBSS_DLL + 0x884CD,
0xFF, 0xE7].pack("C6pClC7lC6lC2")
cc = [0xBA, CCBBSS_CODE, 0xFF, 0xE2].pack("CpC2")
CCBBSS_WPMLP.call(-1, CCBBSS_DLL + 0x884C3, cc, 7, 0)
CCBBSS_FUNC = Win32API.new("c/ccbbss","ccbbss_test2","lllll","v")
def ccbbss_update
unless $game_player
return
end
CCBBSS_FUNC.call(CCBBSS_BITMAP, $game_player.x * 32 + 16, $game_player.y * 32 + 16, 50, 80)
end
end
module Graphics
module_function
CCBBSS_DLL = Win32API.new('kernel32','GetModuleHandleA','p','l').call('RGSS103J')
CCBBSS_WPMLP = Win32API.new('kernel32','WriteProcessMemory','llpll','l')
CCBBSS_WPMPL = Win32API.new('kernel32','WriteProcessMemory','lplll','l')
temp = "\0"*4
CCBBSS_WPMPL.call(-1, temp, CCBBSS_DLL + 0x12B6C4, 4, 0)
CCBBSS_WPMPL.call(-1, temp, temp.unpack("l")[0] + 0x134, 4, 0)
CCBBSS_WPMPL.call(-1, temp, temp.unpack("l")[0] + 0xB4, 4, 0)
CCBBSS_WPMPL.call(-1, temp, temp.unpack("l")[0] + 0x10, 4, 0)
CCBBSS_BITMAP = temp.unpack("l")[0]
CCBBSS_RUBY_CODE = "Graphics.ccbbss_update"
CCBBSS_CODE = [0x8B, 0x54,0x24, 0x10,
0x60, 0x68, CCBBSS_RUBY_CODE,
0xB8, CCBBSS_DLL + 0x31D70,
0xFF, 0xD0,
0x83, 0xC4, 0x04, 0x61,
0x68, 0xCC0020,
0x6A, 0x00, 0x6A, 0x00, 0x57,
0xBF, CCBBSS_DLL + 0x884CD,
0xFF, 0xE7].pack("C6pClC7lC6lC2")
cc = [0xBA, CCBBSS_CODE, 0xFF, 0xE2].pack("CpC2")
CCBBSS_WPMLP.call(-1, CCBBSS_DLL + 0x884C3, cc, 7, 0)
CCBBSS_FUNC = Win32API.new("c/ccbbss","ccbbss_test2","lllll","v")
def ccbbss_update
unless $game_player
return
end
CCBBSS_FUNC.call(CCBBSS_BITMAP, $game_player.x * 32 + 16, $game_player.y * 32 + 16, 50, 80)
end
end
CCBBSS_RUBY_CODE 是会被执行的代码 这里指向了 Graphics.ccbbss_update
CCBBSS_BITMAP 保存了位图数据的地址 等下再说
然后我写了个dll来处理位图
void ccbbss_test2(unsigned char *bits, int ox, int oy, int r1, int r2){
// r1 != r2 !!!
if(r1 == r2)
return;
int gray, xx, yy, xy, r3;
int r12 = r1*r1;
int r22 = r2*r2;
int r21 = r2 - r1;
for(int height = 479; height > -1;height--){
for(int width = 0; width < 640; width++){
xx = width - ox;
yy = height - oy;
xy = xx*xx + yy*yy;
if(xy < r12){
// nothing
}else if( xy > r22){
gray = (bits[2]*313524 + bits[1]*615514 + bits[0]*119538) >> 20;
bits[0] = bits[1] = bits[2] = gray;
}else{
r3 = (int)(sqrt((double)xy) + 0.5);
xx = r3 - r1;
yy = r2 - r3;
gray = (bits[2]*313524 + bits[1]*615514 + bits[0]*119538) >> 20;
bits[0] = (bits[0] * yy + gray * xx) / r21;
bits[1] = (bits[1] * yy + gray * xx) / r21;
bits[2] = (bits[2] * yy + gray * xx) / r21;
}
bits += 4;
}
}
}
void ccbbss_test2(unsigned char *bits, int ox, int oy, int r1, int r2){
// r1 != r2 !!!
if(r1 == r2)
return;
int gray, xx, yy, xy, r3;
int r12 = r1*r1;
int r22 = r2*r2;
int r21 = r2 - r1;
for(int height = 479; height > -1;height--){
for(int width = 0; width < 640; width++){
xx = width - ox;
yy = height - oy;
xy = xx*xx + yy*yy;
if(xy < r12){
// nothing
}else if( xy > r22){
gray = (bits[2]*313524 + bits[1]*615514 + bits[0]*119538) >> 20;
bits[0] = bits[1] = bits[2] = gray;
}else{
r3 = (int)(sqrt((double)xy) + 0.5);
xx = r3 - r1;
yy = r2 - r3;
gray = (bits[2]*313524 + bits[1]*615514 + bits[0]*119538) >> 20;
bits[0] = (bits[0] * yy + gray * xx) / r21;
bits[1] = (bits[1] * yy + gray * xx) / r21;
bits[2] = (bits[2] * yy + gray * xx) / r21;
}
bits += 4;
}
}
}
同时 ruby 端的调用它 CCBBSS_FUNC.call(CCBBSS_BITMAP, $game_player.x * 32 + 16, $game_player.y * 32 + 16, 50, 80)
第一个参数是位图数据地址 保存形式是 bgra 从最后一行开始储存 也就是 第一个四字节数据是位于 x=0 y=479 的像素点 然后 x=1 ... ---> x=639 y=0
第二个第三个参数是渐变中心
然后两个是渐变半径 以内不变 以外全灰 中间折中
具体见代码
效果如下
范例
ccbbss.zip
(706.38 KB, 下载次数: 136)
走起路来灰圈圈动的不协调是因为角色坐标的更新没那么平滑
然后 上面的是例子 不是最终
因为我不太熟悉原生的脚本 没法写的很详细 连这个角色坐标转实际坐标都是现场瞎蒙的...
这个可能要麻烦别人写判断了 比方什么时候启用效果 什么时候关闭 打开菜单的时候关闭 等等等等
我会根据需要修改背后的东西 也可以写写dll啥的(现查现写)
有什么问题都可以问我
(先去睡觉了 明天早课 还一堆考试)
作者: CCD0645 时间: 2019-5-5 01:37
非常感谢,基本上可以解决了,
把$game_player.x * 32 + 16, $game_player.y * 32 + 16,改为$game_player.screen_x, $game_player.screen_y,就基本流畅了。
我现在用的分辨率是1280*736,所以还是出现一些问题,把分辨率改好就完美了。
作者: SixRC 时间: 2019-5-5 10:39
改好了
ccbbss.zip
(706.23 KB, 下载次数: 118)
改了分辨率 然后改了下函数导出名(ccbbss_effect1)
可以改着那个函数玩
像是转灰度 假如多位移一位(亮度减半)
就变这样了
就有晕圈的感觉了 效果好很多欸
其他可以根据需要来调整 像是色调 或是渐变算法什么的
或是别的特效
最早这做法是黄鸡想出来的
[RMVA]游戏画面滤镜(目前有马赛克/浮雕/雪花屏)
去复习了
作者: CCD0645 时间: 2019-5-15 12:58
还有一个问题,假如让两个或者多个作为中心,要怎么做。
比如一个NPC,一个玩家操纵的主角,周围都保持颜色,其他部分为黑白。
@SixRC
作者: SixRC 时间: 2019-5-15 16:30
好了
现在的做法是先根据需要刷新点的亮度信息
在全部刷新完后再渲染
CCBBSS_update_alpha = Win32API.new("c/ccbbss","ccbbss_update_alpha","llll","v")
CCBBSS_render1 = Win32API.new("c/ccbbss","ccbbss_render1","l","v")
CCBBSS_render2 = Win32API.new("c/ccbbss","ccbbss_render2","lll","v")
CCBBSS_update_alpha.call($game_player.screen_x, $game_player.screen_y - 16, 50, 100)
CCBBSS_update_alpha.call(200, 200, 50, 100)
CCBBSS_update_alpha.call(300, 400, 50, 100)
CCBBSS_render2.call(CCBBSS_BITMAP,3,3)
CCBBSS_update_alpha = Win32API.new("c/ccbbss","ccbbss_update_alpha","llll","v")
CCBBSS_render1 = Win32API.new("c/ccbbss","ccbbss_render1","l","v")
CCBBSS_render2 = Win32API.new("c/ccbbss","ccbbss_render2","lll","v")
CCBBSS_update_alpha.call($game_player.screen_x, $game_player.screen_y - 16, 50, 100)
CCBBSS_update_alpha.call(200, 200, 50, 100)
CCBBSS_update_alpha.call(300, 400, 50, 100)
CCBBSS_render2.call(CCBBSS_BITMAP,3,3)
CCBBSS_update_alpha(x, y, r1, r2) 就是更新信息 每次更新一个点
CCBBSS_render1(CCBBSS_BITMAP) 是刷新画面 照常
CCBBSS_render2(CCBBSS_BITMAP, a, b) 是这样操作的 第二个第三个参数是调节圈外亮度的
算式是 *a >> b
3, 3 就是亮度 *3/8
圈子和圈子的交叠的算法是 x+y - xy/k
x 和 y 是两个圈子的亮度 k 是亮度最大值 也就是x y 小的时候加的多 趋近亮度顶了就不加了 凑了半天凑出来的..看了下效果还行
ccbbss.zip
(706.93 KB, 下载次数: 87)
作者: CCD0645 时间: 2019-5-16 11:47
发现一个新问题,能不能将显示图片跟对话框单独分离出去,就是显示图片和显示对话框时不计入黑白的效果
目前的对话效果:
期待的效果是:
@SixRC
作者: SixRC 时间: 2019-5-16 14:18
我以为初版的时候你就发现了然后觉得没关系
因为现在的做法是在所有位图渲染完成后再作修改的
也就是说这时候 对话框 人物 地图 的效果都已经定死了
然后才改灰度
这时候只能选择改不改 改哪里
就像一个有选择的滤镜 但各图层已经融合了
所以理论上没办法不改对话
可以考虑的是对话框盖住底 就是对话框不透明
这样只要对话框和头像不变灰就行
你考虑下?
我先有点事
作者: SixRC 时间: 2019-5-16 20:30
本帖最后由 SixRC 于 2019-5-17 14:51 编辑
新增的函数
CCBBSS_fix1 = Win32API.new("c/ccbbss","ccbbss_fix1","lll","v")
CCBBSS_fix2 = Win32API.new("c/ccbbss","ccbbss_fix2","llll","v")
$ccbbss_test = Sprite.new
$ccbbss_test.bitmap = Bitmap.new("001-Fighter01")
$ccbbss_test.x = 400
$ccbbss_test.y = 400
$ccbbss_test.z = 666
CCBBSS_fix2.call($ccbbss_test.bitmap.id,$ccbbss_test.x,$ccbbss_test.y, 800)
CCBBSS_fix1 = Win32API.new("c/ccbbss","ccbbss_fix1","lll","v")
CCBBSS_fix2 = Win32API.new("c/ccbbss","ccbbss_fix2","llll","v")
$ccbbss_test = Sprite.new
$ccbbss_test.bitmap = Bitmap.new("001-Fighter01")
$ccbbss_test.x = 400
$ccbbss_test.y = 400
$ccbbss_test.z = 666
CCBBSS_fix2.call($ccbbss_test.bitmap.id,$ccbbss_test.x,$ccbbss_test.y, 800)
说明
CCBBSS_fix1(bitmap.id, x, y) 是刷新一个位图点位的亮度到最高 必须要传入位图的 id / __id__ 根据它的透明度进行刷新 透明度不为0则更改 后面的 x 和 y 是位图的屏幕坐标 这些需要自己获取
CCBBSS_fix2 多了一个参数是自定亮度 从 0-->1024 0 是纯灰 1024 不变
ccbbss.zip
(715.58 KB, 下载次数: 90)
现在根据透明度向原来储存的亮度信息渐变 透明度255是满亮度/自己选择的亮度 0是不变
假如CCBBSS_fix2.call这句写在最后面 就是最后刷新立绘色彩 那么角色移动到立绘旁边不会影响它的亮度
假如写在开头 也就是先刷新它的亮度 那之后角色移动过去刷新亮度的时候会影响到它
具体效果因为我没立绘不太清楚 你试试
作者: CCD0645 时间: 2019-5-17 09:13
SixRC 发表于 2019-5-16 20:30
新增的函数
CCBBSS_fix1 = Win32API.new("c/ccbbss","ccbbss_fix1","lll","v")
CCBBSS_fix2 = Win32API.new ...
出现了一个新问题,如图
作者: CCD0645 时间: 2019-5-17 10:23
本帖最后由 CCD0645 于 2019-5-17 13:25 编辑
最初的版本光照的部分过渡很自然,但是没光照的部分很毛躁
现在的版本是,没光照的部分很自然,光照的部分很毛躁
加羽化后的效果
不知道能不能解决,把两者都做得自然点
@SixRC
欢迎光临 Project1 (https://rpg.blue/) |
Powered by Discuz! X3.1 |