I am using Multimedia timer with a resolution of 1 ms and a period of 10 ms. The problem is that the multimedia timer badly interrupts for the first two events as I get a difference of 1 ms , which is not what I want.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.mmtimer.Tick += new System.EventHandler(this.mmtimer_Tick);
}
Multimedia.Timer mmtimer = new Multimedia.Timer();
private void Form1_Load(object sender, EventArgs e)
{
mmtimer.Resolution = 1;
mmtimer.Mode = Multimedia.TimerMode.Periodic;
mmtimer.Period = 10;
mmtimer.SynchronizingObject = this;
}
private void S_Click(object sender, EventArgs e)
{
TD.Items.Clear();
MT.Items.Clear();
delta_MT.Items.Clear();
double T = DateTime.Now.Hour * 60 * 60 * 1000 + DateTime.Now.Minute * 60 * 1000 + DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;
Point C = Cursor.Position;
TD.Items.Add(C.ToString());
MT.Items.Add(T.ToString());
try
{
mmtimer.Start();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK,
MessageBoxIcon.Stop);
}
}
private void Stop_Click(object sender, EventArgs e)
{
mmtimer.Stop();
double T = DateTime.Now.Hour * 60 * 60 * 1000 + DateTime.Now.Minute * 60 * 1000 + DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;
Point C = Cursor.Position;
TD.Items.Add(C.ToString());
MT.Items.Add(T.ToString());
M();
}
private void mmtimer_Tick(object sender, System.EventArgs e)
{
double T = DateTime.Now.Hour * 60 * 60 * 1000 + DateTime.Now.Minute * 60 * 1000 + DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;
Point C = Cursor.Position;
TD.Items.Add(C.ToString());
MT.Items.Add(T.ToString());
}
void M()
{
for (int i = 0; i < MT.Items.Count - 1; i++)
{
double A1 = Convert.ToDouble(MT.Items[i + 1]);
double A2 = Convert.ToDouble(MT.Items[i]);
double d = A1 - A2;
delta_MT.Items.Add(d);
}
}
}
Could you please tell how to fix the first two interrupts? if it is possible.
When the multimedia timer is running at standard resolution before you change the resolution to 1, the timer will first complete its current period. The new period will only be effective after the next interrupt. Setting the multimedia timing is a synchronous job. Thus it may be delayed by as much as 20ms (interrupt period on some systems).
If you want to make sure that you timing scheme works from the start of your main code you should make the calls to the multimedia time configuration 2 interrupt periods ahead of the main code. I'd with 50 ms you should be OK.
The delay you observe for the first interrupts depends on when your call was made with respect to the systems interrupt.
Related
I'm creating a basic racing game in C# for an assignment where two picture boxes race from the left side of the form to the right side. What I am struggling with is resetting the position back to the 1st pixel on the left side of the form once the picture box has reached the end of the form on the right side. At the moment the picture boxes just keep going right and then disappear from the form and never come back.
That is what the layout of the game looks like:
I've tried searching google for snippets of code or even examples on how I might achieve this and have yet to find anything.
Any help would be much appreciated.
public partial class frmRacing : Form
{
public frmRacing()
{
InitializeComponent();
}
//This is the segment of intergers and the randomizer.
Random r = new Random();
int dir = 1;
int min, sec, ms = 0;
private void btnExit_Click(object sender, EventArgs e)
{
this.Close();
}
//This is the timer for "Player One". It moves the players picture box across the form at a random speed between 1-10 and times how long it takes to complete the total laps.
private void tmrOne_Tick(object sender, EventArgs e)
{
dir = r.Next(1, 10);
picStark.Left += dir;
lblTimer1.Text = min + ":" + sec + ":" + ms.ToString();
ms++;
if (ms > 100)
{
sec++;
ms = 0;
}
else
{
ms++;
}
if (sec > 60)
{
min++;
sec = 0;
}
}
//This is the timer for "Player Two". It moves the players picture box across the form at a random speed between 1-10 and times how long it takes to complete the total laps.
private void tmrTwo_Tick(object sender, EventArgs e)
{
dir = r.Next(1, 10);
picLannister.Left += dir;
lblTimer2.Text = min + ":" + sec + ":" + ms.ToString();
ms++;
if (ms > 100)
{
sec++;
ms = 0;
}
else
{
ms++;
}
if (sec > 60)
{
min++;
sec = 0;
}
}
//This is the start button. It enables all the timers and starts the race.
private void btnStart_Click(object sender, EventArgs e)
{
tmrOne.Enabled = true;
tmrTwo.Enabled = true;
tmrThree.Enabled = true;
}
private void hsbLaps_Scroll(object sender, ScrollEventArgs e)
{
lblLaps3.Text = lblLaps3.Text + 1;
}
//This is the overall timer for the race.
private void tmrThree_Tick(object sender, EventArgs e)
{
lblTimer3.Text = min + ":" + sec + ":" + ms.ToString();
ms++;
if (ms > 100)
{
sec++;
ms = 0;
}
else
{
ms++;
}
if (sec > 60)
{
min++;
sec = 0;
}
}
}
You could create a method which you call at the end of your tick events which checks if the Left property is greater than the width of your form.
private void ResetPicture(PictureBox pb)
{
// check if picture box left property is greater than the width
// of your form - the width of your picturebox
if (pb.Left >= this.Width - pb.Width)
{
// the picture has won the game, reset it
pb.Left = 1;
}
}
comboBox selectedindexchanged event:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
updateTime = Convert.ToInt32(comboBox1.SelectedItem);
xpProgressBar1.Position = 0;
counter = 0;
panel1.Select();
}
Update method:
public void Update()
{
counter += 1;
int position = (int)Math.Round((counter / updateTime) * 100);
xpProgressBar1.Text = counter.ToString() + " %";
xpProgressBar1.Position = position;
if (counter == 10)
{
if (!backgroundWorker1.IsBusy)
{
timer1.Stop();
backgroundWorker1.RunWorkerAsync();
}
counter = 0;
}
}
Timer tick event:
private void timer1_Tick(object sender, EventArgs e)
{
Update();
}
In the combBox by default it's on the first item the number 10 then i can change and select the item with the number 30,50,60,120,300 and all this values are in seconds.
The timer1 interval is set to 1000
The problem is when it's on 10 by default when running the program or if i change it back to 10 in the comboBox it's working good. What it does it's counting 10 seconds and updating the progressBar(xpProgressBar1) by 10's i mean each second the progressBar move by 10 percentages. So after 10 seconds it's getting to 100 percentages.
But when i change the comboBox to the second item to 30 it should count now 30 seconds untill 100%
So i'm not sure in what steps it should move and how to do it. Same if i change it to 120 then it should move progress 120 seconds and again i'm not sure what steps and how to do it so it will get to 100%
What it does now for example if i change it to 120 i see it start counting to 120 by steps of 1 but then when it's getting to 10% it's jumping back to the start and not continue.
It should keep counting the whole 120 seconds untill 100%
If i change it to 30 i see it also counting by steps of 1 each time but again in 10% it's jumping to the start and not continue.
When it's on 10 it's counting by steps of 10 untill 100% so i wonder what should i do and how in the others if it's on 120 to step by 120 ? not logic. So tmake them all to step by 1 also the when it's on 10 ? And again how to do it so it will not stop a 10% and start over again.
Now i changed in the Update method the line if (counter == 10) to:
if (counter == updateTime)
So now if i change in the comboBox select 120 it will count in steps of 1 untill 120 but now when it will get the progressBar to 100% it will keep counting untill 120.
There is no sync between the 120 seconds and the 100% of the progressBar.
EDIT
The Update method:
private int _updateCounter;
public void Update()
{
counter += 1;
xpProgressBar1.Text = counter.ToString() + " %";
xpProgressBar1.Position = _updateCounter++ * 10;
if (counter == 10)
{
if (!backgroundWorker1.IsBusy)
{
timer1.Stop();
backgroundWorker1.RunWorkerAsync();
}
counter = 0;
}
}
This is called prescaler (frequency divider). You have single clock source (Timer) with fastest frequency using which you can achieve needed frequencies by skipping certain calls (events).
All you miss is that skipping:
private int _timer1Ticks;
private void timer1_Tick(object sender, EventArgs e)
{
if(_timer1Ticks++ >= int.Parse(comboBox1.Text) / 10)
{
_timer1Ticks = 0;
Update();
}
}
This way Update will be called exactly 10 times, disregard of combobox selection.
And to calculate progress:
private int _updateCounter;
public void Update()
{
xpProgressBar1.Position = _updateCounter++ * 10;
...
// do not forget to stop timer
if(_updateCounter == 10)
{
timer1.Stop();
_updateCounter = 0; // add some cleanup if using timer more than once
_timer1Ticks = 0;
...
}
}
I have this so far on one of my programs and I would like it to be where if you press on one button to break up the number you enter, you enable another button to get that data and save it to an outfile.
private void button1_Click(object sender, EventArgs e)
{
string number = textBox1.Text;
int digits = int.Parse(number);
if (digits > 9999 || digits < 0)
{
MessageBox.Show("That is not a valid number");
}
else
{
int thousands = digits / 1000;
int hundreds = (digits - (thousands * 1000)) / 100;
int tens = (digits - ((hundreds * 100) + (thousands * 1000))) / 10;
int ones = (digits - ((tens * 10) + (hundreds * 100) + (thousands * 1000))) / 1;
label6.Text = thousands.ToString();
label7.Text = hundreds.ToString();
label8.Text = tens.ToString();
label9.Text = ones.ToString();
button2.Enabled = true;
}
I have this so far and it works but for button2, I want these variables that are generated from clicking button one to pass to button2 so when you click on it, it will use those variables to write to a file. Any ideas?
There are several ways, but looking at what you already have, why not just reread the labels back into the variables you want?
private void button2_Click(object sender, EventArgs e)
{
int thousands = Convert.ToInt32(label6.Text);
int hundreds = Convert.ToInt32(label7.Text);
//...etc
}
You could also just set globals instead of locals, ie declare your ints outside of any method call
int thousands;
int hundreds;
int tens;
int ones;
private void button1_Click(object sender, EventArgs e)
{
//...code
thousands = digits / 1000;
hundreds = (digits - (thousands * 1000)) / 100;
tens = (digits - ((hundreds * 100) + (thousands * 1000))) / 10;
ones = (digits - ((tens * 10) + (hundreds * 100) + (thousands * 1000))) / 1;
}
private void button2_Click(object sender, EventArgs e)
{
Console.WriteLine(thousands); //...etc
}
Don't do this too often as if you have tons of globals things can get confusing quick, but for a simple program (which this seems to be) it should be ok.
if it is a asp.net webforms application you can save the vars in the view state and retrieve them from the other button click
//setting
ViewState["thousands "] = thousands;
//Reading
int thousands = Convert.ToInt32(ViewState["thousands "]);
if it is console, windows app, windows service ou can just declare the int vars outside the event scope and you would be able to access them from both button click event;
I am making a program which has to check a data base once on every 30 or 60 minutes and display the results, if there are any, in the windows form interface. Of course, the other functions which the from provides access to, should still be usable while the data base check is being executed. To this end, I am using System.Timers.Timer which executes a method on a different thread from the UI one (If there is something wrong with using this approach, please feel free to comment on it). I wrote a small and simple program in order to test hot things work, only to notice that I cant really set the Interval to over ~ 1 minute ( I need 30 minutes to an hour). I came up with this solution:
public partial class Form1 : Form
{
int s = 2;
int counter = 1; //minutes counter
System.Timers.Timer t;
public Form1()
{
InitializeComponent();
t = new System.Timers.Timer();
t.Elapsed += timerElapsed;
t.Interval = 60000;
t.Start();
listBox1.Items.Add(DateTime.Now.ToString());
}
//doing stuff on a worker thread
public void timerElapsed(object sender, EventArgs e)
{
//check of 30 minutes have passed
if (counter < 30)
{
//increment counter and leave method
counter++;
return;
}
else
{
//do the stuff
s++;
string result = s + " " + DateTime.Now.ToString() + Thread.CurrentThread.ManagedThreadId.ToString();
//pass the result to the form`s listbox
Action action = () => listBox2.Items.Add(result);
this.Invoke(action);
//reset minutes counter
counter = 0;
}
}
//do other stuff to check if threadid`s are different
//and if the threads work simultaneously
private void button1_Click(object sender, EventArgs e)
{
for (int v = 0; v <= 100; v++)
{
string name = v + " " + Thread.CurrentThread.ManagedThreadId.ToString() +
" " + DateTime.Now.ToString(); ;
listBox1.Items.Add(name);
Thread.Sleep(1000); //so the whole operation should take around 100 seconds
}
}
}
But this way, the Elapsed event is being raised and the timerElapsed method called once every minute, it seems kinda useless. Is there a way to actually set longer timer interval ?
Interval is in miliseconds,so it seems that you've set your interval for 60 seconds:
t.Interval = 60000; // 60 * 1000 (1 minute)
If you want to have 1 hour interval then you need to change your interval to:
t.Interval = 3600000; // 60 * 60 * 1000 (1 hour)
I am trying to fill a rectangle in 3 seconds of real time
I want the increment to be a constant value to look nice and not have acceleration
and I am having trouble understanding what to do
this is my code
// constant
// 1.0f = 100% of rectangle, 3 sec = 3000.0 miliseconds
float addValue = 1.0f/3000.0f;
public override void Update(GameTime gameTime)
{
newGameTime += gameTime.ElapsedGameTime.Milliseconds;
// once the percentage is set to 0 this starts
if ((percentage < 1))
{
// calculate value here in order to time
percentage += addValue;
}
}
I've been trying all kind of crazy math to get it right but i completely lost it. :(
I know I should be using gameTime or newGameTime but I'm lost
I assume thats your update / rendering function.
Let's say, for example, that since the last rendering, 300ms elapsed. That means you'd have to add 100%/3000ms * 300ms = 10% to your rectangle.
-> You're missing the elapsed time in the calculation:
percentage += addValue * gameTime.ElapsedGameTime.Milliseconds;
I may be completely wrong with this answer according to what ccKep just mentioned in his comment.
But just in case it's what you're looking for, I put this together.
The main idea is having a timer event controling the increment. Even if the code I'm submitting isn't appropriate, maybe the idea will apply.
public int percentage;
public int Percentage
{
get { return percentage; }
set
{
percentage = value;
if (Percentage >= 0 && Percentage < 100)
{
progressBar1.Value = value;
}
else
{
Percentage = 0;
timer1.Stop();
}
}
}
private void button1_Click(object sender, EventArgs e)
{
Percentage = 0;
timer1.Interval = 1000;
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
double addValue = 100 / 3;
Percentage += (int)addValue;
}