Some questions about SGDK

SGDK only sub forum

Moderator: Stef

Post Reply
izidor
Interested
Posts: 15
Joined: Tue Jan 26, 2021 12:20 pm

Some questions about SGDK

Post by izidor » Wed Feb 03, 2021 6:22 am

Hello,
I would need confirmation, if I understood correctly, Plane A and B can scroll vertically and horizontally and the sprite plane is fixed.
For the coordinate system, the reference point is the coordinate 0,0 of (top left of the screen). When the BGs scroll, I have to update a variable which simulates the displacement of the screen / relative to the BG plane. admit:
Map map // 1280x986pixel
map.x = 0
map.y = 0
Camera_x = map.x; (at the beginning)
Camera_y = map.y; (at the beginning)
display map on BG_A
scroll_map(Camera_x, Camera_y)
if scroll left, Camera_x --
if scrolling to the right, Camera_x ++
ditto with Camera_y and up, down.
Does it work well like this?

Now the sprites, it is compared to screen? to have a sprite that follows the scrolling, I have to update each time it scrolls.
example:
if Camera_x-- then sprite.x ++
if Camera_x ++ then sprite.x --
if Camera_y -- then sprite.y ++
if Camera_y ++ then sprite.y --

Is my reasoning correct? How to update all the sprites that follow the scrolling in a single loop? Does SGDK have something for that? Or should I write the structures and functions for it (exmple: Chained list of * sprite with function to update coordinates)?

Thank you for your answers.

izidor
Interested
Posts: 15
Joined: Tue Jan 26, 2021 12:20 pm

Re: Some questions about SGDK

Post by izidor » Wed Feb 03, 2021 3:44 pm

Apparently, we need to update the sprite position coordinates according to the Camera, I just wrote a function to handle that and it works fine.

Other questions, I looked for on the forum but the subject is only partially addressed. I have a problem to stop an animation on the last frame, I thought I could control that with a loop variable (loopAnim) but it doesn't want to know anything, my animations are still playing in a loop. I have seen that several posts speak about function SPR_setFrame, SPR_nextFrame but I do not see how used them.
Thank you for your advice

Here is my code
Structure

Code: Select all

typedef struct Door
{
  s16 POS_X;
  s16 POS_Y;
  s16 Width;
  s16 Height;
  enum Rank rank;
  enum State state;
  enum Type type;
  enum Status status;
  int IndexDoor;
  int loopAnim;
  Sprite * SPR_door;
}Door;

Door* Create_door()
{
   Door *door = NULL;
   door = MEM_alloc(sizeof(Door));
   if(door==NULL)
   {
      //KLog("Erreur, impossible d'allouer de la memoire pour Door");
   }
   door->state = Close;
   door->status = Lock;
   door->loopAnim = 0;   
   return door;
}
void Init_door(Door *door, int x, int y, int w, int h,  int id, enum Type t, enum Rank r)
{
   door->POS_X = x;
   door->POS_Y = y;
   door->Height =h;
   door->Width = w;
   door->IndexDoor = id;
   door->rank = r;
   door->type = t;
   VDP_setPalette(PAL3, Porte.palette->data);
   door->SPR_door=SPR_addSprite(&Porte, x, y, TILE_ATTR(PAL3,0,FALSE,FALSE));
}

Fonction anim

Code: Select all

void Anim_door(Door *door, bool IsCollision)
{
  switch (IsCollision)
  {
   case TRUE:
        if((door->state==Close)&&(door->status==Unlock)&&(door->loopAnim == 0))
        {
            SPR_setAnim(door->SPR_door, Anim_Door_Open);
            door->state = Open;  
            door->loopAnim = 1;
        }
   break;
   case FALSE:     
        if((door->state==Open)&&(door->loopAnim == 0))
        {
            SPR_setAnim(door->SPR_door, Anim_Door_Close);
            door->state = Close;  
            door->loopAnim = 1;
        }
  break;
  }
  if(door->state == Close)
  {
    door->loopAnim =0;
  }
}

izidor
Interested
Posts: 15
Joined: Tue Jan 26, 2021 12:20 pm

Re: Some questions about SGDK

Post by izidor » Thu Feb 04, 2021 6:57 am

No one to help me! I will wait, there is someone who will come :D .
In the meantime I observed SPR_Update () sprite_eng.c to try to
understand this part:

Code: Select all

 // handle frame animation
        if (timer)
        {
            // timer elapsed --> next frame
            if (--timer == 0) SPR_nextFrame(sprite);
            // just update remaining timer
            else sprite->timer = timer;
        }
at the start of the loop we have a timer u16 initialized with the sprite timer.
The condition for changing the frame is that Timer-1 == 0 (the time has elapsed)
otherwise we update the sprite timer with the u16 timer but I don't understand, or is it decremented?


Another question, In a large map (Resource MAP) how is to manage the coordinates of sprites in the virtual space 512x512.

My map is 1280x896ppx (160x112 Tille), if I put a sprite at 128 * 304, once the camera goes above 512 it gives me one sprite at 128x816 and probably two others at 672x304 and 672x816.

Image Image

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

Re: Some questions about SGDK

Post by Stef » Thu Feb 04, 2021 10:10 am

Hi Izidor,

You have a small sample in SGDK folder called "sprite" (now called "sonic" on github) which demonstrate how to deal with all of these :)
Map scrolling, how camera position is computed from main player sprite position, then how sprites are positions are put relative to this camera position.
Obviously you need to store "world position" for sprites and make them invisible / inactive when they are outside visible area.

izidor
Interested
Posts: 15
Joined: Tue Jan 26, 2021 12:20 pm

Re: Some questions about SGDK

Post by izidor » Thu Feb 04, 2021 10:27 am

Thanks, I'll take your advice and watch this.

izidor
Interested
Posts: 15
Joined: Tue Jan 26, 2021 12:20 pm

Re: Some questions about SGDK

Post by izidor » Sun Feb 07, 2021 5:56 am

Hello,
I have a small problem with the recovery of the tile at the player's position for collisions. I get the tile this way
: pos_x = player.x >> 3, pos_y = player.x >> 3 (division by eight)
the variables player.y and player.y, pos_x and pos_y are declared in u16
To increment player.x and player.y I use a u16 velocity = 2, so two pixels + - to the left or to the right.

The problem is that if player.x = 70, the player is 2 pixels on tile number 8 and 8 pixels on tile number 9 and with 70 >> 3 then pos__x = 8, it returns tile 8 to me while the player is more under the tile 9. I think of rounding up with the nearest whole number but the problem would appear in the other direction.

It gives me a shift when I test in the collision table, the collision is " true" while the player is 8 pixels from the wall.
(I test the tiles around the player)

I saw the samples "sprite of the SGDK folder the position of the player is declared with a fix32 (float)", is there a link with the problem that I encounter or so this float is just to manage the starting speed of sonic (friction).
Thanks for your help!

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

Re: Some questions about SGDK

Post by Stef » Mon Feb 08, 2021 11:26 pm

What about using (posx + 4) >> 3, so it will indeed round the tile position.
Then what about just testing multiple tile position, for collision you may need kind of bounding box collision type so it actually touch several tiles at once.

Code: Select all

(posx + 8) >> 3 for maxX and (posx - 8) >> 3 for minX
, it's just an example, depend from your sprite position afaik.

izidor
Interested
Posts: 15
Joined: Tue Jan 26, 2021 12:20 pm

Re: Some questions about SGDK

Post by izidor » Tue Feb 09, 2021 6:41 am

Ok, thanks for the answer, in the meantime I found a solution:
and indeed I test the tiles where the player is.

Code: Select all

 
if( posx%8 >4 ){ tile_x = ((posx - psox%8)>>3) +1}
else tile_x = ((posx - psox%8)>>3) 

if( posy%8 >4 ){ tile_y = ((posxy - psoxy%8)>>3) +1}
else tile_y = ((posxy - psoxy%8)>>3) 

test_collision (tile_x, tile_y, Table_collision)
 
Last edited by izidor on Tue Feb 09, 2021 3:45 pm, edited 1 time in total.

izidor
Interested
Posts: 15
Joined: Tue Jan 26, 2021 12:20 pm

Re: Some questions about SGDK

Post by izidor » Tue Feb 09, 2021 8:14 am

I have another question regarding the Vblank period, can I use
if (SYS_doVBlankProcess ()) in a function to perform an operation after Vblank period. I tested it looks good but I want to be sure it won't be a source of problem.

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

Re: Some questions about SGDK

Post by Stef » Tue Feb 09, 2021 2:23 pm

Doing that will force to wait for a complete frame (wait for vblank and doing attached vblank process).
It does not guarantee though that after the call you are not in vblank anymore, if the process are shorter than vblank period (and it's likely to happen) then you will be still in vblank after the SYS_doVBlankProcess() call.
If you really want to force to do your task outside VBlank period (it's rare you want to do that but why not) then you need to call VDP_waitVActive(FALSE) after SYS_doVBlankProcess().

izidor
Interested
Posts: 15
Joined: Tue Jan 26, 2021 12:20 pm

Re: Some questions about SGDK

Post by izidor » Tue Feb 09, 2021 3:56 pm

I expressed myself badly, indeed I want to do this operation during a Vblank, in fact I want to slide the camera of X pixel. if I do it outside of Vblank,the camera immediately goes to the position but I tested in a Vblank period and it seems to work, I find it a bit risky to do it in a for loop

Code: Select all

 
enum type_collision = Get_WorldCollsionType(struct *player)
if(type_collision == SliceCamera)
{
      player->move = false
       for( int i =0; i<50, i++)
       {
          if (SYS_doVBlankProcess ())
          {
                camera.y += Camera_speed
                Move_camera(x, y);
          }
      } 
}
player.move = true;
 
 

I'm sorry for all his questions, but I really want to learn well with SGDK :)

izidor
Interested
Posts: 15
Joined: Tue Jan 26, 2021 12:20 pm

Re: Some questions about SGDK

Post by izidor » Mon Feb 15, 2021 5:18 pm

Hello, another question
I have a sprite that won't be erased, i am using the SPR_releaseSprite () function, this sprite is initialized when the player presses a button and i want to delete it when the player presses another button. When I pass all my other sprites as a parameter, no problem it all gets erased ert frees the vram space but it remains displayed. I do not understand.

Detail create inventaire

Code: Select all

typedef struct Inventaire
{
   Sprite *Curseur;<--------------------------
}Inventaire;

Inventaire* Create_inventaire()
{
 Inventaire *Iv=NULL;
    Iv = MEM_alloc(sizeof(Inventaire));
    if(Iv == NULL)
    {

    }   
    return Iv; 
}
Initialized world

Code: Select all

void INIT_level()
{
    //palette
    VDP_setPaletteColors(0,(const u16*)Palette0,16);
    VDP_setPaletteColors(16,(const u16*)Palette1,16);
    //timer
    Frame_counter = 0;
    Current_Time = Current_TimeMax;
    //input
    JOY_init();
    //camera
    INIT_posCamera();   
    //sprites
    SPR_init(0,0,0);
    INIT_posPlayer();
    INIT_IPI();
   ScreenInventaire = Create_inventaire(); <----------------------
    //background
    IND = TILE_USERINDEX;
    BG_TI[1] = IND;
    VDP_loadTileSet( &Tbgimg, IND, DMA );
    IND += Tbgimg.numTile;
    Map_level = MAP_create( &Mbgimg, BG_B, TILE_ATTR_FULL( PAL0, FALSE, FALSE, FALSE,BG_TI[1]));
    MAP_scrollTo( Map_level, Camera_posxToWorld, Camera_posyToWorld);
}
Initialized sprite

Code: Select all

 if(value & BUTTON_C)
   {
      DisplayInventaire();//initialise sprite "Curseur"
   }  
    if(value & BUTTON_A)
   {
      SPR_releaseSprite(ScreenInventaire->Curseur);//delete sprite " Curseur "<--------------------------
      VDP_clearPlane(WINDOW,1);
   } 
Display function

Code: Select all

void DisplayInventaire()
{
     //init Window
     VDP_setWindowAddress(0xD000); 
     VDP_setWindowHPos(1, 0);
     VDP_setWindowVPos(0, 0);
     
     BG_TI[2] = IND;//Tile index
     VDP_loadTileSet(MenuItems.tileset, IND, DMA);
     VDP_setTileMapEx(WINDOW, MenuItems.tilemap,TILE_ATTR_FULL(PAL1, TRUE, FALSE  
    FALSE,BG_TI[2]),5,5,0,0,30,18,CPU);
     //init_sprite
     ScreenInventaire->Curseur = SPR_addSprite(&Curs,128,80,TILE_ATTR(PAL1,1,FALSE,FALSE));<-----------------
}

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

Re: Some questions about SGDK

Post by Stef » Tue Feb 16, 2021 4:01 pm

When you release a sprite, SGDK will just mark it as released and so can give its VRAM / sprite space back to another sprite but it won't "erase" VRAM.
It's normal you always see the data in VRAM (if you're using VRAM viewer from emulator).
Also after SPR_release(..) you need to call SPR_update() to refresh sprites state so the sprite released will indeed be removed from screen.

izidor
Interested
Posts: 15
Joined: Tue Jan 26, 2021 12:20 pm

Re: Some questions about SGDK

Post by izidor » Tue Feb 16, 2021 7:40 pm

Thanks for the answer, it works !!

izidor
Interested
Posts: 15
Joined: Tue Jan 26, 2021 12:20 pm

Re: Some questions about SGDK

Post by izidor » Sat Feb 20, 2021 3:26 pm

How to erase the tiles of the vram of plan A or B?
VDP_clearPlane simply clear the screen, the tiles are still in vram.

I just want to delete the tileset from the vram that I no longer need to load the next level tileset.

If anyone can help me or give me hints.
thank you

Post Reply