examples: new sprite animation demo
This commit is contained in:
parent
bde01e402c
commit
e08d610aef
6 changed files with 186 additions and 24 deletions
136
examples/animate.pas
Normal file
136
examples/animate.pas
Normal 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
BIN
examples/grey.pict
Normal file
Binary file not shown.
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
BIN
examples/walking.sprt
Normal file
Binary file not shown.
|
|
@ -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))
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue