Check collision and prevent overlap - c#

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

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

Selected PictureBox don't move on KeyDown

I have PictureBoxes and I just choose from them via the onClick function and then if it doesn't have a "King" tag, I can move with it ... But I can only do that if I have the MessageBox there (It was only there for the test , if it takes a tag) and if I remove it now, I can't move with it.
private void PictureBoxIsClicked(object sender, MouseEventArgs e)
{
selectedPlayer = (PictureBox)sender;
if (e.Button == MouseButtons.Left)
{
//Choosing King
if (isClicked == true && readyToPlay == false)
{
selectedPlayer.Image = Properties.Resources.CharRed;
selectedPlayer.Tag = "King";
isKing = true;
}
isClicked = false;
//Select pictureBox to move
if (readyToPlay == true)
{
label2.Text = String.Format("{0}", selectedPlayer.Tag.ToString());
label1.Show();
MessageBox.Show(selectedPlayer.Tag.ToString());
}
}
}
private void KeyIsDown(object sender, KeyEventArgs e)
{
if(selectedPlayer.Tag.ToString() != "King")
{
//Move forward
if (e.KeyCode == Keys.Up)
{
forward = true;
}
//Move backward
if (e.KeyCode == Keys.Down)
{
backward = true;
}
//Move Left
if (e.KeyCode == Keys.Left)
{
left = true;
}
//Move right
if (e.KeyCode == Keys.Right)
{
right = true;
}
}
}
private void GameTimerEvent(object sender, EventArgs e)
{
//Movement - Player
if(forward == true)
{
selectedPlayer.Top -= 120;
forward = false;
}
if (backward == true)
{
selectedPlayer.Top += 120;
backward = false;
}
if (left == true)
{
selectedPlayer.Left -= 120;
left = false;
}
if (right == true)
{
selectedPlayer.Left += 120;
right = false;
}
}
Why does it fail?

How do I move an object using a timer and the key press event (Like snake)

I want to move a button automatically using a timer and want it to change direction when another key is pressed, kinda like what happens in snake
I have used a string to set what the direction should be, but this doesn't work.
string x = "right";
public Form1()
{
InitializeComponent();
timer1.Interval = 1000;
timer1.Start();
}
private void Player_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.W)
{
string x = "up";
}
else if (e.KeyCode == Keys.S)
{
string x = "down";
}
else if (e.KeyCode == Keys.D)
{
string x = "right";
}
else if (e.KeyCode == Keys.A)
{
string x = "left";
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Timer1_Tick(object sender, EventArgs e)
{
while (x == "up")
{
Player.Top -= 10;
}
while (x == "down")
{
Player.Top += 10;
}
while (x == "right")
{
Player.Left += 10;
}
while (x == "left")
{
Player.Left -= 10;
}
}
}
The button just disappears, but I want it to move by ten until it gets a key press like "D" then it changes direction
1: You are creating variable 'x' every time means locally in player_keyDown event so create it globally.
2: you are using while loop it, not needed as you are already using timer_tick.
3: Instead of Top, Left use Location property of button it gives you X, Y co-ordinate
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
timer1.Interval = 1000;
timer1.Start();
}
string x = "right";
private void Player_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.W)
{
x = "up";
}
else if (e.KeyCode == Keys.S)
{
x = "down";
}
else if (e.KeyCode == Keys.D)
{
x = "right";
}
else if (e.KeyCode == Keys.A)
{
x = "left";
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (x == "up")
{
Player.Location = new System.Drawing.Point(Player.Location.X, Player.Location.Y - 10);
}
if (x == "down")
{
Player.Location = new System.Drawing.Point(Player.Location.X, Player.Location.Y + 10);
}
if (x == "right")
{
Player.Location = new System.Drawing.Point(Player.Location.X + 10, Player.Location.Y);
}
if (x == "left")
{
Player.Location = new System.Drawing.Point(Player.Location.X - 10, Player.Location.Y);
}
}
}

How to prevent two events about the same thing happening

Basically,I am a beginner in C# and I just started working on a simple platformer game following a basic Visual Studio 2015 tutorial.This is the code:
public partial class Form1 : Form
{
bool goleft = false;
bool goright = false;
bool jumping = false;
int JumpSpeed = 10;
int force = 8;
int score = 0;
public Form1()
{
InitializeComponent();
}
private void keyisdown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Left)
{
goleft = true;
}
if (e.KeyCode == Keys.Right)
{
goright = true;
}
if (e.KeyCode == Keys.Space && !jumping)
{
jumping = true;
}
}
private void keyisup(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Left)
{
goleft = false;
}
if (e.KeyCode == Keys.Right)
{
goright = false;
}
if (jumping)
{
jumping = false;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
player.Top += JumpSpeed;
if (jumping && force < 0)
{
jumping = false;
}
if (goleft)
{
player.Left -= 5;
}
if (goright)
{
player.Left += 5;
}
if (jumping)
{
JumpSpeed = -12;
force -= 1;
}
else
{
JumpSpeed = 12;
}
foreach (Control x in this.Controls)
{
if (x is PictureBox && x.Tag == "p")
{
if (player.Bounds.IntersectsWith(x.Bounds) && !jumping)
{
force = 8;
player.Top = x.Top - player.Height;
}
}
if (player.Bounds.IntersectsWith(Door.Bounds))
{
timer1.Stop();
MessageBox.Show("You Won!");
this.Close();
}
}
}
}
The gravity force and everything works great EXCEPT for one big problem with the player that I definitely can't solve without some help.
The problem is: the player is completely glitched and it keeps going up and down. I realised that this is because of two lines in private void timer1_Tick(object sender, EventArgs e):
player.Top += JumpSpeed;
and
player.Top = x.Top - player.Height;
Both of these try to change player.Top and interfere with each other. The trouble is that I can't just cut one of the two without destroying the gravity force code. What I think might work is applying player.Top += JumpSpeed; ONLY if(player.Bounds.IntersectsWith(x.Bounds) && !jumping) = false but I don't know how to write the code this way at all (previous tries always ended up with errors).
Thanks in advance for any help and please forgive any grammar errors that I made because I am not a native english speaker.
I don't know how your Form looks like, but with what you provided I would change the code like that:
public partial class Form1 : Form
{
bool goleft = false;
bool goright = false;
int JumpSpeed = 0; //current vertical speed
int force = 8; //initial jump speed
int score = 0;
public Form1()
{
InitializeComponent();
}
private void keyisdown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Left)
{
goleft = true;
}
if (e.KeyCode == Keys.Right)
{
goright = true;
}
if (e.KeyCode == Keys.Space && JumpSpeed==0) //JumpSpeed==0 to prevent "double jump"
{
JumpSpeed = force; //start jumping with full power
}
}
private void keyisup(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Left)
{
goleft = false;
}
if (e.KeyCode == Keys.Right)
{
goright = false;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (goleft)
{
player.Left -= 5;
}
if (goright)
{
player.Left += 5;
}
JumpSpeed -= 1; //decrement the vertical speed = gravity -> choose higher value to bring him back on the ground quicker
player.Top -= JumpSpeed;
if (player.Bounds.IntersectsWith(Door.Bounds))
{
timer1.Stop();
MessageBox.Show("You Won!");
this.Close();
}
foreach (PictureBox x in this.Controls.OfType<PictureBox>())
{
if (x.Tag == "p")
{
if (player.Bounds.IntersectsWith(x.Bounds)) //if the player should be able to jump/walk on something the code is
{
player.Top = x.Top - player.Height;
JumpSpeed = 0; //the player stops falling
}
}
}
}
}
To make sure to player does not fall out of the window place PictureBoxes with tag == p on the floor!
PS:
Feel free to leave a comment!

c# need help by moving a object in two direction

I need help by moving a object on a Panel in two different direction. In example in the right and down direction by pressing the right and left buttons. Java have a a key release method do c# have such a similiar method?
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;
namespace runningRectangle
{
enum Position {Left, Right, Down, Up, LeftUp, LeftDown, RightUp, RightDown }
public partial class Form1 : Form
{
private int x;
private int y;
private Position objPos;
private int speed = 10;
private bool stopPressed = false;
public Form1()
{
InitializeComponent();
x = 50;
y = 50;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.FillRectangle(Brushes.Red, x, y, 50, 50);
}
private void timer1_Tick(object sender, EventArgs e)
{
if(objPos == Position.Right)
{
x += speed;
}else if(objPos == Position.Left)
{
x -= speed;
}
else if (objPos == Position.Down)
{
y += speed;
}
else if (objPos == Position.Up)
{
y -= speed;
} else if (objPos == Position.RightUp)
{
x += speed;
y -= speed;
}
else if (objPos == Position.RightDown)
{
x += speed;
y += speed;
}
else if (objPos == Position.LeftUp)
{
x -= speed;
y += speed;
}
else if (objPos == Position.LeftDown)
{
x -= speed;
y -= speed;
}
Invalidate();
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Right)
{
objPos = Position.Right;
}
else if (e.KeyCode == Keys.Left)
{
objPos = Position.Left;
}
else if (e.KeyCode == Keys.Down)
{
objPos = Position.Down;
}
else if (e.KeyCode == Keys.Up)
{
objPos = Position.Up;
}
else if(e.KeyCode == Keys.Right && e.KeyCode == Keys.Down)
{
objPos = Position.RightDown;
}
else if (e.KeyCode == Keys.Right && e.KeyCode == Keys.Up)
{
objPos = Position.RightUp;
}
else if (e.KeyCode == Keys.Left && e.KeyCode == Keys.Down)
{
objPos = Position.LeftDown;
}
else if (e.KeyCode == Keys.Left && e.KeyCode == Keys.Up)
{
objPos = Position.LeftUp;
}
else if(e.KeyCode == Keys.Space)
{
if (!stopPressed)
{
speed = 0;
stopPressed = true;
}
else if(stopPressed)
{
speed += 10;
stopPressed = false;
}
}
}
}
}
Form1_KeyDown and Form1_KeyUp exist in pair.
enum Position { None = -1, Left, Right, Down, Up, LeftUp, LeftDown, RightUp, RightDown }
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
objPos = (Position)(-1);
}

How can i stop my player from moving in a direction when a collision is made

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Game1
{
public partial class Form1 : Form
{
Graphics g;
Rectangle Player;
Rectangle Enemy;
Boolean left;
Boolean right;
Boolean up;
Boolean down;
int Playerx, Playery, Playerw, Playerh;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Playerx = 0;
Playery = 0;
Playerw = 32;
Playerh = 32;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
g = e.Graphics;
//Draw Player
Player = new Rectangle(Playerx, Playery, Playerw, Playerh);
g.FillRectangle(Brushes.Blue, Player);
//Draw Enemy
Enemy = new Rectangle(100, 100, 32, 32);
g.FillRectangle(Brushes.Red, Enemy);
if (Player.IntersectsWith(Enemy.Left))
{
left = false;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (left == true)
{
Playerx -= 5;
}
if (right == true)
{
Playerx += 5;
}
if (up == true)
{
Playery -= 5;
}
if (down == true)
{
Playery += 5;
}
Invalidate();
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.A)
{
left = true;
right = false;
up = false;
down = false;
}
if (e.KeyCode == Keys.D)
{
right = true;
left = false;
up = false;
down = false;
}
if (e.KeyCode == Keys.W)
{
up = true;
down = false;
left = false;
right = false;
}
if (e.KeyCode == Keys.S)
{
down = true;
up = false;
left = false;
right = false;
}
}
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.A)
{
left = false;
}
if (e.KeyCode == Keys.D)
{
right = false;
}
if (e.KeyCode == Keys.W)
{
up = false;
}
if (e.KeyCode == Keys.S)
{
down = false;
}
}
}
}
I want to make the player stop moving when it touches the left side of the enemy but i keep getting an error, and it highlights
if (Player.IntersectsWith(Enemy.Left)) and says Can't convert int into System.Drawing.Rectangle any ideas?
I have tried to see if this works
if (Player.IntersectsWith(Enemy))
{
left = false;
right = false;
up = false;
down = false;
}
but of course it keeps the player in place.
You seem to want a specific collision.
You should try:
if(Player.X + Player.Width >= Enemy.X && Player.X < Enemy.X)
{
right = false;
}
This way you are checking if the right side of the player intersects the left side of the enemy and the left side of the players position is less than the left side of the enemy's position (the player is to the left of the enemy)
You will have to add in heights and stuff to that collision to make it so you can pass the enemy but I think for what you have posted it should work ok.
NOTE: Code is untested, let me know how you get on.

Categories

Resources