function _init() poke(0x5f34, 0x2) --activate inverted shapes room_x = 0 room_y = 0 room_width = 16 room_height = 16 final_room_x = 7 final_room_y = 0 ending = false ending_timer = 0 failed = false spr_open = 2 spr_closed = 4 attention_band = 0 px = 64 py = 64 attention = 0 invert =0x1800 eyes= {} sfx(1,-1) end function _update() -- early-out for ending/failure if ending or failed then ending_timer += 1 if failed and ending_timer > 90 and btnp(5) then _init() end return end update_eyes() if btnp(0) then try_move(-8,0) end if btnp(1) then try_move( 8,0) end if btnp(2) then try_move( 0,-8) end if btnp(3) then try_move( 0, 8) end max_attention = 80 if watched() then attention = min(attention + 1, max_attention) else attention = max(attention - 1, 0) end local new_band = 0 if attention >= 20 and attention < 40 then new_band = 1 elseif attention >= 40 and attention < 60 then new_band = 2 elseif attention >= 60 then new_band = 3 end if new_band != attention_band then attention_band = new_band spawn_eyes_for_band(attention_band) end if attention >= max_attention then if room_x == final_room_x and room_y == final_room_y then start_ending() else start_fail() end end local t = attention / max_attention poke(0x5f40, 32 + t * 16) poke(0x5f42, 2 +t * 4) end function room_sfx() target_vol = 2 target_pitch = 32 shake = 0 --room 0-1 if room_x <= 1 then target_vol = 1 target_pitch = 28 shake = 0 end --room 2-3 if room_x >= 2 and room_x <= 3 then target_vol = 2 target_pitch = 32 shake = 0 end --room 4-5 if room_x >= 4 and room_x <= 5 then target_vol = 3 target_pitch = 36 shake = attention_band >= 2 and 1 or 0 end -- room 6 if room_x == 6 then target_vol = 1 target_pitch = 24 shake = 0 end -- room 7 if room_x == 7 then target_vol = 0 target_pitch = 20 shake = 0 end -- room 8 if room_x == 8 then target_vol = 6 target_pitch = 60 shake = 2 end poke(0x5f42, target_vol) poke(0x5f40, target_pitch) return shake end function start_ending() ending = true ending_timer = 0 end function start_fail() failed = true ending_timer = 0 end function solid_at(px, py) local tx = flr(px / 8) local ty = flr(py / 8) -- convert to map coordinates local map_x = tx + (room_x * room_width) local map_y = ty + (room_y * room_height) return fget(mget(map_x, map_y), 0) end function spawn_eyes_for_band(band) eyes = {} local count = 0 if band == 1 then count = 2 end if band == 2 then count = 4 end if band == 3 then count = 6 end for i=1, count do add(eyes, { x = rnd(120), y = rnd(120), blink_timer = flr(rnd(60)) + 30, open = true, forced_timer = 0 }) end end function player_on_eye(e) return abs(px - e.x) < 8 and abs(py - e.y) < 8 end function update_eyes() for e in all(eyes) do -- if player is standing on the eye if player_on_eye(e) then e.open = false e.forced_timer = 30 -- stays closed for half a second end -- forced closed state if e.forced_timer > 0 then e.forced_timer -= 1 else -- natural blinking e.blink_timer -= 1 if e.blink_timer <= 0 then e.open = not e.open if e.open then e.blink_timer = flr(rnd(90)) + 60 else e.blink_timer = 5 end end end end end function try_move(dx, dy) local nx = px + dx local ny = py + dy if dx > 0 and (solid_at(nx+7, py) or solid_at(nx+7, py+7)) then return end if dx < 0 and (solid_at(nx, py) or solid_at(nx, py+7)) then return end if dy > 0 and (solid_at(px, ny+7) or solid_at(px+7, ny+7)) then return end if dy < 0 and (solid_at(px, ny) or solid_at(px+7, ny)) then return end px = nx py = ny attention += 1 sfx(0) -- footstep -- check for door after successful move check_door() return true end function watched() local tx = flr(px/8) local ty = flr(py/8) -- convert to map coordinates local map_x = tx + (room_x * room_width) local map_y = ty + (room_y * room_height) --check left for x = map_x-1, room_x * room_width, -1 do local t = mget(x, map_y) if fget(t, 0) then break end -- wall blocks if fget(t, 1) then return true end end -- check right for x = map_x+1, (room_x * room_width) + 15 do local t = mget(x, map_y) if fget(t, 0) then break end if fget(t, 1) then return true end end -- check up for y = map_y-1, room_y * room_height, -1 do local t = mget(map_x, y) if fget(t, 0) then break end if fget(t, 1) then return true end end -- check down for y = map_y+1, (room_y * room_height) + 15 do local t = mget(map_x, y) if fget(t, 0) then break end if fget(t, 1) then return true end end return false end function _draw() cls() local shake = room_sfx() if shake > 0 then camera(rnd(shake*2)-shake, rnd(shake*2)-shake) else camera() end -- draw current room using offsets map(room_x * room_width, room_y * room_height, 0, 0, 16, 16) draw_eyes() local min_vision = 0 local max_vision = 8 local vision = max_vision - flr(attention / 10) vision = max(min_vision, vision) fillp(░) circfill(px,py,vision,invert) fillp(▒) circfill(px,py,vision+10,invert) fillp() circfill(px,py,vision+20,invert) spr(5,px, py) if ending then draw_ending() elseif failed then draw_fail() end end function draw_eyes() for e in all(eyes) do if e.open then spr(spr_open, e.x, e.y) else spr(spr_closed, e.x,e.y) end end end function check_door() local tx = flr(px / 8) local ty = flr(py / 8) local map_x = tx + (room_x * room_width) local map_y = ty + (room_y * room_height) local tile = mget(map_x, map_y) if fget(tile, 2) then go_to_next_room() end end function draw_ending() rectfill(0,0,127,127,0) local t = ending_timer if t > 30 then print("you were never alone",64, 60, 7) end if t > 120 then print("🅾️bversation does not end", 64, 70, 6) end end function draw_fail() rectfill(0,0,127,127,0) local t = ending_timer if t > 30 then print("they found you.",44,60,2) end if t > 90 then print("press ❎ to restart.",34,70,7) end end function go_to_next_room() room_x += 1 px = 16 py = 64 attention = max(0, attention - 10) end