Pac Man cross obstacles - c#

I'm doing a Pac-Man game on c# , and pac man cross every obstacles that I pass.
This is the entire code of my Pac-Man game:
using System;
using System.Media;
using System.Windows.Forms;
namespace Pac_Man {
public partial class Form1 : Form
{
Variables:
bool goLeft;
bool goRight;
bool goUp;
bool goDown;
int score = 0;
int totalCoins = 160;
int playerSpeed = 4;
int ghost1 = 4;
int ghost2 = 4;
Initializing:
public Form1()
{
InitializeComponent();
lblGame.Visible = false;
playSound();
}
Play sound:
private void playSound()
{
SoundPlayer simpleSound = new SoundPlayer(#"C:\Users\rsss-\OneDrive\Documentos\Visual Studio 2019\Projects\Pac_Man\Pac_Man\Sound\pacman_beginning.wav");
simpleSound.PlayLooping();
}
Key is down:
private void keyisdown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Up)
{
goUp = true;
}
if (e.KeyCode == Keys.Down)
{
goDown = true;
}
if (e.KeyCode == Keys.Left)
{
goLeft = true;
}
if (e.KeyCode == Keys.Right)
{
goRight = true;
}
}
Key is up:
private void keyisup(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Up)
{
goUp = false;
}
if (e.KeyCode == Keys.Down)
{
goDown = false;
}
if (e.KeyCode == Keys.Left)
{
goLeft = false;
}
if (e.KeyCode == Keys.Right)
{
goRight = false;
}
}
Timer:
private void timer1_Tick(object sender, EventArgs e)
{
int movement = playerSpeed;
if (goLeft)
{
foreach (Control x in this.Controls)
{
if (x is PictureBox && x.Tag == "obstacle" && x.Left == player.Left - playerSpeed && x.Top == player.Top)
{
movement = 0;
break;
}
}
player.Left -= movement;
movement = playerSpeed;
}
else if (goRight)
{
foreach (Control x in this.Controls)
{
if (x is PictureBox && x.Tag == "obstacle" && x.Left == player.Left + playerSpeed && x.Top == player.Top)
{
movement = 0;
break;
}
}
player.Left += movement;
movement = playerSpeed;
}
else if (goUp)
{
foreach (Control x in this.Controls)
{
if (x is PictureBox && x.Tag == "obstacle" && x.Top == player.Top - playerSpeed && x.Left == player.Left)
{
movement = 0;
break;
}
}
player.Top -= movement;
movement = playerSpeed;
}
else if (goDown)
{
foreach (Control x in this.Controls)
{
if (x is PictureBox && x.Tag == "obstacle" && x.Top == player.Top + playerSpeed && x.Left== player.Left)
{
movement = 0;
break;
}
}
player.Top += movement;
movement = playerSpeed;
}
if (player.Left > 641)
{
player.Left = 82;
}
else if (player.Left < 82)
{
player.Left = 641;
}
foreach (Control x in this.Controls)
{
if (x is PictureBox && x.Tag == "ghost")
{
if (((PictureBox)x).Bounds.IntersectsWith(player.Bounds))
{
gameOver();
MessageBox.Show("You Lost!" + "\n" + "Your score is " + score);
this.Close();
}
}
}
Ghosts Movement:
redGhost.Left += ghost1;
orangeGhost.Left += ghost2;
blueGhost.Left -= ghost1;
pinkGhost.Left -= ghost2;
foreach (Control c in this.Controls)
{
if (c is PictureBox && c.Tag == "coin")
{
if (player.Bounds.IntersectsWith(c.Bounds))
{
this.Controls.Remove(c);
score++;
}
}
}
lblScore.Text = "Score: " + score;
if (score == totalCoins)
{
gameOver();
MessageBox.Show("You Win!" + "\n" + "You reach the maximum score: " + score);
this.Close();
}
}
Game Over:
private void gameOver()
{
timer1.Stop();
lblGame.Visible = true;
lblGame.Text = "Game Over!";
}
} }
Basically, I want that the character don't move in that direction if he hits an obstacle.
Anyone can help me?
Thank you.

This is a different and hopefully simpler way to test for obstacle hit, I dont know if it can compile but i hope you get the general idea
First calculate x and y movement, then apply that movement to a copy of the players bounds and check if it intersects with any obstacle, if it does break out of the loop, if not test next obstacle
If no intersections found then move the player
Need to ensure that System.Drawing.Rectangle originalBounds = player.Bounds actually creates a copy of the players bounds, otherwise the player will move back and forward while the loop is running
private void timer1_Tick(object sender, EventArgs e)
{
int moveX = 0;
int moveY = 0;
bool hitObstacle = false;
System.Drawing.Rectangle originalBounds = player.Bounds; // make sure this is a copy of players bounds rectangle.
if(goLeft)
moveX = -playerSpeed;
else if(goRight)
moveX = playerSpeed;
else if (goUp)
moveY = -playerSpeed;
else if (goDown)
moveY = playerSpeed;
originalBounds.Offset(moveX,moveY);
foreach (Control x in this.Controls)
{
if (x is PictureBox && x.Tag == "obstacle") {
if (originalBounds.IntersectsWith(x.Bounds)) {
hitObstacle = true;
break;
}
}
if(hitObstacle==false) {
player.Bounds=originalBounds;
}
if (player.Left > 641)
.....

Related

Moving Pictureboxes from left to right

I have 4 pictureBoxes. I need they move until hit right side and then move to left side and again. But after 1st picturebox hit left side other move closer to him. How fix it ??
link on video with problem
int changePositionX;
bool change = true;
private void timer1_Tick(object sender, EventArgs e)
{
foreach (Control x in this.Controls)
{
if (x is PictureBox && x.Tag != null && x.Tag.ToString() == "enemy")
{
if (x.Location.X < 750 && change == true)
{
changePositionX = x.Location.X + 50;
x.Location = new Point(changePositionX, x.Location.Y);
}
else
{
change = false;
}
if(x.Location.X >= 100 && change == false)
{
changePositionX = x.Location.X - 50;
x.Location = new Point(changePositionX, x.Location.Y);
}
else
{
change = true;
}
}
}
}
Try it like this instead:
private int jumpDistance = 50;
private bool goingRight = true;
private List<PictureBox> PBs = new List<PictureBox>();
private void Form1_Load(object sender, EventArgs e)
{
foreach (PictureBox pb in this.Controls.OfType<PictureBox>())
{
if (pb.Tag != null && pb.Tag.ToString() == "enemy")
{
PBs.Add(pb);
}
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (goingRight)
{
if (PBs.Any(pb => pb.Location.X >= 750))
{
goingRight = !goingRight;
}
}
else
{
if (PBs.Any(pb => pb.Location.X < 100))
{
goingRight = !goingRight; ;
}
}
foreach (PictureBox pb in PBs)
{
if (goingRight)
{
pb.Location = new Point(pb.Location.X + jumpDistance, pb.Location.Y);
}
else // going left
{
pb.Location = new Point(pb.Location.X - jumpDistance, pb.Location.Y);
}
}
}
Here's my code doing its thing with four PictureBoxes:

hold longer will jump higher (C# winforms)

I am trying to make a 2D game in winforms. i want my character to be able to double jump and if i hold the space key (jump) for a long time i will jump higher or if i hold the space key (jump) less i will jump lower (Note that although holding longer will jump higher, but only up to a fixed level, not to infinity). but I can only double jump and only jump 1 fixed distance, not hold the space longer to jump higher or hold it shorter to jump lower, someone help me, below is my code.
public partial class GamePlay_Page : Form
{
bool goRight, goLeft;
int gravity = 16;
int force;
bool jump;
int jumpTimes = 2;
public GamePlay_Page()
{
InitializeComponent();
}
private void GamePlay_Page_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.D)
{
goRight = true;
Trex.Image = Properties.Resources.running;
}
if (e.KeyCode == Keys.A)
{
goLeft = true;
Trex.Image = Properties.Resources.running2;
}
if (e.KeyCode == Keys.W && jumpTimes > 0)
{
jump = true;
force = gravity;
jumpTimes -= 1;
}
private void gameT(object sender, EventArgs e)
{
if (goRight == true && Trex.Right < 600)
{
Trex.Left += 5;
}
if (goLeft == true && Trex.Left > 10)
{
Trex.Left -= 5;
}
if (jump == true)
{
Trex.Top -= force;
force -= 1;
}
if (Trex.Top + Trex.Height >= backgroundAbove.Height)
{
Trex.Top = backgroundAbove.Height - Trex.Height;
}
else
{
Trex.Top += 3;
}
if (Trex.Top + Trex.Height == backgroundAbove.Height)
{
jumpTimes = 2;
}
private void GamePlay_Page_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.D) { goRight = false; }
if (e.KeyCode == Keys.A) { goLeft = false; }
}
I am not sure if this is what you mean, and change it according to your needs.
Please see my example:
Add a stopwatch to judge the length of the pressing time, in order to prevent the intensity from bursting.
What I set is to give a fixed force for pressing more than 3s, otherwise give an initial force for gravity.
Change it according to your needs.
You can completely change it to a force multiplied by time.
Stopwatch watch =new Stopwatch();
watch.Start();//start the timer
watch.Stop(); //stop the timer
watch.ElapsedMilliseconds// Show duration in milliseconds(Type is long)
watch.Reset();//reset the timer
Put the timing start into the KeyDown event:
if (e.KeyCode == Keys.W && jumpTimes > 0)
{
//jump = true;
//force = gravity;
//jumpTimes -= 1;
watch.Start();
}
Put the timing end and trigger the jump into the KeyUp event:
if (e.KeyCode == Keys.W && jumpTimes > 0)
{
watch.Stop();
jump = true;
jumpTimes -= 1;
if (watch.ElapsedMilliseconds > 300)//>3s
{
force = 30;
}
else
{
force = gravity;
}
}
watch.Reset();
All the codes:
using System;
using System.Diagnostics;
using System.Windows.Forms;
namespace GamePlay_Page {
public partial class GamePlay_Page : Form {
public GamePlay_Page () {
InitializeComponent();
}
bool goRight, goLeft;
int gravity = 16;
int force;
bool jump;
int jumpTimes = 2;
Stopwatch watch =new Stopwatch();
private void GamePlay_Page_Load (object sender, EventArgs e) {
}
private void GamePlay_Page_KeyDown (object sender, KeyEventArgs e) {
if (e.KeyCode == Keys.D)
{
goRight = true;
Trex.Image = Properties.Resources.ch;
}
if (e.KeyCode == Keys.A)
{
goLeft = true;
Trex.Image = Properties.Resources.ca;
}
if (e.KeyCode == Keys.W && jumpTimes > 0)
{
//jump = true;
//force = gravity;
//jumpTimes -= 1;
watch.Start();
}
}
private void GamePlay_Page_KeyUp (object sender, KeyEventArgs e) {
if (e.KeyCode == Keys.W && jumpTimes > 0)
{
watch.Stop();
if (e.KeyCode == Keys.W && jumpTimes > 0)
{
watch.Stop();
jump = true;
jumpTimes -= 1;
if (watch.ElapsedMilliseconds > 300)//>3s
{
force = 30;
}
else
{
force = gravity;
}
}
}
watch.Reset();
if (e.KeyCode == Keys.D)
{
goRight = false;
}
if (e.KeyCode == Keys.A)
{
goLeft = false;
}
}
private void Timer1_Tick (object sender, EventArgs e) {
if (goRight == true && Trex.Right < 600)
{
Trex.Left += 5;
}
if (goLeft == true && Trex.Left > 10)
{
Trex.Left -= 5;
}
if (jump == true)
{
Trex.Top -= force;
force -= 1;
}
if (Trex.Top + Trex.Height >= backgroundAbove.Height)
{
Trex.Top = backgroundAbove.Height - Trex.Height;
}
else
{
Trex.Top += 3;
}
if (Trex.Top + Trex.Height == backgroundAbove.Height)
{
jumpTimes = 2;
}
G.Text = gravity.ToString();
F.Text = force.ToString();
T.Text = Trex.Top.ToString();
L.Text = Trex.Left.ToString();
J.Text = jumpTimes.ToString();
W.Text = watch.ElapsedMilliseconds.ToString();
}
}
}
main page:
Output:
If you have questions about my code, please comment below and I will follow up as soon as possible.

c# Platform game optimization issue + player studdering

This is my first question on stackoverflow, sorry if I made stupid mistakes,
I hope you can help me out!
So my game looks kinda laggy when i Run it, my player studders and if I add gifs instead of image's then everything is very slow :/
I used pictureboxes as Image's
Here is my code (I just used one class):
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 ProjectBlok1Remake
{
public partial class myGame : Form
{
bool jump = false;
bool right = false;
bool left = false;
int score = 0;
int jumpspeed = 10;
int force = 8;
System.Media.SoundPlayer sp = new System.Media.SoundPlayer("muziek.wav");
public myGame()
{
InitializeComponent();
sp.Play(); // play music :)
}
private void myGame_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Right)
{
right = true;
}
if (e.KeyCode == Keys.Left)
{
left = true;
}
if (e.KeyCode == Keys.Escape)
{
this.Close(); //exist the game
}
if (jump != true)
{
if (e.KeyCode == Keys.Space)
{
jump = true;
}
}
}
private void myGame_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Right)
{
right = false;
}
if (e.KeyCode == Keys.Left)
{
left = false;
}
if (jump)
{
jump = false;
}
}
private void AddPoints(int valueCoin)
{
score = valueCoin + score;
}
private void GameTimer(object sender, EventArgs e)
{
player.Top += jumpspeed;
if (jump && force < 0)
{
jump = false;
}
if (left)
{
player.Left -= 5;
}
if (right)
{
player.Left += 5;
}
if (jump)
{
jumpspeed = -12;
force -= 1;
}
else
{
jumpspeed = 12;
}
foreach (Control x in this.Controls)
{
if (x is PictureBox && x.Tag == "platform")
{
if (player.Bounds.IntersectsWith(x.Bounds) && !jump)
{
force = 8;
player.Top = x.Top - player.Height;
}
}
if (x is PictureBox && x.Tag == "coin")
{
if (player.Bounds.IntersectsWith(x.Bounds) && !jump)
{
this.Controls.Remove(x); //will remove current touched coin :)
AddPoints(5); // each coin taken, will increase the score with 5 points!
}
}
if (x is PictureBox && x.Tag == "bigCoin")
{
if (player.Bounds.IntersectsWith(x.Bounds) && !jump)
{
this.Controls.Remove(x); //will remove current touched coin :)
AddPoints(15); ; // each coin taken, will increase the score with 15 points!
}
}
this.scoreLabel.Text = "score: " + score;
}
if (player.Bounds.IntersectsWith(door.Bounds))
{
timer1.Stop();
sp.Stop();
MessageBox.Show("Congratulations! YOU WON THE GAME! + \n With a total score of: " + score + "\n Exit the game with escape (2x)");
}
if (player.Bounds.IntersectsWith(panel1.Bounds))
{
timer1.Stop();
sp.Stop();
MessageBox.Show("YOU DIED, GAME OVER! :c");
}
}
}
}
Here is an Image of how the game looks like, All the Image's you see are uploaded from a file.
https://i.stack.imgur.com/8QiIc.png
...but if i delete that, there is no gravity and he can't jump.... I didn't say to delete it. I just pointed the problem of changing the position of the player prior the intersect checking. The way you do it is to chech if the new position is ok then change it:
CODE:
private void GameTimer(object sender, EventArgs e)
{
//Don't change the position of the player but a copy one, playerClone!
Rectangle playerClone = player.Bounds;
playerClone.Y += jumpspeed;
if (jump && force < 0)
{
jump = false;
}
if (left)
{
playerClone.X -= 5;
}
if (right)
{
playerClone.X += 5;
}
if (jump)
{
jumpspeed = -12;
force -= 1;
}
else
{
jumpspeed = 12;
}
foreach (Control x in this.Controls)
{
if (x is PictureBox && x.Tag == "platform")
{
if (playerClone.IntersectsWith(x.Bounds) && !jump)
{
force = 8;
playerClone.Y = x.Top - playerClone.Height;
}
}
if (x is PictureBox && x.Tag == "coin")
{
if (playerClone.IntersectsWith(x.Bounds) && !jump)
{
this.Controls.Remove(x); //will remove current touched coin :)
AddPoints(5); // each coin taken, will increase the score with 5 points!
}
}
if (x is PictureBox && x.Tag == "bigCoin")
{
if (playerClone.IntersectsWith(x.Bounds) && !jump)
{
this.Controls.Remove(x); //will remove current touched coin :)
AddPoints(15); ; // each coin taken, will increase the score with 15 points!
}
}
this.scoreLabel.Text = "score: " + score;
}
if (playerClone.IntersectsWith(door.Bounds))
{
timer1.Stop();
sp.Stop();
MessageBox.Show("Congratulations! YOU WON THE GAME! + \n With a total score of: " + score + "\n Exit the game with escape (2x)");
return;
}
if (playerClone.IntersectsWith(panel1.Bounds))
{
timer1.Stop();
sp.Stop();
MessageBox.Show("YOU DIED, GAME OVER! :c");
return;
}
//And now set the player position
player.Bounds = playerClone;
}

c# variables reset when code is moved from keydown event into a function - can anyone explain why?

I am using a C# windows forms application in VS Express 2010. I'm playing around with some code for the purposes of learning. I have a form object, which I want to continually move in one direction with a key press - original code for this works fine.
In the process of trying to tidy it by moving the code for "movement" into a function, the code no longer works as before. Instead of my object moving from its current position in the direction selected, it now resets its position every time a key is pressed. I was wondering why this is happening, as the change I have made is absolutely minimal. Please see code:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Down)
{
direction = 4;
}
if (e.KeyCode == Keys.Up)
{
direction = 2;
}
if (e.KeyCode == Keys.Right)
{
direction = 3;
}
if (e.KeyCode == Keys.Left)
{
direction = 1;
}
while (direction != 0)
{
Application.DoEvents();
if (direction == 1)
{
X = X - 1;
}
else if (direction == 2)//up
{
Y = Y - 1;
}
else if (direction == 3)
{
X = X + 1;
}
else if (direction == 4)//down
{
Y = Y + 1;
}
Thread.Sleep(100);
label1.Location = new Point(X, Y);
}
}
when I move the while loop into a movement function, the variables X and Y are reset to 0 upon every key press. code for this looks as follows:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Down)
{
direction = 4;
}
if (e.KeyCode == Keys.Up)
{
direction = 2;
}
if (e.KeyCode == Keys.Right)
{
direction = 3;
}
if (e.KeyCode == Keys.Left)
{
direction = 1;
}
movement(X, Y, direction);
}
I feel like I'm missing something obvious here but I don't understand why it's behaving differently. Thanks for any help :)
EDIT 1: The code for the movement function:
movement(int X, int Y, int direction)
{
while (direction != 0)
{
Application.DoEvents();
if (direction == 1)
{
X = X - 1;
}
else if (direction == 2)//up
{
Y = Y - 1;
}
else if (direction == 3)
{
X = X + 1;
}
else if (direction == 4)//down
{
Y = Y + 1;
}
Thread.Sleep(100);
label1.Location = new Point(X, Y);
}
}
I guess your movement method changes X and Y which were supplied as parameters. However, the parameters X and Y are passed 'by value', not 'by reference'.
If you want to make this work, you either have to use class variables, and remove the parameters in the method call, or use ref, which I will demonstrate:
movement(ref X, ref Y, direction);
And:
private void movement(ref int X, ref int Y, int direction)
{ }
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Down) direction = 4;
else if (e.KeyCode == Keys.Up) direction = 2;
else if (e.KeyCode == Keys.Right) direction = 3;
else if (e.KeyCode == Keys.Left) direction = 1;
while (direction != 0)
{
Application.DoEvents();
if (direction == 1) X--;
else if (direction == 2) Y--;
else if (direction == 3) X++;
else if (direction == 4) Y++;
Thread.Sleep(100);
label1.Location = new Point(X, Y);
}
}
Could be rewritten :
private void SetDirection(KeyEventArgs e)
{
if (e.KeyCode == Keys.Down) direction = 4;
else if (e.KeyCode == Keys.Up) direction = 2;
else if (e.KeyCode == Keys.Right) direction = 3;
else if (e.KeyCode == Keys.Left) direction = 1;
}
private void ApplyMovement()
{
while (direction != 0)
{
Application.DoEvents();
if (direction == 1) X--;
else if (direction == 2) Y--;
else if (direction == 3) X++;
else if (direction == 4) Y++;
Thread.Sleep(100);
label1.Location = new Point(X, Y);
}
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
SetDirection(e);
ApplyMovement();
}
You have to understand that the variables X, Y, and direction are class members, so they are accessible from anywhere in your class, and when you call movement(X, Y, direction) then movement plays with copies of those variables, so when you do X = X + 1 inside your movement method, you are not actually changing the X value of your class, but only to the copy of it.
This means that the variables X and Y (i.e. class members) are not reset to 0 upon every key press. In fact they are never set to anything else.
Note that you could also use switch statements instead of all those ifs.
switch (direction)
{
case 1: X--; break; // left
case 2: Y--; break; // up
case 3: X++; break; // right
case 4: Y++; break; // down
}

SlimDX RawInput with WPF

I'm trying to set up keyboard and mouse controls for a space game using SlimDX and RawInput. My current code is as follows:
Device.RegisterDevice(UsagePage.Generic, UsageId.Keyboard, DeviceFlags.None);
Device.KeyboardInput += new EventHandler<KeyboardInputEventArgs>(keyboardInput);
Device.RegisterDevice(UsagePage.Generic, UsageId.Mouse, DeviceFlags.None);
Device.MouseInput += new EventHandler<MouseInputEventArgs>(mouseInput);
However I read here: http://code.google.com/p/slimdx/issues/detail?id=785 that for WPF I need to use a different overload for Device.RegisterDevice(), as well as assigning a HandleMessage using Device.HandleMessage(IntPtr message)
I've found the correct overload for RegisterDevice() which is:
RegisterDevice(UsagePage usagePage, UsageId usageId, DeviceFlags flags, IntPtr target, bool addThreadFilter)
What I can't work out, though, is:
1) Now that I have to use a target, what am I meant to set as a target?
2) Where do I get this IntPtr message from?
This might help, I made this for a game of pong. Hope it helps
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Down)
{
spaceKeyDown = true;
}
if (e.KeyCode == Keys.Up)
{
spaceKeyUp = true;
}
if (e.KeyCode == Keys.W)
{
spaceKeyW = true;
}
if (e.KeyCode == Keys.S)
{
spaceKeyS = true;
}
if (direction == 0)
{
if (e.KeyCode == Keys.Space)
{
Random rand = new Random();
direction = rand.Next(1, 5);
}
}
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Down)
{
spaceKeyDown = false;
}
if (e.KeyCode == Keys.Up)
{
spaceKeyUp = false;
}
if (e.KeyCode == Keys.W)
{
spaceKeyW = false;
}
if (e.KeyCode == Keys.S)
{
spaceKeyS = false;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (spaceKeyDown == true)
{
if (p2y < picPicture.Height - Paddle2.Height)
p2y += 15;
}
if (spaceKeyUp == true)
{
if (p2y > 0)
p2y -= 15;
}
if (spaceKeyS == true)
{
if (p1y < picPicture.Height - Paddle1.Height)
p1y += 15;
}
if (spaceKeyW == true)
{
if (p1y > 0)
p1y -= 15;
}
}

Categories