Hi people
I currently get requested by Vexed Enigma for making a battle system similar to Parasite Eve I
so this more a opinion I ask because I am the type to Divide my information in multiple section (EG : Sprite Class handle all the graphics and such)
but my battle system handle a lot of datas and a lot of them move to a class to a another class
so I wounder if my main Class where all most of the information is handle should be a Module or a Class?
I know Modules are good for making Data information and such but this not to much fragile for support heavy data?
Class can support as well the heavy data (like algorythm and such) but I found this was hard to swap information and data between each class... (EG: class Custom to Game_Map)
so can I have your opinion if I should use Module or Class ? (for support data who move a lot between each class)
thanks for your further answer!
Module or class?
● ARCHIVED · READ-ONLY
-
-
I would go with class if I want to make new objects and store data dynamically.
I would go with module if I want to make a static / constant configurations
Also, if it's a general function, I would go with the module as well. For example in my grid battle system (which is still in development), I use module to calculate the grid position instead of putting them into the class. The terms is like Math module where you can use Math.cos everywhere. -
okai sound legit if I show a exemple of one of my module who not change a lot but this permit to handle my datas
I guess this one is a good way of using the module?
Code:module Dynamic_Character_Pose class << attr_accessor :frame attr_accessor :pose attr_accessor :situation end def self.init @pose = "" @chara = Game_actor.name @frame = 0 @situation = 0 end def self.define_pose unless classic_pose @pose ~= Skill.note "/<@pose>/" endenddef self.classic_pose(pose,frame) case @situation when 0 # no move @pose = @chara.to_s + "_Iddle" when 1 # move @pose = "" when 2 # dash @pose = @chara.to_s + "_Dash" endendend -
I would go with class instead. I never use module to store data
Mostly I use module to make something like this. To counting grid
SpoilerCode:#===============================================================================# TSBS Addon - Grid Battle System (Pre-Alpha)# Version : 0.1#-------------------------------------------------------------------------------# * Configuration part#===============================================================================module Grid MaxRow = 3 MaxCol = 4 PosDebug = true # Display dummy box for positioning Party = [ [302,169],[356,169],[414,169],[471,169], [304,222],[360,222],[422,222],[482,222], [306,270],[364,270],[430,270],[493,270], ] # Troop grid coordinate should be reversed Troop = [ [244,169],[188,169],[132,169],[ 77,169], [242,222],[184,222],[126,222],[ 66,222], [240,270],[180,270],[114,270],[ 55,270], ] end#===============================================================================# * Grid Counting Module#===============================================================================class << Grid #---------------------------------------------------------------------------- # * Grid direction rules #---------------------------------------------------------------------------- # 2 = DOWNWARD # 4 = FORWARD # 6 = BACKWARD # 8 = UPWARD # # 1 = DOWN-LEFT # 3 = DOWN-RIGHT # 7 = UP-LEFT # 9 = UP-RIGHT #---------------------------------------------------------------------------- # * Get neighbor grid #---------------------------------------------------------------------------- def neighbor(index, dir) coordinate = index coordinate = point(index) unless index.is_a?(Array) case dir when 2; coordinate[1] += 1 # DOWN when 4; coordinate[0] -= 1 # FORWARD when 6; coordinate[0] += 1 # BACKWARD when 8; coordinate[1] -= 1 # UP # Diagonal direction when 1 coordinate[0] -= 1 coordinate[1] += 1 when 3 coordinate[0] += 1 coordinate[1] += 1 when 7 coordinate[0] -= 1 coordinate[1] -= 1 when 9 coordinate[0] += 1 coordinate[1] -= 1 end return cell(*coordinate) end #----------------------------------------------------------------------------- # Translate point coordinate [x,y] into Cell Index # > Column equal as X axis # > Row equal as Y axis #----------------------------------------------------------------------------- def cell(col, row) return nil if out_of_bound?(row, 0, Grid::MaxRow - 1) return nil if out_of_bound?(col, 0, Grid::MaxCol - 1) return (Grid::MaxCol * row) + col end #----------------------------------------------------------------------------- # * Translate cell index into point [x,y] #----------------------------------------------------------------------------- def point(index) return [index % Grid::MaxCol, index / Grid::MaxCol] end #----------------------------------------------------------------------------- # * Simply check if the value is out of bound #----------------------------------------------------------------------------- def out_of_bound?(value, min, max) return value > max || value < min end #----------------------------------------------------------------------------- # * Max Index #----------------------------------------------------------------------------- def max_index Grid::MaxRow * Grid::MaxCol end #----------------------------------------------------------------------------- # TARGETING PART! #----------------------------------------------------------------------------- # * Surrounding grid #----------------------------------------------------------------------------- def surrounding(index, directions = Grid::Movement, compact = true) result = directions.collect {|dir| neighbor(index, dir)} + [index] return result.compact.uniq if compact return result.uniq end #----------------------------------------------------------------------------- # * Spread search. Expand node using BFS iteration #----------------------------------------------------------------------------- def spread_search(index,directions = Grid::Movement,limit = 1,compact = true) i = 0 result = [index] iteration = [index] until i == limit temp_res = [] iteration.each do |it| cells = surrounding(it, directions, compact) cells.delete_if {|c| result.include?(c)} temp_res += cells end temp_res.uniq! iteration = temp_res result += temp_res i += 1 end return result.compact.uniq if compact return result.uniq end #----------------------------------------------------------------------------- # * Linear repeated search #----------------------------------------------------------------------------- def linear_search(index,directions = Grid::Movement,limit = 1,compact = true) result = [] directions.each do |dir| result += spread_search(index, [dir], limit, compact) end return result.uniq end #----------------------------------------------------------------------------- # * Random grid drop #----------------------------------------------------------------------------- def random_grid(index = nil) return rand(max_index) unless index result = nil result = rand(max_index) until result != index return result end #----------------------------------------------------------------------------- # * Horizontal line #----------------------------------------------------------------------------- def horizontal(index, limit = Grid::MaxCol) linear_search(index, [4,6], limit) end #----------------------------------------------------------------------------- # * Vertical line #----------------------------------------------------------------------------- def vertical(index, limit = Grid::MaxRow) linear_search(index, [2,8], limit) end #----------------------------------------------------------------------------- # * Eight direction spread #----------------------------------------------------------------------------- def dir8(index, limit = 1) spread_search(index, [1,2,3,4,6,7,8,9], limit) end #----------------------------------------------------------------------------- # * Four direction spread #----------------------------------------------------------------------------- def dir4(index, limit = 1) spread_search(index, [2,4,6,8], limit) end #----------------------------------------------------------------------------- # * Cross shaped area #----------------------------------------------------------------------------- def cross_shape(index, limit = 1) linear_search(index, [1,3,7,9], limit) end #----------------------------------------------------------------------------- # * Plus shaped area #----------------------------------------------------------------------------- def plus_shape(index, limit = 1) linear_search(index, [2,4,6,8], limit) end #----------------------------------------------------------------------------- # * All area #----------------------------------------------------------------------------- def all_area Array.new(Grid::MaxRow * Grid::MaxCol) {|i| i} end end -
I've never really understood the purpose of using a module full of singleton methods but I'm assuming the devs just wanted to make it clear that there should only be one instance of it at any time.
Plus the term "module" just makes it sound different from "class" even though one's just a child of the other. -
modules are useful for monkeypatching (adding features to existing objects)
classes are fine if you're creating new objects.
for example:
module Logging def log msgbox(self.inspect) endendThe logger module contains functionality for displaying an alert. Using this new functionality is where the differences between modules and classes become apparent.
In addition to this module, we are going to create a class to more clearly articulate the disadvantages of each.
class Logger include LoggingendThe Base RPG::Skill class is something we will attempt to augment with the new behavior.
class ::RPG::Skill < ::RPG::UsableItem # Nothing is added yetendThe rpg skill object does not contain the new functionality we want to see in the module, so we will attempt to add it with the two options we have made available.
First, the correct way (using a module to extend behavior):
class ::RPG::Skill include LoggingendThis will allow us to call $data_skills.each { |x| x.log }
The wrong way would be to use a class:
class ::RPG::Skill < LoggerendThis relationship will actually cause an error because RUBY (ergo RGSS) doesn't allow for multiple inheritance relationships.
Because RPG::Skill has already defined an inheritance relationship with RPG::UsableItem, we cannot add another inherited class.
So, use a module if you would like to extend your functionality/data to existing classes.
Otherwise, use a class.
Hopefully this answers your question. -
Have you looked at the way Ace handles things? A module to handle all the turn/action logic, and classes to handle the scene, graphics, participants, etc.
-
That's a really odd way to think about classes and modules.
A class is a container for data, such as a Person, an Item, or a Monster.
A module is a namespace to organize your code, or to mix in as a reusable component.
Think of module namespacing like this: what happens when another script defines a Person? Collisions, and the classes will overwrite each other doing some nasty stuff. You prevent that by namespacing it like so:
module MyScript class Person # code here endend MyScript::person.new
With how many scripts you might end up putting into RPG maker, collisions will make it a very very bad day.
As far as component mixins, think of them as reusable functions. Enumerable is a great read in the Ruby StdLib.
Now then, as far as your code, I'll edit this post with links later:
Commented:
Refactored: -
haha yes I looked all the structure and for build the current battle system I mostly have to play with class and do a tons of aliasHave you looked at the way Ace handles things? A module to handle all the turn/action logic, and classes to handle the scene, graphics, participants, etc.
as I know I have to alias Game_Character , Game_Player , Game_System , Game_Temps
so for me module seemed more logics but class seem to works to
@tyle : thanks for the info haha ~ some information you give was unknow for me~
@Lemur : haha thanks for your answer well I primiraly follow Moghunter Logics of how he use Modules
they are simple to use and just check for schala and is whole "battle" system where he no alias anythings is handle by a whole module called "Schala_Battle" so for me this seemed logics
BUT
I see your point module are primarily use for add extra informations and mixing
and thanks for the further links this will help!
on these words thanks people for answer my question! -
I wouldn't use him as an inspiration for good practices. You'd be better off reading actual Ruby code from programmers in the field to be honest. If you really want to get good, read this book: Practical Object Oriented Design in Rubyhaha yes I looked all the structure and for build the current battle system I mostly have to play with class and do a tons of alias
as I know I have to alias Game_Character , Game_Player , Game_System , Game_Temps
so for me module seemed more logics but class seem to works to
@tyle : thanks for the info haha ~ some information you give was unknow for me~
@Lemur : haha thanks for your answer well I primiraly follow Moghunter Logics of how he use Modules
they are simple to use and just check for schala and is whole "battle" system where he no alias anythings is handle by a whole module called "Schala_Battle" so for me this seemed logics
BUT
I see your point module are primarily use for add extra informations and mixing
and thanks for the further links this will help!
on these words thanks people for answer my question!
Moghunter has a ton of duplication in his code, and a lot of inconsistency of how he implements things. That's the bad part about scripting sometimes, it can make a mess fast without good structure. -
thanks for your further answer : 3!
well I know Moghunter is not the perfect exemple but at least he helped me a lot for begin most of time I also Follow Enu coding
but the book seem interesting I will read it when I get time!
Sadly read big documentation in English are a little hard for me due the fact I am not a pure English and they don't have a lot of documentation in french :/
Naturally I code not in a way for make people easy to read my code this far more simply I code in a way where Myself I can read easily the code I do
Just this one is a exception because I do this battle system for someone else so I force myself for be readable. I can show how naturally I would structure my code
EG :
class Enigmadef initialize# insert normal stuffinitenddef initGraphicsinterpreterpuzzleenddef graphics@graphics = Graphicals.newenddef interpreter@inter = NewInterpreter.newenddef puzzle@puzzle = Puzzle_System.newendendI naturally Spare all my content into multiple class simply because I found more easier for me to update or to structure. -
Always assume that someone else will read your code, and that they just so happen to be a psychopathic madman with anger issues that knows your home address.
Do note though in that code you should probably use ||= to cache those, otherwise you get a new object each time (unless that was intended.) You might also read into dependency injection in Ruby, that book I mentioned above does a great job of it.