FAQ  •  Register  •  Login

Fourspriter: Sprite Engine from the Mojon Twins

<<

apenao

Posts: 45

Joined: Tue Feb 09, 2010 10:08 pm

Post Mon Mar 01, 2010 9:10 pm

Fourspriter: Sprite Engine from the Mojon Twins

As I promissed, here I am with an adaptation for the Mojon Twins "Fourspriter". Well, in fact I promissed just the opposite (skip this one and post the other sprite routine I'm working in), but I think this one is more suited to a basic enviroment and the other one is just great for a crap game (see my game Colour Clash of the Titans in the CSSCGC 2010 thread within the WoS games forum) but not so good if you plan to do a polished game.

The engine itself comes in assembler, and all you have to do is POKE the right adresses to configure and move your sprites (up to 4). All I have done is adding 3 subroutines to make easier the poking part, and 4 labes so you can call the different subroutines of the engine via gosub.

Here goes the code you have to include in your library folder (I called it fourspriter.bas):

  Code:
SUB fsprite (n as uByte, a as uByte, b as uByte, c as uByte, d as uByte)  'Initialite Sprite: n (sprite number 0-3);a,b,c,d (UDG number 0-20,99 means the sprite won't be printed)
POKE @fourspriter+48*n,a
POKE @fourspriter+1+48*n,b
POKE @fourspriter+2+48*n,c
POKE @fourspriter+3+48*n,d
END sub

SUB fspritecoord (n as uByte, x as uByte, y as uByte)   'Set sprite coords: n (sprite number);x,y (vertical,horizontal coords)
POKE @fourspriter+4+48*n,x
POKE @fourspriter+5+48*n,y
POKE @fourspriter+6+48*n,x
POKE @fourspriter+7+48*n,y
END SUB

SUB fspriteattr (n as uByte, attra as uByte, attrb as uByte, attrc as uByte, attrd as uByte) 'Set sprite attrs: n (sprite number);a,b,c,d (UDG attrs)
POKE @fourspriter+40+48*n,attra
POKE @fourspriter+41+48*n,attrb
POKE @fourspriter+42+48*n,attrc
POKE @fourspriter+43+48*n,attrd
END SUB


fourspriter:
ASM

;; 16x16 Sprites moving a character each frame

;; Copyleft 2009 The Mojon Twins.
;; Pergreñado por na_th_an

;; Uses UDGs (it reads the address from the system variables).

;; It moves up to 4 sprites, preserving the backgrounds.



datap:                        ; each block is 40 bytes long.

;; Sprite 1

udgs1:      defb   0, 0, 0, 0      ; Four UDGs of the first sprite.
x_pos1:      defb   0            ; X position in chars.
y_pos1:      defb   0            ; Y position in chars.
cx_pos1:   defb   0            ; Previous X position in chars.
cy_pos1:   defb    0            ; Previous Y position in chars.
buffer1:   defb   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0         ; Gfx buffer.
attrs1:      defb   7, 7, 7, 7      ; Sprite ATTRs
buffatrs1:   defb   0,0,0, 0         ; Attr's buffer

;; Sprite 2

udgs2:      defb   0, 0, 0, 0      ;
x_pos2:      defb   0            ;
y_pos2:      defb   0            ;
cx_pos2:   defb   0            ;
cy_pos2:   defb    0            ;
buffer2:   defb   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0         ;
attrs2:      defb   7, 7, 7, 7      ;
buffatrs2:   defb   0,0,0, 0         ;

;; Sprite 3

udgs3:      defb   0, 0, 0, 0      ;
x_pos3:      defb   0            ;
y_pos3:      defb   0            ;
cx_pos3:   defb   0            ;
cy_pos3:   defb    0            ;
buffer3:   defb   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0         ;
attrs3:      defb   7, 7, 7, 7      ;
buffatrs3:   defb   0,0,0, 0         ;

;; Sprite 4

udgs4:      defb   0, 0, 0, 0      ;
x_pos4:      defb   0            ;
y_pos4:      defb   0            ;
cx_pos4:   defb   0            ;
cy_pos4:   defb    0            ;
buffer4:   defb   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0         ;
attrs4:      defb   7, 7, 7, 7      ;
buffatrs4:   defb   0,0,0, 0         ;

;; General use coordinates

xpos:      defb    0
ypos:      defb    0
cxpos:      defb   0
cypos:      defb    0

;; Sprite control is done writing a certain number
;; in the Sprite's first UDG
;; If the first UDG is 99, it won't be printed

;;
;; Routine to save the background to the buffer
end asm
initsprites:
asm
init_sprites:                  

; pointer = datap
; for (i = 0; i < 4; i ++) {
;    X = *(pointer + 4);                           // A
;    Y = *(pointer + 5);
;    scr_address = get_scr_address (X, Y);               // B
;    for (j = 0; j < 8; j ++) {
;       *(pointer + 8 + j) = *scraddress;
;       scraddress += 256;
;    }
;    scr_address = get_scr_address (X+1, Y);            // C
;    for (j = 0; j < 8; j ++) {
;       *(pointer + 16 + j) = *scraddress;
;       scraddress += 256;
;    }
;    scr_address = get_scr_address (X, Y+1);            // D
;    for (j = 0; j < 8; j ++) {
;       *(pointer + 24 + j) = *scraddress;
;       scraddress += 256;
;    }
;    scr_address = get_scr_address (X+1, Y+1);            // E
;    for (j = 0; j < 8; j ++) {
;       *(pointer + 32 + j) = *scraddress;
;       scraddress += 256;
;    }
;    pointer = pointer + 40;
; }

         ld       de, datap      ;

         ld      b,   4         ;
i4chars:   push   bc
         
         ;;
         ld      a,   (de)
         cp      99
         jr      z,   nxt1

         ;; A

         inc      de
         inc      de
         inc      de
         inc      de

         ;
         ld      a,   (de)
         ld      hl,   xpos
         ld      (hl), a
         
         inc    de
         
         ;
         ld      a,   (de)
         ld      hl, ypos
         ld      (hl), a
         
         inc    de
         inc    de
         inc    de
         
         ;; B
         
         ;
         call   copia_char
         
         ; xpos++
         ld      hl, xpos
         inc      (hl)
         
         ;; C
         
         ;
         call    copia_char

         ; xpos --
         ld      hl, xpos
         ld      a, (hl)
         dec      a
         ld      (hl), a
         
         ; ypos ++
         ld      hl, ypos
         inc      (hl)
         
         ;; D
         
         ;
         call    copia_char

         ; xpos++
         ld      hl, xpos
         inc      (hl)
         
         ;; E
         
         ;
         call   copia_char
         

         ;; Now we point to the ATTR buffer,adding 4:
         inc      de
         inc      de
         inc      de
         inc      de
         
         ;;
         
         ; xpos --
         ld      hl, xpos
         ld      a, (hl)
         dec      a
         ld      (hl), a
         
         ; ypos --
         ld      hl, ypos
         ld      a, (hl)
         dec      a
         ld      (hl), a
               
         ;
         call   get_attr_address
         
         ;
         ld      l,    c
         ld      h,    b
         ld      bc, 31
         ld      a,   (hl)
         ld      (de), a         ; Primer carácter
         inc      hl
         inc      de
         ld      a,    (hl)   
         ld      (de), a         ; Segundo carácter
         add      hl,   bc
         inc      de
         ld      a,   (hl)
         ld      (de), a         ; Tercer carácter
         inc      hl
         inc      de
         ld      a,    (hl)
         ld      (de), a         ; Cuarto carácter
         inc      de            

         ; Fin del bucle
         
nxt1:      pop      bc
         djnz    i4chars
         
         ret
         
copia_char:
         call   get_scr_address   ;
         ld      l,    c
         ld      h,    b         ;
         
         ld      a,   (hl)
         ld      (de), a
         inc      h
         inc      de
         ld      a,   (hl)
         ld      (de), a
         inc      h
         inc      de
         ld      a,   (hl)
         ld      (de), a
         inc      h
         inc      de
         ld      a,   (hl)
         ld      (de), a
         inc      h
         inc      de
         ld      a,   (hl)
         ld      (de), a
         inc      h
         inc      de
         ld      a,   (hl)
         ld      (de), a
         inc      h
         inc      de
         ld      a,   (hl)
         ld      (de), a
         inc      h
         inc      de
         ld      a,   (hl)
         ld      (de), a
         inc      h
         inc      de
         
         ret
         
;; Routine to move the sprites:

end asm
updatesprite:
asm
update_sprites:
   halt
   
   call borra_sprites            ; Erase the sprites
   call init_sprites               ; Save background
   call draw_sprites            ; print sprites
   call update_coordinates         ; update coordinates :)
   
   ret

;; Routine to erase the sprites:
end asm
borrasprites:
asm
borra_sprites:

; pointer = datap
; for (i = 0; i < 4; i ++) {
;    CX = *(pointer + 6)
;    CY = *(pointer + 7)
;    scr_address = get_scr_address (CX, CY);
;    for (j = 0; j < 8; j ++) {
;       *scr_address = *(pointer + 8 + j);
;      scr_address += 256;
;    }
;    scr_address = get_scr_address (CX+1, CY);
;    for (j = 0; j < 8; j ++) {
;       *scr_address = *(pointer + 16 + j);
;      scr_address += 256;
;    }
;    scr_address = get_scr_address (CX, CY+1);
;    for (j = 0; j < 8; j ++) {
;       *scr_address = *(pointer + 24 + j);
;      scr_address += 256;
;    }
;    scr_address = get_scr_address (CX+1, CY+1);
;    for (j = 0; j < 8; j ++) {
;       *scr_address = *(pointer + 32 + j);
;      scr_address += 256;
;    }
;    pointer += 40;
; }

         ld       de, datap      ;
         ld      b,   4         ;
i4chars2:   push   bc
         
         ;;
         ld      a,   (de)
         cp      99
         jr      z,   nxt2

         ;; A

         inc      de
         inc      de
         inc      de
         inc      de
         inc      de
         inc      de
         
         ; Obtenemos xpos = CX
         ld      a,   (de)
         ld      hl,   xpos
         ld      (hl), a
         
         inc    de
         
         ; Obtenemos ypos = CY
         ld      a,   (de)
         ld      hl, ypos
         ld      (hl), a
         
         inc    de
         
         ;; B
         
         ; Pintamos el primer char
         call   borra_char
                  
         ; xpos++
         ld      hl, xpos
         inc      (hl)
         
         ;; C
         
         ; Pintamos el segundo char
         call   borra_char

         ; xpos --
         ld      hl, xpos
         ld      a, (hl)
         dec      a
         ld      (hl), a
         
         ; ypos ++
         ld      hl, ypos
         inc      (hl)
         
         ;; D
         
         ; Pintamos el tercer char
         call    borra_char

         ; xpos++
         ld      hl, xpos
         inc      (hl)
         
         ;; E

         ; Pintamos el cuarto char
         call   borra_char
         
         ;; attr
         inc      de
         inc      de
         inc      de
         inc      de
         
         ;;
         
         ; xpos --
         ld      hl, xpos
         ld      a, (hl)
         dec      a
         ld      (hl), a
         
         ; ypos --
         ld      hl, ypos
         ld      a, (hl)
         dec      a
         ld      (hl), a
               
         ;
         call   get_attr_address
         
         ;
         call   copyattrs
         
         ;
         
nxt2:      pop      bc
         djnz    i4chars2         
      
         ret

borra_char:            
         call   get_scr_address   ;
         ld      l,    c
         ld      h,    b         ;
         
         ld      a,   (de)
         ld      (hl), a
         inc      h
         inc      de
         ld      a,   (de)
         ld      (hl), a
         inc      h
         inc      de
         ld      a,   (de)
         ld      (hl), a
         inc      h
         inc      de
         ld      a,   (de)
         ld      (hl), a
         inc      h
         inc      de
         ld      a,   (de)
         ld      (hl), a
         inc      h
         inc      de
         ld      a,   (de)
         ld      (hl), a
         inc      h
         inc      de
         ld      a,   (de)
         ld      (hl), a
         inc      h
         inc      de
         ld      a,   (de)
         ld      (hl), a
         inc      h
         inc      de
         
         ret

         
;; Print sprites routine

;; UDGs are labeled from  0 to 21. The addres of the UDG is:

;; *(23675) + 256 * *(23676) + 8 * N
         
bufchars:   defb   0,0,0, 0      ;
end asm
drawsprites:
asm
draw_sprites:

         ld       de, datap      ;

         ld      b,   4         ;
i4chars3:   push   bc

         ;;
         ld      a,   (de)
         cp      99
         jr      z,   nxt3

         ;; copiar aquí "de" a un buffer

         call   charsabuff
         
         ; Obtenemos xpos
         ld      a,   (de)
         ld      hl,   xpos
         ld      (hl), a
         
         inc    de
         
         ; Obtenemos ypos
         ld      a,   (de)
         ld      hl, ypos
         ld      (hl), a
         
         inc    de
         inc    de
         inc    de
         
         push    de
         
         ;;
         
         ld      hl, bufchars
         call   getde
         
         ;;
         call   docopy

         ; xpos++
         ld      hl, xpos
         inc      (hl)
         
         ; Dirección del gráfico
         
         ld      hl, bufchars
         inc      hl
         call   getde
         
         ; Pintamos el segundo char
         call   docopy
         
         ; xpos--
         ld      hl, xpos
         ld      a, (hl)
         dec      a
         ld      (hl), a
         
         ; ypos ++
         ld      hl, ypos
         inc      (hl)
         
         ; Dirección del gráfico
         
         ld      hl, bufchars
         inc      hl
         inc      hl
         call   getde
      
         ; Pintamos el tercer char
         call   docopy
         
         ; xpos ++
         ld      hl, xpos
         inc      (hl)
         
         ; Dirección del gráfico
         
         ld      hl, bufchars
         inc      hl
         inc      hl
         inc      hl
         call    getde
         
         ; Pintamos el cuarto char
         call   docopy
                     
         pop      de
         
         ; de = de + 32
         ld      bc, 32
         ld      h, d
         ld      l, e
         add      hl, bc
         ld      d, h
         ld      e, l
         
         ;; attr
         
         ; xpos --
         ld      hl, xpos
         ld      a, (hl)
         dec      a
         ld      (hl), a
         
         ; ypos --
         ld      hl, ypos
         ld      a, (hl)
         dec      a
         ld      (hl), a
               
         ;
         call   get_attr_address
         
         ;
         call   copyattrs
         
         inc      de
         inc      de
         inc      de
         inc      de            ;
         
nxt3:      pop      bc
         djnz    i4chars3
         
         ret

charsabuff: ld      hl,   bufchars
         ld      a, (de)
         ld      (hl), a
         inc      de
         inc      hl
         ld      a, (de)
         ld      (hl), a
         inc      de
         inc      hl
         ld      a, (de)
         ld      (hl), a
         inc      de
         inc      hl
         ld      a, (de)
         ld      (hl), a
         inc      de
         inc      hl
         ret
                  
copyattrs:   ld      l,    c
         ld      h,    b
         ld      bc, 31
         ld      a,   (de)
         ld      (hl), a         ; Primer carácter
         inc      hl
         inc      de            
         ld      a,    (de)   
         ld      (hl), a         ; Segundo carácter
         add      hl,   bc
         inc      de
         ld      a,   (de)
         ld      (hl), a         ; Tercer carácter
         inc      hl
         inc      de
         ld      a,    (de)
         ld      (hl), a         ; Cuarto carácter
         inc      de            ; Ahora de apunta a datap+48, o sea, al siguiente sprite.
         ret
end asm
updatecoordinates:
asm
update_coordinates:
         ld       de, datap      ; Apuntamos a la zona de datos
         ld      hl, datap      ; idem

         ld      b,   4         ; 4 iteraciones
i4chars4:   push   bc

         ;; Para cada sprite hay que hacer:
         ;; *(datap + 6) = *(datap + 4)
         ;; *(datap + 7) = *(datap + 5)
         
         inc      de
         inc      de
         inc      de
         inc      de
         ld      a, (de)         ; a = X
         inc      hl
         inc      hl
         inc    hl
         inc      hl
         inc      hl
         inc      hl
         ld      (hl), a         ; CX = a
         
         inc    de
         ld      a, (de)         ; a = Y
         inc    hl
         ld      (hl), a         ; CY = a

         inc      hl
         
         ;; hl = hl + 40
         ld      bc, 40
         add      hl, bc
         
         ;; de = hl
         ld      d, h
         ld      e, l
         
         pop      bc
         djnz    i4chars4
         ret
         
;; Esta función calcula la posición en memoria del UDG apuntado por
;; el número que está en la dirección hl.
         
getde:      ld      a, (hl)
         ld      d, a
         ld      hl, 23676
         ld      a, (hl)
         ld      e, a
         ld      hl, 23675
         ld      a, (hl)
         ld      l, a
         ld      a, e
         ld      h, a
         ;;      HL = *(23675) + 256 * *(23676)
         ld      a, d
         rlca
         rlca
         rlca   ; a = N * 8
         ld      d, 0
         ld      e, a
         add      hl, de
         ld      d, h
         ld      e, l
         ret

docopy:      
         call   get_scr_address   ; Dirección (xpos, ypos) en BC
         ld      l,    c
         ld      h,    b         ; Dirección (xpos, ypos) en HL         
         
         ld      a,   (de)
         ld      (hl), a
         inc      h
         inc      de
         ld      a,   (de)
         ld      (hl), a
         inc      h
         inc      de
         ld      a,   (de)
         ld      (hl), a
         inc      h
         inc      de
         ld      a,   (de)
         ld      (hl), a
         inc      h
         inc      de
         ld      a,   (de)
         ld      (hl), a
         inc      h
         inc      de
         ld      a,   (de)
         ld      (hl), a
         inc      h
         inc      de
         ld      a,   (de)
         ld      (hl), a
         inc      h
         inc      de
         ld      a,   (de)
         ld      (hl), a
         inc      h
         inc      de
         
         ret
         
;; Esta función devuelve en bc la dirección de memoria
;; de la posición (xpos, ypos) en carácteres. Extraído de código
;; por BloodBaz.

get_scr_address:
         push    de
         ld       a,   (xpos)
         and      31
         ld      c,   a
         ld      a,   (ypos)
         ld      d,   a
         and      24
         add      a,   64
         ld      b,    a
         ld      a,   d
         and      7
         rrca
         rrca
         rrca
         or      c
         ld      c,    a
         pop      de
         ret
               
;; Esta función devuelve en bc la dirección de memoria
;; de la posición (xpos, ypos) dentro del archivo de atributos.
;; Adaptado de código por Jonathan Cauldwell.

;; 010110YY YYYXXXXX

get_attr_address:
         
         ld      a,    (ypos)      ; Cogemos y
         rrca
         rrca
         rrca               ; La multiplicamos por 32
         ld      c,   a         ; nos lo guardamos en c
         and      3            ; ponemos una mascarita 00000011
         add      a,   88         ; 88 * 256 = 22528, aquí empieza el tema
         ld      b,   a         ; Hecho el bite superior.
         ld      a,   c         ; Nos volvemos a traer y * 32
         and      224            ; Mascarita 11100000
         ld      c,   a         ; Lo volvemos a poner en c
         ld      a,   (xpos)      ; Cogemos x
         add      a,    c         ; Le sumamos lo que teníamos antes.
         ld      c,   a         ; Listo. Ya tenemos en BC la dirección.
         
         ret
         
spare:      defb   85,85,85,85,85,85,85, 85
end asm


The subroutines are the following:

1) Define your sprites:

fsprite (n,a,b,c,d) ; where n is the sprite number (0 to 3) and a-d are the UDGs number that compose the sprite (0-21)

2) Set the atributes for each of the sprite's UDG:

fspriteattr (n,a,b,c,d) ; n=sprite number ; a-d=attr of each UDG

3) Set the initial coords for your spries:
fspritecoord (n,y,x) ; n= sprite number ; y=vertical coord ; x=horizontal coord

The labels to be called via gosub are:

borrasprites ; this will erase the sprites, restoring the background.

initsprites ; this will select wether a sprite will be printed or not. If you don't want a sprite to be printed, you have to poke 99 into the first value of the sprite udg (i.e. fsprite (1,99,0,0,0) won't print sprite 1)

drawsprites ; this will draw the sprites on the screen

updatecoordinates ; this will update the current coordinates of each sprite, while storing the old ones so you can restore the background.
Last edited by apenao on Mon Mar 01, 2010 9:15 pm, edited 1 time in total.
<<

apenao

Posts: 45

Joined: Tue Feb 09, 2010 10:08 pm

Post Mon Mar 01, 2010 9:11 pm

Re: Fourspriter: Sprite Engine from the Mojon Twins

Here goes a small example to see it working. It's really fast :)

  Code:
#include <sinclair.bas>
#include <memcopy.bas>
#include <keys.bas>


100 DIM gentle (0 to 3,0 to 7) AS uByte => {  { 15, 15, 15, 15, 15, 15, 13, 15} , _
     { 240, 144, 208, 208, 240, 240, 176, 240} , _
     { 15, 14, 63, 0, 0, 12, 26, 30} , _
     { 176, 112, 252, 0, 0, 48, 104, 120}}

110 POKE Uinteger 23675, @gentle(0,0)


    memcopy (0,16384,4092)
    LET gx=10:LET gy=10:let dx=3:let dy=3:let tx=6:let ty=6:let cx=18:let cy=18
    let dmx=1:let dmy=1:let tmx=-1:let tmy=-1:let cmx=1:let cmy=-1
    fsprite (0,0,1,2,3)
    fspritecoord (0,gy,gx)
    fsprite (1,0,1,2,3)
    fspritecoord (1,dy,dx)
    fsprite (2,0,1,2,3)
    fspritecoord (2,ty,tx)
    fsprite (3,0,1,2,3)
    fspritecoord (3,cy,cx)
    fspriteattr (0,31,31,31,31)
    fspriteattr (1,12,12,12,12)
    fspriteattr (2,26,26,26,26)
    fspriteattr (3,6,6,6,6)
 gosub   initsprites
 gosub drawsprites
 gosub updatecoordinates

bucle:

    IF MULTIKEYS(KEYO)<>0 and gx>0 THEN LET gx=gx-1: END IF
    IF MULTIKEYS(KEYP)<>0 and gx<30 THEN LET gx=gx+1:END IF
    IF MULTIKEYS(KEYQ)<>0 and gy>0 THEN LET gy=gy-1 :END IF
    IF MULTIKEYS(KEYA)<>0 and gy<22 THEN LET gy=gy+1: END IF


    let dx=dx+dmx:if dx=0 or dx=30 then let dmx=-dmx : END IF
    let dy=dy+dmy:if dy=0 or dy=22 then let dmy=-dmy: END IF
    let tx=tx+tmx:if tx=0 or tx=30 then let tmx=-tmx: END IF
    let ty=ty+tmy:if ty=0 or ty=22 then let tmy=-tmy: END IF
    let cx=cx+cmx:if cx=0 or cx=30 then let cmx=-cmx: END IF
    let cy=cy+cmy:if cy=0 or cy=22 then let cmy=-cmy: END IF
pause 2
 gosub borrasprites
    fspritecoord (0,gx,gy)
    fspritecoord (1,dx,dy)
    fspritecoord (2,tx,ty)
    fspritecoord (3,cx,cy)
 gosub   initsprites
 gosub drawsprites
 gosub updatecoordinates

goto bucle

end
#include <fourspriter.bas>
<<

britlion

Posts: 679

Joined: Mon Apr 27, 2009 7:26 pm

Location: Slough, Berkshire, UK

Post Tue Mar 02, 2010 5:25 pm

Re: Fourspriter: Sprite Engine from the Mojon Twins

Nice.

I'd downloaded this and was playing with translating it just yesterday :-)

Seems you beat me to it.

Personally, I probably would have sneaked a few more options into the pile - like a function to return ATTR values, based on ink/paper/bright/flash - because this is really meant for inexperienced programmers, and if we can insulate them from awkward stuff that can't hurt.

Also, when reading their code, I noticed a few times they could have written the code a little tighter, and I was itching to change the assembler. *heh* I'd probably save only a handful of T states *chuckle* So probably not much in the way of worth it though.

Things like:

  Code:
ld      hl, xpos
ld      a, (hl)
dec      a
ld      (hl), a

is 28 T states.

I think
  Code:
ld      hl, xpos
dec (hl)

at 21 T states Would be tighter.

Oddly, they use the latter method for increasing a variable.
<<

apenao

Posts: 45

Joined: Tue Feb 09, 2010 10:08 pm

Post Tue Mar 02, 2010 6:20 pm

Re: Fourspriter: Sprite Engine from the Mojon Twins

You're right about the ATTR values, I didn't think of that :)

I also noticed there are repeated pieces of code in the routine, but my assembler knowledge isn't so high right now so if I dare to change it, I'll probably break something else. But if you want to do it and you have the time, go on :)
<<

britlion

Posts: 679

Joined: Mon Apr 27, 2009 7:26 pm

Location: Slough, Berkshire, UK

Post Tue Mar 02, 2010 6:58 pm

Re: Fourspriter: Sprite Engine from the Mojon Twins

I think your example is a little confusing, apenao.

It has lines like "gosub updatesprites" and I can't see where that code is...


wouldn't that be a SUB as part of the sprite library? So when you want to update the screen, do fspriteUpdate()
<<

boriel

Site Admin

Posts: 1147

Joined: Wed Nov 01, 2006 6:18 pm

Location: Santa Cruz de Tenerife, Spain

Post Tue Mar 02, 2010 7:17 pm

Re: Fourspriter: Sprite Engine from the Mojon Twins

apenao wrote:You're right about the ATTR values, I didn't think of that :)

I also noticed there are repeated pieces of code in the routine, but my assembler knowledge isn't so high right now so if I dare to change it, I'll probably break something else. But if you want to do it and you have the time, go on :)

Amazing work!! :o
I'm fixing compiler bugs at the moment. Once I release 1.2.5, if you like, I can add this library to the /library directory (they will preserve your name authoring), as I will do with Britlion's math f16 library
<<

apenao

Posts: 45

Joined: Tue Feb 09, 2010 10:08 pm

Post Tue Mar 02, 2010 9:20 pm

Re: Fourspriter: Sprite Engine from the Mojon Twins

britlion wrote:I think your example is a little confusing, apenao.

It has lines like "gosub updatesprites" and I can't see where that code is...


wouldn't that be a SUB as part of the sprite library? So when you want to update the screen, do fspriteUpdate()


That GOSUBs do jump to the sprite library, not to the actual example code, but as the library has to be included when compiling, it's the same as if you do it as a subroutine. But if you think it's confusing or find a way to do something better, please do it so when Boriel finally add this to the library it will be optimized :)

To Boriel: Please add the library if you want, but the authoring must go to the Mojon Twins (or Nathan in this particular case, because he did the code I believe). All I did was add a couple of labels and subroutines.
<<

britlion

Posts: 679

Joined: Mon Apr 27, 2009 7:26 pm

Location: Slough, Berkshire, UK

Post Wed Mar 03, 2010 3:12 pm

Re: Fourspriter: Sprite Engine from the Mojon Twins

Aha. I hadn't noticed the end asm label: asm hops.

Incidentally, when including asm code, you have to make sure it doesn't run automatically - one easy way to do that is to include it in a sub or a function:

  Code:
FUNCTION  thingy (a as ubyte)
stuff
stuff
return value

asm
assembly
end asm
end function


I've found that includes code in a decent library fashion, but it can't run - it's after the return.


As for how to do it - your way works just fine! I'd show you what I meant, in terms of how I'd put it together, but I'm snowed under with projects right now. Perhaps in a few days. There's nothing wrong with how you did it though - I'm just from the extensible language school of thought :-)
<<

apenao

Posts: 45

Joined: Tue Feb 09, 2010 10:08 pm

Post Wed Mar 03, 2010 9:45 pm

Re: Fourspriter: Sprite Engine from the Mojon Twins

britlion wrote:Aha. I hadn't noticed the end asm label: asm hops.

Incidentally, when including asm code, you have to make sure it doesn't run automatically - one easy way to do that is to include it in a sub or a function:


Yep, that's true. I found that the hard way. What I do to solve this is to #include the code at the end of the basic program, after an END statement.

But I agree your method would be more readable (and therefor more accesible). At first I tried to do it that way, but I think I encountered some problems as different routines share some code, so when I cut the code into subroutines I ruined some jumps.
<<

boriel

Site Admin

Posts: 1147

Joined: Wed Nov 01, 2006 6:18 pm

Location: Santa Cruz de Tenerife, Spain

Post Wed Mar 03, 2010 10:13 pm

Re: Fourspriter: Sprite Engine from the Mojon Twins

apenao wrote:
britlion wrote:Aha. I hadn't noticed the end asm label: asm hops.

Incidentally, when including asm code, you have to make sure it doesn't run automatically - one easy way to do that is to include it in a sub or a function:


Yep, that's true. I found that the hard way. What I do to solve this is to #include the code at the end of the basic program, after an END statement.

But I agree your method would be more readable (and therefor more accesible). At first I tried to do it that way, but I think I encountered some problems as different routines share some code, so when I cut the code into subroutines I ruined some jumps.


It's a good idea. Alto have a look at the library/ directory. There's a library template to make .bas include files. Basically:
  • Use #ifdef... #endif to avoid recursive includes
  • Look at the pragmas (option push and option case insensitive). If you enable case insentive in your module, your functions might be callable with any letter case configuration:
    spriteattr(...) or SpriteATTR(...) or SpriteAttr(...) for example, will all be valid.

I can help both Britlion and you when 1.2.5 release is out, if you like.
<<

britlion

Posts: 679

Joined: Mon Apr 27, 2009 7:26 pm

Location: Slough, Berkshire, UK

Post Thu Mar 04, 2010 4:46 am

Re: Fourspriter: Sprite Engine from the Mojon Twins

I have to admit, I have no idea of the pragma options that the assembler deals with. I know it's deep under the hood, but some idea of those options might make for nicer library options!
<<

britlion

Posts: 679

Joined: Mon Apr 27, 2009 7:26 pm

Location: Slough, Berkshire, UK

Post Sat Mar 06, 2010 4:28 am

Re: Fourspriter: Sprite Engine from the Mojon Twins

apenao, I think you might be using it inorrectly - have you noticed how flickery it is at the top of the screen?

It's because there's a long time between erase and redraw. Each sprite has two locations - next and previous. You only need to update the next one, erase and redraw.

I've got a version that's much tighter there, but it still is flickery for the top 26 pixels. I'm trying to tighten (and perhaps shorten?) the code to make it faster to cover the shortfall, as well as look at their demo and find out why it doesn't have this issue at all.

If I can get the bugs out and make it even faster and smaller (one subroutine I got 30% faster!) then I'll post it up here.

The docopy routine is also duplicated, so I deleted one to save quite a few bytes.

Return to How-To & Tutorials

Who is online

Users browsing this forum: No registered users and 0 guests

cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by Vjacheslav Trushkin for Free Forums/DivisionCore.

phpBB SEO