0aH 0a0(u(DY y@y@8eP0;*"""""*"@"" @" @*******@***@DJD @D PUPPUPUP DJJVP`UPPP  @***V``P`  "PPP @*"" P``*"PP@" @***@D DJJ  @***  " @*"" `P*"`V`@" VP`V``@***PUVVUUVV@D DJJDJJ DJJ@******  @***""""  "@*"""""" @*"" *"""""*"@"" @" @*******@***@DJD @D PUPPUPUP DJJVP`UPPP  @***V``P`  "PPP @*"" P``*"PP@" @***@D DJJ  @***  " @*"" `P*"`V`@" VP`V``@***PUVVUUVV@D DJJDJJDJJDJJ@***J***$***@***"""""@*"""""""""* @*"" *"""""""""*"`P`P@"""""""""* @" `V``V`@**"""""""""@***VP`V``VP`V``V@"""""""""B @DZUVVUUVVUUVVUUVVUU"""""""""DJJDJJDJJDJJDJJD@*""""""""""@***D***D***D***D***D*""""""""""""""@*"""""""""* @*""J*""J*""J*""J*""J**"""""""""*"*"*"*"*"*@"""""""""" @"J"J"J"J"J@*"""""""""* @***D***D***D***D***D*@""""""""""B @DJDJDJDJDJ$"""""""""*DD DJJDJJDJJDJJDJJD@*"""""""""@N@***D***D***D***D***D*"""""""""""O"""""@*"""""""" @*""J*""J*""J*""J*""J**"""""*"""*NN,*"*"*"*"*"*@""* @NȌ@"J"J"J"J"J@***$******@I̜@***D***D***D***D***D*@DJDJD @N@DJDJDJDJDJPUPPUUPPUPUP@@DPUPPUPUPUUPPUPUPUUPPUPVP`VP`UPPP| VP`UPPPVP`UPPPVP`UPV`V``P`@I{DV``P`V``P`V``PPPPP@PPPPPPPPP`P``L(DP``P``P`PPL)PPPP@ fVf`VUfUe@DVVUUPD$"``UPU@D"B@"BUVP``P`P`P`P`PT@"PB`P`i`V``V``V``V``V`VdBVd`V```VY`VP`V``VP`V``VP`V``VP`V``VP`V``VddV``VP`V``VV^UVVUUVVUUVVUUVVUUVVUUVVUUVVUUVVUUVVUUVVUUVVPUVVUUVVPUVVUUVVJJDJJDJJDJJDJJDJJDJJDJJDJJDJJDJJDJJDJJDJJDJJDJJDJJDJJDJJDJJDJJDJJD"*"*"*"*B***D***D***D***D***D***D***D***D***D***$***@********$****D***@*"*""*""*""*""*""""""""""""""""""""""""*"""$"*"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""* @*""""""""""*"""""""J*"" @*"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""*"""""""""$""""""*"*""""""""""""""""""""""""""""""""""""""""""""""""""""* @""""*""J" @*"**"**"**"**""""""""""""""""""""""""""""""""""""""""""""@******"***$**"***D***@*DJDJDJDJD*""""""""""""""""""""""""""""""""""""""""""B @DJDJDJDJDJD @"""""""""""""""""""""""""""""""""""""""""DJJDJJTUPPUUPPPU@*""""""""""""""""""""""""""""""""""""""""""@******VP`VP`V"""""""""""""""""""""""""""""""""""""""""""""V`V`V@*"""""""""""""""""""""""""""""""""""""""""* @*"""""" PPPPP*"""""""""""""""""""""""""""""""""""""""""*"""""P`P`P@"""""""""""""""""""""""""""""""""""""""""" @"" @*"""""""""""""""""""""""""""""""""""""""""*@*******@""""""""""""""""""""""""""""""""""""""""""B @DJD """""""""""""""""""""""""""""""""""""""""DJJDJJ@*""""""""""""""""""""""""""""""""""""""""""@******"""""""""""""""""""""""""""""""""""""""""""""@*"""""""""""""""""""""""""""""""""""""""""* @*"""""" *"""""""""""""""""""""""""""""""""""""""""P*"""""@"""""""""""""""""""""""""""""""""""""""""" V`@"" @*"""""""""""""""""""""""""""""""""""""""""*V``@*******@""""""""""""""""""""""""""""""""""""""""""BZUVV@DJD """"""""""""""""""""""""""""""""""""""""""DJJ """@*"""""""""""""""""""""""""""""""""""""""""""*** """""""""""""""""""""""""""""""""""""""""""""" """@*"""""""""""""""""""""""""""""""""""""""""""""* """*"""""""""""""""""""""""""""""""""""""""""""""P """``P@"""""""""""""""""""""""""""""""""""""""""""""* V` """``V`@*""""""""""""""""""""""""""""""""""""""""""""""V`` """VP`VP`V``@""""""""""""""""""""""""""""""""""""""""""""""BZUVV """RUVVUUVVUUVV""""""""""""""""""""""""""""""""""""""""""""""DJJ """""""""""""""@*"""""""""""""""""""""""""""""""""""""""""""""""*** """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" """""""""""""""@*"""""""""""""""""""""""""""""""""""""""""""""""""* """""""""""""""f9-- title: Hello World Plaformer WIP -- author: Alexander Makovsky -- desc: learn TIC-80 and Lua --UNFINISHED LIST TODO: --Box Class --Actions --Drop Box/Use Box if usable --JumpOn if jumpAct --Crush Box on Enemy --Box Types: --Redis = 0 HP EatIt(F) --Little Vasa = 1 hp Fragile --Little Box = 1 hp --Box = 2 HP --Vasa = 1 HP --Cloth = 0 HP NoHit WearCloth(num) --Hat = 0 HP NoHit WearHat(num) --Jumper = 0 HP NoHit JumpUp() --Flash = 0 HP NoHit FlashUp() --Fruit = 0 HP EatIt(F) --Cake = 0 HP EatIt(T) (isCreamy) --Bushes - no get, can hide --BlackHoles - no get, can hide --Object Class --Coins --Collision with Hero --Bullets --Danger Objects --Particle Class --Stars --Smoke --Shards --Water Splash --Landshaft --Land tiles --Water +Swim Animation --Swamp Tiles --Dead Tiles --One Side Platform (jump from it) --Cloth --wear cloth to get HP --wear hat to get more HP --wear underwear --2 types of clothing --Enemy Class --cantusia --get n drop --bump with other enemy or box --bump on dangerous objects or tiles --cake on face of enemy --DickMan - mooshrum --ChestMan - turtle --Blob - liqud --Fish - fish --FlyEye - little annoyng fly --Ghost - don't touch it (no attack) --Snake - flower from the tube --Print on Center Function --Level Design? --Decoration Tiles --Waterfall --Castle --Lava --Darkness --Worm --Dick Hills --Interactives? --Spawners --Hero Starter --Effects --Rain --Water Drops --Fog --Bubbles? --FireFlies? --Quake Screen --Sound? --Music? -- GLOBAL VARIABLES --------------------------- T=true F=false rnd=math.random State='init' WX=1920 --Max World X WY=1088 --Max World Y -- Camera Class cam={ x=0,y=0, --Camera Axis fx=0,fy=0, --floor Axis for Drawing sx=0,sy=0, ScX=240,ScY=136 } -- Player Hero Class p={ x=120,y=50, go=0,dir=1,sit=0, sx=0,sy=0,speed=5,go=0, fx=0,fy=0, --Force Speed lastWall=0, -- Collision with Walls climb=0, jumpF=0, -- Jump Force ground=F, -- Grounded oldG=F, -- old Ground landTime=0, -- sit correction state='', getBox=0, jam=F, -- jam strike button wait=0, blink=30, strike=0, --Collider Body body={x=4,y=0,w=12,h=24,sit=1}, -- Set Animations anims={}, anim } -- Math Functions -------------------------- floor=math.floor function Sign(n) return n>0 and 1 or n<0 and -1 or 0 end function Lerp(a,b,t) return (1-t)*a + t*b end function Clamp(n,mn,mx) if n>mx then return mx elseif n0 then an.t=an.t+1 -- timer if an.t>=an.maxT then an.t=0 --reset frame an.cf=an.cf+1 -- new frame if an.cf>=#an.frames then --max frames an.cf=0 -- reset end end end end spr(an.frames[an.cf+1],xx,yy+an.hh,0,1,Clamp(dir,0,1),0,an.xx,an.yy) end -- Box/Vase/Drop Objects Class box={} function BoxNew(nm,spr,x,y,w,h,fr) --Create bx={ name=nm,spr=spr,x=x,y=y,w=w,h=h, body={x=2,y=0,w=w*8-2,h=h*8,sit=0}, sx=0,sy=0, getted=F, broke=fr, HP=1 -- breackable object if more than 0 --fragile=10 breackable on speed=10 } table.insert(box,bx) end function BoxWork() --Update local del=F for i,bx in pairs(box) do del=F if not bx.getted then bx.sy=bx.sy+.1 bx.sx=bx.sx*.98 bx.sy=Clamp(bx.sy,-4,4) local ly=bx.y+bx.sy if Coll(bx.x,ly,bx.body,0) then if bx.broke>1 then del=T end if bx.sy>.1 then bx.sx=bx.sx*.6 end bx.sy=.1 ly=bx.y else bx.y=ly end local lx=bx.x+bx.sx if Coll(lx,ly,bx.body,0) then if bx.broke>1 then del=T end bx.sx=bx.sx*.5 lx=bx.x else bx.x=lx end if not btn(1) then if p.y+242 and not p.ground then if Touch(bx.x,bx.y,bx.body,p.x,p.y,p.body) then p.sy=-7 del=T end end end if bx.y>WY then bx.y=bx.y-WY end if bx.y<0 then bx.y=bx.y+WY end if bx.x>WX then bx.x=bx.x-WX end if bx.x<0 then bx.x=bx.x+WX end end if p.getBox==1 then if Touch(bx.x,bx.y,bx.body,p.x,p.y,p.body) then p.getBox=2 bx.getted=T if bx.broke==1 then bx.broke=2 end -- fragile mode end elseif p.getBox==3 and bx.getted then if p.sit==0 then if btn(0) then bx.sx=0 bx.sy=-3.6 --Drop Up else bx.sx=p.dir*5 bx.sy=-1 end --Drop Speed else if btn(1) then bx.sx=0 bx.sy=3.6 end --Drop Down end p.getBox=0 bx.getted=F end --if bx.getted then -- bx.x=floor(p.x) bx.y=floor(p.y) --end if bx.getted then --bx.x+bx.w*4 local x=p.x+8-(bx.w*4) local y=p.y+12-(bx.h*4) --local y=p.y+p.body.y y=((y+p.body.h)-y)*.5-bx.body.h*.5 --bx.x=p.x+x bx.x=x bx.y=y+p.sit*4 end --Delete if del then table.remove(box, i) end end end function BoxDraw() --Draw local x local y local ok --local count=0 for i,bx in pairs(box) do x=(bx.x-cam.fx)%WX y=(bx.y-cam.fy)%WY ok=T if x<0 then ok=F end if x>cam.ScX then ok=F end if y<0 then ok=F end if y>cam.ScY then ok=F end if ok then --count=count+1 --Draw Box spr(bx.spr,x,y,0,1,0,0,bx.w,bx.h) end end --print(count,100,100) end -- Spawn Class ---------------- spawn={} function SpawnNew(x,y,n) --Create sp={ x=x*8,y=y*8,n=n, body={0,0,8,8,0} } table.insert(spawn,sp) end function SpawnWork() --Update for i,sp in pairs(spawn) do --update --table.remove(spawn, i) end end function SpawnDraw() --Draw local x local y local ok local count=0 for i,sp in pairs(spawn) do x=(sp.x-cam.fx)%WX y=(sp.y-cam.fy)%WY ok=T if x<0 then ok=F end if x>cam.ScX then ok=F end if y<0 then ok=F end if y>cam.ScY then ok=F end if ok then count=count+1 spr(sp.n,x,y,0,1) end end print(count,100,100) end -- START INIT ----------------------------------------- function ReMap() -- check map for create spawners local ok=F for x=0,239 do for y=0,135 do n=mget(x,y) ok=F --Spawners if n==240 then SpawnNew(x,y,129) ok=T end --Boxes (nm,spr,x,y,w,h,fr) if n==130 then BoxNew('box',130,x*8,y*8,1,1,1) ok=T end if n==115 then BoxNew('box2',115,x*8,y*8,2,2,0) ok=T end if n==112 then BoxNew('repa',112,x*8,y*8,2,2,0) ok=T end --Delete Tile from Map if ok then mset(x,y,0) end end end end function init() -- Player Hero Init p.anims={ idle=SetAnim({290},0,8,2,2,F), walk=SetAnim({256,258,260,262},5,8,2,2,F), seat=SetAnim({288,268,304,266,288},7,16,2,1,T), seatJ=SetAnim({268},0,16,2,1,F), jump=SetAnim({264},0,8,2,2,F), fall=SetAnim({258},0,8,2,2,F), hurt=SetAnim({292},0,17,2,2,F), wall=SetAnim({296},0,8,2,2,F), strike=SetAnim({282},0,8,2,2,F), strikeSit=SetAnim({268},0,16,2,1,F) } p.anim=p.anims.idle -- Make Interactives ReMap() end -- COLLISIONS ---------------------------- function Coll(x,y,body,sit) -- collision char vs wall local x1=(x+body.x)//8 local y1=(y+body.y)//8+sit local x2=(x+body.w-1)//8 local y2=(y+body.h-1)//8 local n=0 for r = y1,y2 do for c = x1,x2 do x=c%240 y=r%136 n=mget(x,y) if n>0 and n<64 then return T end end end return F end debug='' function Touch(x,y,body,x2,y2,body2) -- coll. of two bodies x=x+body.x y=y+body.y x2=x2+body2.x y2=y2+body2.y local w=x+body.w local h=y+body.h local w2=x2+body2.w local h2=y2+body2.h if x>w2 or wh2 or h0 then p.climb=p.climb-2 p.sx=0 p.sy=0 --p.sit=1 if Coll(p.x,p.y,p.body,0) then jam=T p.sit=1 end if btn(1) then p.sit=1 end if p.lastWall>0 then ly=p.y-2 else ly=p.y end if Coll(p.x,ly,p.body,2) then ly=p.y else p.y=ly end lx=p.x+p.dir if Coll(lx,ly,p.body,2) then p.lastWall=1 else p.climb=0 p.x=lx end if p.sit==1 then p.anim=p.anims.seatJ --seat else p.anim=p.anims.walk end return end -- Hero Player Control --------------------------- p.sx=p.sx*.93 --Force Control p.fx=p.fx*.96 p.fy=p.fy*.96 --Special Speed Forces p.sy=p.sy+.2 --Gravity Control --Sit/Jammed control if btn(1) then p.sit=1 p.lastWall=0 end if Coll(p.x,p.y,p.body,0) then jam=T p.sit=1 end --Chack Jammed/Sit --Wall Sliding local sldSpd=3 local sld=F if p.sy>0 and p.jumpF<=0 and not p.ground and p.lastWall>0 then sld=T sldSpd=1 end --Strike Control if p.wait<=0 then if p.strike<=0 then if btn(5) then if p.getBox==0 and not p.jam then p.strike=30 end else p.jam=F end else p.strike=p.strike-1 if p.strike==0 then p.wait=10 end end else p.wait=p.wait-1 end --Jump Control if p.landTime>0 then p.landTime=p.landTime-1--After Landing Timer else if sld then if btn(4) and p.lastWall>3 then p.lastWall=0 p.sx = 4 * -p.dir -- wall jump p.jumpF=11 p.sy=-1 -- Jump end else if btn(4) and jam==F then if p.ground then p.jumpF=11 p.sy=-1 end --First Time Jump Correction if p.jumpF>0 then p.sy=p.sy-.35 p.jumpF=p.jumpF-1 end elseif p.ground==F then p.jumpF=0 end --reset JumpF on middleAir end end p.oldG=p.ground -- get Old Ground p.ground=F -- Reset Ground Control p.sy = Clamp(p.sy,-3,sldSpd) ly=p.y+p.sy+p.fy if Coll(p.x,ly,p.body,p.sit) then p.fy=0 if p.sy>0 then -- floor/land Y if p.oldG==F then p.landTime=3 end --After Landing Corr p.sy=.5 p.ground=T else p.sy=p.sy*.25 end -- ceil Y ly=p.y else p.y=ly end if p.sy<0 then p.state='jump' --elseif not p.ground then p.state='fall' end if p.strike<=0 then if btn(2) then p.sx=p.sx-.1 p.dir=-1 p.go=1 end --X Control if btn(3) then p.sx=p.sx+.1 p.dir=1 p.go=1 end end if p.sit==0 then p.sx = Clamp(p.sx,-p.speed,p.speed) --Fast Walk elseif p.ground then p.sx=Clamp(p.sx,-p.speed,p.speed)*.9 end --Slow Crouch lx=p.x+p.sx+p.fx --p.lastWall=0 if Coll(lx,ly,p.body,p.sit) then lx=p.x local high=8 if p.sy>=-.25 and p.go==1 and Sign(p.sx)==p.dir and not Coll(lx+p.dir*4,ly-high,p.body,1) then --climb check --if not p.ground or p.sit==1 then p.climb=high --Auto Climb end p.lastWall=p.lastWall+1 p.sx=0 else p.lastWall=0 p.x=lx end -- Player Animation Control ------------------------ if p.strike>0 then p.state='strike' if p.sit==1 then p.anim=p.anims.strikeSit else p.anim=p.anims.strike end return end if p.sy>0 and p.lastWall>3 and p.sit==0 and p.ground==F then p.state='slide' p.anim=p.anims.wall return end if p.sit==1 or jam==T then if p.ground then p.anim=p.anims.seat --seat else p.anim=p.anims.seatJ end p.sit=1 --correction if not p.ground then p.go=0 end --crouch in air correction else if p.ground then if p.go==1 then p.anim=p.anims.walk --walk else p.anim=p.anims.idle end --idle else if p.sy<0 then p.anim=p.anims.jump --jump else if p.landTime<=0 then p.anim=p.anims.fall -- falling end --else p.anim=p.anims.idle end -- landing correction end end end end function Camera() cam.x=p.x-cam.ScX*.5 cam.y=p.y-cam.ScY*.5 cam.fx=floor(cam.x) cam.fy=floor(cam.y) --cam.x=math.floor(cam.xx) --cam.y=math.floor(cam.yy) --cam.x=Lerp(cam.x,p.x-cam.ScX*.5,.2) --cam.y=Lerp(cam.y,p.y-cam.ScY*.5,.2) --cam.sx=Lerp(cam.sx,p.sx*20,.1) --cam.sy=Lerp(cam.sy,p.sy*10,.1) --cam.x=p.x-cam.ScX*.5+cam.sx --cam.y=p.y-cam.ScY*.5+cam.sy end function World() --if cam.x<0 then cam.x=0 end if p.x<0 then p.x=p.x+WX cam.x=cam.x+WX end if p.x>WX then p.x=p.x-WX cam.x=cam.x-WX end if p.y<0 then p.y=p.y+WY cam.y=cam.y+WY end if p.y>WY then p.y=p.y-WY cam.y=cam.y-WY end end -- DRAWING FUNCTIONS ------------------------------ function DrawLevel() map(cam.x//8,cam.y//8,30,17,-(cam.x%8),-(cam.y%8),0) end function DrawHero() local x=floor(p.x-cam.x) local y=floor(p.y-cam.y) local dir=Clamp(p.dir,0,1) local mov=0 if p.sit==1 then mov=p.dir*5 end --sit control --Hair Back spr(323,x+mov-p.dir*8,y+p.sit*9,0,1,dir,0,2,2) --Tail spr(325,x-p.dir*9-mov*.5,y+13,0,1,dir,0,2,1) --Draw Body DrawAnim(p.anim,p.go,x,y,p.dir) if p.sit==0 then --Draw Tits spr(322,x+4,y+8,0,1,dir,0,1,1) --Tits Cloth spr(338,x+4,y+8,0,1,dir,0,1,1) --Pants spr(354,x+4,y+15,0,1,dir,0,1,1) --Dress spr(368,x,y+7,0,1,dir,0,2,1) spr(384,x,y+15,0,1,dir,0,2,1) else spr(352,x,y+16,0,1,dir,0,2,1) spr(371,x+7-6*dir,y+16,0,1,dir,0,1,1) spr(370,x+7-6*dir,y+16,0,1,dir,0,1,1) end --DrawHead DrawFace(x,y,mov,dir) spr(336,x+mov,y+p.sit*9,0,1,dir,0,2,1)--hair spr(387,x+5-dir*2+mov,y+p.sit*9-5,0,1,dir,0,1,1)--hat --spr(332,x+mov,y+p.sit*9,0,1,dir,0,2,2)--dirt --DrawStrike if p.strike>15 then spr(314,x+7-6*dir+p.dir*4,y+p.sit*9+5,0,1,dir,0,1,1) if not p.jam then spr(329,x+7-6*dir+p.dir,y+p.sit*9+7,0,1,1-dir,0,1,1) end elseif p.strike>0 then spr(315,x+7-6*dir+p.dir*10,y+p.sit*8+6,0,1,dir,0,1,1) if not p.jam then spr(329,x+7-6*dir+p.dir*17,y+p.sit*8+6,0,1,dir,0,1,1) end end end function DrawFace(x,y,mov,dir) local Spr=284 --default if p.state=='' then p.blink=p.blink-1 if p.blink<-10 then p.blink=rnd(60,200) end if p.blink<0 then Spr=302 end --blink else if p.state=='jump' then Spr=270 end --if p.state=='fall' then Spr=334 end if p.state=='strike' then Spr=300 end if p.state=='slide' then Spr=318 end end spr(Spr,x+mov,y+p.sit*9,0,1,dir,0,2,1)--default end function DrawBorder() rect(0,0,cam.ScX,8,0) rect(0,cam.ScY-8,cam.ScX,8,0) rect(0,0,8,cam.ScY,0) rect(cam.ScX-8,0-8,8,cam.ScY,0) end -- Update Core ----------------- function Update() World() Camera() Hero() SpawnWork() BoxWork() end -- Drawing Core ---------------- function Draw() cls(0) -- clear screen SpawnDraw() DrawHero() -- draw hero BoxDraw() DrawLevel() -- draw map DrawBorder() --DrawTest() end function DrawTest() for x=0,15 do for y=0,15 do spr(25,(x+7)*8,(y+1)*8) end end end last='' count=0 -- CORE ------------------------------- function TIC() ------------------------ if p.getBox==1 or p.getBox==3 then p.getBox=0 end if btnp(5) then count=count+1 if p.getBox==0 then p.getBox=1 elseif p.getBox==2 then p.jam=T p.strike=22 p.getBox=3 end end if State=='init' then State='game' init() end Update() Draw() print(count..' '..debug) if btn(4) then last='' end --trace('Hello world!') end