diff options
author | piernov <piernov@piernov.org> | 2014-03-13 16:14:10 +0100 |
---|---|---|
committer | piernov <piernov@piernov.org> | 2014-03-13 16:14:10 +0100 |
commit | 9004e721dd27b2d1c330cf1ce35771ca3c91ac82 (patch) | |
tree | b45e7ce8775e3badc84233a0079fd9628303559b | |
download | MaiLÖVE-9004e721dd27b2d1c330cf1ce35771ca3c91ac82.tar.gz MaiLÖVE-9004e721dd27b2d1c330cf1ce35771ca3c91ac82.tar.bz2 MaiLÖVE-9004e721dd27b2d1c330cf1ce35771ca3c91ac82.tar.xz MaiLÖVE-9004e721dd27b2d1c330cf1ce35771ca3c91ac82.zip |
Importation du projet
-rwxr-xr-x | Config.lua | 7 | ||||
-rwxr-xr-x | Files.lua | 102 | ||||
-rwxr-xr-x | Game.lua | 127 | ||||
-rwxr-xr-x | Menu.lua | 64 | ||||
-rwxr-xr-x | SMFileSchema.lua | 52 | ||||
-rwxr-xr-x | Utils.lua | 56 | ||||
-rwxr-xr-x | main.lua | 36 |
7 files changed, 444 insertions, 0 deletions
diff --git a/Config.lua b/Config.lua new file mode 100755 index 0000000..65eb993 --- /dev/null +++ b/Config.lua @@ -0,0 +1,7 @@ +local Config = {}
+
+Config.width, Config.height = love.window.getDimensions()
+
+Config.songsPerPages = 5
+
+return Config
diff --git a/Files.lua b/Files.lua new file mode 100755 index 0000000..8fc19fe --- /dev/null +++ b/Files.lua @@ -0,0 +1,102 @@ +local Files = {}
+
+function Files.findSongs(folder, fileTree)
+ if folder == nil then folder = "" end
+ if fileTree == nil then fileTree = {} end
+ local filesTable = love.filesystem.getDirectoryItems(folder)
+ for i,v in ipairs(filesTable) do
+ local file = folder.."/"..v
+ if love.filesystem.isFile(file) and v:sub(-3) == ".sm" then
+ table.insert(fileTree, file)
+ elseif love.filesystem.isDirectory(file) then
+ fileTree = Files.findSongs(file, fileTree)
+ end
+ end
+ return fileTree
+end
+
+function Files.readNotesInfos(smInfo)
+
+ local pos = { mesure = 1, beat = 1, note = 1}
+ local state = 0
+ local numNotes = 0
+
+ for line in love.filesystem.lines(smInfo.file) do
+ line = line:gsub("//.*", "")
+
+ local info, text= line:match("^#(%u+):(.-);?%s*$")
+
+ if info == "NOTES" then
+ pos = { mesure = 1, beat = 1, note = 1}
+ state = 1
+ numNotes = numNotes + 1
+ if numNotes > 1 then
+ smInfo["notes"][numNotes] = Utils.copyTable(SMFileSchema.FileSchema["notes"][1])
+ end
+
+ elseif state > 0 and state < SMFileSchema.NotesInfos.noteData then
+
+ if state <= SMFileSchema.NotesInfos.difficultyMeter then
+ tmp = line:match("^%s*(.+):.*$")
+ elseif state == SMFileSchema.NotesInfos.radarValues then
+ tmp = {}
+ for i in line:gmatch("%d+%.%d+") do
+ table.insert(tmp,i)
+ end
+ end
+
+ if tmp then
+ smInfo["notes"][numNotes][state][2] = tmp
+ state = state + 1
+ end
+ elseif state == SMFileSchema.NotesInfos.noteData then
+ for c in line:gmatch"." do
+ if c == "," then
+ pos.beat = 1
+ pos.mesure = pos.mesure + 1
+ elseif c == ";" then
+ pos = { mesure = 1, beat = 1, note = 1}
+ elseif c:find("%w") then
+ if not smInfo["notes"][numNotes][SMFileSchema.NotesInfos.noteData][2][pos.mesure] then
+ smInfo["notes"][numNotes][SMFileSchema.NotesInfos.noteData][2][pos.mesure] = {}
+ end
+ if not smInfo["notes"][numNotes][SMFileSchema.NotesInfos.noteData][2][pos.mesure][pos.beat] then
+ smInfo["notes"][numNotes][SMFileSchema.NotesInfos.noteData][2][pos.mesure][pos.beat] = {}
+ end
+
+ table.insert(smInfo["notes"][numNotes][SMFileSchema.NotesInfos.noteData][2][pos.mesure][pos.beat], c)
+
+ if #smInfo["notes"][numNotes][SMFileSchema.NotesInfos.noteData][2][pos.mesure][pos.beat] >= SMFileSchema.NotesType[smInfo["notes"][numNotes][SMFileSchema.NotesInfos.notesType][2]] then
+ pos.beat = pos.beat + 1
+ end
+ end
+ end
+ end
+ end
+
+ return smInfo
+end
+
+function Files.getSMInfo(file)
+ local smInfo = Utils.copyTable(SMFileSchema.FileSchema)
+ smInfo.file = file
+ for line in love.filesystem.lines(smInfo.file) do
+ line = line:gsub("//.*", "")
+
+ local info, text= line:match("^#(%u+):(.-);?%s*$")
+
+ if info and info ~= "NOTES" then
+ if type(smInfo[info:lower()]) == "table" then
+ for i in text:gmatch("%d+%.%d+=%d+%.%d+") do
+ local beat, bpm = i:match("(%d+%.%d+)=(%d+%.%d+)")
+ smInfo[info:lower()][beat] = bpm
+ end
+ else
+ smInfo[info:lower()] = text
+ end
+ end
+ end
+ return smInfo
+end
+
+return Files
diff --git a/Game.lua b/Game.lua new file mode 100755 index 0000000..c4cc8f5 --- /dev/null +++ b/Game.lua @@ -0,0 +1,127 @@ +local Game = {}
+
+local buttonRadius = 5
+
+function Game:init()
+ self.button = love.graphics.newCanvas( 100, 100, "normal", 16 )
+ love.graphics.setCanvas(self.button)
+ self.button:clear()
+ love.graphics.setBlendMode('alpha')
+ love.graphics.setColor(0, 0, 0, 255)
+ love.graphics.circle( "fill", 50, 50, (buttonRadius/100)*Config.height, 100 )
+ love.graphics.setColor(255, 0, 0, 255)
+ love.graphics.circle( "fill", 50, 50, ((buttonRadius-1)/100)*Config.height, 100 )
+ love.graphics.setCanvas()
+
+ self.circle = love.graphics.newCanvas( 100, 100, "normal", 16 )
+ love.graphics.setCanvas(self.circle)
+ self.circle:clear()
+ love.graphics.setBlendMode('alpha')
+ love.graphics.setColor(0, 0, 0, 128)
+ love.graphics.circle( "fill", 50, 50, (buttonRadius/100)*Config.height, 100 )
+ love.graphics.setColor(255, 0, 0, 128)
+ love.graphics.circle( "fill", 50, 50, ((buttonRadius-1)/100)*Config.height, 100 )
+ love.graphics.setCanvas()
+end
+
+function Game:enter(previous, song, id)
+ self.song = song
+ self.level = id
+ for k,v in pairs(self.song.bpms) do self.beatDuration = 60000*4/v break end
+ --self.beatDuration = 60000*4/self.song.bpms["0.000"]
+ self.music = love.audio.newSource(song.file:match("(.*/)") .. song.music)
+ love.graphics.setBackgroundColor(104, 136, 248)
+end
+
+local tx=0
+local ty=0
+local tp=0
+
+function love.touchpressed(x, y, p)
+ tp = p
+ tx = x
+ ty = y
+end
+
+local speed = 50
+local offset = -1000*45/speed
+local timer = offset
+local musicplaying = false
+local lastnote = -1
+local beat = 0
+local noteTime = 0
+local beatTime = 0
+
+local displayedNotes = {}
+
+function Game:update(dt)
+ if timer < 0 then
+ timer = timer + dt*1000
+ else
+ if not musicplaying then
+ musicplaying = true
+ self.music:play()
+ end
+ timer = self.music:tell("seconds")*1000
+ end
+
+ for k, v in pairs(displayedNotes) do
+ if v.x > 95-buttonRadius or v.y > 95-buttonRadius or v.x < 5-buttonRadius or v.y < 5-buttonRadius then
+ table.remove(displayedNotes, k)
+ elseif v.orientation == "left" then
+ displayedNotes[k].y = v.y + dt*speed
+ elseif v.orientation == "down" then
+ displayedNotes[k].x = v.x + dt*speed
+ elseif v.orientation == "up" then
+ displayedNotes[k].y = v.y - dt*speed
+ elseif v.orientation == "right" then
+ displayedNotes[k].x = v.x - dt*speed
+ end
+ end
+
+ beat = math.ceil((timer-offset)/self.beatDuration)
+ if beat < 1 then return end
+
+ noteTime = self.beatDuration/#self.song.notes[self.level][SMFileSchema.NotesInfos.noteData][2][beat]
+ beatTime = (timer-offset)-(beat-1)*self.beatDuration
+ notes = math.ceil(beatTime/noteTime)
+
+ if lastnote ~= notes then
+ lastnote = notes
+ notes = self.song.notes[self.level][SMFileSchema.NotesInfos.noteData][2][beat][notes]
+ if notes[1] == "1" then table.insert(displayedNotes, { x = 50-buttonRadius, y = 50-buttonRadius, orientation = "left" }) end
+ if notes[2] == "1" then table.insert(displayedNotes, { x = 50-buttonRadius, y = 50-buttonRadius, orientation = "down" }) end
+ if notes[3] == "1" then table.insert(displayedNotes, { x = 50-buttonRadius, y = 50-buttonRadius, orientation = "up" }) end
+ if notes[4] == "1" then table.insert(displayedNotes, { x = 50-buttonRadius, y = 50-buttonRadius, orientation = "right" }) end
+ end
+
+end
+
+function Game:draw()
+ love.graphics.clear()
+ love.graphics.setColor(255, 0, 0)
+ love.graphics.setBlendMode('alpha')
+ love.graphics.print(timer, 320, 300)
+ for k,v in pairs(self.song.bpms) do love.graphics.print(v, 200, 300) end
+ love.graphics.print(beat, 200, 200)
+ love.graphics.print(lastnote, 200, 100)
+ love.graphics.print(noteTime, 200, 50)
+ love.graphics.print(beatTime, 200, 150)
+
+ love.graphics.print(tp, 350, 150)
+ love.graphics.print(tx, 370, 150)
+ love.graphics.print(ty, 390, 150)
+
+ love.graphics.setBlendMode('premultiplied')
+ love.graphics.draw(self.circle, Utils.percentCoordinates(5-buttonRadius, 50-buttonRadius))
+ love.graphics.draw(self.circle, Utils.percentCoordinates(50-buttonRadius, 95-buttonRadius))
+ love.graphics.draw(self.circle, Utils.percentCoordinates(50-buttonRadius, 5-buttonRadius))
+ love.graphics.draw(self.circle, Utils.percentCoordinates(95-buttonRadius, 50-buttonRadius))
+ --love.graphics.draw(self.button, Utils.percentCoordinates(x, 50))
+
+ for k, v in pairs(displayedNotes) do
+ love.graphics.draw(self.button, Utils.percentCoordinates(v.x, v.y))
+ end
+end
+
+return Game
diff --git a/Menu.lua b/Menu.lua new file mode 100755 index 0000000..e75fa01 --- /dev/null +++ b/Menu.lua @@ -0,0 +1,64 @@ +local Menu = {}
+
+function loadSongs()
+ local songs = {}
+ for _,song in pairs(Files.findSongs(nil, nil)) do
+ table.insert(songs, Files.getSMInfo(song))
+ end
+ table.sort(songs, Utils.sortByArtistAndTitle)
+ return songs
+end
+
+function Menu:init()
+ self.songs = loadSongs()
+ self.pageNumber = 0
+end
+
+function Menu:update(dt)
+ Gui.group{grow = "down", pos = {Utils.percentCoordinates(10, 10)}, function()
+ for id = (self.pageNumber*Config.songsPerPages)+1, (self.pageNumber*Config.songsPerPages)+Config.songsPerPages do
+ local smInfo = self.songs[id]
+ if smInfo and smInfo.title then
+ if Gui.Button{text = string.format("%s — %s", smInfo.artist, smInfo.title), size = {Utils.percentCoordinates(80, 80/Config.songsPerPages)}} then
+ Gamestate.switch(Menu.selectDifficulty, self.songs[id])
+ end
+ end
+ end
+ end}
+
+ if self.pageNumber > 0 and Gui.Button{text = "<", pos = {Utils.percentCoordinates(2, 50)}, size = {Utils.percentCoordinates(5, 5)}} then
+ self.pageNumber = self.pageNumber - 1
+ end
+
+ if self.pageNumber+1 < #self.songs/Config.songsPerPages and Gui.Button{text = ">", pos = {Utils.percentCoordinates(93, 50)}, size = {Utils.percentCoordinates(5, 5)}} then
+ self.pageNumber = self.pageNumber + 1
+ end
+end
+
+Menu.selectDifficulty = {}
+
+function Menu.selectDifficulty:init()
+ self.pageNumber = 0
+end
+
+function Menu.selectDifficulty:enter(previous, song)
+ self.song = Files.readNotesInfos(song)
+end
+
+function Menu.selectDifficulty:update()
+ Gui.group{grow = "down", pos = {Utils.percentCoordinates(10, 10)}, function()
+ for id = (self.pageNumber*Config.songsPerPages)+1, (self.pageNumber*Config.songsPerPages)+Config.songsPerPages do
+ local level = self.song["notes"][id]
+ if level and level[SMFileSchema.NotesInfos.description][2] then
+ if Gui.Button{text = string.format("%s — %s", level[SMFileSchema.NotesInfos.description][2], level[SMFileSchema.NotesInfos.difficultyClass][2]), size = {Utils.percentCoordinates(80, 80/Config.songsPerPages)}} then
+ Gamestate.switch(Game, self.song, id)
+ end
+ end
+ end
+ end}
+ if Gui.Button{text = "<-", pos = {Utils.percentCoordinates(50, 93)}, size = {Utils.percentCoordinates(5, 5)}} then
+ Gamestate.switch(Menu)
+ end
+end
+
+return Menu
diff --git a/SMFileSchema.lua b/SMFileSchema.lua new file mode 100755 index 0000000..45cbe7b --- /dev/null +++ b/SMFileSchema.lua @@ -0,0 +1,52 @@ +SMFileSchema = {} + +SMFileSchema.FileSchema = { + title = "", + subtitle = "", + artist = "", + titletranslit = "", + subtitletranslit = "", + artisttranslit = "", + credit = "", + banner = "", + background = "", + cdtitle = "", + music = "", + offset = 0, + samplestart = 0, + samplelength = 0, + selectable = "", + bpms = {}, + displaybpm = {}, + stops = {}, + bgchanges = {}, + + notes = + { + { + {"notesType", ""}, + {"description", ""}, + {"difficultyClass", ""}, + {"difficultyMeter", 1}, + {"radarValues", ""}, + {"noteData", {}} + } + } +} + +SMFileSchema.NotesInfos = Utils.tuple2ToIndexHash(SMFileSchema.FileSchema["notes"][1]) + +SMFileSchema.NotesType = {} +SMFileSchema.NotesType["dance-single"] = 4 +SMFileSchema.NotesType["dance-double"] = 8 +SMFileSchema.NotesType["dance-couple"] = 8 +SMFileSchema.NotesType["dance-solo"] = 6 +SMFileSchema.NotesType["pump-single"] = 5 +SMFileSchema.NotesType["pump-double"] = 10 +SMFileSchema.NotesType["pump-couple"] = 10 +SMFileSchema.NotesType["ez2-single"] = 5 +SMFileSchema.NotesType["ez2-double"] = 10 +SMFileSchema.NotesType["ez2-real"] = 7 +SMFileSchema.NotesType["para-single"] = 5 + +return SMFileSchema diff --git a/Utils.lua b/Utils.lua new file mode 100755 index 0000000..5e06f97 --- /dev/null +++ b/Utils.lua @@ -0,0 +1,56 @@ +local Utils = {}
+
+function Utils.percentCoordinates(x, y)
+ x = (x/100)*Config.width
+ y = (y/100)*Config.height
+ return x, y
+end
+
+function Utils.tprint(tbl, indent)
+if not indent then indent = 0 end
+for k, v in pairs(tbl) do
+formatting = string.rep(" ", indent) .. k .. ": "
+if type(v) == "table" then
+print(formatting)
+Utils.tprint(v, indent+1)
+else
+print(formatting .. v)
+end
+end
+end
+
+function Utils.tuple2ToIndexHash(table)
+ local tmp = {}
+ for k,v in pairs(table) do
+ tmp[v[1]] = k
+ end
+ return tmp
+end
+
+-- From http://lua-users.org/wiki/CopyTable
+function Utils.copyTable(orig)
+ local orig_type = type(orig)
+ local copy
+ if orig_type == 'table' then
+ copy = {}
+ for orig_key, orig_value in next, orig, nil do
+ copy[Utils.copyTable(orig_key)] = Utils.copyTable(orig_value)
+ end
+ setmetatable(copy, Utils.copyTable(getmetatable(orig)))
+ else -- number, string, boolean, etc
+ copy = orig
+ end
+ return copy
+end
+
+function Utils.sortByArtistAndTitle(a, b)
+ if a.artist:lower() < b.artist:lower() then
+ return true
+ elseif a.artist:lower() == b.artist:lower() and a.title:lower() < b.title:lower() then
+ return true
+ else
+ return false
+ end
+end
+
+return Utils
diff --git a/main.lua b/main.lua new file mode 100755 index 0000000..ed38191 --- /dev/null +++ b/main.lua @@ -0,0 +1,36 @@ +Gui = require "Quickie"
+Gamestate = require "hump.gamestate"
+Timer = require "hump.timer"
+Config = require "Config"
+Utils = require "Utils"
+SMFileSchema = require "SMFileSchema"
+Files = require "Files"
+Config = require "Config"
+Game = require "Game"
+Menu = require "Menu"
+
+function love.load()
+ -- preload fonts
+ fonts = {
+ [12] = love.graphics.newFont(12),
+ [20] = love.graphics.newFont(20),
+ }
+ love.graphics.setBackgroundColor(17,17,17)
+ love.graphics.setFont(fonts[20])
+
+ -- group defaults
+ Gui.group.default.size[1] = 150
+ Gui.group.default.size[2] = 25
+ Gui.group.default.spacing = 5
+
+ Gamestate.registerEvents()
+ Gamestate.switch(Menu)
+end
+
+function love.update(dt)
+ Config.width, Config.height = love.window.getDimensions()
+end
+
+function love.draw()
+ Gui.core.draw()
+end
|