Collision only works 2 sides - c#

So i am trying to make a pacman clone in c#, Visual studio express 2013. I have the maze, and ive put labels on the edges. I have a point with the future coordinates of pacman. If that point doesnt intersect with the labels, pacmans location will take the location of the point. This works just fine when pacman is comming from down or right, however it doesnt work if he comes from right or top. This is also true for the ghosts, whose movement is randomly generated. They both seem to consider the label bigger. I tried to search the internet for why this might be, but i cant seem to find an answer. Ive put down the part with collision check and pacman movement. Thanks in advance
private void timer_Tick(object sender, EventArgs e)
{
//colision check
PictureBox intermed = new PictureBox
{
Location = new Point(pictureBox1.Location.X + pacdirx, pictureBox1.Location.Y + pacdiry),
};
if (!intermed.Bounds.IntersectsWith(label1.Bounds) )
pictureBox1.Location = new Point(pictureBox1.Location.X + pacdirx, pictureBox1.Location.Y + pacdiry);
private void Form3_KeyDown(object sender, KeyEventArgs e)
{
//pacman movement
if (e.KeyCode == Keys.W)
{
pacdiry = -3;
pacdirx = 0;
pictureBox1.Image = Image.FromFile("eat_up.gif");
}
if (e.KeyCode == Keys.S)
{
pacdiry = 3;
pacdirx = 0;
pictureBox1.Image = Image.FromFile("eat_down.gif");
}
if (e.KeyCode == Keys.D)
{
pacdiry = 0;
pacdirx = 3;
pictureBox1.Image = Image.FromFile("eat_right.gif");
}
if (e.KeyCode == Keys.A)
{
pacdiry = 0;
pacdirx = -3;
pictureBox1.Image = Image.FromFile("eat_left.gif");
}
}

Related

Set an object as "Solid" in C# windows Form when developing a stickman platform game

For a school project I need to develop a platform style game purely in C# Windows forms and cannot use any other languages. I have a gravity and movement system sorted already but my character is still able to jump off the map or jump through picture boxes. How would I go about making these objects solid so that the character cannot run through them. Here is my code
What my game looks like:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
bool left;
bool right;
int gravity = 20;
int force;
bool jump;
private void Timer(object sender, EventArgs e)
{
if (left == true)
{
Character.Left -= 15;
if (Character.Image != Properties.Resources.LeftChar)
{
Character.Image = Properties.Resources.LeftChar;
}
}
if (right == true)
{
Character.Left += 15;
if (Character.Image != Properties.Resources.RightChar)
{
Character.Image = Properties.Resources.RightChar;
}
}
if (jump == true)
{
Character.Top -= force;
force -= 1;
}
if (Character.Top + Character.Height >= GameBoundary.Height)
{
Character.Top = GameBoundary.Height - Character.Height;
jump = false;
}
else
{
Character.Top += 10;
}
}
private void keydown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.A)
left = true;
if (e.KeyCode == Keys.D)
right = true;
if (jump != true)
{
if (e.KeyCode == Keys.W)
{
jump = true;
force = gravity;
}
}
}
private void keyup(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.A)
left = false;
if (e.KeyCode == Keys.D)
right = false;
}
}
I created an invisible panel that was the same size of the game called "Gameboundary", this made it possible for the player to walk on the bottom of the window, but I am not sure how I would apply this to the rest of the code. If anybody has any suggestions it will be greatly welcome. Not too good at C# just yet!
Here is a basic Collision Detection system:
public class CollisionDetection
{
public static bool ObjectTouchingOthers(Control Object, int SpaceBetweenObjects)
{
for (int i = 0; i < Object.Parent.Controls.Count; i++)
{
if (Object.Parent.Controls[i].Name != Object.Name)
{
if (Object.Left + Object.Width + SpaceBetweenObjects > Object.Parent.Controls[i].Left && Object.Top + Object.Height + SpaceBetweenObjects > Object.Parent.Controls[i].Top && Object.Left < Object.Parent.Controls[i].Left + Object.Parent.Controls[i].Width + SpaceBetweenObjects && Object.Top < Object.Parent.Controls[i].Top + Object.Parent.Controls[i].Height + SpaceBetweenObjects)
{
return true;
}
}
}
return false;
}
public static bool ObjectTouchingOthers(Control Object, int SpaceBetweenObjects, Control[] ControlsToExclude )
{
for (int i = 0; i < Object.Parent.Controls.Count; i++)
{
if (ControlsToExclude.Contains(Object.Parent.Controls[i]) == false && Object.Parent.Controls[i].Name != Object.Name)
{
if (Object.Left + Object.Width + SpaceBetweenObjects > Object.Parent.Controls[i].Left && Object.Top + Object.Height + SpaceBetweenObjects > Object.Parent.Controls[i].Top && Object.Left < Object.Parent.Controls[i].Left + Object.Parent.Controls[i].Width + SpaceBetweenObjects && Object.Top < Object.Parent.Controls[i].Top + Object.Parent.Controls[i].Height + SpaceBetweenObjects)
{
return true;
}
}
}
return false;
}
}
The first argument Object is the control you want collision detection for, and it will only detect other controls in the same container, so if you used it for a control in a panel, for example, it would only work with other controls in the panel, likewise with a Form or any other control. The second argument simply specifies how much distance you want between the controls when they are touching. If you're using the second overload, the third argument is an array of controls that you do not want collision detection for. This is how you would use the second overload:
private void btnMoveLeft_Click(object sender, EventArgs e)
{
btnPlayer.Left -= 1;
if (CollisionDetection.ObjectTouchingOthers(btnPlayer, 1, new Control[] {button1, button2}) == true)
{
btnPlayer.Left += 1;
}
}
With this overload, it will continue right through the controls you specified in the array.
And just to wrap it up, here's a basic example of how to set up collision detection:
private void btnMoveLeft_Click(object sender, EventArgs e)
{
btnPlayer.Left -= 1;
if (CollisionDetection.ObjectTouchingOthers(btnPlayer, 1) == true)
{
btnPlayer.Left += 1;
}
}
private void btnMoveRight_Click(object sender, EventArgs e)
{
btnPlayer.Left += 1;
if (CollisionDetection.ObjectTouchingOthers(btnPlayer, 1) == true)
{
btnPlayer.Left -= 1;
}
}
private void btnMoveUp_Click(object sender, EventArgs e)
{
btnPlayer.Top -= 1;
if (CollisionDetection.ObjectTouchingOthers(btnPlayer, 1) == true)
{
btnPlayer.Top += 1;
}
}
private void btnMoveDown_Click(object sender, EventArgs e)
{
btnPlayer.Top += 1;
if (CollisionDetection.ObjectTouchingOthers(btnPlayer, 1) == true)
{
btnPlayer.Top -= 1;
}
}
Just remember that you're going to have to change the names of the controls in the code I have here. And for reference, here is my test form:
You need to implement collision detection. Draw an imaginary box around your person and any objects you don't want him to pass through. Check if any of the boxes overlap. If they do, move one or both of the objects back until the boxes no longer overlap.
Picture boxes has a .Bounds with a .IntersectWith and this will take an object of type Rectangle.
In a game, you will typically have an ongoing timer, checking all sorts of stuff and progressing time.
In this timer i would make a:
if (pictureBox1.Bounds.IntersectsWith(pictureBox2.Bounds))
{
//They have collided
}
You might have a lot of objects, so you could make a List<PictureBox> and add those objects, then the list will have refferences to those PictureBoxes, that means that they will automatically be updated with the right bounds, when you go through the List.
Be sure to make the List a public property of your form class. Then before rolling through the List, instead set another List = to the public object List. This ensures that you can do a foreach() loop without getting exceptions.

How to make a picturebox rotate only once in c#?

I'm making a mini game. I want to rotate my player with this code when I turn left and right picPlayer.Image.RotateFlip(RotateFlipType.RotateNoneFlipX) My moving code is:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
//when one of the movement keys are pressed,
//makes it's variable true.
if (e.KeyCode == Keys.Right || e.KeyCode == Keys.D)
{
moveRight = true;
}
}
Also, my timer's program is:
private void tmrMovementPlayer_Tick(object sender, EventArgs e)
{
//whenever right arrow is pressed,
if (moveRight == true)
{
//decrease the x variable by 5 (moves right)
x = x + PLAYER_SPEED;
//check for boundaries (if the player is out of the screen)
if (x >= this.ClientSize.Width - picPlayer.Width)
{
//if yes, set it back to the boundary.
x = this.ClientSize.Width - picPlayer.Width;
}
//check the subprogram for info
MovePlayer();
}
}
What should I do at this point? Thanks.
So thanks to the other answer, I found the solution. It was a little bit different. I created another boolean called "goingRight" just for the rotation.
if (e.KeyCode == Keys.Right || e.KeyCode == Keys.D)
{
//make move right true
moveRight = true;
//if i was going left,
if (goingRight == false)
{
//say it im going right
goingRight = true;
//and flip it (only if i was going left before)
picPlayer.Image.RotateFlip(RotateFlipType.RotateNoneFlipX);
}
}
Again, thanks for all the help.
Try something like...
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
//when one of the movement keys are pressed,
//makes it's variable true.
if (e.KeyCode == Keys.Right || e.KeyCode == Keys.D)
{
if (!moveRight)
{
picPlayer.Image.RotateFlip(RotateFlipType.RotateNoneFlipX)
moveRight = true;
}
}
}

How to drag images from a listview (together with an imageview) to pictureboxes?

I am pretty new to C# and struggle a lot with a small project I want to do.
I am busy with something like a collage maker where I have a list of pictures on the left hand side and I want to drag and drop multiple images to the right hand side where I want to be able to move them around to create my collage.
I wanted to show an image but I am not allowed to post images with less than 10 reputation points. But look here for the image:
I can't manage to get it to work. I've looked online for help but I can't really find what I'm looking for. The stuff I do find are too unclear and I struggle to understand.
This is what I have so far for the code to drag and drop from the left to the right but it doesn't work;
private void pictureBox1_DragEnter(object sender, DragEventArgs e)
{
int len = e.Data.GetFormats().Length - 1;
int i;
for (i = 0; i <= len; i++)
{
if (e.Data.GetFormats()[i].Equals("System.Windows.Forms.ListView+SelectedListViewItemCollection"))
{
//The data from the drag source is moved to the target.
e.Effect = DragDropEffects.Move;
}
}
}
private void pictureBox1_DragDrop(object sender, DragEventArgs e)
{
//Return if the items are not selected in the ListView control.
if (listView1.SelectedItems.Count == 0)
{
return;
}
ListViewItem dragitem = listView1.SelectedItems[0];
pictureBox2.Image = imageList1.Images[dragitem.ImageIndex];
listView1.Items.Remove(dragitem);
}
private void listView1_MouseDown(object sender, MouseEventArgs e)
{
listView1.DoDragDrop(listView1.SelectedItems, DragDropEffects.Move);
}
And after I can add image to the left, how can I drag and move them around using the mouse coordinates?
Any help will be appreciated please.
Everything is done using C# in Windows Forms.
Here is a full example you may want to play with:
It uses a form with a ListView, an ImageList and a Panel to hold the PictureBoxes.
You could use a FlowLayoutPanel but this won't let you move the Pictureboxes later.
You also could use a grid of Panels and their BackgroundImage.
First we set up the form:
private void Form1_Load(object sender, EventArgs e)
{
KeyPreview = true;
FillLV(10);
AddPBs(36);
listView1.MouseMove += listView1_MouseMove;
}
void FillLV(int count)
{
for (int i = 0; i < count; i++) listView1.Items.Add("Item" + i, i);
}
void AddPBs(int count)
{
int iWidth = imageList1.ImageSize.Width;
int iHeight = imageList1.ImageSize.Height;
int cols = panel1.ClientSize.Width / iWidth;
for (int i = 0; i < count; i++)
{
PictureBox PB = new PictureBox();
PB.BackColor = Color.LightGray;
PB.Margin = new System.Windows.Forms.Padding(0);
PB.ClientSize = new System.Drawing.Size(iWidth , iHeight );
PB.Location = new Point(iWidth * (i % cols), iHeight * (i / cols));
PB.Parent = panel1;
PB.DragEnter += PB_DragEnter;
PB.DragDrop += PB_DragDrop;
PB.AllowDrop = true;
PB.MouseClick += (ss, ee) => { currentPB = PB; PB.Focus(); };
}
}
Note how we add events to the dynamically created PictureBoxes and how we set their hidden AllowDrop property.
Also note the little lambda to make the MouseClick prepare for moving them around with the keyboard.
For this we will also need a reference to the current box:
PictureBox currentPB = null;
Now we start the dragging. This should not be done in the MouseDown or else it will interfere with normal selection and also happen before the new selection is made..
Either you do it in the MouseMove:
void listView1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
if (listView1.SelectedItems.Count > 0)
{
listView1.DoDragDrop(listView1.SelectedItems[0], DragDropEffects.Move);
}
}
}
Or (Update) for ListViews better and much simpler (thanks Hans!) in their ItemDrag event:
private void listView1_ItemDrag(object sender, ItemDragEventArgs e)
{
listView1.DoDragDrop(e.Item, DragDropEffects.Move);
}
Update: Both ways now use the dragged Item, not just its imageIndex, to make it simpler to remove the Item from the LV..
void PB_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(ListViewItem)))
e.Effect = DragDropEffects.Move;
else
e.Effect = DragDropEffects.None;
}
void PB_DragDrop(object sender, DragEventArgs e)
{
PictureBox pb = sender as PictureBox;
var item = (ListViewItem)e.Data.GetData(typeof(ListViewItem));
int index = item.ImageIndex;
pb.Image = imageList1.Images[index]; // make sure you have images for indices!!
}
Finally we use the keyboard to move the current box around. I have added code to bring it up and down in the z-order as well.
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (currentPB == null) return;
if (e.KeyData == Keys.Left) currentPB.Left -= 1;
else if (e.KeyData == Keys.Right) currentPB.Left += 1;
else if (e.KeyData == Keys.Up) currentPB.Top -= 1;
else if (e.KeyData == Keys.Down) currentPB.Top += 1;
else
{
int z = panel1.Controls.GetChildIndex(currentPB);
if (e.KeyData == Keys.Home) panel1.Controls.SetChildIndex(currentPB, 0);
else if (e.KeyData == Keys.End)
panel1.Controls.SetChildIndex(currentPB, panel1.Controls.Count);
else if (e.KeyData == Keys.PageUp)
panel1.Controls.SetChildIndex(currentPB, z + 1);
else if (e.KeyData == Keys.PageDown)
{ if (z > 0) panel1.Controls.SetChildIndex(currentPB, z - 1); }
}
panel1.Invalidate();
}
For this to work the form must have : KeyPreview = true;
Note that the sizes in an ImageList are restricted to 256x256. So you may want to use only the index and use it to load larger images from disk..

Flip Image(Mirror) in a PictureBox Control

First of all I am a beginner with C#.
I have a picturebox and a timer (enabled, interval = 25).
I have inserted a gif image of a bird in the picturebox.
And in the Timer event I have written,
bool positionBird = true;
private void timer1_Tick(object sender, EventArgs e)
{
if (PictureBox1.Location.X == Screen.PrimaryScreen.Bounds.Width)
{
positionBird = false;
}
else if (PictureBox1.Location.X == 0)
{
positionBird = true;
}
if(positionBird)
{
PictureBox1.Left += 1;
}
else
{
PictureBox1.Left += -1;
}
}
But what I want to achieve is, when the picture box touches the right
boundary and condition become false, I want to flip the image of bird in
the picturebox. Right now the bird is doing Michael Jackson's Moonwalk!
I tried to flip the bird (mirror the bird) using the below code.
else
{
PictureBox pict = new PictureBox();
pict = PictureBox1;
pict.Image.RotateFlip(RotateFlipType.RotateNoneFlipX);
pict.Left += -1;
}
But it looks weird. It shows the flip image and normal image both. Can
someone help me on this? As I already said I am a beginner. Some simple
code with explanation would be very helpful. Also can someone tell me
what I am doing wrong?
DO NOT CREATE another Picture Box. You are seeing the original picture because you have not modified the original but the newly created one.
So the modified code is follows:
bool positionBird = true;
private void timer1_Tick(object sender, EventArgs e)
{
if (PictureBox1.Location.X == Screen.PrimaryScreen.Bounds.Width)
{
positionBird = false;
PictureBox1.Image.RotateFlip(RotateFlipType.RotateNoneFlipX); // picture flips only once when touches boundary
}
else if (PictureBox1.Location.X == 0)
{
positionBird = true;
PictureBox1.Image.RotateFlip(RotateFlipType.RotateNoneFlipX); // picture flips only once when touches boundary
}
if(positionBird)
{
PictureBox1.Left += 1;
}
else
{
PictureBox1.Left += -1;
}
}

Separating mouse down and mouse click events

I have two events wired to a control. A mouse click event plays an audio file. A drag event made up from mouse down, mouse move and mouse up drags the control vertically. By dragging the control vertically the control get assigned a different song.
The problem I have is that when I drag the control the music plays. I do not want this since this is a dragging operation.
Music should play only when control is clicked and note moved.
I think that setting boundaries, e.g. when control moves only 5 pixels play sound otherwise drag control should solve the problem but I tried to create them unsuccessfully.
Can you please guide how to solve this problem preferably with code snippets.
Thank You.
The Drag
int Locked_yLoc; int index;
private void StartDrag(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
sp1.SoundLocation = this.pitch + ".wav";
sp1.Play();
tm1.Interval = 100 * this.noteDuration;
tm1.Start();
isDragging = true;
pitch = e.Y;
this.Location = new Point(this.Location.X, pitch);
}
}
private void StopDrag(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
isDragging = false;
this.Location = new Point(this.Location.X, Locked_yLoc);
pitch = index;
//lbl8.Text = pitch.ToString();
}
}
private void OnDrag(object sender, MouseEventArgs e)
{
if (isDragging)
{
this.Top = this.Top + (e.Y - pitch);
Locked_yLoc = (int)Math.Round((this.Top + (e.Y - pitch)) / 10.0) * 10;
for (int i = 0; i < yLocation.Length; i++)
{
if (Locked_yLoc == yLocation[i])
{
index = CorrPitch[i];
}
}
}
}
The Click
private void MusicNote_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
sp1.SoundLocation = this.pitch + ".wav";
sp1.Play();
tm1.Interval = 100 * this.noteDuration;
tm1.Start();
}
}

Categories