The z-space problem of displaying sprites
#1
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
[Image: sprite-0004-gif.253550]                                [Image: sprite-0003-gif.253551]

Code:
class Game_Character
  attr_accessor :sprite_HEAD
end



class Sprite_Character < Sprite_Character
  def create_HEAD_sprite(text)
   
    $game_variables[195]="Graphics/Characters/197-Support05"

    bitmap = Bitmap.new($game_variables[195])

    viewport = Viewport.new(self.x,self.y,bitmap.width/4,bitmap.height/4)
    viewport.z = self.z
    @_HEAD_sprite = Sprite.new(viewport)
    @_HEAD_sprite.bitmap = bitmap
    @_HEAD_sprite.ox = 0
    @_HEAD_sprite.oy = 0
    @_HEAD_sprite.x = self.x - bitmap.width/8
    @_HEAD_sprite.y = self.y - bitmap.height/8
    @_HEAD_sprite.z = self.z
    @_HEAD_sprite_visible = true

  end



  def dispose_HEAD_sprite
    @_HEAD_sprite.dispose
    @_HEAD_sprite_visible = false
  end

  def update_HEAD_sprite
    if @character.sprite_HEAD != nil

      if not @_HEAD_sprite_visible
        create_HEAD_sprite(@character.sprite_HEAD)
      end
     
      @_HEAD_sprite.viewport.rect.set(
      self.x-@_HEAD_sprite.bitmap.width/8,
      self.y-@_HEAD_sprite.bitmap.height/4,
      @_HEAD_sprite.bitmap.width/4,
      @_HEAD_sprite.bitmap.height/4)
      if @_HEAD_sprite.bitmap != $game_variables[195]
         @_HEAD_sprite.bitmap = Bitmap.new($game_variables[195])
      end

     
      @_HEAD_sprite.x = self.character.pattern * -@_HEAD_sprite.bitmap.width/4
      @_HEAD_sprite.y = (@character.direction - 2) / 2 * -@_HEAD_sprite.bitmap.height/4
      @_HEAD_sprite.viewport.z = self.viewport.z
    else
      if @_HEAD_sprite_visible
        dispose_HEAD_sprite
      end
    end
  end
    
  def update
    super
    update_HEAD_sprite
  end
end
Reply }
#2
https://forums.rpgmakerweb.com/index.php...if.253550/
https://forums.rpgmakerweb.com/index.php...if.253551/
these are images
Reply }
#3
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. 


ELSA (Event Layering Script Advanced

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.

DerVVulfman's Lycan ABS (With Paperdoll)

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...
[Image: AVvXsEga1vIr5Rx3FkoFbGo1OoMJAqgq6TeqcbpF...L3AWg=s752]

BLOG: JayVinci.blogspot.com
FORUM COMING SOON
Currently working on:
Ambitions: RPG Developer Bakin
Heart of Vox: RPG Developer Bakin
Reply }
#4
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.

Best of luck and take care!
[Image: Button-BOTB.png]
[Image: Save-Point.gif][Image: Button-You-Tube2.png][Image: Button-Sound-Cloud2.png][Image: Button-Audio-Mack2.png]
[Image: LS-Banner.gif]
NEW ALBUM OUT NOW!

Reply }
#5
(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. 

* There are a variety of both types in the forum.

We have a demo by a scripter named Rataime that includes 'both'.  Below is the link:
Rataime's Visual Scripts: Visual Equipment

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.

[Image: attachment.php?aid=1756]
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.


Attached Files
.png   FollowMe.png (Size: 15.29 KB / Downloads: 52)
Up is down, left is right and sideways is straight ahead. - Cord "Circle of Iron", 1978 (written by Bruce Lee and James Coburn... really...)

[Image: QrnbKlx.jpg]
[Image: sGz1ErF.png]    [Image: liM4ikn.png]    [Image: fdzKgZA.png]    [Image: sj0H81z.png]
[Image: QL7oRau.png]    [Image: uSqjY09.png]    [Image: GAA3qE9.png]    [Image: 2Hmnx1G.png]    [Image: BwtNdKw.png%5B]
  Above are clickable links
Reply }
#6
And that's why I love this community... Question? They've got ANSWERS!!
[Image: AVvXsEga1vIr5Rx3FkoFbGo1OoMJAqgq6TeqcbpF...L3AWg=s752]

BLOG: JayVinci.blogspot.com
FORUM COMING SOON
Currently working on:
Ambitions: RPG Developer Bakin
Heart of Vox: RPG Developer Bakin
Reply }
#7
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. Confused 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. Happy with a sweat

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.

[Image: SP1-Scripter.png]
[Image: SP1-Writer.png]
[Image: SP1-Poet.png]
[Image: SP1-PixelArtist.png]
[Image: SP1-Reporter.png]

My Original Stories (available in English and Spanish)

List of Compiled Binary Executables I have published...
HiddenChest & Roole

Give me a free copy of your completed game if you include at least 3 of my scripts! Laughing + Tongue sticking out

Just some scripts I've already published on the board...
KyoGemBoost XP VX & ACE, RandomEnkounters XP, KSkillShop XP, Kolloseum States XP, KEvents XP, KScenario XP & Gosu, KyoPrizeShop XP Mangostan, Kuests XP, KyoDiscounts XP VX, ACE & MV, KChest XP VX & ACE 2016, KTelePort XP, KSkillMax XP & VX & ACE, Gem Roulette XP VX & VX Ace, KRespawnPoint XP, VX & VX Ace, GiveAway XP VX & ACE, Klearance XP VX & ACE, KUnits XP VX, ACE & Gosu 2017, KLevel XP, KRumors XP & ACE, KMonsterPals XP VX & ACE, KStatsRefill XP VX & ACE, KLotto XP VX & ACE, KItemDesc XP & VX, KPocket XP & VX, OpenChest XP VX & ACE
Reply }
#8
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.
[Image: Button-BOTB.png]
[Image: Save-Point.gif][Image: Button-You-Tube2.png][Image: Button-Sound-Cloud2.png][Image: Button-Audio-Mack2.png]
[Image: LS-Banner.gif]
NEW ALBUM OUT NOW!

Reply }
#9
I would DEFINITELY not use Viewports.  Viewports are like panes of glass... one atop the other.  For this, allow me to illustrate.

[Image: attachment.php?aid=1757]

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... Laughing TOO LATE!!!


Attached Files
.png   Viewport.png (Size: 119.92 KB / Downloads: 33)
Up is down, left is right and sideways is straight ahead. - Cord "Circle of Iron", 1978 (written by Bruce Lee and James Coburn... really...)

[Image: QrnbKlx.jpg]
[Image: sGz1ErF.png]    [Image: liM4ikn.png]    [Image: fdzKgZA.png]    [Image: sj0H81z.png]
[Image: QL7oRau.png]    [Image: uSqjY09.png]    [Image: GAA3qE9.png]    [Image: 2Hmnx1G.png]    [Image: BwtNdKw.png%5B]
  Above are clickable links
Reply }
#10
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?
Reply }


Possibly Related Threads…
Thread Author Replies Views Last Post
   Problem with drain script form the ATOA ACBS Djigit 2 5,561 07-12-2015, 09:17 PM
Last Post: Djigit
   Event collision problem with FPLE script ThePrinceofMars 2 5,781 11-11-2014, 06:30 PM
Last Post: ThePrinceofMars
  Custom meter problem daylights 13 16,177 08-12-2013, 03:34 AM
Last Post: daylights
   [RUBY] Depack Thread Problem Narzew 1 4,393 07-20-2012, 01:16 PM
Last Post: Narzew
   Advantages & Charlie Fleed CTB problem Yin 7 11,998 12-12-2011, 03:45 PM
Last Post: Yin
   Charlie Fleed's CTB - Problem with dual wielding characters MegaPowerNinja 2 5,875 04-25-2011, 09:51 AM
Last Post: Charlie Fleed
   Slight problem with Omega Quest script. Boot 4 8,662 03-08-2011, 02:53 AM
Last Post: BlackDragon 31
   Help on an old problem. Yin 5 9,372 12-07-2010, 02:55 AM
Last Post: Yin
   AMS script problem Thehero 2 6,573 05-18-2010, 07:30 AM
Last Post: Jaberwocky
   Window Visibility Problem computerwizoo7 7 11,312 05-10-2010, 05:53 PM
Last Post: deValdr



Users browsing this thread: 2 Guest(s)