Moving Picturebox randomly as it roams - c#

I want to make an AI using PictureBox that can roam randomly without messing its movements like for example:
PictureBox must execute the movement to go Right, if the Timer runs out it the next movement is going Down, like just how random it would roam.
I'd thought I might figured it out to Hard code it. However might took long, also once the Timer Stops, it won't Restart again. idk why.
Here's a Picture of my Game so you would have some ideas about it.
Here's the code also
private void Game_Load(object sender, EventArgs e)
{
E_Right.Start();
if(Upcount == 0)
{
E_Right.Start();
}
}
private void E_Right_Tick(object sender, EventArgs e)
{
if(Rightcount > 0)
{
EnemyTank.Left += 5;
EnemyTank.BackgroundImage = Properties.Resources.EnemyTank_RIGHT_v_2;
Rightcount = Rightcount - 1;
}
if (Rightcount == 0)
{
E_Right.Stop();
E_Down.Start();
}
}
private void E_Up_Tick(object sender, EventArgs e)
{
if (Upcount > 0)
{
EnemyTank.Top -= 5;
EnemyTank.BackgroundImage = Properties.Resources.EnemyTank_TOP_v_1;
Upcount = Upcount - 1;
}
if (Upcount == 0)
{
E_Up.Stop();
E_Right.Start();
}
}
private void E_Down_Tick(object sender, EventArgs e)
{
if (Downcount > 0)
{
EnemyTank.Top += 5;
EnemyTank.BackgroundImage = Properties.Resources.EnemyTank_DOWN_v_1;
Downcount = Downcount - 1;
}
if (Downcount == 0)
{
E_Down.Stop();
E_Left.Start();
}
}
private void E_Left_Tick(object sender, EventArgs e)
{
if (Leftcount > 0)
{
EnemyTank.Left -= 5;
EnemyTank.BackgroundImage = Properties.Resources.EnemyTank_LEFT_v_1;
Leftcount = Leftcount - 1;
}
if (Leftcount == 0)
{
E_Left.Stop();
E_Up.Start();
}
}
Well just assume that the PictureBox is in Location(0,0). If you see a PictureBox an image of a Tank nevermind that. That goes for the MainTank of the user will be using.

You could do it with just one timer:
int moveTo = 0; // Move while this is not 0
int speed = 3;
Random rand = new Random();
// Keep track of whether the tank is moving up/down or left/right
enum MoveOrientation { Vertical, Horizontal };
MoveOrientation orientation = MoveOrientation.Vertical;
void ChooseNextPosition()
{
// Negative numbers move left or down
// Positive move right or up
do {
moveTo = rand.Next(-5, 5);
} while (moveTo == 0); // Avoid 0
}
private void Game_Load(object sender, EventArgs e) {
ChooseNextPosition();
timer1.Start();
}
private void timer1Tick(object sender, EventArgs e) {
if (orientation == MoveOrientation.Horizontal)
{
EnemyTank.Left += moveTo * speed;
}
else
{
EnemyTank.Top += moveTo * speed;
}
moveTo -= moveTo < 0 ? -1 : 1;
if (moveTo == 0)
{
// Switch orientation.
// If currently moving horizontal, next move is vertical
// And vice versa
orientation = orientation == MoveOrientation.Horizontal ? MoveOrientation.Vertical : MoveOrientation.Horizontal;
// Get new target
ChooseNextPosition();
}
}

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.

Move the label from left to right and right to left

My question is very simple.
My Label1 should move continuously from left to right.
(Start from the left part of the form and go to the right part of the form. When it reaches the right part of the Form, go to the left and so on.) I have 2 timers(one for right and one for left)
I have the following code, it starts at the left and goes to the right, but when it reaches the right of the Form, it doesn't return.
Can anyone help me?
enum Position
{
Left,Right
}
System.Windows.Forms.Timer timerfirst = new System.Windows.Forms.Timer();
private int _x;
private int _y;
private Position _objPosition;
public Form1()
{
InitializeComponent();
if (label1.Location == new Point(0,180))
{
_objPosition = Position.Right;
}
if (label1.Location == new Point(690,0))
{
_objPosition = Position.Left;
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Label1.SetBounds(_x, _y, 0, 180);
}
private void tmrMoving_Tick(object sender, EventArgs e)
{
tmrMoving.Start();
if (_objPosition == Position.Right && _x < 710)
{
_x +=10;
}
if(_x == 710)
{
tmrMoving.Stop();
}
Invalidate();
}
private void tmrMoving2_Tick(object sender, EventArgs e)
{
tmrMoving2.Start();
if (_objPosition == Position.Right && _x > 690)
{
_x -= 10;
}
if(_x == 1)
{
tmrMoving2.Stop();
}
Invalidate();
}
Thanks.
I think you've overcomplicated things. Let's just have one timer, a step number of pixels that we sometimes flip negative, and some time later flip back to positive. We can move the label by repeatedly setting its Left:
public partial class Form1 : Form
{
private int _step = 10;
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
if (label1.Right > this.Width) _step = -10;
if (label1.Left < 0) _step = 10;
label1.Left += _step;
}
}
You might want to fine tune it, but the basic motion is there

Using data from arduino in winforms

using System;
using System.Drawing;
using System.IO.Ports;
using System.Windows.Forms;
namespace ek_zıplama
{
public partial class Form1 : Form
{
public enum Directions
{
right,
left,
up,
}
private Directions car_direction;
public SerialPort myPort;
int G = 15;
int force;
bool jump;
public string DATA;
public Form1()
{
InitializeComponent();
myPort = new SerialPort();
myPort.BaudRate = 9600;
myPort.PortName = "COM6";
myPort.Open();
jump = false;
}
private void Form1_Load(object sender, EventArgs e)
{
moves();
}
private void timer1_Tick(object sender, EventArgs e)
{
if (jump)
{
car.Top -= force;
force -= 1;
}
//using block to stay in same position when car is stopped
if (car.Left + car.Width - 1 > block.Left && car.Left + car.Width + 5 < block.Left + block.Width + car.Width
&& car.Top + car.Height >= block.Top && car.Top < block.Top)
{
car.Top = ekran.Height - block.Height - car.Height;
force = 0;
jump = false;
}
}
private void moves()
{
if (label2.Text == "10111" && car_direction != Directions.right)
{
car.Location = new Point(car.Location.X + 130, car.Location.Y);
car_direction = Directions.right;
}
if (label2.Text == "01111" && car_direction != Directions.left)
{
car.Location = new Point(car.Location.X - 130, car.Location.Y);
car_direction = Directions.left;
}
if (!jump && label2.Text == "11011")
{
jump = true;
force = G;
}
}
private void timer3_Tick(object sender, EventArgs e)
{
DATA = myPort.ReadExisting();
label2.Text = DATA;
}
}
}
What I botch about that in move function.
I tried to create a function like
*if DATA is 01111 then my car turns left
*if DATA is 10111 then my car turns right
*if DATA is 11011 then my car jumps
Before I changed,car was controlled with keyboards.Everything was same but "move"function.And it was working.What were instead od "move" function is:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Right&& car_direction != Directions.right)
{
car.Location = new Point(car.Location.X + 130, car.Location.Y);
car_direction = Directions.right;
}
if (e.KeyCode == Keys.Left && car_direction != Directions.left)
{
car.Location = new Point(car.Location.X - 130, car.Location.Y);
car_direction = Directions.left;
}
if (!jump && e.KeyCode == Keys.Up)
{
jump = true;
force = G;
}
}
Hope you get me :)
I'm quite sure it's not going to work if you only call it once in your Form_Load event. Since you maybe want your car to move each time the data in the label has changed, you should just make a reference to the function you created. That means, that you should just put moves(); in private void timer3_Tick(object sender, EventArgs e):
private void timer3_Tick(object sender, EventArgs e)
{
DATA = myPort.ReadExisting();
label2.Text = DATA;
moves();
}
In this way, each time the timer ticks, your car is going to move according to the new data in the label.
When I was doing something with Arduino I used something like this:
private void timer_Tick(object sender, EventArgs e)
{
if (serialPort != null && serialPort.IsOpen && serialPort.BytesToRead > 0)
{
data_as_string += serialPort.ReadLine();
}
}
I'm not sure how DATA is sent, but you can send single lines from Arduino using Serial.write("your line here");. Receiving and parsing data from here is very simple, as you could just read lines 01111, 10111, etc. and use any logic to manipulate the car. I hope this helps.

Visual studio c# platformer,background issue

I am currently working on a platformer in C#,VS 2015
The problem i have encountered is:when i press the left/right arrow,the background moves behind the player in the opposite direction,and this happens using a timer(which cannot be set to a value lower than 1 milisecond).
Because the timer is limited to 1 milisecond,the background moves laggy,and i would like to solve this :D
Here is the code
public Form1()
{
InitializeComponent();
}
Bitmap back;
Bitmap bobright;
Bitmap bobleft;
Bitmap bobimage;
Bitmap exit;
Point boblocation = Point.Empty;
Point exitlocation = Point.Empty;
float offSet = 0, vit;
int acc_secunde, acc_secunde_max = 30;
bool left = false, right = false;
private void button1_Click(object sender, EventArgs e)
{
Application.Exit();
}
public void Game()
{
int imageNumber = panel1.Width / back.Width + 3;
using (Bitmap frame = new Bitmap(panel1.Width, panel1.Height))
{
using (Graphics graph = Graphics.FromImage(frame))
{
for (int i = 0; i < imageNumber; i++)
{
graph.DrawImage(back, offSet/2 % back.Width + i * back.Width - back.Width, 0);
}
graph.DrawImage(bobimage, boblocation);
graph.DrawImage(exit,exitlocation);
}
using (Graphics graph = panel1.CreateGraphics())
{
graph.DrawImage(frame, Point.Empty);
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Maximized;
back = Properties.Resources.back;
bobleft = Properties.Resources.bobleft;
bobright = Properties.Resources.bobright;
bobimage = bobright;
exit = Properties.Resources.Exit;
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
boblocation.X = panel1.Width / 2 - bobimage.Width / 2;
boblocation.Y = 210;
exitlocation.X = panel1.Width - exit.Width - 10;
exitlocation.Y = 5;
if (left)
{
offSet = offSet + acc_secunde;
bobimage = bobleft;
}
if(right)
{
bobimage = bobright;
offSet = offSet - acc_secunde;
}
Game();
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.Left)
{
acceleratie.Start();
left = true;
}
if(e.KeyCode == Keys.Right)
{
acceleratie.Start();
right = true;
}
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.Left)
{
acceleratie.Stop();
deacceleratie.Start();
}
if(e.KeyCode == Keys.Right)
{
acceleratie.Stop();
deacceleratie.Start();
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
}
private void deacceleratie_Tick(object sender, EventArgs e)
{
if(acc_secunde > 0)
acc_secunde = acc_secunde - acc_secunde_max / 3;
if (acc_secunde <= 0)
{
deacceleratie.Stop();
if (right == true)
right = false;
if (left == true)
left = false;
acc_secunde = 0;
}
}
private void acceleratie_Tick(object sender, EventArgs e)
{
if(acc_secunde< acc_secunde_max)
acc_secunde+=2;
}
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
Point mousePt = new Point(e.X, e.Y);
if (mousePt.X > panel1.Width - exit.Width - 10 && mousePt.X < panel1.Width - 10 && mousePt.Y > panel1.Top + 10 && mousePt.Y < panel1.Top + 10 + exit.Height)
Application.Exit();
}
}
}

Randomly presenting panels equally over 20 occurrences

So here is the basic code:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
protected Random random;
public Form1()
{
InitializeComponent();
random = new Random();
}
private void Form1_Load(object sender, EventArgs e)
{ }
private void button1_Click(object sender, EventArgs e)
{
bool button1Clicked = true;
if (button1Clicked == true) { ITIpanel.Visible = true; }
}
private void ITIpanel_Paint(object sender, PaintEventArgs e)
{
ITItimer.Enabled = true;
}
private void ITItimer_Tick(object sender, EventArgs e)
{
double rand = random.NextDouble();
if (rand < .50d) { bluestimPanel.Visible = true; }
else if (rand > .5d) { redstimPanel.Visible = true; }
ITItimer.Enabled = false;
}
private void bluestimPanel_Paint(object sender, PaintEventArgs e)
{
Trialtimer.Enabled = true;
}
private void redstimPanel_Paint(object sender, PaintEventArgs e)
{
Trialtimer.Enabled = true;
}
private void Trialtimer_Tick(object sender, EventArgs e)
{
bluestimPanel.Visible = false;
redstimPanel.Visible = false;
Trialtimer.Enabled = false;
ITIpanel.Visible = true;
}
}
}
As you can see, the program itself is fairly straight forward. At the tick of the ITItimer the red or blue panels occurs at random. I want to modify this such that if the ITItimer ticks a total of 10 times, the red and blue panels will both have occurred 5 times each.
I have been researching this for a week or so and have yet to find a solution. Any ideas on how I could best accomplish this?
I actually got the following to work:
double rand = random.NextDouble();
if (rand < .50d && blue < 5) { bluestimPanel.Visible = true; }
else if (blue == 5) { redstimPanel.Visible = true; }
if (rand > .5d && red < 5) { redstimPanel.Visible = true; }
else if (red == 5) { bluestimPanel.Visible = true; }
if (red >= 5 && blue >= 5) { panel1.Visible = true; }
It isn't exactly the prettiest thing in the world. But it gets the job done.
Random numbers using most normal library routines are a low-quality source of pseudorandomness. If this is for a randomized scientific study, this will be a flaw in your protocol design.
The approach that I would recommend would be to consider this a method of randomly arranging a session of at least N trials, where there are X trial types.
The below is pseudocode for illustration of the concept.
Let MinimumTrials be N MOD X + X
Let SessionList be a List<Trial>
For Each TrialType
add X instances of that trial type to SessionList
Shuffle(SessionList)
Then your session engine can call the individual Trials as it walks through the SessionList to have an even distribution of possible trial orders. Note that Shuffle is an operation which requires a certain degree of finesse to get right, searching on SO is a good starting point for that.

Categories