Created
August 8, 2023 21:09
-
-
Save solanoize/8b8424c3fecc5c387a4fdfc8e7c52fd2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Yanwar Solahudin | |
| * ================ | |
| * I built this simple code to implement the game logic of card combat and | |
| * using energy scores. I enjoyed it, and the code is rudimentary as it | |
| * needs to be updated to take advantage of the defense features and possibly | |
| * additional game logic if the cards go over two. | |
| */ | |
| let temmplatePlayer = { | |
| name: "", | |
| player: null, | |
| lifePoint: 18000, | |
| attack: 0, | |
| defence: 0, | |
| }; | |
| let gamePlayers = []; | |
| let gameBoard = null; | |
| let STATE_ON = false; | |
| let SHAKE = true; | |
| function attackEffect(enemy) { | |
| let position = enemy.player.parentElement.object3D; | |
| let scene = enemy.player.parentElement; | |
| let effect = document.createElement("a-gltf-model"); | |
| effect.setAttribute("src", "#attack-effect"); | |
| effect.setAttribute("crossFadeDuration", "2"); | |
| effect.setAttribute("position", { | |
| x: position.x, | |
| y: position.y, | |
| z: position.z, | |
| }); | |
| // effect.setAttribute("rotation", { | |
| // x: -90, | |
| // y: 0, | |
| // z: 0, | |
| // }); | |
| effect.setAttribute("animation-mixer", "clip: *"); | |
| // effect.setAttribute("scale", "0.6 0.6 0.6"); | |
| scene.appendChild(effect); | |
| let time = setTimeout(() => { | |
| effect.remove(); | |
| clearTimeout(time); | |
| }, 4000); | |
| } | |
| function gameStatus(player, flip, timer = 0) { | |
| let statusMessage = `N: ${player.name.toUpperCase()}`; | |
| statusMessage += `\nE: ${player.energy}`; | |
| statusMessage += `\nA: ${player.attack}`; | |
| statusMessage += `\nD: ${player.defence}`; | |
| statusMessage += `\nR: ${flip}`; | |
| if (player.status) { | |
| player.status.setAttribute("value", statusMessage); | |
| } | |
| } | |
| function gameBoardStatus(player, timer, winner = false) { | |
| let statusMessage = ""; | |
| if (winner) { | |
| statusMessage = `${player.name.toUpperCase()} IS LOST!!!`; | |
| gameBoard.setAttribute("value", statusMessage); | |
| } else { | |
| if (player) { | |
| statusMessage = `${player.name.toUpperCase()} attack mode...`; | |
| } | |
| statusMessage += `\nProgress ${(timer * 0.1).toFixed()}%`; | |
| } | |
| try { | |
| gameBoard.setAttribute("value", statusMessage); | |
| } catch (error) {} | |
| } | |
| function fight(player, enemy) { | |
| console.log("Dia ", player.name, "Attack -> ", enemy.name); | |
| player.player.setAttribute( | |
| "animation-mixer", | |
| `clip: ${player.activity.attack}` | |
| ); | |
| let out = setTimeout(() => { | |
| player.player.setAttribute( | |
| "animation-mixer", | |
| `clip: ${player.activity.idle}` | |
| ); | |
| clearTimeout(out); | |
| }, 3000); | |
| attackEffect(enemy); | |
| enemy.energy -= player.attack; | |
| return { player, enemy }; | |
| } | |
| AFRAME.registerComponent("loaded", { | |
| init: function () { | |
| let el = this.el; | |
| el.addEventListener("markerFound", (e) => { | |
| // emit to register | |
| if (e.target.getAttribute("preset") === "kanji") { | |
| gameBoard = e.target.childNodes[1]; | |
| console.log(e.target.childNodes); | |
| } else { | |
| let p = e.target.childNodes[1]; | |
| let activity = {}; | |
| for (let obj of p.components["gltf-model"].model.animations) { | |
| activity[obj.name.toLowerCase()] = obj.name; | |
| } | |
| console.log(activity); | |
| el.emit("onPlayerRegister", { | |
| player: { | |
| player: p, | |
| position: p.object3D.position, | |
| energy: 18000, | |
| attack: parseInt(p.dataset.attack), | |
| defence: parseInt(p.dataset.defence), | |
| status: document.querySelector(`#text-${p.dataset.player}`), | |
| name: p.dataset.player, | |
| activity, | |
| }, | |
| }); | |
| } | |
| }); | |
| }, | |
| }); | |
| AFRAME.registerComponent("player-register", { | |
| init: function () { | |
| let el = this.el; | |
| this.timer = 0; | |
| this.flip = false; | |
| this.start = false; | |
| this.playerRun = null; | |
| this.enemy = null; | |
| el.addEventListener("onPlayerRegister", (e) => { | |
| gamePlayers.push(e.detail.player); | |
| gameStatus(e.detail.player); | |
| }); | |
| }, | |
| tick: function (time, dt) { | |
| if (gamePlayers.length === 2) { | |
| this.start = true; | |
| for (let obj of gamePlayers) { | |
| console.log("OBJ", obj); | |
| if (obj.energy <= 1) { | |
| gameBoardStatus(obj, 0, true); | |
| this.start = false; | |
| gamePlayers = []; | |
| } | |
| } | |
| } | |
| if (this.start) { | |
| this.timer += 1; | |
| gameBoardStatus(this.playerRun, this.timer); | |
| if (this.timer > 100) { | |
| let rand = Math.random() < 0.5; | |
| this.playerRun = gamePlayers[rand ? 1 : 0]; | |
| this.enemy = gamePlayers[rand ? 0 : 1]; | |
| gameBoardStatus(this.playerRun, time); | |
| const { player, enemy } = fight(this.playerRun, this.enemy); | |
| this.playerRun = player; | |
| this.enemy = enemy; | |
| console.log("E", this.enemy); | |
| gameStatus(this.enemy); | |
| SHAKE = !SHAKE; | |
| this.timer = 0; | |
| } | |
| } | |
| }, | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" /> | |
| <title>Hello World!</title> | |
| <!-- include A-Frame obviously --> | |
| <script src="https://aframe.io/releases/1.4.0/aframe.min.js"></script> | |
| <script src="https://cdn.jsdelivr.net/gh/c-frame/aframe-extras@7.0.0/dist/aframe-extras.min.js"></script> | |
| <!-- include ar.js for A-Frame --> | |
| <script src="https://raw.githack.com/AR-js-org/AR.js/master/aframe/build/aframe-ar.js"></script> | |
| <script src="./script.js"></script> | |
| <script src="./ais.js"></script> | |
| <script> | |
| AFRAME.registerComponent("anim", { | |
| tick: function () { | |
| // console.log(this.el.components['gltf-model']) | |
| } | |
| }) | |
| </script> | |
| </head> | |
| <body style="margin: 0px; overflow: hidden"> | |
| <a-scene | |
| player-register | |
| arjs="trackingMethod: best; sourceType: webcam; debugUIEnabled: false;" | |
| embedded | |
| renderer="logarithmicDepthBuffer: true;" | |
| vr-mode-ui="enabled: false" | |
| id="scene" | |
| > | |
| <a-assets> | |
| <!-- Run, Idle, Walk --> | |
| <a-asset-item id="halldora" src="./assets/3d/Halldora.glb"></a-asset-item> | |
| <a-asset-item id="sveinn" src="./assets/3d/Sveinn2.glb"></a-asset-item> | |
| <a-asset-item id="taintvine" src="./assets/3d/Taintvine.glb"></a-asset-item> | |
| <a-asset-item id="voodooghoul" src="./assets/3d/Voodooghoul.glb"></a-asset-item> | |
| <a-asset-item id="effect" src="./assets/3d/effect.glb"></a-asset-item> | |
| <a-asset-item id="attack-effect" src="./assets/3d/attack-effect.glb"></a-asset-item> | |
| <a-asset-item id="candle" src="./assets/3d/candle.glb"></a-asset-item> | |
| </a-assets> | |
| <a-light type="point" color="blue" position="0 5 0"></a-light> | |
| <a-light type="point" color="red" position="0 5 4"></a-light> | |
| <a-light type="point" color="cyan" position="0 5 -4"></a-light> | |
| <a-light type="point" color="yellow" position="4 5 -4"></a-light> | |
| <a-light type="point" color="green" position="-4 5 -4"></a-light> | |
| <a-light type="point" color="black" position="-4 5 -4"></a-light> | |
| <a-marker type='pattern' loaded url='./assets/patt/Halldora.patt'> | |
| <a-gltf-model src="#halldora" data-attack="2000" data-defence="5000" rotation="0 180 0" data-player="halldora" position="0 0.6 0" animation-mixer="clip: Idle" scale="0.3 0.3 0.3"></a-gltf-model> | |
| <a-gltf-model src="#effect" anim id="effect" position="0 0.3 0" animation-mixer></a-gltf-model> | |
| <a-text position="1.5 0 0" rotation="-90 0 0" id="text-halldora" value="Loading..." width="6" color="red"></a-text> | |
| <a-light type="ambient" color="#222"></a-light> | |
| </a-marker> | |
| <a-marker type='pattern' loaded url='./assets/patt/Sveinn.patt'> | |
| <a-gltf-model src="#sveinn" data-attack="4000" data-defence="3000" data-player="sveinn" position="0 0.6 0" rotation="0 -180 0" animation-mixer></a-gltf-model> | |
| <a-gltf-model src="#effect" anim id="effect" position="0 0.3 0" animation-mixer></a-gltf-model> | |
| <a-text position="1.5 0 0" rotation="-90 0 0" id="text-sveinn" value="Sveinn\nEnergi: 18000\nATC: 2000" width="6" color="red"></a-text> | |
| <a-light type="ambient" color="#222"></a-light> | |
| </a-marker> | |
| <!-- <a-gltf-model src="#attack-effect" anim id="effect" rotation="-90 0 0" scale="0.5 0.5 0.5" position="0 0.3 0" animation-mixer></a-gltf-model> --> | |
| <a-marker type='pattern' loaded url='./assets/patt/Taintvine.patt'> | |
| <a-gltf-model src="#taintvine" data-attack="2000" data-defence="5000" data-player="taintvine" position="0 0.6 0" scale="0.1 0.1 0.1"></a-gltf-model> | |
| <a-gltf-model src="#effect" anim id="effect" position="0 0.3 0" animation-mixer></a-gltf-model> | |
| <a-text position="1.5 0 0" rotation="-90 0 0" id="text-taintvine" value="Taintvine\nEnergi: 18000\nATC: 2000" width="6" color="red"></a-text> | |
| <a-light type="ambient" color="#222"></a-light> | |
| </a-marker> | |
| <a-marker type='pattern' loaded url='./assets/patt/Voodooghoul.patt'> | |
| <a-gltf-model src="#voodooghoul" data-attack="2000" data-defence="5000" data-player="voodooghoul" position="0 0.6 0" animation-mixer="clip: *" ></a-gltf-model> | |
| <a-gltf-model src="#effect" anim id="effect" position="0 0.3 0" animation-mixer></a-gltf-model> | |
| <a-text position="1.5 0 0" rotation="-90 0 0" id="text-voodooghoul" value="Loading..." width="6" color="red"></a-text> | |
| <a-light type="ambient" color="#222"></a-light> | |
| </a-marker> | |
| <a-marker preset='kanji' loaded> | |
| <a-text align="center" position="0 0 1" rotation="-90 0 0" id="text-kanji" value="Loading..." width="3.5" color="red"></a-text> | |
| <a-gltf-model src="#voodooghoul" scale="0.4 0.4 0.4" animation="property: rotation; to: 0 360 0; loop: true; dur: 10000" animation-mixer="clip: *" ></a-gltf-model> | |
| <!-- <a-plane position="0 0 0" rotation="-90 0 0" animation="property: rotation; to: 0 360 0; loop: true; dur: 10000" width="0.5" height="0.5" color="#000000"></a-plane> --> | |
| <!-- <a-light type="point" color="blue" position="0 5 0"></a-light> --> | |
| <!-- <a-box opacity="0.3" rotation="-90 0 0" depth="0.2"></a-box> --> | |
| <!-- <a-box opacity="0.4" rotation="-90 0 -2" depth="0.5"></a-box> --> | |
| </a-marker> | |
| <a-entity camera></a-entity> | |
| </a-scene> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment