Home > Software engineering >  Check collision and prevent overlap
Check collision and prevent overlap

Time:10-21

I can't seem to figure out how to make this simple animation work, where i have user control over a red square, and it shouldn't overlap/intersect with a black square (e.g. a wall sprite) enter image description here

My best effort is to have stack data structure of keys pressed and if there is an intersection, then we look at (peek) last key pressed and assign a speed of -1. (See line 67 of code) But this doesn't prevent an overlap. Is there a way that I can make it so the user's red rectangle can't overlap with black?

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;

namespace Movement
{
    public partial class Form1 : Form
    {
        bool moveRight, moveLeft, moveUp, moveDown;
        Keys currentInput;
        Keys lastInput;
        Stack pressedKeys = new Stack();
        int speed = 5;
        bool collision = false;
        public Form1()
        {
            InitializeComponent();
            this.CenterToScreen();
            
        }

        private void pbRed_Click(object sender, EventArgs e)
        {

        }

        
        private void moveTimeEvent(object sender, EventArgs e)
        {
            currentInput = Keys.KeyCode;
            //moving left
            if (moveLeft == true && pbRed.Left > 7 )
            {
                pbRed.Left -= speed;
            }
            //moving right
            if (moveRight == true && pbRed.Left < 750)
            {
                pbRed.Left  = speed;
            }
            //moving up
            if(moveUp == true && pbRed.Top > 7)
            {
                pbRed.Top -= speed;
            }    
            //moving down
            if(moveDown == true && pbRed.Top < 400)
            {
                pbRed.Top  = speed;
            }
            if (moveLeft == true || moveRight == true || moveUp == true || moveDown == true)
            {
                pressedKeys.Push(currentInput);
                
            }
            Collision();
            

        }
         private void Collision()
        {
            
            //collision detection
            if(pbRed.Bounds.IntersectsWith(pbBlack.Bounds))
            { 
                collision = true;
                if(collision)
                {
                    lastInput = (Keys)pressedKeys.Peek();
                    if(currentInput == lastInput)
                    {
                        speed = -1;
                    }
                }                
            }
        }

        private void keyisdown(object sender, KeyEventArgs e)
        {
            if(e.KeyCode == Keys.Left)
            {
                moveLeft = true;
                
            }
            if (e.KeyCode == Keys.Right)
            {
                moveRight = true;
                
            }
            if (e.KeyCode == Keys.Up)
            {
                moveUp = true;
                
            }
            if (e.KeyCode == Keys.Down)
            {
                moveDown = true;
                
            }
        }

        private void keyisup(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Left)
            {
                moveLeft = false;
            }
            if (e.KeyCode == Keys.Right)
            {
                moveRight = false;
            }
            if (e.KeyCode == Keys.Up)
            {
                moveUp = false;
            }
            if (e.KeyCode == Keys.Down)
            {
                moveDown = false;
            }
        }
    }
}

CodePudding user response:

When your speed is 5, don't apply a movement of 5 pixels in one go, but apply the 5 steps separately. Before each step, so before actually moving the rectangle, decide whether that one step movement is allowed. Also look at vertical and horizontal movement separately.

using System;
using System.Drawing;
using System.Windows.Forms;

namespace Movement
{
    public partial class Form1 : Form
    {
        bool moveRight, moveLeft, moveUp, moveDown;
        int speed = 5;

        public Form1()
        {
            InitializeComponent();
            this.CenterToScreen();
        }


        private void moveTimeEvent(object sender, EventArgs e)
        {
            // Get movement vector
            Point movement = new Point(0, 0);
            if (moveLeft) movement.X -= 1;
            if (moveRight) movement.X  = 1;
            if (moveUp) movement.Y -= 1;
            if (moveDown) movement.Y  = 1;

            // Speed defines how many steps we move
            for (int i=1; i<= speed; i  )
            {
                // Check vertical movement allowed
                if (movement.X != 0)
                {
                    Rectangle newPosition = pbRed.Bounds;
                    newPosition.X  = movement.X;
                    if (!CheckCollision(newPosition))
                    {
                        movement.X = 0;
                    }
                }

                // Check horizontal movement allowed
                if (movement.Y != 0)
                {
                    Rectangle newPosition = pbRed.Bounds;
                    newPosition.X  = movement.X;
                    newPosition.Y  = movement.Y;
                    if (!CheckCollision(newPosition))
                    {
                        movement.Y = 0;
                    }
                }

                // Apply Actual movement
                if (!movement.IsEmpty)
                {
                    Rectangle newPosition = pbRed.Bounds;
                    newPosition.X  = movement.X;
                    newPosition.Y  = movement.Y;
                    pbRed.Bounds = newPosition;
                }

            }
        }

        // Returns true when movingRecht is allowed position
        private bool CheckCollision(Rectangle movingRect)
        {
            bool lResult = true;

            //collision detection
            lResult = lResult && !pbBlack.Bounds.IntersectsWith(movingRect);


            // Check we remain inside the form
            lResult = lResult && movingRect.Left >= 0;
            lResult = lResult && movingRect.Top >= 0;
            lResult = lResult && movingRect.Right <= ClientRectangle.Right;
            lResult = lResult && movingRect.Bottom <= ClientRectangle.Bottom;

            return lResult;

        }

        private void keyisdown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Left)
            {
                moveLeft = true;

            }
            if (e.KeyCode == Keys.Right)
            {
                moveRight = true;

            }
            if (e.KeyCode == Keys.Up)
            {
                moveUp = true;

            }
            if (e.KeyCode == Keys.Down)
            {
                moveDown = true;

            }
        }

        private void keyisup(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Left)
            {
                moveLeft = false;
            }
            if (e.KeyCode == Keys.Right)
            {
                moveRight = false;
            }
            if (e.KeyCode == Keys.Up)
            {
                moveUp = false;
            }
            if (e.KeyCode == Keys.Down)
            {
                moveDown = false;
            }
        }

    }
}
  • Related