0,]']±>Sï}WÿÍu§ðp8·d%qy)6o;]ÉA¦ösï÷ôôô”°ÂVl†3 0 and 1) or (n == 0 and 0) or -1 end function Lerp(a,b,t) return (1-t)*a + t*b end function Collides(b1, b2, dist) return math.abs(b1.x-b2.x)row then mset(col, row, SPR.gndLeft) elseif self.surf[col+1] and self.surf[col+1]>row then mset(col, row, SPR.gndRight) else mset(col, row, SPR.gndTop) end elseif row > self.surf[col] then mset(col, row, SPR.gnd) else mset(col, row, SPR.sky) end end end local row = self.surf[0]-3 for i = 0, 2 do mset(0, row+i, 16*i) mset(self.w-1, row+i, 16*i + 1) end end function Ground:TIC(cam) local leftCol = math.floor(cam.x) // 8 local offX = math.floor(cam.x) % 8 map(leftCol, 0, 31, 8, -offX, self.offY) end function Ground:yAt(x) local col = x // 8 if col < 0 then col = 0 end if col >= self.w then col = self.w-1 end return self.surf[col]*8 + self.offY end -- Anims Anims = {fx={}} function Anims:addBoom(x, y, scale) local boom = {frames=HIT_ANIM, x=x-4*scale, y=y-4*scale, tics=0, fps=15, scale=scale} table.insert(self.fx, boom) sfx(1+scale, 8, 20, 3) end function Anims:TIC(cam) for k,v in pairs(self.fx) do local frame = math.floor(v.tics * v.fps / 60) if frame >= #v.frames then table.remove(self.fx, k) else frame = (frame % #v.frames) + 1 spr(v.frames[frame], v.x-cam.x, v.y, COLOR_KEY, v.scale) end v.tics = v.tics + 1 end end -- Flag Flag = {x=FLAG.startX,y=FLAG.startY,vy=0,flip=0} function Flag:TIC(cam, ground) if self.x < TEAM[0].baseX then TEAM[0].score = TEAM[0].score + 1 music(0, 0, 0, false) self:reset() elseif self.x > TEAM[1].baseX then TEAM[1].score = TEAM[1].score + 1 music(1, 0, 0, false) self:reset() end if self.owner == nil then self.y = self.y + self.vy local gndY = ground:yAt(self.x) if self.y >= gndY then self.y = gndY self.vy = 0 else self.vy = self.vy + 0.1 end else self.x, self.y = self.owner.x, self.owner.y self.vy = self.owner.vy -- apply when dropped self.flip = self.owner.vx > 0 and 0 or 1 end local drawX, drawY = self.x-FLAG.w/2-cam.x, self.y-FLAG.h spr(SPR.flag, drawX, drawY, COLOR_KEY, 1, self.flip, 0, 1, 3) end function Flag:reset() self.x, self.y = FLAG.startX, FLAG.startY self.vy = 0 self.owner = nil end -- Mob Mob = {x=0,y=0,vx=0,vy=0,team=0,hit=false,hitTimer=0} function Mob:TIC(cam, ground, flag) self.y = self.y + self.vy self.x = self.x + self.vx if self.hitTimer == 0 then self.hit = false else self.hitTimer = self.hitTimer - 1 end if not self.hit and flag.owner == nil then if Collides(self, flag, MOB.pickDist) then flag.owner = self end end if self.y >= ground:yAt(self.x) and self.vy > 0 then if self.hit then self.x = math.floor(self.x) self.y = ground:yAt(self.x) self.vx, self.vy = 0, 0 else self.vy = -MOB.baseVy + math.random() local targetX = flag.x if self == flag.owner then targetX = TEAM[self.team].baseX end self.vx = Sgn(targetX-self.x)*(MOB.baseVx + math.random()/2) if self == flag.owner then self.vx = self.vx * MOB.flagSlow end end else self.vy = self.vy + 0.1 end local drawX, drawY = math.floor(self.x-MOB.w/2-cam.x), math.floor(self.y-MOB.h) local flip = self.vx > 0 and 0 or 1 local s = self.vy > 0 and TEAM[self.team].SPR.down or TEAM[self.team].SPR.up if self.hit then s = TEAM[self.team].SPR.hit + (self.hitTimer//10)%2 end spr(s, drawX, drawY, COLOR_KEY, 1, flip) end function Mob:takeHit(vx, vy) self.hit = true self.hitTimer = MOB.hitTics self.vx = vx*2 self.vy = vy end -- Mob Manager MobMan = {mobs={}} function MobMan:TIC(cam, ground, flag, anims) if btnp(0) and TEAM.size < TEAM.maxSize then TEAM.size = TEAM.size + 1 elseif btnp(1) and TEAM.size > TEAM.minSize then TEAM.size = TEAM.size - 1 elseif btnp(4) then flag.owner = nil anims:addBoom(flag.x, flag.y, 2) flag.vy = -MOB.baseVy for i=1,#self.mobs do local mob = self.mobs[i] if Collides(flag, mob, MOB.explDist) then mob:takeHit(Sgn(mob.x-flag.x)*MOB.baseVx, -MOB.baseVy/2) end end -- flag:reset() end if #self.mobs < TEAM.size*2 then local mob0 = New(Mob, {x=TEAM[0].baseX, y=0, team=0}) table.insert(self.mobs, mob0) local mob1 = New(Mob, {x=TEAM[1].baseX, y=0, team=1}) table.insert(self.mobs, mob1) elseif #self.mobs > TEAM.size*2 then if self.mobs[#self.mobs] == flag.owner then flag.owner = nil end table.remove(self.mobs, #self.mobs) if self.mobs[#self.mobs] == flag.owner then flag.owner = nil end table.remove(self.mobs, #self.mobs) end for i=1,#self.mobs do local mob = self.mobs[i] mob:TIC(cam, ground, flag) if not mob.hit and flag.owner and Collides(flag.owner, mob, MOB.hitDist) then if mob.vy>0 and mob.vy>flag.owner.vy and flag.owner.team ~= mob.team then flag.owner:takeHit(mob.vx, mob.vy) anims:addBoom(flag.owner.x, flag.owner.y, 1) flag.owner = nil end end end end -- Camera Camera = {x=120,minX=0,maxX=240} function Camera:TIC(flag) if flag.y > 0 then self.x = Lerp(self.x, flag.x-SCR.WIDTH/2, 0.1) self.x = math.max(math.min(self.x, self.maxX), self.minX) end end -- Create entities local ground = New(Ground, {}) ground:prepare() local camera = New(Camera, {}) local flag = New(Flag, {}) local mobMan = New(MobMan, {}) local anims = New(Anims, {}) -- sky gradient function SCN(line) -- LightBlue 0x3FC0 + A*3 (41A6F6) poke(0x3FDE, math.floor(0x41*line/SCR.HEIGHT)) poke(0x3FDF, math.floor(0xA6*line/SCR.HEIGHT)) poke(0x3FE0, math.floor(0xF6*line/SCR.HEIGHT)) end -- lets play function TIC() cls(10) camera:TIC(flag) ground:TIC(camera) flag:TIC(camera, ground) mobMan:TIC(camera, ground, flag, anims) anims:TIC(camera) print(TEAM[0].score.." : "..TEAM[1].score, 93, 13, 2, true, 2) --shadow print(TEAM[0].score.." : "..TEAM[1].score, 92, 12, 4, true, 2) print("up/down: team size ("..TEAM.size..") z: explode flag", 32, 128, 14, true, 1, true) -- print("up/down: team size ("..TEAM.size..") z: explode flag", 4, 2, 9, true) end