Project1

标题: 请问P1P2的地方的变量 [打印本页]

作者: kvkv97    时间: 2023-10-15 21:15
标题: 请问P1P2的地方的变量
module Mercenaries
  class Window_Help < ::Window_Base
    def initialize
      super(0, 0, 196, 256)
      self.contents = Bitmap.new(width - 32, height - 32)
      @actor = nil
      self.z += 10
    end
    def draw_actor(actor)
      if @actor != actor
        self.contents.clear
        bitmap = RPG::Cache.battler(actor.battler_name, actor.battler_hue)
        bx=0
        by=0
        self.contents.blt(bx, by, bitmap, bitmap.rect, 196)
        self.contents.draw_text(4, 4 + 0, 196, 18, "价格:" + actor.price.to_s)
        self.contents.draw_text(4, 4 + 20, 196, 18, "姓名:" + actor.name)
        self.contents.draw_text(4, 4 + 40, 196, 18, "职业:" + actor.class_name)
        self.contents.draw_text(4, 4 + 60, 196, 18, "武器:#{$data_weapons[actor.weapon_id].name}")
        self.contents.draw_text(4, 4 + 80, 196, 18, "铠甲:#{$data_armors[actor.armor3_id].name}")
        self.contents.draw_text(4, 4 + 100, 196, 18, "攻击力:#{actor.atk}")
        self.contents.draw_text(4, 4 + 120, 196, 18, "防御力:#{actor.pdef}")
        self.contents.draw_text(4, 4 + 140, 196, 18, "魔御力:#{actor.mdef}")
        self.contents.draw_text(4, 4 + 160, 196, 18, "力量:#{actor.str}")
        self.contents.draw_text(4, 4 + 180, 196, 18, "灵巧:#{actor.dex}")
        self.contents.draw_text(4, 4 + 200, 196, 18, "速度:#{actor.agi}")
        self.contents.draw_text(4, 4 + 220, 196, 18, "魔力:#{actor.int}")
        @actor = actor
      end
    end
  end #帮助窗口
  class Window_ShopCommand<Window_Selectable
    def initialize
      super(80, 90 - 64, 480, 64)
      self.contents = Bitmap.new(width - 32, height - 32)
      @item_max = 3
      @column_max = 3
      @commands = ["雇佣", "解除", "取消"]
      refresh
      self.index = 0
    end
    def refresh
      for i in [email protected]
        self.contents.draw_text(i*160,0,128,32,@commands)
      end
    end
  end #买卖窗口
  class Window_Mercenaries<::Window_Selectable
    attr_reader   :column_max
    attr_reader   :mercenaries
    def initialize(mercenaries)
      super(80, 90, 480, 320)
      @mercenaries = mercenaries
      @column_max = 7
      refresh
      self.index = 0
    end
    def set_mercenaries(mercenaries)
      @mercenaries = mercenaries
      refresh
    end
    def id
      return @mercenaries[self.index]
    end
    def refresh
      if self.contents != nil
        self.contents.dispose
        self.contents = nil
      end
      @item_max = @mercenaries.size
      if @item_max > 0
        self.contents = Bitmap.new(width - 32, row_max * 80)
        for i in 0...@item_max
          draw_actor(i)
        end
      end
    end
    def draw_actor(index)
      x = index % @column_max * 64
      y = index / @column_max * 80
      actor = $game_actors[@mercenaries[index]]
      bitmap = RPG::Cache.character(actor.character_name,actor.character_hue)
      rect = bitmap.rect
      rect.width /= 4
      rect.height /= 4
      self.contents.blt(x, y, bitmap, rect)
      self.contents.font.size = 12
      self.contents.draw_text(x, y + 64 -8, 64, 16, actor.name)
      self.contents.font.size = 9
      self.contents.draw_text(x, y + 64 -16, 64, 16,
                              "Lv."+sprintf("%02d", actor.level))
    end
    #--------------------------------------------------------------------------
    # ● 更新光标举行
    #--------------------------------------------------------------------------
    def update_cursor_rect
      # 光标位置不满 0 的情况下
      if @index < 0
        self.cursor_rect.empty
        return
      end
      # 获取当前的行
      row = @index / @column_max
      # 当前行被显示开头行前面的情况下
      if row < self.top_row
        # 从当前行向开头行滚动
        self.top_row = row
      end
      # 当前行被显示末尾行之后的情况下
      if row > self.top_row + (self.page_row_max - 1)
        # 从当前行向末尾滚动
        self.top_row = row - (self.page_row_max - 1)
      end
      # 计算光标的宽
      cursor_width = self.width / @column_max - 32
      # 计算光标坐标
      x = @index % @column_max * 64
      y = @index / @column_max * 80 - self.oy
      # 更新国标矩形
      self.cursor_rect.set(x, y, 64, 80)
    end
  end #雇佣与解雇窗口

  class Scene_Mercenaries
    def initialize(mercenaries)
      @mercenaries = mercenaries
      for actor in $game_party.actors
        if @mercenaries.include?(actor.id)
          @mercenaries.delete(actor.id)
        end
      end
      @windows = []
      @temp = @mercenaries.dup
  
    end
    def main_start
      make_window
      @spriteset = Spriteset_Map.new
    end
    def main_loop
      while $scene == self
        rm_update
        update_window
        input_update
     end
    end
    def main_end
      dispose_window
      @spriteset.dispose
    end
    def main
      main_start
      Graphics.transition
      main_loop
      Graphics.freeze
      main_end
    end
    def make_window
      @window_shopcommand = Window_ShopCommand.new #最上面的窗口
      @window_help = Window_Help.new               #帮助窗口
      @window_mercenaries = Window_Mercenaries.new(@mercenaries)#下面的窗口
      @window_mercenaries.active = false
      @window_mercenaries.index = -1
      @window_gold = Window_Gold.new
      @window_gold.x = 640 - @window_gold.width - 32    #右下角窗口
      @window_gold.y = 480 - @window_gold.height - 32
      @windows << @window_gold << @window_shopcommand << @window_mercenaries << @window_help
      @window_help.visible = false
    end
    def update_window
      @windows.each{ |window|window.update }
      help_update
    end
    def help_update
      if @window_mercenaries.active
        @window_help.visible = true
        
        wx = (@window_mercenaries.index % @window_mercenaries.column_max * 64)
        wy = (@window_mercenaries.index / @window_mercenaries.column_max * 80)

        @window_help.x = wx + @window_mercenaries.x + 64
        @window_help.y = wy + @window_mercenaries.y + 80
        if @window_help.x + @window_help.width > 640
          @window_help.x = 640 - @window_help.width
        end
        if @window_help.y + @window_help.height > 480
          @window_help.y = 480 - @window_help.height
        end
        @window_help.draw_actor($game_actors[@window_mercenaries.id])
      else
        @window_help.visible = false
      end
    end
    def rm_update
      Graphics.update
      Input.update
    end
    def input_update
      if Input.trigger?(Input::B)
        @window_shopcommand.active = true
        @window_mercenaries.active = false
        @window_mercenaries.index = -1
        return
      end
      if Input.trigger?(Input::C)
        if @window_shopcommand.active
          case @window_shopcommand.index
          when 0  #雇佣窗口
            @window_mercenaries.set_mercenaries(@temp)
            @type = 0
            @window_shopcommand.active = false
            @window_mercenaries.active = true
            @window_mercenaries.index = 0
            return
          when 1 #解雇窗口
            actors = []
            for actor in $game_party.actors
              actors << actor.id
            end
            @window_mercenaries.set_mercenaries(actors)
            @type = 1
            @window_shopcommand.active = false
            @window_mercenaries.active = true
            @window_mercenaries.index = 0
            return
          when 2
            $scene = Scene_Map.new
            return
          end
        end
        case @type
        when 0  #雇佣
          if $game_party.gold >= $game_actors[@window_mercenaries.id].price
            if $game_party.actors.size < 4
              $game_party.lose_gold($game_actors[@window_mercenaries.id].price)
              $game_party.add_actor(@window_mercenaries.id)
              #@temp=[2,3,4,5,6,7,8,9]
p  @temp
              @window_mercenaries.mercenaries.delete(@window_mercenaries.id)
             #@temp=[3,4,5,6,7,8,9]
p  @temp
              @window_mercenaries.refresh
              if @window_mercenaries.index > @window_mercenaries.mercenaries.size-1
                @window_mercenaries.index = @window_mercenaries.mercenaries.size-1
              end
            end
          end
        when 1  #解雇
          if @window_mercenaries.id != 1
            $game_party.gain_gold($game_actors[@window_mercenaries.id].price / 2)
            $game_party.remove_actor(@window_mercenaries.id)
            @temp << @window_mercenaries.id
            @window_mercenaries.mercenaries.delete(@window_mercenaries.id)
            @window_mercenaries.refresh
            if @window_mercenaries.index > @window_mercenaries.mercenaries.size-1
              @window_mercenaries.index = @window_mercenaries.mercenaries.size-1
            end
          end
        end
        
        @window_gold.refresh
      end
    end
    def dispose_window
      @windows.each{ |window|window.dispose }
    end
  end #雇佣场景类
end
class Game_Actor
  def price
    price = @name.split(/,/)[1].nil? ? 0 : @name.split(/,/)[1].to_i
    return price * self.level
  end
  def name
    return @name.split(/,/)[0]
  end
end

我在程序的后面的case @type为0的时候,分别在@window_mercenaries.mercenaries.delete(@window_mercenaries.id)的前面和后面P @temp,我雇佣了2号角色,为什么数组里面的2会消失?
数组@temp接收来自类里面的@mercenaries的数值,而在这句程序段里面,数组mercenaries是
@window_mercenaries的实际变量而不是雇佣场景类的实际变量,虽然变量的名称相同,请问:雇佣场景类的可以用实际变量可以用同名的@window_mercenaries的实际变量吗?
作者: qq634488405    时间: 2023-10-16 10:24
数组指针的问题。在Scene_Mercenaries里传入的mercenaries是个纯数字的数组,用dup复制没毛病
f Input.trigger?(Input::C)
        if @window_shopcommand.active
          case @window_shopcommand.index
          when 0  #雇佣窗口
            @window_mercenaries.set_mercenaries(@temp)
            @type = 0
            @window_shopcommand.active = false
            @window_mercenaries.active = true
            @window_mercenaries.index = 0
            return
在这里雇佣的时候把@temp传给了window_mercenaries的@mercenaries,由于set方法里使用的@mercenaries=mercenaries
这里实际是把@temp的指针赋值给@mercenaries,这意味着window里的@mercenaries和scene里的@temp指向的是同一个数组,也就是说改变window的@mercenaries也会影响scene里的@temp
因此window.mercenaries.delete也就等效于@temp.delete。
不同类的变量的名称相同与否都没关系。数组的赋值并不是复制。传入的参数为纯数字数组时,建议使用dup/clone,以避免此类情况发生,当然若是想要两者关联起来那直接=
另外如果数组中包含对象时,使用dup/clone也无法复制,建议使用Marshal::load(Marshal.dump(obj))来复制
作者: qq634488405    时间: 2023-10-16 22:29
这就是一个容易搞混的概念,数组是Array类的实例对象,虽然数组的一些运算和方法看起来与整形浮点等变量差不多,但两者是不一样的
数组可以理解成指针或者内存地址
就拿你的脚本来说:
a=[2,3,4,5,6,7,8],内存空间中[2,3,4,5,6,7,8],让a指向这块内存,方便起见把它称作A
$scene=Mercenaries::Scene_Mercenaries.new(a)初始化scene,传入a
初始化中,@mercenaries = mercenaries,这一步使得scene的@mercenaries同样也指向了A这块内存空间
@temp = @mercenaries.dup,这一步单独开辟一块B空间,里面内容是[2,3,4,5,6,7,8],@temp指向这块B空间
make_window初始化各种window,其中Window_Mercenaries中又使用了@mercenaries = mercenaries
于是window的@mercenaries也指向了A这块空间,在这个时候,scene和window各自的@mercenaries都指向了同一块内存地址A,而@temp是单独的B
在进行雇佣操作的时候,先执行了@window_mercenaries.set_mercenaries(@temp),在set_mercenaries方法中使用了@mercenaries = mercenaries
此时,window.mercenaries被修改成指向内存空间B,也就是和@temp是相同的地址
所以接下来雇佣时,从window.mercenaries删除元素时,p @temp时打印出的结果自然也没有,而此时scene.mercenaries并不会改变
总结来说,在方法中传入参数是数组的时候,传入的并不是该数组每个元素的值,而是数组所指向的内存地址的值
可以按一下方式来定义方法
def a(b)
  @c=b.dup  #数组中不含有对象,可以使用此语句
  @d=Marshal::load(Marshal.dump(b))   #数组中不论是否含有对象都可使用此语句
end
或者在调用方法的时候,使用a(b.dup)
作者: kvkv97    时间: 2023-10-17 21:10
请问:        when 1  #解雇
          if @window_mercenaries.id != 1
            $game_party.gain_gold($game_actors[@window_mercenaries.id].price / 2)
            $game_party.remove_actor(@window_mercenaries.id)
            @temp << @window_mercenaries.id
            @window_mercenaries.mercenaries.delete(@window_mercenaries.id)
            @window_mercenaries.refresh
            if @window_mercenaries.index > @window_mercenaries.mercenaries.size-1
              @window_mercenaries.index = @window_mercenaries.mercenaries.size-1
            end
          end
既然@window_mercenaries的实例变量@mercenaries变为[3,4,5,6,7,8]——(我雇佣2号),那为什么在P1和P2的地方,@window_mercenaries.id的值依然是2,而不是nil呢?

作者: kvkv97    时间: 2023-10-18 21:30
本帖最后由 kvkv97 于 2023-10-18 21:33 编辑

我的意思是:
出现问题的地方是P1和P2的地方。P1的时候, @window_mercenaries.mercenaries的实际变量是@window_mercenaries类里面的@mercenaries,它的值是[2,3,4,5,6,7,8],现在P2的时候,我雇佣2号角色,经过方法的改造,@window_mercenaries里面的@mercenaries,它的值是[3,4,5,6,7,8],但是,@window_mercenaries.id的方法是id,它是这样定义的:return @mercenaries[self.index]问题来了:
既然,@window_mercenaries类里面的实际变量 @mercenaries经过delete方法的改造,从P1的[2,3,4,5,6,7,8]变为P2的[3,4,5,6,7,8],既然 @mercenaries的值在P1和P2已经变了,那么作为@window_mercenaries类里面的实际变量 @mercenaries也应该发生变化,从P1的[2,3,4,5,6,7,8]变为P2的[3,4,5,6,7,8],那为什么方法id(@window_mercenaries类里面的方法)返回的是依然是P1的时候的[2,3,4,5,6,7,8]里面的2而不是P2的时候的[3,4,5,6,7,8]里面的nil。因为@mercenaries[self.index],在@mercenaries的值变化的情况下(从P1到P2),它也应该变化才对,从2(我雇佣2号角色)变为nil,这样才能符合@mercenaries的值的变化

作者: qq634488405    时间: 2023-10-19 08:44
kvkv97 发表于 2023-10-18 21:30
我的意思是:
出现问题的地方是P1和P2的地方。P1的时候, @window_mercenaries.mercenaries的实际变量是@wi ...

RUBY 代码复制
  1. when 0  #雇佣
  2.           if $game_party.gold >= $game_actors[@window_mercenaries.id].price
  3.             if $game_party.actors.size < 4
  4.               $game_party.lose_gold($game_actors[@window_mercenaries.id].price)
  5.               $game_party.add_actor(@window_mercenaries.id)
  6.               #@temp=[2,3,4,5,6,7,8,9]
  7. p  @temp
  8.               @window_mercenaries.mercenaries.delete(@window_mercenaries.id)
  9.              #@temp=[3,4,5,6,7,8,9]
  10. p  @window_mercenaries.id
  11.               @window_mercenaries.refresh
  12.               if @window_mercenaries.index > @window_mercenaries.mercenaries.size-1
  13.                 @window_mercenaries.index = @window_mercenaries.mercenaries.size-1
  14.               end
  15.             end
  16.           end


delete之后再p @window_mercenaries.id,结果是3,这没问题啊
雇佣2以后@mercenaries=[3,4,5,6,7,8],雇佣的时候window的index=0
雇佣操作并没有改变index,所以雇佣后,id返回的就是此时数组中的第一个元素3
delete删除的方法是匹配并删除元素,再将后面的元素往前移位
这时候再去调用id返回的就是3

def id
      return @mercenaries[self.index]
end
作者: kvkv97    时间: 2023-10-21 21:24
        when 1  #解雇窗口
          if @window_mercenaries.id != 1
            $game_party.gain_gold($game_actors[@window_mercenaries.id].price / 2)
            $game_party.remove_actor(@window_mercenaries.id)
            @temp << @window_mercenaries.id
            @window_mercenaries.mercenaries.delete(@window_mercenaries.id)
            #@mercenaries=[1]
            @window_mercenaries.refresh
#            if @window_mercenaries.index > @window_mercenaries.mercenaries.size-1
#             @window_mercenaries.index = @window_mercenaries.mercenaries.size-1
#           end
          end
        end

我注释掉上面的3行代码。雇佣2号角色,然后解雇,为什么出现错误?为什么把光标的@window_mercenaries.index调整后就不会错误?




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