Project1

标题: 关于图片渐变 [打印本页]

作者: playmaker    时间: 2022-5-24 23:37
标题: 关于图片渐变
以下是渐变脚本
def gc_pic(str)
  devil = Sprite.new
  devil.bitmap = Bitmap.new(str)
  devil.ox=devil.bitmap.width/2
  devil.oy=devil.bitmap.height/2
  devil.zoom_x=0.9
  devil.zoom_y=0.9
  devil.x=320
  devil.y=240
  for opa in 0..127
    devil.opacity=opa
    Graphics.update
  end
end

虽然成功实现了渐变效果,但是由于Graphics.update这个方法10s不调用会失效,所以显示的图片仅能保留10秒
想请问一下有什么办法能够一直显示,并且当我想要他消失时消失
ps,试过了脚本运行完后使用自带的显示图片功能,但效果是透明度会叠加,效果不如意
作者: 灯笼菜刀王    时间: 2022-5-25 00:13
本帖最后由 灯笼菜刀王 于 2022-5-25 00:15 编辑

XP自带指令
1显示图片- 透明度0
  移动图片- 透明度127
2图片消失

注意渐变需要时间, 所以需要连续执行时要考虑预留等待时间
作者: playmaker    时间: 2022-5-25 09:55
学习了,谢谢!
作者: playmaker    时间: 2022-5-25 10:39
本帖最后由 playmaker 于 2022-5-25 10:41 编辑

不过如果我想用脚本实现相同的功能的话需要怎么做呢
比较好奇系统内部是怎么实现图片的显示的
之前尝试过
def show_pic(num,name)
###  name, origin, x, y, zoom_x, zoom_y, opacity, blend_type
  pic=Game_Picture.new(1)
  pic.show(name,320,320,240,0.9,0.9,127,1)
end

但似乎并没有作用

作者: 灯笼菜刀王    时间: 2022-5-25 11:58
要脚本写法, 你原来的那个, 只要在sprite变量前面加个 @ 就可以了, 实变量就不会被刷新掉咯
作者: playmaker    时间: 2022-5-25 17:23
本帖最后由 playmaker 于 2022-5-25 17:27 编辑

def show_pic(num,name)
  
  for opa in 0..127
    $game_screen.pictures[1].show(name,320,320,240,90,90,opa,0)
    #Graphics.update
   # $game_screen.update()
  end

end
通过这个函数可以显示图片,但却不能通过循环控制透明度,即使加上$game_screen.update()也不行
尝试通过Graphics.update进行操作,但结果是会出现一段时间空白,到最后才出现图片
请问这两个现象的原因是什么呢
个人推测:
1)rm会自己每隔一帧更新一次画面,但由于循环速度过快使得所有的循环在更新周期内结束掉了,所以直接会显示出最后的画面,所以需要每次循环调用一次更新函数,但$game_screen.update()并没有达到预期目标
2)暂时没有想到

补充:尝试通过sleep控制循环速度,但结果是程序卡死
for opa in 0..12700
    $game_screen.pictures[1].show(name,320,320,240,90,90,opa%127,0)
    sleep(0.1)
    #$game_screen.update()
   # Graphics.update
   
  end
作者: guoxiaomi    时间: 2022-5-26 00:30
本帖最后由 guoxiaomi 于 2022-5-26 00:47 编辑

rgss是一个同步模型,只会在执行Graphics.update显示画面,同时Graphics.update还提供了锁定帧率和10s报错的功能。

你这边最大的问题是没搞清楚变量的生命周期。比如你主楼里的函数中产生了临时变量devil是一个Sprite,只要devil仍然存活,那么每次Graphics.update时,devil都会被绘制到画面上,但因为devil是临时变量,在退出作用域后随时可能被GC,一旦被GC,那么在下一次Graphics.update时,devil就会从画面上消失。

所以你要做2件事:
1. 让devil这个Sprite持续存活,直到你主动释放;
2. 每帧更新devil的状态;

前者你可以用一个全局变量存储 devil,比如
  1. def gc_pic(str)
  2.   devil = Sprite.new
  3.   devil.bitmap = Bitmap.new(str)
  4.   devil.ox = devil.bitmap.width/2
  5.   devil.oy = devil.bitmap.height/2
  6.   devil.zoom_x = 0.9
  7.   devil.zoom_y = 0.9
  8.   devil.x = 320
  9.   devil.y = 240
  10.   devil.opacity = 0
  11.   return devil
  12. end

  13. $devil = gc_pic("devil")
复制代码


后者你需要找一个每帧都会执行一次的函数,把你想要的流程放进去。比如建立一个并行的公共事件,添加脚本:
  1. if $devil
  2.   $devil.opacity += 1
  3.   if $devil.opacity == 127
  4.     $devil.dispose
  5.     $devil = nil
  6.   end
  7. end
复制代码


如果你想在脚本中执行,那可以考虑到Scene_Map的update方法也是每帧一次:
  1. class Scene_Map
  2.   alias _devil_update update
  3.   def update
  4.     _devil_update
  5.     if $devil
  6.       $devil.opacity += 1
  7.       if $devil.opacity == 127
  8.         $devil.dispose
  9.         $devil = nil
  10.       end
  11.     end
  12.   end
  13. end
复制代码


当然,如果你要继续考虑到切换到菜单场景的时候,这个图片也要跟随消失,并且切回来的时候图片还要能回来……那么就要参照Spriteset_Map中的实例变量@picture_sprites来做了,注意这段代码:
  1.     # 生成图片
  2.     @picture_sprites = []
  3.     for ii in 1..50
  4.       @picture_sprites.push(Sprite_Picture.new(@viewport2,
  5.         $game_screen.pictures[ii]))
  6.     end
复制代码

$game_screen.pictures中保存的是Game_Picture对象。Game_Picture不是Sprite,只是存储了某个Sprite的x,y,zoom_x等属性的纯数据类。每次切回地图场景时,创建Spriteset_Map对象时都会根据$game_screen.pictures的数据,重新创建一组Sprite_Picture,从而图片就又显示出来了;而每次离开地图场景时,Spriteset_Map对象释放,其实例变量@picture_sprites保存的各个Sprite_Picture也随之释放,图片不再显示。但是图片的属性仍然保存在$game_screen.pictures中,等待下一次进入地图场景时读取。
作者: playmaker    时间: 2022-5-26 23:49
基本了解了,谢谢各位解答




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