I'm fairly new to C# programming, and this is my first time using it in XNA. I'm trying to create a game with a friend, but we're struggling on making a basic counter/clock. What we require is a timer that starts at 1, and every 2 seconds, +1, with a maximum capacity of 50. Any help with the coding would be great! Thanks.
To create a timer in XNA you could use something like this:
int counter = 1;
int limit = 50;
float countDuration = 2f; //every 2s.
float currentTime = 0f;
currentTime += (float)gameTime.ElapsedGameTime.TotalSeconds; //Time passed since last Update()
if (currentTime >= countDuration)
{
counter++;
currentTime -= countDuration; // "use up" the time
//any actions to perform
}
if (counter >= limit)
{
counter = 0;//Reset the counter;
//any actions to perform
}
I am by no means an expert on C# or XNA as well, so I appreciate any hints/suggestions.
If you don't want to use the XNA ElapsedTime you can use the c# timer. You can find tutorials about that, here the msdn reference for timer
Anyway here is some code that do more or less what you want.
First, you need to declare in your class something like that:
Timer lTimer = new Timer();
uint lTicks = 0;
static uint MAX_TICKS = 50;
Then you need to init the timer whereever you want
private void InitTimer()
{
lTimer = new Timer();
lTimer.Interval = 2000;
lTimer.Tick += new EventHandler(Timer_Tick);
lTimer.Start();
}
then in the Tick eventhandler you should do whatever you want to do every 50 ticks.
void Timer_Tick(object sender, EventArgs e)
{
lTicks++;
if (lTicks <= MAX_TICKS)
{
//do whatever you want to do
}
}
Hope, this helps.
Related
Let's say I'm making a game where I want Timers or Stopwatches to slow down in response to slowmo effects. How do I go about doing that? Looking at the API docs, there doesn't seem to be any way to scale the rate that they do their thing, so I was wondering if there's some other trick I can use to get the same effect.
You can set the interval to part of its original value and use some variable to keep track of the elapsed time
Like this:
int counter = 0;
int scale = 2; //scaling factor
int originalInterval = 1000;
Timer timer = new Timer();
timer.Interval = originalInterval / scale;
timer.Tick += (sender, e) => {
counter++;
if (counter >= scale) {
// perform the needed action here
counter = 0; // reset the counter
}
};
If you want to use a stopwatch, then like this:
Stopwatch stopwatch = new Stopwatch();
int scale = 2;
stopwatch.Start();
while (true) {
//Scale the elapsed time and by the factor
double elapsed = stopwatch.Elapsed.TotalMilliseconds / scale;
//When the scaled elapsed time exceeds a threshold
if (elapsed > threshold) {
// perform the needed action here
break;
}
}
I am wondering what is the best way to achieve this in Windows Forms - what I need is a window showing time elapsed (1 sec 2 secs etc) up to 90 seconds while code is being executed. I have a timer right now implemented as follows but I think I also need a stopwatch there as well since the Timer blocks the main thread.
static System.Timers.Timer pXRFTimer = new System.Timers.Timer();
static int _pXRFTimerCounter = 0;
private void ScanpXRF()
{
_pXRFTimerCounter = 0;
pXRFTimer.Enabled = true;
pXRFTimer.Interval = 1000;
pXRFTimer.Elapsed += new ElapsedEventHandler(pXRFTimer_Tick);
pXRFTimer.Start();
//START action to be measured here!
DoSomethingToBeMeasured();
}
private static void pXRFTimer_Tick(Object sender, EventArgs e)
{
_pXRFTimerCounter++;
if (_pXRFTimerCounter >= 90)
{
pXRFTimer.Stop();
}
else
{
//show time elapsed
}
}
I'm not sure about mechanics of your app, but time elapsed can be calculated with something like this
DateTime startUtc;
private void ScanpXRF()
{
startUtc = DateTime.NowUtc;
(...)
//START action to be measured here!
}
private static void pXRFTimer_Tick(Object sender, EventArgs e)
{
var elapsed = DateTime.NowUtc - startUtc;
var elapsedSeconds = elapsed.TotalSeconds; // double so you may want to round.
}
I have a list of few questions saved in a JSON file. I would like to send one different question every 10 seconds.
I launched a timer every 10 seconds, but the int "position" cannot be incremented at each time. How could I do ?
public override void OnStart()
{
dynamic data = Newtonsoft.Json.JsonConvert.DeserializeObject(File.ReadAllText("QCM.js"));
int pos = 0;
Timer aTimer = new Timer(2000);
aTimer.Elapsed += (sender, e) => SendData(pos, data);
pos++;
aTimer.Start();
static void SendData (int pos, dynamic data)
{
PackageHost.WriteInfo(data.Data[pos].Label);
}
The pos variable is captured by the lambda, you can use
aTimer.Elapsed += (sender, e) => SendData(pos++, data);
//pos++;
Make that pos a static variable, and increment it in SendData.
Be sure to end the timer when you run out of data.
How to stop a timer after some numbers of ticks or after, let's say, 3-4 seconds?
So I start a timer and I want after 10 ticks or after 2-3 seconds to stop automatically.
Thanks!
You can keep a counter like
int counter = 0;
then in every tick you increment it. After your limit you can stop timer then. Do this in your tick event
counter++;
if(counter ==10) //or whatever your limit is
yourtimer.Stop();
When the timer's specified interval is reached (after 3 seconds), timer1_Tick() event handler will be called and you could stop the timer within the event handler.
Timer timer1 = new Timer();
timer1.Interval = 3000;
timer1.Enabled = true;
timer1.Tick += new System.EventHandler(timer1_Tick);
void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop(); // or timer1.Enabled = false;
}
i generally talking because you didn't mention which timer, but they all have ticks... so:
you'll need a counter in the class like
int count;
which you'll initialize in the start of your timer, and you'll need a dateTime like
DateTime start;
which you'll initialize in the start of your timer:
start = DateTime.Now;
and in your tick method you'll do:
if(count++ == 10 || (DateTime.Now - start).TotalSeconds > 2)
timer.stop()
here is a full example
public partial class meClass : Form
{
private System.Windows.Forms.Timer t;
private int count;
private DateTime start;
public meClass()
{
t = new Timer();
t.Interval = 50;
t.Tick += new EventHandler(t_Tick);
count = 0;
start = DateTime.Now;
t.Start();
}
void t_Tick(object sender, EventArgs e)
{
if (count++ >= 10 || (DateTime.Now - start).TotalSeconds > 10)
{
t.Stop();
}
// do your stuff
}
}
Assuming you are using the System.Windows.Forms.Tick. You can keep track of a counter, and the time it lives like so. Its a nice way to use the Tag property of a timer.
This makes it reusable for other timers and keeps your code generic, instead of using a globally defined int counter for each timer.
this code is quiet generic as you can assign this event handler to manage the time it lives, and another event handler to handle the specific actions the timer was created for.
System.Windows.Forms.Timer ExampleTimer = new System.Windows.Forms.Timer();
ExampleTimer.Tag = new CustomTimerStruct
{
Counter = 0,
StartDateTime = DateTime.Now,
MaximumSecondsToLive = 10,
MaximumTicksToLive = 4
};
//Note the order of assigning the handlers. As this is the order they are executed.
ExampleTimer.Tick += Generic_Tick;
ExampleTimer.Tick += Work_Tick;
ExampleTimer.Interval = 1;
ExampleTimer.Start();
public struct CustomTimerStruct
{
public uint Counter;
public DateTime StartDateTime;
public uint MaximumSecondsToLive;
public uint MaximumTicksToLive;
}
void Generic_Tick(object sender, EventArgs e)
{
System.Windows.Forms.Timer thisTimer = sender as System.Windows.Forms.Timer;
CustomTimerStruct TimerInfo = (CustomTimerStruct)thisTimer.Tag;
TimerInfo.Counter++;
//Stop the timer based on its number of ticks
if (TimerInfo.Counter > TimerInfo.MaximumTicksToLive) thisTimer.Stop();
//Stops the timer based on the time its alive
if (DateTime.Now.Subtract(TimerInfo.StartDateTime).TotalSeconds > TimerInfo.MaximumSecondsToLive) thisTimer.Stop();
}
void Work_Tick(object sender, EventArgs e)
{
//Do work specifically for this timer
}
When initializing your timer set a tag value to 0 (zero).
tmrAutoStop.Tag = 0;
Then, with every tick add one...
tmrAutoStop.Tag = int.Parse(tmrAutoStop.Tag.ToString()) + 1;
and check if it reached your desired number:
if (int.Parse(tmrAutoStop.Tag.ToString()) >= 10)
{
//do timer cleanup
}
Use this same technique to alternate the timer associated event:
if (int.Parse(tmrAutoStop.Tag.ToString()) % 2 == 0)
{
//do something...
}
else
{
//do something else...
}
To check elapsed time (in seconds):
int m = int.Parse(tmrAutoStop.Tag.ToString()) * (1000 / tmrAutoStop.Interval);
at the moment i am using a while (true) loop to do this. I am not very familiar with timers. can someone tell me how i would convert this to work with a timer?
string lyricspath = #"c:\lyrics.txt";
TextReader reader = new StreamReader(lyricspath);
int start = 0;
string[] read = File.ReadAllLines(lyricspath);
string join = String.Join(" ", read);
int number = join.Length;
while (true)
{
Application.DoEvents();
Thread.Sleep(200);
start++;
string str = join.Substring(start, 15);
byte[] bytes = Encoding.BigEndianUnicode.GetBytes(str);
label9.Text = str;
if (start == number - 15)
{
start = 0;
}
}
Why use a timer? I assume this is because you want to have the app remain responsive during such a supposedly long operation. If so cosider using the same sort of code but in a BackgroundWorker.
Also if you do specifically want to use a Timer, beware which one you use; the Systm.Timer invokes its event in a different thread to the one used by the applications hoting form. The Timer in Forms events in the forms thread. You may need to Invoke() the operations in a timer callback that change the label.
Basically, a timer just sits there and counts, and every X milliseconds it "ticks"; it raises an event, which you can subscribe to with a method that does whatever you want done every X milliseconds.
First, all of the variables you will need inside the loop, that come from outside the loop, will need to have "instance scope"; they must be a part of the object that currently has this method, and not "local" variables like they are now.
Then, your current method will need to perform all of the steps prior to the while loop, setting whose "instance" variables I mentioned, and then create and start a Timer. There are several Timers in .NET; the two that would be most useful would likely be either the System.Windows.Forms.Timer or the System.Threading.Timer. This timer will need to be given a handle to the method it should call when it "ticks", and should be told how often to "tick".
Finally, all the code inside the while loop, EXCEPT the calls to Application.DoEvents() and Thread.Sleep(), should be placed in the method that the Timer will run when it "ticks".
Something like this ought to work:
private string[] join;
private int number;
private int start;
private Timer lyricsTimer;
private void StartShowingLyrics()
{
string lyricspath = #"c:\lyrics.txt";
TextReader reader = new StreamReader(lyricspath);
start = 0;
string[] read = File.ReadAllLines(lyricspath);
join = String.Join(" ", read);
number = join.Length;
lyricsTimer = new System.Windows.Forms.Timer();
lyricsTimer.Tick += ShowSingleLine;
lyricsTimer.Interval = 300;
lyricsTimer.Enabled = true;
}
private void ShowSingleLine(object sender, EventArgs args)
{
start++;
string str = join.Substring(start, 15);
byte[] bytes = Encoding.BigEndianUnicode.GetBytes(str);
label9.Text = str;
if (start == number - 15)
{
start = 0;
}
}
This runs every 200 ms. But the suggestion to try Google before asking a question here is a good one.
using Timer = System.Windows.Forms.Timer;
private static readonly Timer MyTimer = new Timer();
...
MyTimer.Tick += MyTimerTask;
MyTimer.Interval = 200; // ms
MyTimer.Enabled = true;
...
private void MyTimerTask(Object o, EventArgs ea)
{
...
}
Simply define a new timer:
Timer timer1 = new Timer();
timer1.Interval = 1; // Change it to any interval you need.
timer1.Tick += new System.EventHandler(this.timer1_Tick);
timer1.Start();
Then define a method that will be called in every timer tick (every [Interval] miliseconds):
private void timer1_Tick(object sender, EventArgs e)
{
Application.DoEvents();
Thread.Sleep(200);
start++;
string str = join.Substring(start, 15);
byte[] bytes = Encoding.BigEndianUnicode.GetBytes(str);
label9.Text = str;
if (start == number - 15)
{
start = 0;
}
}
*Remember to define the variables outside the method so you will be able to access them in the timer1_Tick method.