Can't reset my gametime to zero in XNA - xna-4.0

I'm creating a game with XNA 4.0 and I have a problem with resetting the game time in my game,
the problem is I'm using this code for adding my objects in game:
Timespan prevSpawn = timespan.zero;
Timespan objectSpawnTime = timespan.fromsec(5);
if (gameTime.TotalGameTime - prevSpawn> objectSpawnTime)
{
prevSpawn = gameTime.TotalGameTime;
AddObject();
}
I want to reset the game time to zero, when start the game again or game end and goes to mainmenu and hit the play again, I want to reset gametime.

As i understand from the MSDN entry below, the GameTime.TotalGameTime property will continue 'ticking' until you end the game, or, entire application.
http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.gametime.totalgametime.aspx
Perhaps it would be wiser to use your own object, for which you can reset with any of your actions and hence have more control over the time span. Then you could still use this property for counting the difference from one and the other.
i.e. when you reset/restart etc, do not refer to TotalGameTime and try to make it be zero, but refer to your own object's timespan, or to (TotalGameTime - TimeWhenReset) where TimeWhenReset is the timespan copied from TotalGameTime when you reset.
This is untested, but I think that it should work if I understood correctly.

For a more accurate timer, you would be better using a time span, and a DateTime vairable. Set the DateTime to now when you want to start the timer, and in the TimeSpan do something like this:
timer = StartTime - DateTime.Now;
This will give you a timer you can deploy at any time.

Related

Play back timed events in real time (millisecond accuracy, or almost)

I'm writing an OS X app that records real time events that come from a serial port and saves them to disk. So each millisecond I get 7 integers that I need to save and later "play back" by drawing them in a sort of live line chart. The saving stuff to disk is already done; playing them back is where I'm stuck.
I've done this sort of thing before with other technologies (Arduino, Corona, Processing) where I get a main game loop in which I can do whatever I want time-wise. What I need to know is how set up some sort of 'onEnterFrame' loop to be able to compare the elapsed time to the first event in my stack and fire it when needed. In this loop I would need to tell my views to update themselves and I know Apple guides state that UI updates must happen in the main thread.
I'm a little lost on how to conceptually achieve this kind of onEnterFrame loop in Cocoa as the paradigm is quite different to what I already know.
Of the many things I encountered, this gave me good timing accuracy in my initial tests (1/10th of a millisecond error):
func test() {
print("test")
}
// Run test() every 1 millisecond
let timer = NSTimer.scheduledTimerWithTimeInterval(0.001, target: self, selector: #selector(test), userInfo: nil, repeats: true)

How to update timer interval in swift?

I am working on a game where the rate of change of an image changes over time. At first the image change every two seconds and then it will speed up.
var change = 2.0
func setupGame(){
change = 2.0
changeImage()
}
func changeImage(){
timer = NSTimer.scheduledTimerWithTimeInterval(change, target: self, selector: #selector(SecondViewController.changeColors), userInfo: nil, repeats: true)
change -= 0.1
}
The problem is that it speeds up too much and it doesn't stop. Eventually the change value becomes negative.
Any way to make this work?
You are forgetting two things.
First, you are creating a new repeating timer every time the timer fires. You need to invalidate the old timer before creating the new timer. And since you are going to replace the timer anyway, you do not want this to be a repeating timer; you need to say false instead of true.
Second, if you don't want change to keep getting smaller, you need some sort of condition where you check how small change has become and, if you don't want to get any faster, don't decrement it.

How to determine if an object is at rest?

Using the physics helper library.
I'm trying to figure out how I can determine whether a physics object is at rest. Does anyone know how to do this or have any ideas of what I could do?
An example scenario is a bouncy ball that can be picked up and thrown around. I tried creating a timer that times each individual bounce from a collision event with the floor and determines if the object is at rest based off of that but this does not work for if the user slides the ball to the left and right.
Any suggestions?
If you have runtime access to the underlying Farseer Body, then you also should have access to the property LinearVelocity, which you can check for 0 magnitude.
This is pretty basic stuff. Your physics object should be an instance of some kind of class which contains information on the object's position, velocity, etc etc. At any given time, you should be able to check the speed of the object, and obviously if its speed == 0, it is at rest.
So far I've came up with a simple method. Creating two class variables (Vector2 currentPosition, Vector2 previousPosition) and then creating a dispatcher timer that ticks every so often and using the following tick method:
void bounceTimer_Tick(object sender, EventArgs e)
{
currentPosition = ball.Position;
if (currentPosition == previousPosition)
{
// Object at rest
}
else
{
// Object moving
}
}
previousPosition = currentPosition;
}
There are some issues with it though for example if it captures the balls position in the air coming up and then back down at the same position (very unlikely) and at a very high frequency in ticking it can sometimes capture the same position unexpectedly, at a slow frequency of ticking it takes time to determine if the object is at rest, anyone else have a better method?

How can I get notified of a system time change in my Cocoa application?

I have a Cocoa application that records datestamps on events. I need to know when the system time is reset and by how much, but I can't seem to fine a notification anywhere that tells me such a thing has happened. This change could happen because NTP reset the clock or because the user reset (e.g. from System Preferences). It would be great if there was just a NSNotification I could register to receive, but I'm open to any suggestions.
Apple added in NSSystemClockDidChangeNotification, part of NSDate, in Snow Leopard (10.6). There doesn't appear to be a way to do it in Leopard (10.5) or earlier. Per the Apple NSDate docs:
Posted whenever the system clock is changed. This can be initiated by a call to settimeofday() or the user changing values in the Date and Time Preference panel. The notification object is null. This notification does not contain a userInfo dictionary.
This doesn't appear to tell you "how much" time has changed. You could possibly calculate that by periodically (say, every 5 seconds in a NSTimer) capturing the system time with [NSDate date], saving it into a variable, and then after NSSystemClockDidChangeNotification fires, grab the new date and compare the two together using NSDate's timeIntervalSinceDate: method to get the difference.
Not millisecond or even second accurate, but pretty close.
EDIT: See this post. You could possibly use the UpTime() C command to grab the system uptime in CPU tics (which you can later convert to seconds). You could use this to figure out by how much time has changed (assuming no system restart or sleep). This works even if the system clock is changed by the user or network time protocol.
If some on is looking for solution know system date change change event from 10.4
OSStatus DateChangeEventHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData)
{
NSLog(#"Event received!\n");
return 0;
}
- (void)SystemTimeChangeHandler
{
EventTypeSpec eventType;
eventType.eventClass = kEventClassSystem;
eventType.eventKind = kEventSystemTimeDateChanged;
EventHandlerUPP eventHandlerUPP =
NewEventHandlerUPP(DateChangeEventHandler);
EventHandlerRef eventHandlerRef = NULL;
(void)InstallApplicationEventHandler(
eventHandlerUPP,
1,
&eventType,
self,
&eventHandlerRef);
}
Time moves constantly. A notification every time the current time changed would be a constant, CPU-soaking stream of notifications.
What you need to do is get the current time in your event handler—the one that receives the events you're datestamping. You get the current time by calling [NSDate date].
I don't think there's a single way to do that because of the different mechanisms by which the time could change. But it wouldn't be very expensive (too expensive? Don't know, have you profiled it yet? ;-) to set an NSTimer once a second to check the time and compare it with the previous value. If it's not advanced by about a second, something interesting happened and you can notify your audit object.

Showing completion in a progress bar

In this particular situation, there are 9 automated steps in a process that take varying lengths of time. We currently have a number showing percentage in the center of a progress bar, but it suffers from the common stop-and-go problem of racing up to 33%, waiting a long time, racing up to 55%, waiting an even longer time, then finishing.
What's the best way to present this to the user? Should we remove the number, remove the whole progress bar in favor of an ajax-type circle animation, add descriptive text for the nine steps and checking them off or leave it the way it is? What are your thoughts?
If it really takes a long time, AJAX type of animation is probably not a good idea. I'd go with checklist of items.
The progress bar serves to reassure the user that something is going on. When you do not have a more detailed list of steps, I would recommend 'faking' them.
A basic solution would be to run a timer and slowly increase the progress, capping it at the next logic step value. If the steps take wildly different amounts of time, you can manually adjust the delta value for every timer 'tick' depending in which step you're in.
However, a better solution (I once implemented it this way, but I cannot post the code :)), would be to slowly decrease the delta as the step continues -- so it never quite makes it to the next step. Then the next step arrives, you have a nice jump and the cycle repeats.
In some cases it's more important for a progress bar to indicate that something is happening than for it to be accurate and smooth. Users tend to panic when progress bars stop progressing.
If you have problems with the bar freezing for periods of time, it might be better to replace it with a generic animation that reassures the user that something is happening without worrying about showing how far along the process is. Or, leave the progress bar in place, but add some additional animation as a placebo.
To expand Cadet Pirx's answer, here's some WinForms C# code. You'll need a new UserControl. Put a ProgressBar control on it, called inner. Add the following code:
public partial class ZenoProgressBar : UserControl
{
private const int DEFAULT_FACTOR_VALUE = 10;
private const int DEFAULT_MAXIMUM_VALUE = 100;
public ZenoProgressBar()
{
InitializeComponent();
Maximum = DEFAULT_MAXIMUM_VALUE;
Factor = DEFAULT_FACTOR_VALUE;
}
/// <summary>
/// The "speed" of the progress bar. While it will never get to
/// the end, it uses this number to decide how much further to
/// go each time Increment is called. For example, setting it to
/// 2 causes half of the remaining distance to be covered.
/// </summary>
[DefaultValue(DEFAULT_FACTOR_VALUE)]
public int Factor { get; set; }
[DefaultValue(DEFAULT_MAXIMUM_VALUE)]
public int Maximum { get; set; }
private void ZenoProgressBar_Load(object sender, EventArgs e)
{
inner.Dock = DockStyle.Fill;
}
public void Increment()
{
inner.Value += (inner.Maximum - inner.Value) / Factor;
}
}
I had almost the exact same problem. We also had 9 steps, so the bar would go 11%, 22% 33% etc. and also with some steps taking longer than others.
I decided to make two of the longer steps count as two, so we how had 11 steps, so it wasn't as obvious, and the jumps weren't always even: 9%, 18%, 36%, 45%, 54%, 72%, 81%, 90%, done. The step values were always the same, but since the size of the step wasn't obvious, it worked..

Resources