Skip to content

Commit a9d212f

Browse files
committed
Implement palette transparency
Add Palt and PaltReset functions. Palt sets color transparency. If true then the color will not be drawn for next drawing operations. Color transparency is used by Spr, SprSize and SprSizeFlip. PaltReset sets all transparent colors to false and makes color 0 transparent.
1 parent ea65d81 commit a9d212f

File tree

7 files changed

+111
-5
lines changed

7 files changed

+111
-5
lines changed
354 Bytes
Loading
354 Bytes
Loading
Loading

pi.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ func Boot() error {
124124

125125
Clip(0, 0, scrWidth, scrHeight)
126126
Camera(0, 0)
127+
PaltReset()
127128

128129
return nil
129130
}

screen.go

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -249,16 +249,43 @@ func SprSizeFlip(n, x, y int, w, h float64, flipX, flipY bool) {
249249
spriteSheetStep = -ssWidth
250250
}
251251

252+
startingPixel := 0
253+
step := 1
254+
255+
if flipX {
256+
startingPixel = width - 1
257+
step = -1
258+
}
259+
252260
for i := 0; i < height; i++ {
253261
spriteSheetLine := SpriteSheetData[spriteSheetOffset : spriteSheetOffset+width]
254-
if flipX {
255-
for j := 0; j < len(spriteSheetLine); j++ {
256-
ScreenData[screenOffset+j] = spriteSheetLine[len(spriteSheetLine)-1-j]
262+
263+
for j := 0; j < len(spriteSheetLine); j++ {
264+
col := spriteSheetLine[startingPixel+(step*j)]
265+
if colorIsTransparent[col] {
266+
continue
257267
}
258-
} else {
259-
copy(ScreenData[screenOffset:screenOffset+width], spriteSheetLine)
268+
269+
ScreenData[screenOffset+j] = col
260270
}
261271
screenOffset += scrWidth
262272
spriteSheetOffset += spriteSheetStep
263273
}
264274
}
275+
276+
var colorIsTransparent [256]bool
277+
278+
// Palt sets color transparency. If true then the color will not be drawn
279+
// for next drawing operations.
280+
//
281+
// Color transparency is used by Spr, SprSize and SprSizeFlip.
282+
func Palt(color byte, transparent bool) {
283+
colorIsTransparent[color] = transparent
284+
}
285+
286+
var defaultTransparency = [256]bool{true}
287+
288+
// PaltReset sets all transparent colors to false and makes color 0 transparent.
289+
func PaltReset() {
290+
colorIsTransparent = defaultTransparency
291+
}

screen_bench_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,14 @@ func BenchmarkSprSizeFlip(b *testing.B) {
8080
})
8181
}
8282

83+
func BenchmarkPaltReset(b *testing.B) {
84+
for i := 0; i < b.N; i++ {
85+
runBenchmarks(b, func(res Resolution) {
86+
pi.PaltReset()
87+
})
88+
}
89+
}
90+
8391
type Resolution struct{ W, H int }
8492

8593
func (s Resolution) String() string {

screen_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,58 @@ func testSpr(t *testing.T, spr func(spriteNo int, x int, y int)) {
454454
})
455455
}
456456
})
457+
458+
t.Run("should not draw color 0 by default", func(t *testing.T) {
459+
pi.Reset()
460+
pi.ScreenWidth = 8
461+
pi.ScreenHeight = 8
462+
pi.Resources = fstest.MapFS{
463+
"sprite-sheet.png": &fstest.MapFile{Data: spriteSheet16x16},
464+
}
465+
pi.BootOrPanic()
466+
spr(2, 0, 0)
467+
// when
468+
spr(1, 0, 0)
469+
// then
470+
expectedScreen := decodePNG(t, "internal/testimage/spr_1_on_top_of_2_trans_0.png")
471+
assert.Equal(t, expectedScreen.Pixels, pi.ScreenData)
472+
})
473+
474+
t.Run("should not draw color 0 after PaltReset", func(t *testing.T) {
475+
pi.Reset()
476+
pi.ScreenWidth = 8
477+
pi.ScreenHeight = 8
478+
pi.Resources = fstest.MapFS{
479+
"sprite-sheet.png": &fstest.MapFile{Data: spriteSheet16x16},
480+
}
481+
pi.BootOrPanic()
482+
spr(2, 0, 0)
483+
pi.Palt(0, false) // make color 0 opaque
484+
// when
485+
pi.PaltReset() // and then make color 0 transparent again
486+
spr(1, 0, 0)
487+
// then
488+
expectedScreen := decodePNG(t, "internal/testimage/spr_1_on_top_of_2_trans_0.png")
489+
assert.Equal(t, expectedScreen.Pixels, pi.ScreenData)
490+
})
491+
492+
t.Run("should not draw transparent colors", func(t *testing.T) {
493+
pi.Reset()
494+
pi.ScreenWidth = 8
495+
pi.ScreenHeight = 8
496+
pi.Resources = fstest.MapFS{
497+
"sprite-sheet.png": &fstest.MapFile{Data: spriteSheet16x16},
498+
}
499+
pi.BootOrPanic()
500+
spr(2, 0, 0)
501+
// when
502+
pi.Palt(0, false)
503+
pi.Palt(50, true)
504+
spr(1, 0, 0)
505+
// then
506+
expectedScreen := decodePNG(t, "internal/testimage/spr_1_on_top_of_2_trans_50.png")
507+
assert.Equal(t, expectedScreen.Pixels, pi.ScreenData)
508+
})
457509
}
458510

459511
func TestSprSize(t *testing.T) {
@@ -565,6 +617,24 @@ func TestSprSizeFlip(t *testing.T) {
565617
})
566618
}
567619
})
620+
621+
t.Run("should not draw transparent colors", func(t *testing.T) {
622+
pi.Reset()
623+
pi.ScreenWidth = 8
624+
pi.ScreenHeight = 8
625+
pi.Resources = fstest.MapFS{
626+
"sprite-sheet.png": &fstest.MapFile{Data: spriteSheet16x16},
627+
}
628+
pi.BootOrPanic()
629+
pi.SprSizeFlip(2, 0, 0, 1.0, 1.0, true, false)
630+
// when
631+
pi.Palt(0, false)
632+
pi.Palt(50, true)
633+
pi.SprSizeFlip(1, 0, 0, 1.0, 1.0, true, false)
634+
// then
635+
expectedScreen := decodePNG(t, "internal/testimage/spr_1_on_top_of_2_trans_50_flipx.png")
636+
assert.Equal(t, expectedScreen.Pixels, pi.ScreenData)
637+
})
568638
}
569639

570640
func clone(s []byte) []byte {

0 commit comments

Comments
 (0)