-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Control: Player Left(W and S)/mouse/touch | Player Right(โ and โ)/mouse/touch
+
+
+
+
+
+
+
+
-
-
-
-
-
+
\ No newline at end of file
diff --git a/07-Ping-Pong-Game/script.js b/07-Ping-Pong-Game/script.js
index 44b5ec0..a389eff 100644
--- a/07-Ping-Pong-Game/script.js
+++ b/07-Ping-Pong-Game/script.js
@@ -7,6 +7,7 @@ var pauseBtn = document.getElementById("pause-btn");
var restartBtn = document.getElementById("restart-btn");
var animationId;
var gameRunning = false;
+var ballColor = "#FFF";
startBtn.addEventListener("click", function () {
if (!gameRunning) {
@@ -33,8 +34,8 @@ addEventListener("load", (event) => {
var ballRadius = 10;
var ballX = canvas.width / 2;
var ballY = canvas.height / 2;
-var ballSpeedX = 5;
-var ballSpeedY = 5;
+var ballSpeedX = 4;
+var ballSpeedY = 4;
// Define paddle properties
var paddleHeight = 80;
@@ -148,9 +149,11 @@ function update() {
} else if (rightPlayerScore === maxScore) {
playerWin("Right player");
}
+
}
function playerWin(player) {
+ gameRunning = false;
var message = "Congratulations! " + player + " win!";
$("#message").text(message); // Set the message text
$("#message-modal").modal("show"); // Display the message modal
@@ -170,13 +173,13 @@ function draw() {
// Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
- ctx.fillStyle = "#FFF";
+ ctx.fillStyle = ballColor;
ctx.font = "15px Arial";
ctx.beginPath();
ctx.moveTo(canvas.width / 2, 0);
ctx.lineTo(canvas.width / 2, canvas.height);
- ctx.strokeStyle = "#FFF"; // Set line color to white
+ ctx.strokeStyle = ballColor; // Set line color to white
ctx.stroke();
ctx.closePath();
@@ -200,6 +203,25 @@ function draw() {
// Draw scores
ctx.fillText("Score: " + leftPlayerScore, 10, 20);
ctx.fillText("Score: " + rightPlayerScore, canvas.width - 70, 20);
+return;
+//debug
+ const lineHeight = 20;
+ const startY = canvas.height / 2 - (debugInfo.length * lineHeight) / 2;
+
+ ctx.save();
+ ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
+ ctx.fillRect(0, startY - 10, canvas.width, debugInfo.length * lineHeight + 20);
+
+ ctx.font = '16px Arial';
+ ctx.fillStyle = 'white';
+ ctx.textAlign = 'center';
+
+ debugInfo.forEach((info, index) => {
+ ctx.fillText(info, canvas.width / 2, startY + index * lineHeight);
+ });
+ drawDebugInfo();
+
+
}
// Game loop
@@ -212,3 +234,340 @@ function loop() {
$("#message-modal-close").on("click", function () {
document.location.reload();
});
+
+var downLock = false;
+function keyDown() {// pressed down arrow key
+ if (upLock) { keyUp(); }
+ if (downLock) {
+ var event = new KeyboardEvent('keyup', {
+ bubbles: true,
+ cancelable: true,
+ key: 'ArrowDown', // or any other key you want to simulate
+ keyCode: 40, // or any other key code you want to simulate
+ which: 40, // or any other key code you want to simulate
+ });
+ document.dispatchEvent(event);
+ downLock = false;
+ document.getElementById("down_arrow").style.transform = "scale(1)";
+ } else {
+ var event = new KeyboardEvent('keydown', {
+ bubbles: true,
+ cancelable: true,
+ key: 'ArrowDown', // or any other key you want to simulate
+ keyCode: 40, // or any other key code you want to simulate
+ which: 40, // or any other key code you want to simulate
+ });
+ document.dispatchEvent(event);
+ downLock = true;
+ document.getElementById("down_arrow").style.transform = "scale(0.9)";
+ }
+}
+
+var upLock = false;
+function keyUp() {// pressed up arrow key
+ if (downLock) { keyDown(); }
+ if (upLock) {
+ var event = new KeyboardEvent('keyup', {
+ bubbles: true,
+ cancelable: true,
+ key: 'ArrowUp', // or any other key you want to simulate
+ keyCode: 38, // or any other key code you want to simulate
+ which: 38, // or any other key code you want to simulate
+ });
+ document.dispatchEvent(event);
+ upLock = false;
+ document.getElementById("up_arrow").style.transform = "scale(1)";
+ } else {
+ var event = new KeyboardEvent('keydown', {
+ bubbles: true,
+ cancelable: true,
+ key: 'ArrowUp', // or any other key you want to simulate
+ keyCode: 38, // or any other key code you want to simulate
+ which: 38, // or any other key code you want to simulate
+ });
+ document.dispatchEvent(event);
+ upLock = true;
+ document.getElementById("up_arrow").style.transform = "scale(0.9)";
+ }
+}
+
+function keyLeft() {
+ keyW();
+}
+
+function keyRight() {// pressed right arrow key
+ keyS();
+}
+
+var wLock = false;
+function keyW() {// pressed w key
+ if (sLock) { keyS(); }
+ if (wLock) {
+ var event = new KeyboardEvent('keyup', {
+ bubbles: true,
+ cancelable: true,
+ key: 'w', // or any other key you want to simulate
+ keyCode: 87, // or any other key code you want to simulate
+ which: 87, // or any other key code you want to simulate
+ });
+ document.dispatchEvent(event);
+ wLock = false;
+ document.getElementById("left_arrow").style.transform = "scale(1)rotate(90deg)";
+ } else {
+ var event = new KeyboardEvent('keydown', {
+ bubbles: true,
+ cancelable: true,
+ key: 'w', // or any other key you want to simulate
+ keyCode: 87, // or any other key code you want to simulate
+ which: 87, // or any other key code you want to simulate
+ });
+ document.dispatchEvent(event);
+ wLock = true;
+ document.getElementById("left_arrow").style.transform = "scale(0.9)rotate(90deg)";
+ }
+
+}
+
+var sLock = false;
+function keyS() {// pressed s key
+ if (wLock) { keyW(); }
+ if (sLock) {
+ var event = new KeyboardEvent('keyup', {
+ bubbles: true,
+ cancelable: true,
+ key: 's', // or any other key you want to simulate
+ keyCode: 83, // or any other key code you want to simulate
+ which: 83, // or any other key code you want to simulate
+ });
+ document.dispatchEvent(event);
+ sLock = false;
+ document.getElementById("right_arrow").style.transform = "scale(1)rotate(90deg)";
+ } else {
+ var event = new KeyboardEvent('keydown', {
+ bubbles: true,
+ cancelable: true,
+ key: 's', // or any other key you want to simulate
+ keyCode: 83, // or any other key code you want to simulate
+ which: 83, // or any other key code you want to simulate
+ });
+ document.dispatchEvent(event);
+ sLock = true;
+ document.getElementById("right_arrow").style.transform = "scale(0.9)rotate(90deg)";
+ }
+}
+
+//ๅขๅ ไธไธช่งฆๆธๅฑๅนไบไปถ๏ผ่ฎฉPaddleๆฐดๅนณ็งปๅจ่ท็ฆปๅ่งฆๆธ็นๆฐดๅนณ็งปๅจ่ท็ฆปไธ่ด
+var touchYstartLeft = null;
+var previousPositionLeft = canvas.height / 2 - paddleHeight;
+var touchYstartRight = null;
+var previousPositionRight = canvas.height / 2 - paddleHeight;
+const canvasBounds = canvas.getBoundingClientRect();
+const canvasMiddle = canvasBounds.width/2+canvasBounds.left;
+
+function actionStart(e) {
+ //e.preventDefault();
+ //ๅคๆญๆฏ้ผ ๆ ๅทฆ้ฎ็นๅป่ฟๆฏ่งฆๆธ
+ if(!gameRunning ) { return; }
+ var leftPt = { pageX: canvas.width, pageY: -1 }, rightPt = { pageX: 0, pageY: -1 };
+
+ if (e.touches && e.touches.length >= 1) {//ๅฆๆๆฏ่งฆๆธ
+ for(var i = 0; i < e.touches.length; i++){//่ฎฐๅฝๅทฆๅ่พน๏ผๆๅทฆ่พน็็น
+ if (e.touches[i].pageX < canvasMiddle) {
+ leftPt = e.touches[i].pageX < leftPt.pageX ? e.touches[i] : leftPt;
+ } else {//่ฎฐๅฝๅณๅ่พน๏ผๆๅณ่พน็็น
+ rightPt = e.touches[i].pageX > rightPt.pageX ? e.touches[i] : rightPt;
+ }
+ }
+ if (touchYstartLeft == null && leftPt.pageY != -1 ) { touchYstartLeft = leftPt.pageY; }
+ if (touchYstartRight == null && rightPt.pageY != -1) { touchYstartRight = rightPt.pageY; }
+ return;
+ } else {//ๅฆๆๆฏ้ผ ๆ touchXstart็ญไบ้ผ ๆ ็xๅๆ
+ if (e.pageX
< e.touches.length; i++) {
+ let touch = e.touches[i];
+ let touchX = touch.pageX;
+ let touchY = touch.pageY;
+
+ // ๆทปๅ ่ฐ่ฏไฟกๆฏ
+ addDebugInfo(`Touch ${i}: (${Math.round(touchX)}, ${Math.round(touchY)})`);
+
+ if (touchX < canvasMiddle) { // ๅทฆๅ่พน
+ if (!leftTouch || touchX < leftTouch.pageX ) {
+ leftTouch = touch;
+ }
+
+ } else { // ๅณๅ่พน
+ if (!rightTouch || touchX > rightTouch.pageX ) {
+ rightTouch = touch;
+ }
+
+ }
+ }
+ try{addDebugInfo(`leftTouch: (${leftTouch.pageX}, ${leftTouch.pageY}, ${touchYstartLeft})`);}catch(e){}
+ try{addDebugInfo(`rightTouch: (${rightTouch.pageX}, ${rightTouch.pageY}, ${touchYstartRight})`);}catch(e){}
+
+ // ๆดๆฐๅทฆไพงๆปๆฟไฝ็ฝฎ
+ try{if (leftTouch && touchYstartLeft !== null) {
+ let distLeft = leftTouch.pageY - touchYstartLeft;
+ leftPaddleY = previousPositionLeft + distLeft;
+ leftPaddleY = Math.max(0, Math.min(canvas.height - paddleHeight, leftPaddleY));
+ addDebugInfo(`distLeft: (${distLeft})`);
+ }}catch(e){}
+
+ // ๆดๆฐๅณไพงๆปๆฟไฝ็ฝฎ
+ try{if (rightTouch && touchYstartRight !== null) {
+ let distRight = rightTouch.pageY - touchYstartRight;
+ rightPaddleY = previousPositionRight + distRight;
+ rightPaddleY = Math.max(0, Math.min(canvas.height - paddleHeight, rightPaddleY));
+ addDebugInfo(`distRight: (${distRight})`);
+ }}catch(e){}
+}
+
+function handleMouseMove(e) {
+ let mouseX = e.pageX;
+ let mouseY = e.pageY;
+
+ // ๆทปๅ ้ผ ๆ ไฝ็ฝฎๅฐ่ฐ่ฏไฟกๆฏ
+ clearDebugInfo();
+ addDebugInfo(`Mouse: (${Math.round(mouseX)}, ${Math.round(mouseY)})`);
+
+ if (mouseX < canvasMiddle) {
+ if (touchYstartLeft !== null) {
+ let distLeft = mouseY - touchYstartLeft;
+ leftPaddleY = previousPositionLeft + distLeft;
+ leftPaddleY = Math.max(0, Math.min(canvas.height - paddleHeight, leftPaddleY));
+ }
+ } else {
+ if (touchYstartRight !== null) {
+ let distRight = mouseY - touchYstartRight;
+ rightPaddleY = previousPositionRight + distRight;
+ rightPaddleY = Math.max(0, Math.min(canvas.height - paddleHeight, rightPaddleY));
+ }
+ }
+}
+
+function clearDebugInfo() {
+ return;
+ debugInfo = [];
+ debugScrollY = 0;
+}
+
+function addDebugInfo(info) {
+ return;
+ debugInfo.push(info);
+ if (debugInfo.length > MAX_LINES) {
+ debugScrollY += LINE_HEIGHT;
+ if (debugScrollY >= DEBUG_AREA_SIZE) {
+ debugScrollY = 0;
+ }
+ }
+}
+
+function drawDebugInfo() {
+ const ctx = canvas.getContext('2d');
+ const startX = (canvas.width - DEBUG_AREA_SIZE) / 2;
+ const startY = (canvas.height - DEBUG_AREA_SIZE) / 2;
+
+ ctx.save();
+
+ // ็ปๅถ่ฐ่ฏๅบๅ่ๆฏ
+ ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
+ ctx.fillRect(startX, startY, DEBUG_AREA_SIZE, DEBUG_AREA_SIZE);
+
+ // ่ฎพ็ฝฎ่ฃๅชๅบๅ
+ ctx.beginPath();
+ ctx.rect(startX, startY, DEBUG_AREA_SIZE, DEBUG_AREA_SIZE);
+ ctx.clip();
+
+ ctx.font = '16px Arial';
+ ctx.fillStyle = 'white';
+ ctx.textAlign = 'left';
+
+ debugInfo.forEach((info, index) => {
+ let y = startY + index * LINE_HEIGHT - debugScrollY;
+ if (y < startY) {
+ y += DEBUG_AREA_SIZE;
+ }
+ ctx.fillText(info, startX + 10, y + LINE_HEIGHT);
+ });
+
+ ctx.restore();
+}
+
+// ๅจๆจ็ไธป็ปๅถๅฝๆฐไธญๆทปๅ ่ฟไธชๅฝๆฐ่ฐ็จ
+//function draw() {
+ // ... ๆจ็ฐๆ็็ปๅถไปฃ็ ...
+
+ // const ctx = canvas.getContext('2d');
+ // const lineHeight = 20;
+ // const startY = canvas.height / 2 - (debugInfo.length * lineHeight) / 2;
+
+ // ctx.save();
+ // ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
+ // ctx.fillRect(0, startY - 10, canvas.width, debugInfo.length * lineHeight + 20);
+
+ // ctx.font = '16px Arial';
+ // ctx.fillStyle = 'white';
+ // ctx.textAlign = 'center';
+
+ // debugInfo.forEach((info, index) => {
+ // ctx.fillText(info, canvas.width / 2, startY + index * lineHeight);
+ // });
+ // drawDebugInfo();
+//}
+
+// ไบไปถ็ๅฌๅจ
+document.addEventListener('touchstart', actionStart, { passive: false });
+document.addEventListener('touchend', actionEnd);
+document.addEventListener('touchmove', actionMove, { passive: false });
+document.addEventListener('mousedown', actionStart);
+document.addEventListener('mouseup', actionEnd);
+document.addEventListener('mousemove', actionMove);
\ No newline at end of file
diff --git a/07-Ping-Pong-Game/style.css b/07-Ping-Pong-Game/style.css
index 5cb33d2..88b9ec6 100644
--- a/07-Ping-Pong-Game/style.css
+++ b/07-Ping-Pong-Game/style.css
@@ -3,6 +3,7 @@
flex-direction: column;
align-items: center;
justify-content: center;
+ max-height: 75vh;
}
.button {
@@ -35,4 +36,12 @@
canvas {
background: #000;
+ width: 95vmin;
}
+body {
+ overscroll-behavior-y: contain;
+ max-height: 80vh;
+ user-select: none;
+ -moz-user-select: none;
+ -o-user-select: none;
+}
\ No newline at end of file
diff --git a/08-Tetris-Game/index.html b/08-Tetris-Game/index.html
index e5a6140..5da63a6 100644
--- a/08-Tetris-Game/index.html
+++ b/08-Tetris-Game/index.html
@@ -1,9 +1,10 @@
-
Talha - Tetris Game
+
Tetris Game
+
-
+
@@ -21,11 +22,12 @@
Lines:
Score:
Time:
-
+
Press the Esc button to pause