[
  {
    "path": "CodeCapture/CodeCapture.lua",
    "content": "local M={}\nM.KONAMI={'up','up','down','down','left','right','left','right','b','a'}\n\nlocal STATES={}\nlocal CURRSTATE\n\nlocal function setNextState(char, state)\n  if not state then \n    state=STATES\n  end\n  if not state[char] then\n    state[char]={}\n  end\n  return state[char]\nend\n\nlocal function getNextState(char, state)\n  if not state then \n    state=STATES\n  end\n  return state[char]\nend\n\nfunction M.setCode(c, fn)\n  if type(c)=='string' then\n    local c2={}\n    for char in c:gmatch('.') do c2[#c2+1]=char end\n    c=c2\n  end\n  local st\n  for k,v in ipairs(c) do\n    st=setNextState(v, st)\n  end\n  st.done=fn\nend\n\nfunction M.keypressed(a)\n  CURRSTATE=getNextState(a, CURRSTATE)\n  if CURRSTATE then\n    if CURRSTATE.done then\n      CURRSTATE.done()\n      CURRSTATE=nil\n    else\n      --tracking...\n    end\n  else\n    -- start from beginning\n    CURRSTATE=getNextState(a)\n  end\nend\n\nreturn M\n\n"
  },
  {
    "path": "CodeCapture/README.md",
    "content": "CodeCapture\n===========\n\nThis sample is inspired by the [KonamiCode] thread.\n\nThis is a simple library, which can be used to register a sequence of codes (key and/or mouse pressess), ofr which the given function should be called.\n\nThe code is implemented as a simple finite state machine, so you can register many different codes at the same time, and if they share a common prefix, they also share the state.\n\nThis sample has several magic codes:\n\n  *  \"qwerty\"\n  *  \"second\"\n  *  \"secundo\"\n  *  KONAMI (UP UP DOWN DOWN LEFT RIGHT LEFT RIGHT b a)\n  *  a MOUSE-LEFT b MOUSE-RIGHT\n  *  \"quit\" and \"exit\"\n\nEach sequence causes the change of text displayed, except the last ones, which quit the program.\n\n[KonamiCode]: http://love2d.org/forums/viewtopic.php?f=5&t=2632\n\n"
  },
  {
    "path": "CodeCapture/main.lua",
    "content": "local CodeCapture=require 'CodeCapture'\n\nfunction love.load()\n  CodeCapture.setCode(\"qwerty\", function() MODE='ONE' end)\n  CodeCapture.setCode('second', function() MODE='TWO' end)\n  CodeCapture.setCode('secundo', function() MODE='DUO' end)\n  CodeCapture.setCode(CodeCapture.KONAMI, function() MODE='KONAMI' end)\n  CodeCapture.setCode({'a','mouse-l','b','mouse-r'}, function() MODE='WITH MOUSE' end)\n  CodeCapture.setCode('quit', function() love.event.quit() end)\n  CodeCapture.setCode('exit', function() love.event.quit() end)\n\n  MODE='NONE'\nend\n\nfunction love.draw()\n  love.graphics.print(MODE, 10, 10)\nend\n\nfunction love.keypressed(a,b)\n  CodeCapture.keypressed(a)\nend\n\nfunction love.mousepressed(x,y,b)\n  CodeCapture.keypressed('mouse-'..b)\nend\n\n"
  },
  {
    "path": "CollisionExample/README.md",
    "content": "Collision example\n===========\n\nThis sample is inspired by the [RestrictRectangleMovement] thread.\n\nThe sample illustrates (in just one of many ways) how you can restrict movement\nof your cursor (character) to stay on screen and not go thru other obstacles.\n\nHow the collision works.\n========================\n\nEvery new frame function love.update() checks if any of the arrow keys is pressed, and if so, computes the new position of the character, keeping the old position ofr reference. Then the function checks if this new position is off-screen (by calling isOnScreen()), or if the character at this new position collides with any other object. If there is collision, then the move is not allowed, so the previously stored position is recalled, and the new position is discarded.\n\nEvery object has its position x,y and its size - width w and height. So the collision is detected when any two rectangles collide.\n\n[RestrictRectangleMovement]: http://love2d.org/forums/viewtopic.php?f=3&t=5072\n\n"
  },
  {
    "path": "CollisionExample/main.lua",
    "content": "local lg=love.graphics\nfunction love.load()\n  W, H=lg.getWidth(), lg.getHeight()\n  local w,h=40,40\n  Obstacles={}\n  for i=1,20 do\n    table.insert(Obstacles, {x=math.random(W-w), y=math.random(H-h), w=w, h=h})\n  end\n  w,h=20,20\n  Cursor={x=math.random(W-w), y=math.random(H-h), w=w, h=h}\n  while isColliding() do\n    Cursor.x, Cursor.y=math.random(W-w), math.random(H-h)\n  end\n  collision=false\nend\n\nfunction love.draw()\n  lg.setColor(255,0,0,255)\n  for k,v in ipairs(Obstacles) do\n    lg.rectangle('fill', v.x, v.y, v.w, v.h)\n  end\n  lg.setColor(0, 255,0,255)\n  lg.rectangle('fill', Cursor.x, Cursor.y, Cursor.w, Cursor.h)\n  lg.setColor(255, 255,255,255)\n  if collision then\n    lg.print('COLLISION!!!', W/2, 0)\n  end\n\nend\n\nlocal isDown=love.keyboard.isDown\nfunction love.update(dt)\n  local dx,dy=0,0\n  if isDown('right') or isDown('d') then\n    dx=1\n  elseif isDown('left') or isDown('a') then\n    dx=-1\n  elseif isDown('up') or isDown('w') then\n    dy=-1\n  elseif isDown('down') or isDown('s') then\n    dy=1\n  end\n  local currX, currY=Cursor.x, Cursor.y\n  Cursor.x, Cursor.y=Cursor.x+dx, Cursor.y+dy\n  collision=false\n  if not isOnScreen() or isColliding() then\n    Cursor.x, Cursor.y=currX, currY\n    collision=true\n  end\nend\n\nfunction isOnScreen()\n  if Cursor.x>0 and Cursor.x+Cursor.w<W and\n     Cursor.y>0 and Cursor.y+Cursor.h<H then\n    return true\n  else\n    return false\n  end\nend\n\nfunction isCollidingWith(obj)\n  local ox, oy=obj.x-Cursor.x, obj.y-Cursor.y -- let's pretent Cursor is at (0,0)\n  if ox+obj.w<0 or oy+obj.h<0 or\n    ox>Cursor.w or oy>Cursor.h then\n    return false\n  else\n    return true\n  end\nend\n\nfunction isColliding()\n  for k,v in ipairs(Obstacles) do\n    if isCollidingWith(v) then\n      return true\n    end\n  end\n  return false\nend\n"
  },
  {
    "path": "Fireworks/Firework.lua",
    "content": "require 'class'\nlocal Vector=require 'Vector'\nlocal Particle=require 'Particle'\nSTATE={ROCKET=1, EXPLODE=2, LIVE=3, DEAD=4}\n\nlocal M=class(function(self, x, y)\n  self.Position=Vector(x, y)\n  self.state=STATE.ROCKET\n  self.Particles={}\n  self.numParticles=math.random(150, 450)\n  self.elapsed=0\n  self.R=math.random(50, 255)\n  self.G=math.random(50, 255)\n  self.B=math.random(50, 255)\n  self.StartPosition=Vector(math.random(0, love.graphics.getWidth()), love.graphics.getHeight())\n  self.elapsed=0\n  self.livetime=math.random(3,20)/10\nend)\n\nfunction M:update(dt)\n  self.elapsed=self.elapsed+dt\n  local state=self.state\n  if state==STATE.LIVE or state==STATE.EXPLODE then\n    if state==STATE.EXPLODE then\n      for i=1,math.random(50,120) do\n        self:addParticle(self.Position.x, self.Position.y)\n      end\n      if #self.Particles>= self.numParticles then\n        self.state=STATE.LIVE\n      end\n    end\n\n    for k=#self.Particles,1,-1 do\n     local p=self.Particles[k]\n     if p:isDead() then\n       table.remove(self.Particles, k) \n     else\n       p:update(dt)\n     end\n    end\n    if state==STATE.LIVE and #self.Particles==0 then\n      self.state=STATE.DEAD\n    end\n  elseif state==STATE.DEAD then\n    return\n  elseif state==STATE.ROCKET then\n    local pct=self.elapsed/self.livetime*100\n    if pct>=100 then\n      self.elapsed=0\n      self.state=STATE.EXPLODE\n    end\n  else\n    error('UNKNOWN STATE: '..state)\n  end\nend\n\nfunction M:draw()\n  if self.state==STATE.ROCKET then\n    local pct=self.elapsed/self.livetime\n    local d=(self.StartPosition-self.Position)*pct\n    local d2=(self.StartPosition-self.Position)*(pct+0.03)\n    local pos1=self.StartPosition-d\n    local pos2=self.StartPosition-d2\n    \n    love.graphics.setColor(self.R, self.G, self.B, 255)\n    love.graphics.setLineWidth(3)\n    love.graphics.line(pos1.x, pos1.y, pos2.x, pos2.y)\n    love.graphics.circle('fill', self.StartPosition.x, self.StartPosition.y, 10, 10)\n  else\n    for k,v in ipairs(self.Particles) do\n      v:draw()\n    end\n  end\nend\n\nfunction M:isDead()\n  return self.state==STATE.DEAD\nend\n\nfunction M:addParticle(x, y)\n  table.insert(self.Particles, Particle(x, y, self.R, self.G, self.B))\nend\n\nreturn M\n"
  },
  {
    "path": "Fireworks/FireworkEngine.lua",
    "content": "require 'class'\nFirework=require 'Firework'\n\nlocal M=class(function(self)\n  self.Fireworks={}\nend)\n\nfunction M:update(dt)\n  for k=#self.Fireworks,1,-1 do\n    local f=self.Fireworks[k]\n    if f:isDead() then\n      table.remove(self.Fireworks, k)\n    else\n      f:update(dt)\n    end\n  end\nend\n\nfunction M:draw()\n  for k,v in ipairs(self.Fireworks) do\n    v:draw()\n  end\n  love.graphics.setColor(255,255,255,255)\n  love.graphics.print('Fireworks: '..#self.Fireworks, 10, 10)\nend\n\nfunction M:addFirework(x, y)\n  table.insert(self.Fireworks, Firework(x, y))\nend\n\nreturn M\n\n"
  },
  {
    "path": "Fireworks/Particle.lua",
    "content": "require 'class'\nlocal Vector=require 'Vector'\nlocal lg=love.graphics\n\nlocal M=class(function(self, x, y, R, G, B, v)\n  self.dead=false\n  self.Position=Vector(x, y)\n  self.Velocity=Vector(math.random(10,50),0):rotate(math.random(0, 360))\n  self.elapsed=0\n  self.livetime=math.random(20,50)/10\n  self.R=R or math.random(50, 255)\n  self.G=G or math.random(50, 255)\n  self.B=B or math.random(50, 255)\n  self.variable=v or 'R'\n  self[self.variable]=math.random(50, 255)\nend)\n\nfunction M:update(dt)\n  self.elapsed=self.elapsed+dt\n  self.Position=self.Position+self.Velocity*dt\n  self.Velocity=self.Velocity+Vector(0,50)*dt\n  if self.elapsed>=self.livetime then\n    self.dead=true\n  end\nend\n\nfunction M:isDead()\n  return self.dead\nend\n\nfunction M:draw()\n  local alpha=math.ceil(255-255*(self.elapsed/self.livetime))\n  if alpha<0 then alpha=0 end\n  lg.setColor(self.R, self.G, self.B, alpha)\n  lg.circle('fill', self.Position.x, self.Position.y, 2, 7)\nend\nreturn M\n\n"
  },
  {
    "path": "Fireworks/README.md",
    "content": "Fireworks example\n==============\n\nThis is an example of fireworks, inspired by the [facepunch] thread, which is mentioned in [love2d] forum.\n\nNothing complicated here, just keep clicking with lefto mouse button.\n\n[love2d]: http://love2d.org/forums/viewtopic.php?f=3&t=3909\n[facepunch]: http://www.facepunch.com/threads/1136691\n\n"
  },
  {
    "path": "Fireworks/Vector.lua",
    "content": "require 'class'\n\nlocal M=class(function(self, x, y)\n  self.x=x or 0\n  self.y=y or 0\nend)\n\nfunction M:isVector()\n  return getmetatable(self)==M\nend\n\nfunction M:__add(v)\n  return M(self.x+v.x, self.y+v.y)\nend\n\nfunction M:__sub(v)\n  return M(self.x-v.x, self.y-v.y)\nend\n\nfunction M:__mul(m)\n  if type(self)=='number' and M.isVector(m) then\n    self, m=m, self\n  end\n  if type(m)=='number' then\n    return M(self.x*m, self.y*m)\n  else\n    return self.x*m.x+self.y*m.y\n  end\nend\n\nfunction M:len()\n  return (self*self)^0.5\nend\n\nfunction M:rotate(phi)\n  phi=math.rad(phi)\n  local c, s = math.cos(phi), math.sin(phi)\n  self.x, self.y = c * self.x - s * self.y, s * self.x + c * self.y\n  return self\nend\n\n\nfunction M:__tostring()\n  return string.format('<%s,%s>', self.x, self.y)\nend\n\nreturn M\n"
  },
  {
    "path": "Fireworks/class.lua",
    "content": "--[[\n-- $Id: class.lua 10 2008-07-01 22:18:32Z basique $\n-- Simple class implementation\n-- Taken from http://lua-users.org/wiki/SimpleLuaClasses\n-- Original author unknown\n--]]\n\n\nfunction class(base,ctor)\n  local c = {}     -- a new class instance\n  if not ctor and type(base) == 'function' then\n      ctor = base\n      base = nil\n  elseif type(base) == 'table' then\n   -- our new class is a shallow copy of the base class!\n      for i,v in pairs(base) do\n          c[i] = v\n      end\n      c._base = base\n  end\n  -- the class will be the metatable for all its objects,\n  -- and they will look up their methods in it.\n  c.__index = c\n\n  -- expose a ctor which can be called by <classname>(<args>)\n  local mt = {}\n  mt.__call = function(class_tbl,...)\n    local obj = {}\n    setmetatable(obj,c)\n\tif ctor then\n       ctor(obj,...)\n    else\n    -- make sure that any stuff from the base class is initialized!\n       if base and base.init then\n         base.init(obj,...)\n       end\n    end\n    return obj\n  end\n  c.init = ctor\n  c.is_a = function(self,klass)\n      local m = getmetatable(self)\n      while m do\n         if m == klass then return true end\n         m = m._base\n      end\n      return false\n    end\n  setmetatable(c,mt)\n  return c\nend\n"
  },
  {
    "path": "Fireworks/main.lua",
    "content": "FireworkEngine=require 'FireworkEngine'\nfunction love.load()\n  FE=FireworkEngine()\n  love.graphics.setBlendMode('additive')\nend\n\nfunction  love.update(dt)\n  FE:update(dt)\nend\n\nfunction love.draw()\n  FE:draw()\nend\n\nfunction love.mousepressed(x, y, b)\n  if b=='l' then\n    FE:addFirework(x, y)\n  end\nend\n\nfunction love.keypressed(k)\n  if k=='q' or k=='escape' then\n    love.event.quit()\n  end\nend\n\n"
  },
  {
    "path": "GameOfLife/Readme.md",
    "content": "Game of Life\n============\n\nGame of Life inspired by [this thread](http://love2d.org/forums/viewtopic.php?f=4&t=2858)\n\nControls:\n\n    0, 1, 2 - set cell border width\n    left,right - decrease/increase no of columns\n    up, down - decrease/increase no of rows\n    +/- - increase/decrease cell size\n    n - next cell generation\n    r,space - toggle running mode\n    c - clear the table\n    x - make some random cells alive\n    q,escape - quit\n    left mouse button - toggle cell dead/alive\n    right mouse button - check the status of a cell\n\nSample screenshot:\n------------------\n\n![Screenshot](../../raw/master/GameOfLife/life.png)\n"
  },
  {
    "path": "GameOfLife/main.lua",
    "content": "-- Game of Life by miko\n-- Controls:\n-- 0, 1, 2 - set cell border width\n-- left,right - decrease/increase no of columns\n-- up, down - decrease/increase no of rows\n-- +/- - increase/decrease cell size\n-- n - next cell generation\n-- r,space - toggle running mode\n-- c - clear the table\n-- x - make some random cells alive\n-- q,escape - quit\n-- left mouse button - toggle cell dead/alive\n-- right mouse button - check the status of a cell\n\nlocal lg=love.graphics\n\nfunction love.load()\n  rows, cols=30,30\n  cellsize=20\n  lineWidth=1+1\n  elapsed=0\n  tick=0.1\n  canvas=lg.newCanvas()\n  lg.setNewFont(20)\n  status=nil\n  init()\nend\n\nfunction init()\n  CELLS={}\n  for c=1,cols do\n    CELLS[c]={}\n    for r=1,cols do\n      CELLS[c][r]=false\n    end\n  end\n  generation=1\nend\n\nfunction love.draw()\n  if not cached then\n    cached=true\n    lg.setCanvas(canvas)\n    if lineWidth>0 then\n      lg.setLineWidth(lineWidth)\n    end\n    for c=1,cols do\n      for r=1,rows do\n        local cell=CELLS[c][r]\n        if cell then\n          lg.setColor(255,0,0,255)\n        else\n          lg.setColor(0,0,0,255)\n        end\n        lg.rectangle('fill', (c-1)*cellsize, (r-1)*cellsize, cellsize, cellsize)\n        if lineWidth>0 then\n          lg.setColor(255,255,255,255)\n          lg.rectangle('line', (c-1)*cellsize, (r-1)*cellsize, cellsize, cellsize)\n        end\n      end\n    end\n    lg.setCanvas()\n  end\n  lg.setColor(255,255,255,255)\n  lg.draw(canvas, 0, 0, 0)\n  local msg=string.format(\"Cols=%d Rows=%d CellSize=%d Gen=%d %s RUNNING FPS=%d \", cols, rows, cellsize, generation, running and '' or 'NOT', love.timer.getFPS())\n  if status then msg=msg..\"\\n\"..status end\n\n  lg.setColor(0,255,0,255)\n  lg.print(msg, 0,0,0)\n  lg.setColor(0,0,255,255)\n  lg.print(msg, 1,1,0)\n  lg.setColor(255,0,0,255)\n  lg.print(msg, 2,2,0)\nend\n\nfunction mouse2cell(x, y)\n  local cx, cy=math.floor(x/cellsize), math.floor(y/cellsize)\n  if cx>=0 and cx<cols and cy>=0 and cy<rows then\n    return cy+1, cx+1\n  end\nend\n\nfunction love.update(dt)\n  if not running then return end\n  elapsed=elapsed+dt\n  if elapsed>=tick then\n    elapsed=elapsed-tick\n    nextGeneration()\n    cached=nil\n  end\nend\n\nfunction love.mousepressed(x, y, b)\n  --local cx, cy=mouse2cell(x, y)\n  local mr, mc=mouse2cell(x, y)\n  status=nil\n  if mr then\n    if b=='l' then\n      CELLS[mc][mr]=not CELLS[mc][mr] \n      status=string.format('Cell c=%d,r=%d changed to %s', mc, mr, CELLS[mc][mr] and 'ALIVE' or 'DEAD')\n    elseif b=='r' then\n      status=string.format('Cell c=%d,y=%d %s neighbours: %d', mc, mr, CELLS[mc][mr] and 'ALIVE' or 'DEAD', countNeighbours(mc, mr))\n    end\n    cached=nil\n  end\n  \nend\n\nfunction love.keypressed(a, b)\n  if a=='q' or a=='escape' then\n    love.event.push(\"q\")\n  end\n  if a=='r' or a==' ' then\n    running=not running\n  end\n  if a=='n' then\n    nextGeneration()\n    cached=nil\n  end\n  if a=='c' then\n    init()\n    cached=nil\n  end\n  if a=='1' or a=='2' or a=='0' then\n    lineWidth=tonumber(a)\n    cached=nil\n  end\n  if a=='down' then\n    rows=rows+1\n    cached=nil\n    init()\n  end\n  if a=='up' then\n    rows=rows-1\n    cached=nil\n    init()\n  end\n  if a=='right' then\n    cols=cols+1\n    cached=nil\n    init()\n  end\n  if a=='left' then\n    cols=cols-1\n    cached=nil\n    init()\n  end\n  if a=='+' or a=='=' then\n    cellsize=math.min(cellsize+1, 30)\n    cached=nil\n  end\n  if a=='-' or a=='_' then\n    cellsize=math.max(cellsize-1, 1)\n    cached=nil\n  end\n  if a=='x' then\n    for i=1,cols*rows*0.1 do\n      CELLS[math.random(1,cols)][math.random(1, rows)]=true\n    end\n    cached=nil\n  end\nend\n\nfunction countNeighbours(c, r)\n  local n=0\n  local cy=c\n  local cx=r\n  if cx>1 and cy>1 then\n    if CELLS[cy-1][cx-1] then n=n+1 end\n  end\n  if cy>1 then\n    if CELLS[cy-1][cx] then n=n+1 end\n  end\n  if cx<cols and cy>1 then\n    if CELLS[cy-1][cx+1] then n=n+1 end\n  end\n\n  if cx>1 then\n    if CELLS[cy][cx-1] then n=n+1 end\n  end\n  if cx<cols then\n      if CELLS[cy][cx+1] then n=n+1 end\n  end\n\n  if cx>1 and cy<rows then\n    if CELLS[cy+1][cx-1] then n=n+1 end\n  end\n  if cy<rows then\n    if CELLS[cy+1][cx] then n=n+1 end\n  end\n  if cx<cols and cy<rows then\n    if CELLS[cy+1][cx+1] then n=n+1 end\n  end\n  return n\nend\n\nfunction nextGeneration()\n  generation=generation+1\n  local NEWCELLS={}\n  --for c, COL in ipairs(CELLS) do\n  for c=1,cols do\n    NEWCELLS[c]={}\n    --for r, cell in ipairs(COL) do\n    for r=1, rows do\n      local cell=CELLS[c][r]\n      --local n=countNeighbours(r, c)\n      local n=countNeighbours(c, r)\n      if cell then\n        if n==2 or n==3 then\n          NEWCELLS[c][r]=true\n        else\n          NEWCELLS[c][r]=false\n        end\n      else\n        if n==3 then\n          NEWCELLS[c][r]=true\n        else\n          NEWCELLS[c][r]=false\n        end\n      end\n\n    end\n  end\n  CELLS=NEWCELLS\nend\n"
  },
  {
    "path": "LICENSE",
    "content": "All the code within this repository is licensed under the terms of the MIT license reproduced below. So it is free to use for both personal and commercial purposes.\n\n===============================================================================\n\nCopyright (C) 2011 Michal Kolodziejczyk, miko@wp.pl\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n===============================================================================\n"
  },
  {
    "path": "MikoIntroScreen/Intro.lua",
    "content": "require 'class'\n\n--love=love or {graphics={}} -- plain lua compatibility\nlocal lg=love.graphics\nif not lg.newFramebuffer then\n  lg.newFramebuffer=lg.newCanvas -- love 0.8 compatilibity\nend\n\nlocal WIDTH, HEIGHT=lg.getWidth(), lg.getHeight()\nlocal _SAVED={}\nlocal iterator\n\nlocal empty=function() end\nlocal function save()\n  for k,v in pairs({'draw', 'update', 'keypressed', 'keyreleased'}) do\n    _SAVED[v]=love[v] or empty\n  end\nend\n\nlocal function restore()\n  for k,v in pairs(_SAVED) do\n    if v==empty then\n      love[k]=nil\n    else\n      love[k]=v\n    end\n  end\nend\n\nlocal function tween(pct, sval, eval)\n  return sval+pct/100*(eval-sval)\nend\n\nlocal function srand(x, y)\n  return math.floor(math.random(x, y))\nend\n\nlocal function makeSample(len, pitch)\n  len=len or 0.1\n  pitch=pitch or 440\n  local overtime=1.5\n  local tick = love.sound.newSoundData(overtime*len * 44100, 44100, 16, 1)\n  for i = 0,len*44100*overtime do\n    local t = i / 44100\n    local sample = math.sin(t * pitch * math.pi * 2) * len\n    tick:setSample(i, sample)\n  end\n  return tick\nend\n\n                                                        \nlocal O=class(function(self, data, ctype)\n  OBJNAME=(OBJNAME or 0)+1\n  self.name=OBJNAME\n  if ctype then\n    self.ctype=ctype\n  end\n  if type(data)=='string' then\n    if not ctype then\n      self.ctype='text'\n    end\n    self.text=data or '???'\n  else\n    if not ctype then\n      self.ctype='image'\n    end\n  end\n  self.data=data\nend)\n\nfunction O:setPosition(x, y)\n  self.x, self.y=x or 0, y or 0\n  return self\nend\nfunction O:setRotation(r)\n  self.r=r or 0\n  return self\nend\nfunction O:setScale(sx, sy)\n  sx=sx or 1\n  if not sy then sy=sx end\n  self.sx, self.sy=sx, sy\n  return self\nend\nfunction O:setFont(font)\n  if type(font)=='number' then\n    font=self:getFont(font)\n  end\n  self.font=font or ''\n  return self\nend\nfunction O:setColor(r, g, b, a)\n  local color\n  if type(r)=='table' then\n    color=r\n  else\n    color={r, g, b, a}\n  end\n  self.color=color\n  return self\nend\n\nfunction O:center()\n  if self.ctype~='text' then\n    return\n  end\n  local w=self:getFont():getWidth(self.text)\n  self.x=(WIDTH-w)/2\n  return self\nend\n\nfunction O:start()\n  self._DATA={}\n  if self.ctype=='text' then\n    local font=self:getFont()\n    local rot=self.r\n    lg.setFont(font)\n    local H=font:getHeight()\n    local dw=0\n    for c in self.text:gmatch('.') do\n      local W=font:getWidth(c)\n      local o={x=self.x+dw, y=self.y, sx=srand(0, WIDTH), sy=srand(0, HEIGHT), char=c}\n      o.scolor={srand(0, 255), srand(0, 255),srand(0, 255)}\n      o.r=rot\n      o.sr=srand(0, 360*4)\n      dw=dw+W\n      o.fb=lg.newFramebuffer(W, H)\n\n      o.cx, o.cy=W/2, H/2\n      o.sSX=math.random(100)/10\n      lg.setCanvas(o.fb)\n      lg.print(c, 0, 0)\n      table.insert(self._DATA, o)\n    end\n  elseif self.ctype=='image' then\n    local o={x=self.x, y=self.y, sx=srand(0, WIDTH), sy=srand(0, HEIGHT)}\n    o.r=self.r\n    o.sr=srand(0, 360*4)\n    local W, H=self.data:getWidth(), self.data:getHeight()\n    o.cx, o.cy=W/2, H/2\n    o.sSX=math.random(100)/10\n    o.fb=self.data\n    self._DATA[1]=o\n  elseif self.ctype=='audio' then\n    love.audio.play(self.data)\n  end\nend\n\nfunction O:stop()\n  if self.ctype=='audio' then\n    love.audio.stop(self.data)\n  end\nend\n\nfunction O:getFont(size)\n  if not self.font then \n    lg.setNewFont(size) \n    self.font=lg.getFont() \n  end\n  return self.font\nend\n\nfunction O:draw(pct)\n  lg.setColor(255, 255, 255, 255)\n  local color=self.color\n  local A=tween(pct, 0, 255)\n  if self.ctype=='text' then\n    for k,v in ipairs(self._DATA) do\n      local x=tween(pct, v.sx, v.x)\n      local y=tween(pct, v.sy, v.y)\n      local scolor=v.scolor\n\n      local R=tween(pct, scolor[1], color[1])\n      local G=tween(pct, scolor[2], color[2])\n      local B=tween(pct, scolor[3], color[3])\n      local rot=tween(pct, v.sr or 0, self.r or 0)\n      local sx=tween(pct, v.sSX, 1)\n      --local sy=tween(pct, v.sSY, 1)\n      if self.hilited==k then\n        lg.setColor(255, 255, 255, 255)\n      else\n        lg.setColor(R, G, B, A)\n      end\n      lg.push()\n      lg.translate(x+v.cx, y+v.cy)\n      lg.rotate(math.rad(rot))\n      lg.translate(-v.cx, -v.cy)\n      --lg.scale(sx, sx)\n      lg.draw(v.fb, 0, 0)\n      lg.pop()\n    end\n  elseif self.ctype=='image' then\n    local v=self._DATA[1]\n    local x=tween(pct, v.sx, v.x)\n    local y=tween(pct, v.sy, v.y)\n    local scolor=v.scolor\n\n    --[[\n    local R=tween(pct, scolor[1], color[1])\n    local G=tween(pct, scolor[2], color[2])\n    local B=tween(pct, scolor[3], color[3])\n    --]]\n    local rot=tween(pct, v.sr or 0, self.r or 0)\n    local sx=tween(pct, v.sSX, 1)\n    lg.setColor(255, 255, 255, A)\n    --local sy=tween(pct, v.sSY, 1)\n    --lg.setColor(R, G, B)\n    lg.push()\n    --lg.scale(sx, sx)\n    lg.translate(x+v.cx, y+v.cy)\n    lg.rotate(math.rad(rot))\n    lg.translate(-v.cx, -v.cy)\n    lg.draw(v.fb, 0, 0)\n    lg.pop()\n  end\nend\n\nfunction O:setHilited(id)\n  self.hilited=id\nend\n\nfunction O:__tostring()\n  return string.format('<Object %s %s>', self.ctype, self.name or 'unnamed')\nend\n\nlocal Object=O\n\n--\nlocal M=class(function(self)\n  self.Objects={}\n  self:setDuration(6)\n  self:setDelay(2)\nend)\n\nfunction M:addText(txt)\n  local obj=Object(txt)\n  table.insert(self.Objects, obj)\n  return obj\nend\n\nfunction M:addImage(filename)\n  local img\n  if type(filename)=='string' then\n    img=lg.newImage(filename)\n  else\n    img=filename\n  end\n  local obj=Object(img)\n  table.insert(self.Objects, obj)\n  return obj\nend\n\nfunction M:addAudio(audio)\n  if type(audio)=='string' then\n    audio=love.audio.newSource(audio, 'static')\n  end\n  local obj=Object(audio, 'audio')\n  table.insert(self.Objects, obj)\n  return obj\nend\nfunction M:setDuration(d)\n  self.duration=d or 6\n  return self\nend\n\nfunction M:setDelay(d)\n  self.delay=d or 2\n  return self\nend\n\nfunction M:makeChaos()\n  return self\nend\n\n-- len - in seconds, just before duration\nfunction M:setBlinks(len, obj, ...)\n  if not obj then return self end\n  self.blink=len\n  self.blinkObjects=self.blinkObjects or {}\n  table.insert(self.blinkObjects, obj)\n  return self:setBlinks(len, ...)\nend\n\nfunction M:_setupBlinks()\n  local count=0\n  for k,v in pairs(self.blinkObjects) do\n    count=count+#v._DATA\n  end\n  self.blinkChars=count\n  self.blinkdt=self.blink/count\n  function self.nextCharIterator()\n    local T=self.blinkObjects\n    local objKey,obj=next(T)\n    local idxKey, idx\n    return function()\n      idxKey, idx=next(obj._DATA, idxKey)\n      if not idx then\n        objKey,obj=next(T, objKey)\n        if not obj then return end\n        idxKey, idx=next(obj._DATA, idxKey)\n      end\n      return obj, idxKey, idx\n    end\n  end\n  SAMPLES={}\n  for obj, idxk, idxo in self:nextCharIterator() do\n    local c=idxo.char:upper()\n    if not SAMPLES[c] then\n      local x=0\n      if c==' ' then\n        x=1\n      elseif c=='!' then\n        x=2\n      else\n        x=c:byte()-45 -- 49 for \"0\", 65 for \"A\"\n      end\n      SAMPLES[c]=makeSample(self.blinkdt, 2^((x-2)/12)*400)\n    end\n  end\nend\n\nfunction M:start()\n  local s=self\n  save()\n  math.randomseed(os.time())\n  love.update=function(dt) s:update(dt) end\n  love.draw=function() s:draw() end\n  love.keypressed=function(a, b) s:keypressed(a, b) end\n  self.elapsed=0\n  lg.setColor(255, 255, 255, 255)\n  for k,v in ipairs(self.Objects) do\n    v:start()\n  end\n  lg.setCanvas()\n  if self.blink then\n    self:_setupBlinks()\n  end\n  return self\nend\n\nfunction M:stop()\n  for k,v in ipairs(self.Objects) do\n    v:stop()\n  end\n  restore()\n  return self\nend\n\nfunction M:keypressed(a, b)\n  if a==' ' then\n    self.paused=not self.paused\n  else\n    self:stop()\n  end\nend\n\nfunction M:update(dt)\n  if self.paused then return end\n  self.elapsed=self.elapsed+dt\n  if self.elapsed>self.duration+self.delay then\n    self:stop()\n  elseif self.elapsed>self.duration then\n    if self.pct~=100 then\n      self.pct=100\n    end\n\n    if self.blink and self.elapsed-self.duration<=self.blink then\n      BLINKDT=(BLINKDT or 0)+dt\n      if BLINKDT>self.blinkdt then\n        BLINKDT=BLINKDT-self.blinkdt\n        if self.objHilited then\n          self.objHilited:setHilited()\n        end\n\n        --local obj=self.blinkObjects[math.random(1, #self.blinkObjects)]\n        iterator=iterator or self:nextCharIterator()\n        local obj, idxk, idxo=iterator()\n        SRC=SRC or {}\n        local src=love.audio.newSource(SAMPLES[idxo.char:upper()])\n        src:setVolume(2)\n        src:play()\n        SRC[#SRC+1]=src\n        --obj:setHilited(math.random(#obj._DATA))\n        obj:setHilited(idxk)\n        self.objHilited=obj\n      end\n    else\n      if self.objHilited then\n        self.objHilited:setHilited()\n      end\n    end\n\n    return\n  end\n  self.pct=self.elapsed/self.duration*100\nend\n\nfunction M:draw()\n  local pct=self.pct\n  if not pct then return end\n  for k,v in ipairs(self.Objects) do\n    v:draw(pct)\n  end\nend\n\nreturn M\n"
  },
  {
    "path": "MikoIntroScreen/README.md",
    "content": "LOVEJam Intro Screen\n===========\n\nThis sample is inspired by the [LOVEJam] site.\n\nThis is a splash screen intro, and also an engine, where you can easily make similar intros for yourself.\n\nThe intro consists of some linef of texts and some images and audio files. The texts will be split by letters, and the images and letters will be put randomly, then will find their way home. Also, the letters get some random colors at the beginning.\n\n\n[LOVEJam]: http://love2d.org/jam\n\n"
  },
  {
    "path": "MikoIntroScreen/class.lua",
    "content": "--[[\n-- $Id: class.lua 10 2008-07-01 22:18:32Z basique $\n-- Simple class implementation\n-- Taken from http://lua-users.org/wiki/SimpleLuaClasses\n-- Original author unknown\n--]]\n\n\nfunction class(base,ctor)\n  local c = {}     -- a new class instance\n  if not ctor and type(base) == 'function' then\n      ctor = base\n      base = nil\n  elseif type(base) == 'table' then\n   -- our new class is a shallow copy of the base class!\n      for i,v in pairs(base) do\n          c[i] = v\n      end\n      c._base = base\n  end\n  -- the class will be the metatable for all its objects,\n  -- and they will look up their methods in it.\n  c.__index = c\n\n  -- expose a ctor which can be called by <classname>(<args>)\n  local mt = {}\n  mt.__call = function(class_tbl,...)\n    local obj = {}\n    setmetatable(obj,c)\n\tif ctor then\n       ctor(obj,...)\n    else\n    -- make sure that any stuff from the base class is initialized!\n       if base and base.init then\n         base.init(obj,...)\n       end\n    end\n    return obj\n  end\n  c.init = ctor\n  c.is_a = function(self,klass)\n      local m = getmetatable(self)\n      while m do\n         if m == klass then return true end\n         m = m._base\n      end\n      return false\n    end\n  setmetatable(c,mt)\n  return c\nend\n"
  },
  {
    "path": "MikoIntroScreen/conf.lua",
    "content": "function love.conf(t)\r\n\tt.title = \"miko lovejam intro\"\r\n\tt.author = \"miko\"\r\n\tt.identity = \"mario\"\r\n\tt.screen.width = 800\r\n\tt.screen.height = 600\r\nend\r\n"
  },
  {
    "path": "MikoIntroScreen/main.lua",
    "content": "local Intro=require 'Intro'\nfunction love.load()\n  I=Intro()\n  local t1=I:addText('LoveJam Test Jam entry!'):setPosition(20, 50):setColor(0, 255, 0):setFont(60):center()\n  local t2=I:addText('Made with Love2d'):setPosition(400, 200):setColor(0, 0, 255):setFont(30)\n  local t3=I:addText('(C) 2011 miko - average Love user'):setPosition(10, 500):setColor(255,0,0):setFont(40):center()\n  I:addImage('logo.png'):setPosition(200, 180)\n  I:addImage('face-grin.png'):setPosition(400, 350)\n\n  I:addAudio('zero-project - 01 - Celtic dream.ogg')\n  I:setDuration(5)\n  I:setDelay(5)\n  I:setBlinks(2, t1, t2)\n  I:start()\nend\n\nfunction love.update(dt)\n  love.event.quit()\nend\n--[[\nfunction love.keypressed(a, b)\n  love.event.quit()\nend\n--]]\n"
  },
  {
    "path": "Minefield/conf.lua",
    "content": "function love.conf(t)\n\tt.modules.joystick = false\n\tt.modules.audio = false\n\tt.modules.keyboard = true\n\tt.modules.event = true\n\tt.modules.image = false\n\tt.modules.graphics = true\n\tt.modules.timer = true\n\tt.modules.mouse = false\n\tt.modules.sound = false\n\tt.modules.physics = false\n\tt.console = false\n\tt.title = \"Minefield\"\n\tt.author = \"MiKo\"\n\tt.screen.fullscreen = false\n\tt.screen.vsync = true\n\tt.screen.fsaa = 0\n\t--t.screen.height = 800\n\t--t.screen.width = 1024\nend\n"
  },
  {
    "path": "Minefield/main.lua",
    "content": "local lg=love.graphics\nORGWIDTH, ORGHEIGHT=lg.getWidth(), lg.getHeight()\nlocal Menu=require 'menu'\n\nfunction love.load()\n  ReplayDelay=0.2\n  lg.setBackgroundColor(255,255,255)\n  mode='menu'\n  fullscreen=false\n  diagonal=true\n  initScreen()\n  initGame()\nend\n\nfunction initScreen()\n  W, H=lg.getWidth(), lg.getHeight()\n  --CellSize=30\n  CellSize=math.floor(math.min(W/25, H/25))\n\n  CX,CY=math.floor(W/CellSize), math.floor(H/CellSize)\n  BorderWidthX=(W-(CX-2)*CellSize)/2\n  BorderWidthY=(H-(CY-2)*CellSize)/2\n  CX,CY=CX-2,CY-2\n  lg.setNewFont(CellSize)\nend\n\nfunction initGame()\n  CenterX=math.floor(CX/2)\n  PX, PY=CenterX, CY+1 -- player position\n  Bombs, Visited={}, {}\n  for x=1,CX do\n    Bombs[x]={}\n    Visited[x]={}\n  end\n  local bomblimit=math.floor(CX*CY/10)\n  for i=1,bomblimit do\n    local x,y=0,0\n    repeat\n      x, y=math.random(1, CX), math.random(1, CY)\n    until not Bombs[x][y] and not (x==CenterX and (y==1 or y==CY))\n    Bombs[x][y]=true\n  end\n  crashed=nil\n  won=nil\n  showingBombs=nil\n  History={}\n  elapsed=0\nend\n\nfunction drawCell(X, Y, Color)\n  if Color then\n    lg.setColor(Color)\n  end\n  lg.rectangle('fill', BorderWidthX+CellSize*(X-1), BorderWidthY+CellSize*(Y-1), CellSize, CellSize)\nend\n\nfunction drawPlayer(X, Y)\n  lg.setColor(255, 255, 0)\n  lg.circle('fill', BorderWidthX+CellSize*(X-0.5), BorderWidthY+CellSize*(Y-0.5), CellSize/2, CellSize)\nend\n\nfunction drawBomb(X, Y)\n  lg.circle('fill', BorderWidthX+CellSize*(X-0.5), BorderWidthY+CellSize*(Y-0.5), CellSize/4, CellSize)\nend\n\nfunction drawBorders()\n  lg.setColor(0, 0, 255)\n  lg.rectangle('fill', 0, 0, W, BorderWidthY)\n  lg.rectangle('fill', 0, H-BorderWidthY, W, BorderWidthY)\n  lg.rectangle('fill', 0, 0, BorderWidthX, H)\n  lg.rectangle('fill', W-BorderWidthX, 0, BorderWidthX, H)\n  lg.setColor(0, 255, 0)\n  drawCell(math.floor(CX/2), CY+1)\n  drawCell(math.floor(CX/2), 0)\nend\n\nfunction drawVisited()\n  lg.setColor(200, 100, 100)\n  for x=1,CX do\n    for y=1,CY do\n      if Visited[x][y] then\n        drawCell(x, y)\n      end\n    end\n  end\nend\n\nfunction countBombs()\n  local n=0\n  if diagonal then\n    for x=PX-1,PX+1 do\n      for y=PY-1,PY+1 do\n        if Bombs[x] and Bombs[x][y] then n=n+1 end\n      end\n    end\n  else\n    if Bombs[PX-1] and Bombs[PX-1][PY] then n=n+1 end\n    if Bombs[PX+1] and Bombs[PX+1][PY] then n=n+1 end\n    if Bombs[PX] and Bombs[PX][PY-1] then n=n+1 end\n    if Bombs[PX] and Bombs[PX][PY+1] then n=n+1 end\n  end\n  return n\nend\n\nfunction drawMsgs()\n  local n=countBombs()\n  lg.setColor(255, 0, 0)\n  lg.printf('Bombs: '..n, 0,0, W, 'right')\n  lg.printf(string.format('Time: %d s', elapsed), 0,0, W, 'left')\n  if replaying then\n    lg.printf('Replaying...', 0, H/2, W, 'center')\n  else\n    if crashed then\n      lg.printf('Bum!\\n\\nPress SPACE to play again, R for replay, M for menu', 0, H/2, W, 'center')\n    end\n    if won then\n      lg.printf('Congratulations! You win in '..math.floor(elapsed)..' seconds!\\n\\nPress SPACE to play again, R for replay, M for menu', 0, H/2, W, 'center')\n    end\n  end\nend\n\nfunction drawBombs()\n  lg.setColor(0, 0, 0)\n  for x=1,CX do\n    for y=1,CY do\n      if Bombs[x][y] then\n        drawBomb(x, y)\n      end\n    end\n  end\n\nend\n\nfunction drawHelp()\n  lg.setColor(0,0,0)\n  lg.printf([[Your goal is to go from the bottom gate to the top gate of the minefield, without stepping on a mine. The counter at the top right corner shows the number of mines in all 8 neighbouring cells.\n\n  Use cursor keys/ WASD for movement, q/ESCAPE for quit.\n\n  In the menu you can change some options (screen resolution, etc).\n  \n  Press any key to return to menu, then select Play.]], W*0.2, H/5, W*0.6, 'center')\nend\n\nfunction love.draw()\n  if mode=='help' then\n    drawHelp()\n    return\n  elseif mode=='menu' then\n    Menu:draw()\n    return\n  end\n\n  drawBorders()\n  drawVisited()\n  drawPlayer(PX, PY)\n  if showingBombs then\n    drawBombs()\n  end\n  drawMsgs()\nend\n\nfunction replayGame()\n  histIndex=1\n  replaying=true\n  Visited={}\n  for x=1,CX do\n    Visited[x]={}\n  end\nend\n\nfunction love.keypressed(a, b)\n  if a=='q' or a=='escape' then\n    love.event.quit()\n  end\n  if mode=='menu' then\n    Menu:keypressed(a, b)\n    return\n  elseif mode=='help' then\n    mode='menu'\n    return\n  end\n  if a=='b' then\n    showingBombs=not showingBombs \n  end\n  if replaying then return end\n  if crashed or won then\n    if a==' ' then\n      initGame()\n    end\n    if a=='r' then\n      replayGame()\n    end\n    if a=='m' then\n      mode='menu'\n    end\n  else\n    local moved\n    if (a=='up' or a=='w') and (PY>1 or PX==CenterX) then PY=PY-1; moved=true end\n    if (a=='down' or a=='s') and PY<CY then PY=PY+1; moved=true end\n    if (a=='left' or a=='a') and PX>1 and PY<=CY then PX=PX-1; moved=true end\n    if (a=='right' or a=='d') and PX<CX and PY<=CY then PX=PX+1; moved=true end\n    if moved then\n      table.insert(History, {PX, PY})\n      if not Visited[PX][PY] then\n        Visited[PX][PY]=true\n      end\n      if Bombs[PX][PY] then\n        crashed=true\n        showingBombs=true\n      end\n      if PY==0 then\n        won=true\n        showingBombs=true\n      end\n    end\n  end\nend\n\nfunction love.update(dt)\n  if mode=='play' and not crashed and not won then\n    elapsed=elapsed+dt\n  end\n  if not replaying then return end\n  timer=(timer or 0)+dt\n  if timer>ReplayDelay then\n    timer=timer-ReplayDelay\n    local move=History[histIndex]\n    histIndex=histIndex+1\n    if not move then\n      timer=nil\n      replaying=nil\n      histIndex=nil\n    else\n      PX, PY=unpack(move)\n      Visited[PX][PY]=true\n    end\n  end\nend\n\nfunction resize(W, H)\n  lg.setMode(W, H, fullscreen , true)\n  initScreen()\nend\n\nfunction love.quit()\n  fullscreen=false\n  resize(ORGWIDTH, ORGHEIGHT)\nend\n\n"
  },
  {
    "path": "Minefield/menu.lua",
    "content": "local lg=love.graphics\nlocal Options={\n  {name='play', title='Play the game!'},\n  {name='help', title='Help'},\n  {name='diagonal', title='Check diagonal positions?', options={'YES','NO'}, value='YES'},\n  --{name='resolution', title='Screen resolution', options={'1280x1024', '1024x800', '800x600', '640x480', '320x240', '256x192'}, value='1024x800'},\n  {name='resolution', title='Screen resolution', options={}, value=nil},\n  {name='fullscreen', title='Fullscreen', options={'YES', 'NO'}, value='NO'},\n  {name='quit', title='Quit'}\n}\n \nlocal modes=lg.getModes()\nfor k,v in ipairs(modes) do\n  Options[4].options[k]=v.width..'x'..v.height\n  if v.width==ORGWIDTH and v.height==ORGHEIGHT then\n    Options[4].value=Options[4].options[k]\n  end\nend\ntable.insert(Options[4].options, '256x192')\nif not Options[4].value then\n  Options[4].value=Options[4].options[1]\nend\nlocal Menu={\n  currentOption=1\n}\n\n\nfunction Menu:draw()\n  for k,v in ipairs(Options) do\n    if k==self.currentOption then\n      lg.setColor(50,50,255)\n    else\n      lg.setColor(50,50,50)\n    end\n    if v.value then\n      lg.printf(string.format('%s [%s]', v.title, v.value), 0, (2+k)*CellSize*2, W, 'center')\n    else\n      lg.printf(v.title, 0, (2+k)*CellSize*2, W, 'center')\n    end\n  end\nend\n\nfunction Menu:keypressed(a, b)\n  if a=='up' or a=='w' then\n    self.currentOption=self.currentOption-1\n    if self.currentOption==0 then self.currentOption=#Options end\n    return\n  elseif a=='down' or a=='s' then\n    self.currentOption=self.currentOption+1\n    if self.currentOption>#Options then self.currentOption=1 end\n    return\n  elseif a=='enter' or a=='return' then\n    self:onSelect(Options[self.currentOption].name)\n  end\n  local o=Options[self.currentOption]\n  if o.options then\n    local idx, previdx\n    for k,v in ipairs(o.options) do\n      if v==o.value then\n        idx=k\n        previdx=k\n        break\n      end\n    end\n    if a=='right' or a=='d' then\n      idx=idx+1\n      if idx>#o.options then idx=1 end\n    elseif a=='left' or a=='a' then\n      idx=idx-1\n      if idx<1 then idx=#o.options end\n    end\n    if previdx~=idx then\n      o.value=o.options[idx]\n      self:onChange(o.name, o.value)\n    end\n  else\n    if a=='right' or a=='left' or a=='d' or a=='a' then\n      self:onSelect(o.name)\n    end\n  end\nend\n\nfunction Menu:onChange(k, v)\n  if k=='resolution' then\n    local w, h=v:match('(%d+)x(%d+)')\n    resize(w, h)\n  end\n  if k=='fullscreen' then\n    if v=='YES' then\n      fullscreen=true\n    else\n      fullscreen=false\n    end\n    resize(W, H)\n  end\n  if k=='diagonal' then\n    if v=='YES' then\n      diagonal=true\n    else\n      diagonal=false\n    end\n  end\nend\nfunction Menu:onSelect(k)\n  if k=='quit' then\n    love.event.quit()\n  elseif k=='play' then\n    mode='play'\n    initGame()\n  elseif k=='help' then\n    mode='help'\n  end\nend\nreturn Menu\n\n"
  },
  {
    "path": "Obey/B.lua",
    "content": "local Char=require('Char')\nlocal lg=love.graphics\n\nlocal M=class(Char, function(self, W, H)\n  Char.init(self, 'B', W, H)\n  self.color={0, 255,0,255}\n  local P={}\n  local p=5\n  for i=-90, 90, p do\n    P[#P+1]=W*math.cos(math.rad(i))\n    P[#P+1]=H*0.3*math.sin(math.rad(i))\n  end\n  self.POINTS=P\nend)\n\nfunction M:_draw()\n  lg.setColor(self.color)\n  lg.translate(-self.W/2, -self.H/5)\n  lg.polygon('fill', self.POINTS)\n  lg.translate(0, 2*self.H/5)\n  lg.polygon('fill', self.POINTS)\n  lg.translate(self.W/2, -self.H/5)\n  lg.setColor(0, 0, 0, 255)\n  lg.circle('fill', 0.6*self.W/2, -0.6*self.H/3, self.H/15)\n  lg.circle('fill', 0.6*self.W/2, 0.6*self.H/3, self.H/15)\nend\n\nreturn M\n"
  },
  {
    "path": "Obey/Char.lua",
    "content": "require 'class'\nlocal lg=love.graphics\n\nlocal M=class(function(self, name, W, H)\n  self.W, self.H=W, H\n  self.position={0,0}\n  self.rotation=0\n  self._scale={1,1}\n  self.name=name or 'unnamed'\nend)\n\nfunction M:draw()\n  lg.push()\n  lg.translate(self.position[1], self.position[2])\n  lg.rotate(math.rad(self.rotation))\n  lg.scale(self._scale[1], self._scale[2])\n  --predraw\n  if self._draw then\n    self:_draw()\n  end\n  --postdraw\n  lg.pop()\nend\n\nfunction M:setPosition(x, y)\n  self.position={x, y}\n  return self\nend\nfunction M:setScale(sx, sy)\n  self._scale={sx, sy or sx}\n  return self\nend\nfunction M:setRotation(r)\n  self.rotation=r\n  return self\nend\n\nfunction M:rotate(dr)\n  local newrotation=self.rotation+dr\n  if self.animated then\n    self._startRotation=self.rotation\n    self._endRotation=newrotation\n  else\n    self.rotation=newrotation\n  end\n  return self\nend\n\nfunction M:move(dx, dy)\n  local newposition={self.position[1]+dx, self.position[2]+dy}\n  if self.animated then\n    self._startPosition=self.position\n    self._endPosition=newposition\n  else\n    self.position=newposition\n  end\n  return self\nend\nfunction M:scale(dsx, dsy)\n  dsy=dsy or dsx\n  local newscalex=self._scale[1]*dsx\n  local newscaley=self._scale[2]*dsy\n  if self.animated then\n    self._startScale=self._scale\n    self._endScale={newscalex, newscaley}\n  else\n    self._scale={newscalex, newscaley}\n  end\n  return self\nend\n\nfunction M:setAnimation(duration)\n  if not duration then\n    self.animated=nil\n  else\n    self.animated=true\n    self.duration=duration\n    self._startPosition=self.position\n    self._endPosition=self.position\n    self._startRotation=self.rotation\n    self._endRotation=self.rotation\n    self._startScale=self.scale\n    self._endScale=self.scale\n  end\n  return self\nend\n\nfunction M:update(dt)\n  if not self.animated then return end\n  if not self._elapsed then\n    self._elapsed=0\n  else\n    self._elapsed=self._elapsed+dt\n  end\n  if self._elapsed>=self.duration then\n    self.animated=nil\n    self._scale=self._endScale\n    self.position=self._endPosition\n    self.rotation=self._endRotation \n    self:onAnimationFinished()\n  else\n    local pct=self._elapsed/self.duration\n    self.rotation=self._startRotation*(1-pct)+self._endRotation*pct\n    self._scale={\n      self._startScale[1]*(1-pct)+self._endScale[1]*pct,\n      self._startScale[2]*(1-pct)+self._endScale[2]*pct\n    }\n    self.position={\n      self._startPosition[1]*(1-pct)+self._endPosition[1]*pct,\n      self._startPosition[2]*(1-pct)+self._endPosition[2]*pct\n    }\n  end\nend\n\nfunction M:onAnimationFinished()\nend\nreturn M\n"
  },
  {
    "path": "Obey/E.lua",
    "content": "local Char=require('Char')\nlocal lg=love.graphics\n\nlocal M=class(Char, function(self, W, H)\n  Char.init(self, 'E', W, H)\n  self.color={0, 0, 255,255}\nend)\n\nfunction M:_draw()\n  lg.setColor(self.color)\n  local H2=self.H/2\n  local W2=self.W/2\n  local w=math.min(self.W/10, self.H/10)\n  lg.setLineWidth(2*w)\n  lg.line(W2,-H2+w, -W2+w,-H2+w, -W2+w,0, W2,0, -W2+w,0, -W2+w,H2-w, W2,H2-w)\nend\n\nreturn M\n"
  },
  {
    "path": "Obey/O.lua",
    "content": "local Char=require('Char')\nlocal lg=love.graphics\n\nlocal M=class(Char, function(self, W, H)\n  Char.init(self, 'O', W, H)\n  self.color={255,255,0,255}\n  self.dx=1.1*self.W/2*math.cos(math.rad(45))\n  self.dy=-1.1*self.H/2*math.sin(math.rad(45))\nend)\n\nfunction M:_draw()\n  lg.setColor(self.color)\n  lg.circle('fill', 0, 0, self.W/2, self.W/2 )\n  lg.circle('fill', self.dx, self.dy, 0.1*self.W, self.W/2 )\n  lg.circle('fill', -self.dx, self.dy, 0.1*self.W, self.W/2 )\nend\n\nreturn M\n"
  },
  {
    "path": "Obey/README.md",
    "content": "Obeying avatar\n===========\n\nThis sample is inspired by the [AngryLovers] thread.\n\nIt creates an avatar animation. The key here is to [obey].\n\n\n[AngryLovers]: http://love2d.org/forums/viewtopic.php?f=5&t=4573\n[obey]: http://love2d.org/forums/viewtopic.php?f=3&t=9\n\n"
  },
  {
    "path": "Obey/Y.lua",
    "content": "local Char=require('Char')\nlocal lg=love.graphics\n\nlocal M=class(Char, function(self, W, H)\n  Char.init(self, 'Y', W, H)\n  self.color={0,0,255, 255}\nend)\n\nfunction M:_draw()\n  lg.setColor(self.color)\n  local W2=self.W/2\n  local H2=self.H/2\n  local w=math.min(self.W/10, self.H/10)\n  lg.setLineWidth(2*w)\n  lg.line(-W2,-H2, 0,0, 0,H2, 0,0, W2,-H2)\nend\n\nreturn M\n"
  },
  {
    "path": "Obey/class.lua",
    "content": "--[[\n-- $Id: class.lua 10 2008-07-01 22:18:32Z basique $\n-- Simple class implementation\n-- Taken from http://lua-users.org/wiki/SimpleLuaClasses\n-- Original author unknown\n--]]\n\n\nfunction class(base,ctor)\n  local c = {}     -- a new class instance\n  if not ctor and type(base) == 'function' then\n      ctor = base\n      base = nil\n  elseif type(base) == 'table' then\n   -- our new class is a shallow copy of the base class!\n      for i,v in pairs(base) do\n          c[i] = v\n      end\n      c._base = base\n  end\n  -- the class will be the metatable for all its objects,\n  -- and they will look up their methods in it.\n  c.__index = c\n\n  -- expose a ctor which can be called by <classname>(<args>)\n  local mt = {}\n  mt.__call = function(class_tbl,...)\n    local obj = {}\n    setmetatable(obj,c)\n\tif ctor then\n       ctor(obj,...)\n    else\n    -- make sure that any stuff from the base class is initialized!\n       if base and base.init then\n         base.init(obj,...)\n       end\n    end\n    return obj\n  end\n  c.init = ctor\n  c.is_a = function(self,klass)\n      local m = getmetatable(self)\n      while m do\n         if m == klass then return true end\n         m = m._base\n      end\n      return false\n    end\n  setmetatable(c,mt)\n  return c\nend\n"
  },
  {
    "path": "Obey/main.lua",
    "content": "if type(love._version)~='string' then\n  error('love 0.8+ required!')\nend\n\nlocal lg=love.graphics\n--W,H=512, 512\nW,H=90,90\n\nlocal O=require 'O'(W, H):setPosition(W/4, H/4):setScale(0.5)\nlocal B=require 'B'(W, H):setPosition(3*W/4, H/4):setScale(0.5)\nlocal E=require 'E'(W, H):setPosition(W/4, 3*H/4):setScale(0.5)\nlocal Y=require 'Y'(W, H):setPosition(3*W/4, 3*H/4):setScale(0.5)\n\nlocal time=3\n\nif false then\n  -- RECTANGLE\n  O:setAnimation(time):move(W/4,0.9*-H/10):scale(2,0.6)\n  B:setAnimation(time):rotate(-90):scale(0.4, 1.6):move(-W/4, -H/8)\n  E:setAnimation(time):move(W/4,H/10):rotate(90):scale(1,2)\n  Y:setAnimation(time):move(-W/4,-H/4):scale(2,0.8)\nelse --CIRCLE\n  O:setAnimation(time):move(W/4,0.8*-H/10):scale(0.8, 0.7)\n  B:setAnimation(time):rotate(-90):scale(0.4,0.7):move(-W/4, -H/8)\n  E:setAnimation(time):move(W/4,H/10):rotate(90):scale(1)\n  Y:setAnimation(time):move(-W/4,-H/4):scale(0.8)\nend\n\nfunction Y:onAnimationFinished()\n  local scr=lg.newScreenshot():encode('miko.png')\nend\n\nfunction love.load()\n  lg.setMode(W, H)\n  Chars={O, B, E, Y}\nend\n\nfunction love.draw()\n  for k,v in ipairs(Chars) do\n    v:draw()\n  end\nend\nfunction love.update(dt)\n  for k,v in ipairs(Chars) do\n    v:update(dt)\n  end\nend\n\n"
  },
  {
    "path": "README.md",
    "content": "Love2d samples\n==============\n\nThis is a repository for sample games and applications which I am playing with while learning [love2d][love2d] platform. Some of those are inspired by forum posts, the others are to test some features.\n\n[love2d]: http://love2d.org/\n"
  },
  {
    "path": "SidescrollerCollision/README.md",
    "content": "Sidescroller Collision example\n===========\n\nThis sample is a follow-up to my earlier [CollisionExample]. This time this is about a sidescroller type of game, where you can only move left or right, and jump up. This collision sample is tile-based, i.e. the obstacles are represented as tile map.\n\nThe sample illustrates (in just one of many ways) how you can restrict movement\nof your cursor (character) to stay on screen and not go thru other obstacles.\n\nSo: move with LEFT/RIGHT, jump with SPACE. Toggle debug with d.\n\nHow the collision works.\n========================\n\nThere are two different cases: one for moving left/right, and another one for fumping up/falling down. You need to check it separately, because you want to move right/left while falling, etc.\nThe map is tile-based, but the character movement is arbitrary, so you character could occupy more than one tile - you need to check for this when looking for collisions. So first find out which tiles would be occupied, then check if any of them would collide.\nThere is another constraint of the movement - the character must stay on the map.\n\n[CollisionExample]: https://github.com/miko/Love2d-samples/tree/master/CollisionExample\n\n"
  },
  {
    "path": "SidescrollerCollision/main.lua",
    "content": "function love.load()\n  CELLSIZE=32\n  PLAYERSIZE=16\n\n  Player={x=92, y=100, G=-100, S=100, jumping=false, falling=false, Cells={}}\n  createMap()\nend\n\nfunction love.update(dt)\n  playermove(dt)\nend\n\nfunction love.draw()\n  love.graphics.setColor(255,255,255)\n  for y=1,#map do\n    for x=1,#map[y] do\n      if map[y][x] == 1 then\n        love.graphics.rectangle(\"fill\",x*CELLSIZE,y*CELLSIZE,CELLSIZE,CELLSIZE)\n      else\n        if DEBUG then\n          love.graphics.rectangle(\"line\",x*CELLSIZE,y*CELLSIZE,CELLSIZE,CELLSIZE)\n        end\n      end\n    end\n  end\n  love.graphics.setColor(255,0,0,128)\n  love.graphics.rectangle(\"fill\",Player.x,Player.y,PLAYERSIZE, PLAYERSIZE)\n  if DEBUG then\n    love.graphics.setColor(0,255,0)\n    love.graphics.print(string.format(\"Player at (%06.2f , %06.2f) jumping=%s falling=\", Player.x, Player.y, tostring(Player.jumping), tostring(Player.falling)), 50,0)\n    love.graphics.print(string.format(\"Player occupies cells(%d): %s\", #Player.Cells, table.concat(Player.Cells, ' | ')), 450,0)\n  end\nend\n\n-- is user off map?\nfunction isOffMap(x, y)\n  if x<CELLSIZE or x+PLAYERSIZE> (1+#map[1])*CELLSIZE\n   or y<CELLSIZE or y+PLAYERSIZE>(1+#map)*CELLSIZE \n  then\n    return true\n  else\n    return false\n  end\nend\n\nfunction createMap()\n  map = {\n      {0,0,0,0,0,0,0,0,0,0,},\n      {0,0,0,1,0,0,0,0,0,0,},\n      {0,0,0,0,0,0,0,0,1,0,},\n      {0,0,0,0,0,0,0,1,0,0,},\n      {0,0,0,1,0,0,0,0,0,0,},\n      {0,0,0,0,0,0,1,0,0,0,},\n      {1,1,1,1,1,1,1,1,1,1,},\n  }\nend\n\n-- which tile is that?\nfunction posToTile(x, y)\n  local tx=math.floor(x/CELLSIZE)\n  local ty=math.floor(y/CELLSIZE)\n  return tx, ty\nend\n\n-- Find out which cells are occupied by a player (check for each corner)\nfunction playerOnCells(x, y)\n  local Cells={}\n  local tx,ty=posToTile(x, y)\n  local key=tx..','..ty\n  Cells[key]=true\n  Cells[#Cells+1]=key\n\n  tx,ty=posToTile(x+PLAYERSIZE, y)\n  key=tx..','..ty\n  if not Cells[key] then\n    Cells[key]=true\n    Cells[#Cells+1]=key\n  end\n\n  tx,ty=posToTile(x+PLAYERSIZE, y+PLAYERSIZE)\n  key=tx..','..ty\n  if not Cells[key] then\n    Cells[key]=true\n    Cells[#Cells+1]=key\n  end\n\n  tx,ty=posToTile(x, y+PLAYERSIZE)\n  key=tx..','..ty\n  if not Cells[key] then\n    Cells[key]=true\n    Cells[#Cells+1]=key\n  end\n  return Cells\nend\n\nlocal isDown = love.keyboard.isDown\nfunction playermove(dt)\n  -- Moving right or left?\n  local newX, newY\n  if isDown(\"left\") then\n    newX=Player.x-Player.S*dt\n  end\n  if isDown(\"right\") then\n    newX=Player.x+Player.S*dt\n  end\n  if newX then -- trying to move to a side\n    local offmap=isOffMap(newX, Player.y)\n    local colliding=isColliding(playerOnCells(newX, Player.y))\n    if not offmap and not colliding then\n      Player.x=newX\n    end\n  end\n\n  -- jumping up or falling down\n  Player.G = Player.G + Player.S*dt\n\n  if not Player.jumping and isDown(\" \") and not Player.falling then\n    Player.jumping = true \n    Player.G = -100\n  end\n\n    -- check only for upper or lower collision\n  newY= Player.y + Player.G*dt -- always falling\n\n  local coll=isColliding(playerOnCells(Player.x, newY))\n  if coll then\n    if Player.G>=0 then -- falling down on the ground\n      Player.jumping=false\n      Player.falling=false\n    end\n    Player.G=0\n  else\n    Player.falling=true -- falling down\n  end\n\n  if not isOffMap(Player.x, newY) and not coll then\n    Player.y=newY\n  end\n  if DEBUG then\n    Player.Cells=playerOnCells(Player.x, Player.y) -- \n  end\nend\n\n-- list of tiles\nfunction isColliding(T)\n  local collision=false\n  for k,v in ipairs(T) do\n    local x,y=v:match('(%d+),(%d+)')\n    x,y=tonumber(x), tonumber(y)\n    if not map[y] or not map[y][x] then\n      collision=true -- off-map\n    elseif map[tonumber(y)][tonumber(x)] == 1 then\n      collision=true\n    end\n  end\n  return collision\nend\n\nfunction love.keypressed(k)\n  if k=='escape' then\n    love.event.quit()\n  end\n  if k=='d' then DEBUG=not DEBUG end\nend\n\n"
  },
  {
    "path": "SpriteSheet/README.md",
    "content": "SpriteSheet\n===========\n\nThis sample is inspired by the [spritesheet] thread.\n\nThis is a simple library, which can be used to create and play many animations from within one spritesheet.\n\n[spritesheet]: http://love2d.org/forums/viewtopic.php?f=4&t=3103\n\n"
  },
  {
    "path": "SpriteSheet/SpriteSheet.lua",
    "content": "local lg=love.graphics\n\nlocal Animation={}\nAnimation.__index=Animation\n\nfunction Animation.new(spritesheet)\n  local obj={parent=spritesheet, name=name, frames={}, currentFrame=0, delay=0.1, playing=true, elapsed=0}\n  return setmetatable(obj, Animation)\nend\n\nfunction Animation:draw(x, y)\n  local quad=self.frames[self.currentFrame]\n  if quad then\n    lg.drawq(self.parent.img, quad, x, y)\n  end\nend\n\nfunction Animation:update(dt)\n  if #self.frames==0 or not self.playing then return end\n  self.elapsed=self.elapsed+dt\n  if self.elapsed>=self.delay then\n    self.elapsed=self.elapsed-self.delay\n    self.currentFrame=self.currentFrame+1\n    if self.currentFrame>#self.frames then\n      self.currentFrame=1\n    end\n  end\nend\n\nfunction Animation:addFrame(col, row)\n  local parent=self.parent\n  local w,h=parent.w, parent.h\n  local quad=lg.newQuad((col-1)*w, (row-1)*h, w, h, parent.imgw, parent.imgh)\n  self.frames[#self.frames+1]=quad\n  return self\nend\n\nfunction Animation:play()\n  self.playing=true\nend\n\nfunction Animation:stop()\n  self.playing=false\n  self.currentFrame=1\n  self.elapsed=0\nend\n\nfunction Animation:pause()\n  self.playing=false\nend\n\nfunction Animation:setDelay(s)\n  self.delay=s\n  return self\nend\n\nfunction Animation:getDelay()\n  return self.delay\nend\n\nfunction Animation:isPaused()\n  return self.playing==false\nend\n  \nlocal SpriteSheet={}\nSpriteSheet.__index=SpriteSheet\n\nfunction SpriteSheet.new(img, w, h)\n  if type(img)=='string' then\n    img=lg.newImage(img)\n  end\n  local obj={img=img, w=w, h=h, Animations={}}\n  obj.imgw=img:getWidth()\n  obj.imgh=img:getHeight()\n  return setmetatable(obj, SpriteSheet)\nend\n\nfunction SpriteSheet:createAnimation(...)\n  local a=Animation.new(self)\n  return a\nend\n\nreturn SpriteSheet\n"
  },
  {
    "path": "SpriteSheet/main.lua",
    "content": "local SpriteSheet=require 'SpriteSheet'\n\nfunction love.load()\n  local img='spritesheet.png'\n  framewidth=32\n  frameheight=32\n  S=SpriteSheet.new(img, framewidth, frameheight)\n  selected=0\n  Animations={}\n  for row=1,5 do\n    local a=S:createAnimation()\n    for col=1,4 do\n      a:addFrame(col, row)\n    end\n    Animations[#Animations+1]=a\n  end\n  a=S:createAnimation()\n  for row=1,5 do\n    for col=1,4 do\n      a:addFrame(col, row)\n    end\n  end\n  Animations[#Animations+1]=a\nend\n\nfunction love.update(dt)\n  for k,v in ipairs(Animations) do v:update(dt) end\nend\n\nfunction love.draw()\n  for k,v in ipairs(Animations) do\n    v:draw(k*framewidth, 0)\n    if k==selected then\n      love.graphics.setColor(255,0,0,127)\n      love.graphics.rectangle('fill', k*framewidth,0, framewidth, frameheight)\n      love.graphics.setColor(255,255, 255,255)\n    end\n  end\n  local a=Animations[selected]\n  if a then\n    love.graphics.print(string.format(\"Animation: %d Delay: %f\", selected, a:getDelay()), 100, 100)\n  end\n    love.graphics.printf(\"Press 1..\"..#Animations..\" to select an animation. \\r\\nWhen selected, press SPACE to toggle playing, and RIGHT/LEFT to increase/decrease the delay between frames.\", 0, 150, 800)\n    \nend\n\nfunction love.keypressed(k)\n  if k=='q' or k=='escape' then\n    love.event.quit()\n  end\n  local n=tonumber(k)\n  local a=Animations[n]\n  if a then\n    selected=n\n  else\n    a=Animations[selected]\n    if a then\n      if k==\" \" then\n        if a:isPaused() then\n          a:play()\n        else\n          a:pause()\n        end    \n      elseif k==\"right\" then\n        a:setDelay(a:getDelay()-0.01)    \n      elseif k==\"left\" then\n        a:setDelay(a:getDelay()+0.01)\n      else\n        selected=0\n      end\n    else\n      selected=0\n    end    \n  end\nend\n"
  },
  {
    "path": "TexturedPolygon/README.md",
    "content": "Textured Polygon\n===========\n\nThis sample is inspired by the [TexturedPolygon] thread.\n\nGiven the texture image, it places it (multiple times) on your framebuffer (only on non-black pixels). So create your image (e.g. filled polygon) first, and then call texturize(framebuffer, texture) to get your image.\n\n[TexturedPolygon]: http://love2d.org/forums/viewtopic.php?f=4&t=3561\n\n"
  },
  {
    "path": "TexturedPolygon/main.lua",
    "content": "\n-- Parameters:\n--  target - framebuffer with black/white pixels\n--  texture - file name or imageData\n-- Returns:\n--  Image\nfunction texturize(target, texture)\n  if type(texture)=='string' then\n    texture=love.image.newImageData(texture)\n  end\n  tx, ty=texture:getWidth(), texture:getHeight()\n  local function placeTexture(x, y, r, g, b, a)\n    if r+g+b==0 then -- black\n      return 0,0,0,0\n    else -- non-black, needs a texture\n      return texture:getPixel(x%tx, y%ty)\n    end\n  end\n  local id=target:getImageData()\n  id:mapPixel(placeTexture)\n  return love.graphics.newImage(id)\nend\n\n-- make texturized polygon\nfunction makePolygon(V, texture)\n  local t=love.image.newImageData(texture)\n\n  local minX, maxX, minY, maxY\n  for n=1,#V, 2 do\n    if not minX or minX>V[n] then minX=V[n] end\n    if not maxX or maxX<V[n] then maxX=V[n] end\n    if not minY or minY>V[n+1] then minY=V[n+1] end\n    if not maxY or maxY<V[n+1] then maxY=V[n+1] end\n  end\n  local w,h=maxX-minX+1, maxY-minY+1\n  local fb\n  if love.graphics.newCanvas then -- 0.8+\n    fb=love.graphics.newCanvas(w, h)\n  else --0.7\n    fb=love.graphics.newFramebuffer(w, h)\n  end\n  love.graphics.setCanvas(fb)\n  love.graphics.setColor(255,255,255)\n  love.graphics.translate(-minX, -minY)\n  love.graphics.polygon('fill', V)\n  love.graphics.translate(minX, minY)\n  love.graphics.setCanvas()\n  return texturize(fb, texture)\nend\n\nfunction love.load()\n  local vertices={0,0, 100,0, 200,100, 100,400, 0,300, -100,200, 0,0}\n  local textures={'face-crying.png', 'face-grin.png', 'face-plain.png', 'face-sad.png', 'face-smile-big.png', 'face-smile.png', 'face-surprise.png', 'face-wink.png'}\n  Polygons={}\n  for k,v in ipairs(textures) do\n    Polygons[k]=makePolygon(vertices, v)\n  end\n  X, Y, r=200,200,0\nend\n\nfunction love.draw()\n  local idx=math.floor(5*r%#Polygons)+1\n  love.graphics.draw(Polygons[1], X-5, Y-5, 0, 1, 1, X, Y)\n  love.graphics.draw(Polygons[idx], X, Y, r, 1, 1, X, Y)\nend\n\nfunction love.update(dt)\n  r=r+dt\nend\n\n"
  },
  {
    "path": "VerbNounParser/Console.lua",
    "content": "local M={}\nlocal MT={}\nMT.__index=M\n\nfunction M.new(P)\n  local o=setmetatable({}, MT)\n  o:initialize(P)\n  return o\nend\n\nfunction M:getName()\n  return 'Console'\nend\n\nfunction M:initialize(P)\n  self.prompt='> '\n  self.line=''\n  self.data={}\n  self.w=love.graphics.getWidth()\n  self.h=200\n  self.x=0\n  self.y=love.graphics.getHeight()-self.h\n  self.showCursor=false\n  self.cursorTime=0\n  self.callback=function(msg) print('Entered: '..msg); self:addLine(msg)  end\nend\n\nfunction M:setCallback(cb)\n  self.callback=cb\nend\n\nfunction M:update(dt)\n  self.cursorTime=self.cursorTime+dt\n  if self.cursorTime>0.5 then\n    self.cursorTime=self.cursorTime-0.5\n    self.showCursor=not self.showCursor\n  end\nend\n\nfunction M:draw()\n  love.graphics.setScissor(self.x, self.y, self.w, self.h)\n  love.graphics.setColor(255,255,255,128)\n  love.graphics.rectangle('fill', self.x, self.y, self.w, self.h)\n  love.graphics.setColor(55,55,55,228)\n  --love.graphics.setLineWidth(3)\n  love.graphics.rectangle('line', self.x, self.y, self.w, self.h)\n\n  for k=1, #self.data do\n    love.graphics.print(self.data[k], self.x+5, self.y+self.h-40-(#self.data-k)*15)\n  end\n\n  local l=self.prompt..self.line\n  if self.showCursor then l=l..'_' end\n  love.graphics.print(l, self.x+5, self.y+self.h-20)\n  love.graphics.setScissor()\nend\n\nfunction M:keyPressed(k, u)\n  if k=='delete' or k=='backspace' then\n    if #self.line>0 then\n      self.line=self.line:sub(1, -2)\n    end\n  elseif k=='return' then\n    if type(self.callback)=='function' then\n      self.callback(self.line, self)\n    end\n    self.line=''\n  else\n    if u>31 then\n      if u<127 then\n        self.line=self.line..string.char(u)\n      else\n        self.line=self.line..k\n      end\n    end\n  end\nend\n\nfunction M:addLine(l)\n  if type(l)=='table' then\n    for k,v in ipairs(l) do\n      self:addLine(v)\n    end\n  else\n    table.insert(self.data, l)\n    if #self.data>8 then\n      table.remove(self.data, 1)\n    end\n  end\nend\n\nreturn M\n\n"
  },
  {
    "path": "VerbNounParser/Door.lua",
    "content": "local M={}\nlocal MT={}\nMT.__index=M\n\nfunction M.new(P)\n  local o=setmetatable({}, MT)\n  o:initialize(P)\n  return o\nend\n\nfunction M:getName()\n  return 'Door'\nend\n\nfunction M:initialize(P)\n  self.color=P.color or 'black'\n  self.open=false\n  self.x=100+math.random(500)\n  self.y=250\n  self.w=80\n  self.h=100\nend\n\nfunction M:openAction(P)\n  local found=false\n  if #P>0 then\n    -- find color\n    for k,v in ipairs(P) do\n      if v:lower()==self.color:lower() then\n        found=true\n        break\n      end\n    end\n  else\n    found=true\n  end\n  if found then\n    if not self.open then\n      self.open=true\n      return true, 'Door '..self.color..' opened'\n    else\n      return true, 'Door '..self.color..' already open!'\n    end\n  else\n    return nil, 'Not for me'\n  end\nend\n\nfunction M:closeAction(P)\n  local found=false\n  if #P>0 then\n    -- find color\n    for k,v in ipairs(P) do\n      if v:lower()==self.color:lower() then\n        found=true\n        break\n      end\n    end\n  else\n    found=true\n  end\n  if found then\n    if self.open then\n      self.open=false\n      return true, 'Door '..self.color..' closed'\n    else\n      return true, 'Door '..self.color..' already closed!'\n    end\n  else\n    return nil, 'Not for me'\n  end\nend\n\nlocal Colors={red={255,0,0}, green={0,255,0}, black={0,0,0}}\nfunction M:draw()\n  if Colors[self.color] then\n    love.graphics.setColor(Colors[self.color])\n  end\n  if self.open then\n    love.graphics.rectangle('fill', self.x, self.y, self.w/4, self.h)\n  else\n    love.graphics.rectangle('fill', self.x, self.y, self.w, self.h)\n  end\n  \nend\n\nreturn M\n"
  },
  {
    "path": "VerbNounParser/Key.lua",
    "content": "local M={}\nlocal MT={}\nMT.__index=M\n\nfunction M.new(P)\n  local o=setmetatable({}, MT)\n  o:initialize(P)\n  return o\nend\n\nfunction M:getName()\n  return 'Key'\nend\n\nfunction M:initialize(P)\n  self.taken=false\n  self.x=100+math.random(500)\n  self.y=250\nend\n\nfunction M:takeAction(P)\n  if not self.taken then\n    self.taken=true\n    return true, 'Key taken'\n  else\n    return true, 'Key already taken!'\n  end\nend\n\nfunction M:dropAction(P)\n  if self.taken then\n    self.taken=false\n    return true, 'Key dropped'\n  else\n    return true, 'Key already dropped!'\n  end\nend\n\nfunction M:draw()\n  love.graphics.setColor(0, 0, 0)\n  local x, y\n  if self.taken then\n    x, y=20, 20\n  else\n    x, y=self.x, self.y\n  end\n  love.graphics.rectangle('fill', x+10, y, 50, 20)\n  love.graphics.circle('fill', x, y+10, 20)\nend\n\nreturn M\n"
  },
  {
    "path": "VerbNounParser/Parser.lua",
    "content": "local P={}\nlocal MT={}\nMT.__index=P\n\nfunction P.new(...)\n  local o=setmetatable({}, MT)\n  o:initialize(...)\n  return o\nend\n\nfunction P:registerObject(o)\n  table.insert(self.Objects, o)\nend\n\nfunction P:findObjects(name)\n  local o={}\n  for k,v in ipairs(self.Objects) do\n    if name:lower()==v:getName():lower() then\n      o[#o+1]=v\n    end\n  end\n  return o\nend\n\nfunction P:initialize(...)\n  self.Objects={}\nend\n\nfunction P:parse(buf)\n  -- tokenize\n  local tokens={}\n  for token in buf:gmatch('%w+') do\n    table.insert(tokens, token:lower())\n  end\n  -- find object\n  local objects\n  for k,v in ipairs(tokens) do\n    local o=self:findObjects(v)\n    if #o>0 then\n      objects=o\n      table.remove(tokens, k)\n      break\n    end\n  end\n  if not objects then\n    return nil, 'No objects found'\n  end\n  -- find action\n  local object=objects[1] -- assuming all objects found have the same methods\n  for k,v in ipairs(tokens) do\n    local method=v..'Action'\n    if type(object[method])=='function' then\n      table.remove(tokens, k)\n      local res={}\n      for a,b in ipairs(objects) do\n        local st,re=b[method](b, tokens)\n        if st then\n          res[#res+1]=re\n        end\n      end\n      return true, res\n    end\n  end\n  return nil, 'Unknown action for this object '..object:getName()\nend\n\nfunction P:getObjects()\n  return self.Objects\nend\n\nreturn P\n\n\n"
  },
  {
    "path": "VerbNounParser/README.md",
    "content": "VerbNounParser\n===========\n\nThis sample is inspired by the [verb-noun parser] thread.\n\nThe idea is to register a sef of objects (instances of classes with given name and a set of actions, or methods). So you can have classes like Door or Window, and objects, like reddoor, greendoor or window. Now when user writes \"open door\", the parser first tokenizes this into tokens, then looks for all objects with a name equals to any token (\"open\", \"door\"), and when found - for this token, looks for a function called token+\"Action\" (like \"openAction\"), and calls it with remaining tokens (minus object name and action name). \n\nNote that the Door class implements \"color discriminator\" - if you pass a color name, only door object with this color will respond.\n\nSo try following commands:\n```\nopen window\nopen door\nclose red door\nclose green door\nOpen door\nClose door red ad green please!\nPlease, take the key.\nDrop my key now.\nexit\n```\n\n[verb-noun parser]: http://love2d.org/forums/viewtopic.php?f=4&t=10291\n\n"
  },
  {
    "path": "VerbNounParser/Window.lua",
    "content": "local M={}\nlocal MT={}\nMT.__index=M\n\nfunction M.new(P)\n  local o=setmetatable({}, MT)\n  o:initialize(P)\n  return o\nend\n\nfunction M:getName()\n  return 'Window'\nend\n\nfunction M:initialize(P)\n  self.open=false\n  self.x=100+math.random(500)\n  self.y=150\n  self.w=50\n  self.h=50\nend\n\nfunction M:openAction(P)\n  if not self.open then\n    self.open=true\n    return true, 'Window opened'\n  else\n    return true, 'Window already open!'\n  end\nend\n\nfunction M:closeAction(P)\n  if self.open then\n    self.open=false\n    return true, 'Window closed'\n  else\n    return true, 'Window already closed!'\n  end\nend\n\nfunction M:draw()\n  love.graphics.setColor(0, 100, 255)\n  if self.open then\n    love.graphics.rectangle('fill', self.x, self.y, self.w/4, self.h)\n  else\n    love.graphics.rectangle('fill', self.x, self.y, self.w, self.h)\n  end\n  \nend\n\nreturn M\n"
  },
  {
    "path": "VerbNounParser/main.lua",
    "content": "local Parser=require 'Parser'\nlocal Door=require 'Door'\nlocal Window=require 'Window'\nlocal Key=require 'Key'\nlocal Console=require 'Console'\n\nlocal Objects\nfunction love.load()\n  love.graphics.setBackgroundColor(255, 255, 255)\n  P=Parser.new()\n\n  local blackdoor=Door.new({color='black'})\n  local greendoor=Door.new({color='green'})\n  local reddoor=Door.new({color='red'})\n\n  local window=Window.new()\n  console=Console.new()\n  local key=Key.new()\n\n  P:registerObject(greendoor)\n  P:registerObject(reddoor)\n  P:registerObject(blackdoor)\n  P:registerObject(window)\n  P:registerObject(key)\n  console:setCallback(function(buf)\n    if buf=='exit' or buf=='quit' then\n      love.event.quit()\n    end\n    local st, res=P:parse(buf)\n    if st then\n      console:addLine(res)\n    else\n      console:addLine('Error: '.. res)\n    end\n  end)\nend\n\nfunction love.draw()\n  for k,v in ipairs(P:getObjects()) do\n    v:draw()\n  end\n  console:draw()\nend\n\nfunction love.update(dt)\n  console:update(dt)\nend\n\nfunction love.keypressed(k, u)\n  console:keyPressed(k, u)\nend\n\n"
  }
]