Trying to update interval for DispatcherTimer, not always working - c#

I am trying to make a Snake game. And what I want to happen is that each time the snake eats a piece of food it moves quicker.
I want to do this by making the timer tick faster.
I start the timer at an interval time of:
gltimer.Interval = new TimeSpan(20000)
And update it with:
public void updateTimer(object sender, EventArgs e)
{
long nrTicks = gltimer.Interval.Ticks;
nrTicks = (long)(nrTicks * 0.95);
gltimer.Interval = new TimeSpan(nrTicks);
}
But when I run my game the speed stays the same until I reach the 14th snack and then it suddenly changes. I already figured out that the nrTicks then drops below 10000.
My question is why the Interval doesn't update for the intermediate values?

The DispatcherTimer is not designed to execute an action at precise intervals.
While it dispatches the action at the exact interval, the dispatched actions will get executed, when the GUI thread in your case the wpf application loop decides to do so.
You setting the interval to 20.000 ticks results in an interval of 20.000*100ns = 2.000.000ns = 2ms. A wpf application has a resolution of around 10ms at best.
Look at those posts:
WPF Timer problem... Cannot get correct millisecond tick
WPF Dispatchertimer delayed reaction / freeze

Related

Using timer and game loop

I'm building a simple console game, there is the player who moves when key press down, and there are enemies which moves automatically, each type of enemy moves one time in X miliseconds.
As I understood I should using the timer, but I don't really know how to do that in the game loop (isn't built yet because I don't know how to do with the timer. but it should be while loop I think). the game ends when the enemy 'touch' the player (same x and y).
One important thing: I can't you in this exercise in Thread, but if you have other suggestions instead of using Timer you are welcome.
Thank you.
You normally don't use conventional timers in games. Games have a very different mechanism for handling their logic and the time that passed, they normally don't work with timers or not in the way you would expect:
Games normally have something called a game loop. Generally speaking it's three main functions that are called one after the other in a loop:
while(running)
{
HandleUserInput();
ChangeWorld();
Render();
}
You get user input, you change the game world accordingly and you draw it to the screen. Now, the faster your computer is, the faster this loop runs. That's good for the graphics (think FPS), but bad for the game. Imagine Tetris where every frame the blocks move. Now I would not want to buy a faster computer, the game would get more difficult that way.
So to keep the game speed constant independent of the power of the computer, the loop considers the time passed:
while(running)
{
var timePassedSinceLastLoop = CalculateTimeDelta();
HandleUserInput();
ChangeWorld(timePassedSinceLastLoop);
Render();
}
Now imagine a cooldown for something in game. The player pressed "a", some cool action happened and although he may press "a" again, nothing will happen for the next 5 seconds. But the game still runs and does all the other things that may happen ingame. This is not a conventional timer. It's a variable, lets call it ActionCooldown, and once the player triggers the action, it's set to 5 seconds. Every time the world changes, the timePassed is subtracted from that number until it's zero. All the time, the game is running and handling input and rendering. But only once ActionCooldown hits zero, another press of "a" will trigger that action again.
The ChangeWorld method includes all automatic changes to the world. Enemies, missiles, whatever moves without player interaction. And It moves based on time. If the enemy moves one square per second, You need to make his coordinate a float and add a fraction of a square every time the loop is run.
Lets say you have 30 fps so your loop runs 30 times a second. Your enemy now needs to move 1/30 of a square each loop. Then it will in the end have moved one full square per second.
The general premise behind the timer is to repeat some code every n.
To create the timer use this:
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed+=new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 1 millisecond. Note: Time is set in Milliseconds
aTimer.Interval=1;
aTimer.Enabled=true;
Then you implement this method:
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
//Whatever you need repeated
}
The full example can be found here:
http://msdn.microsoft.com/en-us/library/system.timers.timer(v=vs.71).aspx

How to make timer keep runing while loop wait for another time result?

i have the following issue in my code,
i have this loop running on timer (this is just a small part of the loops that running on the big timer),
inside that big timer (he tick every 1 second) i have 1 method that need to wait 5 second then continue with the the rest of the loop code, but i want that it wont stuck the code and the timer will continue to run every 1sec and wont wait for those 5sec.
what i did i add a new timer (timer_deva) that tick every 5sec and did all the checks inside it, and then timer stops.
so my issue is that i need to wait 5sec to retrieve a value to complete my code, but i need that my main timer will keep running simultaneously, and when he get his result for the other time he will need to complete the code he left behind.
thanks in advance,
else if (mobID.Equals(Convert.ToInt32(txtDeva)))
{
//START CHECK WITH TIMER
timer_deva.Start();
//Methods inside timer_deva update the winnerNation
//END CHECK TIMER - GET RESULT
winner(zoneId, winnerNation, humansKills, orcKills);
}
tl;dr
Conventional Timers are not used in games. Games have a very different mechanism for handling their logic and the time that passed.
Long Version:
I know this may not answer your question directly, but it's way to much text to cramp into a comment. Your timers sound very complicated and hierarchical. From your variable names I will assume you are programming a game. Games normally don't work with timers or not in the way you would expect. This different game-like behaviour would help you a lot in your timers problem and may even help you more with your design in general.
Games normally have something called a game loop. Generally speaking it's three main functions that are called one after the other in a loop:
while(running)
{
HandleUserInput();
ChangeWorld();
Render();
}
You get user input, you change the game world accordingly and you draw it to the screen. Now, the faster your computer is, the faster this loop runs. That's good for the graphics (think FPS), but bad for the game. Imagine Tetris where every frame the blocks move. Now I would not want to buy a faster computer, the game would get more difficult that way.
So to keep the game speed constant independent of the power of the computer, the loop considers the time passed:
while(running)
{
var timePassedSinceLastLoop = CalculateTimeDelta();
HandleUserInput();
ChangeWorld(timePassedSinceLastLoop);
Render();
}
Now imagine a cooldown for something in game. The player pressed "a", some cool action happened and although he may press "a" again, nothing will happen for the next 5 seconds. But the game still runs and does all the other things that may happen ingame. This is not a conventional timer. It's a variable, lets call it ActionCooldown, and once the player triggers the action, it's set to 5 seconds. Every time the world changes, the timePassed is subtracted from that number until it's zero. All the time, the game is running and handling input and rendering. But only once ActionCooldown hits zero, another press of "a" will trigger that action again.

Farseer Physics non-XNA on separated thread

I'm developing a game in C# with Farseer Physics without XNA. I put world.Step(float dt) in a separated thread in order to keep the form alive (in fact, a while loop would block every other operation). Well, the ball, a dynamic body, runs faster or slower depending on CPU frequency I think. I thought about Thread.Sleep() with a delay time calculated by reading the CPU frequency and mutiplying it by something, but I'm pretty sure I'm wrong. I'm a little noob. Any suggestion?
Thread.Sleep is very much not an accurate way to time things. You want to use something like:
Stopwatch timer = new Stopwatch();
timer.Start();
Which you can then use to drive a timed update loop like this:
// Run enough updates to catch up to the current time
private void Idle()
{
double time = timer.Elapsed.TotalSeconds;
accumulatedTime += (time - lastTime);
lastTime = time;
const double frameTime = 1.0/60.0; // 60 frames per second
while(accumulatedTime > frameTime)
{
world.Step((float)frameTime);
accumulatedTime -= frameTime;
}
}
You can then call the above Idle method followed by a short Sleep in a loop.
Or you could just call it from an event handler for Application.Idle - either directly on the UI thread, or by signalling your other thread.

Inconsistent Storyboard performance in emulator

I'm doing performance tuning on a Silverlight WP7 game and I'm observing a weird behavior when running in the Emulator (I have no real device, so I can't tell if it's an emulator artifact).
I am using a Storyboard as main game loop timer, I update the rendering in the Completed event, then restart the animation. The problem is that the Completed event is triggered at very different intervals.
I isolated the problem in a very simple function, called for ex. on a button click (I put this in a totally empty application, there is nothing else going on in the app).
var sw = new Stopwatch();
var animation = new Storyboard();
animation.Duration = TimeSpan.FromMilliseconds(10);
animation.Completed += (s, e) =>
{
sw.Stop();
Debug.WriteLine(sw.ElapsedMilliseconds.ToString());
sw.Reset();
sw.Start();
animation.Begin();
};
animation.Begin();
The output I would expect (ideally) is something like
10
10
10
10
...
but instead, this is what I get:
12
15
16
17
17
14
10
10
10
9
11
132
10
20
11
11
10
12
The time between cycles varies quite a bit, but most important there are occasional very long delays (like the 132 above). This happens regardless of the animation Duration, i.e. the actual duration is "centered" towards the set duration, but varies a lot with intermittent long delays.
You can imagine that my game is running quite irregularly, not smooth and uniform at all. Also I noticed that regardless of how simple the render operation is, I cannot go over ~42 FPS.
Question 1: Am I doing some obvious and blatant mistake? Is my approach flawed?
Question 2: Why is the Storyboard duration so inconsistent between runs?
I am 90% sure is it caused by emulator yet be aware that 10ms is very short interval. Silverlight app is getting refreshed 60 times per second so it is 16,6ms. I recommend you set it to 33 ms or more.
In one of my game I use DispatcherTimer which works fine (for falling bombs :) ) but is not that accurate as I thought. Using storyboard as a timer is better IMO. Basically, if you do not have any other complex animations compositor thread works smooth and your timer is pretty accurate.
As someone with a device to test your code (or buy one).

Thread.Sleep(1); is too slow for a Silverlight animation, is there an alternative?

I have this algorithm that are drawing a lot of pixels on a Canvas in an animation. But I have no control of the speed of the animation and it is drawing very fast, so I added a Thread.Sleep(1) but then it is too slow when drawing several thousand pixels.
I have tried a Storyboard approach but that ended up to be a very slow.
So are there an alternative to the Thread.sleep for slowing down my loop?
void DrawGasket(object sender, DoWorkEventArgs e)
{
Random rnd = new Random();
Color color = Colors.White;
while (Counter <= noOfPx)
{
switch (rnd.Next(3))
{
case 0:
m_lastPoint.X = (m_top.X + m_lastPoint.X)/2;
m_lastPoint.Y = (m_top.Y + m_lastPoint.Y)/2;
color = Colors.White;
break;
case 1:
m_lastPoint.X = (m_left.X + m_lastPoint.X)/2;
m_lastPoint.Y = (m_left.Y + m_lastPoint.Y)/2;
color = Colors.Orange;
break;
case 2:
m_lastPoint.X = (m_right.X + m_lastPoint.X)/2;
m_lastPoint.Y = (m_right.Y + m_lastPoint.Y)/2;
color = Colors.Purple;
break;
}
Dispatcher.BeginInvoke(() =>
{
var px = new Rectangle {
Height = m_pxSize,
Width = m_pxSize,
Fill = new SolidColorBrush(color)
};
Canvas.SetTop(px, m_lastPoint.Y);
Canvas.SetLeft(px, m_lastPoint.X);
can.Children.Add(px);
lblCounter.Text = Counter.ToString();
});
Counter++;
Thread.Sleep(1);
}
}
Can't you just sleep every N iterations through the loop rather than every iteration?
Here's the simple method: You want it to draw at a specific time...during each loop have it look to see what time it is. If it's "time" (whatever) rate you determine that to be, then draw/update. Otherwise, just loop. (For example, if you want 10 updates per second, and you just updated, then store the current time in a variable...and then compare against that variable. Until it is a 10th of a second later, don't redraw, just loop.)
This isn't bad, so long as you can do anything else you need to do within this loop. If this loop must complete, however, before anything else happens, you'll just be burning a lot of cpu cycles just waiting.
If you want to get fancy, and do this right, you can have it see how much time has passed, and then update the visual by the correct amount. So, for example, if you want your object to move 30 pixels per second, you could just update where it is precisely, (if .0047 seconds have gone by, for instance, it should move .141 pixels). You store that value. Of course, visually, it won't have moved at all until another round of the loop, but exactly when it moves and how far will be determined by time, rather than the speed of the computer. This way you'll get it moving 30 pixels per second, regardless of the speed of the machine...it will just be jumpier on a slow machine.
The CompositionTarget.Rendering event fires every time Silverlight draws a frame, this is a good place to write any custom drawing code. You can use some other mechanism, like a timer, to keep track of your "game time" and adjust the model appropriately on a separate thread (or at least a separate execution path) from the drawing code. That way when it comes time to draw the UI there are no calculations to perform, you just paint the current state of your model. Basically just move the code in Dispatcher.BeginInvoke to the event handler for CompositionTarget.Rendering and I believe you'll be good.
One option would be to not sleep each time:
if(Counter % 2 == 0) Thread.Sleep(1);
With or without Thread.Sleep(), the render speed is determined by how fast your system is, or by how much time your process gets. -> bad!
You should use the approach that video games are written nowadays. Keep track of the current time, and call BeginInvoke() only x times per second (where x is the frames per second render speed)
In the BeginInvoked function check how much is drawn and how much you still need to draw. Especially don't BeginInvoke for every single Rectangle. Even without a Thread.Sleep() it's always a context switch.

Categories