Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Inherit 2 classes

So ruby doesn't support multiple inheritance, so I'm told.

I want to make a class inherit both Game_Actor and Game_Enemy.
I made this code, which works fine, but I'm wondering

is there an easier way ?

[rgss]class Enemy_and_Actor < Game_Actor
 
#=============================================================
# * Inherit_Game_Enemy
#
# The only purpose of this module is to add methods from
# Game_Enemy to this class.
# Instead of doing: @enemy.gold, you can call: gold
# This isn't only for convenience. Other classes will use this class
# instead of Game_Enemy, so they may call actor_enemy.gold
#=============================================================
  module Inherit_Game_Enemy
   
    def def_enemy_methods
     # get a list of methods in Game_Enemy
      methods = Game_Enemy.instance_methods - Game_Battler.instance_methods
      # extract methods with arguments
      special = [ 'initialize','element_rate','state_guard?','transform' ]
      methods = methods - special
     # create the methods using eval.
      for method in methods
        code =   "def #{method.to_s}" + "; "
        code +=    "@enemy.#{method}" + "; "
        code +=  "end"
        Inherit_Game_Enemy.module_eval(code)
      end
    end
   
    #=================================
    # Define methods with arguments
    #=================================
   
    def transform(enemy_id)
      @enemy.transform(enemy_id)
    end
   
    def element_rate(element_id)
      @enemy.element_rate(element_id)
    end
   
    def state_guard?(state_id)
      @enemy.state_guard?(state_id)
    end
   
  end
 
  extend Inherit_Game_Enemy
  include Inherit_Game_Enemy
 
  def initialize(id)
    super(id)
    @enemy = Game_Enemy.new(1,0)
    # Once we have an enemy, define enemy methods in the module.
    def_enemy_methods
    # call a method of game_enemy
    p "testing access: enemy's gold = #{gold},"
  end
 
  def is_a?(clas)
    return (super or clas == Game_Enemy)
  end
 
end
[/rgss]
 
Not entirely sure this would work (the idea should, but the syntax might be wrong), but I would suggest
[rgss]    def def_enemy_methods
     # get a list of methods in Game_Enemy
      methods = Game_Enemy.instance_methods - Game_Battler.instance_methods
      # extract initialize method
      special = ['initialize']
      methods = methods - special
     # create the methods using eval.
      for method in methods
        code =   "def #{method.to_s}(*args)" + "; "
        code +=    "@enemy.#{method}(*args)" + "; "
        code +=  "end"
        Inherit_Game_Enemy.module_eval(code)
      end
    end
[/rgss]
instead of
[rgss]    def def_enemy_methods
     # get a list of methods in Game_Enemy
      methods = Game_Enemy.instance_methods - Game_Battler.instance_methods
      # extract methods with arguments
      special = [ 'initialize','element_rate','state_guard?','transform' ]
      methods = methods - special
     # create the methods using eval.
      for method in methods
        code =   "def #{method.to_s}" + "; "
        code +=    "@enemy.#{method}" + "; "
        code +=  "end"
        Inherit_Game_Enemy.module_eval(code)
      end
    end
   
    #=================================
    # Define methods with arguments
    #=================================
   
    def transform(enemy_id)
      @enemy.transform(enemy_id)
    end
   
    def element_rate(element_id)
      @enemy.element_rate(element_id)
    end
   
    def state_guard?(state_id)
      @enemy.state_guard?(state_id)
    end
[/rgss]

The * converts the arguements into an array or something, so it's good when aliasing/doing things like this if you don't know how many arguements you're passing.
 
oh, trust me, I've been there.
calling initialize(*args) works fine until your method calls 'super'.
the arguments for super are somehow REPLACED with args, which causes bugs.

It doesn't seem like Ruby is built to do this.
I had this script which defined initialize(*args) using eval. I've worked on it for weeks, with no success. I swear I tried everything under the sun o.o;
 
hum you're aware that super can take arguments right ? :) (like super(*args)

and no there's no multiple inheritance in ruby. What you can try is to create module that will hold the functions you want to share, and mix-it in the class with "mixin module_name". and all the class with that mixin will be able to use natively the methods from that module.
 
Yeah I'm aware of that, and my code already does what you said ;)
consider this:
using intialize(*args) for
[rgss]class Window_Command < Window_Selectable
 
  def initialize(width, commands)
    super(0, 0, width, commands.size * 32 + 32)
    #rest of method
  end
end
[/rgss]
will cause an error: 'wrong number of arguments: 2 for 4'
Note I was aliasing the initialize method, and doing so with eval. a more simple use of initialize(*args) might work, I'm not sure.
 
well *args return the current arguments :) in an local variable array called "args"

you can use that array to test the number of arguments and do different things
like
if args.size == 2


so if you use it in the super, ... it might not work, as in your example:
the current class has only 2 arguments when called. so args.size == 2 :)
but the window_selectable (called by super, means call the initialize method of the parent class) needs 4 arguments.. so if you just give args to it.. it'll crash because it misses 2 other arguments.
Hope it helps :)
 
You got me all wrong, I'm NOT giving args to the super class..
I'm not changing anything in initialize, just aliasing it. Yet somehow, the arguments super receives are swapped with *args. :mystery:
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top