Javascript Checkout
My javascript checkout about my click game - dark ahllways
- What is my JS Checkout About?
- Breakdown of this Notebook
- CSS and Styling
- Input/Output and Logic and use of localStorage
- Leaderboard
- Frontend
What is my JS Checkout About?
As a game dev, my JS checkout is a game, which I call dark hallways. After Mr. Mort's statement on slack, I first, as a joke, and then actually thought about the duality of objects, such as hallways. How they can be ween in both an symbol of horror and a symbol of light. I decided to buy into this.
%%html
<!-- escape.scss (menu, leaderboard, etc.) -->
<style>
// This defines a 3x3 grid
$grid-template-columns: repeat(3, 1fr);
$grid-template-rows: repeat(3, 1fr);
.container {
display:grid;
grid-template-rows:auto 1fr auto;
grid-template-columns:100%;
/* fallback height */
min-height:100vh;
/* new small viewport height for modern browsers */
min-height:100svh;
}
.menu{
background-color: white;
text-align: center;
top: 100%;
}
.image {
display: block;
margin-left: auto;
margin-right: auto;
width: 50%;
}
.button{
border-width: 3px;
font-family:'Times New Roman', Times, serif;
width: 100px;
height: 30px;
}
#footer{
text-align: center;
color: purple;
}
// ... define other grid item classes as needed
/* Split the screen in half */
.splitty {
height: 100%;
width: 50%;
position: fixed;
z-index: 1;
top: 0;
overflow-x: hidden;
padding-top: 20px;
}
.left {
left: 0;
background-color: #111;
}
.right {
right: 0;
background-color: red;
}
</style>
%%html
<!-- center.scss (game) -->
<style>
/* Split the screen in half */
.split {
height: 100%;
position: fixed;
z-index: 1;
top: 0;
overflow-x: hidden;
padding-top: 20px;
}
/* Control the left side */
.left {
left: 0;
width: 60%;
background-color: black;
}
/* Control the right side */
.right {
right: 0;
width: 40%;
background-color: rgba(243, 230, 230, 0.176);
}
/* If you want the content centered horizontally and vertically */
.centered {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
}
/* Style the image inside the centered container, if needed */
.centered img {
width: 450px;
height: 550px;
}
.menu {
position: fixed;
bottom: -300px;
right: -280px;
width: 500px;
align-items: center;
}.button {
background-color: rgba(255, 255, 255, 0.441);
width: 100px;
height: 75px;
font-size: large;
font-weight: bold;
font-family: 'Times New Roman', Times, serif;
color: white;
}
.grid-container {
display: grid;
position: fixed;
grid-template-columns: auto auto auto;
background-color: #2195f36a;
padding: 10px;
bottom: 25px;
right: -80px;
}
.grid-item {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(255, 255, 255, 0.8);
padding: 20px;
font-size: 30px;
flex: 25%;
text-align: center;
}
</style>
%%html
<html>
<head>
<title> Dark Hallways </title>
<meta charset="utf-8">
<link rel="stylesheet" href="center.scss">
</script>
</head>
<script>
/*
Player Variables
*/
let armor = 0;
let damage = 0;
var local = "0";
/*
Logic for movement depending on locality (shorthand for where the player is)
*/
var all = {
"0": {
"script": "You approach a dark hallway. <br> There appears to be something on the ground. <br> Pick it up?",
"image": "hallway1.jpeg",
"choices": ["Yes", "No"],
"results" : {"Yes" : addToInv, "No":moveTo, "Yesfunc" : ["pistol", "1"], "Nofunc" : "1"}
},
"1": {
"script": "There appears to be something in the distance. <br> The hallway spans further. <br> Whatever is there appears to be approaching.",
"image": "hallway2.jpeg",
"choices": ["Approach", "Hide"],
"results" : {"Approach" : moveTo, "Hide":moveTo, "Approachfunc" : "3", "Hidefunc" : "2"}
},
"2": {
"script": "You sit behind a couch, waiting for whatever is there to disappear <br> It is possible to sneak <br> Do we sneak or stay?",
"image": "hallway2.jpeg",
"choices": ["Sneak", "Stay"],
"results" : {"Sneak" : moveTo, "Stay":moveTo, "Sneakfunc" : "6", "Stayfunc" : "2"}
},
"3": {
"script": "You approach the thing... <br> And it attacks! <br> Do we fight or run?",
"image": "hallway3.png",
"choices": ["Fight", "Run"],
"results" : {"Fight" : specialMove, "Run":addToInv, "Fightfunc" : [4, 5, 'damage', 0], "Runfunc" : ["Tendril", 1]}
},
"4": {
"script": "You fight furiously... <br> But you are too weak <br> You fall to the maw of the monster",
"image": "hallway3.png",
"choices": ["End", "Game"],
"results" : {"End" : leave, "Game":leave, "Endfunc" : "monster", "Gamefunc" : "monster"}
},
"5": {
"script": "You fight furiously ... <br> and you destroy the monster! <br> You see a door beyond. Will you walk through?",
"image": "hallway3.png",
"choices": ["Go Through", "Stay"],
"results" : {"Go Through" : moveTo, "Stay":moveTo, "Go Throughfunc" : "9", "Stayfunc" : "8"}
},
"6": {
"script": "You sneak by the monster <br> and behind it you see a door. Do we stay or do we go approach the door?",
"image": "hallway3.png",
"choices": ["Go!", "Stay"],
"results" : {"Go!" : moveTo, "Stay":moveTo, "Go!func" : "3", "Stayfunc" : "7"}
},
"7": {
"script": "You stay inside <br> but you are lost within the chaos of the labyrinth <br> You fall in the winding labyrinth",
"image": "hallway4.jpeg",
"choices": ["End", "Game"],
"results" : {"End" : leave, "Game":leave, "Endfunc" : "stay", "Gamefunc" : "stay"}
},
"8": {
"script": "Your raucous fight opens a door in the damp floor <br> unable to keep up your balance, you fall into the ground <br> and fall into the infinite chasm",
"image": "hallway5.jpg",
"choices": ["End", "Game"],
"results" : {"End" : leave, "Game":leave, "Endfunc" : "hole", "Gamefunc" : "hole"}
},
"9": {
"script": "You escape through the door into the light. <br> The air feels good, and the darkness fades <br> You escape!",
"image": "hallway6.jpg",
"choices": ["End", "Game"],
"results" : {"End" : victory, "Game":victory, "Endfunc" : "fighting", "Gamefunc" : "fighting"}
}
};
//TODO: Finish the sneak and the stay/go through (completion page)
// Then finish up backend and leaderboard
// Completed: sneak, ending of staying
var playerStats = {
"armor" : 0,
"damage" : 0,
"health" : 0,
"equipped" : {
"damage": "",
"armor" : ""
}
}
var inventory = {
}
var assets = {
"pistol" : ["damage", 1],
"vest" : ["armor", 2],
"tendril" : ["damage", 2]
}
function formatStuff(location) {
local = location;
console.log("Locality: " + local);
let point = all[location];
document.getElementById("hallwayIMG").src = "images/" + point["image"];
document.getElementById("C1").innerHTML = point["choices"][0];
document.getElementById("C2").innerHTML = point["choices"][1];
document.getElementById("script").innerHTML = point["script"];
}
function equip(item){
inventory[item] = !inventory[item];
if (inventory[item]){
document.getElementById("err").innerHTML = item + " equipped!"
setTimeout(function(){document.getElementById("err").innerHTML = ""},1000);
playerStats[assets[item][0]] += assets[item][1];
playerStats["equipped"][assets[item][0]] = item;
}
else {
document.getElementById("err").innerHTML = item + " unequipped."
setTimeout(function(){document.getElementById("err").innerHTML = ""},1000);
playerStats[assets[item][0]] -= assets[item][1];
}
}
function addToInv(stuff) {
let name = stuff[0];
let location = stuff[1];
let elems = document.getElementsByName("slot");
let ocured = false;
for(let i = 0; i < elems.length; i++){
slot = elems[i];
if(slot.innerHTML === ""){
var b = document.createElement("button");
b.innerHTML = name
b.id = name
b.addEventListener("click", function(event){
equip(name)
})
document.getElementById(slot.id).appendChild(b);
ocured = true;
document.getElementById("err").innerHTML = "You picked up a " + name
setTimeout(function(){document.getElementById("err").innerHTML = ""},1000);
break
}
}
if (!ocured){
document.getElementById("err").innerHTML = "Inventory Full!"
setTimeout(function(){document.getElementById("err").innerHTML = ""},1000);
}
moveTo(location);
}
function moveTo(location){
console.log("Location Passed in " + location)
formatStuff(location);
}
function specialMove(information){//)loc1, loc2, condition, parameter){
console.log(information)
console.log(playerStats[information[2]] > information[3])
if(playerStats[information[2]] > information[3]){
moveTo(information[1])
}
else {
moveTo(information[0])
}
}
function manageFunctions(value){
console.log(local)
console.log("Stuff: " + document.getElementById('C2').innerHTML);
let func = all[local]["results"];
console.log("value: " + value);
console.log(all[local]["results"])
func[value](func[value+"func"]);
}
function leave(cause){
localStorage.setItem("causeOfDeath", cause);
setTimeout(() => {
window.location = 'https://nvarap.github.io/gameover.html'
}, 500);
}
function victory(win){
localStorage.setItem("causeOfVictory", win);
setTimeout(() => {
window.location = 'https://nvarap.github.io/victory.html'
}, 500);
}
window.onload = (event) => {
formatStuff(local);
};
</script>
<body style="position: relative; background-color: black;">
<div class="split left">
<div class="centered">
<img src="images/hallway1.jpeg" alt="Hallway1" id="hallwayIMG">
<div style="color: white;">
<p id="script"> </p>
</div>
</div>
</div>
<div class="split right">
<div class="centered">
<h1 style="position: fixed; bottom: 270px; right: -80px; color: white;"> Inventory </h1>
<div class="grid-container">
<div id="slot1" name="slot" class="grid-item"></div>
<div id="slot2" name="slot" class="grid-item"></div>
<div id="slot3" name="slot" class="grid-item"></div>
<div id="slot4" name="slot" class="grid-item"></div>
<div id="slot5"name="slot" class="grid-item"></div>
<div id="slot6" name="slot" class="grid-item"></div>
<div id="slot7" name="slot" class="grid-item"></div>
<div id="slot8" name="slot" class="grid-item"></div>
<div id="slot9" name="slot" class="grid-item"></div>
<div id="slot10" name="slot" class="grid-item"></div>
<div id="slot11" name="slot" class="grid-item"></div>
<div id="slot12" name="slot" class="grid-item"></div>
<div id="slot13" name="slot" class="grid-item"></div>
<div id="slot14" name="slot" class="grid-item"></div>
<div id="slot15" name="slot" class="grid-item"></div>
</div>
<p id="err" style="position: fixed; top: 10px; right: -35px; color: white;"></p>
<div class="menu">
<button onclick="manageFunctions(document.getElementById('C1').innerHTML)" id="C1" data-inline="true" class="button" style="margin: 0px"> </button>
<button onclick="manageFunctions(document.getElementById('C2').innerHTML)" id="C2" data-inline="true" class="button" style="margin: 50px"> </button>
</div>
</div>
</div>
</div>
</body>
</html>
from flask import Blueprint, request, jsonify # jsonify creates an endpoint response object
from flask_restful import Api, Resource # used for REST API building
app_api = Blueprint('api', __name__,
url_prefix='/api/points')
# API generator https://flask-restful.readthedocs.io/en/latest/api.html#id1
api = Api(app_api)
class UsrAPI:
local_dic = [] # Stores all the users and IDs
def newScore(front, back, diction):
user_id = str(len(diction))
diction.append({'name':front, "points":back})
class _Create(Resource):
def post(self): # simply creates the endpoint, dne otherwise
body = request.get_json()
UsrAPI.newScore(body.get("name"), body.get("score"), UsrAPI.local_dic)
return {"message" : "new person added"}
class _Read(Resource):
def get(self):
return jsonify(sorted(UsrAPI.local_dic,key=lambda x: x["points"], reverse=True))
# init wikipedia by default
# getJoke(id)
# class _ReadWithName(Resource): # read when url have name query satisfied
# def get(self, name):
# return jsonify()# otherwise check with name
# getRandomJoke()
#class _ReadRandom(Resource):
# def get(self):
# return jsonify() # this exists for some reason
# building RESTapi resources/interfaces, these routes are added to Web Server
api.add_resource(_Create, '/create')
api.add_resource(_Read, '/')
%%js
// fetching
fetch('http://127.0.0.1:8086/api/points/')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
let leaderboard = document.getElementById("leaderboard");
// Process the response data
console.log(data);
let i = 1;
data.forEach(element => {
let d = document.createElement("div");
d.style = "color: white; width: 500px";
d.innerHTML = i + ". | " + element["name"] + " | " + element["points"];
leaderboard.appendChild(d);
i ++;
});
})
.catch(error => {
// Handle any errors that occurred during the request
console.error('Error:', error);
});
%%js
// posting
var but = document.getElementById("add");
but.addEventListener("click", () => {
fetch('http://127.0.0.1:8086/api/points/create', {
method: 'POST',
mode: "cors",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ "name" : localStorage.getItem("name"), "score":Math.floor(100-Math.random()*100)})
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
// Process the response data
console.log(data);
localStorage.clear()
setTimeout(() => {
window.location = 'https://nvarap.github.io/index.html'
}, 500);
})
.catch(error => {
// Handle any errors that occurred during the request
console.error('Error:', error);
});
})