458 lines
19 KiB
Plaintext
458 lines
19 KiB
Plaintext
---
|
||
import Layout from "../../layouts/Layout.astro";
|
||
---
|
||
<Layout title="Guided Letter Tracing Game">
|
||
<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 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, you’ve 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 you’ve 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>
|
||
<script is:inline src="/assets/js/phaser_3.60.0.js"></script>
|
||
</main>
|
||
</Layout>
|
||
<script src="/saveGameAI.js" is:inline></script>
|
||
<script is:inline>
|
||
function showAnimation() {
|
||
const clipArt = document.querySelector('.clip-art');
|
||
clipArt.classList.add('show');
|
||
}
|
||
const isMobile = window.innerWidth <= 768;
|
||
const isTab = window.innerWidth > 768 && window.innerWidth <= 1416;
|
||
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: 0xebedea,
|
||
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 demoButton;
|
||
// let x = 100;
|
||
|
||
// // Use x
|
||
// console.log(x);
|
||
|
||
if(isMobile){
|
||
cloudeSize = 200;
|
||
cloudHeight = 340;
|
||
canvasScale = 0.14
|
||
canvasHeight = 35;
|
||
letterHeight = 20;
|
||
letterScale = 1.2;
|
||
backgroundScale = 0.8;
|
||
sunScale = 0.1;
|
||
sunScalePlus = 0.15;
|
||
sunWidth = 70;
|
||
sunHeight = 70;
|
||
|
||
animated4Height = 35;
|
||
animated4Scale = 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 = 10;
|
||
letterScale = 1.3;
|
||
backgroundScale = 1;
|
||
sunScale = 0.2;
|
||
sunScalePlus = 0.25;
|
||
sunWidth = 200;
|
||
sunHeight = 100;
|
||
|
||
animated4Height = 20;
|
||
animated4Scale = 0.7;
|
||
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;
|
||
}
|
||
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() {
|
||
this.load.video('animated4', '/assets/animated-letter/number_4.mp4');
|
||
this.load.svg('number4', '/assets/numeric/n4.svg');
|
||
this.load.svg('layer1', '/assets/numeric/n4_l1.svg');
|
||
this.load.svg('layer2', '/assets/numeric/n4_l2.svg');
|
||
this.load.svg('layer3', '/assets/numeric/n4_l3.svg');
|
||
this.load.audio('audioOne', '/assets/audio/down.mp3');
|
||
this.load.audio('audioTwo', '/assets/audio/slide.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("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() {
|
||
|
||
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);
|
||
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.setInteractive().on('pointerdown', () => {
|
||
// console.log('Clicked');
|
||
submitButton.setVisible(false);
|
||
// windowLoad();
|
||
submitUserData(this);
|
||
showAnimation();
|
||
parentMainContainer.classList.remove('hidden');
|
||
})
|
||
|
||
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, 'animated4').setDepth(2); canvasStand
|
||
firstScreen.setVisible(false);
|
||
|
||
demoButton.setInteractive().on('pointerdown', () => {
|
||
animatedLetter.setCurrentTime(0);
|
||
animatedLetter.play(true);
|
||
graphics.setVisible(false);
|
||
firstScreen.setVisible(true);
|
||
if(animatedLetter.visible){
|
||
animatedLetter.setVisible(false);
|
||
graphics.setVisible(true);
|
||
firstScreen.setVisible(false);
|
||
} else{
|
||
graphics.setVisible(false);
|
||
animatedLetter.setVisible(true);
|
||
firstScreen.setVisible(true);
|
||
|
||
}
|
||
});
|
||
|
||
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: 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);
|
||
|
||
// 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;
|
||
let stepTextSize = isMobile ? 12 : 16;
|
||
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(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');
|
||
// 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(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');
|
||
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(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');
|
||
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 >= 70) {
|
||
|
||
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 >= 70) {
|
||
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.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();
|
||
});
|
||
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);
|
||
})
|
||
}
|
||
|
||
function update() {
|
||
}
|
||
|
||
</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> |