--[[ ______ __ _ /_ __/___ _____ / /_ ____ ___ (_)____ ____ / / / _ \ / ___// __ \ / __ `__ \ / // __ \ / __ \ / / / __// /__ / / / // / / / / // // / / // /_/ / /_/ \___/ \___//_/ /_//_/ /_/ /_//_//_/ /_/ \____/ Techmino is my first "huge project" optimization is welcomed if you also love tetromino stacking game Instructions: 1. I made a framework called Zframework, most code in Zframework are directly relevant to game; 2. "xxx" are texts for reading, 'xxx' are string values in program; 3. Some goto statement are used for better performance. All goto-labes have detailed names so don't afraid; 4. Except "gcinfo" function of lua, other "gc" are short for "graphics"; ]]-- --Var leak check -- setmetatable(_G,{__newindex=function(self,k,v)print('>>'..k)print(debug.traceback():match("\n.-\n\t(.-): "))rawset(self,k,v)end}) --Declaration goto REM love=require"love"::REM::--Just tell IDE to load love-api, no actual usage local fs=love.filesystem TIME=love.timer.getTime YIELD=coroutine.yield SYSTEM=love.system.getOS() MOBILE=SYSTEM=="Android"or SYSTEM=="iOS" SAVEDIR=fs.getSaveDirectory() --Global Vars & Settings DAILYLAUNCH=false --System setting math.randomseed(os.time()*626) love.setDeprecationOutput(false) love.keyboard.setKeyRepeat(true) love.keyboard.setTextInput(false) love.mouse.setVisible(false) --Load modules require"Zframework" SCR.setSize(1280,720)--Initialize Screen size --Delete all naked files (from too old version) FILE.clear("") --Create directories for _,v in next,{"conf","record","replay","cache","lib"}do local info=fs.getInfo(v) if not info then fs.createDirectory(v) elseif info.type~='directory'then fs.remove(v) fs.createDirectory(v) end end --Load shader files from SOURCE ONLY SHADER={} for _,v in next,fs.getDirectoryItems("parts/shaders")do if fs.getRealDirectory("parts/shaders/"..v)~=SAVEDIR then local name=v:sub(1,-6) SHADER[name]=love.graphics.newShader("parts/shaders/"..name..".glsl") end end require"parts.list" require"parts.globalTables" require"parts.gametoolfunc" FREEROW= require"parts.freeRow" DATA= require"parts.data" TEXTURE= require"parts.texture" SKIN= require"parts.skin" USERS= require"parts.users" NET= require"parts.net" VK= require"parts.virtualKey" AIFUNC= require"parts.ai" AIBUILDER= require"parts.AITemplate" PLY= require"parts.player" netPLY= require"parts.netPlayer" MODES= require"parts.modes" --Initialize field[1] FIELD[1]=DATA.newBoard() --First start for phones if not fs.getInfo("conf/settings")and MOBILE then SETTING.VKSwitch=true SETTING.swap=false SETTING.powerInfo=true SETTING.cleanCanvas=true end if SETTING.fullscreen then love.window.setFullscreen(true)end --Initialize image libs IMG.init{ lock="mess/lock.png", dialCircle="mess/dialCircle.png", dialNeedle="mess/dialNeedle.png", lifeIcon="mess/life.png", badgeIcon="mess/badge.png", ctrlSpeedLimit="mess/ctrlSpeedLimit.png", speedLimit="mess/speedLimit.png",--Not used, for future C2-mode pay1="mess/pay1.png", pay2="mess/pay2.png", nakiCH="characters/nakiharu.png", miyaCH="characters/miya.png", miyaF1="characters/miya_f1.png", miyaF2="characters/miya_f2.png", miyaF3="characters/miya_f3.png", miyaF4="characters/miya_f4.png", electric="characters/electric.png", hbm="characters/hbm.png", lanterns={ "lanterns/1.png", "lanterns/2.png", "lanterns/3.png", "lanterns/4.png", "lanterns/5.png", "lanterns/6.png", }, } SKIN.init{ "crystal_scf", "matte_mrz", "contrast_mrz", "polkadots_scf", "toy_scf", "smooth_mrz", "simple_scf", "glass_scf", "penta_scf", "bubble_scf", "minoes_scf", "pure_mrz", "bright_scf", "glow_mrz", "plastic_mrz", "paper_mrz", "yinyang_scf", "cartooncup_earety", "jelly_miya", "brick_notypey", "gem_notypey", "classic", "ball_shaw", "retro_notypey", "textbone_mrz", "coloredbone_mrz", "wtf", } --Initialize sound libs SFX.init((function() local L={} for _,v in next,fs.getDirectoryItems("media/SFX")do if fs.getRealDirectory("media/SFX/"..v)~=SAVEDIR then table.insert(L,v:sub(1,-5)) else LOG.print("Dangerous file : %SAVE%/media/SFX/"..v,'warn') end end return L end)()) BGM.init((function() local L={} for _,v in next,fs.getDirectoryItems("media/BGM")do if fs.getRealDirectory("media/BGM/"..v)~=SAVEDIR then table.insert(L,v:sub(1,-5)) else LOG.print("Dangerous file : %SAVE%/media/BGM/"..v,'warn') end end return L end)()) VOC.init{ "zspin","sspin","lspin","jspin","tspin","ospin","ispin", "single","double","triple","techrash", "mini","b2b","b3b", "perfect_clear","half_clear", "win","lose","bye", "test","happy","doubt","sad","egg", "welcome_voc", } --Initialize language lib LANG.init( { require"parts.language.lang_zh", require"parts.language.lang_zh2", require"parts.language.lang_yygq", require"parts.language.lang_en", require"parts.language.lang_fr", require"parts.language.lang_sp", require"parts.language.lang_pt", require"parts.language.lang_symbol", --1. Add language file to LANG folder; --2. Require it; --3. Add a button in parts/scenes/setting_lang.lua; }, { block={ "Z","S","J","L","T","O","I", "Z5","S5","Q","P","F","E", "T5","U","V","W","X", "J5","L5","R","Y","N","H","I5", "I3","C","I2","O1" }, } ) --Load background files from SOURCE ONLY for _,v in next,fs.getDirectoryItems("parts/backgrounds")do if fs.getRealDirectory("parts/backgrounds/"..v)~=SAVEDIR then if v:sub(-3)=="lua"then local name=v:sub(1,-5) BG.add(name,require("parts.backgrounds."..name)) end end end --Load scene files from SOURCE ONLY for _,v in next,fs.getDirectoryItems("parts/scenes")do if fs.getRealDirectory("parts/scenes/"..v)~=SAVEDIR then local sceneName=v:sub(1,-5) SCN.add(sceneName,require("parts.scenes."..sceneName)) LANG.addScene(sceneName) end end --Update data do local needSave,autoRestart if type(STAT.version)~='number'then STAT.version=0 needSave=true end if STAT.version<1302 then FILE.clear_s("") autoRestart=true end if STAT.version<1405 then fs.remove("conf/user") fs.remove("conf/key") needSave=true autoRestart=true end if STAT.version~=VERSION.code then STAT.version=VERSION.code needSave=true autoRestart=true end if not SETTING.VKSkin then SETTING.VKSkin=1 end if not TABLE.find({8,10,13,17,22,29,37,47,62,80,100},SETTING.frameMul)then SETTING.frameMul=100 end SETTING.appLock=nil for _,v in next,VK_org do v.color=nil end if RANKS.GM then RANKS.GM=0 end if RANKS.infinite then RANKS.infinite=6 end if RANKS.infinite_dig then RANKS.infinite_dig=6 end for k in next,RANKS do if type(k)=='number'then RANKS[k]=nil needSave=true end end local modeTable={attacker_h="attacker_hard",attacker_u="attacker_ultimate",blind_e="blind_easy",blind_h="blind_hard",blind_l="blind_lunatic",blind_n="blind_normal",blind_u="blind_ultimate",c4wtrain_l="c4wtrain_lunatic",c4wtrain_n="c4wtrain_normal",defender_l="defender_lunatic",defender_n="defender_normal",dig_100l="dig_100",dig_10l="dig_10",dig_400l="dig_400",dig_40l="dig_40",dig_h="dig_hard",dig_u="dig_ultimate",drought_l="drought_lunatic",drought_n="drought_normal",marathon_h="marathon_hard",marathon_n="marathon_normal",pc_h="pcchallenge_hard",pc_l="pcchallenge_lunatic",pc_n="pcchallenge_normal",pctrain_l="pctrain_lunatic",pctrain_n="pctrain_normal",round_e="round_1",round_h="round_2",round_l="round_3",round_n="round_4",round_u="round_5",solo_e="solo_1",solo_h="solo_2",solo_l="solo_3",solo_n="solo_4",solo_u="solo_5",sprint_10l="sprint_10",sprint_20l="sprint_20",sprint_40l="sprint_40",sprint_400l="sprint_400",sprint_100l="sprint_100",sprint_1000l="sprint_1000",survivor_e="survivor_easy",survivor_h="survivor_hard",survivor_l="survivor_lunatic",survivor_n="survivor_normal",survivor_u="survivor_ultimate",tech_finesse_f="tech_finesse2",tech_h_plus="tech_hard2",tech_h="tech_hard",tech_l_plus="tech_lunatic2",tech_l="tech_lunatic",tech_n_plus="tech_normal2",tech_n="tech_normal",techmino49_e="techmino49_easy",techmino49_h="techmino49_hard",techmino49_u="techmino49_ultimate",techmino99_e="techmino99_easy",techmino99_h="techmino99_hard",techmino99_u="techmino99_ultimate",tsd_e="tsd_easy",tsd_h="tsd_hard",tsd_u="tsd_ultimate",master_extra="GM"} for k,v in next,modeTable do if RANKS[v]then RANKS[k]=RANKS[v] RANKS[v]=nil end v="record/"..v if fs.getInfo(v..".dat")then fs.write("record/"..k..".rec",fs.read(v..".dat")) fs.remove(v..".dat") end if fs.getInfo(v..".rec")then fs.write("record/"..k..".rec",fs.read(v..".rec")) fs.remove(v..".rec") end end if not RANKS.sprint_10l then RANKS.sprint_10l=0 needSave=true end if needSave then FILE.save(SETTING,'conf/settings','q') FILE.save(RANKS,'conf/unlock','q') FILE.save(STAT,'conf/data','q') end if autoRestart then love.event.quit('restart') end end LANG.set(SETTING.lang) VK.setShape(SETTING.VKSkin)