Compare commits

...

13 Commits

Author SHA1 Message Date
Subhodip Ghosh 702e63b91c Merge pull request 'newb' (#28) from newb into master
Reviewed-on: #28
2024-11-21 11:31:40 +00:00
Suvodip e4dc874374 s1 2024-11-21 16:57:31 +05:30
Suvodip 7e44149a4a fix sub learning area key issue (copy) 2024-11-19 12:32:05 +05:30
Suvodip b8444a361a s1 2024-11-08 16:39:40 +05:30
Suvodip d64bc840bc s1 2024-11-08 16:27:37 +05:30
Suvodip 399186819c s1 2024-11-07 19:30:53 +05:30
Suvodip 1bd86ba8cc s1 2024-11-06 19:05:11 +05:30
Suvodip ebd61445de fix color issue over the button 2024-11-05 18:22:34 +05:30
Suvodip eab9dd370f Change All Guided Tracing Desgine 2024-11-05 16:46:43 +05:30
Suvodip 3392dea286 CS 2024-10-30 16:46:38 +05:30
Suvodip 195756b892 CI 2024-10-29 18:45:48 +05:30
Suvodip cd15a8be17 add new desgine from 0 to a 2024-10-28 18:48:04 +05:30
Suvodip 41ae75207b newb 2024-10-26 18:57:45 +05:30
90 changed files with 14126 additions and 9436 deletions

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -0,0 +1,4 @@
<svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12.832" cy="12.6328" r="12" fill="#F7A915"/>
<path d="M12.834 3.76953L12.834 21.9905" stroke="black" stroke-opacity="0.5" stroke-linecap="round" stroke-dasharray="3 3"/>
</svg>

After

Width:  |  Height:  |  Size: 285 B

View File

@ -0,0 +1,6 @@
<svg width="24" height="25" viewBox="0 0 24 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.9375" width="23" height="23" fill="white"/>
<rect x="0.5" y="0.9375" width="23" height="23" stroke="black"/>
<path d="M12.1367 3.52344L12.1367 22.1211" stroke="black" stroke-opacity="0.5" stroke-linecap="round" stroke-dasharray="3 3"/>
<path d="M2.83594 12.8242H21.4336" stroke="black" stroke-opacity="0.5" stroke-linecap="round" stroke-dasharray="3 3"/>
</svg>

After

Width:  |  Height:  |  Size: 477 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 31 KiB

45
public/galleryFunction.js Normal file
View File

@ -0,0 +1,45 @@
const jsonData = [
{
"src": "/assets/back.jpeg",
"title": "Image Title 1",
"description": "Description for image 1 goes here."
},
{
"src": "/assets/background.jpg",
"title": "Image Title 2",
"description": "Description for image 2 goes here."
},
{
"src": "/assets/backgroundImage.png",
"title": "Image Title 3",
"description": "Description for image 3 goes here."
},
{
"src": "/assets/beanieImage.png",
"title": "Image Title 4",
"description": "Description for image 4 goes here."
}
];
let currentSlide = 0;
function updateSlide(){
const slide = jsonData[currentSlide];
document.getElementById('slideImage').src = slide.src;
document.getElementById('imageTitle').textContent = slide.title;
document.getElementById('imageDescription').textContent = slide.description;
}
document.getElementById('nextButton').addEventListener('click', () => {
currentSlide = (currentSlide + 1) % jsonData.length;
console.log(currentSlide)
updateSlide();
})
document.getElementById('prevButton').addEventListener('click', () => {
currentSlide = (currentSlide - 1 + jsonData.length) % jsonData.length;
updateSlide();
})
updateSlide();
let parentMainContainer = document.getElementById('parentMainContainer');
let gallerySliderId = document.getElementById('gallerySliderId');
function closeGallery(){
gallerySliderId.classList.add('hidden');
}

View File

@ -1,7 +1,6 @@
function retryGame(){ function retryGame(){
window.location.reload(); window.location.reload();
} }
const queryString = window.location.search; const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString); const urlParams = new URLSearchParams(queryString);
const userId = urlParams.get('userId'); const userId = urlParams.get('userId');
@ -50,11 +49,14 @@
function submitUserData(drawingZone) { function submitUserData(drawingZone) {
submitButton.setVisible(false); submitButton.setVisible(false);
if(!gameType[0] === 'guided-tracing'){
snapshotButton.setVisible(false); snapshotButton.setVisible(false);
customCursor.setVisible(false); customCursor.setVisible(false);
galleryButton.setVisible(false);
}
muteIcon.setVisible(false); muteIcon.setVisible(false);
retryButton.setVisible(false); retryButton.setVisible(false);
galleryButton.setVisible(false);
const endTime = Date.now(); const endTime = Date.now();
const timeDifference = endTime - startTime; const timeDifference = endTime - startTime;
const timeDifferenceInSeconds = timeDifference / 1000; const timeDifferenceInSeconds = timeDifference / 1000;
@ -64,11 +66,15 @@ function submitUserData(drawingZone) {
// console.log('This is from main point', scoreTotal); // console.log('This is from main point', scoreTotal);
drawingZone.renderer.snapshot((image) => { drawingZone.renderer.snapshot((image) => {
submitButton.setVisible(true); submitButton.setVisible(true);
if(!gameType[0] == "guided-tracing"){
snapshotButton.setVisible(true); snapshotButton.setVisible(true);
customCursor.setVisible(true); customCursor.setVisible(true);
galleryButton.setVisible(true);
}
muteIcon.setVisible(true); muteIcon.setVisible(true);
retryButton.setVisible(true); retryButton.setVisible(true);
galleryButton.setVisible(true);
if(gameType[0] == 'drawing'){ if(gameType[0] == 'drawing'){
// submitButton.setVisible(true); // submitButton.setVisible(true);
// snapshotButton.setVisible(true); // snapshotButton.setVisible(true);

View File

@ -6,7 +6,7 @@ const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString); const urlParams = new URLSearchParams(queryString);
const userId = urlParams.get('userId'); const userId = urlParams.get('userId');
const gameVersion = urlParams.get('gameName'); const gameVersion = urlParams.get('gameName');
let gameId; const gameId = urlParams.get('id');
let submitNotic; let submitNotic;
console.log(userId); console.log(userId);

View File

@ -0,0 +1,134 @@
function retryGame(){
window.location.reload();
}
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const userId = urlParams.get('userId');
const gameVersion = urlParams.get('gameName');
let gameId;
let submitNotic;
console.log(userId);
let startTime = Date.now();
const url = window.location.href;
const gameName = url.split('/');
const gameType = gameName[3].split('?id=');
// let gameVersion;
// console.log("Here is game name ", gameType[0])
// if(gameType[0] == "guided-tracing"){
// gameVersion = gameType[0].split('?')[0];
// gameId = gameName[4];
// console.log('Type - 1');
// } else if(gameName.length == 4){
// gameVersion = gameName[3].split('?')[0];
// gameId = urlParams.get('id');
// }
// else if(gameName.length == 5){
// gameVersion = gameName[3] + '-' + gameName[4].split('?')[0];
// gameId = urlParams.get('id');
// console.log('Type - 2');
// }else if(gameName.length == 6){
// gameVersion = gameType[0] + '-' + gameName[4];
// gameId = urlParams.get('id');
// console.log('Type - 3');
// }
console.log(gameVersion)
function submitUserData(drawingZone) {
const endTime = Date.now();
const timeDifference = endTime - startTime;
const timeDifferenceInSeconds = timeDifference / 1000;
// console.log(`Time difference: ${timeDifferenceInSeconds} seconds`);
let imageCode;
let gameScore;
if(scoreTotal){
gameScore = scoreTotal;
}else{
gameScore = 0;
}
// console.log('This is from main point', scoreTotal);
drawingZone.renderer.snapshot((image) => {
if(gameType[0] == 'drawing'){
submitButton.setVisible(true);
snapshotButton.setVisible(true);
customCursor.setVisible(true);
image.style.width = '160px';
image.style.height = '120px';
image.style.paddingLeft = '2px';
document.body.appendChild(image);
// Download the snapshot as an image
// const link = document.createElement('a');
// link.href = image.src;
// link.download = 'my_drawing.png';
// link.click();
document.body.removeChild(image);
imageCode = image.src;
}else if( gameType[0] == "guided-tracing"){
// submitButton.setVisible(true);
// snapshotButton.setVisible(true);
// customCursor.setVisible(true);
image.style.width = '160px';
image.style.height = '120px';
image.style.paddingLeft = '2px';
document.body.appendChild(image);
// Download the snapshot as an image
// const link = document.createElement('a');
// link.href = image.src;
// link.download = `guided-tracing-${gameId}.png`;
// link.click();
document.body.removeChild(image);
imageCode = image.src;
}
let starValue;
if(scoreTotal === maxScore){
starValue = 5;
} else if(scoreTotal === maxScore - 1){
starValue = 4;
} else{
starValue = 3;
}
let userData = {
'gameName': gameVersion,
'gameID': gameId,
'screenShot': imageCode,
'userId' : userId,
'gameTime' : timeDifferenceInSeconds,
'score' : scoreTotal,
'gameStar' : starValue
};
// console.log(userData);
fetch(`https://api.teachertrainingkolkata.in/api/saveGameScore`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(userData)
})
.then(response => {
setTimeout(() => {
if (response.ok) {
if (response.status == 200) {
document.getElementById('wsSavedImg').classList.remove('-z-10');
}
} else {
console.log('Something went wrong', response);
}
}, 100);
})
.catch(error => {
console.error('An error occurred', error);
});
// Clear the drawing
// graphics.clear();
});
};

1012
src/pages/buzzboard.astro Normal file

File diff suppressed because one or more lines are too long

View File

@ -22,7 +22,7 @@ import Layout from "../../layouts/Layout.astro";
<div class="container mx-auto px-4"> <div class="container mx-auto px-4">
<!-- <div class="flex flex-col"> <!-- <div class="flex flex-col">
<p id="LearningArea"></p> <p id="LearningArea"></p>
<p id="LearningSubArea_copy"></p> <p id="LearningSubArea"></p>
</div> --> </div> -->
<p class="sm:text-2xl md:text-3xl lg:text-4xl text-center font-[600] text-[#60C6CB] my-4 select-none" id="gameDescription"></p> <p class="sm:text-2xl md:text-3xl lg:text-4xl text-center font-[600] text-[#60C6CB] my-4 select-none" id="gameDescription"></p>
<form id="contactForm"> <form id="contactForm">
@ -143,7 +143,7 @@ import Layout from "../../layouts/Layout.astro";
document.getElementById("label6").innerHTML = gameData.label6; document.getElementById("label6").innerHTML = gameData.label6;
} }
// document.getElementById('LearningArea').innerHTML = gameData.LearningArea; // document.getElementById('LearningArea').innerHTML = gameData.LearningArea;
// document.getElementById('LearningSubArea_copy').innerHTML = gameData.LearningSubArea_copy; // document.getElementById('LearningSubArea').innerHTML = gameData.LearningSubArea;
const assetsURL = 'https://game-du.teachertrainingkolkata.in/assets/'; const assetsURL = 'https://game-du.teachertrainingkolkata.in/assets/';
for (let i = 1; i <= 6; i++) { for (let i = 1; i <= 6; i++) {
@ -430,7 +430,7 @@ import Layout from "../../layouts/Layout.astro";
color: #7C4C23; color: #7C4C23;
padding-top: 10px; padding-top: 10px;
} }
#LearningArea, #LearningSubArea_copy{ #LearningArea, #LearningSubArea{
font-size: 20px; font-size: 20px;
color: #7C4C23; color: #7C4C23;
font-weight: bold; font-weight: bold;

View File

@ -22,7 +22,7 @@ import Layout from "../../layouts/Layout.astro";
<div class="container mx-auto px-4"> <div class="container mx-auto px-4">
<!-- <div class="flex flex-col"> <!-- <div class="flex flex-col">
<p id="LearningArea"></p> <p id="LearningArea"></p>
<p id="LearningSubArea_copy"></p> <p id="LearningSubArea"></p>
</div> --> </div> -->
<p class="sm:text-2xl md:text-3xl lg:text-3xl text-center font-[600] text-[#60C6CB] my-2 select-none" id="gameDescription"></p> <p class="sm:text-2xl md:text-3xl lg:text-3xl text-center font-[600] text-[#60C6CB] my-2 select-none" id="gameDescription"></p>
<form id="contactForm"> <form id="contactForm">
@ -169,7 +169,7 @@ import Layout from "../../layouts/Layout.astro";
document.getElementById("label9").innerHTML = gameData.label9; document.getElementById("label9").innerHTML = gameData.label9;
} }
// document.getElementById('LearningArea').innerHTML = gameData.LearningArea; // document.getElementById('LearningArea').innerHTML = gameData.LearningArea;
// document.getElementById('LearningSubArea_copy').innerHTML = gameData.LearningSubArea_copy; // document.getElementById('LearningSubArea').innerHTML = gameData.LearningSubArea;
const assetsURL = 'https://game-du.teachertrainingkolkata.in/assets/'; const assetsURL = 'https://game-du.teachertrainingkolkata.in/assets/';
for (let i = 1; i <= 9; i++) { for (let i = 1; i <= 9; i++) {
const imageId = `image${i}`; const imageId = `image${i}`;
@ -464,7 +464,7 @@ import Layout from "../../layouts/Layout.astro";
color: #7C4C23; color: #7C4C23;
padding-top: 10px; padding-top: 10px;
} }
#LearningArea, #LearningSubArea_copy{ #LearningArea, #LearningSubArea{
font-size: 20px; font-size: 20px;
color: #7C4C23; color: #7C4C23;
font-weight: bold; font-weight: bold;

View File

@ -22,7 +22,7 @@ import Layout from "../../layouts/Layout.astro";
<div class="container mx-auto px-4"> <div class="container mx-auto px-4">
<!-- <div class="flex flex-col"> <!-- <div class="flex flex-col">
<p id="LearningArea"></p> <p id="LearningArea"></p>
<p id="LearningSubArea_copy"></p> <p id="LearningSubArea"></p>
</div> --> </div> -->
<p class="sm:text-2xl md:text-3xl lg:text-4xl text-center font-[600] text-[#60C6CB] my-4 select-none" id="gameDescription"></p> <p class="sm:text-2xl md:text-3xl lg:text-4xl text-center font-[600] text-[#60C6CB] my-4 select-none" id="gameDescription"></p>
<form id="contactForm"> <form id="contactForm">
@ -144,7 +144,7 @@ import Layout from "../../layouts/Layout.astro";
document.getElementById("label6").innerHTML = gameData.label6; document.getElementById("label6").innerHTML = gameData.label6;
} }
// document.getElementById('LearningArea').innerHTML = gameData.LearningArea; // document.getElementById('LearningArea').innerHTML = gameData.LearningArea;
// document.getElementById('LearningSubArea_copy').innerHTML = gameData.LearningSubArea_copy; // document.getElementById('LearningSubArea').innerHTML = gameData.LearningSubArea;
const assetsURL = 'https://game-du.teachertrainingkolkata.in/assets/'; const assetsURL = 'https://game-du.teachertrainingkolkata.in/assets/';
for (let i = 1; i <= 6; i++) { for (let i = 1; i <= 6; i++) {
@ -431,7 +431,7 @@ import Layout from "../../layouts/Layout.astro";
color: #7C4C23; color: #7C4C23;
padding-top: 10px; padding-top: 10px;
} }
#LearningArea, #LearningSubArea_copy{ #LearningArea, #LearningSubArea{
font-size: 20px; font-size: 20px;
color: #7C4C23; color: #7C4C23;
font-weight: bold; font-weight: bold;

View File

@ -451,7 +451,7 @@ import Layout from "../../layouts/Layout.astro";
color: #7C4C23; color: #7C4C23;
padding-top: 10px; padding-top: 10px;
} }
#LearningArea, #LearningSubArea_copy{ #LearningArea, #LearningSubArea{
font-size: 20px; font-size: 20px;
color: #7C4C23; color: #7C4C23;
font-weight: bold; font-weight: bold;

View File

@ -340,7 +340,7 @@ const numberOfTimes = starNumberOfTime;
}, },
]; ];
// this.add.text(displayW / 14 - 15, 50, data.LearningArea, {font: `20px`}).setTint(0x7c4c23); // this.add.text(displayW / 14 - 15, 50, data.LearningArea, {font: `20px`}).setTint(0x7c4c23);
// this.add.text(displayW / 14 - 15, 70, data.LearningSubArea_copy, {font: `19px`}).setTint(0x7c4c23); // this.add.text(displayW / 14 - 15, 70, data.LearningSubArea, {font: `19px`}).setTint(0x7c4c23);
// Left Image Name // Left Image Name
this.add.text(displayW / 14 - 15, 240, data.left_image1_name).setTint(0x7c4c23); this.add.text(displayW / 14 - 15, 240, data.left_image1_name).setTint(0x7c4c23);
this.add.text(displayW / 14 - 15, 409, data.left_image2_name).setTint(0x7c4c23); this.add.text(displayW / 14 - 15, 409, data.left_image2_name).setTint(0x7c4c23);
@ -465,7 +465,7 @@ const numberOfTimes = starNumberOfTime;
counter++; counter++;
return 'borderCorrect'; return 'borderCorrect';
} else { } else {
console.log(`Score Total: ${scoreTotal}`); // console.log(`Score Total: ${scoreTotal}`);
return 'borderWrong'; return 'borderWrong';
} }
}; };

View File

@ -327,7 +327,7 @@ import Layout from '../../layouts/Layout.astro';
const responsiveFontSize = (window.innerWidth / textSizeScale) * baseFontSize; const responsiveFontSize = (window.innerWidth / textSizeScale) * baseFontSize;
const descrptText = this.add.text(screenCenterX, 85, data.description, { font: `${responsiveFontSize}px quicksand`, fill: '#60C6CB', align: "center", wordWrap: {width: window.innerWidth-wrapWidth}}, ).setOrigin(0.5); const descrptText = this.add.text(screenCenterX, 85, data.description, { font: `${responsiveFontSize}px quicksand`, fill: '#60C6CB', align: "center", wordWrap: {width: window.innerWidth-wrapWidth}}, ).setOrigin(0.5);
// this.add.text(displayW / 14 - 15, 50, data.LearningArea, {font: `20px`}).setTint(0x7c4c23); // this.add.text(displayW / 14 - 15, 50, data.LearningArea, {font: `20px`}).setTint(0x7c4c23);
// this.add.text(displayW / 14 - 15, 70, data.LearningSubArea_copy, {font: `19px`}).setTint(0x7c4c23); // this.add.text(displayW / 14 - 15, 70, data.LearningSubArea, {font: `19px`}).setTint(0x7c4c23);
// Left Image Name // Left Image Name
this.add.text(displayW / 14 - 15, 240, data.left_image1_name).setTint(0x7c4c23); this.add.text(displayW / 14 - 15, 240, data.left_image1_name).setTint(0x7c4c23);
this.add.text(displayW / 14 - 15, 409, data.left_image2_name).setTint(0x7c4c23); this.add.text(displayW / 14 - 15, 409, data.left_image2_name).setTint(0x7c4c23);

View File

@ -365,7 +365,7 @@ import Layout from '../../layouts/Layout.astro';
fill: '#7c4c23', fill: '#7c4c23',
}).setOrigin(0.5); }).setOrigin(0.5);
// this.add.text(displayW / 14 - 15, 50, data.LearningArea, {font: `20px`}).setTint(0x7c4c23); // this.add.text(displayW / 14 - 15, 50, data.LearningArea, {font: `20px`}).setTint(0x7c4c23);
// this.add.text(displayW / 14 - 15, 70, data.LearningSubArea_copy, {font: `19px`}).setTint(0x7c4c23); // this.add.text(displayW / 14 - 15, 70, data.LearningSubArea, {font: `19px`}).setTint(0x7c4c23);
// Left Image Name // Left Image Name
this.add.text(leftTargetZoneW - 45, 240, data.left_image1_name).setTint(0x7c4c23); this.add.text(leftTargetZoneW - 45, 240, data.left_image1_name).setTint(0x7c4c23);
this.add.text(leftTargetZoneW - 45, 409, data.left_image2_name).setTint(0x7c4c23); this.add.text(leftTargetZoneW - 45, 409, data.left_image2_name).setTint(0x7c4c23);

View File

@ -327,7 +327,7 @@ import Layout from '../../layouts/Layout.astro';
const responsiveFontSize = (window.innerWidth / textSizeScale) * baseFontSize; const responsiveFontSize = (window.innerWidth / textSizeScale) * baseFontSize;
const descrptText = this.add.text(screenCenterX, 110, data.description, { font: `${responsiveFontSize}px quicksand`, fill: '#60C6CB', align: "center", wordWrap: {width: window.innerWidth-wrapWidth}}, ).setOrigin(0.5); const descrptText = this.add.text(screenCenterX, 110, data.description, { font: `${responsiveFontSize}px quicksand`, fill: '#60C6CB', align: "center", wordWrap: {width: window.innerWidth-wrapWidth}}, ).setOrigin(0.5);
// this.add.text(displayW / 14 - 15, 50, data.LearningArea, {font: `20px`}).setTint(0x7c4c23); // this.add.text(displayW / 14 - 15, 50, data.LearningArea, {font: `20px`}).setTint(0x7c4c23);
// this.add.text(displayW / 14 - 15, 70, data.LearningSubArea_copy, {font: `19px`}).setTint(0x7c4c23); // this.add.text(displayW / 14 - 15, 70, data.LearningSubArea, {font: `19px`}).setTint(0x7c4c23);
// Left Image Name // Left Image Name
this.add.text(displayW / 14 - 15, 240, data.left_image1_name).setTint(0x7c4c23); this.add.text(displayW / 14 - 15, 240, data.left_image1_name).setTint(0x7c4c23);
this.add.text(displayW / 14 - 15, 409, data.left_image2_name).setTint(0x7c4c23); this.add.text(displayW / 14 - 15, 409, data.left_image2_name).setTint(0x7c4c23);

View File

@ -309,7 +309,7 @@ import Layout from '../../layouts/Layout.astro';
fill: '#7c4c23', fill: '#7c4c23',
}).setOrigin(0.5); }).setOrigin(0.5);
// this.add.text(displayW / 14 - 15, 50, data.LearningArea, {font: `20px`}).setTint(0x7c4c23); // this.add.text(displayW / 14 - 15, 50, data.LearningArea, {font: `20px`}).setTint(0x7c4c23);
// this.add.text(displayW / 14 - 15, 70, data.LearningSubArea_copy, {font: `19px`}).setTint(0x7c4c23); // this.add.text(displayW / 14 - 15, 70, data.LearningSubArea, {font: `19px`}).setTint(0x7c4c23);
// Left Image Name // Left Image Name
this.add.text(displayW / 14 - 15, 240, data.left_image1_name).setTint(0x7c4c23); this.add.text(displayW / 14 - 15, 240, data.left_image1_name).setTint(0x7c4c23);
this.add.text(displayW / 14 - 15, 409, data.left_image2_name).setTint(0x7c4c23); this.add.text(displayW / 14 - 15, 409, data.left_image2_name).setTint(0x7c4c23);

View File

@ -3,14 +3,71 @@ import Layout from '../../layouts/Layout.astro';
--- ---
<Layout title='Drawing Game'> <Layout title='Drawing Game'>
<main> <main>
<div> <div id="parentMainContainer"class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button onclick="retryGame()" class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
<script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; // Define your mobile breakpoint as needed const isMobile = window.innerWidth <= 768; // Define your mobile breakpoint as needed
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416; const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
@ -32,6 +89,7 @@ import Layout from '../../layouts/Layout.astro';
let shortUniqueID; let shortUniqueID;
let scoreTotal = 0; let scoreTotal = 0;
let maxScore; let maxScore;
let erase;
if(isMobile){ if(isMobile){
topLogoWidth = 4.5; topLogoWidth = 4.5;
muteIconWidth = 1.8; muteIconWidth = 1.8;
@ -175,14 +233,19 @@ import Layout from '../../layouts/Layout.astro';
borderBottom.lineTo(x + lineWidth, y); borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath(); borderBottom.strokePath();
// this.add.image(customWidth / topLogoWidth, 30, "topLogo");
// this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
// const retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
// submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
this.add.image(customWidth / topLogoWidth, 30, "topLogo"); this.add.image(customWidth / topLogoWidth, 30, "topLogo");
this.add.image(customWidth / muteIconWidth, 30, "muteIcon"); muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
const retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon"); retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon"); submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
retryButton.setInteractive().on('pointerdown', () => { retryButton.setInteractive().on('pointerdown', () => {
window.location.reload(); graphics.clear();
}); });
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
// submitButton = this.add.text(window.innerWidth - submitWidth, window.innerHeight - submitHeight, "Submit", { // submitButton = this.add.text(window.innerWidth - submitWidth, window.innerHeight - submitHeight, "Submit", {
@ -193,8 +256,13 @@ import Layout from '../../layouts/Layout.astro';
// }); // });
submitButton.setVisible(true); submitButton.setVisible(true);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
if(isMobile){
colorContainer.style.display = 'none';
// parentMainContainer.classList.remove('hidden');
}
}); });
const textStyle = {font: 'bold 40px quicksand', fill: '#05b3a4',}; const textStyle = {font: 'bold 40px quicksand', fill: '#05b3a4',};
@ -216,7 +284,12 @@ import Layout from '../../layouts/Layout.astro';
outlineImage.setDepth(1).setScale(0.5); outlineImage.setDepth(1).setScale(0.5);
} }
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask);
const colorContainer = document.createElement('div'); const colorContainer = document.createElement('div');
colorContainer.style.position = 'absolute'; colorContainer.style.position = 'absolute';
colorContainer.style.top = '13%'; colorContainer.style.top = '13%';
@ -790,12 +863,49 @@ import Layout from '../../layouts/Layout.astro';
slider.style.background = `linear-gradient(to right, #000 0%, #000 ${offsetX}px, #fff ${offsetX}px, #fff 100%)`; slider.style.background = `linear-gradient(to right, #000 0%, #000 ${offsetX}px, #fff ${offsetX}px, #fff 100%)`;
}; };
const cursorSize = brushSize * cursorSizeMultiplier; const cursorSize = brushSize * cursorSizeMultiplier;
customCursor.clear(); // Clear the previous frame customCursor.clear();
customCursor.lineStyle(3, 0x000000); // Set the line style (2 is the line thickness, 0x000000 is black color) customCursor.lineStyle(1.5, 0x000000);
customCursor.strokeCircle(0, 0, cursorSize); customCursor.strokeCircle(0, 0, cursorSize);
// Position the cursor at the current mouse pointer coordinates customCursor.fillStyle(Phaser.Display.Color.HexStringToColor(selectedColor).color, 1);
customCursor.fillCircle(0, 0, cursorSize);
customCursor.x = this.input.x; customCursor.x = this.input.x;
customCursor.y = this.input.y; customCursor.y = this.input.y;
customCursor.moveTo(0, -cursorSize+3);
customCursor.lineTo(0, cursorSize-3);
customCursor.moveTo(-cursorSize + 3, 0);
customCursor.lineTo(cursorSize-3, 0);
customCursor.strokePath();
if (erase === true) {
customCursor.clear();
customCursor.lineStyle(3, 0x000000);
customCursor.strokeCircle(0, 0, cursorSize);
customCursor.x = this.input.x;
customCursor.y = this.input.y;
customCursor.moveTo(0, -cursorSize+3);
customCursor.lineTo(0, cursorSize-3);
customCursor.moveTo(-cursorSize + 3, 0);
customCursor.lineTo(cursorSize-3, 0);
customCursor.strokePath();
} else if (erase === false) {
customCursor.clear();
customCursor.lineStyle(3, 0x000000);
customCursor.strokeCircle(0, 0, cursorSize);
customCursor.fillStyle(Phaser.Display.Color.HexStringToColor(selectedColor).color, 1);
customCursor.fillCircle(0, 0, cursorSize);
customCursor.x = this.input.x;
customCursor.y = this.input.y;
customCursor.moveTo(0, -cursorSize+3);
customCursor.lineTo(0, cursorSize-3);
customCursor.moveTo(-cursorSize + 3, 0);
customCursor.lineTo(cursorSize-3, 0);
customCursor.strokePath();
}
} }
// function update() { // function update() {
@ -835,5 +945,30 @@ import Layout from '../../layouts/Layout.astro';
.clear-button { .clear-button {
background-color: blue; background-color: blue;
} }
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
</style> </style>
<!-- <svg width="64px" height="64px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path d="M11.4001 18.1612L11.4001 18.1612L18.796 10.7653C17.7894 10.3464 16.5972 9.6582 15.4697 8.53068C14.342 7.40298 13.6537 6.21058 13.2348 5.2039L5.83882 12.5999L5.83879 12.5999C5.26166 13.1771 4.97307 13.4657 4.7249 13.7838C4.43213 14.1592 4.18114 14.5653 3.97634 14.995C3.80273 15.3593 3.67368 15.7465 3.41556 16.5208L2.05445 20.6042C1.92743 20.9852 2.0266 21.4053 2.31063 21.6894C2.59466 21.9734 3.01478 22.0726 3.39584 21.9456L7.47918 20.5844C8.25351 20.3263 8.6407 20.1973 9.00498 20.0237C9.43469 19.8189 9.84082 19.5679 10.2162 19.2751C10.5343 19.0269 10.823 18.7383 11.4001 18.1612Z" fill="#1C274C"></path> <path d="M20.8482 8.71306C22.3839 7.17735 22.3839 4.68748 20.8482 3.15178C19.3125 1.61607 16.8226 1.61607 15.2869 3.15178L14.3999 4.03882C14.4121 4.0755 14.4246 4.11268 14.4377 4.15035C14.7628 5.0875 15.3763 6.31601 16.5303 7.47002C17.6843 8.62403 18.9128 9.23749 19.85 9.56262C19.8875 9.57563 19.9245 9.58817 19.961 9.60026L20.8482 8.71306Z" fill="#1C274C"></path> </g></svg> -->

View File

@ -3,14 +3,71 @@ import Layout from '../../layouts/Layout.astro';
--- ---
<Layout title='Drawing Game'> <Layout title='Drawing Game'>
<main> <main>
<div> <div id="parentMainContainer"class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button onclick="retryGame()" class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
<script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; // Define your mobile breakpoint as needed const isMobile = window.innerWidth <= 768; // Define your mobile breakpoint as needed
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416; const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
@ -32,6 +89,7 @@ import Layout from '../../layouts/Layout.astro';
let shortUniqueID; let shortUniqueID;
let scoreTotal = 0; let scoreTotal = 0;
let maxScore; let maxScore;
let erase;
if(isMobile){ if(isMobile){
topLogoWidth = 4.5; topLogoWidth = 4.5;
muteIconWidth = 1.8; muteIconWidth = 1.8;
@ -166,6 +224,8 @@ import Layout from '../../layouts/Layout.astro';
}); });
// window.load // window.load
const borderBottom = this.add.graphics(); const borderBottom = this.add.graphics();
const x = 0; const y = 54; const x = 0; const y = 54;
const lineWidth = window.innerWidth; const lineWidth = window.innerWidth;
@ -176,14 +236,19 @@ import Layout from '../../layouts/Layout.astro';
borderBottom.lineTo(x + lineWidth, y); borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath(); borderBottom.strokePath();
// this.add.image(customWidth / topLogoWidth, 30, "topLogo");
// this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
// const retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
// submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
this.add.image(customWidth / topLogoWidth, 30, "topLogo"); this.add.image(customWidth / topLogoWidth, 30, "topLogo");
this.add.image(customWidth / muteIconWidth, 30, "muteIcon"); muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
const retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon"); retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon"); submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
retryButton.setInteractive().on('pointerdown', () => { retryButton.setInteractive().on('pointerdown', () => {
window.location.reload(); graphics.clear();
}); });
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
@ -195,8 +260,13 @@ import Layout from '../../layouts/Layout.astro';
// }); // });
submitButton.setVisible(true); submitButton.setVisible(true);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
if(isMobile){
colorContainer.style.display = 'none';
// parentMainContainer.classList.remove('hidden');
}
}); });
const textStyle = {font: 'bold 40px quicksand', fill: '#05b3a4',}; const textStyle = {font: 'bold 40px quicksand', fill: '#05b3a4',};
@ -226,7 +296,12 @@ import Layout from '../../layouts/Layout.astro';
// } else{ // } else{
// outlineImage.setDepth(1).setScale(0.65); // outlineImage.setDepth(1).setScale(0.65);
// } // }
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask);
const colorContainer = document.createElement('div'); const colorContainer = document.createElement('div');
colorContainer.style.position = 'absolute'; colorContainer.style.position = 'absolute';
colorContainer.style.top = '13%'; colorContainer.style.top = '13%';
@ -800,50 +875,76 @@ import Layout from '../../layouts/Layout.astro';
slider.style.background = `linear-gradient(to right, #000 0%, #000 ${offsetX}px, #fff ${offsetX}px, #fff 100%)`; slider.style.background = `linear-gradient(to right, #000 0%, #000 ${offsetX}px, #fff ${offsetX}px, #fff 100%)`;
}; };
const cursorSize = brushSize * cursorSizeMultiplier; const cursorSize = brushSize * cursorSizeMultiplier;
customCursor.clear(); // Clear the previous frame customCursor.clear();
customCursor.lineStyle(3, 0x000000); // Set the line style (2 is the line thickness, 0x000000 is black color) customCursor.lineStyle(1.5, 0x000000);
customCursor.strokeCircle(0, 0, cursorSize); customCursor.strokeCircle(0, 0, cursorSize);
// Position the cursor at the current mouse pointer coordinates customCursor.fillStyle(Phaser.Display.Color.HexStringToColor(selectedColor).color, 1);
customCursor.fillCircle(0, 0, cursorSize);
customCursor.x = this.input.x; customCursor.x = this.input.x;
customCursor.y = this.input.y; customCursor.y = this.input.y;
customCursor.moveTo(0, - cursorSize + 3);
customCursor.lineTo(0, cursorSize - 3);
customCursor.moveTo(- cursorSize + 3, 0);
customCursor.lineTo(cursorSize - 3, 0);
customCursor.strokePath();
if (erase === true) {
customCursor.clear();
customCursor.lineStyle(3, 0x000000);
customCursor.strokeCircle(0, 0, cursorSize);
customCursor.x = this.input.x;
customCursor.y = this.input.y;
customCursor.moveTo(0, - cursorSize + 3);
customCursor.lineTo(0, cursorSize - 3);
customCursor.moveTo(- cursorSize + 3, 0);
customCursor.lineTo(cursorSize - 3, 0);
customCursor.strokePath();
} else if (erase === false) {
customCursor.clear();
customCursor.lineStyle(3, 0x000000);
customCursor.strokeCircle(0, 0, cursorSize);
customCursor.fillStyle(Phaser.Display.Color.HexStringToColor(selectedColor).color, 1);
customCursor.fillCircle(0, 0, cursorSize);
customCursor.x = this.input.x;
customCursor.y = this.input.y;
customCursor.moveTo(0, - cursorSize + 3);
customCursor.lineTo(0, cursorSize - 3);
customCursor.moveTo(- cursorSize + 3, 0);
customCursor.lineTo(cursorSize - 3, 0);
customCursor.strokePath();
}
} }
// function update() {
// const slider = document.querySelector('input[type="range"]');
// if (slider && !isDrawing) {
// const sliderValue = parseInt(slider.value);
// const max = parseInt(slider.max);
// const width = slider.offsetWidth;
// const offsetX = (sliderValue - 2) / (max - 2) * width;
// slider.style.background = `linear-gradient(to right, #000 0%, #000 ${offsetX}px, #fff ${offsetX}px, #fff 100%)`;
// }
// const cursorSize = brushSize * cursorSizeMultiplier;
// const cursorScale = 1; // Adjust this value to increase/decrease the cursor size
// // Assuming 'this' refers to your Phaser.Scene instance
// if (!this.customCursor) {
// // Create the custom cursor sprite
// this.customCursor = this.add.sprite(0, 0, 'cursorImage'); // Replace 'yourCursorImage' with the key of your loaded PNG image
// this.customCursor.setOrigin(0.3, 0.8);
// }
// // Set the tint or fill color dynamically based on the selectedColor
// const color = Phaser.Display.Color.HexStringToColor(selectedColor).color;
// this.customCursor.setTint(color);
// // Resize the cursor
// this.customCursor.setScale( cursorScale);
// // Position the cursor at the current mouse pointer coordinates
// this.customCursor.x = this.input.x;
// this.customCursor.y = this.input.y;
// }
</script> </script>
<style> <style>
.clear-button { /* Animation styles */
background-color: blue; @keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
} }
</style> </style>
<!-- <svg width="64px" height="64px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path d="M11.4001 18.1612L11.4001 18.1612L18.796 10.7653C17.7894 10.3464 16.5972 9.6582 15.4697 8.53068C14.342 7.40298 13.6537 6.21058 13.2348 5.2039L5.83882 12.5999L5.83879 12.5999C5.26166 13.1771 4.97307 13.4657 4.7249 13.7838C4.43213 14.1592 4.18114 14.5653 3.97634 14.995C3.80273 15.3593 3.67368 15.7465 3.41556 16.5208L2.05445 20.6042C1.92743 20.9852 2.0266 21.4053 2.31063 21.6894C2.59466 21.9734 3.01478 22.0726 3.39584 21.9456L7.47918 20.5844C8.25351 20.3263 8.6407 20.1973 9.00498 20.0237C9.43469 19.8189 9.84082 19.5679 10.2162 19.2751C10.5343 19.0269 10.823 18.7383 11.4001 18.1612Z" fill="#1C274C"></path> <path d="M20.8482 8.71306C22.3839 7.17735 22.3839 4.68748 20.8482 3.15178C19.3125 1.61607 16.8226 1.61607 15.2869 3.15178L14.3999 4.03882C14.4121 4.0755 14.4246 4.11268 14.4377 4.15035C14.7628 5.0875 15.3763 6.31601 16.5303 7.47002C17.6843 8.62403 18.9128 9.23749 19.85 9.56262C19.8875 9.57563 19.9245 9.58817 19.961 9.60026L20.8482 8.71306Z" fill="#1C274C"></path> </g></svg> -->

View File

@ -142,6 +142,7 @@ import Layout from '../../layouts/Layout.astro';
let muteIcon; let muteIcon;
let retryButton; let retryButton;
let maxScore; let maxScore;
let erase;
if(isMobile){ if(isMobile){
topLogoWidth = 4.5; topLogoWidth = 4.5;
muteIconWidth = 1.65; muteIconWidth = 1.65;
@ -345,7 +346,14 @@ import Layout from '../../layouts/Layout.astro';
} else{ } else{
outlineImage.setDepth(1).setScale(0.65); outlineImage.setDepth(1).setScale(0.65);
} }
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask);
const colorContainer = document.createElement('div'); const colorContainer = document.createElement('div');
colorContainer.style.zIndex = '1'; colorContainer.style.zIndex = '1';
colorContainer.style.position = 'absolute'; colorContainer.style.position = 'absolute';
@ -701,13 +709,17 @@ import Layout from '../../layouts/Layout.astro';
eraserButton.style.boxShadow = '5px 10px 15px #7c4c2390'; eraserButton.style.boxShadow = '5px 10px 15px #7c4c2390';
eraserButton.addEventListener('click', () => { eraserButton.addEventListener('click', () => {
isErasing = !isErasing; isErasing = !isErasing;
erase = false;
if (isErasing) { if (isErasing) {
eraserButton.style.border = '2px solid #0348A8'; erase = true;
eraserButton.style.border = '3px solid #0348A8';
eraserButton.style.backgroundColor = '#0348A820';
} else { } else {
// Return to drawing mode // Return to drawing mode
// eraserButton.style.backgroundColor = 'green'; // Restore eraser button color // eraserButton.style.backgroundColor = 'green'; // Restore eraser button color
eraserButton.style.color = 'blue'; eraserButton.style.color = 'blue';
eraserButton.style.border = 'none'; eraserButton.style.border = 'none';
eraserButton.style.backgroundColor = 'transparent';
} }
}); });
// Add the Clear and Eraser buttons to the container // Add the Clear and Eraser buttons to the container
@ -836,85 +848,6 @@ import Layout from '../../layouts/Layout.astro';
}); });
} }
// const url = window.location.href;
// const gameName = url.split('/');
// const gameType = gameName[3].split('?id=');
// function submitUserData(drawingZone) {
// let imageCode;
// // console.log(drawingZone);
// drawingZone.renderer.snapshot((image) => {
// submitButton.setVisible(true);
// snapshotButton.setVisible(true);
// customCursor.setVisible(true);
// image.style.width = '160px';
// image.style.height = '120px';
// image.style.paddingLeft = '2px';
// document.body.appendChild(image);
// // Download the snapshot as an image
// const link = document.createElement('a');
// link.href = image.src;
// link.download = 'my_drawing.png';
// link.click();
// document.body.removeChild(image);
// imageCode = image.src;
// let userData = {
// 'userID': 'drawing@beanstalkedu.com',
// 'gameType': gameType[0],
// 'gameID': gameType[1],
// 'screenShot': imageCode
// // 'starts': formattedDateTime,
// // 'game_start' : gameStartTime,
// };
// console.log(userData);
// fetch(`https://save-game-data.teachertrainingchennai.in/saveGameData`, {
// method: 'POST',
// headers: {
// 'Content-Type' : 'application/json'
// },
// body: JSON.stringify(userData)
// })
// .then(response => {
// if(response.ok){
// console.log('Data Saved', response)
// } else{
// // console.log('Something Wrong', response)
// }
// })
// .catch(error => {
// console.error('An error occured', error)
// });
// // Clear the drawing
// // graphics.clear();
// });
// };
// function captureSnapshot(drawingZone) {
// submitButton.setVisible(false);
// // snapNotice.setVisible(true);
// snapshotButton.setVisible(false);
// customCursor.setVisible(false);
// drawingZone.renderer.snapshot((image) => {
// submitButton.setVisible(true);
// snapshotButton.setVisible(true);
// customCursor.setVisible(true);
// image.style.width = '160px';
// image.style.height = '120px';
// image.style.paddingLeft = '2px';
// document.body.appendChild(image);
// // Download the snapshot as an image
// const link = document.createElement('a');
// link.href = image.src;
// link.download = 'my_drawing.png';
// link.click();
// document.body.removeChild(image);
// // Clear the drawing
// // graphics.clear();
// });
// }
function startDrawing(x, y) { function startDrawing(x, y) {
if (!isErasing) { if (!isErasing) {
graphics.lineStyle(brushSize * 2, Phaser.Display.Color.HexStringToColor(selectedColor).color); graphics.lineStyle(brushSize * 2, Phaser.Display.Color.HexStringToColor(selectedColor).color);
@ -952,12 +885,49 @@ import Layout from '../../layouts/Layout.astro';
slider.style.background = `linear-gradient(to right, #000 0%, #000 ${offsetX}px, #fff ${offsetX}px, #fff 100%)`; slider.style.background = `linear-gradient(to right, #000 0%, #000 ${offsetX}px, #fff ${offsetX}px, #fff 100%)`;
}; };
const cursorSize = brushSize * cursorSizeMultiplier; const cursorSize = brushSize * cursorSizeMultiplier;
customCursor.clear(); // Clear the previous frame customCursor.clear();
customCursor.lineStyle(3, 0x000000); // Set the line style (2 is the line thickness, 0x000000 is black color) customCursor.lineStyle(1.5, 0x000000);
customCursor.strokeCircle(0, 0, cursorSize); customCursor.strokeCircle(0, 0, cursorSize);
// Position the cursor at the current mouse pointer coordinates customCursor.fillStyle(Phaser.Display.Color.HexStringToColor(selectedColor).color, 1);
customCursor.fillCircle(0, 0, cursorSize);
customCursor.x = this.input.x; customCursor.x = this.input.x;
customCursor.y = this.input.y; customCursor.y = this.input.y;
customCursor.moveTo(0, -cursorSize+3);
customCursor.lineTo(0, cursorSize-3);
customCursor.moveTo(-cursorSize + 3, 0);
customCursor.lineTo(cursorSize-3, 0);
customCursor.strokePath();
if (erase === true) {
customCursor.clear();
customCursor.lineStyle(3, 0x000000);
customCursor.strokeCircle(0, 0, cursorSize);
customCursor.x = this.input.x;
customCursor.y = this.input.y;
customCursor.moveTo(0, -cursorSize+3);
customCursor.lineTo(0, cursorSize-3);
customCursor.moveTo(-cursorSize + 3, 0);
customCursor.lineTo(cursorSize-3, 0);
customCursor.strokePath();
} else if (erase === false) {
customCursor.clear();
customCursor.lineStyle(3, 0x000000);
customCursor.strokeCircle(0, 0, cursorSize);
customCursor.fillStyle(Phaser.Display.Color.HexStringToColor(selectedColor).color, 1);
customCursor.fillCircle(0, 0, cursorSize);
customCursor.x = this.input.x;
customCursor.y = this.input.y;
customCursor.moveTo(0, -cursorSize+3);
customCursor.lineTo(0, cursorSize-3);
customCursor.moveTo(-cursorSize + 3, 0);
customCursor.lineTo(cursorSize-3, 0);
customCursor.strokePath();
}
} }
// function update() { // function update() {
@ -1030,4 +1000,3 @@ import Layout from '../../layouts/Layout.astro';
display: block; display: block;
} }
</style> </style>
<!-- <svg width="64px" height="64px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path d="M11.4001 18.1612L11.4001 18.1612L18.796 10.7653C17.7894 10.3464 16.5972 9.6582 15.4697 8.53068C14.342 7.40298 13.6537 6.21058 13.2348 5.2039L5.83882 12.5999L5.83879 12.5999C5.26166 13.1771 4.97307 13.4657 4.7249 13.7838C4.43213 14.1592 4.18114 14.5653 3.97634 14.995C3.80273 15.3593 3.67368 15.7465 3.41556 16.5208L2.05445 20.6042C1.92743 20.9852 2.0266 21.4053 2.31063 21.6894C2.59466 21.9734 3.01478 22.0726 3.39584 21.9456L7.47918 20.5844C8.25351 20.3263 8.6407 20.1973 9.00498 20.0237C9.43469 19.8189 9.84082 19.5679 10.2162 19.2751C10.5343 19.0269 10.823 18.7383 11.4001 18.1612Z" fill="#1C274C"></path> <path d="M20.8482 8.71306C22.3839 7.17735 22.3839 4.68748 20.8482 3.15178C19.3125 1.61607 16.8226 1.61607 15.2869 3.15178L14.3999 4.03882C14.4121 4.0755 14.4246 4.11268 14.4377 4.15035C14.7628 5.0875 15.3763 6.31601 16.5303 7.47002C17.6843 8.62403 18.9128 9.23749 19.85 9.56262C19.8875 9.57563 19.9245 9.58817 19.961 9.60026L20.8482 8.71306Z" fill="#1C274C"></path> </g></svg> -->

View File

@ -3,34 +3,66 @@ import Layout from '../../layouts/Layout.astro';
--- ---
<Layout title='Drawing Game'> <Layout title='Drawing Game'>
<main> <main>
<div> <div id="parentMainContainer"class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute" style="display: none;"> <div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"> <div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div> </div>
</div> <div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div id="scoreBoard" class=" w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" > <div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center"> <div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div> <div id="star-container"></div>
</div> </div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;"> <div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/clip-art.svg" alt="" /> <img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p> <p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div> </div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3"> <div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button> <button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button> <button onclick="retryGame()" class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div> </div>
</div> </div>
</div> </div>
<div class="clip-art-container absolute bottom-0 right-0"> <div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<img src="/assets/svg/clip-art2.svg" alt="Clip Art" class="clip-art"> <div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div> </div>
</div> </div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() { function showAnimation() {
const clipArt = document.querySelector('.clip-art'); const clipArt = document.querySelector('.clip-art');
@ -65,6 +97,7 @@ import Layout from '../../layouts/Layout.astro';
let noticeWidth; let noticeWidth;
let noticeHeight; let noticeHeight;
let maxScore; let maxScore;
let erase;
if(isMobile){ if(isMobile){
topLogoWidth = 4.5; topLogoWidth = 4.5;
muteIconWidth = 1.8; muteIconWidth = 1.8;
@ -254,12 +287,18 @@ import Layout from '../../layouts/Layout.astro';
const outlineImage1 = this.add.image(customWidth / image1Width, customHeight / image1Height, 'image1'); const outlineImage1 = this.add.image(customWidth / image1Width, customHeight / image1Height, 'image1');
const outlineImage2 = this.add.image(customWidth / image2Width + image2Right, customHeight / image2Height + image2Bottom, 'image2'); const outlineImage2 = this.add.image(customWidth / image2Width + image2Right, customHeight / image2Height + image2Bottom, 'image2');
// this.add.image(customWidth / topLogoWidth, 30, "topLogo");
// this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
// const retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
// submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
this.add.image(customWidth / topLogoWidth, 30, "topLogo"); this.add.image(customWidth / topLogoWidth, 30, "topLogo");
this.add.image(customWidth / muteIconWidth, 30, "muteIcon"); muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
const retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon"); retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon"); submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
retryButton.setInteractive().on('pointerdown', ()=>{ retryButton.setInteractive().on('pointerdown', ()=>{
window.location.reload(); graphics.clear();
}) })
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
// submitButton = this.add.text(window.innerWidth - submitWidth, window.innerHeight - submitHeight, "Submit", { // submitButton = this.add.text(window.innerWidth - submitWidth, window.innerHeight - submitHeight, "Submit", {
@ -268,13 +307,16 @@ import Layout from '../../layouts/Layout.astro';
// backgroundColor: 'blue', // backgroundColor: 'blue',
// padding: { x: 20, y: 10 }, // padding: { x: 20, y: 10 },
// }); // });
submitButton.setVisible(true);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked');
// windowLoad();
// submitUserData();
submitUserData(this); submitUserData(this);
showAnimation(); showAnimation();
}) parentMainContainer.classList.remove('hidden');
if(isMobile){
colorContainer.style.display = 'none';
// parentMainContainer.classList.remove('hidden');
}
});
const textStyle = {font: 'bold 40px quicksand', fill: '#05b3a4',}; const textStyle = {font: 'bold 40px quicksand', fill: '#05b3a4',};
if(!isMobile){ if(!isMobile){
// this.add.text(customWidth / 10, 20, "Drawing", textStyle); // this.add.text(customWidth / 10, 20, "Drawing", textStyle);
@ -294,7 +336,14 @@ import Layout from '../../layouts/Layout.astro';
outlineImage1.setDepth(-5).setScale(0.60); outlineImage1.setDepth(-5).setScale(0.60);
outlineImage2.setDepth(-5).setScale(0.60); outlineImage2.setDepth(-5).setScale(0.60);
} }
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask);
const colorContainer = document.createElement('div'); const colorContainer = document.createElement('div');
colorContainer.style.position = 'absolute'; colorContainer.style.position = 'absolute';
colorContainer.style.top = '13%'; colorContainer.style.top = '13%';
@ -724,12 +773,49 @@ import Layout from '../../layouts/Layout.astro';
slider.style.background = `linear-gradient(to right, #000 0%, #000 ${offsetX}px, #fff ${offsetX}px, #fff 100%)`; slider.style.background = `linear-gradient(to right, #000 0%, #000 ${offsetX}px, #fff ${offsetX}px, #fff 100%)`;
}; };
const cursorSize = brushSize * cursorSizeMultiplier; const cursorSize = brushSize * cursorSizeMultiplier;
customCursor.clear(); // Clear the previous frame customCursor.clear();
customCursor.lineStyle(3, 0x000000); // Set the line style (2 is the line thickness, 0x000000 is black color) customCursor.lineStyle(1.5, 0x000000);
customCursor.strokeCircle(0, 0, cursorSize); customCursor.strokeCircle(0, 0, cursorSize);
// Position the cursor at the current mouse pointer coordinates customCursor.fillStyle(Phaser.Display.Color.HexStringToColor(defaultColor).color, 1);
customCursor.fillCircle(0, 0, cursorSize);
customCursor.x = this.input.x; customCursor.x = this.input.x;
customCursor.y = this.input.y; customCursor.y = this.input.y;
customCursor.moveTo(0, -cursorSize+3);
customCursor.lineTo(0, cursorSize-3);
customCursor.moveTo(-cursorSize + 3, 0);
customCursor.lineTo(cursorSize-3, 0);
customCursor.strokePath();
if (erase === true) {
customCursor.clear();
customCursor.lineStyle(3, 0x000000);
customCursor.strokeCircle(0, 0, cursorSize);
customCursor.x = this.input.x;
customCursor.y = this.input.y;
customCursor.moveTo(0, -cursorSize+3);
customCursor.lineTo(0, cursorSize-3);
customCursor.moveTo(-cursorSize + 3, 0);
customCursor.lineTo(cursorSize-3, 0);
customCursor.strokePath();
} else if (erase === false) {
customCursor.clear();
customCursor.lineStyle(3, 0x000000);
customCursor.strokeCircle(0, 0, cursorSize);
customCursor.fillStyle(Phaser.Display.Color.HexStringToColor(defaultColor).color, 1);
customCursor.fillCircle(0, 0, cursorSize);
customCursor.x = this.input.x;
customCursor.y = this.input.y;
customCursor.moveTo(0, -cursorSize+3);
customCursor.lineTo(0, cursorSize-3);
customCursor.moveTo(-cursorSize + 3, 0);
customCursor.lineTo(cursorSize-3, 0);
customCursor.strokePath();
}
} }
</script> </script>
<style> <style>

View File

@ -3,14 +3,71 @@ import Layout from '../../layouts/Layout.astro';
--- ---
<Layout title='Drawing Game'> <Layout title='Drawing Game'>
<main> <main>
<div> <div id="parentMainContainer"class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button onclick="retryGame()" class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
<script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; // Define your mobile breakpoint as needed const isMobile = window.innerWidth <= 768; // Define your mobile breakpoint as needed
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416; const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
@ -32,6 +89,7 @@ import Layout from '../../layouts/Layout.astro';
let tickIconWidth; let tickIconWidth;
let cancelIconWidth; let cancelIconWidth;
let maxScore; let maxScore;
let erase;
if(isMobile){ if(isMobile){
topLogoWidth = 4.5; topLogoWidth = 4.5;
@ -208,12 +266,21 @@ import Layout from '../../layouts/Layout.astro';
borderBottom.strokePath(); borderBottom.strokePath();
const outlineImage = this.add.image(customWidth / 2, customHeight / 2 + 20, 'outline'); const outlineImage = this.add.image(customWidth / 2, customHeight / 2 + 20, 'outline');
// this.add.image(customWidth / topLogoWidth, 30, "topLogo");
// this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
// const retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
// submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
this.add.image(customWidth / topLogoWidth, 30, "topLogo"); this.add.image(customWidth / topLogoWidth, 30, "topLogo");
this.add.image(customWidth / muteIconWidth, 30, "muteIcon"); muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
const retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon"); retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon"); submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
// galleryButton = this.add.image(customWidth / galleryIconWidth, 30, "galleryIcons");
retryButton.setInteractive().on('pointerdown', () => { retryButton.setInteractive().on('pointerdown', () => {
window.location.reload(); graphics.clear();
}) })
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
// submitButton = this.add.text(window.innerWidth - submitWidth, window.innerHeight - submitHeight, "Submit", { // submitButton = this.add.text(window.innerWidth - submitWidth, window.innerHeight - submitHeight, "Submit", {
@ -222,13 +289,16 @@ import Layout from '../../layouts/Layout.astro';
// backgroundColor: 'blue', // backgroundColor: 'blue',
// padding: { x: 20, y: 10 }, // padding: { x: 20, y: 10 },
// }); // });
// submitButton.setVisible(true); submitButton.setVisible(true);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked');
// submitButton.setVisible(false);
// windowLoad();
submitUserData(this); submitUserData(this);
}) showAnimation();
parentMainContainer.classList.remove('hidden');
if(isMobile){
colorContainer.style.display = 'none';
// parentMainContainer.classList.remove('hidden');
}
});
// const textStyle = {font: 'bold 40px quicksand', fill: '#05b3a4',}; // const textStyle = {font: 'bold 40px quicksand', fill: '#05b3a4',};
// if(!isMobile){ // if(!isMobile){
// this.add.text(customWidth / 10, 20, "Drawing", textStyle); // this.add.text(customWidth / 10, 20, "Drawing", textStyle);
@ -245,7 +315,12 @@ import Layout from '../../layouts/Layout.astro';
outlineImage.setDepth(-1).setScale(1); outlineImage.setDepth(-1).setScale(1);
} }
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask);
const colorContainer = document.createElement('div'); const colorContainer = document.createElement('div');
colorContainer.style.position = 'absolute'; colorContainer.style.position = 'absolute';
colorContainer.style.top = '13%'; colorContainer.style.top = '13%';
@ -747,12 +822,49 @@ import Layout from '../../layouts/Layout.astro';
slider.style.background = `linear-gradient(to right, #000 0%, #000 ${offsetX}px, #fff ${offsetX}px, #fff 100%)`; slider.style.background = `linear-gradient(to right, #000 0%, #000 ${offsetX}px, #fff ${offsetX}px, #fff 100%)`;
}; };
const cursorSize = brushSize * cursorSizeMultiplier; const cursorSize = brushSize * cursorSizeMultiplier;
customCursor.clear(); // Clear the previous frame customCursor.clear();
customCursor.lineStyle(3, 0x000000); // Set the line style (2 is the line thickness, 0x000000 is black color) customCursor.lineStyle(1.5, 0x000000);
customCursor.strokeCircle(0, 0, cursorSize); customCursor.strokeCircle(0, 0, cursorSize);
// Position the cursor at the current mouse pointer coordinates customCursor.fillStyle(Phaser.Display.Color.HexStringToColor(selectedColor).color, 1);
customCursor.fillCircle(0, 0, cursorSize);
customCursor.x = this.input.x; customCursor.x = this.input.x;
customCursor.y = this.input.y; customCursor.y = this.input.y;
customCursor.moveTo(0, -cursorSize+3);
customCursor.lineTo(0, cursorSize-3);
customCursor.moveTo(-cursorSize + 3, 0);
customCursor.lineTo(cursorSize-3, 0);
customCursor.strokePath();
if (erase === true) {
customCursor.clear();
customCursor.lineStyle(3, 0x000000);
customCursor.strokeCircle(0, 0, cursorSize);
customCursor.x = this.input.x;
customCursor.y = this.input.y;
customCursor.moveTo(0, -cursorSize+3);
customCursor.lineTo(0, cursorSize-3);
customCursor.moveTo(-cursorSize + 3, 0);
customCursor.lineTo(cursorSize-3, 0);
customCursor.strokePath();
} else if (erase === false) {
customCursor.clear();
customCursor.lineStyle(3, 0x000000);
customCursor.strokeCircle(0, 0, cursorSize);
customCursor.fillStyle(Phaser.Display.Color.HexStringToColor(selectedColor).color, 1);
customCursor.fillCircle(0, 0, cursorSize);
customCursor.x = this.input.x;
customCursor.y = this.input.y;
customCursor.moveTo(0, -cursorSize+3);
customCursor.lineTo(0, cursorSize-3);
customCursor.moveTo(-cursorSize + 3, 0);
customCursor.lineTo(cursorSize-3, 0);
customCursor.strokePath();
}
} }
// function update() { // function update() {
@ -788,4 +900,40 @@ import Layout from '../../layouts/Layout.astro';
// this.customCursor.y = this.input.y; // this.customCursor.y = this.input.y;
// } // }
</script> </script>
<!-- <svg width="64px" height="64px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path d="M11.4001 18.1612L11.4001 18.1612L18.796 10.7653C17.7894 10.3464 16.5972 9.6582 15.4697 8.53068C14.342 7.40298 13.6537 6.21058 13.2348 5.2039L5.83882 12.5999L5.83879 12.5999C5.26166 13.1771 4.97307 13.4657 4.7249 13.7838C4.43213 14.1592 4.18114 14.5653 3.97634 14.995C3.80273 15.3593 3.67368 15.7465 3.41556 16.5208L2.05445 20.6042C1.92743 20.9852 2.0266 21.4053 2.31063 21.6894C2.59466 21.9734 3.01478 22.0726 3.39584 21.9456L7.47918 20.5844C8.25351 20.3263 8.6407 20.1973 9.00498 20.0237C9.43469 19.8189 9.84082 19.5679 10.2162 19.2751C10.5343 19.0269 10.823 18.7383 11.4001 18.1612Z" fill="#1C274C"></path> <path d="M20.8482 8.71306C22.3839 7.17735 22.3839 4.68748 20.8482 3.15178C19.3125 1.61607 16.8226 1.61607 15.2869 3.15178L14.3999 4.03882C14.4121 4.0755 14.4246 4.11268 14.4377 4.15035C14.7628 5.0875 15.3763 6.31601 16.5303 7.47002C17.6843 8.62403 18.9128 9.23749 19.85 9.56262C19.8875 9.57563 19.9245 9.58817 19.961 9.60026L20.8482 8.71306Z" fill="#1C274C"></path> </g></svg> --> <style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,75 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer"class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416; const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
@ -39,7 +100,7 @@ import Layout from "../../layouts/Layout.astro";
const game = new Phaser.Game(config); const game = new Phaser.Game(config);
const customWidth = window.innerWidth; const customWidth = window.innerWidth;
const customHeight = window.innerHeight; const customHeight = window.innerHeight;
let firstLayer, secondLayer, thirdLayer; let firstLayer;
let graphics; let graphics;
let isDrawing = false; let isDrawing = false;
let formattedDateTime; let formattedDateTime;
@ -55,7 +116,7 @@ import Layout from "../../layouts/Layout.astro";
var assetsList = {} var assetsList = {}
var snapshotButton; var snapshotButton;
let submitButton; let submitButton;
let demoButtonButton; let demoButton;
let shortUniqueID; let shortUniqueID;
let noticeWidth; let noticeWidth;
let noticeHeight; let noticeHeight;
@ -70,23 +131,6 @@ import Layout from "../../layouts/Layout.astro";
tickIconWidth = 1.21; tickIconWidth = 1.21;
cancelIconWidth = 1.08; cancelIconWidth = 1.08;
galleryIconWidth = 2; galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
}else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
if(isMobile){
submitWidth = 250; submitWidth = 250;
submitHeight = 110; submitHeight = 110;
noticeWidth = 100; noticeWidth = 100;
@ -94,24 +138,7 @@ import Layout from "../../layouts/Layout.astro";
downloadWidth = 67; downloadWidth = 67;
downloadHeight = 200; downloadHeight = 200;
learningWidth = 200; learningWidth = 200;
learningHeight = 400 learningHeight = 400;
}else {
submitWidth = 380;
submitHeight = 95;
noticeWidth = 0;
noticeHeight = 0;
downloadWidth = 180;
downloadHeight = 70;
learningWidth = 450;
learningHeight = 400
}
if(isMobile){
cloudeSize = 200;
cloudHeight = 340;
canvasScale = 0.14
canvasHeight = 35;
letterHeight = 30; letterHeight = 30;
letterScale = 1.8; letterScale = 1.8;
backgroundScale = 0.8; backgroundScale = 0.8;
@ -130,11 +157,30 @@ import Layout from "../../layouts/Layout.astro";
submitHeight = customHeight / 1.1; submitHeight = customHeight / 1.1;
noticeWidth = window.innerWidth * 0.5 - 100; noticeWidth = window.innerWidth * 0.5 - 100;
noticeHeight = window.innerHeight * 0.38; noticeHeight = window.innerHeight * 0.38;
} else{ }else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
}else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
submitWidth = 380;
submitHeight = 95;
noticeWidth = 0;
noticeHeight = 0;
downloadWidth = 180;
downloadHeight = 70;
learningWidth = 450;
learningHeight = 400;
cloudeSize = 500; cloudeSize = 500;
cloudHeight = 250; cloudHeight = 250;
canvasScale = 0.195;
canvasHeight = 20;
letterHeight = 10; letterHeight = 10;
letterScale = 1.8; letterScale = 1.8;
backgroundScale = 1; backgroundScale = 1;
@ -154,6 +200,7 @@ import Layout from "../../layouts/Layout.astro";
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -201,24 +248,26 @@ import Layout from "../../layouts/Layout.astro";
borderBottom.lineTo(x + lineWidth, y); borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath(); borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", { // submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand', // font: '900 24px Quicksand',
fill: '#05b3a4', // fill: '#05b3a4',
backgroundColor : '#7c4c23', // backgroundColor : '#7c4c23',
padding: {x: 10, y: 10}, // padding: {x: 10, y: 10},
shadow: { // shadow: {
offsetX : 2, // offsetX : 2,
offsetY : 2, // offsetY : 2,
color: '#000', // color: '#000',
blur: 5, // blur: 5,
fill: true // fill: true
} // }
}); // });
submitButton.setVisible(false); // submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9); // this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
@ -249,6 +298,12 @@ import Layout from "../../layouts/Layout.astro";
// const baseFontSize = 16; // const baseFontSize = 16;
// const responsiveFontSize = (window.innerWidth / 550) * baseFontSize; // const responsiveFontSize = (window.innerWidth / 550) * baseFontSize;
retryButton.setInteractive().on('pointerdown', () => {
window.location.reload();
})
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32; let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Number: 0', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5); this.add.text(window.innerWidth / 2, 80, 'Number: 0', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
@ -307,6 +362,7 @@ import Layout from "../../layouts/Layout.astro";
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask);
// graphics.setMask(mask); // graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
@ -324,20 +380,22 @@ import Layout from "../../layouts/Layout.astro";
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand', document.getElementById('beforeStartBtn').addEventListener('click', function() {
fill: '#05b3a4', document.getElementById('blurDisplay').classList.add('hidden');
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
audioOneAudio.play(); audioOneAudio.play();
gamestart = new Date();
gameStartTime = gamestart.toLocaleString();
firstTextLayer.setVisible(true);
animatedLetter.setVisible(false);
firstScreen.setVisible(false);
graphics.setVisible(true);
demoButton.setVisible(true);
submitButton.setVisible(true);
})
// audioOneAudio.play();
// startButton.setInteractive().on('pointerdown', () => { // startButton.setInteractive().on('pointerdown', () => {
// audioOneAudio.play(); // audioOneAudio.play();
// // gmStartTime(); // // gmStartTime();
@ -355,9 +413,49 @@ import Layout from "../../layouts/Layout.astro";
} }
// function beforeStartGame(){
// audioOneAudio.play();
// document.getElementById('blurDisplay').classList.add('hidden');
// }
function update() { function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer"class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,24 +103,41 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "stat timr here"; let gameStartTime = "stat timr here";
let galleryIconWidth;
let noticeWidth;
let noticeHeight;
let muteIcon;
let retryButton;
let maxScore;
let cancelIcon;
let letterHeight;
let letterScale;
let animated1Height;
let animated1videoScale;
if(isMobile){ if(isMobile){
cloudeSize = 200;
cloudHeight = 340; submitWidth = 250;
canvasScale = 0.14 submitHeight = 110;
canvasHeight = 35; noticeWidth = 100;
letterHeight = 30; noticeHeight = 0;
letterScale = 1.1; downloadWidth = 67;
downloadHeight = 200;
learningWidth = 200;
learningHeight = 400;
letterHeight = 0;
letterScale = 1.8;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animated1videoScale = 1;
animated1videoScale = 0.6;
animated1Height = 32; animated1Height = 32;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -68,23 +148,33 @@ import Layout from "../../layouts/Layout.astro";
submitHeight = customHeight / 1.1; submitHeight = customHeight / 1.1;
noticeWidth = window.innerWidth * 0.5 - 100; noticeWidth = window.innerWidth * 0.5 - 100;
noticeHeight = window.innerHeight * 0.38; noticeHeight = window.innerHeight * 0.38;
} else{ }else if(isTab){
animated1videoScale = 1;
animated1Height = 32;
letterHeight = 0;
letterScale = 1.8;
}else{
submitWidth = 380;
submitHeight = 95;
noticeWidth = 0;
noticeHeight = 0;
downloadWidth = 180;
downloadHeight = 70;
learningWidth = 450;
learningHeight = 400;
cloudeSize = 500; cloudeSize = 500;
cloudHeight = 250; cloudHeight = 250;
canvasScale = 0.195; letterHeight = 0;
canvasHeight = 20; letterScale = 1.8;
letterHeight = 10;
letterScale = 1.2;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animated1videoScale = 0.70; animated1videoScale = 1;
animated1Height = 20; animated1Height = 20;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
startButtonHeight = customHeight / 2 - 20; startButtonHeight = customHeight / 2 - 20;
startButtonWidth = customWidth / 1.32; startButtonWidth = customWidth / 1.32;
submitWidth = customWidth / 1.32; submitWidth = customWidth / 1.32;
@ -92,12 +182,35 @@ import Layout from "../../layouts/Layout.astro";
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
// console.log("Page loaded on: " + formattedDateTime); // console.log("Page loaded on: " + formattedDateTime);
}; };
// let hideButton;
function preload() { function preload() {
this.load.video('animated1', '/assets/animated-letter/number_1.mp4'); this.load.video('animated1', '/assets/animated-letter/number_1.mp4');
@ -112,135 +225,71 @@ import Layout from "../../layouts/Layout.astro";
this.load.image('cloud', '/assets/cloud.png'); this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image('canvas', '/assets/canvas4.png');
this.load.image('sun', '/assets/sun.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Number : 1", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9); // this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'number1').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'number1').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'number1').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'number1').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animated1').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animated1').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale); // this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}
}); });
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write number : 1', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Number: 1', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write number : 1', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animated1Height, 'animated1').setDepth(2).setScale(animated1videoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animated1Height, 'animated1').setDepth(2).setScale(animated1videoScale);
// Play the video // Play the video
@ -256,11 +305,12 @@ import Layout from "../../layouts/Layout.astro";
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Down',{ font: '700 35px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -293,7 +343,7 @@ import Layout from "../../layouts/Layout.astro";
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -310,32 +360,44 @@ import Layout from "../../layouts/Layout.astro";
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", { // let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand', // font: '900 24px Quicksand',
fill: '#05b3a4', // fill: '#05b3a4',
backgroundColor : '#7c4c23', // backgroundColor : '#7c4c23',
padding: {x: 20, y: 10}, // padding: {x: 20, y: 10},
shadow: { // shadow: {
offsetX : 2, // offsetX : 2,
offsetY : 2, // offsetY : 2,
color: '#000', // color: '#000',
blur: 5, // blur: 5,
fill: true // fill: true
} // }
}) // })
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true); gamestart = new Date();
gameStartTime = gamestart.toLocaleString();
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true); demoButton.setVisible(true);
startButton.setVisible(false); submitButton.setVisible(true);
}) })
// startButton.setInteractive().on('pointerdown', () => {
// audioOneAudio.play();
// submitButton.setVisible(true);
// firstTextLayer.setVisible(true);
// animatedLetter.setVisible(false);
// firstScreen.setVisible(false);
// graphics.setVisible(true);
// hideButton.setVisible(false);
// demoButton.setVisible(true);
// startButton.setVisible(false);
// })
} }
@ -345,3 +407,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer"class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,24 +103,21 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer; let firstLayer, secondLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0; let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200;
cloudHeight = 340;
canvasScale = 0.14
canvasHeight = 35;
letterHeight = 58; letterHeight = 58;
letterScale = 1; letterScale = 1.5;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animated2Scale = 0.55; animated2Scale = 0.85;
animated2Height = 32; animated2Height = 32;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -69,18 +129,14 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 100; noticeWidth = window.innerWidth * 0.5 - 100;
noticeHeight = window.innerHeight * 0.38; noticeHeight = window.innerHeight * 0.38;
} else{ } else{
cloudeSize = 500;
cloudHeight = 250;
canvasScale = 0.195;
canvasHeight = 20;
letterHeight = 50; letterHeight = 50;
letterScale = 1; letterScale = 1.5;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animated2Scale = 0.55; animated2Scale = 0.85;
animated2Height = 20; animated2Height = 20;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -91,158 +147,114 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
// console.log("Page loaded on: " + formattedDateTime); // console.log("Page loaded on: " + formattedDateTime);
}; };
// let hideButton;
function preload() { function preload() {
this.load.video('animated2', '/assets/animated-letter/number_2.mp4'); this.load.video('animated2', '/assets/animated-letter/number_2.mp4');
this.load.svg('number2', '/assets/numeric/n2.svg'); this.load.svg('number2', '/assets/numeric/n2.svg');
this.load.svg('layer1', '/assets/numeric/n2.svg'); this.load.svg('layer1', '/assets/numeric/n2_l1.svg');
this.load.svg('layer2', '/assets/numeric/n2.svg'); this.load.svg('layer2', '/assets/numeric/n2_l2.svg');
this.load.audio('audioOne', '/assets/audio/roll-slant.mp3'); this.load.audio('audioOne', '/assets/audio/roll-slant.mp3');
this.load.audio('audioTwo', '/assets/audio/slide.mp3'); this.load.audio('audioTwo', '/assets/audio/slide.mp3');
this.load.image('topLogo', '/assets/top_logo.svg'); this.load.image('topLogo', '/assets/top_logo.svg');
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image('sun', '/assets/sun.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
submitButton = this.add.text(submitWidth, submitHeight, "Submit", { const borderBottom = this.add.graphics();
font: '900 24px Quicksand', const x = 0; const y = 54;
fill: '#05b3a4', const lineWidth = window.innerWidth;
backgroundColor : '#7c4c23', borderBottom.lineStyle(1, 0x0348A8);
padding: {x: 10, y: 10}, borderBottom.setAlpha(0.2);
shadow: { borderBottom.beginPath();
offsetX : 2, borderBottom.moveTo(x, y);
offsetY : 2, borderBottom.lineTo(x + lineWidth, y);
color: '#000', borderBottom.strokePath();
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Number : 2", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9); // this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'number2').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'number2').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number2').setDepth(2).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number2').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number2').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animated2').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animated2').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
firstScreen.setVisible(true);
}
}); });
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write number : 2', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Number: 1', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write number : 2', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
const animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animated2Height, 'animated2').setDepth(2).setScale(animated2Scale); const animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animated2Height, 'animated2').setDepth(2).setScale(animated2Scale);
// Play the video // Play the video
@ -260,9 +272,8 @@ submitUserData(this);
let textX, textY; let textX, textY;
firstLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; let stepTextSize = isMobile ? 12 : 16;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Roll Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const firstTextLayer = this.add.text(textX, textY, '1. Roll Slant',{ font: '700 40px quicksand', fill: '#05b3a4'});
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -271,7 +282,8 @@ submitUserData(this);
secondLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slide',{ font: '700 40px quicksand', fill: '#05b3a4'});
const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -284,7 +296,6 @@ submitUserData(this);
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
@ -307,7 +318,6 @@ submitUserData(this);
firstLayer.setAlpha(0.5); firstLayer.setAlpha(0.5);
} }
}); });
``
// Repeat the above code for secondLayer and thirdLayer // Repeat the above code for secondLayer and thirdLayer
// Add this code for secondLayer // Add this code for secondLayer
@ -329,7 +339,7 @@ submitUserData(this);
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -346,36 +356,60 @@ submitUserData(this);
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true); gamestart = new Date();
gameStartTime = gamestart.toLocaleString();
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
function update() { function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer"class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,24 +103,25 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer; let firstLayer, secondLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
cloudHeight = 340; cloudHeight = 340;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 35; canvasHeight = 35;
letterHeight = 48; letterHeight = 48;
letterScale = 1; letterScale = 1.5;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animated3Scale = 0.55; animated3Scale = 0.92;
animated3Height = 32; animated3Height = 32;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -74,14 +138,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterHeight = 30; letterHeight = 30;
letterScale = 1; letterScale = 1.5;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animated3Scale = 0.55; animated3Scale = 0.92;
animated3Height = 20; animated3Height = 20;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -92,12 +156,33 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
// console.log("Page loaded on: " + formattedDateTime); // console.log("Page loaded on: " + formattedDateTime);
}; };
// let hideButton;
function preload() { function preload() {
this.load.video('animated3', '/assets/animated-letter/number_3.mp4'); this.load.video('animated3', '/assets/animated-letter/number_3.mp4');
@ -109,140 +194,76 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image('sun', '/assets/sun.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
submitButton = this.add.text(submitWidth, submitHeight, "Submit", { const borderBottom = this.add.graphics();
font: '900 24px Quicksand', const x = 0; const y = 54;
fill: '#05b3a4', const lineWidth = window.innerWidth;
backgroundColor : '#7c4c23', borderBottom.lineStyle(1, 0x0348A8);
padding: {x: 10, y: 10}, borderBottom.setAlpha(0.2);
shadow: { borderBottom.beginPath();
offsetX : 2, borderBottom.moveTo(x, y);
offsetY : 2, borderBottom.lineTo(x + lineWidth, y);
color: '#000', borderBottom.strokePath();
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Number : 3", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9); // this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'number3').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'number3').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number3').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number3').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animated3').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animated3').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
firstScreen.setVisible(true);
}
}); });
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write number : 3', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Number: 3', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write number : 3', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animated3Height, 'animated3').setDepth(2).setScale(animated3Scale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animated3Height, 'animated3').setDepth(2).setScale(animated3Scale);
// Play the video // Play the video
@ -258,11 +279,11 @@ submitUserData(this);
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Roll Around',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Roll Around',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -271,7 +292,7 @@ submitUserData(this);
secondLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Roll Around',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Roll Around',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioOne'); const audioTwoAudio = this.sound.add('audioOne');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -307,7 +328,6 @@ submitUserData(this);
firstLayer.setAlpha(0.5); firstLayer.setAlpha(0.5);
} }
}); });
``
// Repeat the above code for secondLayer and thirdLayer // Repeat the above code for secondLayer and thirdLayer
// Add this code for secondLayer // Add this code for secondLayer
@ -329,7 +349,7 @@ submitUserData(this);
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -346,31 +366,14 @@ submitUserData(this);
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -379,3 +382,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer"class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
// let x = 100; // let x = 100;
// // Use x // // Use x
@ -97,6 +162,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -114,138 +201,74 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false); submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Number : 4", { font: '700 40px quicksand', fill: '#05b3a4', });
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number4').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number4').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number4').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number4').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animated4').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animated4').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
firstScreen.setVisible(true);
}
}); });
retryButton.setInteractive().on('pointerdown', () => {
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; window.location.reload();
const baseFontSize = 24; })
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; const maskGraphics = this.make.graphics();
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write number : 4', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Number: 4', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write number : 4', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animated4Height, 'animated4').setDepth(2).setScale(animated4Scale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animated4Height, 'animated4').setDepth(2).setScale(animated4Scale);
// Play the video // Play the video
@ -260,11 +283,12 @@ submitUserData(this);
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Down',{ font: '700 40px quicksand', fill: '#05b3a4'});
const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -273,7 +297,7 @@ submitUserData(this);
secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slide',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -282,8 +306,9 @@ submitUserData(this);
secondLayer.setVisible(false); secondLayer.setVisible(false);
thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale); thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const thirdTextLayer = this.add.text(textX, textY, '3. Down', { font: '700 40px quicksand', fill: '#05b3a4'}); const thirdTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '3. Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioThreeAudio = this.sound.add('audioOne'); const audioThreeAudio = this.sound.add('audioOne');
thirdTextLayer.setVisible(false); thirdTextLayer.setVisible(false);
thirdLayer.setDepth(1.1); thirdLayer.setDepth(1.1);
@ -360,7 +385,7 @@ submitUserData(this);
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -378,31 +403,15 @@ submitUserData(this);
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => {
document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -410,3 +419,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,10 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
// let x = 100; let demoButton;
// // Use x // // Use x
// console.log(x); // console.log(x);
@ -54,7 +118,7 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 35; canvasHeight = 35;
letterHeight = 50; letterHeight = 50;
letterScale = 1; letterScale = 1.2;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
@ -62,7 +126,7 @@ let scoreTotal = 0; let isDrawing = false;
sunHeight = 70; sunHeight = 70;
animated5Height = 35; animated5Height = 35;
animated5Scale = 0.55; animated5Scale = 0.7;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -78,7 +142,7 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterHeight = 40; letterHeight = 40;
letterScale = 1; letterScale = 1.2;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
@ -86,7 +150,7 @@ let scoreTotal = 0; let isDrawing = false;
sunHeight = 100; sunHeight = 100;
animated5Height = 20; animated5Height = 20;
animated5Scale = 0.6; animated5Scale = 0.7;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -97,6 +161,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -115,138 +201,72 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked'); // windowLoad();
submitButton.setVisible(false); submitUserData(this);
// windowLoad(); showAnimation();
submitUserData(this); parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Number : 5", { font: '700 40px quicksand', fill: '#05b3a4', });
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number5').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number5').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number5').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number5').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animated5').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animated5').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale); // this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write number : 5', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Number: 5', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write number : 5', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animated5Height, 'animated5').setDepth(2).setScale(animated5Scale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animated5Height, 'animated5').setDepth(2).setScale(animated5Scale);
// Play the video // Play the video
@ -261,11 +281,11 @@ submitUserData(this);
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -274,7 +294,7 @@ submitUserData(this);
secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Roll Around',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Roll Around',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -284,7 +304,7 @@ submitUserData(this);
thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale); thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const thirdTextLayer = this.add.text(textX, textY, '3. Slide', { font: '700 40px quicksand', fill: '#05b3a4'}); const thirdTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '3. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioThreeAudio = this.sound.add('audioThree'); const audioThreeAudio = this.sound.add('audioThree');
thirdTextLayer.setVisible(false); thirdTextLayer.setVisible(false);
thirdLayer.setDepth(1.1); thirdLayer.setDepth(1.1);
@ -361,7 +381,7 @@ submitUserData(this);
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -379,35 +399,56 @@ submitUserData(this);
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => {
document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
function update() { function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer; let firstLayer, secondLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -50,14 +115,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 30; canvasHeight = 30;
letterHeight = 30; letterHeight = 30;
letterScale = 1; letterScale = 1.2;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animated6Scale = 0.55; animated6Scale = 0.7;
animated6Height = 32; animated6Height = 32;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -74,14 +139,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterHeight = 10; letterHeight = 10;
letterScale = 1; letterScale = 1.2;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animated6Scale = 0.55; animated6Scale = 0.7;
animated6Height = 20; animated6Height = 20;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -93,12 +158,33 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
// console.log("Page loaded on: " + formattedDateTime); // console.log("Page loaded on: " + formattedDateTime);
}; };
// let hideButton;
function preload() { function preload() {
this.load.video('animated6', '/assets/animated-letter/number_6.mp4'); this.load.video('animated6', '/assets/animated-letter/number_6.mp4');
@ -111,159 +197,92 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image('sun', '/assets/sun.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Number : 6", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'number6').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'number6').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number6').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number6').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animated6').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animated6').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write number : 6', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Number: 6', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write number : 6', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animated6Height, 'animated6').setDepth(2).setScale(animated6Scale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animated6Height, 'animated6').setDepth(2).setScale(animated6Scale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
// You can set additional properties for the video, such as loop and mute:
animatedLetter.setLoop(true); // Loop the video animatedLetter.setLoop(true); // Loop the video
animatedLetter.setMute(false); // Unmute the video animatedLetter.setMute(false); // Unmute the video
animatedLetter.on('complete', function () { animatedLetter.on('complete', function () {
// Video playback is complete
// You can add your code here for what to do when the video finishes. // You can add your code here for what to do when the video finishes.
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Curve Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Curve Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -272,7 +291,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Loop',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Loop',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -285,7 +304,6 @@ let scoreTotal = 0; let isDrawing = false;
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
@ -308,7 +326,6 @@ let scoreTotal = 0; let isDrawing = false;
firstLayer.setAlpha(0.5); firstLayer.setAlpha(0.5);
} }
}); });
``
// Repeat the above code for secondLayer and thirdLayer // Repeat the above code for secondLayer and thirdLayer
// Add this code for secondLayer // Add this code for secondLayer
@ -330,7 +347,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -347,30 +364,16 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => {
audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
firstTextLayer.setVisible(false);
document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play();
firstTextLayer.setVisible(true);
animatedLetter.setVisible(false);
firstScreen.setVisible(false);
graphics.setVisible(true);
}) })
} }
@ -379,3 +382,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer; let firstLayer, secondLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -50,14 +115,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 30; canvasHeight = 30;
letterHeight = 30; letterHeight = 30;
letterScale = 1; letterScale = 1.5;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animated7Scale = 0.55; animated7Scale = 0.75;
animated7Height = 32; animated7Height = 32;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -74,14 +139,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterHeight = 10; letterHeight = 10;
letterScale = 1.1; letterScale = 1.5;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animated7Scale = 0.55; animated7Scale = 0.75;
animated7Height = 20; animated7Height = 20;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -93,6 +158,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -111,138 +198,76 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image('sun', '/assets/sun.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false); submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Number : 7", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'number7').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'number7').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number7').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number7').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animated7').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animated7').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale); // this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; }
const baseFontSize = 24; })
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize;
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write number : 7', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
retryButton.setInteractive().on('pointerdown', () => {
window.location.reload();
})
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Number: 7', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write number : 7', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animated7Height, 'animated7').setDepth(2).setScale(animated7Scale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animated7Height, 'animated7').setDepth(2).setScale(animated7Scale);
// Play the video // Play the video
@ -258,11 +283,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Slide',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -271,7 +296,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slant',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -284,8 +309,6 @@ let scoreTotal = 0; let isDrawing = false;
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -327,7 +350,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -344,31 +367,15 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -377,3 +384,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer; let firstLayer, secondLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -50,14 +115,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.14; canvasScale = 0.14;
canvasHeight = 30; canvasHeight = 30;
letterHeight = 30; letterHeight = 30;
letterScale = 1; letterScale = 1.2;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animated8Scale = 0.55; animated8Scale = 0.7;
animated8Height = 15; animated8Height = 15;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -74,14 +139,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterHeight = 10; letterHeight = 10;
letterScale = 1; letterScale = 1.2;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animated8Scale = 0.55; animated8Scale = 0.7;
animated8Height = 0; animated8Height = 0;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -93,6 +158,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -111,138 +198,74 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Number : 8", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'number8').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'number8').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number8').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number8').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animated8').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animated8').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale); // this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write number : 8', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Number: 8', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write number : 8', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animated8Height, 'animated8').setDepth(2).setScale(animated8Scale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animated8Height, 'animated8').setDepth(2).setScale(animated8Scale);
// Play the video // Play the video
@ -258,11 +281,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Hook Snake',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Hook Snake',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -271,7 +294,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Roll Up',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Roll Up',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -328,7 +351,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -345,31 +368,15 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -378,3 +385,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer; let firstLayer, secondLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -50,14 +115,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 30; canvasHeight = 30;
letterHeight = 30; letterHeight = 30;
letterScale = 1; letterScale = 1.3;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animated9Scale = 0.55; animated9Scale = 0.75;
animated9Height = 40; animated9Height = 40;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -74,14 +139,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterHeight = 10; letterHeight = 10;
letterScale = 1; letterScale = 1.3;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animated9Scale = 0.55; animated9Scale = 0.75;
animated9Height = 20; animated9Height = 20;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -93,6 +158,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -111,139 +198,74 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image('sun', '/assets/sun.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false); submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Number : 9", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'number9').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'number9').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number9').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'number9').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animated9').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animated9').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
graphics.setVisible(false);
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write number : 9', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Number: 9', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write number : 9', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animated9Height, 'animated9').setDepth(2).setScale(animated9Scale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animated9Height, 'animated9').setDepth(2).setScale(animated9Scale);
// Play the video // Play the video
@ -259,11 +281,12 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 8 : customWidth * 0.75; textX = isMobile ? customWidth / 8 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Curve Around',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Curve Around',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -272,7 +295,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -308,7 +331,6 @@ let scoreTotal = 0; let isDrawing = false;
firstLayer.setAlpha(0.5); firstLayer.setAlpha(0.5);
} }
}); });
``
// Repeat the above code for secondLayer and thirdLayer // Repeat the above code for secondLayer and thirdLayer
// Add this code for secondLayer // Add this code for secondLayer
@ -330,7 +352,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -347,31 +369,15 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -380,3 +386,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,92 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div> <div>
<div id="wsSavedImg" class="clip-art-container -z-10 absolute bottom-0 right-0">
<img src="/assets/svg/tracing-done.svg" alt="Clip Art" class="clip-art">
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveTracingGameData.js" is:inline></script>
<script is:inline> <script is:inline>
const jsonData = [
{
"src": "/assets/back.jpeg",
"title": "Image Title 1",
"description": "Description for image 1 goes here."
},
{
"src": "/assets/background.jpg",
"title": "Image Title 2",
"description": "Description for image 2 goes here."
},
{
"src": "/assets/backgroundImage.png",
"title": "Image Title 3",
"description": "Description for image 3 goes here."
},
{
"src": "/assets/beanieImage.png",
"title": "Image Title 4",
"description": "Description for image 4 goes here."
}
];
let currentSlide = 0;
function updateSlide(){
const slide = jsonData[currentSlide];
document.getElementById('slideImage').src = slide.src;
document.getElementById('imageTitle').textContent = slide.title;
document.getElementById('imageDescription').textContent = slide.description;
}
document.getElementById('nextButton').addEventListener('click', () => {
currentSlide = (currentSlide + 1) % jsonData.length;
console.log(currentSlide)
updateSlide();
})
document.getElementById('prevButton').addEventListener('click', () => {
currentSlide = (currentSlide - 1 + jsonData.length) % jsonData.length;
updateSlide();
})
updateSlide();
let parentMainContainer = document.getElementById('parentMainContainer');
let gallerySliderId = document.getElementById('gallerySliderId');
function closeGallery(){
gallerySliderId.classList.add('hidden');
}
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +100,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,14 +118,13 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
// let x = 100; let maxScore;
let galleryButton;
// // Use x
// console.log(x);
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -55,14 +132,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 35; canvasHeight = 35;
letterHeight = 70; letterHeight = 70;
letterScale = 1; letterScale = 1.2;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animatedAHeight = 35; animatedAHeight = 35;
animatedAScale = 0.65; animatedAScale = 0.8;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -78,14 +155,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterHeight = 50; letterHeight = 50;
letterScale = 1; letterScale = 1.2;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animatedAHeight = 20; animatedAHeight = 0;
animatedAScale = 0.73; animatedAScale = 0.8;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -96,6 +173,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -114,128 +213,77 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.svg('galleryIcons', '/assets/svg/gallery-icon.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
galleryButton = this.add.image(customWidth / galleryIconWidth, 30, "galleryIcons");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
}) showAnimation();
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo'); // parentMainContainer.classList.remove('hidden');
this.add.text(customWidth / 10, 20, "Letter : A", { font: '700 40px quicksand', fill: '#05b3a4', }); });
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9); galleryButton.setInteractive().on('pointerdown', () => {
cloud.setDepth(-1.8); // parentMainContainer.classList.remove('hidden');
const scrollSpeed = 0.5; gallerySliderId.classList.remove('hidden');
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
}); });
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterA').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterA').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterA').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterA').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedA').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedA').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : A', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: A', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : A', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedAHeight, 'animatedA').setDepth(2).setScale(animatedAScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedAHeight, 'animatedA').setDepth(2).setScale(animatedAScale);
// Play the video // Play the video
@ -250,11 +298,14 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
let finalMessage = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, 'Great job! You traced the letter perfectly!',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
finalMessage.setVisible(false);
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Slant Left',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Slant Left',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -263,7 +314,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slant Right',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slant Right',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -273,10 +324,12 @@ let scoreTotal = 0; let isDrawing = false;
thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale); thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const thirdTextLayer = this.add.text(textX, textY, '3. Slide', { font: '700 40px quicksand', fill: '#05b3a4'}); const thirdTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '3. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioThreeAudio = this.sound.add('audioThree'); const audioThreeAudio = this.sound.add('audioThree');
thirdTextLayer.setVisible(false); thirdTextLayer.setVisible(false);
thirdLayer.setDepth(1.1); thirdLayer.setDepth(1.1);
// thirdLayer.setScale(1.15); // thirdLayer.setScale(1.15);
thirdLayer.setAlpha(0.5); thirdLayer.setAlpha(0.5);
thirdLayer.setInteractive({ draggable: true }); thirdLayer.setInteractive({ draggable: true });
@ -287,8 +340,6 @@ let scoreTotal = 0; let isDrawing = false;
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
let thirdDragStartPoint = { x: 0, y: 0 }; let thirdDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -343,6 +394,7 @@ let scoreTotal = 0; let isDrawing = false;
if (distance >= 100) { if (distance >= 100) {
thirdLayer.setAlpha(1); thirdLayer.setAlpha(1);
thirdTextLayer.setVisible(false); thirdTextLayer.setVisible(false);
finalMessage.setVisible(true)
} else { } else {
thirdLayer.setAlpha(0.5); thirdLayer.setAlpha(0.5);
} }
@ -369,31 +421,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -401,3 +436,37 @@ function update() {
} }
</script> </script>
<style href="https://fonts.googleapis.com/css?family=Quicksand&display=swap" rel="stylesheet">
* {
margin: 0;
padding: 0;
cursor: -webkit-grab; cursor: grab;
font-family: quicksand;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -50,14 +115,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 35; canvasHeight = 35;
letterHeight = 58; letterHeight = 58;
letterScale = 0.85; letterScale = 1.2;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animatedVideoScale = 0.6; animatedVideoScale = 0.8;
animatedBHeight = 32; animatedBHeight = 22;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -73,14 +138,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterHeight = 50; letterHeight = 50;
letterScale = 1; letterScale = 1.2;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animatedVideoScale = 0.70; animatedVideoScale = 0.8;
animatedBHeight = 20; animatedBHeight = 10;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -91,6 +156,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -110,139 +197,73 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : B", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterB').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterB').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterB').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterB').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedB').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedB').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : B', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: B', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : B', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedBHeight, 'animatedB').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedBHeight, 'animatedB').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -256,11 +277,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -269,7 +290,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slide Around',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slide Around',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -279,7 +300,7 @@ let scoreTotal = 0; let isDrawing = false;
thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale); thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const thirdTextLayer = this.add.text(textX, textY, '3. Slide Around', { font: '700 40px quicksand', fill: '#05b3a4'}); const thirdTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '3. Slide Around',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTHreeAudio = this.sound.add('audioTwo'); const audioTHreeAudio = this.sound.add('audioTwo');
thirdTextLayer.setVisible(false); thirdTextLayer.setVisible(false);
thirdLayer.setDepth(1.1); thirdLayer.setDepth(1.1);
@ -293,8 +314,6 @@ let scoreTotal = 0; let isDrawing = false;
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
let thirdDragStartPoint = { x: 0, y: 0 }; let thirdDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -360,7 +379,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -378,31 +397,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -411,3 +413,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer; let firstLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -57,7 +122,7 @@ let scoreTotal = 0; let isDrawing = false;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animatedVideoScale = 0.59; animatedVideoScale = 0.59;
animatedAHeight = 32; animatedCHeight = 32;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
startButtonHeight = customHeight / 1.1; startButtonHeight = customHeight / 1.1;
@ -79,7 +144,7 @@ let scoreTotal = 0; let isDrawing = false;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animatedVideoScale = 0.70; animatedVideoScale = 0.70;
animatedAHeight = 20; animatedCHeight = 20;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -90,6 +155,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -98,7 +185,7 @@ let scoreTotal = 0; let isDrawing = false;
// let hideButton; // let hideButton;
function preload() { function preload() {
this.load.video('animatedA', '/assets/animated-letter/capital_c.mp4'); this.load.video('animatedC', '/assets/animated-letter/capital_c.mp4');
this.load.svg('letterC', '/assets/capital-letter/c.svg'); this.load.svg('letterC', '/assets/capital-letter/c.svg');
this.load.svg('layer1', '/assets/capital-letter/c.svg'); this.load.svg('layer1', '/assets/capital-letter/c.svg');
this.load.audio('audioOne', '/assets/audio/hook-around.mp3'); this.load.audio('audioOne', '/assets/audio/hook-around.mp3');
@ -106,139 +193,72 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('beanie', '/assets/beanieImage.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
this.load.image('canvasStand', '/assets/stand2.png');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false); submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : C", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterC').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterC').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 90, customHeight / 2 + letterHeight, 'letterC').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 90, customHeight / 2 + letterHeight, 'letterC').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedA').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedC').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : C', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedAHeight, 'animatedA').setDepth(2).setScale(animatedVideoScale); maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: C', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : C', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedCHeight, 'animatedC').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -252,11 +272,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Hook Around',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Hook Around',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -289,7 +309,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -307,33 +327,16 @@ let scoreTotal = 0; let isDrawing = false;
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
function update() { function update() {
@ -341,3 +344,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -50,14 +115,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 35; canvasHeight = 35;
letterHeight = 58; letterHeight = 58;
letterScale = 0.85; letterScale = 1.2;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animatedVideoScale = 0.6; animatedVideoScale = 0.8;
animatedDHeight = 32; animatedDHeight = 22;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -73,14 +138,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterHeight = 50; letterHeight = 50;
letterScale = 1; letterScale = 1.2;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animatedVideoScale = 0.70; animatedVideoScale = 0.8;
animatedDHeight = 20; animatedDHeight = 10;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -91,6 +156,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -109,140 +196,74 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
submitNotic.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : D", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 + 15, customHeight / 2 + letterHeight, 'letterD').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 + 15, customHeight / 2 + letterHeight, 'letterD').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 15, customHeight / 2 + letterHeight, 'letterD').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 15, customHeight / 2 + letterHeight, 'letterD').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedD').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedD').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : D', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: D', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : D', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedDHeight, 'animatedD').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedDHeight, 'animatedD').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -256,11 +277,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 + 15, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 + 15, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -269,7 +290,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 + 15, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 + 15, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slide Around',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slide Around',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -282,8 +303,6 @@ let scoreTotal = 0; let isDrawing = false;
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -324,7 +343,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -341,30 +360,15 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => {
audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
firstTextLayer.setVisible(false);
document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play();
firstTextLayer.setVisible(true);
animatedLetter.setVisible(false);
firstScreen.setVisible(false);
graphics.setVisible(true);
}) })
} }
@ -373,3 +377,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer, fourthLayer; let firstLayer, secondLayer, thirdLayer, fourthLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -89,6 +154,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -108,137 +195,70 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : E", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'letterE').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'letterE').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'letterE').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'letterE').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedE').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedE').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : E', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: E', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : E', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedEHeight, 'animatedE').setDepth(2).setScale(0.73); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedEHeight, 'animatedE').setDepth(2).setScale(0.73);
// Play the video // Play the video
@ -254,11 +274,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -267,7 +287,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slide',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -277,7 +297,7 @@ let scoreTotal = 0; let isDrawing = false;
thirdLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale); thirdLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const thirdTextLayer = this.add.text(textX, textY, '3. Slide', { font: '700 40px quicksand', fill: '#05b3a4'}); const thirdTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '3. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioThreeAudio = this.sound.add('audioTwo'); const audioThreeAudio = this.sound.add('audioTwo');
thirdTextLayer.setVisible(false); thirdTextLayer.setVisible(false);
thirdLayer.setDepth(1.1); thirdLayer.setDepth(1.1);
@ -288,7 +308,7 @@ let scoreTotal = 0; let isDrawing = false;
fourthLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer4').setScale(letterScale); fourthLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer4').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const fourthTextLayer = this.add.text(textX, textY, '4. Slide', { font: '700 40px quicksand', fill: '#05b3a4'}); const fourthTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '4. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioFourthAudio = this.sound.add('audioTwo'); const audioFourthAudio = this.sound.add('audioTwo');
fourthTextLayer.setVisible(false); fourthTextLayer.setVisible(false);
fourthLayer.setDepth(1.1); fourthLayer.setDepth(1.1);
@ -389,7 +409,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -407,31 +427,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -440,3 +443,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,28 +103,26 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
// let x = 100; let demoButton;
// // Use x
// console.log(x);
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
cloudHeight = 340; cloudHeight = 340;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 35; canvasHeight = 35;
letterHeight = 70; letterHeight = 35;
letterScale = 1; letterScale = 1.08;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animatedFHeight = 35; animatedFHeight = 0;
animatedFScale = 0.65; animatedFScale = 0.8;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -77,14 +138,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterHeight = 50; letterHeight = 50;
letterScale = 1; letterScale = 1.1;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animatedFHeight = 20; animatedFHeight = 10;
animatedFScale = 0.73; animatedFScale = 0.8;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -95,6 +156,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -112,134 +195,69 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
submitButton = this.add.text(submitWidth, submitHeight, "Submit", { const borderBottom = this.add.graphics();
font: '900 24px Quicksand', const x = 0; const y = 54;
fill: '#05b3a4', const lineWidth = window.innerWidth;
backgroundColor : '#7c4c23', borderBottom.lineStyle(1, 0x0348A8);
padding: {x: 10, y: 10}, borderBottom.setAlpha(0.2);
shadow: { borderBottom.beginPath();
offsetX : 2, borderBottom.moveTo(x, y);
offsetY : 2, borderBottom.lineTo(x + lineWidth, y);
color: '#000', borderBottom.strokePath();
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : F", { font: '700 40px quicksand', fill: '#05b3a4', });
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterA').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterA').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterA').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterA').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedF').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedF').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : F', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: F', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : F', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedFHeight, 'animatedF').setDepth(2).setScale(animatedFScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedFHeight, 'animatedF').setDepth(2).setScale(animatedFScale);
// Play the video // Play the video
@ -254,11 +272,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -267,7 +285,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slide',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -277,7 +295,7 @@ let scoreTotal = 0; let isDrawing = false;
thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale); thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const thirdTextLayer = this.add.text(textX, textY, '3. Slide', { font: '700 40px quicksand', fill: '#05b3a4'}); const thirdTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '3. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioThreeAudio = this.sound.add('audioTwo'); const audioThreeAudio = this.sound.add('audioTwo');
thirdTextLayer.setVisible(false); thirdTextLayer.setVisible(false);
thirdLayer.setDepth(1.1); thirdLayer.setDepth(1.1);
@ -351,7 +369,7 @@ let scoreTotal = 0; let isDrawing = false;
}); });
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -369,31 +387,15 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -401,3 +403,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,24 +103,26 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
cloudHeight = 340; cloudHeight = 340;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 35; canvasHeight = 35;
letterHeight = 58; letterHeight = 30;
letterScale = 0.85; letterScale = 1;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animatedVideoScale = 0.60; animatedVideoScale = 0.7;
animatedGHeight = 32; animatedGHeight = 0;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -91,7 +156,33 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
// let hideButton; if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() {
currentDate = new Date();
formattedDateTime = currentDate.toLocaleString();
// console.log("Page loaded on: " + formattedDateTime);
};
function preload() { function preload() {
this.load.video('animatedG', '/assets/animated-letter/capital_g.mp4'); this.load.video('animatedG', '/assets/animated-letter/capital_g.mp4');
@ -104,138 +195,71 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : G", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterG').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterG').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterG').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterG').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedG').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedG').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; })
const baseFontSize = 24; retryButton.setInteractive().on('pointerdown', () => {
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; window.location.reload();
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : G', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); })
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: G', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : G', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedGHeight, 'animatedG').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedGHeight, 'animatedG').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -249,11 +273,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Hook Around',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Hook Around',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
audioOneAudio.play(); audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -262,7 +286,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slide',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -316,7 +340,7 @@ let scoreTotal = 0; let isDrawing = false;
}); });
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -333,31 +357,15 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -366,3 +374,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,13 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
// let x = 100; let demoButton;
// // Use x
// console.log(x);
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -54,14 +115,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 35; canvasHeight = 35;
letterHeight = 70; letterHeight = 70;
letterScale = 0.9; letterScale = 1.2;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animatedHHeight = 45; animatedHHeight = 30;
animatedHScale = 0.6; animatedHScale = 0.78;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -77,14 +138,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterHeight = 50; letterHeight = 50;
letterScale = 1; letterScale = 1.2;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animatedHHeight = 20; animatedHHeight = 10;
animatedHScale = 0.70; animatedHScale = 0.78;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -95,6 +156,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -112,137 +195,71 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : H", { font: '700 40px quicksand', fill: '#05b3a4', });
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'letterH').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'letterH').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'letterH').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'letterH').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedH').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedH').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : H', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: H', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : H', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedHHeight, 'animatedH').setDepth(2).setScale(animatedHScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedHHeight, 'animatedH').setDepth(2).setScale(animatedHScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -255,11 +272,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -268,7 +285,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioOne'); const audioTwoAudio = this.sound.add('audioOne');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -278,7 +295,7 @@ let scoreTotal = 0; let isDrawing = false;
thirdLayer = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale); thirdLayer = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const thirdTextLayer = this.add.text(textX, textY, '3. Slide', { font: '700 40px quicksand', fill: '#05b3a4'}); const thirdTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '3. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioThreeAudio = this.sound.add('audioTwo'); const audioThreeAudio = this.sound.add('audioTwo');
thirdTextLayer.setVisible(false); thirdTextLayer.setVisible(false);
thirdLayer.setDepth(1.1); thirdLayer.setDepth(1.1);
@ -355,7 +372,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -373,35 +390,55 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); firstScreen.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
function update() { function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,10 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
// let x = 100; let demoButton;
// // Use x // // Use x
// console.log(x); // console.log(x);
@ -95,6 +159,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -112,135 +198,68 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : I", { font: '700 40px quicksand', fill: '#05b3a4', });
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 + 40, customHeight / 2 + letterHeight, 'letterI').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 + 40, customHeight / 2 + letterHeight, 'letterI').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 40, customHeight / 2 + letterHeight, 'letterI').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 40, customHeight / 2 + letterHeight, 'letterI').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedI').setDepth(2); canvasStand
firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : I', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: I', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : I', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedIHeight, 'animatedI').setDepth(2).setScale(animatedIScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedIHeight, 'animatedI').setDepth(2).setScale(animatedIScale);
// Play the video // Play the video
@ -255,11 +274,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 + 40, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 + 40, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -268,7 +287,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 + 40, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 + 40, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slide',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -278,7 +297,7 @@ let scoreTotal = 0; let isDrawing = false;
thirdLayer = this.add.image(customWidth / 2 + 40, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale); thirdLayer = this.add.image(customWidth / 2 + 40, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const thirdTextLayer = this.add.text(textX, textY, '3. Slide', { font: '700 40px quicksand', fill: '#05b3a4'}); const thirdTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '3. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioThreeAudio = this.sound.add('audioTwo'); const audioThreeAudio = this.sound.add('audioTwo');
thirdTextLayer.setVisible(false); thirdTextLayer.setVisible(false);
thirdLayer.setDepth(1.1); thirdLayer.setDepth(1.1);
@ -355,7 +374,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -372,31 +391,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -404,3 +406,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -91,6 +156,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -107,137 +194,70 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
submitButton = this.add.text(submitWidth, submitHeight, "Submit", { const borderBottom = this.add.graphics();
font: '900 24px Quicksand', const x = 0; const y = 54;
fill: '#05b3a4', const lineWidth = window.innerWidth;
backgroundColor : '#7c4c23', borderBottom.lineStyle(1, 0x0348A8);
padding: {x: 10, y: 10}, borderBottom.setAlpha(0.2);
shadow: { borderBottom.beginPath();
offsetX : 2, borderBottom.moveTo(x, y);
offsetY : 2, borderBottom.lineTo(x + lineWidth, y);
color: '#000', borderBottom.strokePath();
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : J", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterJ').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterJ').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 90, customHeight / 2 + letterHeight, 'letterJ').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 90, customHeight / 2 + letterHeight, 'letterJ').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedJ').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedJ').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : J', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: J', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : J', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedJHeight, 'animatedJ').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedJHeight, 'animatedJ').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -251,11 +271,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Hook',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Hook',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -283,7 +303,7 @@ let scoreTotal = 0; let isDrawing = false;
}); });
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -300,33 +320,15 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
function update() { function update() {
@ -334,3 +336,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
// let x = 100; // let x = 100;
// // Use x // // Use x
@ -95,6 +160,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -112,137 +199,71 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : K", { font: '700 40px quicksand', fill: '#05b3a4', });
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 + 50, customHeight / 2 + letterHeight, 'letterK').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 + 50, customHeight / 2 + letterHeight, 'letterK').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterK').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterK').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedK').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedK').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : K', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: K', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : K', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedKHeight, 'animatedK').setDepth(2).setScale(animatedKScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedKHeight, 'animatedK').setDepth(2).setScale(animatedKScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -255,11 +276,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 + 50, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 + 50, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -268,7 +289,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 + 50, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 + 50, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slant',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -278,7 +299,7 @@ let scoreTotal = 0; let isDrawing = false;
thirdLayer = this.add.image(customWidth / 2 + 50, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale); thirdLayer = this.add.image(customWidth / 2 + 50, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const thirdTextLayer = this.add.text(textX, textY, '3. Slant', { font: '700 40px quicksand', fill: '#05b3a4'}); const thirdTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '3. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioThreeAudio = this.sound.add('audioTwo'); const audioThreeAudio = this.sound.add('audioTwo');
thirdTextLayer.setVisible(false); thirdTextLayer.setVisible(false);
thirdLayer.setDepth(1.1); thirdLayer.setDepth(1.1);
@ -354,7 +375,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -371,31 +392,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -403,3 +407,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -90,6 +155,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -114,132 +201,70 @@ let scoreTotal = 0; let isDrawing = false;
this.load.image('sun', '/assets/sun.png'); this.load.image('sun', '/assets/sun.png');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image('bgMobile', '/assets/bgMobile.png');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image('canvasStand', '/assets/stand2.png');
this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : L", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 + 30, customHeight / 2 + letterHeight, 'letterL').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 + 30, customHeight / 2 + letterHeight, 'letterL').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 30, customHeight / 2 + letterHeight, 'letterL').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 30, customHeight / 2 + letterHeight, 'letterL').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedL').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedL').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : L', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: L', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : L', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedLHeight, 'animatedL').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedLHeight, 'animatedL').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -253,11 +278,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 + 30, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 + 30, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -266,7 +291,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 + 30, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 + 30, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slide',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -279,7 +304,6 @@ let scoreTotal = 0; let isDrawing = false;
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
@ -302,7 +326,6 @@ let scoreTotal = 0; let isDrawing = false;
firstLayer.setAlpha(0.5); firstLayer.setAlpha(0.5);
} }
}); });
``
// Repeat the above code for secondLayer and thirdLayer // Repeat the above code for secondLayer and thirdLayer
// Add this code for secondLayer // Add this code for secondLayer
@ -324,7 +347,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -341,30 +364,15 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => {
audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
firstTextLayer.setVisible(false);
document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play();
firstTextLayer.setVisible(true);
animatedLetter.setVisible(false);
firstScreen.setVisible(false);
graphics.setVisible(true);
}) })
} }
@ -373,3 +381,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer, fourthLayer; let firstLayer, secondLayer, thirdLayer, fourthLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -91,6 +156,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -109,139 +196,71 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : M", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterM').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterM').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterM').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterM').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedM').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedM').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : M', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: M', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : M', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedMHeight, 'animatedM').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedMHeight, 'animatedM').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -255,11 +274,12 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -268,7 +288,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioOne'); const audioTwoAudio = this.sound.add('audioOne');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -278,7 +298,7 @@ let scoreTotal = 0; let isDrawing = false;
thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale); thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const thirdTextLayer = this.add.text(textX, textY, '3. Slant', { font: '700 40px quicksand', fill: '#05b3a4'}); const thirdTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '3. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioThreeAudio = this.sound.add('audioTwo'); const audioThreeAudio = this.sound.add('audioTwo');
thirdTextLayer.setVisible(false); thirdTextLayer.setVisible(false);
thirdLayer.setDepth(1.1); thirdLayer.setDepth(1.1);
@ -289,7 +309,7 @@ let scoreTotal = 0; let isDrawing = false;
fourthLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer4').setScale(letterScale); fourthLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer4').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const fourthTextLayer = this.add.text(textX, textY, '4. Slant', { font: '700 40px quicksand', fill: '#05b3a4'}); const fourthTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '4. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioFourthAudio = this.sound.add('audioTwo'); const audioFourthAudio = this.sound.add('audioTwo');
fourthTextLayer.setVisible(false); fourthTextLayer.setVisible(false);
fourthLayer.setDepth(1.1); fourthLayer.setDepth(1.1);
@ -390,7 +410,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -407,30 +427,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); firstScreen.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -439,3 +443,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
// let x = 100; // let x = 100;
// // Use x // // Use x
@ -95,6 +160,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -119,131 +206,71 @@ let scoreTotal = 0; let isDrawing = false;
this.load.image('sun', '/assets/sun.png'); this.load.image('sun', '/assets/sun.png');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image('bgMobile', '/assets/bgMobile.png');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image('canvasStand', '/assets/stand2.png');
this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : N", { font: '700 40px quicksand', fill: '#05b3a4', });
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterN').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterN').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterN').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterN').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedN').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedN').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : N', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: N', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : N', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedNHeight, 'animatedN').setDepth(2).setScale(animatedNScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedNHeight, 'animatedN').setDepth(2).setScale(animatedNScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -256,11 +283,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -269,7 +296,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioOne'); const audioTwoAudio = this.sound.add('audioOne');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -279,7 +306,7 @@ let scoreTotal = 0; let isDrawing = false;
thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale); thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const thirdTextLayer = this.add.text(textX, textY, '3. Slant', { font: '700 40px quicksand', fill: '#05b3a4'}); const thirdTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '3. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioThreeAudio = this.sound.add('audioTwo'); const audioThreeAudio = this.sound.add('audioTwo');
thirdTextLayer.setVisible(false); thirdTextLayer.setVisible(false);
thirdLayer.setDepth(1.1); thirdLayer.setDepth(1.1);
@ -293,8 +320,6 @@ let scoreTotal = 0; let isDrawing = false;
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
let thirdDragStartPoint = { x: 0, y: 0 }; let thirdDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -356,7 +381,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -374,30 +399,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); firstScreen.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -405,3 +414,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -91,6 +156,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -113,133 +200,71 @@ let scoreTotal = 0; let isDrawing = false;
this.load.image('sun', '/assets/sun.png'); this.load.image('sun', '/assets/sun.png');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image('bgMobile', '/assets/bgMobile.png');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image('canvasStand', '/assets/stand2.png');
this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : O", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterO').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterO').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 90, customHeight / 2 + letterHeight, 'letterO').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 90, customHeight / 2 + letterHeight, 'letterO').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedO').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedO').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : O', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: O', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : O', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedOHeight, 'animatedO').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedOHeight, 'animatedO').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -253,11 +278,12 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 12 : customWidth * 0.75; textX = isMobile ? customWidth / 12 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Hook Around Close',{ font: '700 35px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Hook Around Close',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -291,7 +317,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -308,37 +334,53 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); firstScreen.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
function update() { function update() {}
}
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -91,6 +156,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -115,133 +202,70 @@ let scoreTotal = 0; let isDrawing = false;
this.load.image('sun', '/assets/sun.png'); this.load.image('sun', '/assets/sun.png');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image('bgMobile', '/assets/bgMobile.png');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image('canvasStand', '/assets/stand2.png');
this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : P", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 + 30, customHeight / 2 + letterHeight, 'letterP').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 + 30, customHeight / 2 + letterHeight, 'letterP').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterP').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterP').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedP').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedP').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; })
const baseFontSize = 24; retryButton.setInteractive().on('pointerdown', () => {
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; window.location.reload();
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : P', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); })
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: P', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : P', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedPHeight, 'animatedP').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedPHeight, 'animatedP').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -255,11 +279,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 + 30, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 + 30, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -268,7 +292,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 + 30, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 + 30, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slide Around',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slide Around',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -325,7 +349,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -342,31 +366,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -375,3 +382,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -91,6 +156,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -103,145 +190,78 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('letterQ', '/assets/capital-letter/q.svg'); this.load.svg('letterQ', '/assets/capital-letter/q.svg');
this.load.svg('layer1', '/assets/capital-letter/q_l1.svg'); this.load.svg('layer1', '/assets/capital-letter/q_l1.svg');
this.load.svg('layer2', '/assets/capital-letter/q_l2.svg'); this.load.svg('layer2', '/assets/capital-letter/q_l2.svg');
this.load.audio('audioOne', '/assets/audio/tall-down.mp3'); this.load.audio('audioOne', '/assets/audio/hook-around-close.mp3');
this.load.audio('audioTwo', '/assets/audio/slide-around.mp3'); this.load.audio('audioTwo', '/assets/audio/slant.mp3');
this.load.image('topLogo', '/assets/top_logo.svg'); this.load.image('topLogo', '/assets/top_logo.svg');
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false); submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : Q", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterQ').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterQ').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterQ').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterQ').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedQ').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedQ').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : Q', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
animatedLetter = this.add.video(customWidth / 2, customHeight / 2 + animatedQHeight, 'animatedQ').setDepth(2).setScale(animatedVideoScale); maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: Q', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : Q', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedQHeight, 'animatedQ').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -255,11 +275,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Hook Around Close',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Hook Around Close',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -268,7 +288,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slant',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -281,8 +301,6 @@ let scoreTotal = 0; let isDrawing = false;
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -325,7 +343,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -342,36 +360,55 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
function update() { function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
// let x = 100; // let x = 100;
// // Use x // // Use x
@ -97,6 +162,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -121,131 +208,70 @@ let scoreTotal = 0; let isDrawing = false;
this.load.image('sun', '/assets/sun.png'); this.load.image('sun', '/assets/sun.png');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image('bgMobile', '/assets/bgMobile.png');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image('canvasStand', '/assets/stand2.png');
this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : R", { font: '700 40px quicksand', fill: '#05b3a4', });
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 + 10, customHeight / 2 + letterHeight, 'letterR').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 + 10, customHeight / 2 + letterHeight, 'letterR').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 10, customHeight / 2 + letterHeight, 'letterR').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 10, customHeight / 2 + letterHeight, 'letterR').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedR').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedR').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; })
const baseFontSize = 24; retryButton.setInteractive().on('pointerdown', () => {
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; window.location.reload();
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : R', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); })
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: R', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : R', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedRHeight, 'animatedR').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedRHeight, 'animatedR').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -258,11 +284,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 + 10, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 + 10, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -271,7 +297,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 + 10, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 + 10, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slide Around',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slide Around',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -295,8 +321,6 @@ let scoreTotal = 0; let isDrawing = false;
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
let thirdDragStartPoint = { x: 0, y: 0 }; let thirdDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -358,7 +382,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -390,17 +414,13 @@ let scoreTotal = 0; let isDrawing = false;
} }
}) })
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -408,3 +428,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -91,6 +156,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -107,139 +194,71 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : S", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterS').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterS').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 90, customHeight / 2 + letterHeight, 'letterS').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 90, customHeight / 2 + letterHeight, 'letterS').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedS').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedS').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : S', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: S', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : S', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedSHeight, 'animatedS').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedSHeight, 'animatedS').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -253,11 +272,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 12 : customWidth * 0.75; textX = isMobile ? customWidth / 12 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Hook Around Snake',{ font: '700 35px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Hook Around Snake',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -290,7 +309,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -307,31 +326,15 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
@ -340,5 +343,41 @@ let scoreTotal = 0; let isDrawing = false;
function update() { function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -91,6 +156,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -109,137 +196,70 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : T", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterT').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterT').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterT').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterT').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedT').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedT').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : T', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: T', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : T', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedTHeight, 'animatedT').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedTHeight, 'animatedT').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -253,11 +273,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -266,7 +286,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slide',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -321,7 +341,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -338,31 +358,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -371,3 +374,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -91,6 +156,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -107,138 +194,70 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : U", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterU').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterU').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 90, customHeight / 2 + letterHeight, 'letterU').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 90, customHeight / 2 + letterHeight, 'letterU').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedU').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedU').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; })
const baseFontSize = 24; retryButton.setInteractive().on('pointerdown', () => {
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; window.location.reload();
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : U', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); })
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: U', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : U', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedUHeight, 'animatedU').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedUHeight, 'animatedU').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -252,11 +271,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 12 : customWidth * 0.75; textX = isMobile ? customWidth / 12 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Down Curve Up',{ font: '700 35px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Down Curve Up',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -291,7 +310,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -308,30 +327,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
@ -342,3 +345,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -91,6 +156,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -108,140 +195,72 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
submitNotic.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : V", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterV').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterV').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterV').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterV').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedV').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedV').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : V', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: V', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : V', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedVHeight, 'animatedV').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedVHeight, 'animatedV').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -255,11 +274,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Slant',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -268,7 +287,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slant',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioOne'); const audioTwoAudio = this.sound.add('audioOne');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -281,8 +300,6 @@ let scoreTotal = 0; let isDrawing = false;
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -304,7 +321,6 @@ let scoreTotal = 0; let isDrawing = false;
firstLayer.setAlpha(0.5); firstLayer.setAlpha(0.5);
} }
}); });
``
// Repeat the above code for secondLayer and thirdLayer // Repeat the above code for secondLayer and thirdLayer
// Add this code for secondLayer // Add this code for secondLayer
@ -326,7 +342,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -343,30 +359,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); firstScreen.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -375,3 +375,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer, fourthLayer; let firstLayer, secondLayer, thirdLayer, fourthLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -91,6 +156,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -108,139 +195,71 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : W", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterW').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterW').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterW').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterW').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedW').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedW').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : W', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: W', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : W', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedWHeight, 'animatedW').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedWHeight, 'animatedW').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -254,11 +273,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Slant',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -267,7 +286,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slant',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioOne'); const audioTwoAudio = this.sound.add('audioOne');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -277,7 +296,7 @@ let scoreTotal = 0; let isDrawing = false;
thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale); thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const thirdTextLayer = this.add.text(textX, textY, '3. Slant', { font: '700 40px quicksand', fill: '#05b3a4'}); const thirdTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '3. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioThreeAudio = this.sound.add('audioOne'); const audioThreeAudio = this.sound.add('audioOne');
thirdTextLayer.setVisible(false); thirdTextLayer.setVisible(false);
thirdLayer.setDepth(1.1); thirdLayer.setDepth(1.1);
@ -288,7 +307,7 @@ let scoreTotal = 0; let isDrawing = false;
fourthLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer4').setScale(letterScale); fourthLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer4').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const fourthTextLayer = this.add.text(textX, textY, '4. Slant', { font: '700 40px quicksand', fill: '#05b3a4'}); const fourthTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '4. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioFourthAudio = this.sound.add('audioOne'); const audioFourthAudio = this.sound.add('audioOne');
fourthTextLayer.setVisible(false); fourthTextLayer.setVisible(false);
fourthLayer.setDepth(1.1); fourthLayer.setDepth(1.1);
@ -389,7 +408,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -406,37 +425,55 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); firstScreen.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
function update() { function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -91,6 +156,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -109,138 +196,70 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : X", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterX').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterX').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterX').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterX').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedX').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedX').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; })
const baseFontSize = 24; retryButton.setInteractive().on('pointerdown', () => {
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; window.location.reload();
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : X', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); })
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: X', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : X', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedXHeight, 'animatedX').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedXHeight, 'animatedX').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -254,11 +273,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Slant',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -267,7 +286,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Cross',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Cross',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -280,8 +299,6 @@ let scoreTotal = 0; let isDrawing = false;
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -324,7 +341,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -341,31 +358,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -374,3 +374,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
// let x = 100; // let x = 100;
// // Use x // // Use x
@ -95,6 +160,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -113,136 +200,70 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : Y", { font: '700 40px quicksand', fill: '#05b3a4', });
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'letterY').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'letterY').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'letterY').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'letterY').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedY').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedY').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; })
const baseFontSize = 24; retryButton.setInteractive().on('pointerdown', () => {
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; window.location.reload();
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : Y', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); })
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: Y', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : Y', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedYHeight, 'animatedY').setDepth(2).setScale(animatedYScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedYHeight, 'animatedY').setDepth(2).setScale(animatedYScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -255,12 +276,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Slant Right',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Slant Right',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5); const audioOneAudio = this.sound.add('audioOne');
const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
firstLayer.setAlpha(0.5); firstLayer.setAlpha(0.5);
@ -268,7 +288,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slant Left',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slant Left',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -278,7 +298,7 @@ let scoreTotal = 0; let isDrawing = false;
thirdLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale); thirdLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const thirdTextLayer = this.add.text(textX, textY, '3. Down', { font: '700 40px quicksand', fill: '#05b3a4'}); const thirdTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '3. Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioThreeAudio = this.sound.add('audioThree'); const audioThreeAudio = this.sound.add('audioThree');
thirdTextLayer.setVisible(false); thirdTextLayer.setVisible(false);
thirdLayer.setDepth(1.1); thirdLayer.setDepth(1.1);
@ -292,8 +312,6 @@ let scoreTotal = 0; let isDrawing = false;
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
let thirdDragStartPoint = { x: 0, y: 0 }; let thirdDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -355,7 +373,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -373,31 +391,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -405,3 +406,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
// let x = 100; // let x = 100;
// // Use x // // Use x
@ -95,6 +160,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -111,137 +198,71 @@ let scoreTotal = 0; let isDrawing = false;
this.load.image('topLogo', '/assets/top_logo.svg'); this.load.image('topLogo', '/assets/top_logo.svg');
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
this.load.image('canvasStand', '/assets/stand2.png');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : Z", { font: '700 40px quicksand', fill: '#05b3a4', });
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterZ').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterZ').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterZ').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterZ').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedZ').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedZ').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale); retryButton.setInteractive().on('pointerdown', () => {
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale); window.location.reload();
// Set up a mask for the drawing area based on the canvas dimensions })
const maskGraphics = this.make.graphics() const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale); maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask(); const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; })
const baseFontSize = 24; let responsiveFontSize = isMobile ? 16 : 32;
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; this.add.text(window.innerWidth / 2, 80, 'Letter: Z', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : Z', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : Z', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedZHeight, 'animatedZ').setDepth(2).setScale(animatedZScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedZHeight, 'animatedZ').setDepth(2).setScale(animatedZScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -254,11 +275,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Slide',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -267,7 +288,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slant',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -277,7 +298,7 @@ let scoreTotal = 0; let isDrawing = false;
thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale); thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const thirdTextLayer = this.add.text(textX, textY, '3. Slide', { font: '700 40px quicksand', fill: '#05b3a4'}); const thirdTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '3. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioThreeAudio = this.sound.add('audioOne'); const audioThreeAudio = this.sound.add('audioOne');
thirdTextLayer.setVisible(false); thirdTextLayer.setVisible(false);
thirdLayer.setDepth(1.1); thirdLayer.setDepth(1.1);
@ -291,8 +312,6 @@ let scoreTotal = 0; let isDrawing = false;
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
let thirdDragStartPoint = { x: 0, y: 0 }; let thirdDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -354,6 +373,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask);
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
@ -371,31 +391,16 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
});let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", { });
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -403,3 +408,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer; let firstLayer, secondLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -50,13 +115,13 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 35; canvasHeight = 35;
letterHeight = 30; letterHeight = 30;
letterScale = 1; letterScale = 1.7;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animatedVideoScale = 0.6; animatedVideoScale = 0.75;
animatedAHeight = 32; animatedAHeight = 32;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -73,13 +138,13 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterHeight = 20; letterHeight = 20;
letterScale = 1.5; letterScale = 1.7;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animatedVideoScale = 0.7; animatedVideoScale = 0.75;
animatedAHeight = 20; animatedAHeight = 20;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -91,12 +156,33 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
// console.log("Page loaded on: " + formattedDateTime); // console.log("Page loaded on: " + formattedDateTime);
}; };
// let hideButton;
function preload() { function preload() {
this.load.video('animatedA', '/assets/animated-letter/small_a.mp4'); this.load.video('animatedA', '/assets/animated-letter/small_a.mp4');
@ -109,139 +195,73 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image('sun', '/assets/sun.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('canvasStand', '/assets/stand2.png'); let formattedDateTime; this.load.image("cancelIcon", '/assets/svg/cancel.svg');
let gameStartTime = "start time here"; this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
submitButton = this.add.text(submitWidth, submitHeight, "Submit", { const borderBottom = this.add.graphics();
font: '900 24px Quicksand', const x = 0; const y = 54;
fill: '#05b3a4', const lineWidth = window.innerWidth;
backgroundColor : '#7c4c23', borderBottom.lineStyle(1, 0x0348A8);
padding: {x: 10, y: 10}, borderBottom.setAlpha(0.2);
shadow: { borderBottom.beginPath();
offsetX : 2, borderBottom.moveTo(x, y);
offsetY : 2, borderBottom.lineTo(x + lineWidth, y);
color: '#000', borderBottom.strokePath();
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false); submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : a", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterA').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterA').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterA').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterA').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedA').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedA').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : a', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: a', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : a', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedAHeight, 'animatedA').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedAHeight, 'animatedA').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
@ -257,11 +277,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 6 : customWidth * 0.75; textX = isMobile ? customWidth / 6 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Hook Around',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Hook Around',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -270,7 +290,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Small Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Small Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -305,8 +325,6 @@ let scoreTotal = 0; let isDrawing = false;
firstLayer.setAlpha(0.5); firstLayer.setAlpha(0.5);
} }
}); });
``
// Repeat the above code for secondLayer and thirdLayer
// Add this code for secondLayer // Add this code for secondLayer
secondLayer.on('dragstart', (pointer) => { secondLayer.on('dragstart', (pointer) => {
@ -327,7 +345,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -344,32 +362,15 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -378,3 +379,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xeaeae8,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -92,6 +157,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -110,140 +197,69 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
submitButton = this.add.text(submitWidth, submitHeight, "Submit", { const borderBottom = this.add.graphics();
font: '900 24px Quicksand', const x = 0; const y = 54;
fill: '#05b3a4', const lineWidth = window.innerWidth;
backgroundColor : '#7c4c23', borderBottom.lineStyle(1, 0x0348A8);
padding: {x: 10, y: 10}, borderBottom.setAlpha(0.2);
shadow: { borderBottom.beginPath();
offsetX : 2, borderBottom.moveTo(x, y);
offsetY : 2, borderBottom.lineTo(x + lineWidth, y);
color: '#000', borderBottom.strokePath();
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked');
submitButton.setVisible(false);
// windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : b", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'letterB').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'letterB').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'letterB').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'letterB').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedB').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedB').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : b', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: b', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : b', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedBHeight, 'animatedB').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedBHeight, 'animatedB').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -257,11 +273,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -270,7 +286,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Roll Around',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Roll Around',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -325,7 +341,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -342,31 +358,15 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => {
document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -375,3 +375,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -50,14 +115,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 35; canvasHeight = 35;
letterHeight = 40; letterHeight = 40;
letterScale = 1.3; letterScale = 1.7;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animatedVideoScale = 0.6; animatedVideoScale = 0.75;
animatedCHeight = 32; animatedCHeight = 32;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -74,14 +139,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterHeight = 30; letterHeight = 30;
letterScale = 1.5; letterScale = 1.7;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animatedVideoScale = 0.7; animatedVideoScale = 0.75;
animatedCHeight = 20; animatedCHeight = 20;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -93,6 +158,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -109,141 +196,73 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image('sun', '/assets/sun.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
submitButton = this.add.text(submitWidth, submitHeight, "Submit", { const borderBottom = this.add.graphics();
font: '900 24px Quicksand', const x = 0; const y = 54;
fill: '#05b3a4', const lineWidth = window.innerWidth;
backgroundColor : '#7c4c23', borderBottom.lineStyle(1, 0x0348A8);
padding: {x: 10, y: 10}, borderBottom.setAlpha(0.2);
shadow: { borderBottom.beginPath();
offsetX : 2, borderBottom.moveTo(x, y);
offsetY : 2, borderBottom.lineTo(x + lineWidth, y);
color: '#000', borderBottom.strokePath();
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false); submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : c", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterC').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterC').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 90, customHeight / 2 + letterHeight, 'letterC').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 90, customHeight / 2 + letterHeight, 'letterC').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedC').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedC').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : c', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: c', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : c', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedCHeight, 'animatedC').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedCHeight, 'animatedC').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -257,11 +276,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 7 : customWidth * 0.75; textX = isMobile ? customWidth / 7 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Hook Around',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Hook Around',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -273,8 +292,6 @@ let scoreTotal = 0; let isDrawing = false;
// Add these variables to keep track of start points // Add these variables to keep track of start points
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -296,7 +313,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -313,34 +330,15 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
function update() { function update() {
@ -348,3 +346,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer; let firstLayer, secondLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -93,6 +158,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -111,141 +198,80 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image('sun', '/assets/sun.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : d", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 - 30, customHeight / 2 + letterHeight, 'letterD').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 - 30, customHeight / 2 + letterHeight, 'letterD').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 - 30, customHeight / 2 + letterHeight, 'letterD').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 - 30, customHeight / 2 + letterHeight, 'letterD').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedD').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedD').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
// const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2;
// const baseFontSize = 24;
// const responsiveFontSize = (window.innerWidth / 480) * baseFontSize;
// const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : d', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
// animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedDHeight, 'animatedD').setDepth(2).setScale(animatedVideScale);
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : d', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: d', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : d', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedDHeight, 'animatedD').setDepth(2).setScale(animatedVideScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedDHeight, 'animatedD').setDepth(2).setScale(animatedVideScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -259,11 +285,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 - 30, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 - 30, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const secondTextLayer = this.add.text(textX, textY, '2. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioOne'); const audioTwoAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -272,7 +298,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 - 30, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 - 30, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const firstTextLayer = this.add.text(textX, textY, '1. Roll Around',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Roll Around',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioTwo'); const audioOneAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -326,7 +352,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -343,30 +369,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); firstScreen.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -375,3 +385,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xeaeae8,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -50,14 +115,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 35; canvasHeight = 35;
letterHeight = 30; letterHeight = 30;
letterScale = 1.4; letterScale = 1.9;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animatedVideoScale = 0.57; animatedVideoScale = 0.78;
animatedEHeight = 32; animatedEHeight = 32;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -74,14 +139,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterHeight = 20; letterHeight = 20;
letterScale = 1.75; letterScale = 1.9;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animatedVideoScale = 0.7; animatedVideoScale = 0.78;
animatedEHeight = 20; animatedEHeight = 20;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -93,6 +158,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -111,141 +198,74 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image('sun', '/assets/sun.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : e", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'letterE').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'letterE').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'letterE').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'letterE').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedE').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedE').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : e', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: e', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : e', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedEHeight, 'animatedE').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedEHeight, 'animatedE').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -259,11 +279,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 6 : customWidth * 0.75; textX = isMobile ? customWidth / 6 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Hook Around',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Hook Around',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -272,7 +292,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slide',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -307,7 +327,6 @@ let scoreTotal = 0; let isDrawing = false;
firstLayer.setAlpha(0.5); firstLayer.setAlpha(0.5);
} }
}); });
``
// Repeat the above code for secondLayer and thirdLayer // Repeat the above code for secondLayer and thirdLayer
// Add this code for secondLayer // Add this code for secondLayer
@ -329,7 +348,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -346,30 +365,15 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => {
audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
firstTextLayer.setVisible(false);
document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play();
firstTextLayer.setVisible(true);
animatedLetter.setVisible(false);
firstScreen.setVisible(false);
graphics.setVisible(true);
}) })
} }
@ -378,3 +382,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xeaeae8,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -50,14 +115,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 35; canvasHeight = 35;
letterHeight = -10; letterHeight = -10;
letterScale = 1; letterScale = 1.2;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animatedVideoScale = 0.57; animatedVideoScale = 0.70;
animatedFHeight = 32; animatedFHeight = 38;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -73,14 +138,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterHeight = -20; letterHeight = -20;
letterScale = 1; letterScale = 1.2;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animatedVideoScale = 0.65; animatedVideoScale = 0.69;
animatedFHeight = 20; animatedFHeight = 40;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -91,6 +156,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -109,141 +196,72 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image('sun', '/assets/sun.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false); submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : f", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 + 15, customHeight / 2 + letterHeight, 'letterF').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 + 15, customHeight / 2 + letterHeight, 'letterF').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 15, customHeight / 2 + letterHeight, 'letterF').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 15, customHeight / 2 + letterHeight, 'letterF').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedF').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedF').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; })
const baseFontSize = 24; retryButton.setInteractive().on('pointerdown', () => {
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; window.location.reload();
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : f', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); })
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: f', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : f', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedFHeight, 'animatedF').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedFHeight, 'animatedF').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -257,11 +275,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 + 15, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 + 15, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 6 : customWidth * 0.75; textX = isMobile ? customWidth / 6 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Hook Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Hook Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -270,7 +288,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 + 15, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 + 15, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Cross',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Cross',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -282,8 +300,6 @@ let scoreTotal = 0; let isDrawing = false;
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -326,7 +342,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -343,31 +359,15 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -376,3 +376,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -50,15 +115,15 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 35; canvasHeight = 35;
letterHeight = 8; letterHeight = 8;
letterScale = 0.95; letterScale = 1.2;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animatedVideoScale = 0.62; animatedVideoScale = 0.75;
animatedGHeight = 32; animatedGHeight = 45;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -74,14 +139,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterHeight = -20; letterHeight = -20;
letterScale = 1; letterScale = 1.2;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animatedVideoScale = 0.65; animatedVideoScale = 0.8;
animatedGHeight = 20; animatedGHeight = 20;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -93,6 +158,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -111,141 +198,72 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image('sun', '/assets/sun.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : g", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'letterG').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'letterG').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'letterG').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'letterG').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedG').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedG').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : g', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: g', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : g', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedGHeight, 'animatedG').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedGHeight, 'animatedG').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -259,11 +277,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 6 : customWidth * 0.75; textX = isMobile ? customWidth / 6 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Hook Around',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Hook Around',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
audioOneAudio.play(); audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -272,7 +290,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Down Tail',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Down Tail',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -306,7 +324,6 @@ let scoreTotal = 0; let isDrawing = false;
firstLayer.setAlpha(0.5); firstLayer.setAlpha(0.5);
} }
}); });
// Repeat the above code for secondLayer and thirdLayer
// Add this code for secondLayer // Add this code for secondLayer
secondLayer.on('dragstart', (pointer) => { secondLayer.on('dragstart', (pointer) => {
@ -327,7 +344,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -344,31 +361,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -377,3 +377,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xeaeae8,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -50,14 +115,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 35; canvasHeight = 35;
letterHeight = 70; letterHeight = 70;
letterScale = 0.95; letterScale = 1.2;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animatedVideoScale = 0.6; animatedVideoScale = 0.75;
animatedHHeight = 35; animatedHHeight = 35;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -74,15 +139,15 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterHeight = 70; letterHeight = 70;
letterScale = 1; letterScale = 1.2;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animatedVideoScale = 0.63; animatedVideoScale = 0.75;
animatedHHeight = 42; animatedHHeight = 35;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -93,6 +158,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -111,138 +198,71 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : h", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 + 25, customHeight / 2 + letterHeight, 'letterH').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 + 25, customHeight / 2 + letterHeight, 'letterH').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 25, customHeight / 2 + letterHeight, 'letterH').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 25, customHeight / 2 + letterHeight, 'letterH').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedH').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedH').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
firstScreen.setVisible(true);
}
}); });
retryButton.setInteractive().on('pointerdown', () => {
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; window.location.reload();
const baseFontSize = 24; })
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; const maskGraphics = this.make.graphics();
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : h', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: h', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : h', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedHHeight, 'animatedH').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedHHeight, 'animatedH').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
@ -258,11 +278,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 + 25, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 + 25, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
audioOneAudio.play(); audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -271,7 +291,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 + 25, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 + 25, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Roll Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Roll Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -283,8 +303,6 @@ let scoreTotal = 0; let isDrawing = false;
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -327,7 +345,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -344,31 +362,15 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -377,3 +379,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,76 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> <script src="/saveGameAI.js" is:inline></script>
<script src="/saveGameData.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +84,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xecedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +102,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -50,14 +114,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 35; canvasHeight = 35;
letterIeight = 50; letterIeight = 50;
letterScale = 1.2; letterScale = 1.6;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animatedVideoScale = 0.5; animatedVideoScale = 0.7;
animatedIHeight = 32; animatedIHeight = 32;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -74,14 +138,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterIeight = 30; letterIeight = 30;
letterScale = 1.3; letterScale = 1.6;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animatedVideoScale = 0.55; animatedVideoScale = 0.7;
animatedIHeight = 10; animatedIHeight = 10;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -93,6 +157,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -111,141 +197,70 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image('sun', '/assets/sun.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
submitButton = this.add.text(submitWidth, submitHeight, "Submit", { const borderBottom = this.add.graphics();
font: '900 24px Quicksand', const x = 0; const y = 54;
fill: '#05b3a4', const lineWidth = window.innerWidth;
backgroundColor : '#7c4c23', borderBottom.lineStyle(1, 0x0348A8);
padding: {x: 10, y: 10}, borderBottom.setAlpha(0.2);
shadow: { borderBottom.beginPath();
offsetX : 2, borderBottom.moveTo(x, y);
offsetY : 2, borderBottom.lineTo(x + lineWidth, y);
color: '#000', borderBottom.strokePath();
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : i", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 , customHeight / 2 + letterIeight, 'letterI').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 , customHeight / 2 + letterIeight, 'letterI').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 , customHeight / 2 + letterIeight, 'letterI').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 , customHeight / 2 + letterIeight, 'letterI').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterIeight, 'animatedI').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterIeight, 'animatedI').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; })
const baseFontSize = 24; retryButton.setInteractive().on('pointerdown', () => {
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; window.location.reload();
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : i', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); })
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: i', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : i', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedIHeight, 'animatedI').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedIHeight, 'animatedI').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -259,11 +274,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 , customHeight / 2 + letterIeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 , customHeight / 2 + letterIeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 5.5 : customWidth * 0.75; textX = isMobile ? customWidth / 5.5 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Small Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Small Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -272,7 +287,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 , customHeight / 2 + letterIeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 , customHeight / 2 + letterIeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Dot',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Dot',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -284,8 +299,6 @@ let scoreTotal = 0; let isDrawing = false;
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -328,7 +341,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -345,30 +358,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); firstScreen.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -377,3 +374,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -93,6 +158,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -111,140 +198,71 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : j", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 - 20, customHeight / 2 + letterJeight, 'letterJ').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 - 20, customHeight / 2 + letterJeight, 'letterJ').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 - 20 , customHeight / 2 + letterJeight, 'letterJ').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 - 20 , customHeight / 2 + letterJeight, 'letterJ').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterJeight, 'animatedJ').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterJeight, 'animatedJ').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : j', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: j', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : j', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedJHeight, 'animatedJ').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedJHeight, 'animatedJ').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -258,11 +276,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterJeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterJeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Down Tail',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Down Tail',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -271,7 +289,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterJeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterJeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Dot',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Dot',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -283,8 +301,6 @@ let scoreTotal = 0; let isDrawing = false;
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -306,7 +322,6 @@ let scoreTotal = 0; let isDrawing = false;
firstLayer.setAlpha(0.5); firstLayer.setAlpha(0.5);
} }
}); });
``
// Repeat the above code for secondLayer and thirdLayer // Repeat the above code for secondLayer and thirdLayer
// Add this code for secondLayer // Add this code for secondLayer
@ -328,7 +343,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -345,30 +360,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); firstScreen.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -377,3 +376,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xeaeae8,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
// let x = 100; // let x = 100;
// // Use x // // Use x
@ -96,6 +161,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -114,137 +201,71 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : k", { font: '700 40px quicksand', fill: '#05b3a4', });
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'letterK').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'letterK').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterK').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterK').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedK').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedK').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; }
const baseFontSize = 24; })
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize;
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : k', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); retryButton.setInteractive().on('pointerdown', () => {
window.location.reload();
})
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: k', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : k', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedKHeight, 'animatedK').setDepth(2).setScale(animatedKScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedKHeight, 'animatedK').setDepth(2).setScale(animatedKScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -257,11 +278,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -270,7 +291,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slant In',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slant In',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -280,7 +301,7 @@ let scoreTotal = 0; let isDrawing = false;
thirdLayer = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale); thirdLayer = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const thirdTextLayer = this.add.text(textX, textY, '3. Slant Out', { font: '700 40px quicksand', fill: '#05b3a4'}); const thirdTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '3. Slant Out',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioThreeAudio = this.sound.add('audioThree'); const audioThreeAudio = this.sound.add('audioThree');
thirdTextLayer.setVisible(false); thirdTextLayer.setVisible(false);
thirdLayer.setDepth(1.1); thirdLayer.setDepth(1.1);
@ -294,8 +315,6 @@ let scoreTotal = 0; let isDrawing = false;
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
let thirdDragStartPoint = { x: 0, y: 0 }; let thirdDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -357,7 +376,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -375,30 +394,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -406,3 +409,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -93,6 +158,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -109,140 +196,70 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
submitButton = this.add.text(submitWidth, submitHeight, "Submit", { const borderBottom = this.add.graphics();
font: '900 24px Quicksand', const x = 0; const y = 54;
fill: '#05b3a4', const lineWidth = window.innerWidth;
backgroundColor : '#7c4c23', borderBottom.lineStyle(1, 0x0348A8);
padding: {x: 10, y: 10}, borderBottom.setAlpha(0.2);
shadow: { borderBottom.beginPath();
offsetX : 2, borderBottom.moveTo(x, y);
offsetY : 2, borderBottom.lineTo(x + lineWidth, y);
color: '#000', borderBottom.strokePath();
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : l", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 + 50, customHeight / 2 + letterHeight, 'letterL').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 + 50, customHeight / 2 + letterHeight, 'letterL').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 50, customHeight / 2 + letterHeight, 'letterL').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 50, customHeight / 2 + letterHeight, 'letterL').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedL').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedL').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : l', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: l', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : l', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedLHeight, 'animatedL').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedLHeight, 'animatedL').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -256,11 +273,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 + 50, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 + 50, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -272,8 +289,6 @@ let scoreTotal = 0; let isDrawing = false;
// Add these variables to keep track of start points // Add these variables to keep track of start points
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -295,7 +310,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -312,31 +327,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
@ -347,3 +345,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xeaeae8,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
// let x = 100; // let x = 100;
// // Use x // // Use x
@ -54,14 +119,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 35; canvasHeight = 35;
letterHeight = 50; letterHeight = 50;
letterScale = 1.1; letterScale = 1.7;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animatedMHeight = 35; animatedMHeight = 35;
animatedMScale = 0.5; animatedMScale = 0.7;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -77,14 +142,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterHeight = 40; letterHeight = 40;
letterScale = 1.3; letterScale = 1.7;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animatedMHeight = 20; animatedMHeight = 20;
animatedMScale = 0.6; animatedMScale = 0.8;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -95,6 +160,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -112,137 +199,70 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : m", { font: '700 40px quicksand', fill: '#05b3a4', });
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterM').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterM').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterM').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterM').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedM').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedM').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; }
const baseFontSize = 24; })
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; retryButton.setInteractive().on('pointerdown', () => {
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : m', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); window.location.reload();
})
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: m', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : m', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedMHeight, 'animatedM').setDepth(2).setScale(animatedMScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedMHeight, 'animatedM').setDepth(2).setScale(animatedMScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -255,11 +275,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 5 : customWidth * 0.75; textX = isMobile ? customWidth / 5 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Small Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Small Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -268,7 +288,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Roll Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Roll Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -278,7 +298,7 @@ let scoreTotal = 0; let isDrawing = false;
thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale); thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const thirdTextLayer = this.add.text(textX, textY, '3. Roll Down', { font: '700 40px quicksand', fill: '#05b3a4'}); const thirdTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '3. Roll Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioThreeAudio = this.sound.add('audioTwo'); const audioThreeAudio = this.sound.add('audioTwo');
thirdTextLayer.setVisible(false); thirdTextLayer.setVisible(false);
thirdLayer.setDepth(1.1); thirdLayer.setDepth(1.1);
@ -355,7 +375,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -373,30 +393,15 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -404,3 +409,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xeaeae8,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -50,14 +115,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 35; canvasHeight = 35;
letterNeight = 50; letterNeight = 50;
letterScale = 1.4; letterScale = 1.6;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animatedVideoScale = 0.63; animatedVideoScale = 0.7;
animatedNHeight = 32; animatedNHeight = 32;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -74,14 +139,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterNeight = 30; letterNeight = 30;
letterScale = 1.5; letterScale = 1.6;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animatedVideoScale = 0.65; animatedVideoScale = 0.7;
animatedNHeight = 20; animatedNHeight = 20;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -93,6 +158,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -111,140 +198,71 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : n", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 + 60, customHeight / 2 + letterNeight, 'letterN').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 + 60, customHeight / 2 + letterNeight, 'letterN').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 60, customHeight / 2 + letterNeight, 'letterN').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 60, customHeight / 2 + letterNeight, 'letterN').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterNeight, 'animatedN').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterNeight, 'animatedN').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : n', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: n', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : n', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedNHeight, 'animatedN').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedNHeight, 'animatedN').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -258,11 +276,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 + 60, customHeight / 2 + letterNeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 + 60, customHeight / 2 + letterNeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 5 : customWidth * 0.75; textX = isMobile ? customWidth / 5 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Small Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Small Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -271,7 +289,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 + 60, customHeight / 2 + letterNeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 + 60, customHeight / 2 + letterNeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Roll Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Roll Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -283,8 +301,6 @@ let scoreTotal = 0; let isDrawing = false;
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -327,7 +343,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -344,30 +360,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -376,3 +376,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer; let firstLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -50,7 +115,7 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 35; canvasHeight = 35;
letterHeight = 40; letterHeight = 40;
letterScale = 1.3; letterScale = 1.6;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
@ -73,7 +138,7 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterHeight = 30; letterHeight = 30;
letterScale = 1.5; letterScale = 1.6;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
@ -91,6 +156,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -107,141 +194,71 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image('sun', '/assets/sun.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : o", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterO').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterO').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 90, customHeight / 2 + letterHeight, 'letterO').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 90, customHeight / 2 + letterHeight, 'letterO').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedO').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedO').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
retryButton.setInteractive().on('pointerdown', () => {
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; window.location.reload();
const baseFontSize = 24; })
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; const maskGraphics = this.make.graphics();
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : o', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: o', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : o', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedOHeight, 'animatedO').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedOHeight, 'animatedO').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -255,11 +272,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Hook Around Close',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Hook Around Close',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -271,8 +288,6 @@ let scoreTotal = 0; let isDrawing = false;
// Add these variables to keep track of start points // Add these variables to keep track of start points
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -294,7 +309,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -311,30 +326,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -343,3 +342,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -21,7 +84,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -39,9 +102,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -90,6 +155,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
} }
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -108,140 +195,71 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : p", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 + 30, customHeight / 2 + letterPeight, 'letterP').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 + 30, customHeight / 2 + letterPeight, 'letterP').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 30, customHeight / 2 + letterPeight, 'letterP').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 30, customHeight / 2 + letterPeight, 'letterP').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterPeight, 'animatedP').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterPeight, 'animatedP').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; })
const baseFontSize = 24; retryButton.setInteractive().on('pointerdown', () => {
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; window.location.reload();
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : p', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); })
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: p', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : p', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedPHeight, 'animatedP').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedPHeight, 'animatedP').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -255,11 +273,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 + 30, customHeight / 2 + letterPeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 + 30, customHeight / 2 + letterPeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Down Tail',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Down Tail',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -268,7 +286,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 + 30, customHeight / 2 + letterPeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 + 30, customHeight / 2 + letterPeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Roll Around',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Roll Around',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -322,7 +340,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -339,30 +357,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -371,3 +373,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -21,7 +84,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -39,9 +102,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -92,6 +157,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -116,134 +203,70 @@ let scoreTotal = 0; let isDrawing = false;
this.load.image('sun', '/assets/sun.png'); this.load.image('sun', '/assets/sun.png');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image('bgMobile', '/assets/bgMobile.png');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image('canvasStand', '/assets/stand2.png');
this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : q", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 - 45, customHeight / 2 + letterQeight, 'letterQ').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 - 45, customHeight / 2 + letterQeight, 'letterQ').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 - 45, customHeight / 2 + letterQeight, 'letterQ').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 - 45, customHeight / 2 + letterQeight, 'letterQ').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterQeight, 'animatedQ').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterQeight, 'animatedQ').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2;
const baseFontSize = 24;
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize;
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : p', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
const animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedQHeight, 'animatedQ').setDepth(2).setScale(animatedVideoScale);
}
})
retryButton.setInteractive().on('pointerdown', () => {
window.location.reload();
})
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: q', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : q', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedQHeight, 'animatedQ').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
animatedLetter.play(); animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -257,11 +280,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; - 35 let textX, textY; - 35
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 - 45, customHeight / 2 + letterQeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 - 45, customHeight / 2 + letterQeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 6.5 : customWidth * 0.75; textX = isMobile ? customWidth / 6.5 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Hook Around',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Hook Around',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -270,7 +293,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 - 45, customHeight / 2 + letterQeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 - 45, customHeight / 2 + letterQeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Down Hook',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Down Hook',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -282,8 +305,6 @@ let scoreTotal = 0; let isDrawing = false;
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -325,7 +346,7 @@ let scoreTotal = 0; let isDrawing = false;
}); });
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -342,35 +363,56 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
function update() { function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -50,14 +115,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.14 canvasScale = 0.14
canvasHeight = 35; canvasHeight = 35;
letterReight = 20; letterReight = 20;
letterScale = 1.2; letterScale = 1.6;
backgroundScale = 0.8; backgroundScale = 0.8;
sunScale = 0.1; sunScale = 0.1;
sunScalePlus = 0.15; sunScalePlus = 0.15;
sunWidth = 70; sunWidth = 70;
sunHeight = 70; sunHeight = 70;
animatedVideoScale = 0.5; animatedVideoScale = 0.7;
animatedRHeight = 32; animatedRHeight = 32;
helpButtonHeight = customHeight / 1.1; helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10; helpButtonWidth = customWidth / 2 + 10;
@ -74,14 +139,14 @@ let scoreTotal = 0; let isDrawing = false;
canvasScale = 0.195; canvasScale = 0.195;
canvasHeight = 20; canvasHeight = 20;
letterReight = -10; letterReight = -10;
letterScale = 1.2; letterScale = 1.6;
backgroundScale = 1; backgroundScale = 1;
sunScale = 0.2; sunScale = 0.2;
sunScalePlus = 0.25; sunScalePlus = 0.25;
sunWidth = 200; sunWidth = 200;
sunHeight = 100; sunHeight = 100;
animatedVideoScale = 0.6; animatedVideoScale = 0.7;
animatedRHeight = 20; animatedRHeight = 20;
helpButtonHeight = customHeight / 2 + 40; helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32; helpButtonWidth = customWidth / 1.32;
@ -93,6 +158,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -111,141 +198,70 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image('sun', '/assets/sun.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : r", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 + 40, customHeight / 2 + letterReight, 'letterR').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 + 40, customHeight / 2 + letterReight, 'letterR').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 40, customHeight / 2 + letterReight, 'letterR').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 40, customHeight / 2 + letterReight, 'letterR').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterReight, 'animatedR').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterReight, 'animatedR').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; })
const baseFontSize = 24; retryButton.setInteractive().on('pointerdown', () => {
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; window.location.reload();
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : r', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); })
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: r', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : r', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedRHeight, 'animatedR').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedRHeight, 'animatedR').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -259,11 +275,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 + 40, customHeight / 2 + letterReight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 + 40, customHeight / 2 + letterReight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 5 : customWidth * 0.75; textX = isMobile ? customWidth / 5 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Small Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Small Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -272,7 +288,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 + 40, customHeight / 2 + letterReight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 + 40, customHeight / 2 + letterReight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Roll',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Roll',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -284,8 +300,6 @@ let scoreTotal = 0; let isDrawing = false;
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -328,7 +342,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -345,30 +359,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -377,3 +375,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -93,6 +158,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -114,134 +201,71 @@ let scoreTotal = 0; let isDrawing = false;
this.load.image('sun', '/assets/sun.png'); this.load.image('sun', '/assets/sun.png');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image('bgMobile', '/assets/bgMobile.png');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image('canvasStand', '/assets/stand2.png');
this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : s", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterS').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterS').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 90, customHeight / 2 + letterHeight, 'letterS').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 90, customHeight / 2 + letterHeight, 'letterS').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedS').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedS').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : s', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: s', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : s', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedSHeight, 'animatedS').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedSHeight, 'animatedS').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -255,11 +279,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 13 : customWidth * 0.75; textX = isMobile ? customWidth / 13 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Hook Around Snake',{ font: '700 35px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Hook Around Snake',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -290,7 +314,7 @@ let scoreTotal = 0; let isDrawing = false;
}); });
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -307,30 +331,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
@ -341,3 +349,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -93,6 +158,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -111,141 +198,68 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image('sun', '/assets/sun.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : t", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterTeight, 'letterR').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterTeight, 'letterR').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 , customHeight / 2 + letterTeight, 'letterR').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 , customHeight / 2 + letterTeight, 'letterR').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterTeight, 'animatedT').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterTeight, 'animatedT').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
firstScreen.setVisible(true);
}
}); });
retryButton.setInteractive().on('pointerdown', () => {
window.location.reload();
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; })
const baseFontSize = 24; const maskGraphics = this.make.graphics();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : t', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: t', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : t', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedTHeight, 'animatedT').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedTHeight, 'animatedT').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -259,11 +273,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 , customHeight / 2 + letterTeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 , customHeight / 2 + letterTeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Tall Down',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Tall Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -272,7 +286,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 , customHeight / 2 + letterTeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 , customHeight / 2 + letterTeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Cross',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Cross',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -327,7 +341,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -344,30 +358,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand', document.getElementById('beforeStartBtn').addEventListener('click', function() {
fill: '#05b3a4', document.getElementById('blurDisplay').classList.add('hidden');
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => {
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -376,3 +374,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -93,6 +158,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -111,140 +198,71 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
submitNotic.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : u", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 + 20, customHeight / 2 + letterUeight, 'letterU').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 + 20, customHeight / 2 + letterUeight, 'letterU').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterUeight, 'letterU').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterUeight, 'letterU').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterUeight, 'animatedU').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterUeight, 'animatedU').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : u', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: u', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : u', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedUHeight, 'animatedU').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedUHeight, 'animatedU').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -258,11 +276,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterUeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterUeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 25 : customWidth * 0.75; textX = isMobile ? customWidth / 25 : customWidth * 0.75;
textY = isMobile ? customHeight / 6 : customHeight / 2.3; textY = isMobile ? customHeight / 6 : customHeight / 2.3;
const firstTextLayer = this.add.text(textX, textY, '1. Small Down Curve Up',{ font: '700 35px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Small Down Curve Up',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -271,7 +289,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterUeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 + 20, customHeight / 2 + letterUeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Small Down',{ font: '700 35px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Small Down',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -283,8 +301,6 @@ let scoreTotal = 0; let isDrawing = false;
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -327,7 +343,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -344,30 +360,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -376,3 +376,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -93,6 +158,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -110,140 +197,69 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image('sun', '/assets/sun.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
submitNotic.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : v", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterVHeight, 'letterV').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterVHeight, 'letterV').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 , customHeight / 2 + letterVHeight, 'letterV').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 , customHeight / 2 + letterVHeight, 'letterV').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterVHeight, 'animatedV').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterVHeight, 'animatedV').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
firstScreen.setVisible(true);
}
}); });
retryButton.setInteractive().on('pointerdown', () => {
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; window.location.reload();
const baseFontSize = 24; })
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; const maskGraphics = this.make.graphics();
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : v', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: v', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : v', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedVHeight, 'animatedV').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedVHeight, 'animatedV').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
@ -259,11 +275,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 , customHeight / 2 + letterVHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 , customHeight / 2 + letterVHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 + 30 : customWidth * 0.75; textX = isMobile ? customWidth / 4 + 30 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Slant',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -272,7 +288,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 , customHeight / 2 + letterVHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 , customHeight / 2 + letterVHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slant',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioOne'); const audioTwoAudio = this.sound.add('audioOne');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -284,8 +300,6 @@ let scoreTotal = 0; let isDrawing = false;
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -328,7 +342,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -345,30 +359,14 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -377,3 +375,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer, fourthLayer; let firstLayer, secondLayer, thirdLayer, fourthLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -93,6 +158,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -109,142 +196,69 @@ let scoreTotal = 0; let isDrawing = false;
this.load.image('topLogo', '/assets/top_logo.svg'); this.load.image('topLogo', '/assets/top_logo.svg');
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image('sun', '/assets/sun.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : w", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterW').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterW').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterW').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterW').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedW').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedW').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; })
const baseFontSize = 24; retryButton.setInteractive().on('pointerdown', () => {
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; window.location.reload();
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : w', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); })
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: w', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : w', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedWHeight, 'animatedW').setDepth(2).setScale(animatedVideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedWHeight, 'animatedW').setDepth(2).setScale(animatedVideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -258,11 +272,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 + 40: customWidth * 0.75; textX = isMobile ? customWidth / 4 + 40: customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Slant',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -271,7 +285,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slant',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioOne'); const audioTwoAudio = this.sound.add('audioOne');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -281,7 +295,7 @@ let scoreTotal = 0; let isDrawing = false;
thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale); thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const thirdTextLayer = this.add.text(textX, textY, '3. Slant', { font: '700 40px quicksand', fill: '#05b3a4'}); const thirdTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '3. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioThreeAudio = this.sound.add('audioOne'); const audioThreeAudio = this.sound.add('audioOne');
thirdTextLayer.setVisible(false); thirdTextLayer.setVisible(false);
thirdLayer.setDepth(1.1); thirdLayer.setDepth(1.1);
@ -292,7 +306,7 @@ let scoreTotal = 0; let isDrawing = false;
fourthLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer4').setScale(letterScale); fourthLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer4').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const fourthTextLayer = this.add.text(textX, textY, '4. Slant', { font: '700 40px quicksand', fill: '#05b3a4'}); const fourthTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '4. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioFourthAudio = this.sound.add('audioOne'); const audioFourthAudio = this.sound.add('audioOne');
fourthTextLayer.setVisible(false); fourthTextLayer.setVisible(false);
fourthLayer.setDepth(1.1); fourthLayer.setDepth(1.1);
@ -393,7 +407,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -410,33 +424,15 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
function update() { function update() {
@ -444,3 +440,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -93,6 +158,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -111,141 +198,70 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image('sun', '/assets/sun.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : x", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterXHeight, 'letterX').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2, customHeight / 2 + letterXHeight, 'letterX').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 , customHeight / 2 + letterXHeight, 'letterX').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 , customHeight / 2 + letterXHeight, 'letterX').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterXHeight, 'animatedX').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterXHeight, 'animatedX').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; })
const baseFontSize = 24; retryButton.setInteractive().on('pointerdown', () => {
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; window.location.reload();
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : x', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); })
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: x', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : x', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedXHeight, 'animatedX').setDepth(2).setScale(animatedXideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedXHeight, 'animatedX').setDepth(2).setScale(animatedXideoScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -259,11 +275,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 , customHeight / 2 + letterXHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 , customHeight / 2 + letterXHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Slant',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -272,7 +288,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 , customHeight / 2 + letterXHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 , customHeight / 2 + letterXHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Cross',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Cross',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -284,8 +300,6 @@ let scoreTotal = 0; let isDrawing = false;
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -328,7 +342,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -345,30 +359,15 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
@ -377,3 +376,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
if(isMobile){ if(isMobile){
cloudeSize = 200; cloudeSize = 200;
@ -93,6 +158,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -111,138 +198,70 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png'); this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('canvas', '/assets/canvas4.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : y", { font: '700 40px quicksand', fill: '#05b3a4', });
// this.add.image(customWidth / 2, 50, 'cloud').setDepth(1.9);
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 - 10, customHeight / 2 + letterYHeight, 'letterY').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 - 10, customHeight / 2 + letterYHeight, 'letterY').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterYHeight, 'letterY').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterYHeight, 'letterY').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterYHeight, 'animatedY').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterYHeight, 'animatedY').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
}
})
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; retryButton.setInteractive().on('pointerdown', () => {
const baseFontSize = 24; window.location.reload();
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize; })
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : y', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: y', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : y', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedYHeight, 'animatedY').setDepth(2).setScale(animatedYideoScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedYHeight, 'animatedY').setDepth(2).setScale(animatedYideoScale);
// Play the video // Play the video
@ -258,11 +277,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterYHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterYHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Slant Right',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Slant Right',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -271,7 +290,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterYHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 - 10, customHeight / 2 + letterYHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slant Tail',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slant Tail',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -283,8 +302,6 @@ let scoreTotal = 0; let isDrawing = false;
let firstDragStartPoint = { x: 0, y: 0 }; let firstDragStartPoint = { x: 0, y: 0 };
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -327,7 +344,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -344,32 +361,15 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
function update() { function update() {
@ -377,3 +377,40 @@ function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -0,0 +1,413 @@
---
import Layout from "../../layouts/Layout.astro";
---
<Layout title="Guided Letter Tracing Game">
<main>
<div>
</div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main>
</Layout>
<script src="/saveGameData.js" is:inline></script>
<script is:inline>
const isMobile = window.innerWidth <= 768;
const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4,
width: isMobile ? window.innerWidth : window.innerWidth / 2,
height: window.innerHeight / 2,
};
const config = {
type: Phaser.AUTO,
width: window.innerWidth,
height: window.innerHeight,
backgroundColor: 0xFFFFFF,
scale: {
mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
},
scene: {
preload: preload,
create: create,
update: update
}
};
// backgroundImage.png
const game = new Phaser.Game(config);
const customWidth = window.innerWidth;
const customHeight = window.innerHeight;
let firstLayer, secondLayer, thirdLayer;
let graphics;
let animatedLetter;
let scoreTotal = 0; let isDrawing = false;
let formattedDateTime;
let gameStartTime = "start time here";
// let x = 100;
// // Use x
// console.log(x);
if(isMobile){
cloudeSize = 200;
cloudHeight = 340;
canvasScale = 0.14
canvasHeight = 35;
letterHeight = 70;
letterScale = 0.92;
backgroundScale = 0.8;
sunScale = 0.1;
sunScalePlus = 0.15;
sunWidth = 70;
sunHeight = 70;
animatedZHeight = 35;
animatedZScale = 0.65;
helpButtonHeight = customHeight / 1.1;
helpButtonWidth = customWidth / 2 + 10;
startButtonHeight = customHeight / 1.1;
startButtonWidth = customWidth / 2 - 100;
submitWidth = customWidth / 2 - 100;
submitHeight = customHeight / 1.1;
noticeWidth = window.innerWidth * 0.5 - 100;
noticeHeight = window.innerHeight * 0.38;
} else{
cloudeSize = 500;
cloudHeight = 250;
canvasScale = 0.195;
canvasHeight = 20;
letterHeight = 50;
letterScale = 1;
backgroundScale = 1;
sunScale = 0.2;
sunScalePlus = 0.25;
sunWidth = 200;
sunHeight = 100;
animatedZHeight = 20;
animatedZScale = 0.73;
helpButtonHeight = customHeight / 2 + 40;
helpButtonWidth = customWidth / 1.32;
startButtonHeight = customHeight / 2 - 20;
startButtonWidth = customWidth / 1.32;
submitWidth = customWidth / 1.32;
submitHeight = customHeight / 2 - 20;
noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32;
};
window.onload = function() {
currentDate = new Date();
formattedDateTime = currentDate.toLocaleString();
// console.log("Page loaded on: " + formattedDateTime);
};
function preload() {
this.load.video('animatedZ', '/assets/animated-letter/capital_z.mp4');
this.load.svg('letterZ', '/assets/capital-letter/z.svg');
this.load.svg('layer1', '/assets/capital-letter/z_l1.svg');
this.load.svg('layer2', '/assets/capital-letter/z_l2.svg');
this.load.svg('layer3', '/assets/capital-letter/z_l3.svg');
this.load.audio('audioOne', '/assets/audio/slide.mp3');
this.load.audio('audioTwo', '/assets/audio/slant.mp3');
this.load.image('topLogo', '/assets/top_logo.svg');
this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image('sun', '/assets/sun.png');
this.load.image('bgMobile', '/assets/bgMobile.png');
this.load.image('canvasStand', '/assets/stand2.png');
}
function create() {
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked');
submitButton.setVisible(false);
// windowLoad();
submitUserData(this);
})
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : Z", { font: '700 40px quicksand', fill: '#05b3a4', });
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterZ').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterZ').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedZ').setDepth(2); canvasStand
firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const width = customWidth; // Set your desired width
const height = customHeight;
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(
customWidth / 2 - width / 2,
50, // Offset the rectangle to start 150px from the top
width,
height
);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0);
animatedLetter.play(true);
graphics.setVisible(false);
firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button
hideButton.setVisible(true); // Show the "Hide" button
animatedLetter.setVisible(true);
});
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2;
const baseFontSize = 24;
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize;
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : Z', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedZHeight, 'animatedZ').setDepth(2).setScale(animatedZScale);
// Play the video
// animatedLetter.play();
animatedLetter.setVisible(false);
// You can set additional properties for the video, such as loop and mute:
animatedLetter.setLoop(true); // Loop the video
animatedLetter.setMute(false); // Unmute the video
animatedLetter.on('complete', function () {
// add function after end video;
});
let textX, textY;
firstLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Slide',{ font: '700 40px quicksand', fill: '#05b3a4'});
const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play();
firstLayer.setDepth(1);
firstLayer.setAlpha(0.5);
firstLayer.setInteractive({ draggable: true });
secondLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slant',{ font: '700 40px quicksand', fill: '#05b3a4'});
const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false);
secondLayer.setDepth(1);
secondLayer.setAlpha(0.5);
secondLayer.setInteractive({ draggable: true });
secondLayer.setVisible(false);
thirdLayer = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const thirdTextLayer = this.add.text(textX, textY, '3. Slide', { font: '700 40px quicksand', fill: '#05b3a4'});
const audioThreeAudio = this.sound.add('audioOne');
thirdTextLayer.setVisible(false);
thirdLayer.setDepth(1.1);
// thirdLayer.setScale(1.15);
thirdLayer.setAlpha(0.5);
thirdLayer.setInteractive({ draggable: true });
thirdLayer.setVisible(false);
// Add these variables to keep track of start points
let firstDragStartPoint = { x: 0, y: 0 };
let secondDragStartPoint = { x: 0, y: 0 };
let thirdDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x;
firstDragStartPoint.y = pointer.y;
});
firstLayer.on('drag', (pointer) => {
const distance = Phaser.Math.Distance.Between(firstDragStartPoint.x, firstDragStartPoint.y, pointer.x, pointer.y);
if (distance >= 100) {
firstTextLayer.setVisible(false);
secondTextLayer.setVisible(true);
audioTwoAudio.play();
secondLayer.setVisible(true);
firstLayer.setAlpha(1);
secondLayer.setAlpha(0.5);
thirdLayer.setAlpha(0.5);
} else {
firstLayer.setAlpha(0.5);
}
});
secondLayer.on('dragstart', (pointer) => {
secondDragStartPoint.x = pointer.x;
secondDragStartPoint.y = pointer.y;
});
secondLayer.on('drag', (pointer) => {
const distance = Phaser.Math.Distance.Between(secondDragStartPoint.x, secondDragStartPoint.y, pointer.x, pointer.y);
if (distance >= 100) {
secondTextLayer.setVisible(false);
thirdTextLayer.setVisible(true);
audioThreeAudio.play();
thirdLayer.setVisible(true);
secondLayer.setAlpha(1);
thirdLayer.setAlpha(0.5);
} else {
secondLayer.setAlpha(0.5);
}
});
// Add this code for thirdLayer
thirdLayer.on('dragstart', (pointer) => {
thirdDragStartPoint.x = pointer.x;
thirdDragStartPoint.y = pointer.y;
});
thirdLayer.on('drag', (pointer) => {
const distance = Phaser.Math.Distance.Between(thirdDragStartPoint.x, thirdDragStartPoint.y, pointer.x, pointer.y);
if (distance >= 100) {
thirdLayer.setAlpha(1);
thirdTextLayer.setVisible(false);
} else {
thirdLayer.setAlpha(0.5);
}
});
graphics = this.add.graphics();
graphics.setMask(mask);
graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) {
isDrawing = true;
graphics.moveTo(pointer.x, pointer.y);
// console.log("Start Position", pointer.x, pointer.y)
});
this.input.on('pointerup', function () {
isDrawing = false;
});
this.input.on('pointermove', function (pointer) {
if (!isDrawing) return;
graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath();
});let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => {
audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true);
animatedLetter.setVisible(false);
firstScreen.setVisible(false);
graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
})
}
function update() {
}
</script>

View File

@ -3,14 +3,77 @@ import Layout from "../../layouts/Layout.astro";
--- ---
<Layout title="Guided Letter Tracing Game"> <Layout title="Guided Letter Tracing Game">
<main> <main>
<div> <div id="blurDisplay" class="w-full min-h-screen absolute backdrop-blur-[5px] z-50">
<div class="flex justify-center items-center h-screen ">
<button id="beforeStartBtn" class="bg-[#0348A8] px-10 py-2 rounded-[4px] text-[#FFFFFF] text-[32px] font-[700]">Start</button>
</div>
</div>
<div id="parentMainContainer" class="hidden">
<div id="loadingMainContainer" class="w-full h-screen bg-[#00000070] absolute z-10" style="display: none;">
<div id="loadingState" style="display: none;" class="bg-white flex text-[#000] absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] items-center space-y-2 w-full px-6 py-16"></div>
</div>
<div id="scoreBoard" class="z-10 w-full h-screen bg-[#00000070] absolute" style="display: none;">
<div class="flex absolute left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 max-w-lg flex-col rounded-[8px] bg-white space-y-2 w-full p-6" >
<div class="flex flex-row space-x-4 items-center justify-center">
<div id="star-container"></div>
</div>
<div class="flex flex-row" style="margin-top: 15px; margin-bottom: 15px;">
<img class="z-10" src="/assets/animate-clipart.gif" alt="" style="width: 90.21px; height: 86.24px;" />
<p class="text-[#0348A8] text-[12px] font-[700] p-6 rounded-[10px] -ml-[10px]" style="background: linear-gradient(270.05deg, #FFFFFF 4.67%, #DAEAFF 99.61%);">Well done! <span id="countStar"></span> stars for your effort! <br> Keep pushing, youve got this!</p>
</div>
<div class="flex flex-col w-full max-w-sm items-center justify-center mx-auto gap-3">
<button onclick="history.back();" class="rounded-[4px] bg-[#0348A8] text-[#FFF] text-[12px] font-[700] p-2.5 w-full border-[1px] border-[#0348A8]">Wow, Lets Go</button>
<button class="border-[1px] border-[#0348A8] p-2.5 rounded-[4px] text-[#0348A8] w-full">Try Again</button>
</div>
</div>
</div>
<div class="clip-art-container absolute bottom-10 right-10" id="bottomAnimateClipart">
<div class="flex flex-row z-50 place-items-end clip-art">
<img src="/assets/clip-art-with-hand.svg" alt="Clip Art" class="">
<div class="relative bg-yellow-500 rounded-[4px] -ml-[10px]" style="background: linear-gradient(74.79deg, #E8EBFF 4.63%, #DDC9F1 97.93%); height: 200px; box-shadow: 0px 4px 8px 3px #CAD1F5;">
<img src="/assets/svg/bg-star.svg" alt="Left Star" class="absolute left-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<img src="/assets/svg/bg-star.svg" alt="Right Star" class="absolute right-0 top-1/4 transform -translate-y-1/2 w-12 h-12">
<!-- Content -->
<div class="flex flex-col space-y-3 px-10 py-10 w-[348px] h-[187px] ">
<p class="text-center text-[14px] font-[600] text-[#394FC0]">Want to find how much stars youve earned?</p>
<button class="text-[12px] font-[700] text-white bg-[#394FC0] rounded-[4px] w-full py-2.5" onclick="calculateFromAI();" >Ask to Beanie</button>
<a href="" class="text-center text-[12px] font-[600] text-[#394FC0] underline decoration-2 underline-offset-[4px]">Skip</a>
</div>
</div>
</div>
</div>
<div id="gallerySliderId" class="hidden p-2 z-10 absolute inset-0 bg-black w-full h-screen bg-opacity-50 flex justify-center items-center">
<div class="w-full max-w-6xl bg-white rounded-lg">
<div class="flex justify-between p-3">
<p class="text-[19px] font-[700]">Attempt 2</p>
<button onclick="closeGallery();"> <img src="/assets/svg/crossIcon.svg"></button>
</div>
<div class="relative w-full aspect-video overflow-hidden rounded-b-lg shadow-lg">
<img id="slideImage" src="" alt="" class="slide active w-full h-full aspect-video transition-transform duration-500" />
<button id="prevButton" class="flex justify-center items-center w-[40px] h-[40px] absolute left-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/leftIcon.svg" alt=""></button>
<button id="nextButton" class="flex justify-center items-center w-[40px] h-[40px] absolute right-4 top-1/2 transform -translate-y-1/2 bg-[#F4F7FF] text-gray-800 p-2 rounded-full shadow-lg hover:bg-gray-100 transition"><img src="/assets/svg/rightIcon.svg" alt=""></button>
<div id="slidetInfo" class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 p-2 text-center text-white">
<h2 class="text-lg font-bold" id="imageTitle">Image Title</h2>
<p class="text-sm" id="imageDescription">Description goes here.</p>
</div>
</div>
</div>
</div>
</div> </div>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script> <script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main> </main>
</Layout> </Layout>
<script src="/saveGameData.js" is:inline></script> <script src="/saveGameAI.js" is:inline></script>
<script is:inline> <script is:inline>
function showAnimation() {
const clipArt = document.querySelector('.clip-art');
clipArt.classList.add('show');
}
const isMobile = window.innerWidth <= 768; const isMobile = window.innerWidth <= 768;
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
const drawingZone = { const drawingZone = {
x: isMobile ? 0 : window.innerWidth / 4, x: isMobile ? 0 : window.innerWidth / 4,
y: window.innerHeight / 4, y: window.innerHeight / 4,
@ -22,7 +85,7 @@ import Layout from "../../layouts/Layout.astro";
type: Phaser.AUTO, type: Phaser.AUTO,
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,
backgroundColor: 0xFFFFFF, backgroundColor: 0xebedea,
scale: { scale: {
mode: Phaser.Scale.FIT, mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_HORIZONTALLY, autoCenter: Phaser.Scale.CENTER_HORIZONTALLY,
@ -40,9 +103,11 @@ import Layout from "../../layouts/Layout.astro";
let firstLayer, secondLayer, thirdLayer; let firstLayer, secondLayer, thirdLayer;
let graphics; let graphics;
let animatedLetter; let animatedLetter;
let scoreTotal = 0; let isDrawing = false; let scoreTotal = 0;
let isDrawing = false;
let formattedDateTime; let formattedDateTime;
let gameStartTime = "start time here"; let gameStartTime = "start time here";
let demoButton;
// let x = 100; // let x = 100;
// // Use x // // Use x
@ -97,6 +162,28 @@ let scoreTotal = 0; let isDrawing = false;
noticeWidth = window.innerWidth * 0.5 - 120; noticeWidth = window.innerWidth * 0.5 - 120;
noticeHeight = window.innerHeight * 0.32; noticeHeight = window.innerHeight * 0.32;
}; };
if(isMobile){
topLogoWidth = 4.5;
muteIconWidth = 1.65;
resetIconWidth = 1.40;
tickIconWidth = 1.21;
cancelIconWidth = 1.08;
galleryIconWidth = 2;
}else if(isTab){
topLogoWidth = 4.5;
muteIconWidth = 1.6;
resetIconWidth = 1.43;
tickIconWidth = 1.29;
cancelIconWidth = 1.18;
galleryIconWidth = 1.81;
} else{
topLogoWidth = 6;
muteIconWidth = 1.3;
resetIconWidth = 1.26;
tickIconWidth = 1.222;
cancelIconWidth = 1.185;
galleryIconWidth = 1.345;
}
window.onload = function() { window.onload = function() {
currentDate = new Date(); currentDate = new Date();
formattedDateTime = currentDate.toLocaleString(); formattedDateTime = currentDate.toLocaleString();
@ -114,139 +201,71 @@ let scoreTotal = 0; let isDrawing = false;
this.load.svg('succesImage', '/assets/svg/tick.svg'); this.load.svg('succesImage', '/assets/svg/tick.svg');
this.load.svg('hintImage', '/assets/svg/hint.svg'); this.load.svg('hintImage', '/assets/svg/hint.svg');
this.load.svg('handPointer', '/assets/svg/hand.svg'); this.load.svg('handPointer', '/assets/svg/hand.svg');
this.load.image('backgroundImage', '/assets/bg6.png');
this.load.image('cloud', '/assets/cloud.png');
this.load.image('canvas', '/assets/canvas4.png');
this.load.image("tickIcon", '/assets/svg/tick2.svg');
this.load.image('sun', '/assets/sun.png'); this.load.image("muteIcon", '/assets/svg/mute.svg');
this.load.image('bgMobile', '/assets/bgMobile.png'); this.load.image("cancelIcon", '/assets/svg/cancel.svg');
this.load.image('canvasStand', '/assets/stand2.png'); this.load.image("resetIcon", '/assets/svg/reset.svg');
this.load.svg('helpIcons', '/assets/svg/help_icon.svg');
} }
function create() { function create() {
this.add.image(customWidth / topLogoWidth, 30, "topLogo");
muteIcon = this.add.image(customWidth / muteIconWidth, 30, "muteIcon");
retryButton = this.add.image(customWidth / resetIconWidth, 30, "resetIcon");
submitButton = this.add.image(customWidth / tickIconWidth, 30, "tickIcon");
demoButton = this.add.image(customWidth / galleryIconWidth, 30, "helpIcons");
submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false); submitNotic = this.add.text(window.innerWidth / 2 - noticeWidth, window.innerHeight / 2 - noticeHeight, 'Submitted Successfully', {font: '600 20px Quicksand', fill: '#FFFFFF', backgroundColor: '#004aad',padding: {left: 20,right: 20,top: 10,bottom: 10}}).setDepth(3).setVisible(false);
cancelIcon = this.add.image(customWidth / cancelIconWidth, 30, "cancelIcon");
const borderBottom = this.add.graphics();
const x = 0; const y = 54;
const lineWidth = window.innerWidth;
borderBottom.lineStyle(1, 0x0348A8);
borderBottom.setAlpha(0.2);
borderBottom.beginPath();
borderBottom.moveTo(x, y);
borderBottom.lineTo(x + lineWidth, y);
borderBottom.strokePath();
submitButton = this.add.text(submitWidth, submitHeight, "Submit", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 10, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
});
submitButton.setVisible(false);
submitButton.setInteractive().on('pointerdown', () => { submitButton.setInteractive().on('pointerdown', () => {
// console.log('Clicked'); // console.log('Clicked');
submitButton.setVisible(false);
// windowLoad(); // windowLoad();
submitUserData(this); submitUserData(this);
showAnimation();
parentMainContainer.classList.remove('hidden');
}) })
this.add.image(customWidth / 2 * 1.6 - 0.5, 50, 'topLogo');
this.add.text(customWidth / 10, 20, "Letter : z", { font: '700 40px quicksand', fill: '#05b3a4', });
const cloud = this.add.tileSprite(customWidth / 2, customHeight / 2 - cloudHeight, customWidth, cloudeSize, 'cloud').setAlpha(0.9);
cloud.setDepth(-1.8);
const scrollSpeed = 0.5;
this.time.addEvent({
loop: true,
callback: () => {
cloud.tilePositionX += scrollSpeed;
},
delay: 16, // Adjust the delay for the desired scrolling speed
});
const sun = this.add.sprite(customWidth - sunWidth, sunHeight, 'sun').setScale(sunScale).setDepth(-1.9);
const scaleFactor = sunScalePlus; // Scale factor (2 means double the size)
const duration = 3000; // Duration of the animation in milliseconds
// Create a scaling tween
this.tweens.add({
targets: sun,
scaleX: scaleFactor,
scaleY: scaleFactor,
duration: duration,
ease: 'Linear',
yoyo: true, // Makes the animation play in reverse
repeat: -1 // Repeat indefinitely
});
const backgroundImages = this.add.image(customWidth / 2, customHeight /2, 'backgroundImage').setDepth(-2).setScale(backgroundScale);
this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'letterZ').setAlpha(0.2).setDepth(0.5).setScale(letterScale); this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'letterZ').setAlpha(0.2).setDepth(0.5).setScale(letterScale);
const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterZ').setDepth(2).setScale(letterScale); const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'letterZ').setDepth(2).setScale(letterScale);
// const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedZ').setDepth(2); canvasStand // const firstScreen = this.add.image(customWidth / 2, customHeight / 2 + letterHeight, 'animatedZ').setDepth(2); canvasStand
firstScreen.setVisible(false); firstScreen.setVisible(false);
// this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
const canvas = this.add.image(customWidth / 2, customHeight / 2 + canvasHeight, 'canvas').setScale(canvasScale);
// Set up a mask for the drawing area based on the canvas dimensions
const maskGraphics = this.make.graphics()
maskGraphics.fillRect(customWidth / 2 - (canvas.width * canvasScale) / 2, customHeight / 2 + canvasHeight - (canvas.height * canvasScale) / 2, canvas.width * canvasScale, canvas.height * canvasScale);
const mask = maskGraphics.createGeometryMask();
let hideButton = this.add.text(helpButtonWidth, helpButtonHeight, "Let`s Do", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
hideButton.setInteractive().on('pointerdown', () => {
animatedLetter.stop();
isDemoButtonClicked = false;
firstScreen.setVisible(false);
hideButton.setVisible(false); // Hide the "Hide" button
demoButton.setVisible(true); // Show the "Demo" button
graphics.setVisible(true);
animatedLetter.setVisible(false);
});
hideButton.setVisible(false);
let demoButton = this.add.text(helpButtonWidth, helpButtonHeight, "Demo", {
font: '900 24px quicksand',
fill: '#05b3a4',
backgroundColor: '#7c4c23',
padding: { x: 20, y: 10 },
borderRadius: '15px', // Border radius
shadow: {
offsetX: 2, // X offset for the shadow
offsetY: 2, // Y offset for the shadow
color: '#000', // Shadow color
blur: 5, // Shadow blur
fill: true // Apply shadow to fill (background color)
}
});
demoButton.setInteractive().on('pointerdown', () => { demoButton.setInteractive().on('pointerdown', () => {
animatedLetter.setCurrentTime(0); animatedLetter.setCurrentTime(0);
animatedLetter.play(true); animatedLetter.play(true);
graphics.setVisible(false); graphics.setVisible(false);
firstScreen.setVisible(true); firstScreen.setVisible(true);
demoButton.setVisible(false); // Hide the "Demo" button if(animatedLetter.visible){
hideButton.setVisible(true); // Show the "Hide" button animatedLetter.setVisible(false);
graphics.setVisible(true);
firstScreen.setVisible(false);
} else{
graphics.setVisible(false);
animatedLetter.setVisible(true); animatedLetter.setVisible(true);
}); firstScreen.setVisible(true);
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2; }
const baseFontSize = 24; })
const responsiveFontSize = (window.innerWidth / 480) * baseFontSize;
const descrptText = this.add.text(screenCenterX, 90, 'Let`s learn how to write letter : z', { font: `${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5); retryButton.setInteractive().on('pointerdown', () => {
window.location.reload();
})
const maskGraphics = this.make.graphics();
maskGraphics.fillRect(customWidth / 2 - customWidth / 2, 55, customWidth, customHeight);
const mask = maskGraphics.createGeometryMask();
let responsiveFontSize = isMobile ? 16 : 32;
this.add.text(window.innerWidth / 2, 80, 'Letter: z', {fill: '#60C6CB', font: `900 ${responsiveFontSize}px quicksand`}).setOrigin(0.5);
const descrptText = this.add.text(window.innerWidth/2, 125, 'Let`s learn how to write letter : z', { font: `900 ${responsiveFontSize}px quicksand`, fill: '#7c4c23', fontWeight : 'bold'}).setOrigin(0.5);
animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedZHeight, 'animatedZ').setDepth(2).setScale(animatedZScale); animatedLetter = this.add.video(customWidth / 2 , customHeight / 2 + animatedZHeight, 'animatedZ').setDepth(2).setScale(animatedZScale);
// Play the video // Play the video
// animatedLetter.play(); // animatedLetter.play();
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
@ -259,11 +278,11 @@ let scoreTotal = 0; let isDrawing = false;
}); });
let textX, textY; let textX, textY;
let stepTextSize = isMobile ? 12 : 16;
firstLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale); firstLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer1').setScale(letterScale);
textX = isMobile ? customWidth / 4 + 40 : customWidth * 0.75; textX = isMobile ? customWidth / 4 + 40 : customWidth * 0.75;
textY = isMobile ? customHeight / 5 : customHeight / 2.4; textY = isMobile ? customHeight / 5 : customHeight / 2.4;
const firstTextLayer = this.add.text(textX, textY, '1. Slide',{ font: '700 40px quicksand', fill: '#05b3a4'}); const firstTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '1. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioOneAudio = this.sound.add('audioOne'); const audioOneAudio = this.sound.add('audioOne');
// audioOneAudio.play(); // audioOneAudio.play();
firstLayer.setDepth(1); firstLayer.setDepth(1);
@ -272,7 +291,7 @@ let scoreTotal = 0; let isDrawing = false;
secondLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale); secondLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer2').setScale(letterScale);
textX = isMobile ? customWidth / 4 : customWidth * 0.75; textX = isMobile ? customWidth / 4 : customWidth * 0.75;
const secondTextLayer = this.add.text(textX, textY, '2. Slant',{ font: '700 40px quicksand', fill: '#05b3a4'}); const secondTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '2. Slant',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioTwoAudio = this.sound.add('audioTwo'); const audioTwoAudio = this.sound.add('audioTwo');
secondTextLayer.setVisible(false); secondTextLayer.setVisible(false);
secondLayer.setDepth(1); secondLayer.setDepth(1);
@ -282,7 +301,7 @@ let scoreTotal = 0; let isDrawing = false;
thirdLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale); thirdLayer = this.add.image(customWidth / 2 - 20, customHeight / 2 + letterHeight, 'layer3').setScale(letterScale);
textX = isMobile ? customWidth / 3 : customWidth * 0.75; textX = isMobile ? customWidth / 3 : customWidth * 0.75;
const thirdTextLayer = this.add.text(textX, textY, '3. Slide', { font: '700 40px quicksand', fill: '#05b3a4'}); const thirdTextLayer = this.add.text(window.innerWidth / 2, window.innerHeight / 1.2, '3. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioThreeAudio = this.sound.add('audioOne'); const audioThreeAudio = this.sound.add('audioOne');
thirdTextLayer.setVisible(false); thirdTextLayer.setVisible(false);
thirdLayer.setDepth(1.1); thirdLayer.setDepth(1.1);
@ -296,8 +315,6 @@ let scoreTotal = 0; let isDrawing = false;
let secondDragStartPoint = { x: 0, y: 0 }; let secondDragStartPoint = { x: 0, y: 0 };
let thirdDragStartPoint = { x: 0, y: 0 }; let thirdDragStartPoint = { x: 0, y: 0 };
// ...
// Add this code for firstLayer // Add this code for firstLayer
firstLayer.on('dragstart', (pointer) => { firstLayer.on('dragstart', (pointer) => {
firstDragStartPoint.x = pointer.x; firstDragStartPoint.x = pointer.x;
@ -359,7 +376,7 @@ let scoreTotal = 0; let isDrawing = false;
graphics = this.add.graphics(); graphics = this.add.graphics();
graphics.setMask(mask); graphics.setMask(mask);
graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha) graphics.lineStyle(15, 0xFFFFFF, 2).setDepth(2); // Set line style (width, color, alpha)
this.input.on('pointerdown', function (pointer) { this.input.on('pointerdown', function (pointer) {
isDrawing = true; isDrawing = true;
@ -377,34 +394,54 @@ let scoreTotal = 0; let isDrawing = false;
graphics.lineTo(pointer.x, pointer.y); graphics.lineTo(pointer.x, pointer.y);
graphics.strokePath(); graphics.strokePath();
}); });
let startButton = this.add.text(startButtonWidth, startButtonHeight, "Start", {
font: '900 24px Quicksand',
fill: '#05b3a4',
backgroundColor : '#7c4c23',
padding: {x: 20, y: 10},
shadow: {
offsetX : 2,
offsetY : 2,
color: '#000',
blur: 5,
fill: true
}
})
firstTextLayer.setVisible(false); firstTextLayer.setVisible(false);
startButton.setInteractive().on('pointerdown', () => { document.getElementById('beforeStartBtn').addEventListener('click', function() {
document.getElementById('blurDisplay').classList.add('hidden');
audioOneAudio.play(); audioOneAudio.play();
submitButton.setVisible(true);
firstTextLayer.setVisible(true); firstTextLayer.setVisible(true);
animatedLetter.setVisible(false); animatedLetter.setVisible(false);
firstScreen.setVisible(false); firstScreen.setVisible(false);
graphics.setVisible(true); graphics.setVisible(true);
hideButton.setVisible(false);
demoButton.setVisible(true);
startButton.setVisible(false);
}) })
} }
function update() { function update() {
} }
</script> </script>
<style>
.clear-button {
background-color: blue;
}
/* Animation styles */
@keyframes slideInUp {
0% {
opacity: 0;
transform: translateY(100%); /* Start below the viewport */
}
100% {
opacity: 1;
transform: translateY(0); /* End at its original position */
}
}
.clip-art-container {
overflow: hidden; /* Prevents overflow during the animation */
}
.clip-art {
transform: translateX(100%); /* Initially off-screen to the right */
opacity: 0; /* Initially hidden */
transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out; /* Smooth transition */
}
.clip-art.show {
transform: translateX(0); /* Move the image into view */
opacity: 1; /* Fade in */
}
.slide{
display: none;
}
.active{
display: block;
}
</style>

View File

@ -22,7 +22,7 @@ import Layout from "../../layouts/Layout.astro";
<div class="container mx-auto px-4"> <div class="container mx-auto px-4">
<!-- <div class="flex flex-col"> <!-- <div class="flex flex-col">
<p id="LearningArea"></p> <p id="LearningArea"></p>
<p id="LearningSubArea_copy"></p> <p id="LearningSubArea"></p>
</div> --> </div> -->
<p class="sm:text-2xl md:text-3xl lg:text-4xl text-center font-[600] text-[#60C6CB] my-4 select-none" id="gameDescription"></p> <p class="sm:text-2xl md:text-3xl lg:text-4xl text-center font-[600] text-[#60C6CB] my-4 select-none" id="gameDescription"></p>
<form id="contactForm"> <form id="contactForm">
@ -194,7 +194,7 @@ import Layout from "../../layouts/Layout.astro";
document.getElementById("label6").innerHTML = gameData.label6; document.getElementById("label6").innerHTML = gameData.label6;
} }
// document.getElementById('LearningArea').innerHTML = gameData.LearningArea; // document.getElementById('LearningArea').innerHTML = gameData.LearningArea;
// document.getElementById('LearningSubArea_copy').innerHTML = gameData.LearningSubArea_copy; // document.getElementById('LearningSubArea').innerHTML = gameData.LearningSubArea;
const assetsURL = 'https://game-du.teachertrainingkolkata.in/assets/'; const assetsURL = 'https://game-du.teachertrainingkolkata.in/assets/';
for (let i = 1; i <= 6; i++) { for (let i = 1; i <= 6; i++) {
@ -408,7 +408,7 @@ import Layout from "../../layouts/Layout.astro";
color: #7C4C23; color: #7C4C23;
padding-top: 10px; padding-top: 10px;
} }
#LearningArea, #LearningSubArea_copy{ #LearningArea, #LearningSubArea{
font-size: 20px; font-size: 20px;
color: #7C4C23; color: #7C4C23;
font-weight: bold; font-weight: bold;

View File

@ -22,7 +22,7 @@ import Layout from "../../layouts/Layout.astro";
<div class="container mx-auto px-4"> <div class="container mx-auto px-4">
<!-- <div class="flex flex-col"> <!-- <div class="flex flex-col">
<p id="LearningArea"></p> <p id="LearningArea"></p>
<p id="LearningSubArea_copy"></p> <p id="LearningSubArea"></p>
</div> --> </div> -->
<p class="sm:text-2xl md:text-3xl lg:text-4xl text-center font-[600] text-[#60C6CB] my-4 select-none" id="gameDescription"></p> <p class="sm:text-2xl md:text-3xl lg:text-4xl text-center font-[600] text-[#60C6CB] my-4 select-none" id="gameDescription"></p>
<form id="contactForm" class="flex flex-col justify-center"> <form id="contactForm" class="flex flex-col justify-center">
@ -226,7 +226,7 @@ import Layout from "../../layouts/Layout.astro";
document.getElementById("label9").innerHTML = gameData.label9; document.getElementById("label9").innerHTML = gameData.label9;
} }
// document.getElementById('LearningArea').innerHTML = gameData.LearningArea; // document.getElementById('LearningArea').innerHTML = gameData.LearningArea;
// document.getElementById('LearningSubArea_copy').innerHTML = gameData.LearningSubArea_copy; // document.getElementById('LearningSubArea').innerHTML = gameData.LearningSubArea;
const assetsURL = 'https://game-du.teachertrainingkolkata.in/assets/'; const assetsURL = 'https://game-du.teachertrainingkolkata.in/assets/';
for (let i = 1; i <= 9; i++) { for (let i = 1; i <= 9; i++) {
const imageId = `image${i}`; const imageId = `image${i}`;
@ -435,7 +435,7 @@ import Layout from "../../layouts/Layout.astro";
color: #7C4C23; color: #7C4C23;
padding-top: 10px; padding-top: 10px;
} }
#LearningArea, #LearningSubArea_copy{ #LearningArea, #LearningSubArea{
font-size: 20px; font-size: 20px;
color: #7C4C23; color: #7C4C23;
font-weight: bold; font-weight: bold;

View File

@ -152,7 +152,7 @@ import Layout from "../../layouts/Layout.astro";
document.getElementById("label6").innerHTML = gameData.label6; document.getElementById("label6").innerHTML = gameData.label6;
} }
// document.getElementById('LearningArea').innerHTML = gameData.LearningArea; // document.getElementById('LearningArea').innerHTML = gameData.LearningArea;
// document.getElementById('LearningSubArea_copy').innerHTML = gameData.LearningSubArea_copy; // document.getElementById('LearningSubArea').innerHTML = gameData.LearningSubArea;
const assetsURL = 'https://game-du.teachertrainingkolkata.in/assets/'; const assetsURL = 'https://game-du.teachertrainingkolkata.in/assets/';
for (let i = 1; i <= 6; i++) { for (let i = 1; i <= 6; i++) {
@ -396,7 +396,7 @@ import Layout from "../../layouts/Layout.astro";
color: #7C4C23; color: #7C4C23;
padding-top: 10px; padding-top: 10px;
} }
#LearningArea, #LearningSubArea_copy{ #LearningArea, #LearningSubArea{
font-size: 20px; font-size: 20px;
color: #7C4C23; color: #7C4C23;
font-weight: bold; font-weight: bold;

View File

@ -22,7 +22,7 @@ import Layout from "../../layouts/Layout.astro";
<div class="container mx-auto px-4"> <div class="container mx-auto px-4">
<!-- <div class="flex flex-col"> <!-- <div class="flex flex-col">
<p id="LearningArea"></p> <p id="LearningArea"></p>
<p id="LearningSubArea_copy"></p> <p id="LearningSubArea"></p>
</div> --> </div> -->
<p class="sm:text-2xl md:text-3xl lg:text-4xl text-center font-[600] text-[#60C6CB] my-4 select-none" id="gameDescription"></p> <p class="sm:text-2xl md:text-3xl lg:text-4xl text-center font-[600] text-[#60C6CB] my-4 select-none" id="gameDescription"></p>
<form id="contactForm" class="flex flex-col justify-center"> <form id="contactForm" class="flex flex-col justify-center">
@ -223,7 +223,7 @@ import Layout from "../../layouts/Layout.astro";
document.getElementById("label9").innerHTML = gameData.label9; document.getElementById("label9").innerHTML = gameData.label9;
} }
// document.getElementById('LearningArea').innerHTML = gameData.LearningArea; // document.getElementById('LearningArea').innerHTML = gameData.LearningArea;
// document.getElementById('LearningSubArea_copy').innerHTML = gameData.LearningSubArea_copy; // document.getElementById('LearningSubArea').innerHTML = gameData.LearningSubArea;
const assetsURL = 'https://game-du.teachertrainingkolkata.in/assets/'; const assetsURL = 'https://game-du.teachertrainingkolkata.in/assets/';
for (let i = 1; i <= 9; i++) { for (let i = 1; i <= 9; i++) {
const imageId = `image${i}`; const imageId = `image${i}`;
@ -437,7 +437,7 @@ import Layout from "../../layouts/Layout.astro";
color: #7C4C23; color: #7C4C23;
padding-top: 10px; padding-top: 10px;
} }
#LearningArea, #LearningSubArea_copy{ #LearningArea, #LearningSubArea{
font-size: 20px; font-size: 20px;
color: #7C4C23; color: #7C4C23;
font-weight: bold; font-weight: bold;