examples: new sprite animation demo

This commit is contained in:
slederer 2025-06-20 01:19:40 +02:00
parent bde01e402c
commit e08d610aef
6 changed files with 186 additions and 24 deletions

136
examples/animate.pas Normal file
View file

@ -0,0 +1,136 @@
program animate;
uses sprites;
type PictData = record
magic,mode:integer;
palette: array [0..15] of integer;
pixeldata: array [0..31999] of integer;
end;
Sprite = record
x,y:integer;
oldX,oldY:integer;
xdelta,ydelta:integer;
curFrame:integer;
frameCount:integer;
frameTime:integer;
frameLeft:integer;
changed:boolean;
frame:array [0..3] of SpritePixels;
end;
var pic:PictData;
filename:string;
infile:file;
ch:char;
stickMan:Sprite;
procedure WaitVSync; external;
procedure loadPalette(var pic:PictData);
var i:integer;
begin
for i := 0 to 15 do
setpalette(i, pic.palette[i]);
end;
procedure showPic(var pic:PictData);
begin
PutScreen(pic.pixeldata);
end;
procedure loadSpriteFrame(var aSprite:Sprite;spriteIndex:integer;
var sheetFile:file;sheetIndex:integer);
begin
seek(sheetFile, 8 + sheetIndex * 512);
read(sheetFile, aSprite.frame[spriteIndex]);
if aSprite.frameCount <= spriteIndex then
aSprite.frameCount := spriteIndex + 1;
aSprite.curFrame := 0;
writeln('loaded sprite frame ', spriteIndex, ' from ', sheetIndex);
end;
procedure animateSprite(var aSprite:Sprite);
var frameIndex:integer;
frameTime,frameLeft:integer;
ydelta:integer;
oldX,oldY:integer;
begin
ydelta := aSprite.ydelta;
frameIndex := aSprite.curFrame;
frameTime := aSprite.frameTime;
frameLeft := aSprite.frameLeft;
oldX := aSprite.x; oldY := aSprite.y;
aSprite.oldX := oldX; aSprite.oldY := oldY;
frameLeft := frameLeft - 1;
if frameLeft <= 0 then
begin
frameIndex := frameIndex + 1;
frameLeft := aSPrite.frameTime;
aSprite.frameLeft := frameLeft;
aSprite.curFrame := frameIndex;
if frameIndex >= aSprite.frameCount then
aSprite.curFrame := 0;
aSprite.frameLeft := frameLeft;
aSprite.x := aSprite.x + aSprite.xdelta;
aSprite.y := aSprite.y + aSprite.ydelta;
if aSprite.x > 608 then aSprite.x := 0;
end;
aSprite.frameLeft := frameLeft;
end;
procedure animLoop;
var i:integer;
oldX,oldY:integer;
begin
stickMan.x := 0;
stickMan.y := 310;
stickMan.frameTime := 6;
stickMan.frameLeft := stickMan.frameTime;
stickMan.curFrame := 0;
stickMan.xdelta := 2;
stickMan.ydelta := 0;
oldX := stickMan.x;
oldY := stickMan.y;
while not ConAvail do
begin
oldX := stickMan.x;
oldY := stickMan.y;
PutSprite(oldX, oldY, stickMan.frame[stickMan.curFrame]);
animateSprite(stickMan);
Delay(10);
WaitVSync;
UndrawSprite(oldX, oldY, pic.pixeldata);
end;
end;
begin
filename := 'grey.pict';
open(infile, filename, ModeReadonly);
read(infile, pic);
close(infile);
writeln('magic: ', pic.magic, ' mode:', pic.mode);
loadPalette(pic);
showPic(pic);
open(infile, 'Walking.sprt', ModeReadOnly);
loadSpriteFrame(stickMan, 0, infile, 0);
loadSpriteFrame(stickMan, 1, infile, 1);
loadSpriteFrame(stickMan, 2, infile, 2);
loadSpriteFrame(stickMan, 3, infile, 3);
close(infile);
animLoop;
end.

BIN
examples/grey.pict Normal file

Binary file not shown.

View file

@ -1,4 +1,4 @@
type SpritePixels = array[0..31] of integer; type SpritePixels = array[0..128] of integer;
type BackgroundPixels = array[0..31999] of integer; type BackgroundPixels = array[0..31999] of integer;
procedure PutSprite(x,y:integer; var sprite: SpritePixels); external; procedure PutSprite(x,y:integer; var sprite: SpritePixels); external;

View file

@ -1,4 +1,5 @@
.EQU SPRITE_HEIGHT 16 .EQU SPRITE_HEIGHT 32 ; height in lines
.EQU SPRITE_STRIPES 4 ; width in words i.e. 8-pixel stripes
.EQU WORDS_PER_LINE 80 .EQU WORDS_PER_LINE 80
.EQU FB_RA $900 .EQU FB_RA $900
@ -65,7 +66,8 @@ CALC_VMEM_ADDR:
.EQU PS_Y 16 .EQU PS_Y 16
.EQU PS_SHIFT_C 20 .EQU PS_SHIFT_C 20
.EQU PS_SPILL 24 .EQU PS_SPILL 24
.EQU PS_FS 28 .EQU PS_STRIPE_C 28
.EQU PS_FS 32
PUTSPRITE: PUTSPRITE:
FPADJ -PS_FS FPADJ -PS_FS
STORE PS_SPRITE_DATA STORE PS_SPRITE_DATA
@ -160,10 +162,14 @@ PS_LOOP2_X:
STOREI ; store result into i/o reg STOREI ; store result into i/o reg
DROP DROP
; ; set counter for remaining stripes
; process spilled bits and right half of sprite data LOADC SPRITE_STRIPES - 1
; STORE PS_STRIPE_C
;
; process spilled bits and next vertical stripe of sprite data
;
PS_NEXT_STRIPE:
; put spill bits on stack for later ; put spill bits on stack for later
LOAD PS_SPILL LOAD PS_SPILL
@ -177,6 +183,8 @@ PS_LOOP2_X:
LOADC 0 LOADC 0
STORE PS_SPILL STORE PS_SPILL
; last spill bits are on ToS now
; shift pixel data to right ; shift pixel data to right
LOAD PS_SHIFT_C ; load shift count LOAD PS_SHIFT_C ; load shift count
PS_LOOP3: ; test it for zero PS_LOOP3: ; test it for zero
@ -231,7 +239,13 @@ PS_LOOP3_X:
STOREI STOREI
DROP DROP
; write spilled bits into next vmem word LOAD PS_STRIPE_C ; decrement stripe count
DEC 1
DUP
STORE PS_STRIPE_C
CBRANCH.NZ PS_NEXT_STRIPE ; if non-zero, next stripe
; write spilled bits of the last stripe into next vmem word
LOAD PS_SPILL ; get spill bits LOAD PS_SPILL ; get spill bits
DUP DUP
LOADCP CALC_MASK ; calculate sprite mask for spill bits LOADCP CALC_MASK ; calculate sprite mask for spill bits
@ -274,7 +288,8 @@ PS_L_XT:
.EQU UD_S_BGDATA 12 .EQU UD_S_BGDATA 12
.EQU UD_S_OFFSET 16 .EQU UD_S_OFFSET 16
.EQU UD_S_BGORIG 20 .EQU UD_S_BGORIG 20
.EQU UD_S_FS 24 .EQU UD_STRIPE_C 24
.EQU UD_S_FS 28
UNDRAWSPRITE: UNDRAWSPRITE:
FPADJ -UD_S_FS FPADJ -UD_S_FS
STORE UD_S_BGORIG STORE UD_S_BGORIG
@ -318,25 +333,35 @@ UD_S_L1:
STOREI STOREI
; reuse addr from STOREI ; reuse addr from STOREI
; load 2nd word of background data LOADC SPRITE_STRIPES - 1 ; set remaining stripe count
STORE UD_STRIPE_C
UD_NEXT_STRIPE:
; load next word of background data
LOAD UD_S_BGDATA LOAD UD_S_BGDATA
INC 4 INC 4
DUP DUP
STORE UD_S_BGDATA STORE UD_S_BGDATA
LOADI LOADI
STOREI ; and write it to vmem STOREI ; and write it to vmem
DROP ; reuse addr from STOREI
; if pixel shift is zero, no 3rd word LOAD UD_STRIPE_C ; decrease remaining stripe count
DEC 1
DUP
STORE UD_STRIPE_C
CBRANCH.NZ UD_NEXT_STRIPE ; if non-zero, next stripe
DROP ; remove addr from STOREI
; if pixel shift is zero, no spill word
LOAD UD_S_PXS LOAD UD_S_PXS
CBRANCH.Z UD_S_L2 CBRANCH.Z UD_S_L2
; load 3rd word of background data ; load next word of background data
LOADCP FB_IO LOADCP FB_IO
LOAD UD_S_BGDATA LOAD UD_S_BGDATA
INC 4 INC 4
DUP
STORE UD_S_BGDATA
LOADI LOADI
STOREI ; and write it to vmem STOREI ; and write it to vmem
DROP DROP

BIN
examples/walking.sprt Normal file

Binary file not shown.

View file

@ -2,6 +2,9 @@
import sys import sys
import png import png
sprite_width = 32
sprite_height = 32
def process_pixdata(outfile, pixdata, frameindex = 0, pix_w=640, pix_h=400): def process_pixdata(outfile, pixdata, frameindex = 0, pix_w=640, pix_h=400):
pixmask = 15 pixmask = 15
@ -72,22 +75,20 @@ def write_pict_file(width, height, px, metadata, outfile):
def write_sprite_file(width, height, px, metadata, outfile): def write_sprite_file(width, height, px, metadata, outfile):
sprite_height=16
print("processing as SPRT file with {} sprites...".format(height//sprite_height)) print("processing as SPRT file with {} sprites...".format(height//sprite_height))
if width != 16: if width != sprite_width:
print("width must be 16, aborting") print("width must be {}, aborting".format(sprite_width))
sys.exit(1) sys.exit(1)
pixdata = list(px) pixdata = list(px)
palette = metadata['palette'] palette = metadata['palette']
if len(palette) != 16: if len(palette) != 16:
print("palette must have 16 colors, aborting") print("palette must have 16 colors instead of {}, aborting".format(len(palette)))
sys.exit(0) sys.exit(0)
with open(outfile,'wb') as f: with open(outfile,'wb') as f:
write_sprite_header(f) write_sprite_header(f)
process_pixdata(f, pixdata, pix_w=16, pix_h=height) process_pixdata(f, pixdata, pix_w=sprite_width, pix_h=height)
if __name__ == '__main__': if __name__ == '__main__':
@ -103,8 +104,8 @@ if __name__ == '__main__':
width, height, px, metadata = p width, height, px, metadata = p
if width == 640: if width == 640:
write_pict_file(width, height, px, metadata, outfile) write_pict_file(width, height, px, metadata, outfile)
elif width == 16: elif width == sprite_width:
write_sprite_file(width, height, px, metadata, outfile) write_sprite_file(width, height, px, metadata, outfile)
else: else:
print("Can't handle this file, need a width of\n640 or 16 pixels with 16 color palette.") print("Can't handle this file, need a width of\n640 or {} pixels with 16 color palette.".format(sprite_width))