I am currently programming a Jump n' Run game in C# using OpenTK Framework and OpenGL.
Open TK provides preset functions like GameWindow.Run(); or GameWindow.onUpdateFrame(); onRenderFrame();
As far as i thought through it, all actions that draw OpenGL elements or primitives should belong into onRenderFrame, whereas game events like player movement should be performed in onUpdateFrame, so these actions can be calculated in advance before rendering a new frame.
Am I right? Would it make a difference to perform all actions in the onRenderFrame method? OpenTK suggests not to override these methods and subscribing to their Events (onRenderFrameEvent) instead.
http://www.opentk.com/files/doc/class_open_t_k_1_1_game_window.html#abc3e3a8c21a36d226c9d899f094152a4]
What is subscribing and how would i subscribe to an event instead of overriding a method?
protected override void OnUpdateFrame(FrameEventArgs e)
{
base.OnUpdateFrame(e);
this.gameObjects.moveObjects();
this.player.Move();
if (this.player.jumpstate == true) this.player.Jump();
}
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
Matrix4 modelview = Matrix4.LookAt(Vector3.Zero, Vector3.UnitZ, Vector3.UnitY);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadMatrix(ref modelview);
GL.LoadIdentity();
GL.Translate(0.0f, 0.0f, -3.5f);
this.gameObjects.drawObjects();
this.player.Draw();
SwapBuffers();
}
It's pretty much as the comments said: update your world in the UpdateFrame event and render it in RenderFrame.
This makes sense when you realize that your game will run on wildly different hardware. Some computers might only be able to render your game at 15fps. Others will achieve a solid 60fps. And players with 120Hz monitors will want your game to run at 120fps in order to enjoy the full potential of their systems.
In all those cases, you want your game logic to run at the same speed and give identical results.
The simplest way to achieve this is by setting a fixed UpdateFrame rate in GameWindow.Run():
using (var game = new GameWindow())
{
game.VSync = VSyncMode.Adaptive;
game.Run(60.0, 0.0);
}
This code snippet instructs OpenTK to raise 60 UpdateFrame events per second and as many RenderFrame events as the system can handle, up to the refresh rate of the monitor. When running on a slower system, OpenTK will drop RenderFrame events in order to ensure a solid 60 UpdateFrame events per second. This is typically called a "fixed timestep".
See Fix Your Timestep! for why this is desirable.
See Quake 3 for why you should not perform your world updates inside the RenderFrame event (short version: in Quake 3, numerical inaccuracies on high fps allow players to jump higher and gain a competitive advantage.)
Edit: for the second part of your question, see understanding C# events. For example:
using (var game = new GameWindow())
{
game.RenderFrame += (sender, e) =>
{
GL.Clear(ClearBufferMask.ColorBufferBit);
game.SwapBuffers();
};
}
There is no inherent advantage to subscribing GameWindow.RenderFrame compared to inheriting from GameWindow and overloading its OnRenderFrame method. Pick whichever approach fits your code structure better.
Related
I wrote a little application, which replaces the cursor with a hand drawn cursor. Therefor i used a QOpenGlWidget.
For the animation i use the frameSwapped signal:
connect(this, SIGNAL(frameSwapped()), this, SLOT(update()));
Till now i don't use any specific OpenGl function, so i just override the paintevent analog to a classic QWidget.
Qt documentation:
When performing drawing using QPainter only, it is also possible to perform the painting like it is done for ordinary widgets: by reimplementing paintEvent().
void Widget::paintEvent(QPaintEvent* event) {
// Draw Cursor
POINT LpPoint;
GetCursorPos(&LpPoint);
QPoint CursorPos(LpPoint.x, LpPoint.y);
CursorPos = mapFromGlobal(CursorPos);
QPainter Painter(this);
Painter.drawEllipse(CursorPos, 20, 20);
}
I filmed the result with 240 fps and recognized that my drawn cursor is 2 frames behind the windows cursor. It is not important, that there's no lag at all. But only one frame would be great. And it would be great if i would be able to quantify the lag. Such that i know it's one Frame +- the duration for rendering. I already read this, but i'm not quite familiar with OpenGl. And i don't think i can use this with a QOpenGlWidget. Maybe somebody has an idea how to decrease the lag to only one Frame.
Update 1:
I did some research and tried a lot with moderate success.
My latest version:
connect(this, SIGNAL(frameSwapped()), this, SLOT(animate()));
void Widget::animate() {
makeCurrent();
QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions();
f->glFinish();
//std::this_thread::sleep_for(std::chrono::milliseconds(12));
update();
}
I use glFinish() to sync CPU and GPU. Now the drawn cursor is about one frame behind. Sometimes it is even better than one frame. But there are skipped frames, so the drawn cursor does not move at all. Overall there is no consistency. I still have some trouble understandig exactly how OpenGl updates. Maybe some more information: setIntervall is set to 1 and it is double buffered. I think maybe it is a problem not know what Qt exactly does. Calling update only schedules an update and i don't have controll on how the buffers are swaped. Maybe somebody has more experience on these issues. I can say that the paintevent/paintGL is called every 16 ms. I added std::this_thread::sleep_for(std::chrono::milliseconds(12)); to have less delay between render and the actual mouse position. That helps to reduce the average latency. But for me it is nearly impossible to make a solid prediction on what will happen in the next frame.
Update 2:
I posted a similar issue on Qt forum. Even though it's not a direct answer, it contains some helpfull information.
I'm developing a 2d fighting game in c++ (for learning purposes) and I'm having a hard time figuring out how to properly implement game logic. For a quick overview of my current architecture, I have component classes that act as data holders and I have 'systems' which are just functions designed to act on those components. I have a scene class which holds an array of fighters that are currently in game and this scene is passed to individual sub-systems which then can freely act on fighter components, updating fighters state:
//Add a fighter object to array of fighters and set starting position
scene.CreatePlayerFighter(160.0f, 0.0f);
scene.CreateAIFighter(80.0f, 45.0f);
gameWolrd.Init(scene);
Renderer.Init(scene, window);
AI.Init(scene);
//etc...
//Game loop
while (true)
{
Input.Update(scene);
Physics.Update(scene);
AI.Update(scene);
//etc....
window.ClearBuffers();
Renderer.Update(scene, colorShaderProgram);
window.SwapBuffers();
}
Again, inside each sub-system (Renderer, AI, Input, etc.) all fighter components are being passed into system functions and spit back out with new values which are then inserted back into fighters:
void Physics::Update(Scene& scene)
{
for (Fighter& fighter : scene.fighters)
{
//Update fighter position based on fighter's current velocity which has been set by input
TransformComponent newFighterPosition = System::MoveFighter(fighter.GetComponent<TransformComponent>(), fighter.GetComponent<VelocityComponent>());
//Insert new TransformComponent to update fighter's position
fighter.Insert<TransformComponent>(newFighterPosition);
}
}
This current architecture has the advantage of being loosley coupled in that I can add and remove systems very easily without effecting the fighter class or it's components directly. The problem is everything is hopelessly serial, as my scene is passed into each sub-system one by one to update fighters. I mention this problem because one of my thoughts to implement a game logic layer was to have higher level classes just call specific game engine system functions directly like physics.MoveFighter(TransformComponent, VelocityComponent, float amountToMove); where I can add additional parameters to give the user at the game logic layer level more control. Of course doing things this way means system functions would be called and invoked in any order the user of the game logic saw fit. Would there be a way to still implement a game logic layer in this way and maybe queue up all calls and reorder them to run correctly within the game engine? Or would there be a better way to try and implement game logic within my current architecture?
As I see your goal, you could just store movementFactor field in fighter, and allow to change it from game logic layer. In Physics class delta is then mul-ied by that field. If you use component like system you probably do not want to update components manually, only operate with data.
Logic update order is a complex problem: imagine a chicken falling on an egg. It happens that in the same frame chicken touches the egg and egg is ready to show us new little chick. What should be executed first? That depends on what is updated first: physics or eggs, and on the fact whether reactions apply immediately. The best scenario (most fair usually) would be for them not to apply immediately, but form a stack of objects (components) state changes, for them to be resolved independently after the action phase.
Also make sure you do not want to stick with existing entity system like entityx.
for a scientific task, flickering areas with a stable frequency (max. 60 Hz), shall be displayed on the screen. I tried to achieve a stable stimulus visualization using Qt 5.6.
According to this blog entry and many other online recommendations, I realized three different approaches: Inheriting from QWindow Class, QOpenGLWindow Class and QRasterWindow Class. I wanted to get the advantage of vsync and avoid the usage of QTimer.
The flickering area can be displayed. Also a stable time period between the frames has been measured with 16 up to 17 ms.
But every few seconds some missed frames are spotted. It can be seen very clearly that there is no stable visualization of the stimulus. The same effect occurs on all three approaches.
Have I done the implementation of my code properly or do better solutions exist? If the code is adequate for its purpose do I have to assume that it is a hardware problem? Could it be that difficult then, to display a simple flickering area?
Thank you very much for helping me!
As Example you can see my code for QWindow Class here:
Window::Window(QWindow *parent)
: m_context(0)
, m_paintDevice(0)
, m_bFlickerState(true){
setSurfaceType(QSurface::OpenGLSurface);
QSurfaceFormat format;
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
format.setSwapInterval(1);
this->setFormat(format);
m_context.setFormat(format);
m_context.create();}
The render() function, which is called by overwritten event functions, is:
void Window::render(){
//calculating exposed time between frames
m_t1 = QTime::currentTime();
int curDelta = m_t0.msecsTo(m_t1);
m_t0 = m_t1;
qDebug()<< curDelta;
m_context.makeCurrent(this);
if (!m_paintDevice)
m_paintDevice = new QOpenGLPaintDevice;
if (m_paintDevice->size() != size())
m_paintDevice->setSize(size());
QPainter p(m_paintDevice);
// draw using QPainter
if(m_bFlickerState){
p.setBrush(Qt::white);
p.drawRect(0,0,this->width(),this->height());
}
p.end();
m_bFlickerState = !m_bFlickerState;
m_context.swapBuffers(this);
// animate continuously: schedule an update
QCoreApplication::postEvent( this, new QEvent(QEvent::UpdateRequest));}
I got help of some experts from the qt-forum. You can follow the whole discussion here. At the end, this was the result:
"
V-sync is hard ;) Basically it's fighting with the inherent noisiness of the system. If the output shows 16-17 ms then that's the problem. 17 ms is too much. That's the skipping you see.
Couple of things to reduce that noise:
Don't do I/O in the render loop! qDebug()is I/O and it can block on all kinds of buffering shenanigans.
Testing V-sync under a debugger is useless. Debugging introduces all kinds of noise into your app. You should be testing v-sync in Release mode without debugger attached.
try not to use signals/slots/events if you can help it. They can be noisy i.e. call update() manually at the end of paintGL. You skip some overhead this way (not much but every bit counts).
If all you need is a flickering screen avoid QPainter. It's not exactly slow, but drop into the begin() method of it and see how much it actually does. OpenGL has fast, dedicated facilities to fill the buffer with a color. You might as well use it.
Not directly related, but it will make your code cleaner:
Use QElapsedTimer instead of manually calculating time intervals. Why re-invent the wheel.
Applying these bits I was able to remove the skipping from your example. Note that the skipping will occur in some circumstances, e.g. when you move/resize the window or when OS/other apps are busy doing something . You have no control over that.
"
I am trying to launch a physics object after loading a game scene, something similar to https://www.makegameswith.us/tutorials/getting-started-with-spritebuilder/creating-two-levels/
The code I have is something like this
- (void)didLoadFromCCB {
// tell this scene to accept touches
self.userInteractionEnabled = TRUE;
[self launchObject];
}
- (void) launchObject {
CCNode* object = [CCBReader load:#"Object"];
// Apply force to it
}
The problem is if I add a sleep method in didLoadFromCCB before launching the object or the first line in the launchObject, the game scene itself is loading only after that many seconds (say after clicking play) and immediately launches, but I want the game scene to load and after n seconds the physics object is launched.
I can easily solve this problem by using
- (void)update:(CCTime)delta
by setting some conditions for launch, but the question is, is that the right approach. I don't want to complicate update method to hold multiple if/else stuff and use it beyond what it's intended for, especially if there is another best way to do it.
I tried different solutions posted in this forum but didn't help my case.
I am working on a screen manager for a miniature game engine, and so far I cannot find a proper solution to managing screen objects without using the 'blob' for each one of the screens. Is blob tolerable in such circumstances where I need a list of renderable objects in one controller?
I would consider using the MVC pattern in this situation. Otherwise, if you're not careful, it's very easy to end up with a bunch of spaghetti code where the screen code is reaching into the game code, and vice versa.
I have recently coded something you might call a "screen manager".
I started with the idea that, whatever game I make, the render system is going to be pretty much the same in terms of how to render (how to manage the hardware). The thing that changes is what is rendered, and how to draw it (do I want a box or a circle or a bitmap.. representing what... etc).
So basically the "game state" is responsible for knowing how to render itself, and should do so when given a render surface from the screen manager or graphics system (It should also be responsible for other things like knowing how input, physics, etc act upon itself).
I implemented it with a singleton for the GraphicsSystem object, which was called something like this:
GameState gs;
Graphics::System().Init(DOUBLE_BUFFER, 640, 480);
...
while(still_looping) {
...
// When it is time to render:
Graphics::System().RenderGameState(&gs);
}
And how, you ask, does the Graphics::System() singleton know how to render the game state? It knows because the game state is inherited from a listener exposed by the graphics system...
//within GraphicsSystem.h...
class BaseRenderer
{
public:
virtual void Render(BITMAP *render_surface) = 0;
};
//GameState defined with:
class GameState : public BaseRenderer
{
public:
void Render(BITMAP *render_surface);
...
You can do this with nearly all the subsystems... (probably not timing, as it is needed in the game loop).
Why singletons? Well, it is C++ and I'm assuming there is only 1 screen, or graphics subsystem to render with. I'm not sure if you are using multiple screens, or a mobile phone or a console. The other way I would do it is to have the graphics system as static global variables in a separate file, giving them file scope only, and having accessor functions in that file (my old C way of doing things).
The key though is encapsulation. Let your screen manager manage the hardware. Let your game state dictate how itself should be expressed.
If this misses the point, please clear up your question and I can edit the answer.