Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 36 additions & 12 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<!-- Importing local CSS file -->
<link href="./style.css" rel="stylesheet">
<!-- Importing local JS file -->
<script src="utils.js" defer></script>
<script src="config.js" defer></script>
<script src="main.js" defer></script>
</head>
Expand All @@ -25,20 +26,43 @@ <h1>ChatVenture</h1>
<p>Hello PLAYER! Welcome to the text adventure game where the story is made up by GPT :)</p>
</header>

<div class="loading hidden">
<img src="./images/loader.gif" alt="loading icon">
</div>
<main class="container">
<div class="loading hidden">
<img src="./images/loader.gif" alt="loading icon">
</div>

<div class="error hidden">
<strong>Sorry, something went wrong...</strong>
<div class="error-messages"></div>
</div>
<div class="error hidden">
<strong>Sorry, something went wrong...</strong>
<div class="error-messages"></div>
</div>

<div class="genres">
<button class="genre" data-genre="horror">👻</button>
<button class="genre" data-genre="spy film">🕵🏻‍</button>
<button class="genre" data-genre="marvel superheros">🦸🏻</button>
</div>
<div class="stage-container"></div>

<div class="genres">
<button class="genre" data-genre="horror">👻</button>
<button class="genre" data-genre="spy film">🕵🏻‍</button>
<button class="genre" data-genre="marvel superheros">🦸🏻</button>
</div>
</main>


<template id="stage-template">
<div class="stage-set">
<div class="stage-image">
<!-- <img src="https://picsum.photos/600" alt=""> -->
</div>
<p class="stage-setting">
<!-- Lorem ipsum -->
</p>
</div>
<div class="stage-actions">
<!--
<button>Action 1</button>
<button>Action 2</button>
<button>Action 3</button>
-->
</div>
</template>
</body>

</html>
68 changes: 40 additions & 28 deletions main.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,48 @@
const chatGptMessages = [];
const stageContainer = document.querySelector('.stage-container');

const makeRequest = async (url, data) => {
const response = await fetch(url, {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${_CONFIG_.API_KEY}`,
// Our _CONFIG data is imported in the HTML file using the <script> tag meaning
// it is then accessible via global scope (other JS files, browser console, etc).
},
method: 'POST',
body: JSON.stringify(data)
});
const createSetting = (stage, setting) => {
stage.querySelector('.stage-setting').innerHTML = setting;
stageContainer.append(stage);
}

return response.json();
const createActions = (actions) => {
const actionsHtml = actions.map((action) => `<button>${action}</button>`).join('');
document.querySelector('.stage-actions').innerHTML = actionsHtml;
const buttons = document.querySelectorAll('.stage-actions button');
buttons.forEach((button) => button.addEventListener(
'click',
() => alert(button.innerText)
));
}

const showLoadingAnimation = (isLoading) => {
const loadingScreen = document.querySelector('.loading');
if(isLoading) {
loadingScreen.classList.remove('hidden');
} else {
loadingScreen.classList.add('hidden');
}
const createImage = async (genre, setting) => {
const generatedImage = await makeRequest(
_CONFIG_.API_BASE_URL + '/images/generations',
{
prompt: `This is a story based on ${genre}. ${setting}`,
n: 1,
size: '512x512',
response_format: 'url',
}
);

const image = generatedImage.data[0].url;
document.querySelector('.stage-image').innerHTML = `<img src="${image}" alt="${setting}" >`
}

const showErrorMessage = (isError) => {
const loadingScreen = document.querySelector('.error');
if(isError) {
loadingScreen.classList.remove('hidden');
} else {
loadingScreen.classList.add('hidden');
}
const createStage = async (genre, setting, actions) => {
const stageTemplate = document.querySelector('#stage-template');
const stage = stageTemplate.content.cloneNode(true);

createSetting(stage, setting);
createActions(actions);
await createImage(genre, setting);
}

const startGame = async (genre) => {
showErrorMessage(false);
showGenresButtons(false);

// Message to send to ChatGPT to start the game
chatGptMessages.push({
Expand Down Expand Up @@ -66,8 +74,11 @@ const startGame = async (genre) => {
const message = chatResponseJson.choices[0].message;
const content = JSON.parse(message.content);
const {setting, actions} = content;
console.log('SETTING:', setting);
console.log('ACTIONS:', actions);

// Add the generated message to our message history
chatGptMessages.push(message)

await createStage(genre, setting, actions);

showLoadingAnimation(false);
} catch (error) {
Expand All @@ -80,6 +91,7 @@ const startGame = async (genre) => {
showLoadingAnimation(false);
document.querySelector('.error-messages').innerHTML = errorMessages;
showErrorMessage(true);
showGenresButtons(true);
}
}

Expand Down
36 changes: 36 additions & 0 deletions style.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,42 @@ header {
padding: 32px;
}

.container {
max-width: 720px;
margin: 0 auto;
}

.container > * {
margin-bottom: 32px;
}

.stage-actions {
display: flex;
flex-direction: column;
gap: 8px;
padding: 16px;
}

.stage-actions button {
background-color: transparent;
padding: 16px;
font-family: 'Space Grotesk', sans-serif;
font-size: 20px;
text-align: center;
color: white;
border: 2px solid #a1d2ff;
cursor: pointer;
}

.stage-image {
display: grid;
place-items: center;
}

.stage-image img {
max-width: 100%;
}

.loading {
display: flex;
justify-content: center;
Expand Down
43 changes: 43 additions & 0 deletions utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const makeRequest = async (url, data) => {
const response = await fetch(url, {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${_CONFIG_.API_KEY}`,
// Our _CONFIG data is imported in the HTML file using the <script> tag meaning
// it is then accessible via global scope (other JS files, browser console, etc).
},
method: 'POST',
body: JSON.stringify(data)
});

return response.json();
}

const showLoadingAnimation = (isLoading) => {
const loadingScreen = document.querySelector('.loading');
if(isLoading) {
loadingScreen.classList.remove('hidden');
stageContainer.classList.add('hidden');
} else {
loadingScreen.classList.add('hidden');
stageContainer.classList.remove('hidden');
}
}

const showErrorMessage = (isError) => {
const loadingScreen = document.querySelector('.error');
if(isError) {
loadingScreen.classList.remove('hidden');
} else {
loadingScreen.classList.add('hidden');
}
}

const showGenresButtons = (isVisible) => {
const genres = document.querySelector('.genres');
if(isVisible) {
genres.classList.remove('hidden');
} else {
genres.classList.add('hidden');
}
}