Skip to content

Commit ea65d81

Browse files
committed
[bugifx] SprSize panics when range is too high
SprSize sometimes panics if trying to copy range outside the sprite-sheet. The main reason is the algorithm used to clamp the range. It does not take into consideration that width or height can be a non-integer value.
1 parent 77631ab commit ea65d81

File tree

6 files changed

+26
-22
lines changed

6 files changed

+26
-22
lines changed
364 Bytes
Loading
364 Bytes
Loading

pi.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ func Boot() error {
114114
numberOfSprites = (ssWidth * ssHeight) / (SpriteWidth * SpriteHeight)
115115

116116
spritesInLine = ssWidth / SpriteWidth
117-
spritesRows = ssHeight / SpriteHeight
118117

119118
scrWidth = ScreenWidth
120119
scrHeight = ScreenHeight

screen.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -204,20 +204,22 @@ func SprSizeFlip(n, x, y int, w, h float64, flipX, flipY bool) {
204204

205205
screenOffset := y*scrWidth + x
206206

207-
spriteX := n % spritesInLine
208-
spriteY := n / spritesInLine
207+
spriteX := (n % spritesInLine) * SpriteWidth
208+
spriteY := (n / spritesInLine) * SpriteHeight
209209

210-
if spriteX+int(w) >= spritesInLine {
211-
w = float64(spritesInLine - spriteX)
210+
width := int(SpriteWidth * w)
211+
height := int(SpriteHeight * h)
212+
213+
if spriteX+width > ssWidth {
214+
width = ssWidth - spriteX
212215
}
213216

214-
if spriteY+int(h) >= spritesRows {
215-
h = float64(spritesRows - spriteY)
217+
if spriteY+height > ssHeight {
218+
height = ssHeight - spriteY
216219
}
217220

218-
spriteSheetOffset := spriteY*ssWidth*SpriteHeight + spriteX*SpriteWidth
221+
spriteSheetOffset := spriteY*ssWidth + spriteX
219222

220-
width := int(SpriteWidth * w)
221223
if x < clippingRegion.x {
222224
dx := clippingRegion.x - x
223225
width -= dx
@@ -231,7 +233,6 @@ func SprSizeFlip(n, x, y int, w, h float64, flipX, flipY bool) {
231233
return
232234
}
233235

234-
height := int(SpriteHeight * h)
235236
if y < clippingRegion.y {
236237
dy := clippingRegion.y - y
237238
height -= dy

screen_test.go

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -494,20 +494,25 @@ func testSprSize(t *testing.T, sprSize func(spriteNo int, x, y int, w, h float64
494494

495495
t.Run("should draw sprite", func(t *testing.T) {
496496
tests := map[string]struct {
497+
spriteNo int
497498
w, h float64
498499
x, y int
499500
expectedScreenFile string
500501
}{
501-
"sprite at (0,0,0.5,1.0)": {w: 0.5, h: 1.0, expectedScreenFile: "spr_0_0_0.5_1.0.png"},
502-
"sprite at (0,0,1.0,0.5)": {w: 1.0, h: 0.5, expectedScreenFile: "spr_0_0_1.0_0.5.png"},
503-
"sprite at (0,0,2.0,1.0)": {w: 2.0, h: 1.0, expectedScreenFile: "spr_0_0_2.0_1.0.png"},
504-
"sprite at (0,0,1.0,2.0)": {w: 1.0, h: 2.0, expectedScreenFile: "spr_0_0_1.0_2.0.png"},
505-
"sprite at (0,0,2.5,1.0)": {w: 2.5, h: 1.0, expectedScreenFile: "spr_0_0_2.0_1.0.png"},
506-
"sprite at (0,0,1.0,2.5)": {w: 1.0, h: 2.5, expectedScreenFile: "spr_0_0_1.0_2.0.png"},
507-
"sprite at (8,0,2.0,1.0)": {x: 8, w: 2.0, h: 1.0, expectedScreenFile: "spr_8_0_2.0_1.0.png"},
508-
"sprite at (0,8,1.0,2.0)": {y: 8, w: 1.0, h: 2.0, expectedScreenFile: "spr_0_8_1.0_2.0.png"},
509-
"sprite at (0,0,1.1,0.5)": {w: 1.1, h: 0.5, expectedScreenFile: "spr_0_0_1.0_0.5.png"}, // should floor(w*8)
510-
"sprite at (0,0,0.5,1.1)": {w: 0.5, h: 1.1, expectedScreenFile: "spr_0_0_0.5_1.0.png"}, // should floor(h*8)
502+
"sprite at (0,0,0.5,1.0)": {w: 0.5, h: 1.0, expectedScreenFile: "spr_0_0_0.5_1.0.png"},
503+
"sprite at (0,0,1.0,0.5)": {w: 1.0, h: 0.5, expectedScreenFile: "spr_0_0_1.0_0.5.png"},
504+
"sprite at (0,0,2.0,1.0)": {w: 2.0, h: 1.0, expectedScreenFile: "spr_0_0_2.0_1.0.png"},
505+
"sprite at (0,0,1.0,2.0)": {w: 1.0, h: 2.0, expectedScreenFile: "spr_0_0_1.0_2.0.png"},
506+
"sprite at (0,0,2.5,1.0)": {w: 2.5, h: 1.0, expectedScreenFile: "spr_0_0_2.0_1.0.png"},
507+
"sprite at (0,0,1.0,2.5)": {w: 1.0, h: 2.5, expectedScreenFile: "spr_0_0_1.0_2.0.png"},
508+
"sprite at (8,0,2.0,1.0)": {x: 8, w: 2.0, h: 1.0, expectedScreenFile: "spr_8_0_2.0_1.0.png"},
509+
"sprite at (0,8,1.0,2.0)": {y: 8, w: 1.0, h: 2.0, expectedScreenFile: "spr_0_8_1.0_2.0.png"},
510+
"sprite at (0,0,1.1,0.5)": {w: 1.1, h: 0.5, expectedScreenFile: "spr_0_0_1.0_0.5.png"}, // should floor(w*8)
511+
"sprite at (0,0,0.5,1.1)": {w: 0.5, h: 1.1, expectedScreenFile: "spr_0_0_0.5_1.0.png"}, // should floor(h*8)
512+
"sprite 1 at (0,0,2.0,1.0)": {spriteNo: 1, w: 2.0, h: 1.0, expectedScreenFile: "spr_1_at_0_0_2.0_1.0.png"},
513+
"sprite 1 at (0,0,1.9,1.0)": {spriteNo: 1, w: 1.9, h: 1.0, expectedScreenFile: "spr_1_at_0_0_2.0_1.0.png"},
514+
"sprite 2 at (0,0,1.0,2.0)": {spriteNo: 2, w: 1.0, h: 2.0, expectedScreenFile: "spr_2_at_0_0_1.0_2.0.png"},
515+
"sprite 2 at (0,0,1.0,1.9)": {spriteNo: 2, w: 1.0, h: 1.9, expectedScreenFile: "spr_2_at_0_0_1.0_2.0.png"},
511516
}
512517
for name, test := range tests {
513518
t.Run(name, func(t *testing.T) {
@@ -519,7 +524,7 @@ func testSprSize(t *testing.T, sprSize func(spriteNo int, x, y int, w, h float64
519524
pi.BootOrPanic()
520525
expectedScreen := decodePNG(t, "internal/testimage/"+test.expectedScreenFile)
521526
// when
522-
sprSize(0, test.x, test.y, test.w, test.h)
527+
sprSize(test.spriteNo, test.x, test.y, test.w, test.h)
523528
// then
524529
assert.Equal(t, expectedScreen.Pixels, pi.ScreenData)
525530
})

sprite_sheet.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ var (
2525
ssWidth, ssHeight int
2626
numberOfSprites int
2727
spritesInLine int
28-
spritesRows int
2928
)
3029

3130
// Sset sets the pixel color on the sprite sheet. It does not update the global Color.

0 commit comments

Comments
 (0)