Instructions on incorporating a logical condition for an object that is entering a region in motion

I am currently in the process of developing a new game concept. The goal of the game is to maneuver a square across the screen while avoiding raindrops that fall from the top of the canvas. I need assistance with programming the logic so that when a raindrop intersects with the square, it resets back to the starting position at x = 0. Below is the current code snippet:

var canvas = document.getElementById('game');
var ctx = canvas.getContext('2d');

var WIDTH = 1000;
var HEIGHT = 700;
var x = 0;
var y = HEIGHT-20;
var xPos = [0];
var yPos = [0];
var speed = [1];
var rainDrops = 50;
var rectWidth = 20;
var rectHeight = 20;

for (var i = 0; i < rainDrops; i++) {
    xPos.push(Math.random() * WIDTH);
    yPos.push(0);
    speed.push(Math.random() * 5);
}

function rainFall () {

    window.requestAnimationFrame(rainFall);
    ctx.clearRect(0, 0, WIDTH, HEIGHT);

    for (var i = 0; i < rainDrops; i++) {
        //Rain
        ctx.beginPath();
        ctx.arc(xPos[i], yPos[i], 3, 0, 2 * Math.PI);
        ctx.fillStyle = 'blue';
        ctx.fill();

        //Rain movement
        yPos[i] += speed[i];

        //Square
        ctx.fillStyle = 'red';
        ctx.fillRect(x, y, rectWidth, rectWidth);

        if (yPos[i] > HEIGHT) {
            yPos[i] = 0;
            yPos[i] += speed[0];
        }

        //Logic to reset square position
        if (/*condition*/) {
            x = 0;
        }
    }
};

//Move square object

function move(e) {
    if (e.keyCode === 37) {
        ctx.clearRect(0, 0, WIDTH, HEIGHT);
        x -= 10;
    }
    if (e.keyCode === 39) {
        ctx.clearRect(0, 0, WIDTH, HEIGHT);
        x += 10;
    }
    canvas.width = canvas.width;
}

//Lock arrow key events

window.addEventListener("keydown", function(e) {
    if ([37, 39].indexOf(e.keyCode) > -1) {
        e.preventDefault();
    }
}, false);

rainFall(); 
document.onkeydown = move;
window.addEventListener("load", doFirst, false);

Answer №1

Conditions and Decisions

I find myself in a bit of a dilemma when it comes to answering these types of questions. As you're just starting out, I want to avoid overwhelming you with complex code and techniques, yet at the same time, I don't want to promote any incorrect practices.

The Simple Answer

First off, let's address your code snippet:

//This is the part where I need the Help!!!!!!!!!
// the test checks the center of the drop 
// if drop is greater than > top of player (y) and (&&) 
// drop x  greater than > left side of player x and (&&) drop is less than <
// right side of player (x + rectWidth) then drop has hit player   
if (yPos[i] > y && xPos[i] > x && xPos[i] < x + rectWidth ){
    x = 0; // move player back
}

By the way, you're drawing the player's rectangle for each raindrop. It would be better to move that draw function outside the loop.

The Detailed Answer

I hope my explanation isn't too confusing, and I've included ample comments to clarify my decisions.

To maintain organization, I segment different elements into separate objects - the player, rain, and keyboard handler. These components are coordinated through the mainLoop, which is triggered once per frame using requestAnimationFrame and executes necessary functions.

The player object encompasses all player-related data and functions for drawing and updating the player's position.

The rain object contains an array called rain.drops to store raindrops along with functions for drawing, updating, randomizing drops, and adding new ones.

In determining if rain hits the player, I handle this check within the rain.update function while moving the raindrops. Since I'm unsure of the desired outcome upon impact, I simply reset the raindrop and increment a hit counter.

Initially, I inspect whether the raindrop's bottom (drop.y + drop.radius) surpasses the player's top (player.y), thus omitting unnecessary evaluations for rain above the player.

Next, I evaluate the rain horizontally. Assessing for non-collision scenarios simplifies logic. If the drop's right is left of the player's left or its left is right of the player's right, I determine the drop doesn't contact the player by putting the condition inside parentheses and preceding it with a negation operator if(! ( ... ) ).

Given the complexity of the test, I break it into two lines for clarity.

// drop is a single rain drop player is the player
 if (drop.y + drop.radius >= player.y) {
     if (! (drop.x + drop.radius < player.x || 
     drop.x - drop.radius > player.x + player.width)) { 
         // code for player hit by rain in here
     }
 }

Furthermore, the rain.update function also checks if raindrops touch the canvas' bottom and resets them accordingly.

Live Demonstration

I've tweaked and incorporated your provided code into a functional setup.

addEventListener("load",function(){  
    var canvas = document.getElementById('gameCanvas');
    var ctx = canvas.getContext('2d');
    ctx.font = "20px arial";
    var frameCount = 0;

    var WIDTH = canvas.width;
    var HEIGHT = canvas.height;    
    var currentMaxDrops = 5;
    const numberFramesPerRainIncrease = 60 * 5;
    const maxRainDrops = 150;  
    
    addEventListener("keydown", keyEvent);
    addEventListener("keyup", keyEvent);    
    requestAnimationFrame(mainLoop);

    const keys = {  
        ArrowLeft : false,
        ArrowRight : false,
    }
    function keyEvent(event){  
        if(keys[event.code] !== undefined){
            event.preventDefault();  
            keys[event.code] = event.type === "keydown";  
        }
    }


    const player = {  
        x : 0,          
        y : HEIGHT - 20,  
        width : 20,      
        height : 20,      
        speed : 4,       
        color : "red",
        showHit : 0,  
        hitCount : 0,   
        status(){  
            if(player.hitCount === 0){
                return "Dry as a bone.";
            }
            if(player.hitCount < 5){
                return "A little damp.";
            }
            if(player.hitCount < 15){
                return "Starting to get wet.";
            }
            return "Soaked to the core";
        },
        draw(){  
           if(player.showHit > 0){
               player.showHit -= 1; 
               ctx.fillStyle = "blue";
           }else{
               ctx.fillStyle = player.color;
           }
           ctx.fillRect(player.x,player.y,player.width,player.height);
        },
        update(){ 
           if(keys.ArrowLeft){
               player.x -= player.speed;  
               keys.ArrowLeft = false; 
               if(player.x < 0){ 
                    player.x = 0; 
               }
           }
           if(keys.ArrowRight){
               player.x += player.speed;  
               keys.ArrowRight = false; 
               if(player.x + player.width >= WIDTH){ 
                    player.x = WIDTH - player.width; 
               }
           }
        }
            
    }

    const rain = {  
        numberRainDrops : 50,
        drops : [],  
        randomizeDrop(drop){ 
            drop.x = Math.random() * WIDTH;  
            drop.y = -10;                      
            drop.radius = Math.random() *3 + 1; 
            drop.speed = Math.random() * 4 + 1; 
            return drop;
        },
        createDrop(){  
            if(rain.drops.length < currentMaxDrops){
                rain.drops.push(rain.randomizeDrop({}));
                rain.numberRainDrops = rain.drops.length;
            }
        },
        draw(){    
            ctx.beginPath();  
            ctx.fillStyle = 'blue';  
            for(var i = 0; i < rain.drops.length; i ++){
                var drop = rain.drops[i]; 
                ctx.arc(drop.x, drop.y, drop.radius, 0, 2 * Math.PI);
                ctx.closePath(); 
            }        
            ctx.fill();    
        },
        update(){
            for(var i = 0; i < rain.drops.length; i ++){
                var drop = rain.drops[i]; 
                drop.y += drop.speed;     
                if(drop.y + drop.radius >= player.y){ 
                     if(!(drop.x + drop.radius < player.x || 
                        drop.x - drop.radius > player.x + player.width)){ 
                        player.hitCount += 1;
                        player.showHit += 5;
                        rain.randomizeDrop(drop); 
                     }
                }
                if(drop.y > HEIGHT + drop.radius){ 
                      rain.randomizeDrop(drop); 
                }
            }        
        }
    }
            
    function mainLoop () {  
        requestAnimationFrame(mainLoop);  
        ctx.clearRect(0, 0, WIDTH, HEIGHT);
        frameCount += 1; 
        if(frameCount % numberFramesPerRainIncrease === 0){
            if(currentMaxDrops < maxRainDrops){
               currentMaxDrops += 1;
            }
        }
        
        rain.createDrop(); 
        rain.update();  
        player.update();   
        player.draw();   
        rain.draw();  
        ctx.fillStyle = "black";
        ctx.fillText("Hit " + player.hitCount + " times.",5,20);
        ctx.setTransform(0.75,0,0,0.75,5,34); 
        ctx.fillText(player.status(),0,0); 
        ctx.setTransform(1,0,0,1,0,0); 
    };

});
canvas {
   border : 2px black solid;
}
<canvas id="gameCanvas" width=512 height=200></canvas>

I trust this information proves valuable to you.

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

Steps to extract selected values from the MUI data grid

Can values be retrieved from a mui DataGrid? I have a table and I would like to create a custom export that takes into account user filters and the display status of columns. However, I need to access these filtered values. Is there a way to achieve this ...

Obtaining JavaScript data using Python Selenium Web Driver

I have been attempting to execute a javascript file within a Python script using Selenium WebDriver in order to retrieve the return value from the function. Despite my efforts and research, I have not been successful after spending several hours on this ta ...

HTTP request form

I'm currently working on a form that utilizes XMLHttpRequest, and I've encountered an issue: Upon form submission, if the response is 0 (string), the message displayed in the #output section is "Something went wrong..." (which is correct); Howe ...

What is the best way to retrieve the values of various input fields using their numbered IDs and then store them in a MySQL

I attempted to design a form that allows for multiple inserts, where users can add as many titles and languages as they desire by entering a number. The display of titles and languages is functioning correctly, but I am struggling to retrieve the individua ...

Issues with the HTML required attribute not functioning properly are encountered within the form when it is

I am encountering an issue with my modal form. When I click the button that has onclick="regpatient()", the required field validation works, but in the console, it shows that the data was submitted via POST due to my onclick function. How can I resolve thi ...

What is the way to execute a function *once* all my ajax call functions have finished?

I am utilizing jQuery to execute some ajax requests: var information = {}; function process_information(item){ information[item.id] = item; } function perform(){ var calls = []; for(var i = 0; i < 10; i++){ var call = $.get(URL, ...

Troubleshooting issue: JSON.stringify function returning 'undefined'

Having some trouble with JSON in JavaScript. I've been using JSON.stringify without issue until now. But suddenly, when I try to use it in my application, I keep getting this error in the console (Google Chrome): Uncaught TypeError: undefined is not ...

What is the proper way to incorporate a ref within a class component?

I am encountering an issue with my class component. I'm wondering if there is a comparable feature to useRef() in class components? Despite several attempts at researching, I have yet to find a solution. ...

What is the best way to assign user input to my JavaScript variables?

As a newcomer to programming, I am eager to develop an app that utilizes the numerical values inputted by customers as variables for calculations. How can I extract the value from an input using JavaScript? For instance, how can I subtract one input value ...

the status of timers across various servers

I have come across a minor architecture issue that I am seeking help to resolve. My website sells products with limited inventory, and when a customer clicks the purchase button, my server updates the database with the details of the potential sale. This i ...

Troubleshooting Puppeteer compatibility issues when using TypeScript and esModuleInterop

When attempting to use puppeteer with TypeScript and setting esModuleInterop=true in tsconfig.json, an error occurs stating puppeteer.launch is not a function If I try to import puppeteer using import * as puppeteer from "puppeteer" My questi ...

Looking to extract a specific field using Angular JS?

The JSON data I need is fetched from the link provided below: http://maps.googleapis.com/maps/api/geocode/json?address=SFO When retrieving the JSON, only the parameter example ?adress=sfo should be used. This will result in fetching all values associated ...

AngularJS ui-router, html5Mode, and Express causing "Cannot GET" error in nested state

Currently, I am facing an issue while trying to implement $locationProvider.html5Mode(true) with AngularJS, ui-router, and ExpressJS. The problem arises when navigating to a nested state parent.child with URL /child, as refreshing the page or directly typi ...

Issues with rendering HTML5 drag and drop styles are not visible on a Windows Server 2003 platform

I am currently developing a file upload tool utilizing Valum's Ajax-Uploader as the foundation. The concept is reminiscent of how attaching files works in Gmail. Users should be able to simply drag and drop a file from their desktop into the browser w ...

Tips for avoiding automatic updates to .js scripts after pressing F5

Is there a method to stop a JavaScript script from resetting when the user refreshes the page? For instance, if I have a picture slider that is constantly changing images, I would like the script to continue where it left off instead of starting over wit ...

Displaying HTML content using Typescript

As a newcomer to typescript, I have a question regarding displaying HTML using typescript. Below is the HTML code snippet: <div itemprop="copy-paste-block"> <ul> <li><span style="font-size:11pt;"><span style="font-family ...

Exploring Angular2: A Guide to Interpolating Expressions in Templates

Is it possible to interpolate different types of Javascript expressions? Along with displayed properties like object.property and short expressions such as {{1+1}}, what other valid Javascript expressions can be used for interpolation? ...

What is the best way to transfer data to a component that is not directly related

I am looking to showcase an image, title, and description for a specific recipe that I select. Here is my setup using ItemSwiper (parent): <template> <Slide v-for="recipe in storeRecipe.data" :key="recipe.rec ...

Using AngularJS to transfer data from a datepicker to an ng-model

I am currently trying to figure out how to pass the date from a datetimepicker into the model. Unfortunately, I am facing some challenges with this process. I wish I could provide a demo of the issue on a fiddle, but I am unsure of how to do so due to the ...

An HTML attribute with a blank value will not display the equals sign operator

jQuery can be used like this: $select.append('<option value="">All</option>'); This code appears to insert the element in HTML as follows: <option value>All</option> However, what is intended is to append the elemen ...