Detect collision in PVSnesLib

Démarré par faeldaniel, 17 Juillet 2013 à 19:42:32

« précédent - suivant »

0 Membres et 1 Invité sur ce sujet

faeldaniel

Hello alekmaul,

i did not understand how the collision in unique existing example in "likemario"  :-\

As I understand it you must create an image with two color palettes where the first color is pink, the second color is the collision. Having as an example of "AnimatedSprite" how do I image that the sprite does not move through the squares reds? below is how I did it so does not work.

This is my example "AnimatedSprite" but not work, this is link for the project test the collision https://anonfiles.com/file/d156b7840b851b865b018ff44df47b41:



/*---------------------------------------------------------------------------------
Animated Sprite demo
-- alekmaul
Sprite from Stephen "Redshrike" Challener), http://opengameart.org
---------------------------------------------------------------------------------*/
#include <snes.h>

extern char gfxpsrite, gfxpsrite_end;
extern char palsprite, palsprite_end;

extern char patterns, patterns_end;
extern char palette, palette_end;
extern char map, map_end;

extern char col, col_e;

#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,


//---------------------------------------------------------------------
// The magic function for collision
//---------------------------------------------------------------------
u16 getCollisionTile(u16 x, u16 y) {
u16 *ptrMap = (u16 *) &col + (y) + (x);

return (*ptrMap);
}

//---------------------------------------------------------------------------------
int main(void) {
unsigned short pad0,i;
Monster monster = {10,10};

    // Initialize SNES
consoleInit();

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


// Copy tiles to VRAM
bgInitTileSet(0, &patterns, &palette, 0, (&patterns_end - &patterns), (&palette_end - &palette), BG_16COLORS, 0x4000);

// Copy Map to VRAM
bgInitMapSet(0, &map, (&map_end - &map),SC_32x32, 0x1000);


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


// Now Put in 16 color mode and disable all backgrounds
setMode(BG_MODE1,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 (getCollisionTile((monster.x), ((monster.y) - 1)) == 0) {
if(monster.y >= SCREEN_TOP) monster.y--;
}
monster.state = W_UP;
monster.flipx = 0;
}
if(pad0 & KEY_LEFT) {
if (getCollisionTile(((monster.x) - 1), (monster.y)) == 0) {
if(monster.x >= SCREEN_LEFT) monster.x--;
}
monster.state = W_LEFT;
monster.flipx = 1;
}
if(pad0 & KEY_RIGHT) {
if (getCollisionTile(((monster.x) + 1), (monster.y)) == 0) {
if(monster.x <= SCREEN_RIGHT) monster.x++;
}
monster.state = W_LEFT;
monster.flipx = 0;
}
if(pad0 & KEY_DOWN) {
if (getCollisionTile((monster.x), ((monster.y) + 1)) == 0) {
if(monster.y <= SCREEN_BOTTOM) monster.y++;
}
monster.state = W_DOWN;
monster.flipx = 0;
}
monster.anim_frame++;
if(monster.anim_frame >= FRAMES_PER_ANIMATION){
monster.anim_frame = 0;
}
}

// 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);


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




Fix this code for me?  ;D

alekmaul

#1
Well, the collision map uses 8x8 pixel for each tile, so you need to devide coordinate by the size of your collide box.
Also, to have the correct tile, you must add map size * y , not only y.

Citationu16 getCollisionTile(u16 x, u16 y) {
   u16 *ptrMap = (u16 *) &col + (y>>3)*32+ (x>>3);
   
   return (*ptrMap);
}

But, you also need to take care of sprite size and where is the point that you need to use to check the collide box.
Here is an example, "not so good" but that uses a point near middle of sprite to test hit box with back ground (so I use x+8, y+8).

Citation
/*---------------------------------------------------------------------------------


   Animated Sprite demo
   -- alekmaul

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

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

extern char gfxpsrite, gfxpsrite_end;
extern char palsprite, palsprite_end;

extern char patterns, patterns_end;
extern char palette, palette_end;
extern char map, map_end;

extern char col, col_e;

#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,


u16 getCollisionTile(u16 x, u16 y) {
   u16 *ptrMap = (u16 *) &col + (y>>3)*32 + (x>>3);
   
   return (*ptrMap);
}

//---------------------------------------------------------------------------------
int main(void) {
   unsigned short pad0,i;
   Monster monster = {10,10};
   
    // Initialize SNES
   consoleInit();
   
   // Init Sprites gfx and palette with default size of 16x16
   oamInitGfxSet(&gfxpsrite, (&gfxpsrite_end-&gfxpsrite), &palsprite, (&palsprite_end-&palsprite), 0, 0x0000, OBJ_SIZE16);
   
   
   // Copy tiles to VRAM
   bgInitTileSet(0, &patterns, &palette, 0, (&patterns_end - &patterns), (&palette_end - &palette), BG_16COLORS, 0x4000);

   // Copy Map to VRAM
   bgInitMapSet(0, &map, (&map_end - &map),SC_32x32, 0x1000);
   
   
   // Define sprites parameters
   oamSet(0,  monster.x, monster.y, 0, 0, 0, 0, 0);
   oamSetEx(0, OBJ_SMALL, OBJ_SHOW);

   
   // Now Put in 16 color mode and disable all backgrounds
   setMode(BG_MODE1,0); bgSetDisable(1); bgSetDisable(2);
   
   // Wait VBL 'and update sprites too ;-)
   WaitForVBlank();
      
   // Wait for nothing :P
   while(1) {
      // Refresh pad values
      // no more need with last lib scanPads();
      
      // Get current #0 pad
      pad0 = padsCurrent(0);
      
      if (pad0) {
         // Update sprite with current pad
         if(pad0 & KEY_UP) {
            if (getCollisionTile((monster.x+8), ((monster.y) - 1)) == 0) {
               if(monster.y >= SCREEN_TOP) monster.y--;
            }
            monster.state = W_UP;
            monster.flipx = 0;
         }
         if(pad0 & KEY_LEFT) {
            if (getCollisionTile(((monster.x) - 1), (monster.y+8)) == 0) {
               if(monster.x >= SCREEN_LEFT) monster.x--;
            }
            monster.state = W_LEFT;
            monster.flipx = 1;
         }
         if(pad0 & KEY_RIGHT) {
            if (getCollisionTile(((monster.x +16) +1), (monster.y+8)) == 0) {
               if(monster.x <= SCREEN_RIGHT) monster.x++;
            }
            monster.state = W_LEFT;
            monster.flipx = 0;
         }
         if(pad0 & KEY_DOWN) {
            if (getCollisionTile((monster.x+8), ((monster.y+16) + 1)) == 0) {
               if(monster.y <= SCREEN_BOTTOM) monster.y++;
            }
            monster.state = W_DOWN;
            monster.flipx = 0;
         }
         monster.anim_frame++;
         if(monster.anim_frame >= FRAMES_PER_ANIMATION){
            monster.anim_frame = 0;
         }
      }
      
      // 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);
   
      
      // Wait VBL 'and update sprites too ;-) )
      WaitForVBlank();
   }
   return 0;
}