I have created an animation using C# in Visual Studio, within a pictureBox using multiple images of pacman. I am now attempting to get the pictureBox to move around the form (up, down, right and left) by using the arrow keys but I cannot seem to get it working. Can anyone help me figure out why the pictureBox won't move?
Thanks
Here is my code so far:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Week9
{
public partial class Pacman : Form
{
private Image[] pacmanImage = new Image[4];
private int currentMouthPosition = 0;
private int xPosition = 0;
private int yPosition = 0;
// The index of the current frame.
private int FrameNum = 0;
public Pacman()
{
InitializeComponent();
this.KeyDown +=newSystem.Windows.Forms.KeyEventHandler(this.Pacman_KeyDown);
}
private void picFrame_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawImage(pacmanImage[currentMouthPosition], xPosition, yPosition, 32, 32);
}
// Load the images.
private void Pacman_Load(object sender, EventArgs e)
{
pacmanImage[0] = Image.FromFile("..\\..\\pac32_left_close.png");
pacmanImage[1] = Image.FromFile("..\\..\\pac32_left_open.png");
pacmanImage[2] = Image.FromFile("..\\..\\pac32_left_wide.png");
pacmanImage[3] = Image.FromFile("..\\..\\pac32_left_widest.png");
// Display the first frame.
picFrame.Image = pacmanImage[FrameNum];
}
// This is where I have tried to get the pictureBox to move
private void Pacman_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Left:
picFrame.Left -= 5;
break;
case Keys.Right:
picFrame.Left += 5;
break;
case Keys.Up:
picFrame.Top -= 5;
break;
case Keys.Down:
picFrame.Top += 5;
break;
}
}
// Display the next image.
private void tmrNextFrame_Tick(object sender, EventArgs e)
{
FrameNum = ++FrameNum % pacmanImage.Length;
picFrame.Image = pacmanImage[FrameNum];
}
private void btnStartStop_Click_1(object sender, EventArgs e)
{
tmrNextFrame.Enabled = !tmrNextFrame.Enabled;
if (tmrNextFrame.Enabled) btnStartStop.Text = "Stop";
else btnStartStop.Text = "Start";
}
}
}
private void Pacman_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Left:
mouthcurrentposition = 0;
picFrame.yPosition -= 10;
picFrame.Left(); //This should be a method that will draw your pacman
break;
case Keys.Right:
mouthcurrentposition = 1;
picFrame.yPosition += 10;
picFrame.Right();
break;
case Keys.Up:
mouthcurrentposition = 2;
picFrame.yPosition -= 10;
picFrame.Up();
break;
case Keys.Down:
mouthcurrentposition = 3;
picFrame.yPosition += 10;
picFrame.Down();
break;
}
}
pictureBox1.Location = new Point(x, y);
you can write some codes like this in your form key press event or keydown or keyup events. get the current picture box location and add up or Reduce the position.
you can use this code to get the current position :
pictureBox1.Location.X; //to get X
pictureBox1.Location.Y; // To get Y
I know i'm super hella late but what you missed was this.KeyDown += Pacman_KeyDown on your main form
Related
I'm making a program that lets the user select a score/grade from a combobox and using a button click will calculate the answer for the user. However for some reason when I press calculate button the label text doesn't change at all. Also sorry if the codes messy or looks wrong as I'm still trying to learn.
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 btec_to_ucas
{
public partial class Form1 : Form
{
//These are the values i want displayed on the label
int PPP = 48;
int MPP = 64;
int MMP = 80;
int MMM = 96;
int MMD = 112;
int DDM = 128;
int DDD = 144;
public Form1()
{
InitializeComponent();
}
// below i want whenever the button is pressed it will take the selected answer and display the int onto the label
private void button1_Click(object sender, EventArgs e)
{
{
switch (comboBox1.SelectedIndex)
{
case 0:
if (comboBox1.SelectedIndex == PPP)
{
label1.Text = "48";
}
break;
case 1:
if (comboBox1.SelectedIndex == MPP)
{
label1.Text = "64";
}
break;
case 2:
if (comboBox1.SelectedIndex == MMP)
{
label1.Text = "96";
}
break;
}
}
}
private void label1_Click(object sender, EventArgs e)
{
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
}
} ```
Your switch statement should be like this:
switch (comboBox1.SelectedIndex)
{
case 0:
label1.Text = PPP.ToString();
break;
case 1:
label1.Text = MPP.ToString();
break;
...
I'm trying to preview and resize shapes (just like you would do in Paint) before drawing them. The problem I encountered is that even though I'm using double buffering, I still get horrible flickering, which is a logical result of calling Invalidate() for the region containing the temporary element.
Another issue is that previewing lines using this method causes graphical residue to build up.
The shape also disappears when I stop moving the mouse, with the left mouse button still held down.
PaintForm.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
namespace MyPaint
{
public partial class PaintForm : Form
{
// Where user clicks the first time.
private Point start = Point.Empty;
// Where user releases the mouse button.
private Point end = Point.Empty;
private DrawingElementType currentElementType = DrawingElementType.Line;
private List<DrawingElement> drawingElements;
// Used for double buffering (aka first drawing on a bitmap then drawing the bitmap onto the control).
private Bitmap bmp;
public PaintForm()
{
InitializeComponent();
drawingElements = new List<DrawingElement>();
bmp = new Bitmap(pbCanvas.Width, pbCanvas.Height, PixelFormat.Format24bppRgb);
Graphics.FromImage(bmp).Clear(Color.White);
}
private void pbCanvas_Paint(object sender, PaintEventArgs e)
{
if (bmp != null)
{
bmp.Dispose();
bmp = null;
}
bmp = new Bitmap(pbCanvas.Width, pbCanvas.Height, PixelFormat.Format24bppRgb);
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(Color.White);
g.SmoothingMode = SmoothingMode.AntiAlias;
foreach (var elem in drawingElements)
{
switch (elem.Type)
{
case DrawingElementType.Line:
g.DrawLine(new Pen(Color.BlueViolet), elem.Start, elem.End);
break;
case DrawingElementType.Rectangle:
g.FillRectangle(Brushes.Black, elem.Container);
break;
case DrawingElementType.Ellipse:
g.FillEllipse(Brushes.Bisque, elem.Container);
break;
default:
break;
}
}
}
e.Graphics.DrawImageUnscaled(bmp, new Point(0, 0));
}
private void pbCanvas_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
start = e.Location;
}
}
private void pbCanvas_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
var temp = new DrawingElement(currentElementType, start, e.Location);
using (Graphics g = pbCanvas.CreateGraphics())
{
switch (currentElementType)
{
case DrawingElementType.Line:
g.DrawLine(new Pen(Color.BlueViolet), temp.Start, temp.End);
break;
case DrawingElementType.Rectangle:
g.FillRectangle(Brushes.Black, temp.Container);
break;
case DrawingElementType.Ellipse:
g.FillEllipse(Brushes.Bisque, temp.Container);
break;
default:
break;
}
}
pbCanvas.Invalidate(temp.Container);
}
}
private void pbCanvas_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
end = e.Location;
var elem = new DrawingElement(currentElementType, start, end);
drawingElements.Add(elem);
// This triggers the paint event and only repaints the region of the new element.
pbCanvas.Invalidate(elem.Container);
}
}
private void btnLine_Click(object sender, EventArgs e)
{
currentElementType = DrawingElementType.Line;
}
private void btnEllipse_Click(object sender, EventArgs e)
{
currentElementType = DrawingElementType.Ellipse;
}
private void btnlRectangle_Click(object sender, EventArgs e)
{
currentElementType = DrawingElementType.Rectangle;
}
}
}
DrawingElement.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyPaint
{
enum DrawingElementType
{
Line,
Rectangle,
Ellipse
}
class DrawingElement
{
public Point Start { get; set; }
public Point End { get; set; }
public DrawingElementType Type { get; }
// Returns the region of the control that contains the element.
public Rectangle Container
{
get
{
int width = Math.Abs(End.X - Start.X);
int height = Math.Abs(End.Y - Start.Y);
return new Rectangle(Math.Min(Start.X, End.X), Math.Min(Start.Y, End.Y), width, height);
}
}
public DrawingElement(DrawingElementType type, Point start, Point end)
{
Type = type;
Start = start;
End = end;
}
}
}
I probably fried my brain trying to find workarounds.
Preview of the application
I'm trying to make a game that is round-based, and I want to make it so that the user is able to define the amount of rounds from the beginning. I've made it so that the user will input a number into a text box, and then a button will put that number into a variable called length by using "length = Convert.ToInt32(textBox1.Text)". Unfortunately, I'm not sure how to access this length variable from the Form1 class so that I can set the number of rounds. Can someone please point me in the right direction? I've tried doing SpeedDialog.length (SpeedDialog is a windows form designer class that I'm getting the info from), but it did not seem to work, saying that I cannot reference a non-static class. Could I fix this problem by making SpeedDialog static (I'm thinking not but I could be wrong)? Thank you so much! I really appreciate it!
Here's my Form1 class:
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;
using System.Runtime.InteropServices;
using System.Threading;
namespace BrickO1
{
public partial class Form1 : Form
{
private const int kNumberOfTries = 3;
public int rounds;
private Ball TheBall = new Ball();
private Paddle ThePaddle = new Paddle();
private Paddle TheOtherPaddle = new Paddle();
// private System.Windows.Forms.Timer timer1;
private Score TheScore = null;
private Score TheOtherScore = null;
private Thread oThread = null; //thread is used to run sounds independently
[DllImport("winmm.dll")]
public static extern long PlaySound(String lpszName, long hModule, long dwFlags);
//method PlaySound must be imported from the .dll file winmm
public Form1()
{
InitializeComponent();
ThePaddle.Position.X = 5;
ThePaddle.Position.Y = this.ClientRectangle.Bottom - ThePaddle.Height;
TheOtherPaddle.Position.X = 5;
TheOtherPaddle.Position.Y = 0;
// this.ClientRectangle refers to the current container (the instance of Form1)
TheBall.Position.Y = this.ClientRectangle.Bottom - 200;
TheScore = new Score(ClientRectangle.Right - 30, ClientRectangle.Bottom - 40);
TheOtherScore = new Score(ClientRectangle.Right - 30, ClientRectangle.Bottom - 370);
//positions the score - 0 at this moment
// choose Level
SpeedDialog dlg = new SpeedDialog();
/* makes sure that, if the DialogResult property of the button "OK" is on,
the SpeedDialog form appears and stays on the screen, and timer's Interval
gets an appropriate value */
if (dlg.ShowDialog() == DialogResult.OK)
{
timer1.Interval = dlg.Speed;
}
}
private string m_strCurrentSoundFile = "BallOut.wav"; //sound file is initialized
public void PlayASound() //method to play a sound; to be called by a thread
{
if (m_strCurrentSoundFile.Length > 0)
{
PlaySound(Application.StartupPath + "\\" + m_strCurrentSoundFile, 0, 0);
/* the above gives full path to the location of the sound file from the startup path
of the executable file: Application.StartupPath */
}
m_strCurrentSoundFile = "";
oThread.Abort(); //aborts the tread playing sound
}
public void PlaySoundInThread(string wavefile) //creates and starts a new thread to play a sound
{
m_strCurrentSoundFile = wavefile;
oThread = new Thread(new ThreadStart(PlayASound)); //calls the method PlayASound
oThread.Start();
}
private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e) //method to draw Form1
{
Graphics g = e.Graphics;
g.FillRectangle(Brushes.White, 0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height);
TheScore.Draw(g);
TheOtherScore.Draw(g);
ThePaddle.Draw(g);
TheOtherPaddle.Draw(g);
TheBall.Draw(g);
}
private void CheckForCollision()
{
if (TheBall.Position.X < 0) // hit the left side, switch polarity
{
TheBall.XStep *= -1;
TheBall.Position.X += TheBall.XStep;
PlaySoundInThread("WallHit.wav");
}
if (TheBall.Position.Y < 0) // hit the top of the form
{
//Lost the ball for 2nd paddle
TheScore.Increment();
if(TheScore.Count == SpeedDialog.length)
{
MessageBox.Show("Congrats! Player 1 wins!");
Application.Exit();
}
Reset();
PlaySoundInThread("BallOut.wav");
}
if (TheBall.Position.X > this.ClientRectangle.Right - TheBall.Width) // hit the right side, switch polarity
{
TheBall.XStep *= -1;
TheBall.Position.X += TheBall.XStep;
PlaySoundInThread("WallHit.wav");
}
if (TheBall.Position.Y > this.ClientRectangle.Bottom - TheBall.YStep) // lost the ball!
{
TheOtherScore.Increment();
if (TheScore.Count == SpeedDialog.length)
{
MessageBox.Show("Congrats! Player 2 wins!");
Application.Exit();
}
Reset();
PlaySoundInThread("BallOut.wav");
}
int hp = HitsPaddle(TheBall.Position); //check if the ball hit the paddle
if (hp > -1)// checks if the ball is not lost
{
PlaySoundInThread("PaddleHit.wav");
switch (hp) //new direction of the ball depends on which quarter of the paddle is hit
{
case 1:
TheBall.XStep = -7;
TheBall.YStep = -3;
break;
case 2:
TheBall.XStep = -5;
TheBall.YStep = -5;
break;
case 3:
TheBall.XStep = 5;
TheBall.YStep = -5;
break;
default:
TheBall.XStep = 7;
TheBall.YStep = -3;
break;
}
}
int hp2 = HitsPaddle2(TheBall.Position); //check if the ball hit the paddle
if (hp2 > -1)// checks if the ball is not lost
{
PlaySoundInThread("PaddleHit.wav");
switch (hp2) //new direction of the ball depends on which quarter of the paddle is hit
{
case 1:
TheBall.XStep = -7;
TheBall.YStep = 3;
break;
case 2:
TheBall.XStep = -5;
TheBall.YStep = 5;
break;
case 3:
TheBall.XStep = 5;
TheBall.YStep = 5;
break;
default:
TheBall.XStep = 7;
TheBall.YStep = 3;
break;
}
}
}
private int HitsPaddle(Point p)
{
Rectangle PaddleRect = ThePaddle.GetBounds(); //current position of the paddle
if (p.Y >= this.ClientRectangle.Bottom - (PaddleRect.Height + TheBall.Height))//If the ball has hit the paddle according to its y value
{
if ((p.X > PaddleRect.Left) && (p.X < PaddleRect.Right)) //ball hits the paddle (horizontally)!
{
if ((p.X > PaddleRect.Left) && (p.X <= PaddleRect.Left + PaddleRect.Width / 4))
return 1; //hits leftmost quarter of the paddle
else if ((p.X > PaddleRect.Left + PaddleRect.Width / 4) && (p.X <= PaddleRect.Left + PaddleRect.Width / 2))
return 2; //hits the second quarter of the paddle
else if ((p.X > PaddleRect.Left + PaddleRect.Width / 2) && (p.X <= PaddleRect.Right - PaddleRect.Width / 2))
return 3; //hits the third quarter of the paddle
else
return 4; //hits the rightmost quarter of the paddle
}
}
return -1;
}
private int HitsPaddle2(Point q)
{
Rectangle Paddle2Rect = TheOtherPaddle.GetBounds(); //current position of the paddle
if (q.Y <= this.ClientRectangle.Top + Paddle2Rect.Height)
{
if ((q.X > Paddle2Rect.Left) && (q.X < Paddle2Rect.Right)) //ball hits the paddle!
{
if ((q.X > Paddle2Rect.Left) && (q.X <= Paddle2Rect.Left + Paddle2Rect.Width / 4))
return 1; //hits leftmost quarter of the paddle
else if ((q.X > Paddle2Rect.Left + Paddle2Rect.Width / 4) && (q.X <= Paddle2Rect.Left + Paddle2Rect.Width / 2))
return 2; //hits the second quarter of the paddle
else if ((q.X > Paddle2Rect.Left + Paddle2Rect.Width / 2) && (q.X <= Paddle2Rect.Right - Paddle2Rect.Width / 2))
return 3; //hits the third quarter of the paddle
else
return 4; //hits the rightmost quarter of the paddle
}
}
return -1;
}
private void Reset() //resets the ball, stops timer, and redraws the main form
{
TheBall.XStep = 5;
TheBall.YStep = 5;
TheBall.Position.Y = this.ClientRectangle.Bottom - 190;
TheBall.Position.X = 5;
timer1.Stop();
TheBall.UpdateBounds();
Invalidate(TheBall.GetBounds());
}
private void timer1_Tick(object sender, System.EventArgs e) //runs one round of the game, when started
{
TheBall.UpdateBounds(); //gets the ball position
Invalidate(TheBall.GetBounds()); //redraws the ball
TheBall.Move(); //moves the ball
TheBall.UpdateBounds(); //updates position of the ball
Invalidate(TheBall.GetBounds()); //redraws the boll
CheckForCollision(); //checks for collision
Invalidate(TheScore.GetFrame()); //redraws the score
Invalidate(TheOtherScore.GetFrame());
}
private void Form1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
string result = e.KeyData.ToString();
Invalidate(ThePaddle.GetBounds());
switch (result)
{
case "Left":
ThePaddle.MoveLeft();
Invalidate(ThePaddle.GetBounds());
if (timer1.Enabled == false) //starts the game if it does not run yet
timer1.Start();
break;
case "Right":
ThePaddle.MoveRight(ClientRectangle.Right);
Invalidate(ThePaddle.GetBounds());
if (timer1.Enabled == false) //starts the game if it does not run yet
timer1.Start();
break;
case "Z":
TheOtherPaddle.MoveLeft();
Invalidate(TheOtherPaddle.GetBounds());
if (timer1.Enabled == false) //starts the game if it does not run yet
timer1.Start();
break;
case "C":
TheOtherPaddle.MoveRight(ClientRectangle.Right);
Invalidate(TheOtherPaddle.GetBounds());
if (timer1.Enabled == false) //starts the game if it does not run yet
timer1.Start();
break;
default:
break;
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
And here's the SpeedDialog class:
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 BrickO1
{
public partial class SpeedDialog : Form
{
public int Speed = 250;
private static int length = 0;
public SpeedDialog()
{
InitializeComponent();
}
private void SlowRadio_CheckedChanged(object sender, EventArgs e)
{
}
private void button1_Click(object sender, System.EventArgs e)
{
if (SlowRadio.Checked)
Speed = 100;
else if (MediumRadio.Checked)
Speed = 100;
else
Speed = 50;
length = Convert.ToInt32(textBox1.Text);
if(length == 0)
{
length = 5;
}
}
public int SelectedLength { get{ return length; }}
private void groupBox1_Enter(object sender, EventArgs e)
{
}
private void SpeedDialog_Load(object sender, EventArgs e)
{
}
private void groupBox2_Enter(object sender, EventArgs e)
{
}
private void maskedTextBox1_MaskInputRejected(object sender, MaskInputRejectedEventArgs e)
{
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
}
}
Thanks again!!!
So I have a picturebox named picbox1 and an image inside it. I need it to move up if W is pressed , left if A is pressed and you get the idea. What's the easiest way to do this? Could you please explain the code as well.
Here is my code(just in case):
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Threading;
public class MyProgram {
public static void Main() {
Form form1 = new Form();
form1.Show();
form1.Width = 800;
form1.Height = 600;
PictureBox picbox1 = new PictureBox();
form1.Controls.Add(picbox1);
picbox1.Image = Image.FromFile("c:\\Users\\FakeUsername\\Downloads\\AnimatedTest.gif");
Application.Run();
}
}
Creating form and picture box dynamically in Program.cs code is not good idea. You should declare your Form1 from in another file. Put pictureThen use KeyPress event:
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
int offset = 10;
if(e.KeyChar == 'a')
{
pictureBox1.Location = new Point(pictureBox1.Location.X - offset, pictureBox1.Location.Y);
}
else if(e.KeyChar == 'w')
{
pictureBox1.Location = new Point(pictureBox1.Location.X, pictureBox1.Location.Y - offset);
}
else if (e.KeyChar == 's')
{
pictureBox1.Location = new Point(pictureBox1.Location.X, pictureBox1.Location.Y + offset);
}
else if (e.KeyChar == 'd')
{
pictureBox1.Location = new Point(pictureBox1.Location.X + offset, pictureBox1.Location.Y);
}
}
Code:
private void sprites_updater_Tick(object sender, EventArgs e)
{
s++;
int x = player.Location.X;
int y = player.Location.Y;
if (s == 1)
if (ModifierKeys.HasFlag(Keys.A))
{
player.Location = new Point(x - 5, y);
}
s = 0;
sprites_updater.Start();
}
So while using timer code, I wrote the same thing above (ModifierKeys.HasFlag(Keys.A)) but it didnĀ“t work. Why?!
BTW, is there any way to show a 3d camera perspective inside a WinForms Panel WITHOUT USING XNA, WPF or any other stuff (only .NET)?!
The best way to get keyboard strokes and processing them later is to catch the Keyboards events in the form using both KeyDown, KeyUp and flags:
bool isAPressed;
...
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
switch(e.KeyCode)
{
case Key.A:
isAPressed = true;
break;
case Key.XXXX:
...
}
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
switch(e.KeyCode)
{
case Key.A:
isAPressed = false;
break;
case Key.XXXX:
...
}
}
Then you can use this information in your timer :
private void sprites_updater_Tick(object sender, EventArgs e)
{
s++;
int x = player.Location.X;
int y = player.Location.Y;
if (s == 1)
if (isAPressed)
{
player.Location = new Point(x - 5, y);
}
s = 0;
sprites_updater.Start();
}
This is particularily interresting to handle player moves this way (arrows).