local gc=love.graphics local gc_push,gc_pop=gc.push,gc.pop local gc_translate,gc_scale,gc_rotate,gc_applyTransform=gc.translate,gc.scale,gc.rotate,gc.applyTransform local gc_setColor,gc_setLineWidth=gc.setColor,gc.setLineWidth local gc_draw,gc_line=gc.draw,gc.line local gc_rectangle,gc_circle=gc.rectangle,gc.circle local gc_print,gc_printf=gc.print,gc.printf local ms,kb,tc=love.mouse,love.keyboard,love.touch local mt=love.math local max,min=math.max,math.min local int,abs=math.floor,math.abs local setFont=FONT.set local mapCam={ sel=false,--Selected mode ID xOy=mt.newTransform(0,0,0,1),--Transformation for map display keyCtrl=false,--If controlling with key --For auto zooming when enter/leave scene zoomMethod=false, zoomK=false, } local visibleModes local touchDist local scene={} function scene.sceneInit(org) BG.set() mapCam.zoomK=org=='main'and 5 or 1 visibleModes={}--1=unlocked, 2=locked but visible for name,M in next,MODES do if RANKS[name]and M.x then visibleModes[name]=1 if M.unlock then for i=1,#M.unlock do visibleModes[M.unlock[i]]=visibleModes[M.unlock[i]]or 2 end end end end end local function _getK() return abs(mapCam.xOy:transformPoint(1,0)-mapCam.xOy:transformPoint(0,0)) end local function _getPos() return mapCam.xOy:inverseTransformPoint(0,0) end local function _onModeRaw(x,y) for name,M in next,MODES do if visibleModes[name]and M.x then local s=M.size if M.shape==1 then if x>M.x-s and xM.y-s and y1300 and dx<0 or x<-1500 and dx>0 then dx=0 end if y>420 and dy<0 or y<-1900 and dy>0 then dy=0 end mapCam.xOy:translate(dx/k,dy/k) end function scene.wheelMoved(_,dy) mapCam.keyCtrl=false local k=_getK() k=min(max(k+dy*.1,.3),1.6)/k mapCam.xOy:scale(k) local x,y=_getPos() mapCam.xOy:translate(x*(1-k),y*(1-k)) end function scene.mouseMove(_,_,dx,dy) if ms.isDown(1)then _moveMap(dx,dy) end mapCam.keyCtrl=false end function scene.mouseClick(x,y) local _=mapCam.sel if not _ or x<920 then x,y=x-640,y-360 x,y=mapCam.xOy:inverseTransformPoint(x,y) local SEL=_onModeRaw(x,y) if _~=SEL then if SEL then mapCam.moving=true _=MODES[SEL] mapCam.sel=SEL SFX.play('click') else mapCam.sel=false end elseif _ then scene.keyDown("return") end end mapCam.keyCtrl=false end function scene.touchDown() touchDist=false end function scene.touchMove(x,y,dx,dy) local L=tc.getTouches() if not L[2]then _moveMap(dx,dy) elseif not L[3]then x,y=SCR.xOy:inverseTransformPoint(tc.getPosition(L[1])) dx,dy=SCR.xOy:inverseTransformPoint(tc.getPosition(L[2]))--Not delta!!! local d=(x-dx)^2+(y-dy)^2 if d>100 then d=d^.5 if touchDist then scene.wheelMoved(nil,(d-touchDist)*.02) end touchDist=d end end mapCam.keyCtrl=false end function scene.touchClick(x,y) scene.mouseClick(x,y) end function scene.keyDown(key,isRep) if isRep then return end if key=="return"then if mapCam.sel then if visibleModes[mapCam.sel]==2 then MES.new('info',text.unlockHint) else mapCam.keyCtrl=false loadGame(mapCam.sel) end end elseif key=="f1"then SCN.go('mod') elseif key=="escape"then if mapCam.sel then mapCam.sel=false else SCN.back() end end end function scene.update() local dx,dy=0,0 local F if not SCN.swapping then if kb.isDown("up", "w")then dy=dy+10 F=true end if kb.isDown("down","s")then dy=dy-10 F=true end if kb.isDown("left","a")then dx=dx+10 F=true end if kb.isDown("right","d")then dx=dx-10 F=true end local js1=Z.js[1] if js1 then local dir=js1:getAxis(1) if dir~="c"then if dir=="u"or dir=="ul"or dir=="ur"then dy=dy+10 F=true end if dir=="d"or dir=="dl"or dir=="dl"then dy=dy-10 F=true end if dir=="l"or dir=="ul"or dir=="dl"then dx=dx+10 F=true end if dir=="r"or dir=="ur"or dir=="dr"then dx=dx-10 F=true end end end end if F then mapCam.keyCtrl=true if kb.isDown("lctrl","rctrl","lalt","ralt")then scene.wheelMoved(nil,(dy-dx)*.026) else _moveMap(dx,dy) local x,y=_getPos() local SEL=_onModeRaw(x,y) if SEL and mapCam.sel~=SEL then mapCam.sel=SEL SFX.play('click') end end end local _=SCN.stat.tar mapCam.zoomMethod=_=="game"and 1 or _=="mode"and 2 if mapCam.zoomMethod==1 then _=mapCam.zoomK if _<.8 then _=_*1.05 end if _<1.1 then _=_*1.05 end mapCam.zoomK=_*1.05 elseif mapCam.zoomMethod==2 then mapCam.zoomK=mapCam.zoomK^.9 end end --noRank/B/A/S/U/X local baseRankColor={ [0]={0,0,0,.3}, {.2,.4,.6,.3}, {.6,.85,.65,.3}, {.85,.8,.3,.3}, {.85,.5,.4,.3}, {.85,.3,.8,.3}, } local function _drawModeShape(M,S,drawType) if M.shape==1 then--Rectangle gc_rectangle(drawType,M.x-S,M.y-S,2*S,2*S) elseif M.shape==2 then--Diamond gc_circle(drawType,M.x,M.y,S+12,4) elseif M.shape==3 then--Octagon gc_circle(drawType,M.x,M.y,S+6,8) end end function scene.draw() local _ gc_push('transform') gc_translate(640,360) gc_rotate((mapCam.zoomK^.6-1)) gc_scale(mapCam.zoomK^.7) gc_applyTransform(mapCam.xOy); local R=RANKS local sel=mapCam.sel --Lines connecting modes gc_setLineWidth(8) gc_setColor(1,1,1,.2) for name,M in next,MODES do if R[name]and M.unlock and M.x then for _=1,#M.unlock do local m=MODES[M.unlock[_]] gc_line(M.x,M.y,m.x,m.y) end end end --Modes setFont(80) gc_setLineWidth(4) for name,M in next,MODES do local unlocked=visibleModes[name] if unlocked then local rank=R[name] local S=M.size --Draw shapes on map if unlocked==1 then gc_setColor(baseRankColor[rank]) _drawModeShape(M,S,'fill') end gc_setColor(1,1,sel==name and 0 or 1,unlocked==1 and .8 or .3) _drawModeShape(M,S,'line') --Icon local icon=M.icon if icon then gc_setColor(unlocked==1 and COLOR.lH or COLOR.dH) local length=icon:getWidth()*.5 gc_draw(icon,M.x,M.y,nil,S/length,nil,length,length) end --Rank if unlocked==1 then name=RANK_CHARS[rank] if name then gc_setColor(0,0,0,.8) mStr(name,M.x+M.size*.7,M.y-50-M.size*.7) gc_setColor(RANK_COLORS[rank]) mStr(name,M.x+M.size*.7+4,M.y-50-M.size*.7-4) end end end end gc_pop() --Score board if sel then local M=MODES[sel] gc_setColor(.5,.5,.5,.8) gc_rectangle('fill',920,0,360,720,5)--Info board gc_setColor(COLOR.Z) setFont(40)mStr(text.modes[sel][1],1100,5) setFont(30)mStr(text.modes[sel][2],1100,50) setFont(25)gc_printf(text.modes[sel][3],920,110,360,'center') if M.slowMark then gc_draw(IMG.ctrlSpeedLimit,1230,50,nil,.4) end if M.score then mText(TEXTOBJ.highScore,1100,240) gc_setColor(.3,.3,.3,.7) gc_rectangle('fill',940,290,320,280,5)--Highscore board local L=M.records gc_setColor(1,1,1) if visibleModes[sel]==2 then mText(TEXTOBJ.modeLocked,1100,370) elseif L[1]then for i=1,#L do local t=M.scoreDisp(L[i]) local f=int((30-#t*.5)/5)*5 setFont(f) gc_print(t,955,275+25*i+17-f*.7) _=L[i].date if _ then setFont(10) gc_print(_,1155,285+25*i) end end else mText(TEXTOBJ.noScore,1100,370) end end end if mapCam.keyCtrl then gc_setColor(1,1,1) gc_setLineWidth(4) gc_translate(640,360) gc_line(-20,0,20,0) gc_line(0,-20,0,20) gc_translate(-640,-360) end end scene.widgetList={ WIDGET.newKey{name='mod', x=140,y=655,w=220,h=80,font=35,code=goScene'mod'}, WIDGET.newButton{name='start',x=1040,y=655,w=180,h=80,font=40,code=pressKey"return",hideF=function()return not mapCam.sel end}, WIDGET.newButton{name='back', x=1200,y=655,w=120,h=80,font=60,fText=CHAR.icon.back,code=backScene}, } return scene