Mercurial > vanillian
changeset 0:716ff40413d2
initial commit
| author | Radomir Dopieralski <sheep-devel@sheep.art.pl> |
|---|---|
| date | Sat, 15 Dec 2012 10:23:11 +0100 |
| parents | |
| children | 71b36e588242 |
| files | anim8.lua civilian.png main.lua sprite.lua villain.png |
| diffstat | 5 files changed, 316 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/anim8.lua Sat Dec 15 10:23:11 2012 +0100 @@ -0,0 +1,259 @@ +-- anim8 v1.1.1 - 2012-06 +-- Copyright (c) 2011 Enrique GarcĂa Cota +-- 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. + +local Grid = {} + +local _frames = {} + +local function assertPositiveInteger(value, name) + if type(value) ~= 'number' then error(("%s should be a number, was %q"):format(name, tostring(value))) end + if value < 1 then error(("%s should be a positive number, was %d"):format(name, value)) end + if value ~= math.floor(value) then error(("%s should be an integer, was %d"):format(name, value)) end +end + +local function createFrame(self, x, y) + local fw, fh = self.frameWidth, self.frameHeight + return love.graphics.newQuad( + self.left + (x-1) * fw + x * self.border, + self.top + (y-1) * fh + y * self.border, + fw, + fh, + self.imageWidth, + self.imageHeight + ) +end + +local function getGridKey(...) + return table.concat( {...} ,'-' ) +end + + +local function getOrCreateFrame(self, x, y) + if x < 1 or x > self.width or y < 1 or y > self.height then + error(("There is no frame for x=%d, y=%d"):format(x, y)) + end + local key = self._key + _frames[key] = _frames[key] or {} + _frames[key][x] = _frames[key][x] or {} + _frames[key][x][y] = _frames[key][x][y] or createFrame(self, x, y) + return _frames[key][x][y] +end + +local function parseInterval(str) + str = str:gsub(' ', '') + local min, max = str:match("^(%d+)-(%d+)$") + if not min then + min = str:match("^%d+$") + max = min + end + assert(min and max, ("Could not parse interval from %q"):format(str)) + min, max = tonumber(min), tonumber(max) + local step = min <= max and 1 or -1 + return min, max, step +end + +local function parseIntervals(str) + local left, right = str:match("(.+),(.+)") + assert(left and right, ("Could not parse intervals from %q"):format(str)) + local minx, maxx, stepx = parseInterval(left) + local miny, maxy, stepy = parseInterval(right) + return minx, maxx, stepx, miny, maxy, stepy +end + +local function parseFrames(self, args, result, position) + local current = args[position] + local kind = type(current) + + if kind == 'number' then + + result[#result + 1] = getOrCreateFrame(self, current, args[position + 1]) + return position + 2 + + elseif kind == 'string' then + + local minx, maxx, stepx, miny, maxy, stepy = parseIntervals(current) + for y = miny, maxy, stepy do + for x = minx, maxx, stepx do + result[#result+1] = getOrCreateFrame(self,x,y) + end + end + + return position + 1 + + else + + error(("Invalid type: %q (%s)"):format(kind, tostring(args[position]))) + + end +end + +function Grid:getFrames(...) + local args = {...} + local length = #args + local result = {} + local position = 1 + + while position <= length do + position = parseFrames(self, args, result, position) + end + + return result +end + +local Gridmt = { + __index = Grid, + __call = Grid.getFrames +} + +local function newGrid(frameWidth, frameHeight, imageWidth, imageHeight, left, top, border) + assertPositiveInteger(frameWidth, "frameWidth") + assertPositiveInteger(frameHeight, "frameHeight") + assertPositiveInteger(imageWidth, "imageWidth") + assertPositiveInteger(imageHeight, "imageHeight") + + left = left or 0 + top = top or 0 + border = border or 0 + + local key = getGridKey(frameWidth, frameHeight, imageWidth, imageHeight, left, top, border) + + local grid = setmetatable( + { frameWidth = frameWidth, + frameHeight = frameHeight, + imageWidth = imageWidth, + imageHeight = imageHeight, + left = left, + top = top, + border = border, + width = math.floor(imageWidth/frameWidth), + height = math.floor(imageHeight/frameHeight), + _key = key + }, + Gridmt + ) + return grid +end + +----------------------------------------------------------- + +local Animation = {} + +local function cloneArray(arr) + local result = {} + for i=1,#arr do result[i] = arr[i] end + return result +end + +local function parseDelays(delays) + local parsedDelays = {} + local tk,min,max,step + for k,v in pairs(delays) do + tk = type(k) + if tk == "number" + then parsedDelays[k] = v + elseif tk == "string" then + min, max, step = parseInterval(k) + for i = min,max,step do parsedDelays[i] = v end + else + error(("Unexpected delay key: [%s]. Expected a number or a string"):format(tostring(k))) + end + end + return parsedDelays +end + +local function repeatValue(value, times) + local result = {} + for i=1,times do result[i] = value end + return result +end + +local function createDelays(frames, defaultDelay, delays) + local maxFrames = #frames + local result = repeatValue(defaultDelay, maxFrames) + for i,v in pairs(parseDelays(delays)) do + if i > maxFrames then + error(("The delay value %d is too high; there are only %d frames"):format(i, maxFrames)) + end + result[i] = v + end + return result +end + +local animationModes = { + loop = function(self) self.position = 1 end, + once = function(self) + self.position = #self.frames + self.status = "finished" + end, + bounce = function(self) + self.direction = self.direction * -1 + self.position = self.position + self.direction + self.direction + end +} + +local Animationmt = { __index = Animation } + +local function newAnimation(mode, frames, defaultDelay, delays) + delays = delays or {} + assert(animationModes[mode], ("%q is not a valid mode"):format(tostring(mode))) + assert(type(defaultDelay) == 'number' and defaultDelay > 0, "defaultDelay must be a positive number" ) + assert(type(delays) == 'table', "delays must be a table or nil") + return setmetatable({ + mode = mode, + frames = cloneArray(frames), + endSequence = animationModes[mode], + delays = createDelays(frames, defaultDelay, delays), + timer = 0, + position = 1, + direction = 1, + status = "playing" + }, + Animationmt + ) +end + +function Animation:clone() + return newAnimation(self.mode, self.frames, 1, self.delays) +end + +function Animation:update(dt) + if self.status ~= "playing" then return end + + self.timer = self.timer + dt + + while self.timer > self.delays[self.position] do + self.timer = self.timer - self.delays[self.position] + self.position = self.position + self.direction + if self.position < 1 or self.position > #self.frames then + self:endSequence() + end + end +end + +function Animation:pause() + self.status = "paused" +end + +function Animation:resume() + self.status = "playing" +end + +function Animation:gotoFrame(position) + self.position = position +end + +function Animation:draw(image, x, y, r, sx, sy, ox, oy) + local frame = self.frames[self.position] + love.graphics.drawq(image, frame, x, y, r, sx, sy, ox, oy) +end + +----------------------------------------------------------- + +local anim8 = { + newGrid = newGrid, + newAnimation = newAnimation +} +return anim8
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.lua Sat Dec 15 10:23:11 2012 +0100 @@ -0,0 +1,31 @@ +local anim8 = require("anim8") +local sprite = require("sprite") + +local sprites = {} + +function love.load() + local VILLAIN_IMAGE = love.graphics.newImage('villain.png') + local CIVILIAN_IMAGE = love.graphics.newImage('civilian.png') + local grid = anim8.newGrid(64, 64, 128, 128) + table.insert(sprites, sprite.newSprite( + 255, + 255, + VILLAIN_IMAGE, + anim8.newAnimation('loop', grid('1-2,1'), 0.25) + )) +end + + +function love.draw() + for k, sprite in pairs(sprites) do + sprite:draw() + end +end + + +function love.update(dt) + for k, sprite in pairs(sprites) do + sprite:update(dt) + end + table.sort(sprites, function (a, b) return a.y < b.y end) +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sprite.lua Sat Dec 15 10:23:11 2012 +0100 @@ -0,0 +1,26 @@ +local Sprite = {} +local Sprite_mt = { __index = Sprite } + +local function newSprite(x, y, image, animation) + local sprite = setmetatable({ + x = x, + y = y, + image = image, + animation = animation, + }, Sprite_mt) + return sprite +end + +function Sprite:draw() + self.animation:draw(self.image, math.floor(self.x), math.floor(self.y)) +end + +function Sprite:update(dt) + self.animation:update(dt) +end + +local sprite = { + newSprite = newSprite, +} + +return sprite
