DD@LЕdD  DD@LЕdD @DDDEdD0#3336s3s3s70333360w30s#0w07 P 33<Г<Жs3PP 33<Г<Жs3P 03336s3UP 3#А3<Аc<07U 3#А3<Аc<07UP 3#0330c307dD`D@D``ddDdDdDdD``D`D`DdDDD@fd`FD`D@`DdDs3p303ppss3s3s3s3pp3p3p3s3s3Pp3U5U7P50707s3s3703U0WU07U0W7s3330wsp73p30p3s3P3UusPPw3U53Pu7s3PPPUPSs5w3p73p3s3dDdFDFdeDdDdTdD`F@F`FeDDDdDdTDD@fdedfDDDdDdTs3s737sv3s3scs3p707p7v333s3scs3pw5sPuP7P5u7scs3wS0s0wU`70S7Ssc330wsvsw333s3scP53PuwPe7wU33P07scPP0PP5u5wsvs733scdDedd```DdDdDeDd```ddDDE@ffdFDdEDdDdDs3vssppp3s3s3v3spppss3s3`757PU7Pg5P7s3s37S`7U0W070W7s3360wws73s63s3s3PU56PPuw5w3PUg357s3PP0UUvP0w7Ps73s6s3dDf`fedDdEdDdDfD`feddEdDFPffdFDdD@dEdDs3wpwvs3s6s3s3w3pwvss6s3s3u7P7Pu7PP707UgPs3s37pWU07pW`7Sgs37`wws73s30s6s3P77UvwPPw3573PUgs3PUU0PUWwPPw7s73s3s3dDeDPF@V@F`EdDdDe@P@V@FdEdDDEEf@fF@FEdEdDs3v3`70g07p6s3s3v0`0g07s6s3s3ewPUsUvPPs0usgs3s3w`s0vU0sV0sgSs3366w0w7076s6s3P6ewPu7s6Ugs3PP5P5vP675w757s3dDdDE@`P`dDdDE@PpPs07`3cpfps3s360p`ps3s360`p`07PuU356PuPf07PuU356PePws0W`3UcSpWfps0W`3UcS`Vw`` """              r     7 7 8 8 ; ????????????????????????? ј ј ј ј ј ј ј ш ш ш ш ш ш ш ш44444444444444bш=ооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооаDDD@EDT@DTа@fdfffffdFffdаedfDTDDDDfFDDFаDDDDEDDDEdFаdDdDаdTdFаdDDFаe@Fа@@аPPа@V@а@F@FаdEDVаdDDFаdDDFаfDTFа`@Fаf@Vаe@fаd@аdEDfаdDDFаDFDFаTF@FаFDT@DT@@DD@E@DDT@Td@аPfffdFffdFfffFfffffffFffdFfdfPаdFDDDfFDDfFDDDDDTDDDDDDDDfFfT@аdD@EDDDEDDDDD@DDD@EDDDTD@FаdEDVаdDDFаdDEFаeDDFаdDDа`DVа`dа`dаddаdDDFаDFDFаDDFаF@DDT@DFDDDDDTDTFаPffffFffdFfDdPffDDDEdfDDDdFаdFDDDDDDDfFFfdFDfffffdFfffаdD@DD@EDDDDDdD@d`EDEDTDаdEdEаdDdDаdDDFа`FTFа@F@Fа`F@VаeD@fаDD@аdDDfаdTDFаdDDFаdDDFаELDDDDDDDTDDDTFа@ DEDDDDDDDEdfDDDDDEDdFаPDdfdfffffffdFfffffffаpLD@d`EDEDd`EDTDаPааа`аа "а""а ааааааааааааааааааааааааааааааааааааааааааааааааааооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооряяряяряяяряряяяряяяяряяяяяррряяяяяяряряяяряряяряяяя)-- title: My snake -- author: Gazprom -- desc: My first game at TIC-80 -- site: -- license: MIT License -- version: 0.1 -- script: lua -- saveid: 1 -- Snake head animation HD_ANIM = { idle={ 256, 257, 256, 257, 256, 257, 256, 257, 256, 257, 256, 257, 258, -- Blinks }, dead={259}, dead_turn={260}, poisoned={ 261, 262, 261, 262, 261, 262, 261, 262, 263, -- Blinks }, poisoned_turn={ 264, 265, 264, 265, 264, 265, 264, 265, 266, -- Blinks }, } HD_ANIM_DL = 3 -- Snake body animation BD_ANIM = {{ idle={272,273}, turn={274}, dead={275}, poisoned={275,276}, bitten_left={277}, bitten_right={278}, dead_turn={279}, turn_bitten_left={280}, turn_bitten_top={281}, },{ idle={288,289}, turn={290}, dead={291}, poisoned={291,292}, bitten_left={293}, bitten_right={294}, dead_turn={295}, turn_bitten_left={296}, turn_bitten_top={297}, },{ idle={304,305}, turn={306}, dead={307}, poisoned={307,308}, bitten_left={309}, bitten_right={310}, dead_turn={311}, turn_bitten_left={312}, turn_bitten_top={313}, },{ idle={320,321}, turn={322}, dead={323}, poisoned={323,324}, bitten_left={325}, bitten_right={326}, dead_turn={327}, turn_bitten_left={328}, turn_bitten_top={329}, },{ idle={336,337}, turn={338}, dead={339}, poisoned={339,340}, bitten_left={341}, bitten_right={342}, dead_turn={343}, turn_bitten_left={344}, turn_bitten_top={345}, }} BD_ANIM_DL = .2 -- Snake tail animation TL_ANIM = { idle={352,353}, dead={355}, poisoned={356,357}, bitten_left={358,359}, bitten_right={360,361}, } TL_ANIM_DL = .2 -- Snake data SK = {} SK_ALIVE = true -- Fruit animation FT_ANIM = { idle={368} } FT_ANIM_DL = 1 -- Fruits FT = {} -- Snake movement HAS_MOV = false MOV_VX = 0 MOV_VY = 0 MOV_RT = 0 -- Area measures HT = 14 WD = 29 -- Background BG = {} BG_ANIM = { idle={0} } BG_ANIM_DL = 1 -- Initial position INIT_X = 0 INIT_Y = 0 INIT_VX = 0 INIT_VY = 1 INIT_RT = 90 -- Game variables INIT = false SFX = nil SFX_T = 0 FRS = 0 SCR = 0 -- Misc constants BG_COLOR = 0 FRS_PS = 8 SK_SPD = 8 SCALE = 1 FLIP = 0 function TIC() cls() if not INIT then init() INIT = true end if SK_ALIVE then receiveHeadMovement() if checkNewFrame() then applyBodyMovement() applyHeadMovement() if not checkSnakeDeath() then updateSnake() checkFruitCollected() updateBodySprite() updateTailSprite() end if SFX_T > 0 then SFX_T = SFX_T - 1 end if type(SFX) == "number" then sfx(SFX) SFX = nil end end elseif btnp(4) then reset() end drawList(BG) drawList(FT) drawList(SK) print("Score: " .. SCR, 0, 16*8) if not SK_ALIVE then print( "Press Z to start over...", 10*8, 16*8 ) end end function init() -- Background createBackground() -- Snake head addToSnake( INIT_X, INIT_Y + 16, INIT_VX, INIT_VY, HD_ANIM, HD_ANIM_DL, INIT_RT ) -- Snake body addToSnake( INIT_X, INIT_Y + 8, INIT_VX, INIT_VY, getRandomBody(), BD_ANIM_DL, INIT_RT ) -- Snake tail addToSnake( INIT_X, INIT_Y, INIT_VX, INIT_VY, TL_ANIM, TL_ANIM_DL, INIT_RT ) -- First fruit addRandomFruit() end function checkNewFrame() local t = time() // (1000 / FRS_PS) if FRS + 1 > t then return false end FRS = FRS + 1 return true end function updateSnake() for i, s in ipairs(SK) do updateSnakePart(s) if s.vs == false then s.vs = true return end end end function updateSnakePart(s) if s.vx == -1 then s.x = s.x - SK_SPD elseif s.vx == 1 then s.x = s.x + SK_SPD elseif s.vy == -1 then s.y = s.y - SK_SPD elseif s.vy == 1 then s.y = s.y + SK_SPD end end function checkFruitCollected() local hd = SK[1] local ft = FT[1] if hd.x == ft.x and hd.y == ft.y then local tl = SK[#SK] local bd = SK[#SK-1] addToSnake( tl.x, tl.y, bd.vx, bd.vy, getRandomBody(), BD_ANIM_DL, tl.rt, false ) table.remove(FT, 1) addRandomFruit() SFX = 0 SFX_T = 4 SCR = SCR + 1 end end function drawList(list) for i, obj in ipairs(list) do draw(obj) end end function draw(obj) if obj.vs == false then return end local dl = obj.dl * 100 local anim = obj.anim[obj.st] local t = (time() // 10) % dl local cr = (t // (dl / #anim)) + 1 spr( anim[cr], obj.x, obj.y, BG_COLOR, SCALE, FLIP, obj.rt ) end function createBackground() for i=0, HT, 1 do addToBackground(0, i*8, 0) addToBackground(WD*8, i*8, 90) end for i=0, WD, 1 do addToBackground(i*8, 0, 45) addToBackground(i*8, HT*8, 135) end end function addToBackground(x, y, rt) table.insert(BG, { x=x, y=y, vx=0, vy=0, anim=BG_ANIM, dl=BG_ANIM_DL, st="idle", rt=rt }) end function getRandomBody() local max = #BD_ANIM local idx = math.random(1, max) return BD_ANIM[idx] end function addToSnake( x, y, vx, vy, anim, dl, rt, vs ) local idx = #SK + 1 if vs == nil then vs = true else idx = idx - 1 end table.insert(SK, idx, { x=x, y=y, vx=vx, vy=vy, anim=anim, dl=dl, st="idle", rt=rt, vs=vs, }) end function receiveHeadMovement() local hd = SK[1] if btn(0) and hd.vy < 1 then HAS_MOV = true MOV_VX = 0 MOV_VY = -1 MOV_RT = 0 elseif btn(1) and hd.vy > -1 then HAS_MOV = true MOV_VX = 0 MOV_VY = 1 MOV_RT = 90 elseif btn(2) and hd.vx < 1 then HAS_MOV = true MOV_VX = -1 MOV_VY = 0 MOV_RT = 135 elseif btn(3) and hd.vx > -1then HAS_MOV = true MOV_VX = 1 MOV_VY = 0 MOV_RT = 45 end end function applyHeadMovement() if not HAS_MOV then return end HAS_MOV = false local hd = SK[1] if hd.vx == MOV_VX and hd.vy == MOV_VY then return end hd.vx = MOV_VX hd.vy = MOV_VY hd.rt = MOV_RT if SFX_T == 0 then SFX = 1 end end function applyBodyMovement() local prev_vx = 0 local aux_vx = 0 local prev_vy = 0 local aux_vy = 0 for i, s in ipairs(SK) do aux_vx = s.vx aux_vy = s.vy if i > 1 then s.vx = prev_vx s.vy = prev_vy end prev_vx = aux_vx prev_vy = aux_vy end end function updateTailSprite() local tl = SK[#SK] local bd = SK[#SK - 1] if bd.vy == -1 then tl.rt = 0 elseif bd.vy == 1 then tl.rt = 90 elseif bd.vx == -1 then tl.rt = 135 else tl.rt = 45 end end function updateBodySprite() for i, s in ipairs(SK) do if i > 1 and i < #SK then updateBodyPartSprite( SK[i], SK[i-1] ) end end end function updateBodyPartSprite(cr, pv) if pv.vx == cr.vx or pv.vy == cr.vy then cr.st = "idle" else cr.st = "turn" end if pv.vy == -1 and cr.vy == -1 or pv.vx == 1 and cr.vy == -1 or pv.vy == 1 and cr.vx == -1 then cr.rt = 0 elseif pv.vx == 1 and cr.vx == 1 or pv.vy == 1 and cr.vx == 1 or pv.vx == -1 and cr.vy == -1 then cr.rt = 45 elseif pv.vy == 1 and cr.vy == 1 or pv.vx == -1 and cr.vy == 1 or pv.vy == -1 and cr.vx == 1 then cr.rt = 90 else cr.rt = 135 end end function addRandomFruit() local x = math.random(0, WD) * 8 local y = math.random(0, HT) * 8 if checkSkColision(x, y) then addRandomFruit() return end table.insert(FT, { x=x, y=y, vx=0, vy=0, anim=FT_ANIM, dl=FT_ANIM_DL, st="idle", rt=0 }) end function checkSkColision(x, y) for i, s in ipairs(SK) do if checkSkPrtColision(s, x, y) then return s end end return false end function checkSkPrtColision(s, x, y) return s.x == x and s.y == y end function checkSnakeDeath() local hd = SK[1] if hd.x == 0 and hd.vx == -1 or hd.y == 0 and hd.vy == -1 or hd.x == WD*8 and hd.vx == 1 or hd.y == HT*8 and hd.vy == 1 then applyDeathByBumpSprites() SK_ALIVE = false SFX = 2 return true end local cl = checkSkColision( hd.x + 8 * hd.vx, hd.y + 8 * hd.vy ) if cl == false then return false end applyDeathByBiteSprites(cl) SK_ALIVE = false SFX = 3 return true end function applyDeathByBumpSprites() for i, s in ipairs(SK) do if s.st == "turn" then s.st = "dead_turn" else s.st = "dead" end end applyHeadDeadByBumpSprite() end function applyHeadDeadByBumpSprite() local hd = SK[1] local bd = SK[2] if hd.vx == bd.vx and hd.vy == bd.vy then return end hd.st = "dead_turn" if hd.vx == -1 and bd.vy == -1 or hd.vx == 1 and bd.vy == -1 then hd.rt = 0 elseif hd.vy == 1 and bd.vx == 1 or hd.vy == -1 and bd.vx == 1 then hd.rt = 45 elseif hd.vx == -1 and bd.vy == 1 or hd.vx == 1 and bd.vy == 1 then hd.rt = 90 else hd.rt = 135 end end function applyDeathByBiteSprites(cl) for i, s in ipairs(SK) do if s.st == "turn" then s.st = "dead_turn" else s.st = "poisoned" end end applyHeadBiteDeathSprite() applyBiteSprite(cl) end function applyBiteSprite(cl) local hd = SK[1] if cl.st == "dead_turn" then if cl.vx == 1 and hd.vx == 1 or cl.vy == 1 and hd.vy == 1 then cl.st = "turn_bitten_left" else cl.st = "turn_bitten_top" end return end if cl.vx == -1 and hd.vy == -1 or cl.vx == 1 and hd.vy == 1 or cl.vy == -1 and hd.vx == 1 or cl.vy == 1 and hd.vx == -1 then cl.st = "bitten_left" else cl.st = "bitten_right" end end function applyHeadBiteDeathSprite() local hd = SK[1] local bd = SK[2] if hd.vx == bd.vx and hd.vy == bd.vy then return end hd.st = "poisoned_turn" if hd.vx == -1 and bd.vy == -1 or hd.vx == 1 and bd.vy == -1 then hd.rt = 0 elseif hd.vy == 1 and bd.vx == 1 or hd.vy == -1 and bd.vx == 1 then hd.rt = 45 elseif hd.vx == -1 and bd.vy == 1 or hd.vx == 1 and bd.vy == 1 then hd.rt = 90 else hd.rt = 135 end end