Repository: miko/Love2d-samples
Branch: master
Commit: 50a8b4b43d51
Files: 47
Total size: 64.7 KB
Directory structure:
gitextract_xy8xzx00/
├── CodeCapture/
│ ├── CodeCapture.lua
│ ├── README.md
│ └── main.lua
├── CollisionExample/
│ ├── README.md
│ └── main.lua
├── Fireworks/
│ ├── Firework.lua
│ ├── FireworkEngine.lua
│ ├── Particle.lua
│ ├── README.md
│ ├── Vector.lua
│ ├── class.lua
│ └── main.lua
├── GameOfLife/
│ ├── Readme.md
│ └── main.lua
├── LICENSE
├── MikoIntroScreen/
│ ├── Intro.lua
│ ├── README.md
│ ├── class.lua
│ ├── conf.lua
│ ├── main.lua
│ └── zero-project - 01 - Celtic dream.ogg
├── Minefield/
│ ├── conf.lua
│ ├── main.lua
│ └── menu.lua
├── Obey/
│ ├── B.lua
│ ├── Char.lua
│ ├── E.lua
│ ├── O.lua
│ ├── README.md
│ ├── Y.lua
│ ├── class.lua
│ └── main.lua
├── README.md
├── SidescrollerCollision/
│ ├── README.md
│ └── main.lua
├── SpriteSheet/
│ ├── README.md
│ ├── SpriteSheet.lua
│ └── main.lua
├── TexturedPolygon/
│ ├── README.md
│ └── main.lua
└── VerbNounParser/
├── Console.lua
├── Door.lua
├── Key.lua
├── Parser.lua
├── README.md
├── Window.lua
└── main.lua
================================================
FILE CONTENTS
================================================
================================================
FILE: CodeCapture/CodeCapture.lua
================================================
local M={}
M.KONAMI={'up','up','down','down','left','right','left','right','b','a'}
local STATES={}
local CURRSTATE
local function setNextState(char, state)
if not state then
state=STATES
end
if not state[char] then
state[char]={}
end
return state[char]
end
local function getNextState(char, state)
if not state then
state=STATES
end
return state[char]
end
function M.setCode(c, fn)
if type(c)=='string' then
local c2={}
for char in c:gmatch('.') do c2[#c2+1]=char end
c=c2
end
local st
for k,v in ipairs(c) do
st=setNextState(v, st)
end
st.done=fn
end
function M.keypressed(a)
CURRSTATE=getNextState(a, CURRSTATE)
if CURRSTATE then
if CURRSTATE.done then
CURRSTATE.done()
CURRSTATE=nil
else
--tracking...
end
else
-- start from beginning
CURRSTATE=getNextState(a)
end
end
return M
================================================
FILE: CodeCapture/README.md
================================================
CodeCapture
===========
This sample is inspired by the [KonamiCode] thread.
This 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.
The 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.
This sample has several magic codes:
* "qwerty"
* "second"
* "secundo"
* KONAMI (UP UP DOWN DOWN LEFT RIGHT LEFT RIGHT b a)
* a MOUSE-LEFT b MOUSE-RIGHT
* "quit" and "exit"
Each sequence causes the change of text displayed, except the last ones, which quit the program.
[KonamiCode]: http://love2d.org/forums/viewtopic.php?f=5&t=2632
================================================
FILE: CodeCapture/main.lua
================================================
local CodeCapture=require 'CodeCapture'
function love.load()
CodeCapture.setCode("qwerty", function() MODE='ONE' end)
CodeCapture.setCode('second', function() MODE='TWO' end)
CodeCapture.setCode('secundo', function() MODE='DUO' end)
CodeCapture.setCode(CodeCapture.KONAMI, function() MODE='KONAMI' end)
CodeCapture.setCode({'a','mouse-l','b','mouse-r'}, function() MODE='WITH MOUSE' end)
CodeCapture.setCode('quit', function() love.event.quit() end)
CodeCapture.setCode('exit', function() love.event.quit() end)
MODE='NONE'
end
function love.draw()
love.graphics.print(MODE, 10, 10)
end
function love.keypressed(a,b)
CodeCapture.keypressed(a)
end
function love.mousepressed(x,y,b)
CodeCapture.keypressed('mouse-'..b)
end
================================================
FILE: CollisionExample/README.md
================================================
Collision example
===========
This sample is inspired by the [RestrictRectangleMovement] thread.
The sample illustrates (in just one of many ways) how you can restrict movement
of your cursor (character) to stay on screen and not go thru other obstacles.
How the collision works.
========================
Every 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.
Every object has its position x,y and its size - width w and height. So the collision is detected when any two rectangles collide.
[RestrictRectangleMovement]: http://love2d.org/forums/viewtopic.php?f=3&t=5072
================================================
FILE: CollisionExample/main.lua
================================================
local lg=love.graphics
function love.load()
W, H=lg.getWidth(), lg.getHeight()
local w,h=40,40
Obstacles={}
for i=1,20 do
table.insert(Obstacles, {x=math.random(W-w), y=math.random(H-h), w=w, h=h})
end
w,h=20,20
Cursor={x=math.random(W-w), y=math.random(H-h), w=w, h=h}
while isColliding() do
Cursor.x, Cursor.y=math.random(W-w), math.random(H-h)
end
collision=false
end
function love.draw()
lg.setColor(255,0,0,255)
for k,v in ipairs(Obstacles) do
lg.rectangle('fill', v.x, v.y, v.w, v.h)
end
lg.setColor(0, 255,0,255)
lg.rectangle('fill', Cursor.x, Cursor.y, Cursor.w, Cursor.h)
lg.setColor(255, 255,255,255)
if collision then
lg.print('COLLISION!!!', W/2, 0)
end
end
local isDown=love.keyboard.isDown
function love.update(dt)
local dx,dy=0,0
if isDown('right') or isDown('d') then
dx=1
elseif isDown('left') or isDown('a') then
dx=-1
elseif isDown('up') or isDown('w') then
dy=-1
elseif isDown('down') or isDown('s') then
dy=1
end
local currX, currY=Cursor.x, Cursor.y
Cursor.x, Cursor.y=Cursor.x+dx, Cursor.y+dy
collision=false
if not isOnScreen() or isColliding() then
Cursor.x, Cursor.y=currX, currY
collision=true
end
end
function isOnScreen()
if Cursor.x>0 and Cursor.x+Cursor.w<W and
Cursor.y>0 and Cursor.y+Cursor.h<H then
return true
else
return false
end
end
function isCollidingWith(obj)
local ox, oy=obj.x-Cursor.x, obj.y-Cursor.y -- let's pretent Cursor is at (0,0)
if ox+obj.w<0 or oy+obj.h<0 or
ox>Cursor.w or oy>Cursor.h then
return false
else
return true
end
end
function isColliding()
for k,v in ipairs(Obstacles) do
if isCollidingWith(v) then
return true
end
end
return false
end
================================================
FILE: Fireworks/Firework.lua
================================================
require 'class'
local Vector=require 'Vector'
local Particle=require 'Particle'
STATE={ROCKET=1, EXPLODE=2, LIVE=3, DEAD=4}
local M=class(function(self, x, y)
self.Position=Vector(x, y)
self.state=STATE.ROCKET
self.Particles={}
self.numParticles=math.random(150, 450)
self.elapsed=0
self.R=math.random(50, 255)
self.G=math.random(50, 255)
self.B=math.random(50, 255)
self.StartPosition=Vector(math.random(0, love.graphics.getWidth()), love.graphics.getHeight())
self.elapsed=0
self.livetime=math.random(3,20)/10
end)
function M:update(dt)
self.elapsed=self.elapsed+dt
local state=self.state
if state==STATE.LIVE or state==STATE.EXPLODE then
if state==STATE.EXPLODE then
for i=1,math.random(50,120) do
self:addParticle(self.Position.x, self.Position.y)
end
if #self.Particles>= self.numParticles then
self.state=STATE.LIVE
end
end
for k=#self.Particles,1,-1 do
local p=self.Particles[k]
if p:isDead() then
table.remove(self.Particles, k)
else
p:update(dt)
end
end
if state==STATE.LIVE and #self.Particles==0 then
self.state=STATE.DEAD
end
elseif state==STATE.DEAD then
return
elseif state==STATE.ROCKET then
local pct=self.elapsed/self.livetime*100
if pct>=100 then
self.elapsed=0
self.state=STATE.EXPLODE
end
else
error('UNKNOWN STATE: '..state)
end
end
function M:draw()
if self.state==STATE.ROCKET then
local pct=self.elapsed/self.livetime
local d=(self.StartPosition-self.Position)*pct
local d2=(self.StartPosition-self.Position)*(pct+0.03)
local pos1=self.StartPosition-d
local pos2=self.StartPosition-d2
love.graphics.setColor(self.R, self.G, self.B, 255)
love.graphics.setLineWidth(3)
love.graphics.line(pos1.x, pos1.y, pos2.x, pos2.y)
love.graphics.circle('fill', self.StartPosition.x, self.StartPosition.y, 10, 10)
else
for k,v in ipairs(self.Particles) do
v:draw()
end
end
end
function M:isDead()
return self.state==STATE.DEAD
end
function M:addParticle(x, y)
table.insert(self.Particles, Particle(x, y, self.R, self.G, self.B))
end
return M
================================================
FILE: Fireworks/FireworkEngine.lua
================================================
require 'class'
Firework=require 'Firework'
local M=class(function(self)
self.Fireworks={}
end)
function M:update(dt)
for k=#self.Fireworks,1,-1 do
local f=self.Fireworks[k]
if f:isDead() then
table.remove(self.Fireworks, k)
else
f:update(dt)
end
end
end
function M:draw()
for k,v in ipairs(self.Fireworks) do
v:draw()
end
love.graphics.setColor(255,255,255,255)
love.graphics.print('Fireworks: '..#self.Fireworks, 10, 10)
end
function M:addFirework(x, y)
table.insert(self.Fireworks, Firework(x, y))
end
return M
================================================
FILE: Fireworks/Particle.lua
================================================
require 'class'
local Vector=require 'Vector'
local lg=love.graphics
local M=class(function(self, x, y, R, G, B, v)
self.dead=false
self.Position=Vector(x, y)
self.Velocity=Vector(math.random(10,50),0):rotate(math.random(0, 360))
self.elapsed=0
self.livetime=math.random(20,50)/10
self.R=R or math.random(50, 255)
self.G=G or math.random(50, 255)
self.B=B or math.random(50, 255)
self.variable=v or 'R'
self[self.variable]=math.random(50, 255)
end)
function M:update(dt)
self.elapsed=self.elapsed+dt
self.Position=self.Position+self.Velocity*dt
self.Velocity=self.Velocity+Vector(0,50)*dt
if self.elapsed>=self.livetime then
self.dead=true
end
end
function M:isDead()
return self.dead
end
function M:draw()
local alpha=math.ceil(255-255*(self.elapsed/self.livetime))
if alpha<0 then alpha=0 end
lg.setColor(self.R, self.G, self.B, alpha)
lg.circle('fill', self.Position.x, self.Position.y, 2, 7)
end
return M
================================================
FILE: Fireworks/README.md
================================================
Fireworks example
==============
This is an example of fireworks, inspired by the [facepunch] thread, which is mentioned in [love2d] forum.
Nothing complicated here, just keep clicking with lefto mouse button.
[love2d]: http://love2d.org/forums/viewtopic.php?f=3&t=3909
[facepunch]: http://www.facepunch.com/threads/1136691
================================================
FILE: Fireworks/Vector.lua
================================================
require 'class'
local M=class(function(self, x, y)
self.x=x or 0
self.y=y or 0
end)
function M:isVector()
return getmetatable(self)==M
end
function M:__add(v)
return M(self.x+v.x, self.y+v.y)
end
function M:__sub(v)
return M(self.x-v.x, self.y-v.y)
end
function M:__mul(m)
if type(self)=='number' and M.isVector(m) then
self, m=m, self
end
if type(m)=='number' then
return M(self.x*m, self.y*m)
else
return self.x*m.x+self.y*m.y
end
end
function M:len()
return (self*self)^0.5
end
function M:rotate(phi)
phi=math.rad(phi)
local c, s = math.cos(phi), math.sin(phi)
self.x, self.y = c * self.x - s * self.y, s * self.x + c * self.y
return self
end
function M:__tostring()
return string.format('<%s,%s>', self.x, self.y)
end
return M
================================================
FILE: Fireworks/class.lua
================================================
--[[
-- $Id: class.lua 10 2008-07-01 22:18:32Z basique $
-- Simple class implementation
-- Taken from http://lua-users.org/wiki/SimpleLuaClasses
-- Original author unknown
--]]
function class(base,ctor)
local c = {} -- a new class instance
if not ctor and type(base) == 'function' then
ctor = base
base = nil
elseif type(base) == 'table' then
-- our new class is a shallow copy of the base class!
for i,v in pairs(base) do
c[i] = v
end
c._base = base
end
-- the class will be the metatable for all its objects,
-- and they will look up their methods in it.
c.__index = c
-- expose a ctor which can be called by <classname>(<args>)
local mt = {}
mt.__call = function(class_tbl,...)
local obj = {}
setmetatable(obj,c)
if ctor then
ctor(obj,...)
else
-- make sure that any stuff from the base class is initialized!
if base and base.init then
base.init(obj,...)
end
end
return obj
end
c.init = ctor
c.is_a = function(self,klass)
local m = getmetatable(self)
while m do
if m == klass then return true end
m = m._base
end
return false
end
setmetatable(c,mt)
return c
end
================================================
FILE: Fireworks/main.lua
================================================
FireworkEngine=require 'FireworkEngine'
function love.load()
FE=FireworkEngine()
love.graphics.setBlendMode('additive')
end
function love.update(dt)
FE:update(dt)
end
function love.draw()
FE:draw()
end
function love.mousepressed(x, y, b)
if b=='l' then
FE:addFirework(x, y)
end
end
function love.keypressed(k)
if k=='q' or k=='escape' then
love.event.quit()
end
end
================================================
FILE: GameOfLife/Readme.md
================================================
Game of Life
============
Game of Life inspired by [this thread](http://love2d.org/forums/viewtopic.php?f=4&t=2858)
Controls:
0, 1, 2 - set cell border width
left,right - decrease/increase no of columns
up, down - decrease/increase no of rows
+/- - increase/decrease cell size
n - next cell generation
r,space - toggle running mode
c - clear the table
x - make some random cells alive
q,escape - quit
left mouse button - toggle cell dead/alive
right mouse button - check the status of a cell
Sample screenshot:
------------------

================================================
FILE: GameOfLife/main.lua
================================================
-- Game of Life by miko
-- Controls:
-- 0, 1, 2 - set cell border width
-- left,right - decrease/increase no of columns
-- up, down - decrease/increase no of rows
-- +/- - increase/decrease cell size
-- n - next cell generation
-- r,space - toggle running mode
-- c - clear the table
-- x - make some random cells alive
-- q,escape - quit
-- left mouse button - toggle cell dead/alive
-- right mouse button - check the status of a cell
local lg=love.graphics
function love.load()
rows, cols=30,30
cellsize=20
lineWidth=1+1
elapsed=0
tick=0.1
canvas=lg.newCanvas()
lg.setNewFont(20)
status=nil
init()
end
function init()
CELLS={}
for c=1,cols do
CELLS[c]={}
for r=1,cols do
CELLS[c][r]=false
end
end
generation=1
end
function love.draw()
if not cached then
cached=true
lg.setCanvas(canvas)
if lineWidth>0 then
lg.setLineWidth(lineWidth)
end
for c=1,cols do
for r=1,rows do
local cell=CELLS[c][r]
if cell then
lg.setColor(255,0,0,255)
else
lg.setColor(0,0,0,255)
end
lg.rectangle('fill', (c-1)*cellsize, (r-1)*cellsize, cellsize, cellsize)
if lineWidth>0 then
lg.setColor(255,255,255,255)
lg.rectangle('line', (c-1)*cellsize, (r-1)*cellsize, cellsize, cellsize)
end
end
end
lg.setCanvas()
end
lg.setColor(255,255,255,255)
lg.draw(canvas, 0, 0, 0)
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())
if status then msg=msg.."\n"..status end
lg.setColor(0,255,0,255)
lg.print(msg, 0,0,0)
lg.setColor(0,0,255,255)
lg.print(msg, 1,1,0)
lg.setColor(255,0,0,255)
lg.print(msg, 2,2,0)
end
function mouse2cell(x, y)
local cx, cy=math.floor(x/cellsize), math.floor(y/cellsize)
if cx>=0 and cx<cols and cy>=0 and cy<rows then
return cy+1, cx+1
end
end
function love.update(dt)
if not running then return end
elapsed=elapsed+dt
if elapsed>=tick then
elapsed=elapsed-tick
nextGeneration()
cached=nil
end
end
function love.mousepressed(x, y, b)
--local cx, cy=mouse2cell(x, y)
local mr, mc=mouse2cell(x, y)
status=nil
if mr then
if b=='l' then
CELLS[mc][mr]=not CELLS[mc][mr]
status=string.format('Cell c=%d,r=%d changed to %s', mc, mr, CELLS[mc][mr] and 'ALIVE' or 'DEAD')
elseif b=='r' then
status=string.format('Cell c=%d,y=%d %s neighbours: %d', mc, mr, CELLS[mc][mr] and 'ALIVE' or 'DEAD', countNeighbours(mc, mr))
end
cached=nil
end
end
function love.keypressed(a, b)
if a=='q' or a=='escape' then
love.event.push("q")
end
if a=='r' or a==' ' then
running=not running
end
if a=='n' then
nextGeneration()
cached=nil
end
if a=='c' then
init()
cached=nil
end
if a=='1' or a=='2' or a=='0' then
lineWidth=tonumber(a)
cached=nil
end
if a=='down' then
rows=rows+1
cached=nil
init()
end
if a=='up' then
rows=rows-1
cached=nil
init()
end
if a=='right' then
cols=cols+1
cached=nil
init()
end
if a=='left' then
cols=cols-1
cached=nil
init()
end
if a=='+' or a=='=' then
cellsize=math.min(cellsize+1, 30)
cached=nil
end
if a=='-' or a=='_' then
cellsize=math.max(cellsize-1, 1)
cached=nil
end
if a=='x' then
for i=1,cols*rows*0.1 do
CELLS[math.random(1,cols)][math.random(1, rows)]=true
end
cached=nil
end
end
function countNeighbours(c, r)
local n=0
local cy=c
local cx=r
if cx>1 and cy>1 then
if CELLS[cy-1][cx-1] then n=n+1 end
end
if cy>1 then
if CELLS[cy-1][cx] then n=n+1 end
end
if cx<cols and cy>1 then
if CELLS[cy-1][cx+1] then n=n+1 end
end
if cx>1 then
if CELLS[cy][cx-1] then n=n+1 end
end
if cx<cols then
if CELLS[cy][cx+1] then n=n+1 end
end
if cx>1 and cy<rows then
if CELLS[cy+1][cx-1] then n=n+1 end
end
if cy<rows then
if CELLS[cy+1][cx] then n=n+1 end
end
if cx<cols and cy<rows then
if CELLS[cy+1][cx+1] then n=n+1 end
end
return n
end
function nextGeneration()
generation=generation+1
local NEWCELLS={}
--for c, COL in ipairs(CELLS) do
for c=1,cols do
NEWCELLS[c]={}
--for r, cell in ipairs(COL) do
for r=1, rows do
local cell=CELLS[c][r]
--local n=countNeighbours(r, c)
local n=countNeighbours(c, r)
if cell then
if n==2 or n==3 then
NEWCELLS[c][r]=true
else
NEWCELLS[c][r]=false
end
else
if n==3 then
NEWCELLS[c][r]=true
else
NEWCELLS[c][r]=false
end
end
end
end
CELLS=NEWCELLS
end
================================================
FILE: LICENSE
================================================
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.
===============================================================================
Copyright (C) 2011 Michal Kolodziejczyk, miko@wp.pl
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================================================
================================================
FILE: MikoIntroScreen/Intro.lua
================================================
require 'class'
--love=love or {graphics={}} -- plain lua compatibility
local lg=love.graphics
if not lg.newFramebuffer then
lg.newFramebuffer=lg.newCanvas -- love 0.8 compatilibity
end
local WIDTH, HEIGHT=lg.getWidth(), lg.getHeight()
local _SAVED={}
local iterator
local empty=function() end
local function save()
for k,v in pairs({'draw', 'update', 'keypressed', 'keyreleased'}) do
_SAVED[v]=love[v] or empty
end
end
local function restore()
for k,v in pairs(_SAVED) do
if v==empty then
love[k]=nil
else
love[k]=v
end
end
end
local function tween(pct, sval, eval)
return sval+pct/100*(eval-sval)
end
local function srand(x, y)
return math.floor(math.random(x, y))
end
local function makeSample(len, pitch)
len=len or 0.1
pitch=pitch or 440
local overtime=1.5
local tick = love.sound.newSoundData(overtime*len * 44100, 44100, 16, 1)
for i = 0,len*44100*overtime do
local t = i / 44100
local sample = math.sin(t * pitch * math.pi * 2) * len
tick:setSample(i, sample)
end
return tick
end
local O=class(function(self, data, ctype)
OBJNAME=(OBJNAME or 0)+1
self.name=OBJNAME
if ctype then
self.ctype=ctype
end
if type(data)=='string' then
if not ctype then
self.ctype='text'
end
self.text=data or '???'
else
if not ctype then
self.ctype='image'
end
end
self.data=data
end)
function O:setPosition(x, y)
self.x, self.y=x or 0, y or 0
return self
end
function O:setRotation(r)
self.r=r or 0
return self
end
function O:setScale(sx, sy)
sx=sx or 1
if not sy then sy=sx end
self.sx, self.sy=sx, sy
return self
end
function O:setFont(font)
if type(font)=='number' then
font=self:getFont(font)
end
self.font=font or ''
return self
end
function O:setColor(r, g, b, a)
local color
if type(r)=='table' then
color=r
else
color={r, g, b, a}
end
self.color=color
return self
end
function O:center()
if self.ctype~='text' then
return
end
local w=self:getFont():getWidth(self.text)
self.x=(WIDTH-w)/2
return self
end
function O:start()
self._DATA={}
if self.ctype=='text' then
local font=self:getFont()
local rot=self.r
lg.setFont(font)
local H=font:getHeight()
local dw=0
for c in self.text:gmatch('.') do
local W=font:getWidth(c)
local o={x=self.x+dw, y=self.y, sx=srand(0, WIDTH), sy=srand(0, HEIGHT), char=c}
o.scolor={srand(0, 255), srand(0, 255),srand(0, 255)}
o.r=rot
o.sr=srand(0, 360*4)
dw=dw+W
o.fb=lg.newFramebuffer(W, H)
o.cx, o.cy=W/2, H/2
o.sSX=math.random(100)/10
lg.setCanvas(o.fb)
lg.print(c, 0, 0)
table.insert(self._DATA, o)
end
elseif self.ctype=='image' then
local o={x=self.x, y=self.y, sx=srand(0, WIDTH), sy=srand(0, HEIGHT)}
o.r=self.r
o.sr=srand(0, 360*4)
local W, H=self.data:getWidth(), self.data:getHeight()
o.cx, o.cy=W/2, H/2
o.sSX=math.random(100)/10
o.fb=self.data
self._DATA[1]=o
elseif self.ctype=='audio' then
love.audio.play(self.data)
end
end
function O:stop()
if self.ctype=='audio' then
love.audio.stop(self.data)
end
end
function O:getFont(size)
if not self.font then
lg.setNewFont(size)
self.font=lg.getFont()
end
return self.font
end
function O:draw(pct)
lg.setColor(255, 255, 255, 255)
local color=self.color
local A=tween(pct, 0, 255)
if self.ctype=='text' then
for k,v in ipairs(self._DATA) do
local x=tween(pct, v.sx, v.x)
local y=tween(pct, v.sy, v.y)
local scolor=v.scolor
local R=tween(pct, scolor[1], color[1])
local G=tween(pct, scolor[2], color[2])
local B=tween(pct, scolor[3], color[3])
local rot=tween(pct, v.sr or 0, self.r or 0)
local sx=tween(pct, v.sSX, 1)
--local sy=tween(pct, v.sSY, 1)
if self.hilited==k then
lg.setColor(255, 255, 255, 255)
else
lg.setColor(R, G, B, A)
end
lg.push()
lg.translate(x+v.cx, y+v.cy)
lg.rotate(math.rad(rot))
lg.translate(-v.cx, -v.cy)
--lg.scale(sx, sx)
lg.draw(v.fb, 0, 0)
lg.pop()
end
elseif self.ctype=='image' then
local v=self._DATA[1]
local x=tween(pct, v.sx, v.x)
local y=tween(pct, v.sy, v.y)
local scolor=v.scolor
--[[
local R=tween(pct, scolor[1], color[1])
local G=tween(pct, scolor[2], color[2])
local B=tween(pct, scolor[3], color[3])
--]]
local rot=tween(pct, v.sr or 0, self.r or 0)
local sx=tween(pct, v.sSX, 1)
lg.setColor(255, 255, 255, A)
--local sy=tween(pct, v.sSY, 1)
--lg.setColor(R, G, B)
lg.push()
--lg.scale(sx, sx)
lg.translate(x+v.cx, y+v.cy)
lg.rotate(math.rad(rot))
lg.translate(-v.cx, -v.cy)
lg.draw(v.fb, 0, 0)
lg.pop()
end
end
function O:setHilited(id)
self.hilited=id
end
function O:__tostring()
return string.format('<Object %s %s>', self.ctype, self.name or 'unnamed')
end
local Object=O
--
local M=class(function(self)
self.Objects={}
self:setDuration(6)
self:setDelay(2)
end)
function M:addText(txt)
local obj=Object(txt)
table.insert(self.Objects, obj)
return obj
end
function M:addImage(filename)
local img
if type(filename)=='string' then
img=lg.newImage(filename)
else
img=filename
end
local obj=Object(img)
table.insert(self.Objects, obj)
return obj
end
function M:addAudio(audio)
if type(audio)=='string' then
audio=love.audio.newSource(audio, 'static')
end
local obj=Object(audio, 'audio')
table.insert(self.Objects, obj)
return obj
end
function M:setDuration(d)
self.duration=d or 6
return self
end
function M:setDelay(d)
self.delay=d or 2
return self
end
function M:makeChaos()
return self
end
-- len - in seconds, just before duration
function M:setBlinks(len, obj, ...)
if not obj then return self end
self.blink=len
self.blinkObjects=self.blinkObjects or {}
table.insert(self.blinkObjects, obj)
return self:setBlinks(len, ...)
end
function M:_setupBlinks()
local count=0
for k,v in pairs(self.blinkObjects) do
count=count+#v._DATA
end
self.blinkChars=count
self.blinkdt=self.blink/count
function self.nextCharIterator()
local T=self.blinkObjects
local objKey,obj=next(T)
local idxKey, idx
return function()
idxKey, idx=next(obj._DATA, idxKey)
if not idx then
objKey,obj=next(T, objKey)
if not obj then return end
idxKey, idx=next(obj._DATA, idxKey)
end
return obj, idxKey, idx
end
end
SAMPLES={}
for obj, idxk, idxo in self:nextCharIterator() do
local c=idxo.char:upper()
if not SAMPLES[c] then
local x=0
if c==' ' then
x=1
elseif c=='!' then
x=2
else
x=c:byte()-45 -- 49 for "0", 65 for "A"
end
SAMPLES[c]=makeSample(self.blinkdt, 2^((x-2)/12)*400)
end
end
end
function M:start()
local s=self
save()
math.randomseed(os.time())
love.update=function(dt) s:update(dt) end
love.draw=function() s:draw() end
love.keypressed=function(a, b) s:keypressed(a, b) end
self.elapsed=0
lg.setColor(255, 255, 255, 255)
for k,v in ipairs(self.Objects) do
v:start()
end
lg.setCanvas()
if self.blink then
self:_setupBlinks()
end
return self
end
function M:stop()
for k,v in ipairs(self.Objects) do
v:stop()
end
restore()
return self
end
function M:keypressed(a, b)
if a==' ' then
self.paused=not self.paused
else
self:stop()
end
end
function M:update(dt)
if self.paused then return end
self.elapsed=self.elapsed+dt
if self.elapsed>self.duration+self.delay then
self:stop()
elseif self.elapsed>self.duration then
if self.pct~=100 then
self.pct=100
end
if self.blink and self.elapsed-self.duration<=self.blink then
BLINKDT=(BLINKDT or 0)+dt
if BLINKDT>self.blinkdt then
BLINKDT=BLINKDT-self.blinkdt
if self.objHilited then
self.objHilited:setHilited()
end
--local obj=self.blinkObjects[math.random(1, #self.blinkObjects)]
iterator=iterator or self:nextCharIterator()
local obj, idxk, idxo=iterator()
SRC=SRC or {}
local src=love.audio.newSource(SAMPLES[idxo.char:upper()])
src:setVolume(2)
src:play()
SRC[#SRC+1]=src
--obj:setHilited(math.random(#obj._DATA))
obj:setHilited(idxk)
self.objHilited=obj
end
else
if self.objHilited then
self.objHilited:setHilited()
end
end
return
end
self.pct=self.elapsed/self.duration*100
end
function M:draw()
local pct=self.pct
if not pct then return end
for k,v in ipairs(self.Objects) do
v:draw(pct)
end
end
return M
================================================
FILE: MikoIntroScreen/README.md
================================================
LOVEJam Intro Screen
===========
This sample is inspired by the [LOVEJam] site.
This is a splash screen intro, and also an engine, where you can easily make similar intros for yourself.
The 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.
[LOVEJam]: http://love2d.org/jam
================================================
FILE: MikoIntroScreen/class.lua
================================================
--[[
-- $Id: class.lua 10 2008-07-01 22:18:32Z basique $
-- Simple class implementation
-- Taken from http://lua-users.org/wiki/SimpleLuaClasses
-- Original author unknown
--]]
function class(base,ctor)
local c = {} -- a new class instance
if not ctor and type(base) == 'function' then
ctor = base
base = nil
elseif type(base) == 'table' then
-- our new class is a shallow copy of the base class!
for i,v in pairs(base) do
c[i] = v
end
c._base = base
end
-- the class will be the metatable for all its objects,
-- and they will look up their methods in it.
c.__index = c
-- expose a ctor which can be called by <classname>(<args>)
local mt = {}
mt.__call = function(class_tbl,...)
local obj = {}
setmetatable(obj,c)
if ctor then
ctor(obj,...)
else
-- make sure that any stuff from the base class is initialized!
if base and base.init then
base.init(obj,...)
end
end
return obj
end
c.init = ctor
c.is_a = function(self,klass)
local m = getmetatable(self)
while m do
if m == klass then return true end
m = m._base
end
return false
end
setmetatable(c,mt)
return c
end
================================================
FILE: MikoIntroScreen/conf.lua
================================================
function love.conf(t)
t.title = "miko lovejam intro"
t.author = "miko"
t.identity = "mario"
t.screen.width = 800
t.screen.height = 600
end
================================================
FILE: MikoIntroScreen/main.lua
================================================
local Intro=require 'Intro'
function love.load()
I=Intro()
local t1=I:addText('LoveJam Test Jam entry!'):setPosition(20, 50):setColor(0, 255, 0):setFont(60):center()
local t2=I:addText('Made with Love2d'):setPosition(400, 200):setColor(0, 0, 255):setFont(30)
local t3=I:addText('(C) 2011 miko - average Love user'):setPosition(10, 500):setColor(255,0,0):setFont(40):center()
I:addImage('logo.png'):setPosition(200, 180)
I:addImage('face-grin.png'):setPosition(400, 350)
I:addAudio('zero-project - 01 - Celtic dream.ogg')
I:setDuration(5)
I:setDelay(5)
I:setBlinks(2, t1, t2)
I:start()
end
function love.update(dt)
love.event.quit()
end
--[[
function love.keypressed(a, b)
love.event.quit()
end
--]]
================================================
FILE: Minefield/conf.lua
================================================
function love.conf(t)
t.modules.joystick = false
t.modules.audio = false
t.modules.keyboard = true
t.modules.event = true
t.modules.image = false
t.modules.graphics = true
t.modules.timer = true
t.modules.mouse = false
t.modules.sound = false
t.modules.physics = false
t.console = false
t.title = "Minefield"
t.author = "MiKo"
t.screen.fullscreen = false
t.screen.vsync = true
t.screen.fsaa = 0
--t.screen.height = 800
--t.screen.width = 1024
end
================================================
FILE: Minefield/main.lua
================================================
local lg=love.graphics
ORGWIDTH, ORGHEIGHT=lg.getWidth(), lg.getHeight()
local Menu=require 'menu'
function love.load()
ReplayDelay=0.2
lg.setBackgroundColor(255,255,255)
mode='menu'
fullscreen=false
diagonal=true
initScreen()
initGame()
end
function initScreen()
W, H=lg.getWidth(), lg.getHeight()
--CellSize=30
CellSize=math.floor(math.min(W/25, H/25))
CX,CY=math.floor(W/CellSize), math.floor(H/CellSize)
BorderWidthX=(W-(CX-2)*CellSize)/2
BorderWidthY=(H-(CY-2)*CellSize)/2
CX,CY=CX-2,CY-2
lg.setNewFont(CellSize)
end
function initGame()
CenterX=math.floor(CX/2)
PX, PY=CenterX, CY+1 -- player position
Bombs, Visited={}, {}
for x=1,CX do
Bombs[x]={}
Visited[x]={}
end
local bomblimit=math.floor(CX*CY/10)
for i=1,bomblimit do
local x,y=0,0
repeat
x, y=math.random(1, CX), math.random(1, CY)
until not Bombs[x][y] and not (x==CenterX and (y==1 or y==CY))
Bombs[x][y]=true
end
crashed=nil
won=nil
showingBombs=nil
History={}
elapsed=0
end
function drawCell(X, Y, Color)
if Color then
lg.setColor(Color)
end
lg.rectangle('fill', BorderWidthX+CellSize*(X-1), BorderWidthY+CellSize*(Y-1), CellSize, CellSize)
end
function drawPlayer(X, Y)
lg.setColor(255, 255, 0)
lg.circle('fill', BorderWidthX+CellSize*(X-0.5), BorderWidthY+CellSize*(Y-0.5), CellSize/2, CellSize)
end
function drawBomb(X, Y)
lg.circle('fill', BorderWidthX+CellSize*(X-0.5), BorderWidthY+CellSize*(Y-0.5), CellSize/4, CellSize)
end
function drawBorders()
lg.setColor(0, 0, 255)
lg.rectangle('fill', 0, 0, W, BorderWidthY)
lg.rectangle('fill', 0, H-BorderWidthY, W, BorderWidthY)
lg.rectangle('fill', 0, 0, BorderWidthX, H)
lg.rectangle('fill', W-BorderWidthX, 0, BorderWidthX, H)
lg.setColor(0, 255, 0)
drawCell(math.floor(CX/2), CY+1)
drawCell(math.floor(CX/2), 0)
end
function drawVisited()
lg.setColor(200, 100, 100)
for x=1,CX do
for y=1,CY do
if Visited[x][y] then
drawCell(x, y)
end
end
end
end
function countBombs()
local n=0
if diagonal then
for x=PX-1,PX+1 do
for y=PY-1,PY+1 do
if Bombs[x] and Bombs[x][y] then n=n+1 end
end
end
else
if Bombs[PX-1] and Bombs[PX-1][PY] then n=n+1 end
if Bombs[PX+1] and Bombs[PX+1][PY] then n=n+1 end
if Bombs[PX] and Bombs[PX][PY-1] then n=n+1 end
if Bombs[PX] and Bombs[PX][PY+1] then n=n+1 end
end
return n
end
function drawMsgs()
local n=countBombs()
lg.setColor(255, 0, 0)
lg.printf('Bombs: '..n, 0,0, W, 'right')
lg.printf(string.format('Time: %d s', elapsed), 0,0, W, 'left')
if replaying then
lg.printf('Replaying...', 0, H/2, W, 'center')
else
if crashed then
lg.printf('Bum!\n\nPress SPACE to play again, R for replay, M for menu', 0, H/2, W, 'center')
end
if won then
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')
end
end
end
function drawBombs()
lg.setColor(0, 0, 0)
for x=1,CX do
for y=1,CY do
if Bombs[x][y] then
drawBomb(x, y)
end
end
end
end
function drawHelp()
lg.setColor(0,0,0)
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.
Use cursor keys/ WASD for movement, q/ESCAPE for quit.
In the menu you can change some options (screen resolution, etc).
Press any key to return to menu, then select Play.]], W*0.2, H/5, W*0.6, 'center')
end
function love.draw()
if mode=='help' then
drawHelp()
return
elseif mode=='menu' then
Menu:draw()
return
end
drawBorders()
drawVisited()
drawPlayer(PX, PY)
if showingBombs then
drawBombs()
end
drawMsgs()
end
function replayGame()
histIndex=1
replaying=true
Visited={}
for x=1,CX do
Visited[x]={}
end
end
function love.keypressed(a, b)
if a=='q' or a=='escape' then
love.event.quit()
end
if mode=='menu' then
Menu:keypressed(a, b)
return
elseif mode=='help' then
mode='menu'
return
end
if a=='b' then
showingBombs=not showingBombs
end
if replaying then return end
if crashed or won then
if a==' ' then
initGame()
end
if a=='r' then
replayGame()
end
if a=='m' then
mode='menu'
end
else
local moved
if (a=='up' or a=='w') and (PY>1 or PX==CenterX) then PY=PY-1; moved=true end
if (a=='down' or a=='s') and PY<CY then PY=PY+1; moved=true end
if (a=='left' or a=='a') and PX>1 and PY<=CY then PX=PX-1; moved=true end
if (a=='right' or a=='d') and PX<CX and PY<=CY then PX=PX+1; moved=true end
if moved then
table.insert(History, {PX, PY})
if not Visited[PX][PY] then
Visited[PX][PY]=true
end
if Bombs[PX][PY] then
crashed=true
showingBombs=true
end
if PY==0 then
won=true
showingBombs=true
end
end
end
end
function love.update(dt)
if mode=='play' and not crashed and not won then
elapsed=elapsed+dt
end
if not replaying then return end
timer=(timer or 0)+dt
if timer>ReplayDelay then
timer=timer-ReplayDelay
local move=History[histIndex]
histIndex=histIndex+1
if not move then
timer=nil
replaying=nil
histIndex=nil
else
PX, PY=unpack(move)
Visited[PX][PY]=true
end
end
end
function resize(W, H)
lg.setMode(W, H, fullscreen , true)
initScreen()
end
function love.quit()
fullscreen=false
resize(ORGWIDTH, ORGHEIGHT)
end
================================================
FILE: Minefield/menu.lua
================================================
local lg=love.graphics
local Options={
{name='play', title='Play the game!'},
{name='help', title='Help'},
{name='diagonal', title='Check diagonal positions?', options={'YES','NO'}, value='YES'},
--{name='resolution', title='Screen resolution', options={'1280x1024', '1024x800', '800x600', '640x480', '320x240', '256x192'}, value='1024x800'},
{name='resolution', title='Screen resolution', options={}, value=nil},
{name='fullscreen', title='Fullscreen', options={'YES', 'NO'}, value='NO'},
{name='quit', title='Quit'}
}
local modes=lg.getModes()
for k,v in ipairs(modes) do
Options[4].options[k]=v.width..'x'..v.height
if v.width==ORGWIDTH and v.height==ORGHEIGHT then
Options[4].value=Options[4].options[k]
end
end
table.insert(Options[4].options, '256x192')
if not Options[4].value then
Options[4].value=Options[4].options[1]
end
local Menu={
currentOption=1
}
function Menu:draw()
for k,v in ipairs(Options) do
if k==self.currentOption then
lg.setColor(50,50,255)
else
lg.setColor(50,50,50)
end
if v.value then
lg.printf(string.format('%s [%s]', v.title, v.value), 0, (2+k)*CellSize*2, W, 'center')
else
lg.printf(v.title, 0, (2+k)*CellSize*2, W, 'center')
end
end
end
function Menu:keypressed(a, b)
if a=='up' or a=='w' then
self.currentOption=self.currentOption-1
if self.currentOption==0 then self.currentOption=#Options end
return
elseif a=='down' or a=='s' then
self.currentOption=self.currentOption+1
if self.currentOption>#Options then self.currentOption=1 end
return
elseif a=='enter' or a=='return' then
self:onSelect(Options[self.currentOption].name)
end
local o=Options[self.currentOption]
if o.options then
local idx, previdx
for k,v in ipairs(o.options) do
if v==o.value then
idx=k
previdx=k
break
end
end
if a=='right' or a=='d' then
idx=idx+1
if idx>#o.options then idx=1 end
elseif a=='left' or a=='a' then
idx=idx-1
if idx<1 then idx=#o.options end
end
if previdx~=idx then
o.value=o.options[idx]
self:onChange(o.name, o.value)
end
else
if a=='right' or a=='left' or a=='d' or a=='a' then
self:onSelect(o.name)
end
end
end
function Menu:onChange(k, v)
if k=='resolution' then
local w, h=v:match('(%d+)x(%d+)')
resize(w, h)
end
if k=='fullscreen' then
if v=='YES' then
fullscreen=true
else
fullscreen=false
end
resize(W, H)
end
if k=='diagonal' then
if v=='YES' then
diagonal=true
else
diagonal=false
end
end
end
function Menu:onSelect(k)
if k=='quit' then
love.event.quit()
elseif k=='play' then
mode='play'
initGame()
elseif k=='help' then
mode='help'
end
end
return Menu
================================================
FILE: Obey/B.lua
================================================
local Char=require('Char')
local lg=love.graphics
local M=class(Char, function(self, W, H)
Char.init(self, 'B', W, H)
self.color={0, 255,0,255}
local P={}
local p=5
for i=-90, 90, p do
P[#P+1]=W*math.cos(math.rad(i))
P[#P+1]=H*0.3*math.sin(math.rad(i))
end
self.POINTS=P
end)
function M:_draw()
lg.setColor(self.color)
lg.translate(-self.W/2, -self.H/5)
lg.polygon('fill', self.POINTS)
lg.translate(0, 2*self.H/5)
lg.polygon('fill', self.POINTS)
lg.translate(self.W/2, -self.H/5)
lg.setColor(0, 0, 0, 255)
lg.circle('fill', 0.6*self.W/2, -0.6*self.H/3, self.H/15)
lg.circle('fill', 0.6*self.W/2, 0.6*self.H/3, self.H/15)
end
return M
================================================
FILE: Obey/Char.lua
================================================
require 'class'
local lg=love.graphics
local M=class(function(self, name, W, H)
self.W, self.H=W, H
self.position={0,0}
self.rotation=0
self._scale={1,1}
self.name=name or 'unnamed'
end)
function M:draw()
lg.push()
lg.translate(self.position[1], self.position[2])
lg.rotate(math.rad(self.rotation))
lg.scale(self._scale[1], self._scale[2])
--predraw
if self._draw then
self:_draw()
end
--postdraw
lg.pop()
end
function M:setPosition(x, y)
self.position={x, y}
return self
end
function M:setScale(sx, sy)
self._scale={sx, sy or sx}
return self
end
function M:setRotation(r)
self.rotation=r
return self
end
function M:rotate(dr)
local newrotation=self.rotation+dr
if self.animated then
self._startRotation=self.rotation
self._endRotation=newrotation
else
self.rotation=newrotation
end
return self
end
function M:move(dx, dy)
local newposition={self.position[1]+dx, self.position[2]+dy}
if self.animated then
self._startPosition=self.position
self._endPosition=newposition
else
self.position=newposition
end
return self
end
function M:scale(dsx, dsy)
dsy=dsy or dsx
local newscalex=self._scale[1]*dsx
local newscaley=self._scale[2]*dsy
if self.animated then
self._startScale=self._scale
self._endScale={newscalex, newscaley}
else
self._scale={newscalex, newscaley}
end
return self
end
function M:setAnimation(duration)
if not duration then
self.animated=nil
else
self.animated=true
self.duration=duration
self._startPosition=self.position
self._endPosition=self.position
self._startRotation=self.rotation
self._endRotation=self.rotation
self._startScale=self.scale
self._endScale=self.scale
end
return self
end
function M:update(dt)
if not self.animated then return end
if not self._elapsed then
self._elapsed=0
else
self._elapsed=self._elapsed+dt
end
if self._elapsed>=self.duration then
self.animated=nil
self._scale=self._endScale
self.position=self._endPosition
self.rotation=self._endRotation
self:onAnimationFinished()
else
local pct=self._elapsed/self.duration
self.rotation=self._startRotation*(1-pct)+self._endRotation*pct
self._scale={
self._startScale[1]*(1-pct)+self._endScale[1]*pct,
self._startScale[2]*(1-pct)+self._endScale[2]*pct
}
self.position={
self._startPosition[1]*(1-pct)+self._endPosition[1]*pct,
self._startPosition[2]*(1-pct)+self._endPosition[2]*pct
}
end
end
function M:onAnimationFinished()
end
return M
================================================
FILE: Obey/E.lua
================================================
local Char=require('Char')
local lg=love.graphics
local M=class(Char, function(self, W, H)
Char.init(self, 'E', W, H)
self.color={0, 0, 255,255}
end)
function M:_draw()
lg.setColor(self.color)
local H2=self.H/2
local W2=self.W/2
local w=math.min(self.W/10, self.H/10)
lg.setLineWidth(2*w)
lg.line(W2,-H2+w, -W2+w,-H2+w, -W2+w,0, W2,0, -W2+w,0, -W2+w,H2-w, W2,H2-w)
end
return M
================================================
FILE: Obey/O.lua
================================================
local Char=require('Char')
local lg=love.graphics
local M=class(Char, function(self, W, H)
Char.init(self, 'O', W, H)
self.color={255,255,0,255}
self.dx=1.1*self.W/2*math.cos(math.rad(45))
self.dy=-1.1*self.H/2*math.sin(math.rad(45))
end)
function M:_draw()
lg.setColor(self.color)
lg.circle('fill', 0, 0, self.W/2, self.W/2 )
lg.circle('fill', self.dx, self.dy, 0.1*self.W, self.W/2 )
lg.circle('fill', -self.dx, self.dy, 0.1*self.W, self.W/2 )
end
return M
================================================
FILE: Obey/README.md
================================================
Obeying avatar
===========
This sample is inspired by the [AngryLovers] thread.
It creates an avatar animation. The key here is to [obey].
[AngryLovers]: http://love2d.org/forums/viewtopic.php?f=5&t=4573
[obey]: http://love2d.org/forums/viewtopic.php?f=3&t=9
================================================
FILE: Obey/Y.lua
================================================
local Char=require('Char')
local lg=love.graphics
local M=class(Char, function(self, W, H)
Char.init(self, 'Y', W, H)
self.color={0,0,255, 255}
end)
function M:_draw()
lg.setColor(self.color)
local W2=self.W/2
local H2=self.H/2
local w=math.min(self.W/10, self.H/10)
lg.setLineWidth(2*w)
lg.line(-W2,-H2, 0,0, 0,H2, 0,0, W2,-H2)
end
return M
================================================
FILE: Obey/class.lua
================================================
--[[
-- $Id: class.lua 10 2008-07-01 22:18:32Z basique $
-- Simple class implementation
-- Taken from http://lua-users.org/wiki/SimpleLuaClasses
-- Original author unknown
--]]
function class(base,ctor)
local c = {} -- a new class instance
if not ctor and type(base) == 'function' then
ctor = base
base = nil
elseif type(base) == 'table' then
-- our new class is a shallow copy of the base class!
for i,v in pairs(base) do
c[i] = v
end
c._base = base
end
-- the class will be the metatable for all its objects,
-- and they will look up their methods in it.
c.__index = c
-- expose a ctor which can be called by <classname>(<args>)
local mt = {}
mt.__call = function(class_tbl,...)
local obj = {}
setmetatable(obj,c)
if ctor then
ctor(obj,...)
else
-- make sure that any stuff from the base class is initialized!
if base and base.init then
base.init(obj,...)
end
end
return obj
end
c.init = ctor
c.is_a = function(self,klass)
local m = getmetatable(self)
while m do
if m == klass then return true end
m = m._base
end
return false
end
setmetatable(c,mt)
return c
end
================================================
FILE: Obey/main.lua
================================================
if type(love._version)~='string' then
error('love 0.8+ required!')
end
local lg=love.graphics
--W,H=512, 512
W,H=90,90
local O=require 'O'(W, H):setPosition(W/4, H/4):setScale(0.5)
local B=require 'B'(W, H):setPosition(3*W/4, H/4):setScale(0.5)
local E=require 'E'(W, H):setPosition(W/4, 3*H/4):setScale(0.5)
local Y=require 'Y'(W, H):setPosition(3*W/4, 3*H/4):setScale(0.5)
local time=3
if false then
-- RECTANGLE
O:setAnimation(time):move(W/4,0.9*-H/10):scale(2,0.6)
B:setAnimation(time):rotate(-90):scale(0.4, 1.6):move(-W/4, -H/8)
E:setAnimation(time):move(W/4,H/10):rotate(90):scale(1,2)
Y:setAnimation(time):move(-W/4,-H/4):scale(2,0.8)
else --CIRCLE
O:setAnimation(time):move(W/4,0.8*-H/10):scale(0.8, 0.7)
B:setAnimation(time):rotate(-90):scale(0.4,0.7):move(-W/4, -H/8)
E:setAnimation(time):move(W/4,H/10):rotate(90):scale(1)
Y:setAnimation(time):move(-W/4,-H/4):scale(0.8)
end
function Y:onAnimationFinished()
local scr=lg.newScreenshot():encode('miko.png')
end
function love.load()
lg.setMode(W, H)
Chars={O, B, E, Y}
end
function love.draw()
for k,v in ipairs(Chars) do
v:draw()
end
end
function love.update(dt)
for k,v in ipairs(Chars) do
v:update(dt)
end
end
================================================
FILE: README.md
================================================
Love2d samples
==============
This 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.
[love2d]: http://love2d.org/
================================================
FILE: SidescrollerCollision/README.md
================================================
Sidescroller Collision example
===========
This 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.
The sample illustrates (in just one of many ways) how you can restrict movement
of your cursor (character) to stay on screen and not go thru other obstacles.
So: move with LEFT/RIGHT, jump with SPACE. Toggle debug with d.
How the collision works.
========================
There 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.
The 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.
There is another constraint of the movement - the character must stay on the map.
[CollisionExample]: https://github.com/miko/Love2d-samples/tree/master/CollisionExample
================================================
FILE: SidescrollerCollision/main.lua
================================================
function love.load()
CELLSIZE=32
PLAYERSIZE=16
Player={x=92, y=100, G=-100, S=100, jumping=false, falling=false, Cells={}}
createMap()
end
function love.update(dt)
playermove(dt)
end
function love.draw()
love.graphics.setColor(255,255,255)
for y=1,#map do
for x=1,#map[y] do
if map[y][x] == 1 then
love.graphics.rectangle("fill",x*CELLSIZE,y*CELLSIZE,CELLSIZE,CELLSIZE)
else
if DEBUG then
love.graphics.rectangle("line",x*CELLSIZE,y*CELLSIZE,CELLSIZE,CELLSIZE)
end
end
end
end
love.graphics.setColor(255,0,0,128)
love.graphics.rectangle("fill",Player.x,Player.y,PLAYERSIZE, PLAYERSIZE)
if DEBUG then
love.graphics.setColor(0,255,0)
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)
love.graphics.print(string.format("Player occupies cells(%d): %s", #Player.Cells, table.concat(Player.Cells, ' | ')), 450,0)
end
end
-- is user off map?
function isOffMap(x, y)
if x<CELLSIZE or x+PLAYERSIZE> (1+#map[1])*CELLSIZE
or y<CELLSIZE or y+PLAYERSIZE>(1+#map)*CELLSIZE
then
return true
else
return false
end
end
function createMap()
map = {
{0,0,0,0,0,0,0,0,0,0,},
{0,0,0,1,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,1,0,},
{0,0,0,0,0,0,0,1,0,0,},
{0,0,0,1,0,0,0,0,0,0,},
{0,0,0,0,0,0,1,0,0,0,},
{1,1,1,1,1,1,1,1,1,1,},
}
end
-- which tile is that?
function posToTile(x, y)
local tx=math.floor(x/CELLSIZE)
local ty=math.floor(y/CELLSIZE)
return tx, ty
end
-- Find out which cells are occupied by a player (check for each corner)
function playerOnCells(x, y)
local Cells={}
local tx,ty=posToTile(x, y)
local key=tx..','..ty
Cells[key]=true
Cells[#Cells+1]=key
tx,ty=posToTile(x+PLAYERSIZE, y)
key=tx..','..ty
if not Cells[key] then
Cells[key]=true
Cells[#Cells+1]=key
end
tx,ty=posToTile(x+PLAYERSIZE, y+PLAYERSIZE)
key=tx..','..ty
if not Cells[key] then
Cells[key]=true
Cells[#Cells+1]=key
end
tx,ty=posToTile(x, y+PLAYERSIZE)
key=tx..','..ty
if not Cells[key] then
Cells[key]=true
Cells[#Cells+1]=key
end
return Cells
end
local isDown = love.keyboard.isDown
function playermove(dt)
-- Moving right or left?
local newX, newY
if isDown("left") then
newX=Player.x-Player.S*dt
end
if isDown("right") then
newX=Player.x+Player.S*dt
end
if newX then -- trying to move to a side
local offmap=isOffMap(newX, Player.y)
local colliding=isColliding(playerOnCells(newX, Player.y))
if not offmap and not colliding then
Player.x=newX
end
end
-- jumping up or falling down
Player.G = Player.G + Player.S*dt
if not Player.jumping and isDown(" ") and not Player.falling then
Player.jumping = true
Player.G = -100
end
-- check only for upper or lower collision
newY= Player.y + Player.G*dt -- always falling
local coll=isColliding(playerOnCells(Player.x, newY))
if coll then
if Player.G>=0 then -- falling down on the ground
Player.jumping=false
Player.falling=false
end
Player.G=0
else
Player.falling=true -- falling down
end
if not isOffMap(Player.x, newY) and not coll then
Player.y=newY
end
if DEBUG then
Player.Cells=playerOnCells(Player.x, Player.y) --
end
end
-- list of tiles
function isColliding(T)
local collision=false
for k,v in ipairs(T) do
local x,y=v:match('(%d+),(%d+)')
x,y=tonumber(x), tonumber(y)
if not map[y] or not map[y][x] then
collision=true -- off-map
elseif map[tonumber(y)][tonumber(x)] == 1 then
collision=true
end
end
return collision
end
function love.keypressed(k)
if k=='escape' then
love.event.quit()
end
if k=='d' then DEBUG=not DEBUG end
end
================================================
FILE: SpriteSheet/README.md
================================================
SpriteSheet
===========
This sample is inspired by the [spritesheet] thread.
This is a simple library, which can be used to create and play many animations from within one spritesheet.
[spritesheet]: http://love2d.org/forums/viewtopic.php?f=4&t=3103
================================================
FILE: SpriteSheet/SpriteSheet.lua
================================================
local lg=love.graphics
local Animation={}
Animation.__index=Animation
function Animation.new(spritesheet)
local obj={parent=spritesheet, name=name, frames={}, currentFrame=0, delay=0.1, playing=true, elapsed=0}
return setmetatable(obj, Animation)
end
function Animation:draw(x, y)
local quad=self.frames[self.currentFrame]
if quad then
lg.drawq(self.parent.img, quad, x, y)
end
end
function Animation:update(dt)
if #self.frames==0 or not self.playing then return end
self.elapsed=self.elapsed+dt
if self.elapsed>=self.delay then
self.elapsed=self.elapsed-self.delay
self.currentFrame=self.currentFrame+1
if self.currentFrame>#self.frames then
self.currentFrame=1
end
end
end
function Animation:addFrame(col, row)
local parent=self.parent
local w,h=parent.w, parent.h
local quad=lg.newQuad((col-1)*w, (row-1)*h, w, h, parent.imgw, parent.imgh)
self.frames[#self.frames+1]=quad
return self
end
function Animation:play()
self.playing=true
end
function Animation:stop()
self.playing=false
self.currentFrame=1
self.elapsed=0
end
function Animation:pause()
self.playing=false
end
function Animation:setDelay(s)
self.delay=s
return self
end
function Animation:getDelay()
return self.delay
end
function Animation:isPaused()
return self.playing==false
end
local SpriteSheet={}
SpriteSheet.__index=SpriteSheet
function SpriteSheet.new(img, w, h)
if type(img)=='string' then
img=lg.newImage(img)
end
local obj={img=img, w=w, h=h, Animations={}}
obj.imgw=img:getWidth()
obj.imgh=img:getHeight()
return setmetatable(obj, SpriteSheet)
end
function SpriteSheet:createAnimation(...)
local a=Animation.new(self)
return a
end
return SpriteSheet
================================================
FILE: SpriteSheet/main.lua
================================================
local SpriteSheet=require 'SpriteSheet'
function love.load()
local img='spritesheet.png'
framewidth=32
frameheight=32
S=SpriteSheet.new(img, framewidth, frameheight)
selected=0
Animations={}
for row=1,5 do
local a=S:createAnimation()
for col=1,4 do
a:addFrame(col, row)
end
Animations[#Animations+1]=a
end
a=S:createAnimation()
for row=1,5 do
for col=1,4 do
a:addFrame(col, row)
end
end
Animations[#Animations+1]=a
end
function love.update(dt)
for k,v in ipairs(Animations) do v:update(dt) end
end
function love.draw()
for k,v in ipairs(Animations) do
v:draw(k*framewidth, 0)
if k==selected then
love.graphics.setColor(255,0,0,127)
love.graphics.rectangle('fill', k*framewidth,0, framewidth, frameheight)
love.graphics.setColor(255,255, 255,255)
end
end
local a=Animations[selected]
if a then
love.graphics.print(string.format("Animation: %d Delay: %f", selected, a:getDelay()), 100, 100)
end
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)
end
function love.keypressed(k)
if k=='q' or k=='escape' then
love.event.quit()
end
local n=tonumber(k)
local a=Animations[n]
if a then
selected=n
else
a=Animations[selected]
if a then
if k==" " then
if a:isPaused() then
a:play()
else
a:pause()
end
elseif k=="right" then
a:setDelay(a:getDelay()-0.01)
elseif k=="left" then
a:setDelay(a:getDelay()+0.01)
else
selected=0
end
else
selected=0
end
end
end
================================================
FILE: TexturedPolygon/README.md
================================================
Textured Polygon
===========
This sample is inspired by the [TexturedPolygon] thread.
Given 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.
[TexturedPolygon]: http://love2d.org/forums/viewtopic.php?f=4&t=3561
================================================
FILE: TexturedPolygon/main.lua
================================================
-- Parameters:
-- target - framebuffer with black/white pixels
-- texture - file name or imageData
-- Returns:
-- Image
function texturize(target, texture)
if type(texture)=='string' then
texture=love.image.newImageData(texture)
end
tx, ty=texture:getWidth(), texture:getHeight()
local function placeTexture(x, y, r, g, b, a)
if r+g+b==0 then -- black
return 0,0,0,0
else -- non-black, needs a texture
return texture:getPixel(x%tx, y%ty)
end
end
local id=target:getImageData()
id:mapPixel(placeTexture)
return love.graphics.newImage(id)
end
-- make texturized polygon
function makePolygon(V, texture)
local t=love.image.newImageData(texture)
local minX, maxX, minY, maxY
for n=1,#V, 2 do
if not minX or minX>V[n] then minX=V[n] end
if not maxX or maxX<V[n] then maxX=V[n] end
if not minY or minY>V[n+1] then minY=V[n+1] end
if not maxY or maxY<V[n+1] then maxY=V[n+1] end
end
local w,h=maxX-minX+1, maxY-minY+1
local fb
if love.graphics.newCanvas then -- 0.8+
fb=love.graphics.newCanvas(w, h)
else --0.7
fb=love.graphics.newFramebuffer(w, h)
end
love.graphics.setCanvas(fb)
love.graphics.setColor(255,255,255)
love.graphics.translate(-minX, -minY)
love.graphics.polygon('fill', V)
love.graphics.translate(minX, minY)
love.graphics.setCanvas()
return texturize(fb, texture)
end
function love.load()
local vertices={0,0, 100,0, 200,100, 100,400, 0,300, -100,200, 0,0}
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'}
Polygons={}
for k,v in ipairs(textures) do
Polygons[k]=makePolygon(vertices, v)
end
X, Y, r=200,200,0
end
function love.draw()
local idx=math.floor(5*r%#Polygons)+1
love.graphics.draw(Polygons[1], X-5, Y-5, 0, 1, 1, X, Y)
love.graphics.draw(Polygons[idx], X, Y, r, 1, 1, X, Y)
end
function love.update(dt)
r=r+dt
end
================================================
FILE: VerbNounParser/Console.lua
================================================
local M={}
local MT={}
MT.__index=M
function M.new(P)
local o=setmetatable({}, MT)
o:initialize(P)
return o
end
function M:getName()
return 'Console'
end
function M:initialize(P)
self.prompt='> '
self.line=''
self.data={}
self.w=love.graphics.getWidth()
self.h=200
self.x=0
self.y=love.graphics.getHeight()-self.h
self.showCursor=false
self.cursorTime=0
self.callback=function(msg) print('Entered: '..msg); self:addLine(msg) end
end
function M:setCallback(cb)
self.callback=cb
end
function M:update(dt)
self.cursorTime=self.cursorTime+dt
if self.cursorTime>0.5 then
self.cursorTime=self.cursorTime-0.5
self.showCursor=not self.showCursor
end
end
function M:draw()
love.graphics.setScissor(self.x, self.y, self.w, self.h)
love.graphics.setColor(255,255,255,128)
love.graphics.rectangle('fill', self.x, self.y, self.w, self.h)
love.graphics.setColor(55,55,55,228)
--love.graphics.setLineWidth(3)
love.graphics.rectangle('line', self.x, self.y, self.w, self.h)
for k=1, #self.data do
love.graphics.print(self.data[k], self.x+5, self.y+self.h-40-(#self.data-k)*15)
end
local l=self.prompt..self.line
if self.showCursor then l=l..'_' end
love.graphics.print(l, self.x+5, self.y+self.h-20)
love.graphics.setScissor()
end
function M:keyPressed(k, u)
if k=='delete' or k=='backspace' then
if #self.line>0 then
self.line=self.line:sub(1, -2)
end
elseif k=='return' then
if type(self.callback)=='function' then
self.callback(self.line, self)
end
self.line=''
else
if u>31 then
if u<127 then
self.line=self.line..string.char(u)
else
self.line=self.line..k
end
end
end
end
function M:addLine(l)
if type(l)=='table' then
for k,v in ipairs(l) do
self:addLine(v)
end
else
table.insert(self.data, l)
if #self.data>8 then
table.remove(self.data, 1)
end
end
end
return M
================================================
FILE: VerbNounParser/Door.lua
================================================
local M={}
local MT={}
MT.__index=M
function M.new(P)
local o=setmetatable({}, MT)
o:initialize(P)
return o
end
function M:getName()
return 'Door'
end
function M:initialize(P)
self.color=P.color or 'black'
self.open=false
self.x=100+math.random(500)
self.y=250
self.w=80
self.h=100
end
function M:openAction(P)
local found=false
if #P>0 then
-- find color
for k,v in ipairs(P) do
if v:lower()==self.color:lower() then
found=true
break
end
end
else
found=true
end
if found then
if not self.open then
self.open=true
return true, 'Door '..self.color..' opened'
else
return true, 'Door '..self.color..' already open!'
end
else
return nil, 'Not for me'
end
end
function M:closeAction(P)
local found=false
if #P>0 then
-- find color
for k,v in ipairs(P) do
if v:lower()==self.color:lower() then
found=true
break
end
end
else
found=true
end
if found then
if self.open then
self.open=false
return true, 'Door '..self.color..' closed'
else
return true, 'Door '..self.color..' already closed!'
end
else
return nil, 'Not for me'
end
end
local Colors={red={255,0,0}, green={0,255,0}, black={0,0,0}}
function M:draw()
if Colors[self.color] then
love.graphics.setColor(Colors[self.color])
end
if self.open then
love.graphics.rectangle('fill', self.x, self.y, self.w/4, self.h)
else
love.graphics.rectangle('fill', self.x, self.y, self.w, self.h)
end
end
return M
================================================
FILE: VerbNounParser/Key.lua
================================================
local M={}
local MT={}
MT.__index=M
function M.new(P)
local o=setmetatable({}, MT)
o:initialize(P)
return o
end
function M:getName()
return 'Key'
end
function M:initialize(P)
self.taken=false
self.x=100+math.random(500)
self.y=250
end
function M:takeAction(P)
if not self.taken then
self.taken=true
return true, 'Key taken'
else
return true, 'Key already taken!'
end
end
function M:dropAction(P)
if self.taken then
self.taken=false
return true, 'Key dropped'
else
return true, 'Key already dropped!'
end
end
function M:draw()
love.graphics.setColor(0, 0, 0)
local x, y
if self.taken then
x, y=20, 20
else
x, y=self.x, self.y
end
love.graphics.rectangle('fill', x+10, y, 50, 20)
love.graphics.circle('fill', x, y+10, 20)
end
return M
================================================
FILE: VerbNounParser/Parser.lua
================================================
local P={}
local MT={}
MT.__index=P
function P.new(...)
local o=setmetatable({}, MT)
o:initialize(...)
return o
end
function P:registerObject(o)
table.insert(self.Objects, o)
end
function P:findObjects(name)
local o={}
for k,v in ipairs(self.Objects) do
if name:lower()==v:getName():lower() then
o[#o+1]=v
end
end
return o
end
function P:initialize(...)
self.Objects={}
end
function P:parse(buf)
-- tokenize
local tokens={}
for token in buf:gmatch('%w+') do
table.insert(tokens, token:lower())
end
-- find object
local objects
for k,v in ipairs(tokens) do
local o=self:findObjects(v)
if #o>0 then
objects=o
table.remove(tokens, k)
break
end
end
if not objects then
return nil, 'No objects found'
end
-- find action
local object=objects[1] -- assuming all objects found have the same methods
for k,v in ipairs(tokens) do
local method=v..'Action'
if type(object[method])=='function' then
table.remove(tokens, k)
local res={}
for a,b in ipairs(objects) do
local st,re=b[method](b, tokens)
if st then
res[#res+1]=re
end
end
return true, res
end
end
return nil, 'Unknown action for this object '..object:getName()
end
function P:getObjects()
return self.Objects
end
return P
================================================
FILE: VerbNounParser/README.md
================================================
VerbNounParser
===========
This sample is inspired by the [verb-noun parser] thread.
The 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).
Note that the Door class implements "color discriminator" - if you pass a color name, only door object with this color will respond.
So try following commands:
```
open window
open door
close red door
close green door
Open door
Close door red ad green please!
Please, take the key.
Drop my key now.
exit
```
[verb-noun parser]: http://love2d.org/forums/viewtopic.php?f=4&t=10291
================================================
FILE: VerbNounParser/Window.lua
================================================
local M={}
local MT={}
MT.__index=M
function M.new(P)
local o=setmetatable({}, MT)
o:initialize(P)
return o
end
function M:getName()
return 'Window'
end
function M:initialize(P)
self.open=false
self.x=100+math.random(500)
self.y=150
self.w=50
self.h=50
end
function M:openAction(P)
if not self.open then
self.open=true
return true, 'Window opened'
else
return true, 'Window already open!'
end
end
function M:closeAction(P)
if self.open then
self.open=false
return true, 'Window closed'
else
return true, 'Window already closed!'
end
end
function M:draw()
love.graphics.setColor(0, 100, 255)
if self.open then
love.graphics.rectangle('fill', self.x, self.y, self.w/4, self.h)
else
love.graphics.rectangle('fill', self.x, self.y, self.w, self.h)
end
end
return M
================================================
FILE: VerbNounParser/main.lua
================================================
local Parser=require 'Parser'
local Door=require 'Door'
local Window=require 'Window'
local Key=require 'Key'
local Console=require 'Console'
local Objects
function love.load()
love.graphics.setBackgroundColor(255, 255, 255)
P=Parser.new()
local blackdoor=Door.new({color='black'})
local greendoor=Door.new({color='green'})
local reddoor=Door.new({color='red'})
local window=Window.new()
console=Console.new()
local key=Key.new()
P:registerObject(greendoor)
P:registerObject(reddoor)
P:registerObject(blackdoor)
P:registerObject(window)
P:registerObject(key)
console:setCallback(function(buf)
if buf=='exit' or buf=='quit' then
love.event.quit()
end
local st, res=P:parse(buf)
if st then
console:addLine(res)
else
console:addLine('Error: '.. res)
end
end)
end
function love.draw()
for k,v in ipairs(P:getObjects()) do
v:draw()
end
console:draw()
end
function love.update(dt)
console:update(dt)
end
function love.keypressed(k, u)
console:keyPressed(k, u)
end
gitextract_xy8xzx00/
├── CodeCapture/
│ ├── CodeCapture.lua
│ ├── README.md
│ └── main.lua
├── CollisionExample/
│ ├── README.md
│ └── main.lua
├── Fireworks/
│ ├── Firework.lua
│ ├── FireworkEngine.lua
│ ├── Particle.lua
│ ├── README.md
│ ├── Vector.lua
│ ├── class.lua
│ └── main.lua
├── GameOfLife/
│ ├── Readme.md
│ └── main.lua
├── LICENSE
├── MikoIntroScreen/
│ ├── Intro.lua
│ ├── README.md
│ ├── class.lua
│ ├── conf.lua
│ ├── main.lua
│ └── zero-project - 01 - Celtic dream.ogg
├── Minefield/
│ ├── conf.lua
│ ├── main.lua
│ └── menu.lua
├── Obey/
│ ├── B.lua
│ ├── Char.lua
│ ├── E.lua
│ ├── O.lua
│ ├── README.md
│ ├── Y.lua
│ ├── class.lua
│ └── main.lua
├── README.md
├── SidescrollerCollision/
│ ├── README.md
│ └── main.lua
├── SpriteSheet/
│ ├── README.md
│ ├── SpriteSheet.lua
│ └── main.lua
├── TexturedPolygon/
│ ├── README.md
│ └── main.lua
└── VerbNounParser/
├── Console.lua
├── Door.lua
├── Key.lua
├── Parser.lua
├── README.md
├── Window.lua
└── main.lua
Condensed preview — 47 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (71K chars).
[
{
"path": "CodeCapture/CodeCapture.lua",
"chars": 893,
"preview": "local M={}\nM.KONAMI={'up','up','down','down','left','right','left','right','b','a'}\n\nlocal STATES={}\nlocal CURRSTATE\n\nlo"
},
{
"path": "CodeCapture/README.md",
"chars": 767,
"preview": "CodeCapture\n===========\n\nThis sample is inspired by the [KonamiCode] thread.\n\nThis is a simple library, which can be use"
},
{
"path": "CodeCapture/main.lua",
"chars": 749,
"preview": "local CodeCapture=require 'CodeCapture'\n\nfunction love.load()\n CodeCapture.setCode(\"qwerty\", function() MODE='ONE' end)"
},
{
"path": "CollisionExample/README.md",
"chars": 995,
"preview": "Collision example\n===========\n\nThis sample is inspired by the [RestrictRectangleMovement] thread.\n\nThe sample illustrate"
},
{
"path": "CollisionExample/main.lua",
"chars": 1764,
"preview": "local lg=love.graphics\nfunction love.load()\n W, H=lg.getWidth(), lg.getHeight()\n local w,h=40,40\n Obstacles={}\n for "
},
{
"path": "Fireworks/Firework.lua",
"chars": 2196,
"preview": "require 'class'\nlocal Vector=require 'Vector'\nlocal Particle=require 'Particle'\nSTATE={ROCKET=1, EXPLODE=2, LIVE=3, DEAD"
},
{
"path": "Fireworks/FireworkEngine.lua",
"chars": 568,
"preview": "require 'class'\nFirework=require 'Firework'\n\nlocal M=class(function(self)\n self.Fireworks={}\nend)\n\nfunction M:update(dt"
},
{
"path": "Fireworks/Particle.lua",
"chars": 958,
"preview": "require 'class'\nlocal Vector=require 'Vector'\nlocal lg=love.graphics\n\nlocal M=class(function(self, x, y, R, G, B, v)\n s"
},
{
"path": "Fireworks/README.md",
"chars": 328,
"preview": "Fireworks example\n==============\n\nThis is an example of fireworks, inspired by the [facepunch] thread, which is mentione"
},
{
"path": "Fireworks/Vector.lua",
"chars": 785,
"preview": "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"
},
{
"path": "Fireworks/class.lua",
"chars": 1246,
"preview": "--[[\n-- $Id: class.lua 10 2008-07-01 22:18:32Z basique $\n-- Simple class implementation\n-- Taken from http://lua-users.o"
},
{
"path": "Fireworks/main.lua",
"chars": 396,
"preview": "FireworkEngine=require 'FireworkEngine'\nfunction love.load()\n FE=FireworkEngine()\n love.graphics.setBlendMode('additiv"
},
{
"path": "GameOfLife/Readme.md",
"chars": 631,
"preview": "Game of Life\n============\n\nGame of Life inspired by [this thread](http://love2d.org/forums/viewtopic.php?f=4&t=2858)\n\nCo"
},
{
"path": "GameOfLife/main.lua",
"chars": 4784,
"preview": "-- Game of Life by miko\n-- Controls:\n-- 0, 1, 2 - set cell border width\n-- left,right - decrease/increase no of columns\n"
},
{
"path": "LICENSE",
"chars": 1405,
"preview": "All the code within this repository is licensed under the terms of the MIT license reproduced below. So it is free to us"
},
{
"path": "MikoIntroScreen/Intro.lua",
"chars": 8857,
"preview": "require 'class'\n\n--love=love or {graphics={}} -- plain lua compatibility\nlocal lg=love.graphics\nif not lg.newFramebuffer"
},
{
"path": "MikoIntroScreen/README.md",
"chars": 475,
"preview": "LOVEJam Intro Screen\n===========\n\nThis sample is inspired by the [LOVEJam] site.\n\nThis is a splash screen intro, and als"
},
{
"path": "MikoIntroScreen/class.lua",
"chars": 1246,
"preview": "--[[\n-- $Id: class.lua 10 2008-07-01 22:18:32Z basique $\n-- Simple class implementation\n-- Taken from http://lua-users.o"
},
{
"path": "MikoIntroScreen/conf.lua",
"chars": 151,
"preview": "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"
},
{
"path": "MikoIntroScreen/main.lua",
"chars": 727,
"preview": "local Intro=require 'Intro'\nfunction love.load()\n I=Intro()\n local t1=I:addText('LoveJam Test Jam entry!'):setPosition"
},
{
"path": "Minefield/conf.lua",
"chars": 465,
"preview": "function love.conf(t)\n\tt.modules.joystick = false\n\tt.modules.audio = false\n\tt.modules.keyboard = true\n\tt.modules.event ="
},
{
"path": "Minefield/main.lua",
"chars": 5691,
"preview": "local lg=love.graphics\nORGWIDTH, ORGHEIGHT=lg.getWidth(), lg.getHeight()\nlocal Menu=require 'menu'\n\nfunction love.load()"
},
{
"path": "Minefield/menu.lua",
"chars": 2838,
"preview": "local lg=love.graphics\nlocal Options={\n {name='play', title='Play the game!'},\n {name='help', title='Help'},\n {name='"
},
{
"path": "Obey/B.lua",
"chars": 677,
"preview": "local Char=require('Char')\nlocal lg=love.graphics\n\nlocal M=class(Char, function(self, W, H)\n Char.init(self, 'B', W, H)"
},
{
"path": "Obey/Char.lua",
"chars": 2588,
"preview": "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={"
},
{
"path": "Obey/E.lua",
"chars": 397,
"preview": "local Char=require('Char')\nlocal lg=love.graphics\n\nlocal M=class(Char, function(self, W, H)\n Char.init(self, 'E', W, H)"
},
{
"path": "Obey/O.lua",
"chars": 478,
"preview": "local Char=require('Char')\nlocal lg=love.graphics\n\nlocal M=class(Char, function(self, W, H)\n Char.init(self, 'O', W, H)"
},
{
"path": "Obey/README.md",
"chars": 264,
"preview": "Obeying avatar\n===========\n\nThis sample is inspired by the [AngryLovers] thread.\n\nIt creates an avatar animation. The ke"
},
{
"path": "Obey/Y.lua",
"chars": 361,
"preview": "local Char=require('Char')\nlocal lg=love.graphics\n\nlocal M=class(Char, function(self, W, H)\n Char.init(self, 'Y', W, H)"
},
{
"path": "Obey/class.lua",
"chars": 1246,
"preview": "--[[\n-- $Id: class.lua 10 2008-07-01 22:18:32Z basique $\n-- Simple class implementation\n-- Taken from http://lua-users.o"
},
{
"path": "Obey/main.lua",
"chars": 1223,
"preview": "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,9"
},
{
"path": "README.md",
"chars": 263,
"preview": "Love2d samples\n==============\n\nThis is a repository for sample games and applications which I am playing with while lear"
},
{
"path": "SidescrollerCollision/README.md",
"chars": 1196,
"preview": "Sidescroller Collision example\n===========\n\nThis sample is a follow-up to my earlier [CollisionExample]. This time this "
},
{
"path": "SidescrollerCollision/main.lua",
"chars": 3873,
"preview": "function love.load()\n CELLSIZE=32\n PLAYERSIZE=16\n\n Player={x=92, y=100, G=-100, S=100, jumping=false, falling=false, "
},
{
"path": "SpriteSheet/README.md",
"chars": 254,
"preview": "SpriteSheet\n===========\n\nThis sample is inspired by the [spritesheet] thread.\n\nThis is a simple library, which can be us"
},
{
"path": "SpriteSheet/SpriteSheet.lua",
"chars": 1736,
"preview": "local lg=love.graphics\n\nlocal Animation={}\nAnimation.__index=Animation\n\nfunction Animation.new(spritesheet)\n local obj="
},
{
"path": "SpriteSheet/main.lua",
"chars": 1768,
"preview": "local SpriteSheet=require 'SpriteSheet'\n\nfunction love.load()\n local img='spritesheet.png'\n framewidth=32\n frameheigh"
},
{
"path": "TexturedPolygon/README.md",
"chars": 377,
"preview": "Textured Polygon\n===========\n\nThis sample is inspired by the [TexturedPolygon] thread.\n\nGiven the texture image, it plac"
},
{
"path": "TexturedPolygon/main.lua",
"chars": 1981,
"preview": "\n-- Parameters:\n-- target - framebuffer with black/white pixels\n-- texture - file name or imageData\n-- Returns:\n-- Im"
},
{
"path": "VerbNounParser/Console.lua",
"chars": 1958,
"preview": "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\n"
},
{
"path": "VerbNounParser/Door.lua",
"chars": 1585,
"preview": "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\n"
},
{
"path": "VerbNounParser/Key.lua",
"chars": 812,
"preview": "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\n"
},
{
"path": "VerbNounParser/Parser.lua",
"chars": 1357,
"preview": "local P={}\nlocal MT={}\nMT.__index=P\n\nfunction P.new(...)\n local o=setmetatable({}, MT)\n o:initialize(...)\n return o\ne"
},
{
"path": "VerbNounParser/README.md",
"chars": 1003,
"preview": "VerbNounParser\n===========\n\nThis sample is inspired by the [verb-noun parser] thread.\n\nThe idea is to register a sef of "
},
{
"path": "VerbNounParser/Window.lua",
"chars": 841,
"preview": "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\n"
},
{
"path": "VerbNounParser/main.lua",
"chars": 1052,
"preview": "local Parser=require 'Parser'\nlocal Door=require 'Door'\nlocal Window=require 'Window'\nlocal Key=require 'Key'\nlocal Cons"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the miko/Love2d-samples GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 47 files (64.7 KB), approximately 21.7k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.