Why do you have to fix your timestep instead of having a SetFPS function?

As a beginner to MonoGame, I am wondering why it requires you to fix your timestep instead of having a function like SetFPS() or something similar to make MonoGame get the correct FPS of your computer. Could you explain to me why it is this way?

You do not have to have a fixed time step in your game

You can turn on vertical sync, which will lock the draw and update rate to the refresh rate of your monitor (if your computer can keep up)

You can set your own update rate, 112fps, 65 fps or whatever you like. However your better off using an update/draw rate that matches your monitor

You can have an unlocked draw and update rate.

You will have to make the SetFps method yourself. However Monogame does let you set all these things.

2 Likes

its legacy stuff from single threaded games before phones had 8 cores and now i think almost no computers in use have <2 … there no point (that i can see), in drawing faster than the screen can refresh. now we should use at least 2 threads , one for more for game, physics , colliders, (unless u do pixel type collidision) AI, and then the draw at VSYNC. I would look into producer consumer pattern… that way u can use multiple threads without locks , and then copy the last good frame (just the visible data) , draw that, while updating the next frame. I dont use the Update function, my draw function doesnt have a lock anymore and i draw whatever last frame was reference after the other thread finished writing to it. my physics might update at 4000 fps!, while i draw at 60 or 120 or whenever it vync calls the draw, just the last finished frame data, AND as a bonus if you save some old frames you get an instant replay feature cheap. i use setTimerResulotion (windows only) , measure the time to update the back threads, and even the framerate that way. so i get an even frameratee or its 1000 fps, i can set ti to 120 or something playable now and enjoy great lock free mutlthreaded performance.

Hi, how do you update/copy visual data without locking? Won’t there be contentions between threads?

Google Producer-Consumer Pattern. I update one frame in a ring of vector data structures or lists. Meanwhile, the drawing code gets a reference to the last good frame that can be immutable; it can be copied to a buffer. In the drawing code, while the back code has released that buffer, it’s updating another one.

I have my drawing code draw with a reference to a struct of structs or a display list of polygons with lists of Vector2D. These contain just visual data such as vertices, color, positions in the World Coordinate System (in meters), or some entity handles or unique IDs. It’s mapped to a sprite, and its location in meters has already been changed. This can be immutable. If it’s the last good frame, you can draw it whenever.

i jsu asked chatgpt:

heres how to set timer so thatt you can acutally tim

using System;
using System.Collections.Generic;
using System.Threading;

struct FrameData
{
public List Vertices;
public Color Color;
public Vector2D Position;
// Other data as needed
}

class LocklessProducerConsumerRenderer
{
private FrameData frameBuffer;
private int bufferSize;
private volatile int writeIndex = 0;
private volatile int readIndex = 0;

public LocklessProducerConsumerRenderer(int bufferSize)
{
    this.bufferSize = bufferSize;
    frameBuffer = new FrameData[bufferSize];
}

public void UpdateFrame(FrameData newFrame)
{
    int nextWriteIndex = (writeIndex + 1) % bufferSize;

    // Check if the buffer is full
    if (nextWriteIndex != readIndex)
    {
        frameBuffer[writeIndex] = newFrame;
        writeIndex = nextWriteIndex;
    }
    else
    {
        // Handle buffer full situation (e.g., drop frames or wait)
    }
}

public void RenderFrames()
{
    while (true)
    {
        if (readIndex != writeIndex)
        {
            FrameData frameToRender = frameBuffer[readIndex];
            readIndex = (readIndex + 1) % bufferSize;

            // Render the frame using frameToRender data
            // ...
        }
        else
        {
            // Handle no frames to render (e.g., wait or continue)
        }
    }
}

}

setTimerResolution (windows only) , set to 4 -1 ms… to smooth the framerate if you must…

i have a game loop on a worker thread…

took me 3 months to figure this how… tried on android with locks i was stuck for a week.

enjoy… wrangling AI is hard but its doign ok. i like monogame because its trained on it… its old.

still you cannot trust its code… fully…

make the most creative code you can this its hard to google up… it hello to get figured out so people dont want to share it… well the chat bot can do it… so here you go…

public void SetTimerResolution(uint resolutionInMilliseconds)
{
TimeBeginPeriod(resolutionInMilliseconds);
}

public void ResetTimerResolution(uint resolutionInMilliseconds)
{
TimeEndPeriod(resolutionInMilliseconds);
}

Achieving 1 millisecond (ms) timing accuracy in .NET Core, particularly on Linux and Android, can be challenging due to the way these operating systems schedule tasks and handle timers. However, there are a few methods you can explore:

  1. High-Precision Timers in Linux: Linux offers high-resolution timers (HRTimers) that can theoretically provide better timing accuracy. These are accessible via system calls and may require P/Invoke in C#. However, they’re generally used in native C or C++ development due to the complexity of working directly with system calls in C#.
  2. Busy Wait Loop: For very short durations, you might resort to a busy wait loop using Stopwatch. This approach can provide high precision but is very CPU-intensive and generally not recommended due to its impact on system performance and power consumption.

csharpCopy code

var stopwatch = Stopwatch.StartNew();
while (stopwatch.ElapsedMilliseconds < 1)
{
    // Busy wait
}
stopwatch.Stop();
  1. Thread.Sleep Accuracy: The accuracy of Thread.Sleep is typically around 15-16 ms on Windows due to the default system clock resolution, and it’s similar or potentially worse on Linux and Android. You can try to improve this by using a combination of Thread.Sleep and a busy wait loop.

csharpCopy code

int waitTime = 1; // Desired wait time in milliseconds
var stopwatch = Stopwatch.StartNew();
while (true)
{
    if (stopwatch.ElapsedMilliseconds >= waitTime)
        break;

    Thread.Sleep(0); // Yield to other threads
}
  1. Real-Time Operating Systems (RTOS): If precise timing is crucial, consider using a Real-Time Operating System (RTOS). Linux can be configured with real-time patches (PREEMPT_RT) for better timing accuracy, although this is typically beyond the scope of standard application development.
  2. Hardware Timers: On certain hardware, you might have access to hardware timers that can provide high precision. Accessing these would require specific hardware knowledge and potentially native development.
  3. .NET Core Timer Classes: Unfortunately, the standard timer classes in .NET Core, like System.Threading.Timer and System.Timers.Timer, do not provide millisecond precision reliably due to the way they are scheduled by the operating system.
  4. Android Specific: For Android, using Xamarin or MAUI, the same constraints apply. Android’s timer granularity is generally not fine enough for 1 ms timing due to the non-real-time nature of the Android operating system.

In summary, achieving 1 ms timing accuracy on Linux and Android using .NET Core is challenging and often not feasible with standard programming approaches due to the limitations of the operating systems and hardware. If exact 1 ms accuracy is essential, you may need to consider specialized hardware or software solutions tailored to real-time operations.

User

You

hwo can i call the posit timer from c# i liinux or android

ChatGPT

ChatGPT

To call POSIX timers from C# on Linux or Android, you’ll have to use Platform Invocation Services (P/Invoke), which allow managed code to call unmanaged functions implemented in dynamic link libraries (DLLs). In the case of Linux and Android, these would be shared object files (.so). POSIX timers are part of the Linux kernel APIs and are not directly available in the .NET framework.

Here’s a basic example of how you can define and use POSIX timer APIs in C# via P/Invoke. The following code demonstrates how to set up a periodic timer using timer_create, timer_settime, and a signal handler:

  1. Import the Necessary Libraries: First, declare the external functions you’ll need from the C library:

csharpCopy code

using System;
using System.Runtime.InteropServices;

class PosixTimer
{
    // Define the necessary structures and enums
    private struct itimerspec
    {
        public timespec it_interval; // Interval for periodic timer
        public timespec it_value;    // Initial expiration
    }

    private struct timespec
    {
        public long tv_sec;  // Seconds
        public long tv_nsec; // Nanoseconds
    }

    private enum clockid_t : int
    {
        CLOCK_REALTIME = 0,
        CLOCK_MONOTONIC = 1,
        // Other clock types...
    }

    private enum sigevent_type : int
    {
        SIGEV_SIGNAL = 0,
        SIGEV_NONE,
        SIGEV_THREAD,
        SIGEV_THREAD_ID = 4
        // Other event types...
    }

    // Declare the external functions
    [DllImport("libc.so.6", EntryPoint = "timer_create")]
    private static extern int timer_create(clockid_t clockid, ref sigevent sevp, out IntPtr timerid);

    [DllImport("libc.so.6", EntryPoint = "timer_settime")]
    private static extern int timer_settime(IntPtr timerid, int flags, ref itimerspec new_value, ref itimerspec old_value);

    // Add other necessary P/Invoke declarations...

    // Define methods to use these APIs...
}
  1. Set Up a POSIX Timer: You will need to create a timer, set its time, and handle the expiration events. Handling signal-based events directly in C# can be complex and might require additional handling depending on your application’s architecture.
  2. Platform-Specific Considerations:
  • The above code is an example for Linux. On Android, especially if you’re using Xamarin or .NET MAUI, you might not have direct access to these APIs due to the sandboxed nature of the platform.
  • Ensure that the libc version (libc.so.6 in the example) matches the target system. The exact version or path might vary.
  1. Safety and Compatibility:
  • Working with P/Invoke requires careful management of memory and resources. Make sure to handle errors and clean up resources properly.
  • This approach is low-level and might not be compatible across all distributions or versions of Linux/Android.
  1. Alternative Approaches:
  • If you find this approach too complex or not suitable for your needs, consider using higher-level abstractions or libraries that are more .NET-friendly.
  • For periodic actions or timing, investigate whether the built-in .NET timers (System.Threading.Timer, System.Timers.Timer) or System.Diagnostics.Stopwatch can meet your needs despite their limitations.

Implementing POSIX timers in C# for Linux and Android is advanced and requires a good understanding of both the .NET interoperability features and the Linux/Android system APIs. This kind of implementation is typically done in more system-level programming languages like C or C++.

ChatGPT can make mistakes. Consider checking important information.

?

for android i havent tired because itse slower… i run it full trottle…
ChatGPT