diff --git a/README.md b/README.md index a7c49dd..bc20c66 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,53 @@ # XO-Game-Three.js - - - ## Introduction -Do you remember playing tic-tac-toe (X and O) when you were bored growing up? Well, imagine taking that classic game to a whole new level of fun with Three.js! This project implements the X and O game in JavaScript using Three.js, adding a 3D experience, physics, and even some music. Get ready to enjoy a modern twist on a timeless game! +Remember the classic tic-tac-toe (X and O) game you used to play when you were bored? Now, imagine taking that timeless game to a whole new level of excitement with Three.js! This project brings the X and O game to life in JavaScript using Three.js, providing a 3D experience, realistic physics, and even background music. Get ready to enjoy a modern twist on a childhood favorite! ## Features - X and O game implemented in JavaScript. -- Built using Three.js for a 3D experience. -- Incorporates physics for realistic interactions. -- Includes background music for added enjoyment. -- saving the game -- changing themes -- adjusting volumes -- and more suprising fun +- Built using Three.js for immersive 3D graphics. +- Realistic physics interactions for an engaging gameplay experience. +- Background music to enhance enjoyment. +- Save game functionality. +- Theme customization. +- Volume adjustment. +- And more surprising fun elements! ## How to Play 1. Open the game in your web browser. 2. Click on a square to place your X or O. -3. Try to get three of your symbols in a row, either horizontally, vertically, or diagonally, before your opponent does. -4. Enjoy the immersive 3D experience and lively background music as you play! -5. the game can be played under your conditions like if you want to play one sqaure at a time or 6 sqaures very quickly to find out the real champion of the x and o game-final boss.. - +3. Aim to get three of your symbols in a row horizontally, vertically, or diagonally before your opponent. +4. Immerse yourself in the 3D experience and enjoy the lively background music as you play! +5. Customize the gameplay conditions to your preference, whether you want to play one square at a time or compete in a fast-paced match with six squares simultaneously to determine the ultimate X and O champion. ## Technologies Used -- JavaScript(mainly) +- JavaScript (mainly) - Three.js +- Matter.js - HTML/CSS - Web Audio API (for music) -- local storage for saving the game and theme... -- matter js(very little) - +- Local storage for saving the game and theme... + +## Explanation of Technologies +- **JavaScript**: The primary language used for game logic and interaction. +- **Three.js**: Utilized for creating and rendering the 3D scene, including objects and animations. +- **Matter.js**: Employed for simulating physics interactions, such as gravity and collision detection. +- **HTML/CSS**: Used for structuring the web page and styling elements. +- **Web Audio API**: Integrated for background music and sound effects. +- **Local Storage**: Implemented to save the game state and theme preferences for future sessions. ## Installation To run the game locally: 1. Clone this repository to your local machine. 2. Open the `index.html` file in your web browser. -3. console and check for errors if there (not possible) enjoy these contains all the files required for running the game.... -4. If you dont like the colours there is so many themes or you yourself can generate the themes you like and use them ........... +3. Check the console for any errors (unlikely to occur) to ensure smooth gameplay. +4. Explore various color themes available or create your own to personalize the gaming experience. ## Credits -This project was created by Ahmmed Binas as a fun way to explore game development with Three.js. - -suggest me for some improvemnets or changes if required ... thx :))) - +This project was created by Ahmmed Binas as a fun exploration of game development using Three.js. -- The creators of Three.js for providing an amazing library for 3D graphics in the browser. -- the awesome background music used in the game. +Special thanks to: +- The creators of Three.js for providing an exceptional library for 3D graphics in the browser. +- The background music used in the game for adding an extra layer of enjoyment. ## License This project is licensed under the [MIT License](LICENSE). diff --git a/cameras.js b/cameras.js deleted file mode 100644 index e69de29..0000000 diff --git a/game.js b/game.js deleted file mode 100644 index e69de29..0000000 diff --git a/htmlcube.js b/htmlcube.js index 417da35..aa5aa16 100644 --- a/htmlcube.js +++ b/htmlcube.js @@ -12,7 +12,6 @@ document.querySelector('#renderer-container').appendChild(renderer.domElement); const controls = new THREE.OrbitControls(camera, renderer.domElement); controls.autoRotate = false; -// Matter.js setup const engine = Matter.Engine.create(); const render = Matter.Render.create({ element: document.body, @@ -21,14 +20,14 @@ const render = Matter.Render.create({ Matter.Render.run(render); Matter.Runner.run(engine); -// Cube + const cubeSize = 2.28; const cubeGeometry = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize); const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0x44aa88 }); const cube = new THREE.Mesh(cubeGeometry, cubeMaterial); scene.add(cube); -// Ground +//ground const ground = Matter.Bodies.rectangle(9, -8, 800, 2, { isStatic: true }); Matter.World.add(engine.world, [ground]); diff --git a/index.js b/index.js deleted file mode 100644 index e99c22a..0000000 --- a/index.js +++ /dev/null @@ -1,6 +0,0 @@ -function hello(){ - console.log("woooooo") -} - - -hello(); \ No newline at end of file diff --git a/settings.js b/settings.js index b60a2ef..8c3b926 100644 --- a/settings.js +++ b/settings.js @@ -9,13 +9,13 @@ let isSettingsOpen = false; settingsButton.addEventListener("click", toggleSettings); closeButton.addEventListener("click", closeSettings); document.addEventListener("keydown", handleKeyPress); -volumeInput.addEventListener("input", updateVolume); + function toggleSettings() { isSettingsOpen = !isSettingsOpen; if (isSettingsOpen) { openSettings(); - stopgame(); + } else { closeSettings(); applySettings(); @@ -25,8 +25,7 @@ function toggleSettings() { function openSettings() { modal.style.display = "block"; const overlay = document.getElementById("overlay"); - overlay.style.display = "block"; - stopgame(); + } function closeSettings() { @@ -45,4 +44,11 @@ function handleKeyPress(event) { function updateVolume() { const volume = volumeInput.value / 100; - sound.setVolume(volume);} + const sources = document.querySelectorAll("audio"); + sources.forEach(source => { + const gainNode = audioContext.createGain(); + source.connect(gainNode); + gainNode.connect(audioContext.destination); + gainNode.gain.value = volume; + }); +} \ No newline at end of file diff --git a/startUI.js b/startUI.js index c16e9b6..3ea1147 100644 --- a/startUI.js +++ b/startUI.js @@ -9,6 +9,61 @@ function startGame() { }, delay); } +const audioContext = new AudioContext(); +let soundBuffer, soundSource, gainNode, isSoundEnabled; + +fetch('./space-ambience-56265.mp3') + .then(response => response.arrayBuffer()) + .then(arrayBuffer => audioContext.decodeAudioData(arrayBuffer)) + .then(decodedBuffer => { + soundBuffer = decodedBuffer; + isSoundEnabled = localStorage.getItem("isSoundEnabled") === "true"; + document.getElementById("toggleSoundCheckbox2").checked = isSoundEnabled; + if (isSoundEnabled) { + playSound(); + } + }) + .catch(error => console.error('Error loading sound file:', error)); + +function toggleSound() { + isSoundEnabled = !isSoundEnabled; + if (!isSoundEnabled) { + stopSound(); + } + else { + playSound(); + } + localStorage.setItem("isSoundEnabled", isSoundEnabled); +} + +document.getElementById("toggleSoundCheckbox2").addEventListener("change", toggleSound); + +function playSound() { + if (soundBuffer && isSoundEnabled) { + soundSource = audioContext.createBufferSource(); + soundSource.buffer = soundBuffer; + gainNode = audioContext.createGain(); + soundSource.connect(gainNode); + gainNode.connect(audioContext.destination); + soundSource.start(); + } +} + +function stopSound() { + if (soundSource) { + soundSource.stop(); + } +} + +document.getElementById("saveSettings").addEventListener("click", saveSettings); + +function saveSettings() { + localStorage.setItem("isSoundEnabled", isSoundEnabled); + alert("Settings saved successfully!"); +} + + + const windowGeometry = new THREE.BoxGeometry(5, 5, 0); const windowMaterial = new THREE.MeshBasicMaterial({ color: 0x808080, transparent: true, opacity: 0.8 }); diff --git a/styles.css b/styles.css index 4a683fc..d6883e1 100644 --- a/styles.css +++ b/styles.css @@ -1,73 +1,128 @@ body { margin: 0; overflow: hidden; + background-color: #000; + font-family: 'Arial', sans-serif; + color: #fff; } -#x-match-count { +#x-match-count, +#o-match-count, +#settingsButton { position: fixed; - top: 20px; - left: 20px; - color: rgb(189, 189, 189); + color: #ccc; font-size: 20px; } +#x-match-count { + top: 20px; + left: 20px; +} + #o-match-count { - position: fixed; - top: 43px; - left: 20px; - color: rgb(189, 189, 189); - font-size: 20px; + top: 43px; + left: 20px; } #settingsButton { - position: fixed; - top: 73px; - left: 20px; - color: rgb(189, 189, 189); - font-size: 20px; + top: 73px; + left: 20px; + width: 50px; + height: 50px; background-image: url("seting1.avif"); - background-size: contain; - background-repeat: no-repeat; - width: 50px; - height: 50px; + background-size: contain; + background-repeat: no-repeat; } - - - .modal { - display: none; - position: fixed; + display: none; + position: fixed; z-index: 1; left: 0; top: 0; - width: 100%; - height: 100%; + width: 100%; + height: 100%; overflow: auto; - background-color: rgb(0,0,0); - background-color: rgba(0,0,0,0.4); + background-color: rgba(0, 0, 0, 0.8); } - .modal-content { - background-color: #fefefe; + background-color: #222; margin: 15% auto; padding: 20px; - border: 1px solid #888; - width: 80%; + border-radius: 10px; + width: 80%; } - .close { - color: #aaa; + color: #999; float: right; font-size: 28px; font-weight: bold; + cursor: pointer; } .close:hover, .close:focus { - color: black; - text-decoration: none; + color: #fff; +} + +h2, +h3 { + color: #ccc; +} + +#colorSelect { + background-color: #333; + color: #ccc; + border: none; + padding: 8px; + border-radius: 5px; + font-size: 16px; + margin-bottom: 10px; +} + +#applySettings, +#saveSettings, +#deleteSettings { + background-color: #444; + color: #ccc; + border: none; + padding: 10px 20px; + border-radius: 5px; + font-size: 16px; cursor: pointer; + margin-right: 10px; +} + +#applySettings:hover, +#saveSettings:hover, +#deleteSettings:hover { + background-color: #555; +} + +input[type="checkbox"] { + display: none; +} + +input[type="checkbox"] + label { + position: relative; + padding-left: 30px; + cursor: pointer; + color: #ccc; +} + +input[type="checkbox"] + label:before { + content: ''; + position: absolute; + left: 0; + top: 2px; + width: 20px; + height: 20px; + border: 2px solid #ccc; + border-radius: 5px; +} + +input[type="checkbox"]:checked + label:before { + background-color: #fff; } diff --git a/three.html b/three.html index 1d4b66c..410c025 100644 --- a/three.html +++ b/three.html @@ -28,15 +28,13 @@

Color Settings

- - - - - + + + + -
@@ -47,7 +45,6 @@

Color Settings

- diff --git a/x.js b/x.js index f3b9756..3cf03cc 100644 --- a/x.js +++ b/x.js @@ -81,35 +81,61 @@ document.addEventListener("DOMContentLoaded", function() { }); - -/* const audioContext = new AudioContext(); -const soundURL = './mixkit-negative.wav'; -let soundBuffer; +let soundBuffer, soundSource, gainNode, isSoundEnabled; -fetch(soundURL) +fetch('./mixkit-negative.wav') .then(response => response.arrayBuffer()) .then(arrayBuffer => audioContext.decodeAudioData(arrayBuffer)) .then(decodedBuffer => { soundBuffer = decodedBuffer; + isSoundEnabled = localStorage.getItem("isSoundEnabled2") === "true"; + document.getElementById("toggleSoundCheckbox").checked = isSoundEnabled; + if (isSoundEnabled) { + playSound(); + } }) .catch(error => console.error('Error loading sound file:', error)); -// Function to play the sound -function playSound(count) { - if (!soundBuffer) { - console.error('Sound buffer not loaded'); - return; - } - - for (let i = 0; i < count; i++) { - const source = audioContext.createBufferSource(); - source.buffer = soundBuffer; - source.connect(audioContext.destination); - source.start(); - } +function toggleSound() { + isSoundEnabled = !isSoundEnabled; + if (!isSoundEnabled) { + stopSound(); + } + else { + playSound(); + } + localStorage.setItem("isSoundEnabled2", isSoundEnabled); +} + +document.getElementById("toggleSoundCheckbox").addEventListener("change", toggleSound); + +function playSound() { + if (soundBuffer && isSoundEnabled) { + soundSource = audioContext.createBufferSource(); + soundSource.buffer = soundBuffer; + gainNode = audioContext.createGain(); + soundSource.connect(gainNode); + gainNode.connect(audioContext.destination); + soundSource.start(); } -*/ +} + +function stopSound() { + if (soundSource) { + soundSource.stop(); + } +} + +document.getElementById("saveSettings").addEventListener("click", saveSettings); + +function saveSettings() { + localStorage.setItem("isSoundEnabled2", isSoundEnabled); + alert("Settings saved successfully!"); +} + + + const textpositions= [ new THREE.Vector3(-0.94, -0.94, -1.2), // 1