设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
楼主: guoxiaomi
打印 上一主题 下一主题

[原创发布] 【RGM】RGModern 1.0.4 - RMXP新runtime

[复制链接]

Lv2.观梦者

梦石
0
星屑
380
在线时间
53 小时
注册时间
2023-7-16
帖子
19
1
发表于 2023-8-6 19:32:02 | 显示全部楼层
本帖最后由 zlyl_wiley 于 2023-9-16 01:11 编辑

伟大的新轮子,感谢

经过测试,有一些BUG、疑问和需求反馈,一股脑列出来了

1
set_title已经移动,但使用指南暂未更新,新人容易踩坑,建议将更新信息汇总在1楼方便查阅

2
一直觉得对话框出现时会闪一下,直到我在框里加了图片,这个情况就很明显了,看抓拍到的图,像是叠加模式从减法过渡到正常的样子,连灰色的文字也曝光成白的了,虽然实际上还挺帅的,但如果是BUG的话还是修了吧,然后可以移植成可选的附加功能哈哈哈哈




3
以下脚本预期的效果是 Alt + Enter 切换全屏和窗口显示,但是实际上除了 Enter ,按 C 或 Space 也能触发, 虚拟按键的绑定不应该是双向的吧,另外我还是没搞懂如何添加新的按键,直接传递未注册的键码似乎是不支持的,下个版本可否做成自动识别是直接传递键码还是虚拟按键常量(把常量值平移放大?),原键码只监听单键,虚拟常量监听多个键,并默认开放全键盘?
RUBY 代码复制
  1. if Input.press?(23)
  2.       if Input.trigger?(13)
  3.         RGM::Ext::Window.set_fullscreen($full_screen ? 0 : 1)
  4.         $full_screen = !$full_screen
  5.         return
  6.       end
  7.     end


4
input.rb中有句注释:“RGM 会在按键抬起的那一帧判定为 trigger”,实测好像并不是这样,而是在按下的那一帧触发,当然这样更好,否则鼠标拖拽还不好做了,这里只是问一下是否笔误
还有非常需要隐藏鼠标,甚至锁定鼠标,否则鼠标模块是没有灵魂的
窗口是否焦点和鼠标移入移出判断是已存在的,但不知如何获取,求教
(编辑)仔细一想还是需要抬起时的判定的,因为实际上经常会有这样的操作:在元件上按下左键后,如果抬起前鼠标发生位移,则开始拖拽(或移出范围后不触发点击),若抬起时鼠标未移动,才判定为点击

5
TextBox非常值得继续强化,感觉很快就会有人接入AI聊天了呢
建议增加Shift+左右键选取部分文本功能,可以考虑顺便增加鼠标选取操作
目前字体不能设置,简单添加attr_accessor :sprite可以凑合,但是@textbox.sprite.bitmap.font.size也很怪,或可弄个font_size和font_name属性
希望开放设置确认按键,支持限制输入长度,并增加输入过滤功能,例如:可以设置按小键盘回车键确认,并限制输入范围为0-9的4位数字(感觉目前的应用场景还是输入密码居多)
需要随时修改输入框中内容的方法,毕竟是游戏引擎,这个玩法就多了,而且做工具时也有很多用处,例如检测到输入左括号时,自动补全右括号并把光标移动到括号中间
建议开放自定义光标样式,可以update(自己做动画效果)

6
需要在程序退出(红X和Alt+F4)时调用函数,用于自动存档和META整活

7
需要隐藏控制台,但不关闭(关闭后IO会受阻),试过用vbs脚本调用RGM并设置后台运行,但结果两个窗口一起钻后台去了……
(编辑)正考虑写一些工具,为了方便与编辑器联动,最好能实现窗体置顶,(虽然能获取句柄但我不懂WINDOWS……
另外传递中文数据时经常乱码,看着不像编码的问题,但我还是尽力尝试设置了内外环境的编码,结果仍无法正常工作,疑似某个环节的to_string之类的方法有问题?
(编辑)我好像发现了,应该是dump了对吗……能否去掉……
  

8
建议增加整体打包功能,不为防盗,只是从游戏设计的角度出发,希望阻止玩家竭尽所能地破坏自身的游戏体验而已,多一道坎,让普通玩家懒得寻求破解就足够了

9
非常需要高效的蒙板功能,逐像素一get一set(原图r,g,b,原图a - 蒙板a)的话实在太贵了,用Palette也不可能经得起update,请求从底层开发一个最便宜的
希望增加反色的blend_type
另外进入战斗画面的那个渐变过渡能否挪出来平时给Sprite什么的用用?

10
看说明的意思是只要释放Viewport,里面的东西就都不用手动dispose吗?
顺便Plane不要求指定Viewport了,会有什么不同吗?

11
音频的BUG似乎是淡出时会卡线程?而且奇怪的是一旦触发BGM无声BUG之后,即使重启电脑也不会复原,必须在游戏中另一处位置正常触发播放音乐才能解除,以及有无声BUG的地方是固定会触发的,很可能都是在渐隐之后

12
补充一点,建议天气的范围和数量根据屏幕大小动态调整
其它的就不赘述了,感觉最迫切的就音频BUG了

13
最后一点个人的感想:现在RM在大众眼里的印象并不是很好,处在鄙视链底端不说,甚至被有些人贴上了黄油引擎的标签,所幸现在还有像郭大这样的大神在持续给XP注入新的生命,真的非常感动,但是话说,我个人觉得光是性能的提升,还是很难有大的改观的,很容易给路人玩家“只是现在电脑升级了”的感觉,所以我非常盼望未来RGM在功能上也能展现出morden的一面,但只要提供一些最基础实用的功能接口就行,比如我会期待RGM加入简单的几何绘图API,常用shader预置(模糊、描边、通道偏移、空气扰动之类),以及类似RGD的音频滤镜等等,从实质上提升RMXP的表现力,换言之就是希望能给XP多加技能点,要LEVEL UP而不是疯狂奶血再苟一阵,当然我这么说也是很不负责任啦,但无奈水平实在有限,只是一家之言请别介意,另外48地图我基本是整出来了,不过还有另外一些构想,所以大概迟些再发,大大就请专心捉虫吧


就这些了,再次感谢
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
380
在线时间
53 小时
注册时间
2023-7-16
帖子
19
2
发表于 2023-8-7 14:52:33 | 显示全部楼层
本帖最后由 zlyl_wiley 于 2023-8-8 14:46 编辑

本来只想改一下天气随屏幕大小调整,结果捉到一只BUG,就是屏幕跟窗口大小不一致的情况下,画面冻结和过渡时会瞬间缩小的问题
目前解决方法就是自行Graphics#resize_screen一下
看config.rb里面似乎并没有读取屏幕的宽高,不清楚是在哪里读取的,郭大修一下吧

然后天气稍微改动了一下,根据屏幕大小,按原来的比例调整天气的范围和数量
没什么技术含量的东西,应该出不了什么问题

-----------
更新一下脚本:

RUBY 代码复制
  1. # 屏幕大小改动过的话,目前需要先手动更新一下
  2. Graphics.resize_screen(960, 720)


RUBY 代码复制
  1. # -------------------------------------------------------------------------------------------------
  2. # RPG::Weather
  3. # -------------------------------------------------------------------------------------------------
  4. module RPG
  5.   class Weather
  6.     MULTIPLE = (Graphics.width * Graphics.height) / 307200.0 # (640 * 480.0)
  7.     PW = Graphics.width - 640
  8.     PH = Graphics.height - 480
  9.     SPRITE_MAX = (40 * MULTIPLE).to_i
  10.     def initialize(viewport = nil)
  11.       @type = 0
  12.       @max = 0
  13.       @ox = 0
  14.       @oy = 0
  15.       color1 = Color.new(255, 255, 255, 255)
  16.       color2 = Color.new(255, 255, 255, 128)
  17.       @rain_bitmap = Bitmap.new(7, 56)
  18.       (0..6).each do |i|
  19.         @rain_bitmap.fill_rect(6 - i, i * 8, 1, 8, color1)
  20.       end
  21.       @storm_bitmap = Bitmap.new(34, 64)
  22.       (0..31).each do |i|
  23.         @storm_bitmap.fill_rect(33 - i, i * 2, 1, 2, color2)
  24.         @storm_bitmap.fill_rect(32 - i, i * 2, 1, 2, color1)
  25.         @storm_bitmap.fill_rect(31 - i, i * 2, 1, 2, color2)
  26.       end
  27.       @snow_bitmap = Bitmap.new(6, 6)
  28.       @snow_bitmap.fill_rect(0, 1, 6, 4, color2)
  29.       @snow_bitmap.fill_rect(1, 0, 4, 6, color2)
  30.       @snow_bitmap.fill_rect(1, 2, 4, 2, color1)
  31.       @snow_bitmap.fill_rect(2, 1, 2, 4, color1)
  32.       @sprites = []
  33.       (1..SPRITE_MAX).each do |_i|
  34.         sprite = Sprite.new(viewport)
  35.         sprite.z = 1000
  36.         sprite.visible = false
  37.         sprite.opacity = 0
  38.         @sprites.push(sprite)
  39.       end
  40.     end
  41.  
  42.     def dispose
  43.       @sprites.each do |sprite|
  44.         sprite.dispose
  45.       end
  46.       @rain_bitmap.dispose
  47.       @storm_bitmap.dispose
  48.       @snow_bitmap.dispose
  49.     end
  50.  
  51.     def type=(type)
  52.       return if @type == type
  53.  
  54.       @type = type
  55.       bitmap = case @type
  56.                when 1
  57.                  @rain_bitmap
  58.                when 2
  59.                  @storm_bitmap
  60.                when 3
  61.                  @snow_bitmap
  62.                end
  63.       (1..SPRITE_MAX).each do |i|
  64.         sprite = @sprites[i]
  65.         unless sprite.nil?
  66.           sprite.visible = (i <= @max)
  67.           sprite.bitmap = bitmap
  68.         end
  69.       end
  70.     end
  71.  
  72.     def ox=(ox)
  73.       return if @ox == ox
  74.  
  75.       @ox = ox
  76.       @sprites.each do |sprite|
  77.         sprite.ox = @ox
  78.       end
  79.     end
  80.  
  81.     def oy=(oy)
  82.       return if @oy == oy
  83.  
  84.       @oy = oy
  85.       @sprites.each do |sprite|
  86.         sprite.oy = @oy
  87.       end
  88.     end
  89.  
  90.     def max=(max)
  91.       return if @max == max
  92.       @max = ([[max, 0].max, 40].min * MULTIPLE).to_i
  93.       (1..SPRITE_MAX).each do |i|
  94.         sprite = @sprites[i]
  95.         sprite.visible = (i <= @max) unless sprite.nil?
  96.       end
  97.     end
  98.  
  99.     def update
  100.       return if @type == 0
  101.       (1..@max).each do |i|
  102.         sprite = @sprites[i]
  103.         break if sprite.nil?
  104.  
  105.         if @type == 1
  106.           sprite.x -= 2
  107.           sprite.y += 16
  108.           sprite.opacity -= 8
  109.         end
  110.         if @type == 2
  111.           sprite.x -= 8
  112.           sprite.y += 16
  113.           sprite.opacity -= 12
  114.         end
  115.         if @type == 3
  116.           sprite.x -= 2
  117.           sprite.y += 8
  118.           sprite.opacity -= 8
  119.         end
  120.         x = sprite.x - @ox
  121.         y = sprite.y - @oy
  122.         next unless (sprite.opacity < 64) || (x < -50) || (x > 750 + PW) || (y < -300) || (y > 500 + PH)
  123.  
  124.         sprite.x = rand(-50..(749 + PW)) + @ox
  125.         sprite.y = rand(-200..(599 + PH)) + @oy
  126.         sprite.opacity = 255
  127.       end
  128.     end
  129.     attr_reader :type, :max, :ox, :oy
  130.   end
  131. end




--------------
再来个变量版
这一版多了个resize(width, height)方法,在中途更改分辨率的时候,可以不中断天气地刷新天气的范围大小
经过频繁随机$game_screen.weather和resize测试,没测出毛病来,但对自己还是不太放心……
并且大概是在浪费时间,应该不会有人在游戏中途改分辨率吧!
RUBY 代码复制
  1. # -------------------------------------------------------------------------------------------------
  2. # RPG::Weather
  3. # -------------------------------------------------------------------------------------------------
  4. module RPG
  5.   class Weather
  6.     def initialize(viewport = nil)
  7.       @multiple = (Graphics.width * Graphics.height) / 307200.0 # (640 * 480.0)
  8.       @pw = Graphics.width - 640
  9.       @ph = Graphics.height - 480
  10.       @max = (40 * @multiple).to_i
  11.       @type = 0
  12.       @ox = 0
  13.       @oy = 0
  14.       color1 = Color.new(255, 255, 255, 255)
  15.       color2 = Color.new(255, 255, 255, 128)
  16.       @rain_bitmap = Bitmap.new(7, 56)
  17.       (0..6).each do |i|
  18.         @rain_bitmap.fill_rect(6 - i, i * 8, 1, 8, color1)
  19.       end
  20.       @storm_bitmap = Bitmap.new(34, 64)
  21.       (0..31).each do |i|
  22.         @storm_bitmap.fill_rect(33 - i, i * 2, 1, 2, color2)
  23.         @storm_bitmap.fill_rect(32 - i, i * 2, 1, 2, color1)
  24.         @storm_bitmap.fill_rect(31 - i, i * 2, 1, 2, color2)
  25.       end
  26.       @snow_bitmap = Bitmap.new(6, 6)
  27.       @snow_bitmap.fill_rect(0, 1, 6, 4, color2)
  28.       @snow_bitmap.fill_rect(1, 0, 4, 6, color2)
  29.       @snow_bitmap.fill_rect(1, 2, 4, 2, color1)
  30.       @snow_bitmap.fill_rect(2, 1, 2, 4, color1)
  31.       @sprites = []
  32.       (1..@max).each do |_i|
  33.         sprite = Sprite.new(viewport)
  34.         sprite.z = 1000
  35.         sprite.visible = false
  36.         sprite.opacity = 0
  37.         @sprites.push(sprite)
  38.       end
  39.     end
  40.  
  41.     def resize(width, height)
  42.       @multiple = (width * height) / 307200.0 # (640 * 480.0)
  43.       @pw = width - 640
  44.       @ph = height - 480
  45.       @max = (40 * @multiple).to_i
  46.       if @max == @sprites.size
  47.         return
  48.       elsif @max < @sprites.size
  49.         (@max...@sprites.size).each do |i|
  50.           @sprites[i].visible = false
  51.         end
  52.       else
  53.         bitmap = case @type
  54.                  when 1
  55.                    @rain_bitmap
  56.                  when 2
  57.                    @storm_bitmap
  58.                  when 3
  59.                    @snow_bitmap
  60.                  end
  61.         viewport = @sprites[0].viewport
  62.         (@sprites.size..@max).each do |_i|
  63.           sprite = Sprite.new(viewport)
  64.           sprite.z = 1000
  65.           sprite.bitmap = bitmap
  66.           @sprites.push(sprite)
  67.         end
  68.       end
  69.     end
  70.  
  71.     def dispose
  72.       @sprites.each do |sprite|
  73.         sprite.dispose
  74.       end
  75.       @rain_bitmap.dispose
  76.       @storm_bitmap.dispose
  77.       @snow_bitmap.dispose
  78.     end
  79.  
  80.     def type=(type)
  81.       return if @type == type
  82.       @type = type
  83.       bitmap = case @type
  84.                when 1
  85.                  @rain_bitmap
  86.                when 2
  87.                  @storm_bitmap
  88.                when 3
  89.                  @snow_bitmap
  90.                end
  91.       (0..[@max, @sprites.size].max).each do |i|
  92.         sprite = @sprites[i]
  93.         unless sprite.nil?
  94.           sprite.visible = (i <= @max)
  95.           sprite.bitmap = bitmap
  96.         end
  97.       end
  98.     end
  99.  
  100.     def ox=(ox)
  101.       return if @ox == ox
  102.  
  103.       @ox = ox
  104.       @sprites.each do |sprite|
  105.         sprite.ox = @ox
  106.       end
  107.     end
  108.  
  109.     def oy=(oy)
  110.       return if @oy == oy
  111.  
  112.       @oy = oy
  113.       @sprites.each do |sprite|
  114.         sprite.oy = @oy
  115.       end
  116.     end
  117.  
  118.     def max=(max)
  119.       return if @max == (max * @multiple).to_i
  120.       last = @max
  121.       @max = ([[max, 0].max, 40].min * @multiple).to_i
  122.       ([last, @max].min...@sprites.size).each do |i|
  123.         @sprites[i].visible = (i <= @max)
  124.       end
  125.     end
  126.  
  127.     def update
  128.       return if @type == 0
  129.       (0..@max).each do |i|
  130.         sprite = @sprites[i]
  131.         break if sprite.nil?
  132.  
  133.         if @type == 1
  134.           sprite.x -= 2
  135.           sprite.y += 16
  136.           sprite.opacity -= 8
  137.         end
  138.         if @type == 2
  139.           sprite.x -= 8
  140.           sprite.y += 16
  141.           sprite.opacity -= 12
  142.         end
  143.         if @type == 3
  144.           sprite.x -= 2
  145.           sprite.y += 8
  146.           sprite.opacity -= 8
  147.         end
  148.         x = sprite.x - @ox
  149.         y = sprite.y - @oy
  150.         next unless (sprite.opacity < 64) || (x < -50) || (x > 750 + @pw) || (y < -300) || (y > 500 + @ph)
  151.  
  152.         sprite.x = rand(-50..(749 + @pw)) + @ox
  153.         sprite.y = rand(-200..(599 + @ph)) + @oy
  154.         sprite.opacity = 255
  155.       end
  156.     end
  157.     attr_reader :type, :max, :ox, :oy
  158.   end
  159. end

点评

一般情况下只在游戏开始的时候改一下分辨率比较好,大部分游戏都是这样的,改变分辨率后要重启>_<。我先记下了,等1.1.0出来再统一改bug  发表于 2023-8-18 22:47
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
380
在线时间
53 小时
注册时间
2023-7-16
帖子
19
3
发表于 2023-9-16 00:40:29 | 显示全部楼层
本帖最后由 zlyl_wiley 于 2023-9-22 23:31 编辑

(编辑)好吧,把问题说出来之后我自己就理清楚思路了。。小黄鸭DEBUG了属于是,。。已经统一采用#text_size测量高度了,很抱歉冒昧打扰了,不知道该不该删帖,总之不看也罢。。
另外我在第十页最后一贴有一些关于RGM的使用反馈,可能刚好翻页大佬没看见,顺便再次请求简单回复一下,或者在1.1发布时再统一回复也好,我确定我会是比较重度的使用者,但属于人菜瘾大,所以今后大概还会时常需要大佬的技术支持,最近我也在造轮子,当然跟重写一个RT完全不在一个档次,但也体会到了个中的艰辛,真的很佩服各位大神,再次感谢!
-------

不好意思又是我
最近在写一个图文排版的脚本,并且目标是要兼容RGM、RGU和原版RT,然后出现了一个问题,就是三个RT对Font#size的表现各异,导致了相同的代码和文档在排版之后会呈现不同的效果
这个问题发生在高度大于宽度的字体上,原版RT的处理是将字体的长边限制在Font#size然后按比例缩小,而RGM和RGU是让短边等于Font#size,长边按比例放大,即Bitmap#text_size的height会大于Font#size,这样,将Font#size作为Bitmap#draw_text的height参数时,原版字体不会超出rect的范围,而两个第三方RT超出,但表现又不一样,RGU在绘制时会将字体居中于绘制框,这样字体上下两端会被截掉,而RGM是顶对齐,所以字体下方会被截掉,再一个,我现在碰到的出问题的字体,它上下超出的部分其实是空白的,所以RGU的表现其实刚刚好,比原版RT还完美,而RGM变成顶端留白下方缺失,效果比较难以接受,具体见下图
这个问题困扰了我很久,首先这应该不算是BUG,其次我不知道其它字体还有多少存在这种情况,它们超出部分是不是也是空白的,为了兼容各个RT,我已经在脚本里加了很多判断分歧,而这个问题牵涉比较广,再加恐怕代码会非常臃肿,而且频繁#text_size也实在是浪费,所以不得已来请教一下郭大的意见,我个人的想法是希望RGM能跟RGU一样居中,先不管其它字体是否还有隐患,但即使最终脚本仍然难逃大改,但至少两者效果能够统一肯定是好事

RGM,字体大小与RGU一致,只是绘制的位置不同:


RGU,字体垂直居中,上下空白被截后,在Font#size为高度的绘制范围内刚好顶天立地:


原版,字体大小与第三方的两位不同,所以自动换行也不同,字体在Font#size为高度的绘制框中上下留有白边:


其它测试用的涂鸦:



点评

个人看法是,字超出框是ub,runtime想怎么实现都可以,不过确实可以增加一个设置,让它居中或者对齐吧  发表于 2023-9-30 22:51
回复 支持 反对

使用道具 举报

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

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-5-10 06:36

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表