// Cloned by Fiachra Gill on 16 Feb 2024 from World "Nightmare Simulator" by Michael Regan
// Please leave this clone trail here.
//Michael Regan 22112111
//ca318 Practicle - impressive usecase: Nightmare Simulator
let sprites = []; //storing sprites
let urls = []; //storing image urls
let responces = []; //storing ai generated text responces
// movement booleans
let movingUp = false;
let movingDown = false;
let movingLeft = false;
let movingRight = false;
let apikey = "";
AB.world.newRun = function()
{
AB.runReady = false; //Not running setup() as to take users input
ABWorld.init ( 'white' ); //Backgound colour
AB.headerRHS(); //Moving header the RHS
AB.newSplash(); //Creating HTML
AB.splashHtml ( " <h1> Welcome to Nightmare Simulator (Michael Regan ca318) </h1> " +
" <p>API keys can be sourced form: https://platform.openai.com/api-keys </p> " +
" <div>Enter API Key: <input style='width:25vw;' maxlength='2000' id=apikey NAME=apikey VALUE='' > </div>" +
" <div>Describe yourself:<input style='width:25vw;' maxlength='2000' id=player NAME=player VALUE='' ></div> " +
" <div>Who/What are you most affraid of: <input style='width:25vw;' maxlength='2000' id=enemy NAME=enemy VALUE='' > </div>" +
" <button onclick='intialSetup();' class=ab-normbutton >Start game</button> " +
" <div id=errordiv name=errordiv> </div> " );
};
function intialSetup() {
apikey = jQuery("input#apikey").val();
var player = jQuery("input#player").val();
var enemy = jQuery("input#enemy").val();
AB.removeSplash(); //Removing HTML
console.log(player);
console.log(enemy);
//Asynchronously generatng sprite images and text
getImages(player, () => {
getImages(enemy, () => {
getText(enemy, player);
createSprites(urls);
});
})
AB.runReady = true;
}
//Generate image using DALL-E
const getImages = async (promptValue, callback) => {
const options = {
method: "POST", //Post request
headers: {
"Authorization": `Bearer ${apikey}`, //API key
'Content-Type': "application/json" //Conetent type JSON
},
body: JSON.stringify({ //Turn body into JSON
"prompt" : "pixel art of a personified " + promptValue + "(whole body)", //Modified prompt for pixel art generation
"n": 1, //1 image
"size": "256x256" //Image size 256x256
})
}
try {
const responce = await fetch('https://api.openai.com/v1/images/generations', options) //Asynchronously fetching from OpenAI
const data = await responce.json() //Turning responce into json
console.log(data.data[0].url);
urls.push(data.data[0].url); //Storing url in list
if(callback) callback(); //Asynchronous functionailty
} catch (error){ //Error handling
console.error(error) //Print error
}
}
const getText = async (promptValue1, promptValue2, callback) => {
const options = {
method: "POST", //Post request
headers: {
"Authorization": `Bearer ${apikey}`, //API key
'Content-Type': "application/json" //Conetent type JSON
},
body: JSON.stringify({
"model": "gpt-3.5-turbo", //Model
"messages" : [{role: "user", content: `think of soemthing a ${promptValue1} would say to ${promptValue2} while chasing them (funny)`}], //Prompt
"max_tokens": 100 //max tokens
})
}
try {
const responce = await fetch('https://api.openai.com/v1/chat/completions', options) //Asynchronously fetching to chatgpt
const data = await responce.json()
responces.push(data.choices[0].message.content); //Push message to list
if(callback) callback(); //Asynchronous functionailty
} catch (error){ //Error handling
console.error(error) //Print error
}
}
//create user's sprite
function createCustomSprite(x, y, img) {
return {
x: x,
y: y,
img: img,
speed: 5,
display: function() {
image(this.img, this.x, this.y);
},
//moving up,down,left,right
move: function() {
if (movingUp) {
this.y -= this.speed;
}
if (movingDown) {
this.y += this.speed;
}
if (movingLeft) {
this.x -= this.speed;
}
if (movingRight) {
this.x += this.speed;
}
}
};
}
//creating enemy sprite
function createEnemySprite(x, y, img, sprite) {
return {
x: x,
y: y,
img: img,
speed: 1,
display: function() {
image(this.img, this.x, this.y);
},
move: function() {
// Move horizontally towards player
if (sprite.x > this.x) {
this.x += this.speed;
} else if (sprite.x < this.x) {
this.x -= this.speed;
}
// Move vertically towards player
if (sprite.y > this.y) {
this.y += this.speed;
} else if (sprite.y < this.y) {
this.y -= this.speed;
}
}
};
}
//Create sprites from list of image URLs
function createSprites(imageUrls) {
const proxyUrl = 'https://corsproxy.io/?'; //CORS error handling
proxiedUrl = proxyUrl + encodeURIComponent(imageUrls[0]); //New CORs safe URL
// Load Image into sprite
loadImage(proxiedUrl , img => {
let sprite = createCustomSprite(random(width), random(height), img); //First URL will be the player
sprites.push(sprite); //Push sprite to list
if (imageUrls.length > 1) {
proxiedUrl = proxyUrl + encodeURIComponent(imageUrls[1]); //New CORS safe URL
//load image into sprite
loadImage(proxiedUrl, img => {
let enemySprite = createEnemySprite(random(width), random(height), img, sprites[0]); //Second URL will be enemy
sprites.push(enemySprite); //Push sprite to list
}, err => { //Error handling
console.error(err); //Print error
});
}
}, err => { //Error handling
console.error(err); //Print error
});
}
//Keyboard input for moving player
function keyPressed() {
//Move up
if (key === 'W' || key === 'w') {
movingUp = true;
}
//Move down
if (key === 'S' || key === 's') {
movingDown = true;
}
//Move left
if (key === 'A' || key === 'a') {
movingLeft = true;
}
//Move Right
if (key === 'D' || key === 'd') {
movingRight = true;
}
}
// Stop player moving when key is released
function keyReleased() {
//Stop moving up
if (key === 'W' || key === 'w') {
movingUp = false;
}
//Stop moving down
if (key === 'S' || key === 's') {
movingDown = false;
}
//Stop moving left
if (key === 'A' || key === 'a') {
movingLeft = false;
}
//Stop moving right
if (key === 'D' || key === 'd') {
movingRight = false;
}
}
// Dynamically get text size
function calculateMaxFontSize(textContent, boxWidth, boxHeight) {
let fontSize = 1; //Starting text size
textSize(fontSize);
while (textWidth(textContent) < boxWidth && textAscent() + textDescent() < boxHeight) { //While text widthis less then box with and texthight is less the box heigh
fontSize++; //Increment text size
textSize(fontSize); //Adjust text size
}
return fontSize - 1; //Return -1 because while loop will go one to far
};
//---- draw ---------------------------
function draw() {
background(" white"); //Images need to be removed when they move and replaced at new coordinates
//Text box details
let textBoxX = 10;
let textBoxY = height - 100;
let textBoxWidth = width - 20;
let textBoxHeight = 100;
//Draw TextBox
rect(textBoxX, textBoxY, textBoxWidth, textBoxHeight); //Draw TextBox
let textContent = responces[0]; //Set text box's content to chatGPT's responce
let fontSize = calculateMaxFontSize(textContent, textBoxWidth, textBoxHeight); //Dynamicly fill the box with text
textSize(fontSize); //Set text size
text(textContent, textBoxX + 10, textBoxY + textBoxHeight / 2 + 5); //Show Text
// For the player an enemy
for (let sprite of sprites) {
sprite.move(); //move sprite to new coordinates
sprite.display(); //Display sprite
}
}