From e08d610aef5ed9e5afb385d9e7b2679a9504e2da Mon Sep 17 00:00:00 2001 From: slederer Date: Fri, 20 Jun 2025 01:19:40 +0200 Subject: [PATCH] examples: new sprite animation demo --- examples/animate.pas | 136 ++++++++++++++++++++++++++++++++++++++++++ examples/grey.pict | Bin 0 -> 128072 bytes examples/sprites.inc | 2 +- examples/sprites.s | 55 ++++++++++++----- examples/walking.sprt | Bin 0 -> 2056 bytes utils/png2pict.py | 17 +++--- 6 files changed, 186 insertions(+), 24 deletions(-) create mode 100644 examples/animate.pas create mode 100644 examples/grey.pict create mode 100644 examples/walking.sprt diff --git a/examples/animate.pas b/examples/animate.pas new file mode 100644 index 0000000..2869c46 --- /dev/null +++ b/examples/animate.pas @@ -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. diff --git a/examples/grey.pict b/examples/grey.pict new file mode 100644 index 0000000000000000000000000000000000000000..da05406be36dc803b6782343838f9cf345503d74 GIT binary patch literal 128072 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 literal 0 HcmV?d00001 diff --git a/examples/sprites.inc b/examples/sprites.inc index 2b25366..2713c8e 100644 --- a/examples/sprites.inc +++ b/examples/sprites.inc @@ -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; procedure PutSprite(x,y:integer; var sprite: SpritePixels); external; diff --git a/examples/sprites.s b/examples/sprites.s index 42a3d0e..3391339 100644 --- a/examples/sprites.s +++ b/examples/sprites.s @@ -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 FB_RA $900 @@ -65,7 +66,8 @@ CALC_VMEM_ADDR: .EQU PS_Y 16 .EQU PS_SHIFT_C 20 .EQU PS_SPILL 24 - .EQU PS_FS 28 + .EQU PS_STRIPE_C 28 + .EQU PS_FS 32 PUTSPRITE: FPADJ -PS_FS STORE PS_SPRITE_DATA @@ -160,10 +162,14 @@ PS_LOOP2_X: STOREI ; store result into i/o reg DROP - ; - ; process spilled bits and right half of sprite data - ; + ; set counter for remaining stripes + 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 LOAD PS_SPILL @@ -176,7 +182,9 @@ PS_LOOP2_X: ; reset spill bits LOADC 0 STORE PS_SPILL - + + ; last spill bits are on ToS now + ; shift pixel data to right LOAD PS_SHIFT_C ; load shift count PS_LOOP3: ; test it for zero @@ -230,8 +238,14 @@ PS_LOOP3_X: SWAP STOREI 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 DUP LOADCP CALC_MASK ; calculate sprite mask for spill bits @@ -274,7 +288,8 @@ PS_L_XT: .EQU UD_S_BGDATA 12 .EQU UD_S_OFFSET 16 .EQU UD_S_BGORIG 20 - .EQU UD_S_FS 24 + .EQU UD_STRIPE_C 24 + .EQU UD_S_FS 28 UNDRAWSPRITE: FPADJ -UD_S_FS STORE UD_S_BGORIG @@ -318,25 +333,35 @@ UD_S_L1: 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 INC 4 DUP STORE UD_S_BGDATA LOADI 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 CBRANCH.Z UD_S_L2 - ; load 3rd word of background data + ; load next word of background data LOADCP FB_IO LOAD UD_S_BGDATA INC 4 - DUP - STORE UD_S_BGDATA LOADI STOREI ; and write it to vmem DROP diff --git a/examples/walking.sprt b/examples/walking.sprt new file mode 100644 index 0000000000000000000000000000000000000000..2cdd0ceda91d8f52c7e9e6e4471d8620271d1dea GIT binary patch literal 2056 zcmd5-2@1n74D;}Z0{O_;_W!p`P9e6`LRcxRDTOF@d`Lv-yrjIp~i z6xH?{Jhnp6JWG)G7v@`RY=`Hl__?L3)