Forem

Cover image for Optimizing Mini Micro for pixel-art games
JoeStrout
JoeStrout

Posted on

Optimizing Mini Micro for pixel-art games

I recently wrote about why Mini Micro's display is 960 x 640 pixels. In short: that's a reasonably high but still manageable resolution.

But many people discover Mini Micro because they're into retro computing, and they want to really lean into that retro look. Early home computers typically had a resolution around 320 x 200 pixels, at which scale you can really see the pixels. If you love pixel art, that's exactly what you want.

So, in this post, we'll explore how best to set up such a lower-resolution display in Mini Micro.

Scaling a PixelDisplay

The easiest (and also most retro-authentic) thing you can do is to simply scale up any PixelDisplay you use. If you scale it by a factor of 3, then the effective resolution is 320 x 213, very close to the classic 320 x 200.

Screen shot showing display with scale = 3

Source code for the above demo
clear
gfx.scale = 3
gfx.drawEllipse 0, 0, 320, 213, color.silver
gfx.line 0, 0, 320, 213, color.blue
gfx.line 0, 213, 320, 0, color.blue
gfx.print "gfx.scale = 3", 5, 5
img = file.loadImage("/sys/pics/tank.png")
gfx.drawImage img, 200, 100
key.get
Enter fullscreen mode Exit fullscreen mode

The pixels don't even have to be square! For example, if you're porting some old Applesoft BASIC program that used low-res (48 columns by 40 rows) graphics, you can do that by using a scale of [960/40, 640/48].

Screen shot showing low-res 48x40 display

Source code for the above demo
clear
gfx.scale = [960/40, 640/48]
gfx.drawEllipse 0, 0, 40, 48, color.silver
gfx.line 0, 0, 40, 48, color.blue
gfx.line 0, 48, 40, 0, color.blue
gfx.print "low", 7, 25, color.green, "small"
gfx.print "res", 7, 4, color.green, "small"
key.get
Enter fullscreen mode Exit fullscreen mode

Scaling a TileDisplay

It's just as easy to scale a TileDisplay; you simply set the cellSize (which is how big each cell of the display appears on-screen) to some multiple of tileSetTileSize (which is how big the tiles are in the tile set image).

Screen shot of tile display scaled by a factor of 6

Source code for the above demo
clear
display(5).mode = displayMode.tile
td = display(5)
td.tileSet = file.loadImage("/sys/pics/1bitTiles.png")
td.tileSetTileSize = 16
td.cellSize = 16*6
ROWS = 640/td.cellSize
COLS = 960/td.cellSize
td.clear 5
td.setCellTint range(0,COLS), range(0,ROWS), color.green
td.setCell 8,4, 212; td.setCellTint 8,4, color.brown
td.setCell 8,5, 180; td.setCellTint 8,5, color.lime
td.setCell 5,3, 27;  td.setCellTint 5,3, color.silver
td.setCell 2,4, 184; td.setCellTint 2,4, color.red
for y in range(0,ROWS)
    td.setCell 6,y, 172; td.setCellTint 6,y, color.blue
end for
td.setCell 6,2, 166; td.setCellTint 6,2, color.brown
key.get
Enter fullscreen mode Exit fullscreen mode

Scaling Sprites

Sprites in Mini Micro are easily scaled, individually (just assign a number to the scale property). And this scaling works in a pixel-precise manner — no blurring or interpolation — which is just what you want for pixel graphics.

Unfortunately, you currently can't scale the entire SpriteDisplay at once. That means that it's up to your code to not only scale the sprites, but position them in even multiples of your scaling factor.

But you can make this relatively painless by defining a Sprite subclass that does the conversion from world (low-res) to screen (high-res) positions for you, like so:

ScaledSprite = new Sprite
ScaledSprite.wx = 0  // "world x"
ScaledSprite.wy = 0  // "world y"
ScaledSprite.update = function
    self.x = round(self.wx) * self.scale
    self.y = round(self.wy) * self.scale
end function
Enter fullscreen mode Exit fullscreen mode

Animated screen shot of scaled sprite

Source code for the above demo
clear
gfx.scale = 6
for i in range(1000)
    c = color.rgb(50*rnd, 50*rnd, 100+150*rnd)
    gfx.setPixel 160*rnd, 106*rnd, c
end for

sprDisp = display(4) // sprite display
oneBitImage = file.loadImage("/sys/pics/1bitTiles.png")
guy = oneBitImage.getImage(336, 352, 16, 16)

ScaledSprite = new Sprite
ScaledSprite.wx = 0  // "world x"
ScaledSprite.wy = 0  // "world y"
ScaledSprite.update = function
    self.x = round(self.wx) * self.scale
    self.y = round(self.wy) * self.scale
end function

sp = new ScaledSprite
sp.scale = 6
sp.image = guy
sp.tint = "#FFFFAA"
sp.wx = 80; sp.wy = 50
sprDisp.sprites.push sp
while true
    sp.wx += 1
    sp.wy = 80 + 5 * sin(sp.wx/5)
    sp.update
    wait 0.25
end while
Enter fullscreen mode Exit fullscreen mode

Conclusion

Now that you know all the tricks for getting nice chunky graphics in Mini Micro, you can create any low-resolution retro-style pixel-art masterpiece you can imagine. What will you create?

Top comments (0)