Page 1 of 2

Rotating BIG sprites

Posted: Thu Mar 03, 2016 7:34 pm
by psycopathicteen
My current sprite rotation engine fills up the RAM with rotation steps. Obviously this limits the size of the rotating sprites, so I'm thinking of an alternative for larger sprites.

My idea is to pre-rotate the sprite to only 16 angles (which doubles to 32 angles when flipped) and smoothing the rotation by doing something similar to offset-per-tile mode, only being applied to sprites, and being done through software. First it will shift columns of 8x8 cells vertically, then it will shift lines of pixels horizontally.

Re: Rotating BIG sprites

Posted: Thu Mar 03, 2016 9:24 pm
by tepples
psycopathicteen wrote:My idea is to pre-rotate the sprite to only 16 angles (which doubles to 32 angles when flipped) and smoothing the rotation by doing something similar to offset-per-tile mode, only being applied to sprites, and being done through software. First it will shift columns of 8x8 cells vertically, then it will shift lines of pixels horizontally.
So something like this sprite shearing technique?

Re: Rotating BIG sprites

Posted: Thu Mar 03, 2016 10:16 pm
by psycopathicteen
tepples wrote:
psycopathicteen wrote:My idea is to pre-rotate the sprite to only 16 angles (which doubles to 32 angles when flipped) and smoothing the rotation by doing something similar to offset-per-tile mode, only being applied to sprites, and being done through software. First it will shift columns of 8x8 cells vertically, then it will shift lines of pixels horizontally.
So something like this sprite shearing technique?
Pretty much, except the shearing would be done through software.

One thing I'd need to change about my engine is something I think Khan mentioned in a thread about animation. He once mentioned about using a bit to signal when an animation needs to be updated, as opposed to comparing numbers. Instead of having to compare 2 metasprite data address registers, 2 graphics address registers, and now a flag to mark if the graphics at that particular address happened to change, it makes sense to just have a flag that declares if the metasprite was changed in general.

Re: Rotating BIG sprites

Posted: Wed Apr 27, 2016 7:27 pm
by psycopathicteen
I think I'll arrange the "unshifted" version of the sprites in a slightly different format. All 4 planar bytes would be stored together, and the 8x1 slivers would be stored from left to right, top to bottom. The sprites would be padded 4 lines of pixels on top and bottom with blank pixels in order to not have boundary crossing problems. So here is some code to copy a column of pixels.

Code: Select all

-;
lda $0000,x
sta $0000,y
lda $0002,x
sta $0010,y

lda $0020,x
sta $0002,y
lda $0022,x
sta $0012,y

lda $0040,x
sta $0004,y
lda $0042,x
sta $0014,y

lda $0060,x
sta $0006,y
lda $0062,x
sta $0016,y

lda $0080,x
sta $0008,y
lda $0082,x
sta $0018,y

lda $00a0,x
sta $000a,y
lda $00a2,x
sta $001a,y

lda $00c0,x
sta $000c,y
lda $00c2,x
sta $001c,y

lda $00e0,x
sta $000e,y
lda $00e2,x
sta $001e,y

txa
clc
adc #$0100
tax
tya
clc
adc #$0100
tay
dec {temp}
bne -

Re: Rotating BIG sprites

Posted: Thu Apr 28, 2016 6:47 pm
by psycopathicteen
Okay, now I have working code for tilting a 64x64 sprite.

Code: Select all

big_sprite_rotation:
phb
lda #$7e7e
pha
plb
plb

ldy #$0000
sty {temp4}
sty {temp3}

lda #$0008
clc
adc {shift_factor}	//shift factor is between -8 and 7
asl #2
sta {temp2}


-;
and #$0038
asl #2
clc
adc {temp3}
tax
jsr copy_collumn
lda {temp4}
clc
adc #$0020
sta {temp4}
tay
lda {temp3}
clc
adc #$0004
sta {temp3}
cmp #$0020
beq +

lda {temp2}
sec
sbc {shift_factor}
sta {temp2}
bra -
+;



ldx #$0000
lda {shift_factor}
asl #5
sta {temp}
-;
lda {temp}
lsr #6
sep #$20
cmp #$00
beq ++
bpl +
jsr shift_pixels_left
bra ++
+;
jsr shift_pixels_right
+;
rep #$20
lda {temp}
sec
sbc {shift_factor}
sta {temp}
inx
inx
txa
and #$001f
cmp #$0010
bne -
txa
clc
adc #$00f0
tax
cpx #$0800
beq +
jmp -
+;

plb
rts







copy_collumn:
lda #$0008
sta {temp}
-;
lda {rotating_sprite}+$0000,x
sta {rotating_sprite_buffer}+$0000,y
lda {rotating_sprite}+$0002,x
sta {rotating_sprite_buffer}+$0010,y

lda {rotating_sprite}+$0020,x
sta {rotating_sprite_buffer}+$0002,y
lda {rotating_sprite}+$0022,x
sta {rotating_sprite_buffer}+$0012,y

lda {rotating_sprite}+$0040,x
sta {rotating_sprite_buffer}+$0004,y
lda {rotating_sprite}+$0042,x
sta {rotating_sprite_buffer}+$0014,y

lda {rotating_sprite}+$0060,x
sta {rotating_sprite_buffer}+$0006,y
lda {rotating_sprite}+$0062,x
sta {rotating_sprite_buffer}+$0016,y

lda {rotating_sprite}+$0080,x
sta {rotating_sprite_buffer}+$0008,y
lda {rotating_sprite}+$0082,x
sta {rotating_sprite_buffer}+$0018,y

lda {rotating_sprite}+$00a0,x
sta {rotating_sprite_buffer}+$000a,y
lda {rotating_sprite}+$00a2,x
sta {rotating_sprite_buffer}+$001a,y

lda {rotating_sprite}+$00c0,x
sta {rotating_sprite_buffer}+$000c,y
lda {rotating_sprite}+$00c2,x
sta {rotating_sprite_buffer}+$001c,y

lda {rotating_sprite}+$00e0,x
sta {rotating_sprite_buffer}+$000e,y
lda {rotating_sprite}+$00e2,x
sta {rotating_sprite_buffer}+$001e,y

txa
clc
adc #$0100
tax
tya
clc
adc #$0100
tay
dec {temp}
beq +
jmp -
+;
rts


shift_pixels_right:
-;
pha
lsr {rotating_sprite_buffer}+$0000,x
ror {rotating_sprite_buffer}+$0020,x
ror {rotating_sprite_buffer}+$0040,x
ror {rotating_sprite_buffer}+$0060,x
ror {rotating_sprite_buffer}+$0080,x
ror {rotating_sprite_buffer}+$00a0,x
ror {rotating_sprite_buffer}+$00c0,x
ror {rotating_sprite_buffer}+$00e0,x

lsr {rotating_sprite_buffer}+$0001,x
ror {rotating_sprite_buffer}+$0021,x
ror {rotating_sprite_buffer}+$0041,x
ror {rotating_sprite_buffer}+$0061,x
ror {rotating_sprite_buffer}+$0081,x
ror {rotating_sprite_buffer}+$00a1,x
ror {rotating_sprite_buffer}+$00c1,x
ror {rotating_sprite_buffer}+$00e1,x

lsr {rotating_sprite_buffer}+$0010,x
ror {rotating_sprite_buffer}+$0030,x
ror {rotating_sprite_buffer}+$0050,x
ror {rotating_sprite_buffer}+$0070,x
ror {rotating_sprite_buffer}+$0090,x
ror {rotating_sprite_buffer}+$00b0,x
ror {rotating_sprite_buffer}+$00d0,x
ror {rotating_sprite_buffer}+$00f0,x

lsr {rotating_sprite_buffer}+$0011,x
ror {rotating_sprite_buffer}+$0031,x
ror {rotating_sprite_buffer}+$0051,x
ror {rotating_sprite_buffer}+$0071,x
ror {rotating_sprite_buffer}+$0091,x
ror {rotating_sprite_buffer}+$00b1,x
ror {rotating_sprite_buffer}+$00d1,x
ror {rotating_sprite_buffer}+$00f1,x
pla
dec
beq +
jmp -
+;

rts


shift_pixels_left:
-;
pha

asl {rotating_sprite_buffer}+$00e0,x
rol {rotating_sprite_buffer}+$00c0,x
rol {rotating_sprite_buffer}+$00a0,x
rol {rotating_sprite_buffer}+$0080,x
rol {rotating_sprite_buffer}+$0060,x
rol {rotating_sprite_buffer}+$0040,x
rol {rotating_sprite_buffer}+$0020,x
rol {rotating_sprite_buffer}+$0000,x

asl {rotating_sprite_buffer}+$00e1,x
rol {rotating_sprite_buffer}+$00c1,x
rol {rotating_sprite_buffer}+$00a1,x
rol {rotating_sprite_buffer}+$0081,x
rol {rotating_sprite_buffer}+$0061,x
rol {rotating_sprite_buffer}+$0041,x
rol {rotating_sprite_buffer}+$0021,x
rol {rotating_sprite_buffer}+$0001,x

asl {rotating_sprite_buffer}+$00f0,x
rol {rotating_sprite_buffer}+$00d0,x
rol {rotating_sprite_buffer}+$00b0,x
rol {rotating_sprite_buffer}+$0090,x
rol {rotating_sprite_buffer}+$0070,x
rol {rotating_sprite_buffer}+$0050,x
rol {rotating_sprite_buffer}+$0030,x
rol {rotating_sprite_buffer}+$0010,x

asl {rotating_sprite_buffer}+$00f1,x
rol {rotating_sprite_buffer}+$00d1,x
rol {rotating_sprite_buffer}+$00b1,x
rol {rotating_sprite_buffer}+$0091,x
rol {rotating_sprite_buffer}+$0071,x
rol {rotating_sprite_buffer}+$0051,x
rol {rotating_sprite_buffer}+$0031,x
rol {rotating_sprite_buffer}+$0011,x

pla
inc
beq +
jmp -
+;

rts

Re: Rotating BIG sprites

Posted: Thu Apr 28, 2016 9:34 pm
by lint
Can you post a rom ? I'm curious about the result ... and the perfs ...

Re: Rotating BIG sprites

Posted: Fri Apr 29, 2016 4:59 pm
by psycopathicteen
At 60fps it causes slowdown, but I can fix it by having it run outside the main routine. It's okay if it runs 30fps or 20fps, because even the non-realtime rotation sprites have variable framerates because of DMA limitations.

Re: Rotating BIG sprites

Posted: Sun May 01, 2016 2:26 pm
by Stef
Really impressive psycopathicteen :)

Re: Rotating BIG sprites

Posted: Mon Apr 24, 2017 7:47 pm
by psycopathicteen
I've been thinking today about this and I realized that if I scroll every 5 pixels instead of 8, I would only need 8 distinct rotation frames (16 including x/y flip) to make a full circle because arctan(1/5) = ~11.25 degrees.

Re: Rotating BIG sprites

Posted: Fri Apr 28, 2017 1:17 pm
by psycopathicteen
I got a 64x64 sprite rotating 360 degrees, but it looks kind've crappy because I was in a rush.

Re: Rotating BIG sprites

Posted: Sat Apr 29, 2017 1:03 am
by UnDisbeliever
Looking good.

EDIT: The rotations look a lot nicer on my CRT TV then on a SNES emulator. I can barely see the tearing on my PAL SNES+CRT TV.

Re: Rotating BIG sprites

Posted: Sat Apr 29, 2017 4:41 am
by tokumaru
UnDisbeliever wrote:The rotations look a lot nicer on my CRT TV then on a SNES emulator.
EVERYTHING looks better on a CRT television than on an emulator. :wink:

Re: Rotating BIG sprites

Posted: Sat Apr 29, 2017 7:12 am
by psycopathicteen
I didn't think about this, but it would look better on a PAL TV set than an NTSC TV set, because you have 20% more CPU time.

Here is an improved version, that would look good even on NTSC.

Re: Rotating BIG sprites

Posted: Sat Apr 29, 2017 10:25 am
by Drew Sebastino
UnDisbeliever wrote:I can barely see the tearing on my PAL SNES+CRT TV.
"It looks a lot better after it's been blurred out." :lol:

Re: Rotating BIG sprites

Posted: Sat Apr 29, 2017 8:04 pm
by ccovell
It looks quite good, and I really like the green pumpkin spider. Very Wolfteam-like.

Music is strident, but slowly getting less abrasive....