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)
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;
}
}
}
}