Multisprites ?

SGDK only sub forum

Moderator: Stef

tryphon
Very interested
Posts: 316
Joined: Sat Aug 17, 2013 9:38 pm
Location: France

Multisprites ?

Post by tryphon » Sat Dec 20, 2014 9:05 am

hi,

when you have to draw a sprite whose size is more than 32x32, you have to cut it into several smaller sprites.

I call this assembly a Multisprite, but there may be a more widespread terminology.

Are there functions in SGDK to handle it or have I to code it ?

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Sat Dec 20, 2014 10:48 am

The new sprite engine handle it for you. Just look in the "sprite" sample from SGDK to see how to deal with sprites :
https://code.google.com/p/sgdk/source/b ... src/main.c

It's quite easy actually, just give a sprites sheet to the resource compiler and it generate all structures for you. Then You just need to play with the SPR_xxx method to handle your sprites.

It's also important to read the rescomp.txt file to understand how resources work in SGDK :
https://code.google.com/p/sgdk/source/b ... escomp.txt

tryphon
Very interested
Posts: 316
Joined: Sat Aug 17, 2013 9:38 pm
Location: France

Post by tryphon » Sat Dec 20, 2014 6:17 pm

Thanks.

If I understand correctly your terminology :
* a tile is a 8*8 bitmap
* a frame is an assembly of "sprites in the sense of VDP" (you call it a VDPsprite?)
* a sprite is a set of frames
* Genres isn't yet able to detect empty tiles in a frame.

I guess it's not yet able to detect shared tiles in different frames ?

I dont know how genres cut frames, does it cut rectangles whose edges are aligned on multiples of 8 (for example, I guess a 40x40 px frame will be cut in a 32x32, a 8x32, a 32x8 and a 8x8 ) ? Or is possible to give any position (not necessarily multiples of 8 ) for parts of the frame ? (the goal would be to maximize redundant tiles in different frames : think of the head of a character, which is the same in most frames, but moved one pixel up or down between walking frames).

PS : I know lots of members are french. Is there a french board somewhere for discussing SGDK or MD programming ? (My English is quite laborious and I've difficulties in handling efficiently technical discussions when they become tricky) (which is not yet the case but could occur :) ) (at least I hope this message is understandable).

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Sat Dec 20, 2014 7:00 pm

Be careful, i am not speaking about genres which is a different resource complier (.rc file). I was speaking about rescomp (.res file) which do not use the same structures at all.

In rescomp :
- a tile is a bloc of 8x8 pixel
- a VDPSprite is a bloc of 8x8 to 32x32 pixel defining a hardware VDP sprite
- a FrameSprite is just a VDPSprite with the attached TileSet
- a AnimationFrame a single frame of animation and can be composed of several FrameSprite (VDP sprite) if its size is > 32x32 pixels.
- a Animation is a complete sheet row defining one of the sprite animations.
- a SpriteDefinition contains all the Animation present in a sheet (so a SpriteDefinition defines a complete sheet of sprite).
- a Sprite is just the live sprite structure storing information for an active sprite (its position on screen, the attached SpriteDefinition information, the current active animation and frame animation)...

I know it's a bit complex but this structure allow flexible and easy sprite manipulation.
Right now, rescomp is able to detect duplicate tileset, it means it detects duplicated hardware sprite but only if they have same size.
When rescomp analyze the sprite sheet it generate "lazy" sprite cut (for multiple sprites) and so it is not "optimized". But if you want, you can define your own SpriteDefinition manually to optimizing the tileset usage (structures allow it).

There is a french site for megadrive development but not as active as here :
http://www.ultimate-consoles.fr/index

tryphon
Very interested
Posts: 316
Joined: Sat Aug 17, 2013 9:38 pm
Location: France

Post by tryphon » Sun Dec 21, 2014 9:34 am

Thanks for the answer.

Still some questions (don't hesitate to tell me if I'm getting... er... "lourd") :

* let's say I have all animations in a spritesheet and the resulting SpriteDefinition structure. Will all the tiles composing all the AnimationFrames be loaded in VRAM at once, or will the engine load only the ones relevant for the current AnimationFrame ? I'm studying the Shadow Dancer code, and it only load the current AnimationFrame's tiles to preserve VRAM, for the main sprites and the ennmies present at screen at the moment.

* If I want to make my own SpriteDefinition generator, in which format am I supposed to export it ? It seems (from "tools/rescomp/src/sprite.c") that you export it as a sequence of dc.?, but I haven't still understood the fate of the generated files during the compilation process (I suck at compilation process anyway - I turn into panic mode as soon as the compiler throw an error I don't understand)

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Sun Dec 21, 2014 10:46 am

tryphon wrote: * let's say I have all animations in a spritesheet and the resulting SpriteDefinition structure. Will all the tiles composing all the AnimationFrames be loaded in VRAM at once, or will the engine load only the ones relevant for the current AnimationFrame ? I'm studying the Shadow Dancer code, and it only load the current AnimationFrame's tiles to preserve VRAM, for the main sprites and the ennmies present at screen at the moment.
Of course the sprite engine only load the current AnimationFrame in VRAM else you quickly run out of VRAM !
Actually when you initialize the Sprite Engine with the method

Code: Select all

void SPR_init(u16 value);
The value is the number of tiles to reserve in VRAM for sprites.
It internally uses the "Tile Cache" feature of SGDK which allow to deal with tile allocation in VRAM.
So depending the number of tiles you allocate to sprite, the Sprite Engine will be able to "cache" less or more tiles in VRAM and in best case avoid to re-upload already loaded tiles.
* If I want to make my own SpriteDefinition generator, in which format am I supposed to export it ? It seems (from "tools/rescomp/src/sprite.c") that you export it as a sequence of dc.?, but I haven't still understood the fate of the generated files during the compilation process (I suck at compilation process anyway - I turn into panic mode as soon as the compiler throw an error I don't understand)
Hehe, actually you just need to generate the different sprite structures :
VDPSprite, TileSet, FrameSprite, AnimationFrame, Animation then SpriteDefinition
I do it in assembly (.s file) as i can control alignment for instance but you can do it in C as you don't need any memory alignment for the sprites structures.

For instance in your generated .c file :

Code: Select all

u32 _tiledata1[4] =
{
  0x00022334,
  0x01113455,
  0x01234553,
  0x00113430
};

TileSet _tset1 =
{
    COMPRESSION_NONE,    // compression
    4*4,    // number of tile
    _tiledata1   // tiledata
};

FrameSprite _fspr1 =
{
  // VDPSprite
  {
    0,    // y pos
    SPRITE_SIZE(2, 2),    // size_link (2x2 tiles here)
    TILE_ATTR_FULL(FALSE, PAL0, FALSE, FALSE, 0),    // tile attributs
    0     // x pos
  },
  // TileSet*
  _tset1
}

FrameSprite _fspr2 =
{
  // VDPSprite
  {
    0,    // y pos
    SPRITE_SIZE(2, 2),    // size_link
    TILE_ATTR_FULL(FALSE, PAL0, FALSE, FALSE, 4),    // tile attribut
    16     // x pos
  },
  // TileSet*
  _tset1
}

FrameSprite _fspr3 =
{
  // VDPSprite
  {
    16,    // y pos
    SPRITE_SIZE(2, 2),    // size_link
    TILE_ATTR_FULL(FALSE, PAL0, FALSE, FALSE, 8),    // tile attribut
    0     // x pos
  },
  // TileSet*
  _tset1
}

FrameSprite _fspr4 =
{
  // VDPSprite
  {
    16,    // y pos
    SPRITE_SIZE(2, 2),    // size_link
    TILE_ATTR_FULL(FALSE, PAL0, FALSE, FALSE, 12),    // tile attribut
    16     // x pos
  },
  // TileSet*
  _tset1
}

FrameSprite* _fsprites[] =
{ _fspr1, _fspr2, _fspr3, _fspr4 };

AnimationFrame _aframe1 =
{
	4,    // number of sprite
	_fsprites;   // sprite array
	0,   // number of collision
	NULL,   // collision array
	32,     // width of current animation frame in pixel
	32,     // height of current animation frame in pixel
	COLLISION_TYPE_NONE,    // collision type
	5,   // time to keep this frame in number of frame
};

....
I think you got the idea !
But you really need to understand the different sprite structures before doing that (they are all documented in the spr_eng.h file) !

KanedaFr
Administrateur
Posts: 1139
Joined: Tue Aug 29, 2006 10:56 am
Contact:

Post by KanedaFr » Sun Dec 21, 2014 11:52 am

just be aware than multisprites consumes a lot of code
So use them only on game with a few (multi)sprites on screen hence it will lags (learnt it the hard way)

So perfect for a fighting game but don't use it on a platformer or a shooter

I'm currently fixing mine (using GenRes so need to be adapted for ResComp) to handle a mix of single and multi sprite
this way I'll be able to handle big end level boss without requiring mutlisprite everywhere, even for a single shot

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Sun Dec 21, 2014 1:21 pm

It's true that my code for handling sprite (and so multi sprite) is really slow and dealing with many sprites will make the game slowdown...
I really need to optimize it by converting to assembly still it won't never be blazing fast.

tryphon
Very interested
Posts: 316
Joined: Sat Aug 17, 2013 9:38 pm
Location: France

Post by tryphon » Mon Dec 22, 2014 1:09 pm

Stef wrote:Of course the sprite engine only load the current AnimationFrame in VRAM else you quickly run out of VRAM !
Some games do load all frames at once (okay, the only ones I know are RPGs)
I think you got the idea !
Got it, thanks :)
But you really need to understand the different sprite structures before doing that (they are all documented in the spr_eng.h file) !
I have my eyes on it since yesterday :)
It's true that my code for handling sprite (and so multi sprite) is really slow and dealing with many sprites will make the game slowdown...
I really need to optimize it by converting to assembly still it won't never be blazing fast.
The goal is arcade Shinobi. So there are at most 5 characters at screen, each one is a multisprite around 48x56 pixels (+ some projectiles). I can prepare the tiles so that all the tiles for a given Multisprite can be directly DMA-ed to VRAM. I'll try to design the code so as I can use your Sprite engine at least for prototyping, then switch to a custom engine maybe better suited for this case.

djcouchycouch
Very interested
Posts: 710
Joined: Sat Feb 18, 2012 2:44 am

Post by djcouchycouch » Mon Dec 22, 2014 1:57 pm

You can take a look at the projects I recently released code for (Pingouin Bleu, Pingouin Rose, Violence Pingouin, etc.) They handle large sprites converted from Graphics Gale files. Violence Pingouin is the closest to Shinobi in terms of gameplay.

I'm pretty confident you could do a Shinobi clone with only SGDK. You'd need to work on optimization, of course, but I feel it's perfectly doable.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Mon Dec 22, 2014 3:53 pm

Indeed i believe a Shinobi port should be doable with SGDK.
To be honest i would love to see a 1:1 port of the arcade version on Sega Genesis and if you experience performances issue i can work to improve that in SGDK. What mainly eat time in the sprite engine is the SPR_Update(..) method. I almost certain than converting this method and maybe computeVisibility(..) to assembly can already bring a 2x factor performance improvement. Converting some of the tile cache engine methods can help too. You should also give a look on the sources of the different projects made by DJCC as he pointed ! He's using SGDK and his own structures and actually it does work pretty well for 100% C code !

tryphon
Very interested
Posts: 316
Joined: Sat Aug 17, 2013 9:38 pm
Location: France

Post by tryphon » Mon Dec 22, 2014 4:21 pm

A 1:1 port is not possible due to palettes limitations (I don't have System-16 specs, but Shinobi display quite a few more than 61 colors). I'll try to adapt MD Shadow Dancer constraints (12 colors for Musashi, one palette for the background, and clever use of the rest). Except for that, I'll try to stick the most closely possible to the arcade.

Edit by stef: I'm really sorry, I edited your post by mistake (sometime happen as i am moderator on SGDK sub section) and can't recover your whole original message :-/

Moon-Watcher
Very interested
Posts: 117
Joined: Sun Jan 02, 2011 9:14 pm
Contact:

Post by Moon-Watcher » Mon Dec 22, 2014 5:16 pm

I experienced slowdowns (40 simultaneous sprites) only when transferring lots of tiles to the VRAM at the same time. I decided lowering the refresh rate and to give the sprites fixed positions instead using automatic location. It worked for me :)

I also think a Shinobi port is quite posible

djcouchycouch
Very interested
Posts: 710
Joined: Sat Feb 18, 2012 2:44 am

Post by djcouchycouch » Mon Dec 22, 2014 6:06 pm

In my projects, I only updated the player's tiles in the VDP since it had by far the most frames of animation. Everything else had few frames. The enemies and backgrounds and everything else I made to fit in the remaining space for that level/section. I also needed DMA bandwidth to update the foreground plane's columns/rows when scrolling.

tryphon
Very interested
Posts: 316
Joined: Sat Aug 17, 2013 9:38 pm
Location: France

Post by tryphon » Mon Dec 22, 2014 11:10 pm

Shadow Dancer updates up to 256 tiles, from what I saw.

I also think I'll use fixed address in VRAM.

Post Reply