🎮ArcadeLab

Untitled Game

by RapidKoala78
1306 lines21.7 KB
▶ Play
<div id="fnaf4game" class="w-full text-white" style="background:#07070b;border:1px solid #40313d;border-radius:14px;overflow:hidden;font-family:monospace">
<style>
#fnaf4game *{box-sizing:border-box}
#fnaf4game button{
  font-family:inherit;cursor:pointer;color:#eee;background:#211a24;
  border:1px solid #59414e;border-radius:7px;padding:10px 5px;font-size:12px
}
#fnaf4game button:active{transform:scale(.96)}
#fnaf4game button:disabled{opacity:.4;cursor:default}

#fnaf4game .game{
  position:relative;
  height:330px;
  overflow:hidden;
  background:#090910;
  perspective:700px;
}

#fnaf4game .room{
  position:absolute;
  inset:0;
  transition:transform .45s ease;
  background:linear-gradient(#0a0b13,#211b25 70%,#09080d);
}

#fnaf4game .backwall{
  position:absolute;
  left:17%;
  right:17%;
  top:9%;
  bottom:25%;
  background:
    repeating-linear-gradient(
      90deg,
      #15131b 0px,
      #15131b 42px,
      #201b25 44px,
      #0e0d14 48px
    );
  border-bottom:5px solid #39303b;
}

#fnaf4game .floor{
  position:absolute;
  bottom:0;
  left:0;
  width:100%;
  height:28%;
  background:
    repeating-linear-gradient(
      7deg,
      #0d0b11 0px,
      #1b151e 4px,
      #09080d 15px
    );
}

#fnaf4game .doorway{
  position:absolute;
  top:12%;
  width:24%;
  height:70%;
  background:#020205;
  border:6px solid #443440;
  overflow:hidden;
  box-shadow:inset 0 0 30px #000;
}

#fnaf4game .doorway.left{left:0}
#fnaf4game .doorway.right{right:0}

#fnaf4game .door{
  position:absolute;
  inset:0;
  background:
    repeating-linear-gradient(
      90deg,
      #302530 0px,
      #302530 6px,
      #17121b 9px
    );
  transform-origin:left;
  transition:transform .7s cubic-bezier(.2,.8,.2,1);
  z-index:5;
}

#fnaf4game .right .door{
  transform-origin:right;
}

#fnaf4game .door.closed{transform:rotateY(0deg)}
#fnaf4game .left .door.open{transform:rotateY(-87deg)}
#fnaf4game .right .door.open{transform:rotateY(87deg)}

#fnaf4game .monsterAtDoor{
  position:absolute;
  z-index:3;
  bottom:0;
  left:50%;
  transform:translateX(-50%) translateY(30px) scale(.8);
  opacity:0;
  transition:
    opacity .25s,
    transform .5s cubic-bezier(.2,.8,.2,1);
  pointer-events:none;
}

#fnaf4game .monsterAtDoor.visible{
  opacity:1;
  transform:translateX(-50%) translateY(0) scale(1);
}

#fnaf4game .monsterBody{
  width:100px;
  height:155px;
  position:relative;
  filter:drop-shadow(0 0 13px #8d111d);
}

#fnaf4game .head{
  position:absolute;
  top:8px;
  left:12px;
  width:76px;
  height:88px;
  border-radius:48% 48% 38% 38%;
  background:
    radial-gradient(
      ellipse at 50% 20%,
      #51404b 0%,
      #2a202b 45%,
      #08070b 85%
    );
  border:3px solid #59414c;
}

#fnaf4game .ear{
  position:absolute;
  top:-17px;
  width:30px;
  height:43px;
  background:#201820;
  border:3px solid #4b3945;
  clip-path:polygon(50% 0,100% 100%,0 100%);
}

#fnaf4game .ear.left{left:0;transform:rotate(-15deg)}
#fnaf4game .ear.right{right:0;transform:rotate(15deg)}

#fnaf4game .eye{
  position:absolute;
  top:35px;
  width:13px;
  height:9px;
  background:#ff2828;
  border-radius:50%;
  box-shadow:
    0 0 7px 3px #ff1010,
    0 0 17px 7px #750009;
  animation:eyePulse 1.7s infinite;
}

#fnaf4game .eye.left{left:17px}
#fnaf4game .eye.right{right:17px}

@keyframes eyePulse{
  0%,100%{opacity:1}
  48%{opacity:.75}
  52%{opacity:1}
}

#fnaf4game .mouth{
  position:absolute;
  left:18px;
  right:18px;
  bottom:7px;
  height:37px;
  background:#050205;
  border:2px solid #66515b;
  border-radius:35%;
  overflow:hidden;
  animation:jawMove .65s infinite alternate;
}

@keyframes jawMove{
  from{transform:scaleY(.85)}
  to{transform:scaleY(1.08)}
}

#fnaf4game .teeth{
  position:absolute;
  inset:0;
  background:
    linear-gradient(
      to bottom,
      transparent 0 22%,
      #ddd1c7 23% 34%,
      transparent 35% 66%,
      #ddd1c7 67% 79%,
      transparent 80%
    );
}

#fnaf4game .body{
  position:absolute;
  left:20px;
  right:20px;
  bottom:0;
  height:75px;
  background:linear-gradient(#31252f,#08070b);
  clip-path:polygon(20% 0,80% 0,100% 100%,0 100%);
}

#fnaf4game .flashlight{
  position:absolute;
  inset:0;
  z-index:10;
  pointer-events:none;
  opacity:0;
  background:
    radial-gradient(
      ellipse at center,
      rgba(255,244,200,.75) 0%,
      rgba(255,240,190,.22) 25%,
      transparent 57%
    );
  transition:opacity .18s;
}

#fnaf4game .flashlight.on{opacity:1}

#fnaf4game .scratches{
  position:absolute;
  z-index:8;
  width:130px;
  height:150px;
  opacity:0;
  pointer-events:none;
  transition:opacity .2s;
}

#fnaf4game .scratches.show{
  opacity:1;
  animation:scratchShake .12s 3;
}

#fnaf4game .scratches.left{
  left:4%;
  top:28%;
}

#fnaf4game .scratches.right{
  right:4%;
  top:28%;
}

#fnaf4game .scratch{
  position:absolute;
  width:5px;
  height:105px;
  background:#6e414a;
  box-shadow:0 0 5px #39151c;
  transform:rotate(15deg);
}

#fnaf4game .scratch:nth-child(1){left:15px}
#fnaf4game .scratch:nth-child(2){left:42px;height:125px;transform:rotate(7deg)}
#fnaf4game .scratch:nth-child(3){left:70px;height:95px;transform:rotate(20deg)}
#fnaf4game .scratch:nth-child(4){left:97px;height:115px;transform:rotate(4deg)}

@keyframes scratchShake{
  0%,100%{transform:translateX(0)}
  50%{transform:translateX(5px)}
}

#fnaf4game .cameraShake{
  animation:cameraShake .07s linear 6;
}

@keyframes cameraShake{
  0%,100%{transform:translate(0)}
  25%{transform:translate(-5px,2px)}
  75%{transform:translate(5px,-2px)}
}

#fnaf4game .tag{
  position:absolute;
  z-index:12;
  top:8px;
  left:9px;
  font-size:11px;
  color:#ddd;
  text-shadow:0 2px 5px #000;
}

#fnaf4game .overlay{
  position:absolute;
  inset:0;
  z-index:30;
  background:#040408ed;
  display:flex;
  justify-content:center;
  align-items:center;
  text-align:center;
  padding:20px;
}

#fnaf4game .hidden{display:none!important}

#fnaf4game .bar{
  height:5px;
  background:#30232c;
  border-radius:5px;
  overflow:hidden;
}

#fnaf4game .fill{
  width:0;
  height:100%;
  background:#c52e42;
  transition:width .25s;
}

#fnaf4game .controls{
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:7px;
}

#fnaf4game .controls button{
  min-height:53px;
}

#fnaf4game .small{
  font-size:11px;
  color:#b8aab8;
}

@media(max-width:420px){
  #fnaf4game .game{height:275px}
  #fnaf4game .controls button{
    font-size:10px;
    padding:8px 2px;
  }
}
</style>

<div class="p-3 sm:p-4">

<div class="flex justify-between items-center mb-3">
  <div>
    <div class="small" style="letter-spacing:2px;color:#f05264">NACHT 04</div>
    <div class="font-black text-lg">NIGHTMARE</div>
  </div>

  <div class="text-right">
    <div id="f-clock" class="text-2xl font-black">12 AM</div>
    <div class="small">OVERLEEF TOT 6 AM</div>
  </div>
</div>

<div class="bar mb-3">
  <div id="f-progress" class="fill"></div>
</div>

<div class="game" id="f-game">

  <div class="room">

    <div class="backwall"></div>
    <div class="floor"></div>

    <!-- LINKER DEUR -->
    <div class="doorway left">

      <div class="monsterAtDoor" id="f-monster-left">
        <div class="monsterBody">
          <div class="head">
            <div class="ear left"></div>
            <div class="ear right"></div>
            <div class="eye left"></div>
            <div class="eye right"></div>
            <div class="mouth">
              <div class="teeth"></div>
            </div>
          </div>
          <div class="body"></div>
        </div>
      </div>

      <div class="door open" id="f-door-left"></div>

    </div>

    <!-- RECHTER DEUR -->
    <div class="doorway right">

      <div class="monsterAtDoor" id="f-monster-right">
        <div class="monsterBody">
          <div class="head">
            <div class="ear left"></div>
            <div class="ear right"></div>
            <div class="eye left"></div>
            <div class="eye right"></div>
            <div class="mouth">
              <div class="teeth"></div>
            </div>
          </div>
          <div class="body"></div>
        </div>
      </div>

      <div class="door open" id="f-door-right"></div>

    </div>

  </div>

  <!-- KRASSEN -->
  <div class="scratches left" id="f-scratch-left">
    <div class="scratch"></div>
    <div class="scratch"></div>
    <div class="scratch"></div>
    <div class="scratch"></div>
  </div>

  <div class="scratches right" id="f-scratch-right">
    <div class="scratch"></div>
    <div class="scratch"></div>
    <div class="scratch"></div>
    <div class="scratch"></div>
  </div>

  <div class="flashlight" id="f-flash"></div>

  <div class="tag" id="f-tag">
    SLAAPKAMER • VOORUIT KIJKEN
  </div>

  <div class="overlay" id="f-overlay">
    <div>
      <div style="font-size:50px">🌑</div>

      <h2 class="text-2xl font-black mb-3">
        DE NACHT BEGINT
      </h2>

      <p class="text-sm leading-6 mb-5">
        De deuren staan open.<br>
        Als je een monster ziet: <b>DOE DE DEUR DICHT.</b><br>
        Zie je krassen? Controleer die kant.
      </p>

      <button
        id="f-start"
        style="background:#7d2435;padding:12px 25px;font-weight:bold"
      >
        START NACHT
      </button>
    </div>
  </div>

</div>

<div class="flex justify-between my-3 small">
  <span>GEVAAR</span>
  <span id="f-dangerText">RUSTIG</span>
</div>

<div class="bar">
  <div id="f-danger" class="fill"></div>
</div>

<div
  id="f-message"
  class="my-3 p-3 rounded-lg text-sm"
  style="background:#141019;border:1px solid #382632;min-height:45px"
>
  Je hoort alleen de klok...
</div>

<div class="controls">

  <button id="f-look-left">
    ◀ KIJK LINKS
  </button>

  <button id="f-look-center">
    ◎ VOORUIT
  </button>

  <button id="f-look-right">
    KIJK RECHTS ▶
  </button>

  <button id="f-flash">
    🔦 SCHIJN
  </button>

  <button id="f-listen">
    👂 LUISTER
  </button>

  <button id="f-door">
    🚪 DEUR
  </button>

  <button id="f-reset">
    ↻ OPNIEUW
  </button>

</div>

<div class="small text-center mt-3">
  Open deur → 🔦 schijnen → monster zien → 🚪 deur dicht
</div>

</div>

<script>
(()=>{
const root=document.getElementById("fnaf4game");

if(root.dataset.started)return;
root.dataset.started="yes";

const $=id=>root.querySelector("#f-"+id);

let running=false;
let seconds=0;
let timer=null;

let currentSide="center";

let monster={
  left:false,
  right:false
};

let danger={
  left:0,
  right:0
};

let scratches={
  left:false,
  right:false
};

let door={
  left:false,
  right:false
};

let reactionWindow={
  left:0,
  right:0
};

function message(text){
  $("message").textContent=text;
}

function update(){

  const progress=Math.min(100,seconds/90*100);

  $("progress").style.width=progress+"%";

  if(seconds<15)
    $("clock").textContent="12 AM";
  else
    $("clock").textContent=
      Math.min(5,Math.floor(seconds/15))+" AM";

  const maxDanger=Math.max(
    danger.left,
    danger.right
  );

  $("danger").style.width=maxDanger+"%";

  if(maxDanger<30){
    $("dangerText").textContent="RUSTIG";
    $("dangerText").style.color="#86efac";
  }
  else if(maxDanger<65){
    $("dangerText").textContent="IETS NADERT";
    $("dangerText").style.color="#fde047";
  }
  else{
    $("dangerText").textContent="GEVAAR!";
    $("dangerText").style.color="#fb7185";
  }

}

function look(side){

  if(!running)return;

  currentSide=side;

  if(side==="left"){

    $("tag").textContent=
      "LINKER DEUR • KIJKEN";

    message(
      monster.left
      ?"De deur staat open... iets staat daar."
      :"Je kijkt naar de donkere linker deur."
    );

  }

  if(side==="right"){

    $("tag").textContent=
      "RECHTER DEUR • KIJKEN";

    message(
      monster.right
      ?"De deur staat open... iets staat daar."
      :"Je kijkt naar de donkere rechter deur."
    );

  }

  if(side==="center"){

    $("tag").textContent=
      "SLAAPKAMER • VOORUIT";

    message(
      "Je kijkt terug naar het midden van de kamer."
    );

  }

}

function flashlight(){

  if(!running)return;

  $("flash").classList.add("on");

  setTimeout(()=>{
    $("flash").classList.remove("on");
  },700);

  if(
    currentSide==="left" &&
    !door.left
  ){

    if(monster.left){

      message(
        "👁️ HIJ STAAT IN DE DEUROPENING!"
      );

      reactionWindow.left=3;

    }
    else{

      message(
        "De linker gang is leeg."
      );

    }

  }

  if(
    currentSide==="right" &&
    !door.right
  ){

    if(monster.right){

      message(
        "👁️ HIJ STAAT IN DE DEUROPENING!"
      );

      reactionWindow.right=3;

    }
    else{

      message(
        "De rechter gang is leeg."
      );

    }

  }

  update();

}

function closeDoor(){

  if(!running)return;

  if(
    currentSide!=="left" &&
    currentSide!=="right"
  ){

    message(
      "Kijk eerst naar een deur."
    );

    return;
  }

  const side=currentSide;

  if(side==="left"){

    door.left=!door.left;

    $("door-left").className=
      "door "+(door.left?"closed":"open");

    if(door.left){

      if(monster.left){

        monster.left=false;
        danger.left=5;
        reactionWindow.left=0;

        $("monster-left")
          .classList.remove("visible");

        message(
          "KRAK! Je hebt de linker deur net op tijd dichtgedaan!"
        );

      }
      else{

        message(
          "De linker deur schuift dicht..."
        );

      }

    }
    else{

      message(
        "Je doet de linker deur weer open."
      );

    }

  }

  if(side==="right"){

    door.right=!door.right;

    $("door-right").className=
      "door "+(door.right?"closed":"open");

    if(door.right){

      if(monster.right){

        monster.right=false;
        danger.right=5;
        reactionWindow.right=0;

        $("monster-right")
          .classList.remove("visible");

        message(
          "KRAK! Je hebt de rechter deur net op tijd dichtgedaan!"
        );

      }
      else{

        message(
          "De rechter deur schuift dicht..."
        );

      }

    }
    else{

      message(
        "Je doet de rechter deur weer open."
      );

    }

  }

  update();

}

function createScratch(side){

  scratches[side]=true;

  const element=
    side==="left"
    ?$("scratch-left")
    :$("scratch-right");

  element.classList.add("show");

  message(
    side==="left"
    ?"KRASSSS... Er verschijnen krassen links!"
    :"KRASSSS... Er verschijnen krassen rechts!"
  );

  setTimeout(()=>{

    element.classList.remove("show");

  },3500);

}

function spawnMonster(side){

  if(door[side])return;

  monster[side]=true;

  const monsterElement=
    side==="left"
    ?$("monster-left")
    :$("monster-right");

  monsterElement.classList.add("visible");

  danger[side]=95;

  reactionWindow[side]=5;

  message(
    side==="left"
    ?"KRAAK... IETS KOMT IN DE LINKER DEUR TE STAAN!"
    :"KRAAK... IETS KOMT IN DE RECHTER DEUR TE STAAN!"
  );

  update();

}

function removeMonster(side){

  monster[side]=false;

  const monsterElement=
    side==="left"
    ?$("monster-left")
    :$("monster-right");

  monsterElement.classList.remove("visible");

  danger[side]=10;
  reactionWindow[side]=0;

}

function lose(){

  running=false;

  clearInterval(timer);

  $("game").classList.add("cameraShake");

  message(
    "Het monster kwam binnen..."
  );

  setTimeout(()=>{

    $("overlay").classList.remove("hidden");

    $("overlay").innerHTML=`
      <div>
        <div style="font-size:65px">☠️</div>

        <h2
          class="text-3xl font-black my-3"
          style="color:#ff4058"
        >
          TE LAAT
        </h2>

        <p class="text-sm mb-5">
          Je had de deur moeten sluiten.
        </p>

        <button
          id="f-again"
          style="background:#7d2435;padding:12px 25px;font-weight:bold"
        >
          OPNIEUW
        </button>
      </div>
    `;

    $("again").onclick=start;

  },600);

}

function win(){

  running=false;

  clearInterval(timer);

  $("overlay").classList.remove("hidden");

  $("overlay").innerHTML=`
    <div>

      <div style="font-size:55px">🌅</div>

      <h2
        class="text-3xl font-black my-3"
        style="color:#86efac"
      >
        6:00 AM
      </h2>

      <p class="text-sm mb-5">
        Je hebt de nacht overleefd.
      </p>

      <button
        id="f-again"
        style="background:#31583d;padding:12px 25px"
      >
        OPNIEUW
      </button>

    </div>
  `;

  $("again").onclick=start;

}

function start(){

  clearInterval(timer);

  running=true;
  seconds=0;

  currentSide="center";

  monster={
    left:false,
    right:false
  };

  danger={
    left:0,
    right:0
  };

  scratches={
    left:false,
    right:false
  };

  door={
    left:false,
    right:false
  };

  reactionWindow={
    left:0,
    right:0
  };

  $("overlay").classList.add("hidden");

  $("door-left").className="door open";
  $("door-right").className="door open";

  $("monster-left")
    .classList.remove("visible");

  $("monster-right")
    .classList.remove("visible");

  $("scratch-left")
    .classList.remove("show");

  $("scratch-right")
    .classList.remove("show");

  message(
    "De deuren staan open. Luister goed..."
  );

  update();

  timer=setInterval(()=>{

    if(!running)return;

    seconds++;

    /*
      MONSTERS NADEREN
    */

    if(!door.left)
      danger.left=
        Math.min(
          100,
          danger.left+
          Math.random()*5
        );

    if(!door.right)
      danger.right=
        Math.min(
          100,
          danger.right+
          Math.random()*5
        );

    /*
      KRASSEN OP DE MUUR
    */

    if(
      Math.random()<0.09 &&
      !monster.left
    ){

      createScratch("left");

    }

    if(
      Math.random()<0.09 &&
      !monster.right
    ){

      createScratch("right");

    }

    /*
      ALS DE KRASSEN VERSCHIJNEN,
      KAN HET MONSTER DAARNA KOMEN.
    */

    if(
      scratches.left &&
      !monster.left &&
      Math.random()<0.12
    ){

      spawnMonster("left");

    }

    if(
      scratches.right &&
      !monster.right &&
      Math.random()<0.12
    ){

      spawnMonster("right");

    }

    /*
      NORMAAL SPAWNEN
    */

    if(
      !monster.left &&
      !door.left &&
      danger.left>70 &&
      Math.random()<0.09
    ){

      spawnMonster("left");

    }

    if(
      !monster.right &&
      !door.right &&
      danger.right>70 &&
      Math.random()<0.09
    ){

      spawnMonster("right");

    }

    /*
      REACTIETIJD
    */

    if(monster.left){

      reactionWindow.left--;

      if(
        reactionWindow.left<=0 &&
        !door.left
      ){

        lose();
        return;

      }

    }

    if(monster.right){

      reactionWindow.right--;

      if(
        reactionWindow.right<=0 &&
        !door.right
      ){

        lose();
        return;

      }

    }

    /*
      DEUR HOUDT MONSTER WEG
    */

    if(
      monster.left &&
      door.left
    ){

      removeMonster("left");

    }

    if(
      monster.right &&
      door.right
    ){

      removeMonster("right");

    }

    /*
      OM DE 10 SEC EEN GELUID
    */

    if(seconds%10===0){

      const sounds=[
        "Je hoort een zware voetstap...",
        "Kras... kras... ergens in de muur.",
        "Er klinkt een ademhaling.",
        "De vloer kraakt naast je.",
        "Je hoort iets tegen een deur tikken."
      ];

      message(
        sounds[
          Math.floor(
            Math.random()*sounds.length
          )
        ]
      );

    }

    /*
      90 SECONDEN = 6 AM
    */

    if(seconds>=90){

      win();
      return;

    }

    update();

  },1000);

}

$("start").onclick=start;

$("look-left").onclick=()=>{
  look("left");
};

$("look-right").onclick=()=>{
  look("right");
};

$("look-center").onclick=()=>{
  look("center");
};

$("flash").onclick=flashlight;

$("door").onclick=closeDoor;

$("listen").onclick=()=>{

  if(!running)return;

  if(currentSide==="left"){

    if(monster.left){

      message(
        "👂 Je hoort zware ademhaling vlak voor je!"
      );

    }
    else if(danger.left>45){

      message(
        "👂 Voetstappen komen dichterbij..."
      );

    }
    else{

      message(
        "👂 De linker gang is stil."
      );

    }

  }

  else if(currentSide==="right"){

    if(monster.right){

      message(
        "👂 Je hoort zware ademhaling vlak voor je!"
      );

    }
    else if(danger.right>45){

      message(
        "👂 Voetstappen komen dichterbij..."
      );

    }
    else{

      message(
        "👂 De rechter gang is stil."
      );

    }

  }

  else{

    message(
      "👂 Je hoort de klok en iets dat over de muur krast..."
    );

  }

};

$("reset").onclick=start;

})();
</script>
</div>

Game Source: Untitled Game

Creator: RapidKoala78

Libraries: none

Complexity: complex (1306 lines, 21.7 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: untitled-game-rapidkoala78" to link back to the original. Then publish at arcadelab.ai/publish.