Is there a way to combine the range data from the selected cells in my grid's output?

In the development of my game, I have reached a critical juncture where an effective collision detection system is imperative. Currently, I am utilizing a complex array containing 1s and 0s to designate boundaries.

To streamline this process, I have created a basic grid tool that highlights specific cells indicating boundary areas. However, I am facing challenges in simplifying the output for faster access.

My plan involves restructuring the boundaries based on consecutive highlighted cells while leaving out entries for non-highlighted cells, essentially creating a sparse matrix.

For example, with a cell size of 10: 0,0 [_ _ ]- - -[ _ _]

The expected output would be:

{ x: [0,30], y: [0,10] },
{ x: [60,90], y: [0,10] }

However, instead of obtaining this desired result, I end up with empty objects for each cell.

The code snippet below illustrates my attempt at merging the ranges of highlighted cells into a singular object representing a boundary:

    function mergeConsecutiveCells(boundaries) {
        const mergedBoundaries = [];
       
        if (boundaries.length === 0) {
            return mergedBoundaries;
        }
       
        boundaries.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
       
        let currentBoundary = boundaries[0];
       
        for (let i = 1; i < boundaries.length; i++) {

            const nextBoundary = boundaries[i];
       
            if (
                currentBoundary[1] === nextBoundary[1] &&
                currentBoundary[2] === nextBoundary[2] &&
                currentBoundary[3] === nextBoundary[3] &&
                currentBoundary[0] + cellSize === nextBoundary[0]
            ) {
                // Consecutive cells, extend the range
                currentBoundary[0] = nextBoundary[0];
            } else {
               // Non-consecutive cells, add the current boundary to the result
               mergedBoundaries.push({
                   x: { start: currentBoundary[0], end: currentBoundary[0] + cellSize },
                   y: { start: currentBoundary[1], end: currentBoundary[3] }
               });
               currentBoundary = nextBoundary;
            }
        }
        
        // Add the last boundary
        mergedBoundaries.push({
            x: { start: currentBoundary[0], end: currentBoundary[0] + cellSize },
            y: { start: currentBoundary[1], end: currentBoundary[3] }
        });

        return mergedBoundaries;
    }

Answer №1

After countless hours of experimentation and tinkering, I have stumbled upon a rather straightforward solution to my initial problem.

It feels like I was on the right track but not quite there.. XD

If you're curious, here is the link to the codepen: ifaus - 2d sparse matrix - merging range data

Edit:

I've added comments in the JavaScript code to provide clarity on how this solution addresses my query.

<div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>  
// This currently operates exclusively on the X-axis
  
// Merges overlapping entries in the array based on certain conditions
function combineEntries(entries, cellSize) {
  // Flag to keep track of combined entries
  let combined = true;

  // Continually merge entries until no more combinations are possible
  while (combined) {
    combined = false;

    // Iterate through the entries
      for (let i = 1; i < entries.length; i++) {
        const currentEntry = entries[i];
        const previousEntry = entries[i - 1];

        // Check if currentEntry and previousEntry can be merged
        if (canCombine(previousEntry, currentEntry, cellSize)) {
            // Combine X and Y coordinates of previousEntry and currentEntry
            previousEntry.x = [previousEntry.x[0], currentEntry.x[1]];
            previousEntry.y = [previousEntry.y[0], currentEntry.y[1]];

            // Remove currentEntry from the array
            entries.splice(i, 1);

            // Set combined flag to true
            combined = true;
        }
    }
}

// Return the array with combined entries
return entries;
}

// Merges overlapping entries in the array based on certain conditions
function combineEntries(entries, cellSize) {
// Flag to keep track of combined entries
let combined = true;

// Continue merging entries until no more combinations are possible
while (combined) {
    combined = false;

    // Iterate through the entries array
    for (let i = 1; i < entries.length; i++) {
        const currentEntry = entries[i];
        const previousEntry = entries[i - 1];

        // Check if currentEntry and previousEntry can be merged
        if (canCombine(previousEntry, currentEntry, cellSize)) {
            // Combine the X and Y coordinates of previousEntry and currentEntry
            previousEntry.x = [previousEntry.x[0], currentEntry.x[1]];
            previousEntry.y = [previousEntry.y[0], currentEntry.y[1]];

            // Remove currentEntry from the array
            entries.splice(i, 1);

            // Set combined flag to true
            combined = true;
        }
    }
}

// Return the array with combined entries
return entries;
}

// Checks if two entries can be combined based on specified conditions
function canCombine(entry1, entry2, cellSize) {
// Check if the entries overlap and meet certain criteria
return (
    entry1.x[1] >= entry2.x[0] &&
    entry1.y[0] === entry2.y[0] &&
    entry1.y[1] === entry2.y[1] &&
    entry2.x[0] - entry1.x[1] <= cellSize
);
}
// Ensures that two entries can be combined following specific guidelines
// these guidelines represent a coordinate matrix used for object collision boundaries 
// intended for use in a game

// Assuming a Cell size of 10
// { x: [0,10], y: [0,10] } would be Cell at location 0,0
// if a consecutive cell has an x value that is a multiple of the given cell size, then that entry is combined
// For example:
// { x: [0,10], y: [0,10] }
// { x: [10,20], y: [0,10] }
// would be combined as one entry in entries array
// { x: [0,20], y: [0,10] }

function canCombine(entry1, entry2, cellSize) {
// Check if the entries overlap and meet certain criteria
return (
    entry1.x[1] >= entry2.x[0] &&
    entry1.y[0] === entry2.y[0] &&
    entry1.y[1] === entry2.y[1] &&
    entry2.x[0] - entry1.x[1] <= cellSize
);
}
* {
    margin:0;
    padding:0;
}

body {
    height: 100vh;
}

div {
    text-align: center;
    margin:0 auto;
}

canvas {
    border: 1px solid #000;
    max-width: 100%;
    max-height: 100%;
    margin-top: 40px;
}

textarea {
    display:inline-block;
    width:200px;
    height:200px
}

table {
    margin:0 auto;
    margin-top: 40px;
}

input[type=number] {
    width: 30px;
}
<div>
    <table>
    <tr><td>
        <input type="file" id="imageInput" accept="image/*">
        <label for="cellSize">Cell Size:</label>
        <input type="number" id="cellSize" value="20">
    </td></tr>
    <tr><td><canvas id="gridCanvas"></canvas></td></tr>
    <tr><td>
        <textarea id="outputRaw" disabled="true"></textarea>
        <textarea id="outputFinal"></textarea>
    </td></tr>
    </table>
    <input type="button" id="bttnOutputFinal" value="Condense">
</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

Embedding PayPal buttons within a Vue.js component

I am in the process of integrating PayPal order buttons into my Vue.js component. I have been referencing the official documentation which outlines three key steps: Import the PayPal SDK script Create a <div> element where the buttons will be displ ...

What is the best way to include the input object in a JSON array?

In the process of creating a weather forecasting console application, I have encountered an issue regarding saving user input locations. The user is asked if they would like to save the longitude and latitude input, which are then stored in a JSON file. Th ...

Exploring the chosen choice in the Material Design Lite select box

Consider the following scenario. If I want to extract the name of the country chosen using JavaScript, how can this be achieved? <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label getmdl-select getmdl-select__fullwidth"> ...

Step-by-step guide on eliminating the modal post-validation

Newbie in reactjs looking for help with modal validation issue. Goal: Press submit button inside modal, validate, then close the modal. Want to reuse modal for another row. Problem: I'm having trouble making the function work for a new row after ...

Adding elements to an array in Node.js

In my 'both' object, I need to store 2 arrays: eng and fr. Each of these arrays contains multiple objects. How can I transfer all values from frDisplayData to fr:[] within the 'both' object: const displayData = []; var both = {eng:dis ...

Guide to utilizing jquery within node.js

Can anyone assist me with using jQuery in Node.js? I have the following code: const jsdom = require("jsdom"); const { JSDOM } = jsdom; const { window } = new JSDOM('<!DOCTYPE html>'); const $ = require('jquery')(window); var con ...

Unable to retrieve information from server

enter image description here <!DOCTYPE html> <html ng-app="myApp"> <head> <title>ContactApp</title> <!-- Latest compiled and minified CSS --> <link rel="stylesheet" href="https://maxcdn.bootst ...

Tips for managing event listeners with JavaScript validation and PHP

Hi everyone, I'm a new student learning Web Programming and focusing on Web Development. I encountered an issue while trying to use JavaScript validation with a form submitted to a PHP file. I attempted to utilize event listeners to check the input fi ...

How can I personalize the navigation buttons and indicators of the "react-owl-carousel" component in my React project with CSS or JavaScript?

I've been working on customizing the navigation arrows and dots for the React Owl Carousel npm package using CSS or JS for quite some time now, but have not been successful. I am determined to avoid using jQuery in this project. https://i.sstatic.net ...

Executing a Function Prior to onClick Event of a Link Element in Next.js

While working on a slider/carousel, I encountered an issue. Each photo in the slider should be draggable back and forth, with a click taking the user to a product page. I am using next.js with react-flickity-component for this purpose. Please note that thi ...

Generate a unique class for each img element randomly

Is there a way to assign each image a unique random class instead of giving all the images the same random class? Any help would be appreciated. $(document.body).ready(function () { bgImageTotal = 5; randomNumber = Math.round(Math.random() * (b ...

What is the process for updating the package-lock.json file in Laravel?

GateLab's security feature has identified some known vulnerabilities in the package-lock.json file that need to be updated. The message states: Known security vulnerabilities detected Dependency object-path Version < 0.11.5 Upgrade to ~> 0.11. ...

Steps to execute ajax calls in a sequential manner

Here is a function called loadGraphInSeq that loads graphs in a sequence based on certain conditions. The function iterates through all the div elements with class .graph_box and checks if they are displayed (not hidden). Depending on the name of the graph ...

Encountering the error code 'ERR_EMPTY_RESPONSE' while utilizing an AJAX-powered live search feature

My website features a live AJAX search bar that retrieves records from a MySQL database. However, when users repeatedly conduct searches by modifying the search criteria, some web browsers display an error message stating 'ERR_EMPTY_RESPONSE'. ...

Modify a quartet of divs simultaneously

I am currently working on a project that involves 4 input fields, each accompanied by a dropdown element for selecting currency. My goal is to create a JavaScript function that will update all input fields when one of them is changed. For instance, if I s ...

Loading all assets in advance

Is there a one-size-fits-all method to preload all assets before using them? I need to load various images, audio files, and some .swf files before my application launches. Right now, I load images by creating new <img> elements with the image path a ...

Unlock the full potential of `enableReinitialize: true` by utilizing the options `destroyOnUnmount: false` and `forceUnregisterOnUnmount: false` in a

I am currently working on a wizard form using redux-form/immutable for creating and updating a form. An issue I'm facing is that when moving from tab1 to tab2 in the wizard form, the state (user inputs) in tab1 gets lost. I have experimented with di ...

The result of the passed variable in the MYSQL query is 0

I've been struggling to execute a very basic MySQL query without any success. Despite all my efforts, searching through forums and attempting various solutions, I can't seem to get it to work. Hopefully, someone can help point out the mistake as ...

Ensuring that the UIview Controller design is always set within a scroll view is essential in order to cater to both

https://i.sstatic.net/1U8uG.pngCurrently, I am utilizing the AutoLayout class for designing purposes and it functions smoothly in portrait mode on all iPhone and iPad devices. However, upon switching to landscape orientation, some views extend beyond the s ...

Executing PHP script using JavaScript via AJAX request

I need to execute a PHP script immediately upon clicking the Submit button without having to refresh the page. I attempted an AJAX call to achieve this, but it seems that the code provided does not work upon clicking. The login.php file is saved in the sa ...