Talk:Plan for raising sprite frame limits

From OHRRPGCE-Wiki

(Difference between revisions)
Jump to: navigation, search
(mitigate abuse of lumps in format proposition)
(eventual reply)
Line 114: Line 114:
multiple frames are lumped . we need a strategy for balancing lumping I/O cost vs quick access when unlumped, this will be an issue as number of frames rise.
multiple frames are lumped . we need a strategy for balancing lumping I/O cost vs quick access when unlumped, this will be an issue as number of frames rise.
A categorization of frame types (weapon, hero, etc.) will help here.
A categorization of frame types (weapon, hero, etc.) will help here.
 +
 +
[[User:The Mad Cacti|The Mad Cacti]]: Took some time to think about this
 +
 +
:What about this: rather than every frame being variable size, allow sets of frames which share a size and an alignment .. this reduces the burden of choice on the user.
 +
I don't follow: what logical unit would such a set of frames comprise?
 +
 +
I think most of the alignment/bounding box issues you mentioned are easily solved by the base size boxes; a better explanation: the base box would be the bounding box, because Game would only work with base boxes, and be completely unaware of the real size (and offset) of each frame except in special circumstances (eg. drawing the hero picker menu) where visual instead of logical size needs to be considered. I suppose placing attack graphics over an inbattle sprite would be one of these. It occurs to me now that you ought be able to set the base box per graphics set rather than being fixed per graphics type, due to the Plan for non-tile-based walking. I guess this means that you ought to be allowed to place weapon handle points outside of the box.
 +
 +
If the frame size defaults to the base size, then the user doesn't have to choose a larger frame size for the whole by guessing how much space they'll need. Does this increase or decrease the "burden of choice"?
 +
 +
:what is X/Y offset relative to? (bottom center of 'base box' seems appropriate to me.)
 +
But placing the origin at top left of base box would most directly specifies position and 'extents' over base box in each direction.  The engine can place the sprite based on the base size box however it like: in some cases, you would want to anchor the center of the bottom edge at a screen position.
 +
 +
:Similarly, while I agree with the idea of animation patterns, I think they are also in danger of creating excessive complexity. (without the concept of multiple framesets, next/prev frame is not really sufficient IMO -- when frames > 64, being able to jump to a specific frame or in large steps is needed) If we can work out a GUI position for editing these that 'fits' well, I'll retract that.
 +
I definitely agree that complexity will have a potentially very high bound. (Not sure what is meant by 'GUI position'.) I imagine that you would be able to select a frame either from the animation, or from the graphics set; next/prev frame would navigate through the appropriate sequence. With key repeat you could move through 64 frames very quickly (though imprecisely). Prehaps we could create a menu with a 'view' of an animation as just the sequence of all the frames (loops optionally unrolled) to allow easy scrolling and selection. Also, if it necessary to compare two or more frames that are not sequential in any animation, you could reorder the graphics set to place them (possibly temporarily) sequentially; and assumably they are logically related.
 +
 +
Naming frames sounds like a good idea, especially with a way to reorder the frames in the graphics set (which of course updates all animations): for use by scripts. At least one person requested the ability to name tilesets.
 +
 +
:We do still need a way to categorize graphics+animations though (walk, enemy, attack etc.. this scheme we are working on should render much of the old PT? design obsolete.)
 +
It might seem to make sense to combine small/medium/large enemy sprites, but the possible complications of doing so seem very difficult. But after the old scheme is obsolete, the logical conclusion seems to be that all sizes of enemy are equal. (However there is a problem with formations: enemies are placed by top left coordinate, and you don't know what size enemy will spawn into an empty slot).
 +
Also, [[Plan for implementing battlescripting#An alternate possible plan]] could blur the distinction between walkabout, enemy, and hero graphics.
 +
 +
:A lighterweight 'lump-like' format seems about right: RECORDSIZE(SHORT) ID(SHORT? or INT?) NRECORDS(SHORT) DATA(BYTES) [ID NRECORDS DATA...]
 +
Ambiguity in your description: is the recordsize per animation, or per animation operation. I guess that's one way to have variable length records: size all records to the largest.
 +
 +
:FRAMEID XOFFSET YOFFSET VALUE1 VALUE2 [...repeats]
 +
If X/YOFFSET are only used by frames, then this is redundant to VALUE1/2. A triplet per animation operation would do.
 +
 +
I'm not sure about specifying the offset for every frame. I think modifying the offset would to be fairly rare, such as when creating a hoping animation. Alternatively, you could have an explicit 'set offset' operation, which stays in effect. It's a pretty minor detail though.
 +
 +
Tile animations are rather limiting in length, number, tileset layout requires, etc. and ought to be replaced. It would be nice to use the same animation format, but the operations are somewhat different. I thought that perhaps we could specify some animation operations specific to sprites, others to tiles. Would switching from animation 'template' patterns to one animation per animated tile be a good idea? Maybe ideally support both? This is a mess.
 +
 +
:we need a strategy for balancing lumping I/O cost vs quick access when unlumped, this will be an issue as number of frames rise.
 +
Odd, I only realised after multiple readthroughs that you suggested storing each frame in a lump. I suppose that is doable, but is it very benficial? The benefit is to be able to extract a frame as a self contained file; but it is not really self contained, since the bitdepth was not specified. Would the filename encode any information?
 +
 +
Loading an RPG (without unlumping) by creating an index of all lumps and sublumps and subsublumps starts to become large and expensive - clearly you would only want to index the sublumps of a graphics set when loading it. I don't see why you would need fast random access to a specific frame without loading the whole graphics set.

Revision as of 15:14, 3 November 2009

Bob the Hamster: I had originally thought that a total overhaul of sprite storage lumps would be mandatory before we could increase sprite frame limits, but now that upgrade() works in both game and custom, we can increase the sprite frame limits in the same way we increase the size of other binary records, using new entries in BINSIZE.BIN and a bit in FIXBITS.BIN to trigger any initialization of the new frames. A clean-up of the sprite format would still be desirable, but it is a goal that we can pursue separately from the plan for raising sprite frame limits

Raekuul: If we clean up the code first, wouldn't adding new frames be easier? And would a blank frame default to the walk frame, or would there be an option to mimic old behavior?

Bob the Hamster: Code cleanup is always a good thing, but changing a storage format requires careful thought to avoid painful backwards compatibility problems. I'm not sure yet how we will handle blank new frames, but yes, supporting the old behavior is essential.

NeoTA: I was just thinking about the 'plan for bigger walkabouts' thread on the mailing list, and decided my comments had better go here:

Store each frame-set as a separate file (not each frame, nor each graphics-set). Consider a graphics-set as the sum of all the eligible frame-sets. For example, GS0.000, GS0.001, GS0.002, GS0.003 , GS1.000, GS2.000, GS2.001: graphicset 0 contains 4 framesets (presumably it's a walkabout set with the 4 cardinal directions)

This doesn't provide a way to classify graphic sets (eg hero, enemy, misc). Perhaps GSH0.000, GSE0.000, GSM0.000 etc (use a filename character for classification) with hex number storage, this allows for <=1048576 graphics sets each containing <=4096 framesets in <=26 categories; in decimal, it would be <=100000 gsets with <= 1000 fsets each in <=26 categories. I think this is adequate.

A frameset could be stored in a format something like W H N FRAMEFRAMEFRAME

(this would occupy 2+2+2 + (N*W*H/2) bytes for 16color graphics, double that for 256color. A walkabout set like the current walkabout sets would be stored in 4 frameset files, each of which would be 406 bytes, totalling 1624 bytes, which is 24 more bytes than )

In the context of supporting custom-sized sprites, this avoids a lot of trouble; Upsides:

  • allows you to reasonably postulate "all frames in a frameset must be the same size", without requiring that all frames in the graphicset are same size,
  • avoids excessive I/O (resizing one frameset doesn't require rewriting a whole graphicset file),
  • supports the possibility of different graphicsets having different numbers of frames
  • utilizes the filename as storage space, which is more inspectable than some number inside a binary file.
  • Only unlump the graphicsets you need

Downsides:

  • export/import of graphicsets would be slightly more complex
  • need to generate a temporary lump to help us lookup how many frames are in each graphic set. This should be trivially doable as part of unlumping, so should only incur a cost if running-without-unlumping is implemented.
  • Running-without-unlumping is a better situation: it addresses the 'lump proliferation' problem well by eliminating the need to unlump:)
  • Some things won't need animation at all and will be of uniform dimensions. Effectively storing each frame in a separate file seems a bit silly in this case. (what about something like GSM5.___ indicating that each 'frame' in the set should actually be treated as a separate 'frameset', and all frames for the graphicset are included in that one file)

Requirements:

  • with variable numbers of frames, we'd probably need 'previous/next frame' keyboard shortcuts for the sprite editor, and possibly 'previous/next graphicset'
  • and of course some way to resize a frameset's frames (as a whole)

Lastly, I just realized that it has a serious flaw (the above mentioned lump proliferation). I feel that with some changes this would be resolvable, however, so I'm still posting this.

NeoTA: Even if each graphicset were its own file, this would still be serious lump proliferation (500 graphicsets -> 500 files). Perhaps using sublumping would help: eg. HEROGFX.BIN -> contains 500 lumps, 1 per graphicset). These two measures would reduce the number of toplevel lumps per graphicset to equal the current PTx setup (that is, 1/NGRAPHICSETS -- 0.002 for the '500 sets' example)


The Mad Cacti: When you talked about sublumping, did you mean to say one lump per graphics set or one lump per frameset? Or would the idea be to lump the framesets for each graphicset up?

Thanks greatly for writing this, I've been thinking about the new graphics format for a while, but with uncertainty. One sublump per graphics set or frameset, lumped up by type seems like a good way to go.

You didn't mention animation, but I'll digress into it:

The end goal that I've been thinking about is flexible sprite animation. An animation would not just be a frame-set, but a set of frames and an animation pattern (I'm guessing you intended this), similar to tile animations patterns but with various improvements. Thinking with a focus on animations rather than frames or sprite sets, my idea was for a spriteset as an otherwise unorganised bunch of frames each of arbitrary size. This way you could have a single frame appearing in multiple animations, which is actually quite likely. For example, walkabout sets converted would have an animation for walking in each direction, and one for standing facing in each direction. When actually editing a sprite, you could select a frame from an animation, and have previous/next keys as you described, to switch to the neighbouring frames in that animation.

A problem with this scheme is that you can't say anything about what a frame is without reading the complex animation description. But there should definitely be a way to rearrange the order of the frame so you can give them some logical grouping.

Anyway, the idea in allowing each frame to have an individual size is so that you could draw over the 'edge of the frame' if you wanted to, such as one exceptionally wide frame in a sword swinging animation. The sprite set type would have a set base size - 20x20 for walkabouts - and each frame would have an offset from this, so that have an inherent placement, eg wrt the tile on which a sprite is standing. I imagine that the sprite editor would also place the frames as so to align them as you switch between.

Each animation would have a name, and I envision 3 types:

  • Default animations, such as standing animations and attack patterns that suitable graphics sets get automatically. Replaceable, but prehaps not actually stored to file.
  • Nondefault predefined meaning. For example "walking left", however also includes animations not added by default when converting old games, eg "walking up-left"
  • User defined animations. Callable by name from scripts or other places, such as "Play hero animation" on textboxes.

Is there really any difference to the ease with which nohrio can manipulate graphics between: every frameset of every graphics set having a different size; and every frame a different size?

NeoTA: I try to compartmentalize my thinking about this kind of problem; the capabilities of nohrio didn't inform this description. (however, it's true that nohrio could handle either. memmapping works with fixed-width records, however, so a file containing variable-width records would need to be 'mapped' through a wrapper class if you wanted to read many records with random access.)

The limitation of all frames in a set being the same size is to avoid alignment problems, inconsistencies, and complexities. For example, if a frame is drawn according to a centre coordinate, and frames change between an odd width and an even width, it will bounce one pixel to the side (unless we store an anchor point to allow us to control this). By allowing variance in frame widths, you actually discard the implicit data indicating alignment, and as you said, have to add it back manually. In my opinion, the complexity introduced by variable-size frames is much greater than cost of the pixels wasted in non-wide/tall frames. but if you think of all frames as homogenous, I can understand why you might need to do this.. What about this: rather than every frame being variable size, allow sets of frames which share a size and an alignment .. this reduces the burden of choice on the user. I also think that the animation system ought to allow us to provide an additional offset per 'virtual frame' (ie. individual frame in an individual animation). (think about this: what do we do about bounding boxes and eg. weapon handles etc?)

Similarly, while I agree with the idea of animation patterns, I think they are also in danger of creating excessive complexity. (without the concept of multiple framesets, next/prev frame is not really sufficient IMO -- when frames > 64, being able to jump to a specific frame or in large steps is needed) If we can work out a GUI position for editing these that 'fits' well, I'll retract that.

re: sublumping: the graphicset format is not specified (since it's basically just a collection of framesets). it also using sublumping seems likely (esp. for ease of CUSTOM operation)

re: identifying frames: In this case, it makes sense to me to have a separate lump listing names for each frame, since this would be quite useful for editing and irrelevant to running. Empty named frames could be implicitly named <name of animation><index into animation> (eg WALKL02) and this name could be written upon changing it.

So, I officially agree that your 'collection of frames + animation patterns referencing them' idea is more practical than my 'graphicsets containing framesets' idea. We do still need a way to categorize graphics+animations though (walk, enemy, attack etc.. this scheme we are working on should render much of the old PT? design obsolete.)

fileformat sketching:

Animations:

(one animation-describing file for each category, with one lump for each animation.. ugh. could be improved. A lighterweight 'lump-like' format seems about right: RECORDSIZE(SHORT) ID(SHORT? or INT?) NRECORDS(SHORT) DATA(BYTES) [ID NRECORDS DATA...] Arguably this is partly-redundant with BINSIZE.BIN, but I'd argue that having record-size information stored locally to a lump makes things more robust, reduces i/o, makes utility writing easier, and arguably just makes more intuitive sense)

FRAMEID XOFFSET YOFFSET VALUE1 VALUE2 [...repeats]

(special operations being implemented via negative FRAMEID, eg 'wait 5 ticks' : FRAMEID = -1, VALUE1 = 5; 'loop to animation start': FRAMEID=-99, VALUE1=1, 'loop to 6th vframe': FRAMEID=-99, VALUE1 = 5, 'loop to -3th vframe'. i assume this kind of thing is what you meant by more advanced features)

VALUE2 is intended for commands like 'loop to start 2 times' (FRAMEID=-99 VALUE1=0 VALUE2=2)

frame data format: W H XOFFSET YOFFSET DATA (what is X/Y offset relative to? (bottom center of 'base box' seems appropriate to me.)

)

multiple frames are lumped . we need a strategy for balancing lumping I/O cost vs quick access when unlumped, this will be an issue as number of frames rise. A categorization of frame types (weapon, hero, etc.) will help here.

The Mad Cacti: Took some time to think about this

What about this: rather than every frame being variable size, allow sets of frames which share a size and an alignment .. this reduces the burden of choice on the user.

I don't follow: what logical unit would such a set of frames comprise?

I think most of the alignment/bounding box issues you mentioned are easily solved by the base size boxes; a better explanation: the base box would be the bounding box, because Game would only work with base boxes, and be completely unaware of the real size (and offset) of each frame except in special circumstances (eg. drawing the hero picker menu) where visual instead of logical size needs to be considered. I suppose placing attack graphics over an inbattle sprite would be one of these. It occurs to me now that you ought be able to set the base box per graphics set rather than being fixed per graphics type, due to the Plan for non-tile-based walking. I guess this means that you ought to be allowed to place weapon handle points outside of the box.

If the frame size defaults to the base size, then the user doesn't have to choose a larger frame size for the whole by guessing how much space they'll need. Does this increase or decrease the "burden of choice"?

what is X/Y offset relative to? (bottom center of 'base box' seems appropriate to me.)

But placing the origin at top left of base box would most directly specifies position and 'extents' over base box in each direction. The engine can place the sprite based on the base size box however it like: in some cases, you would want to anchor the center of the bottom edge at a screen position.

Similarly, while I agree with the idea of animation patterns, I think they are also in danger of creating excessive complexity. (without the concept of multiple framesets, next/prev frame is not really sufficient IMO -- when frames > 64, being able to jump to a specific frame or in large steps is needed) If we can work out a GUI position for editing these that 'fits' well, I'll retract that.

I definitely agree that complexity will have a potentially very high bound. (Not sure what is meant by 'GUI position'.) I imagine that you would be able to select a frame either from the animation, or from the graphics set; next/prev frame would navigate through the appropriate sequence. With key repeat you could move through 64 frames very quickly (though imprecisely). Prehaps we could create a menu with a 'view' of an animation as just the sequence of all the frames (loops optionally unrolled) to allow easy scrolling and selection. Also, if it necessary to compare two or more frames that are not sequential in any animation, you could reorder the graphics set to place them (possibly temporarily) sequentially; and assumably they are logically related.

Naming frames sounds like a good idea, especially with a way to reorder the frames in the graphics set (which of course updates all animations): for use by scripts. At least one person requested the ability to name tilesets.

We do still need a way to categorize graphics+animations though (walk, enemy, attack etc.. this scheme we are working on should render much of the old PT? design obsolete.)

It might seem to make sense to combine small/medium/large enemy sprites, but the possible complications of doing so seem very difficult. But after the old scheme is obsolete, the logical conclusion seems to be that all sizes of enemy are equal. (However there is a problem with formations: enemies are placed by top left coordinate, and you don't know what size enemy will spawn into an empty slot). Also, Plan for implementing battlescripting#An alternate possible plan could blur the distinction between walkabout, enemy, and hero graphics.

A lighterweight 'lump-like' format seems about right: RECORDSIZE(SHORT) ID(SHORT? or INT?) NRECORDS(SHORT) DATA(BYTES) [ID NRECORDS DATA...]

Ambiguity in your description: is the recordsize per animation, or per animation operation. I guess that's one way to have variable length records: size all records to the largest.

FRAMEID XOFFSET YOFFSET VALUE1 VALUE2 [...repeats]

If X/YOFFSET are only used by frames, then this is redundant to VALUE1/2. A triplet per animation operation would do.

I'm not sure about specifying the offset for every frame. I think modifying the offset would to be fairly rare, such as when creating a hoping animation. Alternatively, you could have an explicit 'set offset' operation, which stays in effect. It's a pretty minor detail though.

Tile animations are rather limiting in length, number, tileset layout requires, etc. and ought to be replaced. It would be nice to use the same animation format, but the operations are somewhat different. I thought that perhaps we could specify some animation operations specific to sprites, others to tiles. Would switching from animation 'template' patterns to one animation per animated tile be a good idea? Maybe ideally support both? This is a mess.

we need a strategy for balancing lumping I/O cost vs quick access when unlumped, this will be an issue as number of frames rise.

Odd, I only realised after multiple readthroughs that you suggested storing each frame in a lump. I suppose that is doable, but is it very benficial? The benefit is to be able to extract a frame as a self contained file; but it is not really self contained, since the bitdepth was not specified. Would the filename encode any information?

Loading an RPG (without unlumping) by creating an index of all lumps and sublumps and subsublumps starts to become large and expensive - clearly you would only want to index the sublumps of a graphics set when loading it. I don't see why you would need fast random access to a specific frame without loading the whole graphics set.