I am building a video game where fireballs drop from the top screen. The spaceship, moved by controllers, must avoid those fireballs in order win. My issue is that I do not know how to detect when the spaceship collides into fireballs. However, I found this link: Detect if animated object touched another object in DOM. I analysed this code and it seems it only works for his issue particularly. Do you guys know how to do this?
Code for image spaceship and fireball:
<img src="Photo/fireball.png" id="fireball"> <img src="Photo/Spaceship1.png" id="icon-p">
Code for spaceship:
let rect = icon let pos = {top: 1000, left: 570} const keys = {} window.addEventListener("keydown", function(e) {keys[e.keyCode] = true}) window.addEventListener("keyup", function(e) {keys[e.keyCode] = false}) const loop = function() { if (keys[37] || keys[81]) {pos.left -= 10} if (keys[39] || keys[68]) {pos.left += 10} if (keys[38] || keys[90]) {pos.top -= 10} if (keys[40] || keys[83]) {pos.top += 10} var owidth = display.offsetWidth var oheight = display.offsetHeight var iwidth = rect.offsetWidth var iheight = rect.offsetHeight if (pos.left < 0) pos.left = -10 if (pos.top < 0) pos.top = -10 if (pos.left + iwidth >= owidth) pos.left = owidth-iwidth if (pos.top + iheight >= oheight) pos.top= oheight-iheight rect.setAttribute("data", owidth + ":" + oheight) rect.style.left = pos.left + "px"; rect.style.top = pos.top + "px"} let sens = setInterval(loop, 1000 / 60)
Code for fireball:
function fFireball(offset) { return Math.floor(Math.random() * (window.innerWidth - offset))} let fireballElement = document.querySelector("#fireball"); let fireball = {x: fFireball(fireballElement.offsetWidth), y: 0} const fireLoop = function() { fireball.y += 2 fireballElement.style.top = fireball.y + 'px' if (fireball.y > window.innerHeight) { fireball.x = fFireball(fireballElement.offsetWidth) fireballElement.style.left = fireball.x + 'px'; fireball.y = 0}} fireballElement.style.left = fireball.x + 'px' let fireInterval = setInterval(fireLoop, 1000 / 100)
Thanks!
Advertisement
Answer
here I’ve integrated collision detection for your game. The most notable thing is in this function:
function checkCollision() { var elem = document.getElementById("icon"); var elem2 = document.getElementById("fireball"); if ( detectOverlap(elem, elem2) && elem2.getAttribute('hit')=='false' ){ hits++; // detect hit and increase elem2.setAttribute('hit', true); // set attribute to not have flooding console.log( hits ); // console it just to see it } setTimeout( checkCollision, 20); }
In lower window you can test demo that I’ve built for you without images but some random boxes as images 🙂
Good luck with game man, cool
////////// "use strict" //Stay on focus function stayOnFocus() { setTimeout(function() { alert("Do not exit window or game progression will be lost!") }, 1000) } let hits = 0 //"A" keypress plays Music document.addEventListener('keydown', function(e) { if (e.keyCode !== 173) { //document.getElementById('audio').play() } }) //Input Validation let icon = document.getElementById("icon") let fireballElement = document.querySelector("#fireball") var input = document.getElementById("input") input.addEventListener("keydown", function(event) { if (event.keyCode === 13) { event.preventDefault(); document.getElementById("begin-timer").click() } }) //CountDown (3...2...1) var count = 3 function countDown() { function preventCountFast() { document.getElementById("count").innerHTML = count if (count > 0) { count-- } else { clearInterval(ncount); document.getElementById("count").style.display = "none" } } var ncount = setInterval(preventCountFast, 1000) } //Name displayed + space(switch between images) + parameter icon displayed function Username(field) { field = input.value if (field == "") { alert("Complete blanks"); return false } document.getElementById("askName").style.display = "none" setTimeout(function() { document.getElementById("name").innerHTML = "Player: " + field icon.style.display = 'block'; fireballElement.style.display = "block" const images = ["https://placehold.it/30x30", "https://placehold.it/90x90", "https://placehold.it/120x40", "https://placehold.it/100x100" ] document.body.onkeyup = function(e) { if (e.keyCode === 32) { hits++; icon.src = images[hits % 5] } } checkCollision(); }, 4000) } //Spaceship moves into space + prevent going out borders let display = document.getElementById("body"); let rect = icon let pos = { top: 1000, left: 570 } const keys = {} window.addEventListener("keydown", function(e) { keys[e.keyCode] = true }) window.addEventListener("keyup", function(e) { keys[e.keyCode] = false }) const loop = function() { if (keys[37] || keys[81]) { pos.left -= 10 } if (keys[39] || keys[68]) { pos.left += 10 } if (keys[38] || keys[90]) { pos.top -= 10 } if (keys[40] || keys[83]) { pos.top += 10 } var owidth = display.offsetWidth var oheight = display.offsetHeight var iwidth = rect.offsetWidth var iheight = rect.offsetHeight if (pos.left < 0) pos.left = -10 if (pos.top < 0) pos.top = -10 if (pos.left + iwidth >= owidth) pos.left = owidth - iwidth if (pos.top + iheight >= oheight) pos.top = oheight - iheight rect.setAttribute("data", owidth + ":" + oheight) rect.style.left = pos.left + "px"; rect.style.top = pos.top + "px" } let sens = setInterval(loop, 1000 / 60) //Parameter Sensibility let param = document.getElementById("parameters") let b2 = document.getElementById("body2") document.getElementById("general").addEventListener("click", function() { param.style.display = "block"; b2.style.display = "none" }) function validateSens() { b2.style.display = "block"; param.style.display = "none"; clearInterval(sens) let sensibilty = parseFloat(document.getElementById("sensibilty").value) switch (sensibilty) { case 1: sens = setInterval(loop, 1000 / 40); break; case 2: sens = setInterval(loop, 1000 / 60); break; case 3: sens = setInterval(loop, 1000 / 80); break; default: alert("Sorry, a bug occured") } } //Fireball script function fFireball(offset) { return Math.floor(Math.random() * (window.innerWidth - offset)) } let fireball = { x: fFireball(fireballElement.offsetWidth), y: 0 } const fireLoop = function() { fireball.y += 2; fireballElement.style.top = fireball.y + 'px' if (fireball.y > window.innerHeight) { fireball.x = fFireball(fireballElement.offsetWidth) fireballElement.style.left = fireball.x + 'px'; fireball.y = 0; fireballElement.setAttribute('hit', false ); } } fireballElement.style.left = fireball.x + 'px' let fireInterval = setInterval(fireLoop, 1000 / 100) function checkCollision() { var elem = document.getElementById("icon"); var elem2 = document.getElementById("fireball"); if (detectOverlap(elem, elem2) && elem2.getAttribute('hit')=='false' ){ hits++; // detect hit elem2.setAttribute('hit', true); aler("hi") } setTimeout( checkCollision, 20); } // detect fn var detectOverlap = (function() { function getPositions(elem) { var pos = elem.getBoundingClientRect(); return [ [pos.left, pos.right], [pos.top, pos.bottom] ]; } function comparePositions(p1, p2) { var r1, r2; r1 = p1[0] < p2[0] ? p1 : p2; r2 = p1[0] < p2[0] ? p2 : p1; return r1[1] > r2[0] || r1[0] === r2[0]; } return function(a, b) { var pos1 = getPositions(a), pos2 = getPositions(b); return comparePositions(pos1[0], pos2[0]) && comparePositions(pos1[1], pos2[1]); }; })();
body { user-select: none; margin: 0px; height: 100vh; padding: 0; width: 100%; background-image: url(Photo/bg.jpg); background-repeat: no-repeat; background-attachment: fixed; animation: intro-fade 3s; background-size: cover; overflow: hidden; } #askName { display: block; z-index: 1; margin-left: auto; margin-top: 12%; margin-right: auto; width: 400px; text-align: center; background-color: #737373; opacity: 0.8; border-radius: 15px; padding: 40px 50px 40px 50px; } #askName:hover { opacity: 0.9 } #askName>label { text-align: center; font-size: 150%; font-weight: lighter; text-align: center; } #askName>input { display: block; font-size: 100%; margin: 30px auto 20px auto; border: none; border-radius: 10px; padding: 10px 20px 10px 20px; } #askName>button { background-color: #e6e6e6; cursor: pointer; padding: 10px 20px 10px 20px; border: none; border-radius: 10px; } #count { margin-top: 13%; animation: count-down 16s; font-weight: lighter; font-family: cursive; text-align: center; color: black; font-size: 200px; } h6 { margin-right: 20px; padding-top: 5px; font-weight: normal; font-family: sans-serif; margin-top: 0px; color: white; text-align: center; font-size: 190%; cursor: default; } h6:hover { font-size: 210% } #icon { position: absolute; top: 0; left: 0; cursor: none; width: 9%; } #general { position: absolute; cursor: pointer; min-width: 4%; top: 10px; width: 4%; right: 10px; } #general:hover { transform: rotate(-100deg) } #parameters { text-align: center; display: none; animation: intro-fade 3s; height: auto; border: none; background-color: #d9d9d9; color: black; position: absolute; padding: 0px 60px 20px 60px; left: 50%; width: auto; min-width: 200px; top: 50%; transform: translate(-50%, -50%); border-radius: 13px; } h3 { color: black; font-weight: normal; font-size: 150%; } #sensibilty { display: block; margin-right: auto; margin-left: auto; } #validateSens { margin-top: 20px; border: none; padding: 10px; border-radius: 5px; cursor: pointer; } @keyframes intro-fade { from { opacity: 0 } to { opacity: 1 } } @keyframes count-down { from { transform: scale(0) } to { transform: scale(1) } }
<body id="body" onload="stayOnFocus()"> <img src="https://placehold.it/350x350" id="general"> <section id="parameters"> <h3> Choose your sensibility </h3> <input type="range" id="sensibilty" min="1" max="3" value="2"> <button id="validateSens" onclick="validateSens()"> Submit </button> </section> <main id="body2"> <form id="askName" title="Write your name"> <label> Enter your username: </label> <input id="input" type="text" maxlength="10" autofocus> <button type="button" onclick="countDown(); return Username()" id="begin-timer"> Submit </button> </form> <h6 id="name"></h6> <h2 id="count"></h2> <img src="https://placehold.it/50x52" id="fireball" style="display:none; width:3%; position:absolute; cursor:none"> <img src="https://placehold.it/80x40" id="icon" style="display:none"> </main>