phaser-game-bs/src/pages/guided-tracing/A.astro

472 lines
18 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>
<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>
<script is:inline src="/assets/js/phaser_3.60.0.js"></script>
</main>
</Layout>
<script src="/saveTracingGameData.js" is:inline></script>
<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 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 maxScore;
let galleryButton;
if(isMobile){
cloudeSize = 200;
cloudHeight = 340;
canvasScale = 0.14
canvasHeight = 35;
letterHeight = 70;
letterScale = 1.2;
backgroundScale = 0.8;
sunScale = 0.1;
sunScalePlus = 0.15;
sunWidth = 70;
sunHeight = 70;
animatedAHeight = 35;
animatedAScale = 0.8;
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.2;
backgroundScale = 1;
sunScale = 0.2;
sunScalePlus = 0.25;
sunWidth = 200;
sunHeight = 100;
animatedAHeight = 0;
animatedAScale = 0.8;
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('animatedA', '/assets/animated-letter/capital_a.mp4');
this.load.svg('letterA', '/assets/capital-letter/a.svg');
this.load.svg('layer1', '/assets/capital-letter/a_l1.svg');
this.load.svg('layer2', '/assets/capital-letter/a_l2.svg');
this.load.svg('layer3', '/assets/capital-letter/a_l3.svg');
this.load.audio('audioOne', '/assets/audio/slant-left.mp3');
this.load.audio('audioTwo', '/assets/audio/slant-right.mp3');
this.load.audio('audioThree', '/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.svg('galleryIcons', '/assets/svg/gallery-icon.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");
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.setInteractive().on('pointerdown', () => {
// console.log('Clicked');
// windowLoad();
submitUserData(this);
showAnimation();
// parentMainContainer.classList.remove('hidden');
});
galleryButton.setInteractive().on('pointerdown', () => {
// parentMainContainer.classList.remove('hidden');
gallerySliderId.classList.remove('hidden');
});
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, 'animatedA').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, '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);
// 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;
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);
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. Slant Left',{ 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. Slant Right',{ 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. Slide',{ font: `600 ${stepTextSize}px quicksand`, fill: '#000000'}).setOrigin(0.5);
const audioThreeAudio = this.sound.add('audioThree');
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);
finalMessage.setVisible(true)
} 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 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>