[RESOLVED][RGSS] Can't see the issue...

Started by bigace, December 09, 2012, 03:43:25 pm

Previous topic - Next topic

bigace

December 09, 2012, 03:43:25 pm Last Edit: December 12, 2012, 01:30:24 am by bigace
Okay so I was trying to simplify my code:

Old Code:
	def draw_enemy_hp(enemy, x, y, hidden)
colour = STAT_BAR_COLOURS[:hp_bar]
draw_enemy_bar(x, y, 120, 10, enemy.maxhp, ENEMY_STATS[:maxhp], colour)
contents.font.color = system_color
contents.draw_text(x, y-22, 24, 32, "#{$data_system.words.hp}:")
contents.font.color = normal_color
rect = Rect.new(x + 24, y-22, 72, 32)
unless hidden
contents.draw_text(rect, enemy.maxhp.group)
else
contents.draw_text(rect, '???')
end
end
def draw_enemy_sp(enemy, x, y, hidden)
colour = STAT_BAR_COLOURS[:hp_bar]
draw_enemy_bar(x, y, 120, 10, enemy.maxsp, ENEMY_STATS[:maxsp], colour)
contents.font.color = system_color
contents.draw_text(x, y-22, 24, 32, "#{$data_system.words.sp}:")
contents.font.color = normal_color
rect = Rect.new(x + 24, y-22, 72, 32)
unless hidden
contents.draw_text(rect, enemy.maxhp.group)
else
contents.draw_text(rect, '???')
end
end


New Code:

DEF = [
['hp', :hp_bar, 'enemy.maxhp', :maxhp],
['sp', :sp_bar, 'enemy.maxsp', :maxsp],
]
(DEF.size).times do |i|
eval "def draw_enemy_#{DEF[i][0]}(enemy, x, y, hidden)
value = #{DEF[i][2]}
max = ENEMY_STATS[#{DEF[i][3]}]
draw_enemy_bar(x, y, 120, 10, value, max, STAT_BAR_COLOURS[#{DEF[i][1]}])
contents.font.color = system_color
contents.draw_text(x, y-22, 24, 32, $data_system.words.#{DEF[i][0]})
contents.font.color = normal_color
rect = Rect.new(x + 24, y-22, 72, 32)
unless hidden
contents.draw_text(rect, #{DEF[i][2]}.group)
else
contents.draw_text(rect, '???')
end
end"
end


And for some reason I kept getting an error, well to my eyes I don't really see how I'm getting this error. So if anyone else can help spot it that would be great. If you need anymore info I'll post it.


Use Dropbox to upload your files. Much simpler than other upload sites, you can simply place a folder on your desktop that will sync with your DropBox account.

Blizzard

*fixes* Use [code] tags for code.

You seem to have a comma at the end of line 3 which basically adds a nil value as 3rd element into your array.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

bigace

Nope I still get the same error

Quote
Script 'Window_Bestiary_Info' line 32: NameError occurred.

undefined local variable or method 'maxhp' for #<Window_Bestiary_Info:0x31c9d60>


Also I don't know why the error is pointing there the only thing on that line is:
draw_enemy_hp(@enemy, 4, bar_Y=286, @hidden)


Use Dropbox to upload your files. Much simpler than other upload sites, you can simply place a folder on your desktop that will sync with your DropBox account.

Blizzard

December 09, 2012, 05:08:03 pm #3 Last Edit: December 09, 2012, 05:10:21 pm by Blizzard
Maybe you should just use the classic way (or make a method that takes a few more parameters), because using eval in such a way is really bad design.

EDIT: You can try putting the symbols in strings as well:

['hp', ':hp_bar', 'enemy.maxhp', ':maxhp'],
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

bigace

oh okay I'll test it when I get home.


Use Dropbox to upload your files. Much simpler than other upload sites, you can simply place a folder on your desktop that will sync with your DropBox account.

bigace

Nope doesn't work, I guess I'll just stick with the normal way :P . thanks for the help though.


Use Dropbox to upload your files. Much simpler than other upload sites, you can simply place a folder on your desktop that will sync with your DropBox account.

Ryex

December 10, 2012, 03:51:08 am #6 Last Edit: December 10, 2012, 03:57:26 am by Ryex
well, I applaud you for being clever and trying to define both methods at once but I would hardly consider this "simplification" of your code. but as you see here Eval has some very interesting scope considerations to take into account. some how "enemy" in your evaled code was an instance of a Window_Bestiary_Info I'm not sure how it happened.

Using eval in general is bad practice for multiple reasons but it does have a place. I'd advise you to read these two pages.

http://stackoverflow.com/questions/1902744/when-is-eval-in-ruby-justified
http://blog.grayproductions.net/articles/eval_isnt_quite_pure_evil

general rule of thumb:
if your using eval to reduce the number of lines of code you have, your doing it wrong.
if your using it to deal with a dynamic system where your program must adapt at run-time then it's good tool, but use wisely.


If you really want to get clever you could write a generic bar drawing method and use something like this

def draw_enemy_stat(enemy, x, y, hidden, stat)
...
value = enemy.instance_variable_get(stat)
draw_enemy_bar(x, y, 120, 10, value, ENEMY_STATS[stat], colour)
...
end


note that you can turn strings to symbols with to_sym so you can build a symbol form a string


stat = "hp"
enemy.instance_variable_get(("max" + stat).to_sym)
STAT_BAR_COLOURS[(stat + "_bar").to_sym]


note that the above assumes that maxhp and maxsp are instance variables (it's been too long since I used XP so I cant remember) if the value is handeled by getter and setter methods (ie. attr_accessor, attr_reader, and attr_writer) you will need to use send.

enemy.send(:maxhp)
I no longer keep up with posts in the forum very well. If you have a question or comment, about my work, or in general I welcome PM's. if you make a post in one of my threads and I don't reply with in a day or two feel free to PM me and point it out to me.<br /><br />DropBox, the best free file syncing service there is.<br />

bigace

December 10, 2012, 05:06:52 pm #7 Last Edit: December 10, 2012, 06:41:20 pm by bigace
wait so where does the line go, because even after I put it in still got the same error message that maxhp wasn't an instance variables

Scratch that, I got the error to go away but now both the sp and hp guages say the same thing. Plus instead of saying HP: & SP: from the database. It now prints RPG:Sy... (Can't read the rest).


def draw_enemy_health(enemy, x, y, type, hidden)
colour = STAT_BAR_COLOURS[(type + "_bar").to_sym]
value = enemy.send(:maxhp)
max = ENEMY_STATS[("max" + type).to_sym]
draw_enemy_bar(x, y, 120, 10, value, max, colour)
contents.font.color = system_color
contents.draw_text(x, y-22, 24, 32, "#{$data_system.words.type}:")
contents.font.color = normal_color
rect = Rect.new(x + 24, y-22, 72, 32)
unless hidden
contents.draw_text(rect, value.group)
else
contents.draw_text(rect, '???')
end
end


----------------
So practically from reading those findings you posted: eval() is evil as it can ruin your hardware if used extensively (something like that), though it's alright to use it sometimes, but rarely should you use it.


Use Dropbox to upload your files. Much simpler than other upload sites, you can simply place a folder on your desktop that will sync with your DropBox account.

Ryex

December 11, 2012, 02:56:00 am #8 Last Edit: December 11, 2012, 02:58:01 am by Ryex
well because your using enemy.send(:maxhp) you need to build that symbol from a string using the type like you do the rest to get both HP and SP bars. don't just cut and past my code I gave it as examples not exactly how to do it.

and eval isn't evil (but that is the common over-generalization) it is meirly a powerfully tool that can be misused very easyily
I no longer keep up with posts in the forum very well. If you have a question or comment, about my work, or in general I welcome PM's. if you make a post in one of my threads and I don't reply with in a day or two feel free to PM me and point it out to me.<br /><br />DropBox, the best free file syncing service there is.<br />

Blizzard

I think that one article has a few pretty good comments on it. Using eval for code definition is bad design, but using it to run dynamically created code or allow some sort of Ruby prompt (like I allowed in RMX-OS if somebody is an admin) are great ways where eval is not only useful and is considered good design, it's sometimes also the only possible solution (or the cleanest anyway).
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

Heretic86

PHP has an eval equivilant.  When running a web server, one definitely does not want to allow unchecked user input to be allowed to run in eval because it effectively runs as shell on the system, which can be dangerous. 

But running eval in RMXP doesnt have the same security needs and boils down to how it needs to be used.  Eval threw me for a loop with Zeriab's caterpillar where he used eval to create a bunch of definitions dynamically, and applied the same change to each dynamic definition.  Space saver, and in that situation I dont think it was required. 

I also used eval in Timed User Inputs to allow scripts to run at specific times in different scenes.  It became necessary to allow access to eval to process scripts after you change scenes to a non eventable / scriptable scene (like Menu) and not modify the scene itself in any way.

Eval does have very legit uses.
Current Scripts:
Heretic's Moving Platforms

Current Demos:
Collection of Art and 100% Compatible Scripts

(Script Demos are all still available in the Collection link above.  I lost some individual demos due to a server crash.)

bigace

December 12, 2012, 01:28:19 am #11 Last Edit: December 12, 2012, 01:29:27 am by bigace
Okay thank you for the help Ryex as I got this code to work:
	
def draw_enemy_health(enemy, x, y, type, hidden)
colour = STAT_BAR_COLOURS[(type + "_bar").to_sym]
value = enemy.send(("max" + type).to_sym)
max = ENEMY_STATS[("max" + type).to_sym]
draw_enemy_bar(x, y, 120, 10, value, max, colour)
contents.font.color = system_color
contents.draw_text(x, y-22, 24, 32, eval("$data_system.words.#{type}") + ":")
contents.font.color = normal_color
rect = Rect.new(x + 24, y-22, 72, 32)
unless hidden
contents.draw_text(rect, value.group)
else
contents.draw_text(rect, '???')
end
end


And thank you everyone for giving more info on eval()


Use Dropbox to upload your files. Much simpler than other upload sites, you can simply place a folder on your desktop that will sync with your DropBox account.