Using Löve2d's SpriteBatch

I keep forgetting how to use SpriteBatch, so I wrote a short snippet to remind myself and anyone else interested in Löve2d.

function love.load()
  -- Load our image we want to draw many times
  image ="dirt.png")

  -- The number of tiles we want to draw is pretty much the number
  -- that will fit on the screen
  maxX = math.ceil(  / image:getWidth())  + 2
  maxY = math.ceil( / image:getHeight()) + 2
  local size = maxX * maxY

  -- Set up a sprite batch with our single image and the max number of times we
  -- want to be able to draw it. Later we will call spriteBatch:add() to tell
  -- Love where we want to draw our image
  spriteBatch =, size)

function love.update(dt)
  -- If we were using a moving background, we would want to only call
  -- setupSpriteBatch when its range or position changed

function setupSpriteBatch()

  -- Set up (but don't draw) our images in a grid
  for y = 0, maxY do
    for x = 0, maxX do
      -- Convert our x/y grid references to x/y pixel coordinates
      local xPos = x * image:getWidth()
      local yPos = y * image:getHeight()

      -- Add the image we previously set to this point
      spriteBatch:add(xPos, yPos)

function love.draw()
  -- Draw the spriteBatch with only one call!,255,255)

  -- Draw FPS in the bottom right corner,0,0),,

For a more advanced example using Quads, check out Efficient Tile-based Scrolling.

Subclassing Löve2d's HardonCollider Shapes

This took me way too long to get my head around, but here is how to subclass HardonCollider shapes.

To add these to the spatial hash that HC uses to track objects, I had to mess with HardonCollider's init.lua.


-- Add this line to the main hardoncollider/init.lua file around line 136
-- to allow you to add preconstructed shapes.
function HC:addExistingShape(shape)
  return new_shape(self, shape)


Sprite = require("sprite")

function love.load()
  -- Effectively Sprite:new(x, y, width, height)
  mySprite = common.instance(Sprite, 200, 200, 50, 200)

function love.draw()
  -- center() is from ConvexPolygonShape
  local x, y = mySprite:center()
  -- Run our custom method, x, y)

  -- Implemented by ConvexPolygonShape


-- Have to require HC because it sets up the class stuff
HC = require("hardoncollider")

Shapes = require("hardoncollider.shapes")
Polygon = require("hardoncollider.polygon")

local Sprite = {}
function Sprite:init(x, y, width, height)
  -- ConvexPolygonShape requires an instance of Polygon
  -- set up a square with our size. Could be set based on the image
  -- in our sprite
  local polygon = common.instance(Polygon,
    x - width/2, y - height/2,
    x + width/2, y - height/2,
    x + width/2, y + height/2,
    x - width/2, y + height/2)

  -- Run our parent's constructor
	Shapes.ConvexPolygonShape.init(self, polygon)

  self.bacon = 42

function Sprite:hello()
  return "Hey, bacon is currently " .. self.bacon

Sprite = common.class("Sprite", Sprite, Shapes.ConvexPolygonShape)
return Sprite

Drawing a Textured Polygon in Löve2d

Löve2d makes a lot of stuff super-easy, but I found rendering a polygon with a texture is a bit tricky. Here’s how to do it.

▲ The final product.

I modified a dirt texture is from PixelJoint and erased some bits, just to show the transparency works.

▲ Semitransparent tiling dirt texture.


function love.load()
  -- Load our repeating texture
  local img      ="dirt.png")

  -- Points for our polygon
  local vertices = {12,0, 396,7, 500,375, 195,520, 78,377}
  texturedPoly = newTexturedPoly(vertices, img)

function newTexturedPoly(vertices, img)
  -- We want our images to tile
  img:setWrap("repeat", "repeat")

  -- We need a quad so the img is repeated
  -- The quad width/height should be the max x/y of the poly
  local quad =, 0, 500, 520, img:getWidth(), img:getHeight())

  -- Set up and store our clipped canvas once as it's expensive
  local canvas =

  -- Our clipping function, we want to render within a polygon shape
  local myStencilFunction = function()"fill", unpack(vertices))
  -- Setting to premultiplied means that pixels just get overlaid ignoring
  -- their alpha values. Then when we render this canvas object itself, we
  -- will use the alpha of the canvas itself"premultiplied")

  -- Draw the repeating image within the quad, quad, 0, 0)

  -- Reset everything back to normal"alpha")
  return canvas

function love.draw()
  -- Draw our canvas object texturedPoly, 50, 50)

  -- showfps,255,255,200),,

If you have any feedback then message me on Twitter.

Typography Presentation

I made a short presentation on typography (20mb) based on what I’d learned reading Detail in Typography. What little text there is, is in a mixture of Japanese and English.

Parsing Wiki Text (Part 2)

More on parsing Wikipedia markup. So you’ve abandoned the idea of using regular expressions to parse the markup, congratulations. This should save yourself from insanity and oblivion.

mwlib is a Python library for parsing Wiki markup. It seems semi-official. Whatever, it’s what we’re going to use. It can parse the zipped XML dumps as I’ve shown in previous tutorials. However you have to provide it with an ariticle name, and today we’re feeling more John Wayne.

How can we feed mwlib raw Wiki markup and get the same hierarchical deliciousness as output? Here’s how:

from mwlib.refine import compat

raw = """
Je suis le voyageur dans le baked beans.

parsed = compat.parse_txt(raw)

A more involved example:

from mwlib.refine import compat,core
from mwlib.parser import nodes
import pprint

def main():
  pp = pprint.PrettyPrinter(indent=2)

  raw = """
Modern cake, especially layer cakes, normally contain a
combination of [[flour]], [[sugar]], [[egg (food)|eggs]], and [[butter]].
This is a subheading.
Oh and another nested subheading
=Related Cakes=
* Jaffa cakes!?
* This related section is not a subsection

  # Returns raw 'token' classes that aren't much use
  #r = core.parse_txt(raw)

  ### This is the magic
  # Returns nicer classes, Paragraph, PreFormatted etc.
  parsed = compat.parse_txt(raw)
  ### Everything below here is just as an example

  f = open('test.txt', 'w')

  for section in parsed:
    recursive_parse(f, section, 0)


def recursive_parse(f, node, indent):
  tabs    = indent * "  "
  indent += 1
  print tabs + node.__class__.__name__

  if isinstance(node, nodes.Section):
    level = u"=" * node.level
    title = level + node.children[0].asText()
    title = title.rstrip()

    # Skip the text child, move onto the rest
    for child in node.children[1:]:
      recursive_parse(f, child, indent)

  elif isinstance(node, nodes.Table):
    # Don't process children
    print tabs + "Table: Skipping"

  elif isinstance(node, nodes.Text):
    txt = node.asText()
    if txt != "\n": # and re.match("^\s+$", txt) == None:

      txt = txt.rstrip('\n')
      #re.sub("\n", '', txt)

      #f.write('<text>' + txt.encode('UTF-8') + '</text>')


  if node.children is not None:
    for child in node.children:
      recursive_parse(f, child, indent)

if __name__ == '__main__':

subscribe via RSS