How to duplicate sprites using different colors?

Démarré par zenac, 14 Mai 2014 à 17:05:51

« précédent - suivant »

0 Membres et 1 Invité sur ce sujet

zenac

How can I draw the same sprite two times in the same screen but using different colors? For example, in a fight "Ryu (white clothes) vs. Ryu (dark clothes)" in "Street Fighter II" or in a sport game (Lakers with yellow uniform and Celtics with green uniform). Considering that two objects have the same sprite, can I associate the first object to a palette and the second object to another different palette?

alekmaul

Well, as you said, you need to create two palettes, on for 1st tile and another for second and you need to modify last parameter of oamSet to use the correct palette.
Be careful to have same color id for the sprite in the two palette.
transparent palette muset be #0 and  #16 for two sprite, 1 color #1 and #17, and so on ...

zenac

I am trying it, but my program doesn't work.

I am changing "AnimatedSprite" project to "TwoAnimatedSprites". In the image "sprites.bmp", I have set new colors in the palette: color #16 is magenta (equal to color #0) and I have added new colors from #17 to #31.

Lines 63 to 65 in Makefile changed (I have changed "pc16 -po16" to "pc256 -po256" in line 65):


sprites.pic: sprites.bmp
@echo convert bitmap ... $(notdir $@)
$(GFXCONV) -gs16 -pc256 -po256 -n $<


And my complete "TwoAnimatedSprites.c" below:


/*---------------------------------------------------------------------------------


Animated Sprite demo
-- alekmaul

Sprite from Stephen "Redshrike" Challener), http://opengameart.org

---------------------------------------------------------------------------------*/
#include <snes.h>

extern char gfxpsrite, gfxpsrite_end;
extern char palsprite;

#define FRAMES_PER_ANIMATION 3 // 3 sprites per direction

//---------------------------------------------------------------------
// The Monster sprite
//---------------------------------------------------------------------
typedef struct
{
short x, y;
int gfx_frame;
int state;
int anim_frame;
int flipx;
} Monster;

//---------------------------------------------------------------------
// The state of the sprite (which way it is walking)
//---------------------------------------------------------------------
enum SpriteState {W_DOWN = 0, W_UP = 1, W_RIGHT = 2,  W_LEFT = 2};

//---------------------------------------------------------------------
// Screen dimentions
//---------------------------------------------------------------------
enum {SCREEN_TOP = 0, SCREEN_BOTTOM = 224, SCREEN_LEFT = 0, SCREEN_RIGHT = 256};

char sprTiles[9]={0,2,4, 6,8,10, 12,14,32};  // Remeber that sprites are interleave with 128 pix width,

//---------------------------------------------------------------------------------
int main(void) {
unsigned short pad0,i;
Monster monster = {100,100};
Monster monster2 = {150,150}; // NEW LINE

    // Initialize SNES
consoleInit();

// Init Sprites gfx and palette with default size of 16x16
oamInitGfxSet(&gfxpsrite, (&gfxpsrite_end-&gfxpsrite), &palsprite, 0, 0x4000, OBJ_SIZE16);

// Define sprites parameters
oamSet(0,  monster.x, monster.y, 0, 0, 0, 0, 0);
oamSetEx(0, OBJ_SMALL, OBJ_SHOW);

oamSet(16,  monster2.x, monster2.y, 0, 0, 0, 0, 16);  // NEW LINE
oamSetEx(16, OBJ_SMALL, OBJ_SHOW);  // NEW LINE

// Now Put in 16 color mode and disable all backgrounds
setMode(BG_MODE1,0); bgSetDisable(0); bgSetDisable(1); bgSetDisable(2);

// Wait VBL 'and update sprites too ;-) )
WaitForVBlank();

// Wait for nothing :P
while(1) {
// Refresh pad values
scanPads();

// Get current #0 pad
pad0 = padsCurrent(0);

if (pad0) {
// Update sprite with current pad
if(pad0 & KEY_UP) {
if(monster.y >= SCREEN_TOP) monster.y--;
monster.state = W_UP;
monster.flipx = 0;
if(monster2.y >= SCREEN_TOP) monster2.y--;  // NEW LINE
monster2.state = W_UP;  // NEW LINE
monster2.flipx = 0;  // NEW LINE
}
if(pad0 & KEY_LEFT) {
if(monster.x >= SCREEN_LEFT) monster.x--;
monster.state = W_LEFT;
monster.flipx = 1;
if(monster2.x >= SCREEN_LEFT) monster2.x--;  // NEW LINE
monster2.state = W_LEFT;  // NEW LINE
monster2.flipx = 1;  // NEW LINE
}
if(pad0 & KEY_RIGHT) {
if(monster.x <= SCREEN_RIGHT) monster.x++;
monster.state = W_LEFT;
monster.flipx = 0;
if(monster2.x <= SCREEN_RIGHT) monster2.x++;  // NEW LINE
monster2.state = W_LEFT;  // NEW LINE
monster2.flipx = 0;  // NEW LINE
}
if(pad0 & KEY_DOWN) {
if(monster.y <= SCREEN_BOTTOM) monster.y++;
monster.state = W_DOWN;
monster.flipx = 0;
if(monster2.y <= SCREEN_BOTTOM) monster2.y++;  // NEW LINE
monster2.state = W_DOWN;  // NEW LINE
monster2.flipx = 0;  // NEW LINE
}
monster.anim_frame++;
if(monster.anim_frame >= FRAMES_PER_ANIMATION) monster.anim_frame = 0;
monster2.anim_frame++;  // NEW LINE
if(monster2.anim_frame >= FRAMES_PER_ANIMATION) monster2.anim_frame = 0;  // NEW LINE
}

// Now, get current sprite in current animation
monster.gfx_frame = sprTiles[monster.anim_frame + monster.state*FRAMES_PER_ANIMATION ];
oamSet(0,  monster.x, monster.y, 3, monster.flipx, 0, monster.gfx_frame, 0);

monster2.gfx_frame = sprTiles[monster2.anim_frame + monster2.state*FRAMES_PER_ANIMATION ];  // NEW LINE
oamSet(16,  monster2.x, monster2.y, 3, monster2.flipx, 0, monster2.gfx_frame, 16);  // NEW LINE

// Wait VBL 'and update sprites too ;-) )
WaitForVBlank();
}
return 0;
}



I have NOT changed "date.asm" and "hdr.asm".

alekmaul

-po16 is better because you can only have 16 colors for sprites, same for -pc. But you need to convert each sprite graphics/palette even if you dn't use them (for graphcis if I understand well your need ).
Also, you need to specify- pe to add to correct palette entry with something like -pe1 and put 1 in the last parameter of oamSet to have correct palette.
At least, you need to load second palette, even if you don't load graphics (because they are the same as your palette #0 graphics).
dmaCopyCGRam is the function you need to do such thing.

zenac