Sprites III: Transparency (C & ASM with SDCC)

Pincha aquí para verlo en español

In this tutorial we will see how to paint a sprite with transparency over a background. For this we will use the graphics of arcade Bomberman (Dynablaster).'ll Use a background of the game and the main character (already retouched):

dyna

A little bigger:

dyna

and the background of the game:

dyna

As can be seen the main character's sprite, pink is the color we want to not paint (transparent color), to make the character fits into the background. We will convert the graphics with ConvImgCPC as we saw in previous tutorials. These are the values I used for the main character:

Since the sprite and background must share the same palette, we must check the colors in the program we want to keep fixed, before opening the background graphic. In this case the sprite uses 10 colors, so we mark the 10 checkboxes:

Then we opened the background and convert it, these are the values I used:

Once we have the two graphics exported in asm, are converted to c language as we have seen in other tutorials. Being in a similar way to this:

/*
;Généré par ConvImgCpc Version 0.16
; Mode 0
; 12x23
; Linear
*/

#define SPRITE_WIDTH 12
#define SPRITE_HEIGHT 23
#define NUM_COLORS 16
const unsigned char Palette[NUM_COLORS] = {8,0,26,15,24,6,20,14,11,1,10,12,25,9,13,19};


const char Sprite[] = 
{
               0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0xC0
        ,      0xC0, 0x00, 0x00, 0x00, 0x00, 0xC4, 0xC8, 0x00
        ,      0xC0, 0x84, 0x0C, 0x0C, 0x48, 0xC0, 0x00, 0x00
        ,      0x00, 0xC4, 0xC8, 0xC0, 0x0C, 0x0C, 0x0C, 0x0C
        ,      0x0C, 0x48, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0
        ,      0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xC0, 0x00
        ,      0x00, 0x00, 0x00, 0x84, 0x0C, 0x0C, 0x0C, 0x0C
        ,      0xCC, 0xCC, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x84
        ,      0x0C, 0x0C, 0x0C, 0x4C, 0x30, 0x90, 0x60, 0x00
        ,      0x00, 0x00, 0x00, 0x84, 0x0C, 0x0C, 0x0C, 0x4C
        ,      0x30, 0x90, 0x60, 0x00, 0x00, 0x00, 0x00, 0x84
        ,      0x0C, 0x0C, 0x0C, 0x4C, 0x30, 0x90, 0x60, 0x00
        ,      0x00, 0x00, 0x00, 0x84, 0x0C, 0x0C, 0x0C, 0x0C
        ,      0xCC, 0xCC, 0xC8, 0x00, 0x00, 0x00, 0x00, 0xC0
        ,      0x0C, 0x0C, 0xC0, 0xC0, 0x0C, 0xFC, 0xC0, 0x00
        ,      0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xAC, 0x48
        ,      0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
        ,      0xC1, 0x42, 0x0C, 0x0C, 0x94, 0x68, 0xC0, 0x00
        ,      0x00, 0x00, 0x00, 0x00, 0xC1, 0x42, 0x0C, 0x0C
        ,      0x94, 0x3C, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00
        ,      0xC0, 0xC0, 0xC0, 0xC0, 0xC4, 0x60, 0xC0, 0x00
        ,      0x00, 0x00, 0x00, 0x00, 0xC1, 0x42, 0xF0, 0xF0
        ,      0x94, 0x3C, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00
        ,      0xC0, 0xC0, 0xC0, 0xC0, 0x81, 0x42, 0x00, 0x00
        ,      0x00, 0x00, 0x00, 0x00, 0xC0, 0xD4, 0x0C, 0x0C
        ,      0xE8, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0
        ,      0xC0, 0xD4, 0x0C, 0x0C, 0x48, 0xC0, 0x00, 0x00
        ,      0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0
        ,      0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0xC0
        ,      0xC0, 0xD0, 0xF0, 0xF0, 0xF0, 0xC0, 0xC0, 0x00
        ,      0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0
        ,      0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0xC0
        ,      0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00
        ,      0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0
        ,      0xC0, 0xC0, 0x00, 0x00
};
/*
;Généré par ConvImgCpc Version 0.16
; Mode 0
; 80x200
; Linear
*/

const char Background[] = 
{
               0x9B, 0x31, 0x30, 0x33, 0x67, 0x33, 0x30, 0x32
        ,      0x32, 0x32, 0x33, 0x33, 0x31, 0x9B, 0x30, 0x32
        ,      0x32, 0x32, 0x33, 0x33, 0x31, 0x9B, 0x30, 0x32
        ,      0x32, 0x32, 0x33, 0x33, 0x31, 0x9B, 0x30, 0x32
        ,      0x32, 0x32, 0x33, 0x33, 0x31, 0x9B, 0x30, 0x32
        ,      0x32, 0x32, 0x33, 0x33, 0x31, 0x9B, 0x30, 0x32
        ,      0x32, 0x32, 0x33, 0x33, 0x31, 0x9B, 0x30, 0x32
        ,      0x32, 0x32, 0x33, 0x33, 0x31, 0x9B, 0x30, 0x32
        ,      0x32, 0x32, 0x33, 0x33, 0x31, 0x9B, 0x30, 0x32
        ,      0x32, 0x32, 0x33, 0x9B, 0x33, 0x30, 0x9B, 0x31
        ,      0x32, 0x33, 0x31, 0x32, 0x30, 0x65, 0x33, 0x33
        ,      0x30, 0x31, 0x9A, 0xCA, 0xB2, 0x32, 0x33, 0x33
        ,      0x30, 0x31, 0x9A, 0xCA, 0xB2, 0x32, 0x33, 0x33
        ,      0x30, 0x31, 0x9A, 0xCA, 0xB2, 0x32, 0x33, 0x33
        ,      0x30, 0x31, 0x9A, 0xCA, 0xB2, 0x32, 0x33, 0x33
        ,      0x30, 0x31, 0x9A, 0xCA, 0xB2, 0x32, 0x33, 0x33
        ,      0x30, 0x31, 0x9A, 0xCA, 0xB2, 0x32, 0x33, 0x33
        ,      0x30, 0x31, 0x9A, 0xCA, 0xB2, 0x32, 0x33, 0x33
        ,      0x30, 0x31, 0x9A, 0xCA, 0xB2, 0x32, 0x33, 0x33
        ,      0x30, 0x31, 0x9A, 0x30, 0x31, 0x32, 0x32, 0x32
        ,      0x31, 0x31, 0x33, 0x30, 0x9B, 0x30, 0x32, 0xCF

        ...
        
          ,      0x32, 0x33, 0x33, 0x33, 0x31, 0x9B, 0x31, 0x32
        ,      0x33, 0x33, 0x33, 0x33, 0x31, 0x9B, 0x31, 0x32
        ,      0x33, 0x33, 0x33, 0x33, 0x31, 0x9B, 0x30, 0x33
        ,      0x32, 0x33, 0x33, 0x33, 0x31, 0x9B, 0x31, 0x32
        ,      0x33, 0x33, 0x33, 0x33, 0x31, 0x9B, 0x30, 0x33
        ,      0x32, 0x33, 0x33, 0x91, 0x33, 0x65, 0x30, 0x32
};

If we apply what we have learned until now in other tutorials, would paint the background image and then paint over the sprite, moving and would be as follows:

////////////////////////////////////////////////////////////////////////
// sprite01.c
// Mochilote - www.cpcmania.com
////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Sprite.h"
#include "Background.h"

#define MAX_X 79

void SetColor(unsigned char nColorIndex, unsigned char nPaletteIndex)
{
  __asm
    ld a, 4 (ix)
    ld b, 5 (ix)
    ld c, b
    call #0xBC32 ;SCR SET INK
    __endasm;
}

void SetPalette(const unsigned char *pPalette)
{
  unsigned char nColor = 0;

  for(nColor = 0; nColor < NUM_COLORS; nColor++)
    SetColor(nColor, pPalette[nColor]);
}

void PutSpriteMode0(unsigned char *pAddress, unsigned char nWidth, unsigned char nHeight, unsigned char *pSprite)
{
  __asm
    LD L, 4(IX) 
    LD H, 5(IX) 
    LD C, 6(IX) 
    LD B, 7(IX)            
    LD E, 8(IX) 
    LD D, 9(IX) 

    _loop_alto:
       PUSH BC
       LD B,C
       PUSH HL
    _loop_ancho:
       LD A,(DE)
       LD (HL),A
       INC DE
       INC HL
       DJNZ _loop_ancho
       POP HL
       LD A,H
       ADD #0x08
       LD H,A
       SUB #0xC0
       JP NC, _sig_linea
       LD BC, #0xC050
       ADD HL,BC
    _sig_linea:
       POP BC
       DJNZ _loop_alto
  __endasm;
}


////////////////////////////////////////////////////////////////////////
unsigned char char1,char2,char3,char4;

unsigned int GetTime()
{
  unsigned int nTime = 0;

  __asm
    CALL #0xBD0D ;KL TIME PLEASE
    PUSH HL
    POP DE
    LD HL, #_char3
    LD (HL), D
    LD HL, #_char4
    LD (HL), E
  __endasm;

  nTime = (char3 << 8) + char4;

  return nTime;
}
////////////////////////////////////////////////////////////////////////

void main()
{
  unsigned char nSprite = 0;
  int nX = 20;
  int nY = 100;
  char nXDir = 1;
  unsigned int nLastMoveTime = GetTime();
  
  //SCR_SET_MODE 0
  __asm
    ld a, #0
    call #0xBC0E
  __endasm;

  //SCR SET BORDER 0
  __asm
    ld b, #0 ;black
    ld c, b
    call #0xBC38
  __endasm;
  
  SetPalette(Palette);

  PutSpriteMode0((unsigned char *)0xC000, 80, 200, Background);
  
  while(1)
  {
    if(GetTime() - nLastMoveTime < 15)
      continue;

    nLastMoveTime = GetTime();

    //move
    nX += nXDir;
      
    if(nX <= 0)
    {
      nX = 0;
      nXDir = 1;
    }
  
    if(nX >= (MAX_X - SPRITE_WIDTH))
    {
      nX = MAX_X - SPRITE_WIDTH;
      nXDir = -1;
    }
  
    //paint
    PutSpriteMode0((unsigned char *)(0xC000 + ((nY / 8u) * 80u) + ((nY % 8u) * 2048u) + nX), SPRITE_WIDTH, SPRITE_HEIGHT, Sprite);
  }
}
////////////////////////////////////////////////////////////////////////

The result would be:

 

 

To achieve transparency, we will make a new function to paint the sprite, based on the previous, but do not paint the pixels with color 0 (pink) to work transparency, the source code would look like:

////////////////////////////////////////////////////////////////////////
// sprite02.c
// Mochilote - www.cpcmania.com
////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Sprite.h"
#include "Background.h"

#define MAX_X 79

void SetColor(unsigned char nColorIndex, unsigned char nPaletteIndex)
{
  __asm
    ld a, 4 (ix)
    ld b, 5 (ix)
    ld c, b
    call #0xBC32 ;SCR SET INK
    __endasm;
}

void SetPalette(const unsigned char *pPalette)
{
  unsigned char nColor = 0;

  for(nColor = 0; nColor < NUM_COLORS; nColor++)
    SetColor(nColor, pPalette[nColor]);
}

void PutSpriteMode0(unsigned char *pAddress, unsigned char nWidth, unsigned char nHeight, unsigned char *pSprite)
{
  __asm
    LD L, 4(IX) 
    LD H, 5(IX) 
    LD C, 6(IX) 
    LD B, 7(IX)            
    LD E, 8(IX) 
    LD D, 9(IX) 

    _loop_alto:
       PUSH BC
       LD B,C
       PUSH HL
    _loop_ancho:
       LD A,(DE)
       LD (HL),A
       INC DE
       INC HL
       DJNZ _loop_ancho
       POP HL
       LD A,H
       ADD #0x08
       LD H,A
       SUB #0xC0
       JP NC, _sig_linea
       LD BC, #0xC050
       ADD HL,BC
    _sig_linea:
       POP BC
       DJNZ _loop_alto
  __endasm;
}

void PutSpriteMode0Trans(unsigned char *pAddress, unsigned char nWidth, unsigned char nHeight, unsigned char *pSprite)
{
  __asm
    LD L, 4(IX) 
    LD H, 5(IX) 
    LD C, 6(IX) 
    LD B, 7(IX)            
    LD E, 8(IX) 
    LD D, 9(IX) 

_loop_alto2:
    PUSH BC
    LD B,C
    PUSH HL
_loop_ancho2:
    LD A,(DE)
    CP #0
    JP Z, _notpaint
    LD (HL),A
_notpaint:
    INC DE
    INC HL
    DJNZ _loop_ancho2
    POP HL
    LD A,H
    ADD #0x08
    LD H,A
    SUB #0xC0
    JP NC, _sig_linea2
    LD BC, #0xC050
    ADD HL,BC
_sig_linea2:
    POP BC
    DJNZ _loop_alto2
    __endasm;
}

////////////////////////////////////////////////////////////////////////
unsigned char char1,char2,char3,char4;

unsigned int GetTime()
{
  unsigned int nTime = 0;

  __asm
    CALL #0xBD0D ;KL TIME PLEASE
    PUSH HL
    POP DE
    LD HL, #_char3
    LD (HL), D
    LD HL, #_char4
    LD (HL), E
  __endasm;

  nTime = (char3 << 8) + char4;

  return nTime;
}
////////////////////////////////////////////////////////////////////////

void main()
{
  unsigned char nSprite = 0;
  int nX = 20;
  int nY = 100;
  char nXDir = 1;
  unsigned int nLastMoveTime = GetTime();
  
  //SCR_SET_MODE 0
  __asm
    ld a, #0
    call #0xBC0E
  __endasm;

  //SCR SET BORDER 0
  __asm
    ld b, #0 ;black
    ld c, b
    call #0xBC38
  __endasm;
  
  SetPalette(Palette);

  PutSpriteMode0((unsigned char *)0xC000, 80, 200, Background);
  
  while(1)
  {
    if(GetTime() - nLastMoveTime < 15)
      continue;

    nLastMoveTime = GetTime();

    //move
    nX += nXDir;
      
    if(nX <= 0)
    {
      nX = 0;
      nXDir = 1;
    }
  
    if(nX >= (MAX_X - SPRITE_WIDTH))
    {
      nX = MAX_X - SPRITE_WIDTH;
      nXDir = -1;
    }
  
    //paint
    PutSpriteMode0Trans((unsigned char *)(0xC000 + ((nY / 8u) * 80u) + ((nY % 8u) * 2048u) + nX), SPRITE_WIDTH, SPRITE_HEIGHT, Sprite);
  }
}
////////////////////////////////////////////////////////////////////////

The result would be:

 

 

As can be seen the sprite leaves a trail behind, erasing the background ... Many would think that the easiest thing would always paint the entire background and then over the sprite, let's try it. The source code would look like:

////////////////////////////////////////////////////////////////////////
// sprite03.c
// Mochilote - www.cpcmania.com
////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Sprite.h"
#include "Background.h"

#define MAX_X 79

void SetColor(unsigned char nColorIndex, unsigned char nPaletteIndex)
{
  __asm
    ld a, 4 (ix)
    ld b, 5 (ix)
    ld c, b
    call #0xBC32 ;SCR SET INK
    __endasm;
}

void SetPalette(const unsigned char *pPalette)
{
  unsigned char nColor = 0;

  for(nColor = 0; nColor < NUM_COLORS; nColor++)
    SetColor(nColor, pPalette[nColor]);
}

void PutSpriteMode0(unsigned char *pAddress, unsigned char nWidth, unsigned char nHeight, unsigned char *pSprite)
{
  __asm
    LD L, 4(IX) 
    LD H, 5(IX) 
    LD C, 6(IX) 
    LD B, 7(IX)            
    LD E, 8(IX) 
    LD D, 9(IX) 

    _loop_alto:
       PUSH BC
       LD B,C
       PUSH HL
    _loop_ancho:
       LD A,(DE)
       LD (HL),A
       INC DE
       INC HL
       DJNZ _loop_ancho
       POP HL
       LD A,H
       ADD #0x08
       LD H,A
       SUB #0xC0
       JP NC, _sig_linea
       LD BC, #0xC050
       ADD HL,BC
    _sig_linea:
       POP BC
       DJNZ _loop_alto
  __endasm;
}

void PutSpriteMode0Trans(unsigned char *pAddress, unsigned char nWidth, unsigned char nHeight, unsigned char *pSprite)
{
  __asm
    LD L, 4(IX) 
    LD H, 5(IX) 
    LD C, 6(IX) 
    LD B, 7(IX)            
    LD E, 8(IX) 
    LD D, 9(IX) 

_loop_alto2:
    PUSH BC
    LD B,C
    PUSH HL
_loop_ancho2:
    LD A,(DE)
    CP #0
    JP Z, _notpaint
    LD (HL),A
_notpaint:
    INC DE
    INC HL
    DJNZ _loop_ancho2
    POP HL
    LD A,H
    ADD #0x08
    LD H,A
    SUB #0xC0
    JP NC, _sig_linea2
    LD BC, #0xC050
    ADD HL,BC
_sig_linea2:
    POP BC
    DJNZ _loop_alto2
    __endasm;
}

////////////////////////////////////////////////////////////////////////
unsigned char char1,char2,char3,char4;

unsigned int GetTime()
{
  unsigned int nTime = 0;

  __asm
    CALL #0xBD0D ;KL TIME PLEASE
    PUSH HL
    POP DE
    LD HL, #_char3
    LD (HL), D
    LD HL, #_char4
    LD (HL), E
  __endasm;

  nTime = (char3 << 8) + char4;

  return nTime;
}
////////////////////////////////////////////////////////////////////////

void main()
{
  unsigned char nSprite = 0;
  int nX = 20;
  int nY = 100;
  char nXDir = 1;
  unsigned int nLastMoveTime = GetTime();
  
  //SCR_SET_MODE 0
  __asm
    ld a, #0
    call #0xBC0E
  __endasm;

  //SCR SET BORDER 0
  __asm
    ld b, #0 ;black
    ld c, b
    call #0xBC38
  __endasm;
  
  SetPalette(Palette);

  PutSpriteMode0((unsigned char *)0xC000, 80, 200, Background);
  
  while(1)
  {
    if(GetTime() - nLastMoveTime < 15)
      continue;

    nLastMoveTime = GetTime();

    //move
    nX += nXDir;
      
    if(nX <= 0)
    {
      nX = 0;
      nXDir = 1;
    }
  
    if(nX >= (MAX_X - SPRITE_WIDTH))
    {
      nX = MAX_X - SPRITE_WIDTH;
      nXDir = -1;
    }
  
    //paint
    PutSpriteMode0((unsigned char *)0xC000, 80, 200, Background);
    PutSpriteMode0Trans((unsigned char *)(0xC000 + ((nY / 8u) * 80u) + ((nY % 8u) * 2048u) + nX), SPRITE_WIDTH, SPRITE_HEIGHT, Sprite);
  }
}
////////////////////////////////////////////////////////////////////////

The result would be:

 

 

As can be seen this method, besides being very slow, causing a big flicker. As we are working directly on the video memory is impossible to avoid flicker using this method. To solve the flicker and not have to paint the entire background every time we try to use a double buffer, but only of the size of sprite, not full screen. What we do is dump the background piece on double buffering, paint over the sprite transparently and finally dump the double buffer on the screen. In this case I used a mixture of methods in C and Asm, very simple, perfectly illustrating the method used. The complete source code would be as follows:

////////////////////////////////////////////////////////////////////////
// sprite04.c
// Mochilote - www.cpcmania.com
////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Sprite.h"
#include "Background.h"

#define MAX_X 79

const char SpriteBuffer[SPRITE_WIDTH * SPRITE_HEIGHT] = {0};

void SetColor(unsigned char nColorIndex, unsigned char nPaletteIndex)
{
  __asm
    ld a, 4 (ix)
    ld b, 5 (ix)
    ld c, b
    call #0xBC32 ;SCR SET INK
    __endasm;
}

void SetPalette(const unsigned char *pPalette)
{
  unsigned char nColor = 0;

  for(nColor = 0; nColor < NUM_COLORS; nColor++)
    SetColor(nColor, pPalette[nColor]);
}

void PutSpriteMode0(unsigned char *pAddress, unsigned char nWidth, unsigned char nHeight, unsigned char *pSprite)
{
  __asm
    LD L, 4(IX) 
    LD H, 5(IX) 
    LD C, 6(IX) 
    LD B, 7(IX)            
    LD E, 8(IX) 
    LD D, 9(IX) 

    _loop_alto:
       PUSH BC
       LD B,C
       PUSH HL
    _loop_ancho:
       LD A,(DE)
       LD (HL),A
       INC DE
       INC HL
       DJNZ _loop_ancho
       POP HL
       LD A,H
       ADD #0x08
       LD H,A
       SUB #0xC0
       JP NC, _sig_linea
       LD BC, #0xC050
       ADD HL,BC
    _sig_linea:
       POP BC
       DJNZ _loop_alto
  __endasm;
}

void PutSpriteLinealTrans(unsigned char *pAddress, unsigned char *pSprite, unsigned int nBytes)
{
  __asm
    LD L, 4(IX) 
    LD H, 5(IX) 
    LD E, 6(IX) 
    LD D, 7(IX)            
    LD C, 8(IX) 
    LD B, 9(IX) 

_loop:
    LD A,(DE)
    CP #0
    JP Z, _notpaint
    LD (HL),A
_notpaint:
    INC DE
    INC HL
    DEC BC
    LD A, #0
    ADD A, B
    ADD A, C
    JP NZ, _loop
    __endasm;
}

////////////////////////////////////////////////////////////////////////
unsigned char char1,char2,char3,char4;

unsigned int GetTime()
{
  unsigned int nTime = 0;

  __asm
    CALL #0xBD0D ;KL TIME PLEASE
    PUSH HL
    POP DE
    LD HL, #_char3
    LD (HL), D
    LD HL, #_char4
    LD (HL), E
  __endasm;

  nTime = (char3 << 8) + char4;

  return nTime;
}
////////////////////////////////////////////////////////////////////////

void main()
{
  unsigned char nSprite = 0;
  int nX = 20;
  int nY = 100;
  char nXDir = 1;
  unsigned int nLastMoveTime = GetTime();
  int nAux = 0;
  
  //SCR_SET_MODE 0
  __asm
    ld a, #0
    call #0xBC0E
  __endasm;

  //SCR SET BORDER 0
  __asm
    ld b, #0 ;black
    ld c, b
    call #0xBC38
  __endasm;
  
  SetPalette(Palette);

  PutSpriteMode0((unsigned char *)0xC000, 80, 200, Background);
  
  while(1)
  {
    if(GetTime() - nLastMoveTime < 10)
      continue;

    nLastMoveTime = GetTime();

    //move
    nX += nXDir;
      
    if(nX <= 0)
    {
      nX = 0;
      nXDir = 1;
    }
  
    if(nX >= (MAX_X - SPRITE_WIDTH))
    {
      nX = MAX_X - SPRITE_WIDTH;
      nXDir = -1;
    }
  
    //copy background to sprite double buffer
    for(nAux = 0; nAux < SPRITE_HEIGHT; nAux++)
      memcpy(SpriteBuffer + nAux * SPRITE_WIDTH, Background + 80 * (nY + nAux) + nX, SPRITE_WIDTH);
    
    //paint sprite to double buffer with transparency
    PutSpriteLinealTrans(SpriteBuffer, Sprite, SPRITE_WIDTH * SPRITE_HEIGHT);

    //paint the result to screen
    PutSpriteMode0((unsigned char *)(0xC000 + ((nY / 8u) * 80u) + ((nY % 8u) * 2048u) + nX), SPRITE_WIDTH, SPRITE_HEIGHT, SpriteBuffer);
  }
}
////////////////////////////////////////////////////////////////////////

The result would be:

 

As we see, this time if it looks good, avoiding unnecessary flicker.

You could download a zip with all files (source code, bat to compile, binary and dsk's) here: Sprites_III.zip

 

www.CPCMania.com 2012