02-18-2023, 08:23 AM (This post was last modified: 02-18-2023, 08:25 AM by icogil.)
I wanted to make a sprite that follows a character like a visual equipment script without size restrictions, so I made the script below while studying and putting together several scripts for the past few days.
And the results were generally very satisfactory.
But one more problem arose.
If you adjust the z of the sprite created in this way, it will either go above everything on the screen, or below everything, and become invisible.
I honestly don't know what to do.
self.z I thought was the z value of the character's sprite.
It is not simply on top of the character sprite, but on top of the entire screen.
self.viewport.z also doesn't work
I also put it in viewport.z
I tried putting it in @_HEAD_sprite.z as well, but it doesn't work as I want.
What should I do?
current situation what i want
Code:
class Game_Character
attr_accessor :sprite_HEAD
end
class Sprite_Character < Sprite_Character
def create_HEAD_sprite(text)
02-18-2023, 01:02 PM (This post was last modified: 02-18-2023, 01:07 PM by JayRay.)
Now, while someone else will probably give you a much better answer regarding this issue, I only have this reference from a XP script that I co-authored with DerVVulfman, called ELSA, or Event Layering Script Advance, which allowed tags to determine at what layer an Event would show.
Now, in that script, each of the references used screen.z with exact layers. I don't know if that's what you want, also perhaps you can remove the self.z and put in a flat integer like 1. which SHOULD put it in the same sprite priority as the character. 2 would be a layer up and so on and so forth.
I'd also look at DerVVUlfman's Paperdolls script that also emulates a visual equipment style setup. It was part of the Lycan ABS and while you may not want EVERYTHING in there, it might have just the right syntax you need for your own visual equipment script.
I'm sorry I couldn't be more help, but I AM the only one on here at 6AM so, there's that... lol
but, just brainstorming, you might find out what the game_character z is set at, and then just make your head sprite be "thatnumber"+1 - from a layman's perspective.
Code:
@character.screen_z(@ch) + 1
+2 for the next layer, +3, and so on and so forth...
BLOG: JayVinci.blogspot.com
FORUM COMING SOON
Currently working on:
Ambitions: RPG Developer Bakin
Heart of Vox: RPG Developer Bakin
02-18-2023, 01:52 PM (This post was last modified: 02-18-2023, 02:08 PM by Kain Nobel.)
The first issue I see is Sprite_Character < Sprite_Character.
Were you intending to do something like Sprite_Equipment < Sprite_Character ? I suggest studying the topic of Ruby class inheritance.
I would suggest studying how alias or alias_method is used to add new code to pre-existing methods. By calling an alias, you're making a call to the original method definition, and you can add new code above and below the alias call. This allows you to extend an existing class without editing the original source code.
Here is how I would refactor the script...
Sprite_Character
Code:
class Sprite_Character
alias_method :visualequip_spcharacter_initialize, :initialize
alias_method :visualequip_spcharacter_update, :update
alias_method :visualequip_spcharacter_dispose, :dispose
def initialize(viewport)
# Call alias method
visualequip_spcharacter_initialize(viewport)
# Create equipment sprites
create_equipment
end
def create_equipment
# Create an array for equipment layers
@equipment_sprites = []
# (Finish the method definition...)
end
def dispose
# Call alias method
visualequip_spcharacter_dispose
# Dispose of equipment sprites
@equipment_sprites.each {|sprite| sprite.dispose}
end
def update
# Call original method
visualequip_spcharacter_update
# Update equipment sprites
@equipment_sprites.each {|sprite| sprite.update}
end
end
Sprite_Equipment
Code:
class Sprite_Equipment < Sprite_Character
def initialize(sprite)
# Get character sprite
@sprite = sprite
# Parent method (Set viewport)
super(@sprite.viewport)
# Set Z value on top of character
self.z = (@sprite.z + 1)
# Refresh equipment graphic
refresh
end
def refresh
# (Your code goes here)
end
def update
# (Your code goes here)
# Set Z value on top of character
self.z = (@sprite.z + 1)
end
def dispose
unless (self.bitmap.nil? || self.bitmap.disposed?)
self.bitmap.dispose
self.bitmap = nil
end
end
end
Now that I've provided you some slightly better structure hopefully you'll have an easier time with your script. This is by no means a finished work, just a starter example, so you'll still have to do some work in regards to refactoring your existing code for the new format.
I've already provided a little bit of code in the Sprite_Equipment#update method which should keep your Z value synchronized with the Sprite_Character. If you start adding more than one piece of equipment, you may need to re-prioritize the Z stack. You'll have to ask yourself "do the boots go above the pants, or below? Is this a hard-defined rule, or is it situational and flexible?" That's beyond the scope of this help topic, you'll have to figure that out on your own.
Please note that I'm using Sprite_Character's viewport as Sprite_Equipment's viewport; if the accessory is larger than Sprite_Character's graphic, you may have to create a new Viewport object with modified dimensions. It would need to retrieve the width and height properties from the equipment's bitmap.rect. You might also need to modify the X and Y of the Viewport (synchronize them with the Character's X and Y, but modified.) I did not address this issue in the sample code, I only focused on synchronizing the Z value, so you'll have to implement your own solution.
What JayRay linked above would probably be the best thing to look at (or use) because I don't know how to explain it any better than that system would. Maybe it has exactly what you need already.
Hopefully I didn't overload you with too much information. There is a lot of different aspects to think about when making a visual equipment system. I'm not discouraging you from writing your own, but I would definitely suggest checking out existing visual equipment systems and getting more study time in with the Ruby language. Figure out what you like VS what you don't like and go from there.
02-18-2023, 03:01 PM (This post was last modified: 02-18-2023, 03:07 PM by DerVVulfman.)
(02-18-2023, 08:23 AM)icogil Wrote: I wanted to make a sprite that follows a character like a visual equipment script without size restrictions, so I made the script below while studying and putting together several scripts for the past few days.
Your statement is a bit... mixed up, sounding like a visual equipment script forces characters to follow the player. It doesn't.
A script known as a caterpillar (or party follow) script is one that has party members following the player. And visual equipment (or paperdoll) is a system that applies sprites upon the player. The two are actually quite different.
I would recommend downloading the demo itself. (I doublechecked the link.... right click to get to the box.com screen for the demo. Then click Download at the top-right.). The demo not only includes Rataime's Visual Equipment script which is the oldest and simplest I've seen. But it includes a caterpillar script with the name "Train Actor" by fukuyama, also the oldest one that existed. Both work fine together. And the demo has other features including sprite reflections for mirror effects and shadow creation.
And neither system required editing of the Z-axis.
In the demo, you will find I performed some edits... to give the end user (like you) more flexibility.
In the Train Actor script by Fukuyama, it mattered not the size of the sprite. I replaced the third party member with a larger skeleton shown here. But if I were to apply items to the skeleton, the gear would need to be the same size as the skeleton's sprite. That is possible, but would require an edit of the visual equipment to recognize WHO gets the armor or weapon.
Up is down, left is right and sideways is straight ahead. - Cord "Circle of Iron", 1978 (written by Bruce Lee and James Coburn... really...)
02-18-2023, 09:13 PM (This post was last modified: 02-18-2023, 09:47 PM by kyonides.
Edit Reason: Corrections
)
There's something missing in Kain's reply that you should be aware of for your game's sake, like in performance and memory handling. I noticed it in his Sprite_Character class edit.
Code:
def dispose
# Call alias method
visualequip_spcharacter_dispose
# Dispose of equipment sprites
@equipment_sprites.each do |sprite|
sprite.bitmap.dispose
sprite.dispose
end
end
I changed the definition of the each loop for a good reason: Sprite class and its derivatives don't dispose their bitmaps automatically. That means that there's a chance you can still see your character on a new scene like the menu scene when it's supposed to have been marked for future deletion. Even if they weren't visible, it'd still be happening behind the curtains. This issue can be accumulative...
EDIT
There's a second issue that is related to the z coordinate.
Code:
class Sprite_Equipment < Sprite_Character
def initialize(sprite)
# Get character sprite
@sprite = sprite
# Parent method (Set viewport)
super(@sprite.viewport)
# Set Z value on top of character
self.z = (@sprite.z + 1)
# Refresh equipment graphic
refresh
end
self.z = (@sprite.z + 1) can't always be + 1 because of the character's current direction. If he's facing downwards, the wings will be on top of it. Thus, you need to change the value to - 1 when it's facing down at least.
Probably, he could have taken care of it already, yet, I had to mention it just in case icogil ended up finding his characters in such a perilous situation.
Code:
def dispose
unless (self.bitmap.nil? || self.bitmap.disposed?)
self.bitmap.dispose
self.bitmap = nil
end
end
There self.bitmap.disposed? is optional normally, for you should only dispose such sprites at the end of your Scene script. The only reason why you'd need it would be if you're implementing a dynamic change of the equipment ON THE MAP. If you leave the scene and open another one, even if it has the spriteset being drawn on screen as a backdrop, you'll never need to double check that there's no disposed bitmap still hanging around at that moment. The parentheses he used above are unnecessary in this case.
PLUS, it should include a call to super method, like ALWAYS. It should be placed outside that condition, in fact, below the end keyword that closes the definition of the unless statement. Just super because it'd handle the disposal of the Sprite object in C or C++ code.
Code:
def dispose
unless self.bitmap.nil?
self.bitmap.dispose
self.bitmap = nil
end
super
end
Correction of an Inaccurate Statement
Kain Nobel Wrote:Please note that I'm using Sprite_Character's viewport as Sprite_Equipment's viewport; if the accessory is larger than Sprite_Character's graphic, you may have to create a new Viewport object with modified dimensions. It would need to retrieve the width and height properties from the equipment's bitmap.rect. You might also need to modify the X and Y of the Viewport (synchronize them with the Character's X and Y, but modified.) I did not address this issue in the sample code, I only focused on synchronizing the Z value, so you'll have to implement your own solution.
No, Kain. He won't need to define a new Viewport object at all. The reason is quite simple, the Spriteset_Map class assigns a viewport that has the same dimensions as the game window so ANY of icogill's weapons and armor pieces and wings will be visible the whole time his heroes spend on the map, travelling around the game world.
A Badly Needed Emphasis
There's something quite basic but HIGHLY important that Kain Nobel told you that you should keep in mind, icogil.
Kain Nobel Wrote:Hopefully I didn't overload you with too much information. There is a lot of different aspects to think about when making a visual equipment system. I'm not discouraging you from writing your own, but I would definitely suggest checking out existing visual equipment systems and getting more study time in with the Ruby language. Figure out what you like VS what you don't like and go from there.
"For God has not destined us for wrath, but for obtaining salvation through our Lord Jesus Christ," 1 Thessalonians 5:9
Maranatha!
The Internet might be either your friend or enemy. It just depends on whether or not she has a bad hair day.
Ah, thank you kyonides for correcting the inaccurate statement. (Is it inaccurate? Possibly.)
I've never wrote or used a visual equipment system, so I'm not sure exactly how any of the systems handle an "equipment graphic that is bigger than the character graphic."
The reason I did bring up a separate Viewport object (which is a suggestion I admittedly don't like) is because, yes, your equipment could be bigger than the bitmap.rect of the character graphic. An individual character graphic cel may be (32x48), but your helmet cel could possibly be larger (36x52). If you had a big helmet with spikes on it, the spikes could cut off at the top, left and/or right edges of a character's head due to equipment dimensions being larger than character dimensions. There are pre-established scripts that have already been there and done that insofar as handling that issue. If you don't use them, and you decide to write your own solutions, I still suggest at least checking out other scripts and seeing their solution to this challenge.
02-19-2023, 04:00 AM (This post was last modified: 02-19-2023, 04:29 AM by DerVVulfman.)
I would DEFINITELY not use Viewports. Viewports are like panes of glass... one atop the other. For this, allow me to illustrate.
The map system is divided into three viewports already
Viewport 1: The Map tiles and panorama viewport
Viewport 2: The pictures (from Show Picture) is atop that
Viewport 3: This handles the flash effect alone
Relatively speaking, the z-Depth of Viewport 1 is defaulted to a depth of 0, Viewport 2 to a depth of 200 and Viewport 3 to 5000. And yes, the sprites within Viewport 1 can be set to a wide variety of z-Depths. But these sprites only have a z-Depth within in Viewport 1 alone. A sprite, be it a tree or hero, at a Z-Depth of 300 within Viewport 1 will never be drawn over the depth of Viewport 2.
Also...
If you were to create a separate viewport for visual graphics and had this layer atop Viewport 1, you would likely show the graphics atop the trees from whatever position you were. And if your custom viewport were below (good luck with that), then the custom graphics would not be very visible.
Now it's MAGIC time....
ALL... paperdoll systems, and I prefer the term because of its historic connotations, rely upon layering to be sure. But moreso, they also create or recreate the character's sprite only when triggered. So when your hero is walking about, nothing happens. However, when something is given to them within their Equip menu, a trigger is pulled and the character sprite system looks and then redraws accordingly. And ONLY then it performs the redraw, so no lag should ever be equated with a paperdoll system. And since it is creating, or re-creating the sprite, from the layers, there is no need to deal with a layer's z-depth.
Now for some drawbacks to older systems....
Most all assume that the principle character (the hero) is drawn first and every graphic is drawn atop. This works most of the time for clothing or armor if a rigid setup. But there is nothing drawn behind the hero... so cloaks behind the hero can be problematic depending upon the armor, dress or garments worn.
For that, you would want a layering system that would know to layer the cloak first, the hero, the clothes, the armor atop, and so on.
And THEN, you have another issue... Layer direction. Assuming the fore-mentioned hero is facing you, the cloak would be drawn first, and then the hero. But if the hero is facing away, the cloak would be the last item rendered. This I know too well. As JayRay mentioned, I created a version of my ABS with a paperdoll system... and it does take character facing direction into consideration. It wasn't easy, but it did.
And then, character 'size' difference... you may want to have a feature in the paperdoll system to recognize certain shirts' or 'wings' for different heroes based on their size. You may have a hero named Kim who is the normal sized character. Then, you can have Keiko being an unusually tall fighter. For her, you may wish to have a separate wings given the name 'wings_keiko.png'. You would need to have the paperdoll system check to see if wings_keiko exists of course. But this is a feature I personally looked into.
And I won't talk about the fun with dual weapons... TOO LATE!!!
Up is down, left is right and sideways is straight ahead. - Cord "Circle of Iron", 1978 (written by Bruce Lee and James Coburn... really...)
As I said I created a new viewport for the character and equipment sprites of different sizes.
If another viewport is used, is layering not normally processed on the map?
What I'm a bit confused about is that all characters and events on the screen share one viewport?
If so, is the function that limits sprites to 1/16 defined separately without using the viewport?
If so, what should I do?
Is it impossible in principle to superimpose sprites of different sizes from characters?