Detect if HTML elements are overlapping in CSS/JavaScript by checking for hover states

My journey into writing HTML/CSS/JS began just a few months ago. I challenged myself to create a 2D game from scratch without using any libraries like jQuery. Here is a snippet of what I came up with:

document.addEventListener("keydown",keyDown);

function keyDown(e) {
    if(e.keyCode == 39) move(8, 0);
    if(e.keyCode == 37) move(-8, 0);
    if(e.keyCode == 40) move(0, -8);
    if(e.keyCode == 38) move(0, 8);
}

function move(X,Y) {
    var player=document.getElementById("player")
    ... (remaining code block)
#box {
        position:absolute;
        top:0px;
        left:0px;
        background-color:blue;
        width:512px;
        height:256px;
    }
    #player {
        position:absolute;
        bottom:32px;
        left:136px;
        ... (remaining code block)
</body>

I encountered some issues when the size of the player and brick didn't match. The player would end up covering the brick due to calculations based on their center positions. This led me to seek answers to questions like detecting overlapping elements at pixel-level precision and handling multiple bricks with different IDs.

var brk = document.getElementById("brick");
... (other code blocks)
#box {
  position: absolute;
  top: 0px;
  left: 0px;
  ... (remaining code block)
<head>
</head>
<body>
  <div id="box">
    <div id="world">
      <div id="brick" />
    </div>
    <div id="player" />
  </div>

Answer №1

I revisited this concept and came up with an alternative approach. How about trying something like this instead? By implementing this method, it will become simpler to incorporate additional objects in the future. It's important to note that using the same id for all your bricks may not be feasible, so you'll need to navigate around that limitation. However, this technique allows you to define the width/height in the CSS and position in the JS:

document.addEventListener("keydown",keyDown);

gameObjects = [];

const boxStyles = getComputedStyle(document.getElementById("box"))

// This accomplishes what your code was doing, but in two steps
// Placing a + before a string converts it to a positive Number value
const SCREEN_WIDTH = +boxStyles.getPropertyValue("width").replace('px',"");
const SCREEN_HEIGHT = +boxStyles.getPropertyValue("height").replace('px',"");

function createGameObject(id, x, y) {
    const retVal = {
        "id": id,
        "element": document.getElementById(id),
        "x": x,
        "y": y,
        "width": document.getElementById(id).offsetWidth,
        "height": document.getElementById(id).offsetHeight,
        "setScreenPosition": function(){this.element.style.left = this.x + "px"; this.element.style.top = this.y + "px";},
        "moveLeft": function() {this.x -= this.width; this.setScreenPosition();},
        "moveRight": function() {this.x += this.width; this.setScreenPosition();},
        "moveUp": function() {this.y -= this.height; this.setScreenPosition();},
        "moveDown": function() {this.y += this.height; this.setScreenPosition();},
        "setXY": function(x, y) {this.x = x; this.y = y; this.setScreenPosition();}
    }
    retVal.setScreenPosition();
    gameObjects.push(retVal);
    return retVal;
}

const myPlayer = createGameObject("player", 0, 0);
const myBrick = createGameObject("brick", 128, 32);
const myWall = createGameObject("wall", 256, 128);

function keyDown(e) {

    switch(e.keyCode) {
        case 37:
            moveLeft(myPlayer);
            break;
        case 38:
            moveUp(myPlayer);
            break;
        case 39:
            moveRight(myPlayer);
            break;
        case 40:
            moveDown(myPlayer);
            break;
    }
}

function moveLeft(gameObject) {
    let newX = gameObject.x - gameObject.width;

    if (newX < 0){
        console.log("Off the screen to the left.");
        return
    }
    // The following three lines perform these actions:
    // Check if the gameObj[brick] will touch gameObject[Player] (x)
    // Check if the brick is in the way in the other dimension (y)
    // Check that the object we're comparing against isn't itself
    // I'm using filter to create an array of all objects in the path and then checking the length of that array. An empty array means nothing in the way
    if (gameObjects.filter(gameObj=>gameObj.x <= newX && gameObj.x + gameObj.width >= gameObject.x && 
                                    gameObject.y >= gameObj.y && gameObject.y + gameObject.height <= gameObj.y + gameObj.height && 
                                    gameObj.id !== gameObject.id).length) {
        console.log("Hitting something on the left.");
        return;
    }
    gameObject.moveLeft();
}
function moveRight(gameObject) {
    let newX = gameObject.x + gameObject.width;

    if (newX >= SCREEN_WIDTH) {
        console.log("Off the screen to the right.");
        return;
    }
    if (gameObjects.filter(gameObj=>gameObj.x === newX && gameObject.y >= gameObj.y && 
                                    gameObject.y + gameObject.height <= gameObj.y + gameObj.height && 
                                    gameObj.id !== gameObject.id).length) {
        console.log("Hitting something on the right.")
        return;
    }
    gameObject.moveRight();
}
function moveUp(gameObject) {
    let newY = gameObject.y - gameObject.height;

    if (newY < 0) {
        console.log("Off the screen to the top.");
        return;
    }
    if (gameObjects.filter(gameObj=>gameObj.y <= newY && gameObj.y + gameObj.height >= gameObject.y &&
                                    gameObject.x >= gameObj.x && gameObject.x + gameObject.width <= gameObj.x + gameObj.width && 
                                    gameObj.id !== gameObject.id).length) {
        console.log("Hitting something above.");
        return;
    }
    gameObject.moveUp();
}
function moveDown(gameObject) {
    let newY = gameObject.y + gameObject.height;

    if (newY >= SCREEN_HEIGHT) {
        console.log("Off the screen to the bottom.");
        return;
    }
    if (gameObjects.filter(gameObj=>gameObj.y === newY && gameObject.x >= gameObj.x && 
                                    gameObject.x + gameObject.width <= gameObj.x + gameObj.width && 
                                    gameObj.id !== gameObject.id).length) {
        console.log("Hitting something below.");
        return;
    }
    gameObject.moveDown();
}
#box {
    position:absolute
    top:0px;
    left:0px;
    background-color:blue;
    width:512px;
    height:256px;
}
#player {
    position:absolute;
    background-color:red;
    width:8px;
    height:8px;
    z-index:2;
}
#world {
    position:relative;
    bottom:0px;
    left:0px;
    width:100%;
    height:100%;
    z-index:1;
}
#brick {
    position:absolute;
    background-color:black;
    width:16px;
    height:16px;
    z-index:1;
}

#wall {
    position:absolute;
    background-color:yellow;
    width:16px;
    height:48px;
    z-index:1;
}
<div id="box">
    <div id="world">
        <div id="brick"></div>
        <div id="wall"/></div>
        <div id="player"/></div>
    </div>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Inserting documents into an array of objects in MongoDB

I am facing challenges while attempting to insert multiple objects into an array of objects in my development. The issue arises when trying to add more than one object with the same structure but different content. This is the structure of the groups coll ...

The attribute interface overload in Typescript is an important concept to

Consider a scenario where there are multiple payload options available: interface IOne { type: 'One', payload: { name: string, age: number } } interface ITwo { type: 'Two', payload: string } declare type TBoth = IOne ...

Looking to conceal the children of other parents when clicking on a specific parent element?

Is there a way to hide all child elements of every Parent Element except for the one that has been clicked? For example, when I click on one parent element to toggle its children, all other child items should be hidden. Unfortunately, I can't make any ...

Mini-navigation bar scrolling

I am trying to create a menu where I want to hide elements if the length of either class a or class b is larger than the entire container. I want to achieve a similar effect to what Facebook has. How can I make this happen? I have thought about one approac ...

Unable to access the response received from subscribing in Angular

I came across a helpful guide on this website, and I attempted to implement a similar concept discussed in the section about Unrelated Components: Sharing Data with a Service. Data Service: @Injectable() export class MyDataService{ private messageSou ...

Implementing date range filtering in AngularJS model using filters

Within my view, I have the following: <tr dir-paginate="post in posts |orderBy:propertyName:reverse | filter: searchPost | itemsPerPage: pageSize"> <td> {{post.title}} </td> <td> {{post.content}} </td> <td& ...

Unable to execute script tag on PHP page loading

When I make an AJAX request to fetch JavaScript wrapped in <script> tags that needs to be inserted on the current page, how can I ensure that the code executes upon insertion? Here's the snippet I'm using to add the code: function display ...

There is an issue as headers cannot be changed after being set for the client

I am in the process of developing an employee leave management system. Everything runs smoothly until an issue arises when attempting to update the leave status as an admin, and the logged-in account or user does not have admin privileges. There is a midd ...

Calculating the depth of a webpage with Python

I need help determining the depth of a website through Python. The depth of a subwebsite is defined as the number of clicks needed to reach it from the main website (e.g. www.ualberta.ca). For example, if a subwebsite like www.ualberta.ca/beartracks requir ...

What steps should I take to replicate the "GitHub browse repository effect" on my website? (updating URL without needing to refresh the page)

While exploring a repository on GitHub (for example, https://github.com/sizzlelab/kassi), I noticed that clicking on a folder triggers a stylish JavaScript animation that moves elements to the left without reloading the entire page. However, the URL in the ...

`Inconsistencies between Postman and AngularJS service responses`

When I make a call to the endpoint using Postman, I receive this response: https://i.stack.imgur.com/pH31G.png However, when I make the same request from my AngularJS service defined below: this.login = function (loginInfo) { return $http({ ...

Invisible and Unrestricted automatic playback

Why is auto play muted in both Firefox and Chrome? How can we code it so that browsers don't block it? Here's the code I'm using: <audio id="audio1" src="https://notificationsounds.com/storage/sounds/file-sounds-1217-relax ...

The identical animation is experiencing delays in various directions

Having an issue with my image slider - when clicking on the previous image button, the animation takes longer compared to when clicking on the next image button, even though the animation duration is set to be the same for both. Any idea why this might be ...

Excessive requests to location or history APIs in a brief period of time

Alert: Reached maximum update depth. This issue may arise when a component invokes setState within useEffect without a dependency array, or if any of the dependencies change on each render. const OwnerPage = () => { const onOpen = useAgencyModal((s ...

Sharing data between ReactJS components using arrays

When I try to send a value from one component to another, the route in my http address shows as undefined instead of the actual value. The server response that I receive is structured like this: https://i.sstatic.net/wxiiM.png The issue arises when I atte ...

Utilizing jQuery to Bind AJAX Events without a DOM Element

The documentation for jQuery AJAX Events provides examples that all involve using a jQuery DOM Element to declare a binding, like so: $('.log').ajaxSend( hander ); I am interested in capturing jQuery AJAX Events without the need for a DOM Eleme ...

Angular JS - Resolving issues with table headers

I've been working on fixing the headers of a table and have tried multiple solutions I found online, but nothing seems to be effective for me. Here's my current code: <div class="report-container"> <div class="row"> <d ...

How can I preserve data in editable PDFs with Angular and JavaScript?

Need help with savedoc() functionality <iframe [src] ="fileurl" #iframe> </iframe> <button (click)="saveDoc()"> </button> Having trouble accessing edited PDF content in Typescript: /*api cal ...

Which HTML layout is more efficient for the web browser?

It seems to be widely believed that we should only use tables for tabular data, and not for layouting. I agree with this principle and understand the reasons behind it, including performance considerations. Has anyone conducted real benchmarks comparing ...

The reliability of next router events can sometimes be called into question as they do not always function consistently

I've been working on creating a loading screen for my Next.js project. The issue I'm facing is that sometimes the loading message stays on the screen and doesn't go away even after the page has loaded. I suspect this may be due to the state ...