I'v always wondered how this works. Does having more slow down the game? for example how would one represent checking if a car has flipped. It could be seen as:
if (player.car.angle.y == 180)
{
do something
}
The parts that puzzle me is, when would the game check for it? The way I see it, every thing that can happen in the game seems to evolve an if. I'm just wondering how these are handled.
Also, since the game runs through a loop, what if the car is flipped for more than 1 frame, would a Boolean really be used to check if the event has been fired
Thanks
In most general terms, any object in an engine has a state - if it changes state (e.g. not flipped to flipped), that is a transition.
From a transition you can fire an event or not, but as the transition does only occur when changing state the event won't be fired more then once.
As for the conditions that trigger the transitions, they have to be coded somewhere of course. Sometimes they are more explicitly coded, but mostly they are parameterized so that scripts or some sort of configuration can change them easily.
How it is implemented in the end differs broadly, it depends on the libraries that are used as well the engine design itself.
Related
In my little project, I've decided to create a game that updates a counter of the user's experience points every second, as well as printing a menu and allowing the user to navigate said menu simultaneously. The code to update the user's experience is as follows, and it works perfectly fine standalone.
double timerX = GetTickCount();
double timerY = GetTickCount();
while(true)
{
double timerZ = GetTickCount() - timerX;
double timerA = GetTickCount() - timerY;
if(timerZ >= 1000) {
userExperience = userExperience + 1;
timerX = GetTickCount();
}
if(timerA >= 1100) {
system("CLS");
refreshExperience();
timerY = GetTickCount();
}
The function 'refreshExperience()' simply prints the 'userExperience' variable onto the screen using 'cout'.
At the same time as this, my program should be able to display the main menu GUI and ask for input from the user. However, I do not want the asking of input to halt the program, especially the money updater, as it is paramount that that is updated constantly. I have attempted to use multithreading by creating a thread for the 'refreshExperience' function, and also creating a thread for asking for input, but the problem still remained - the money would only update if the user was continually inputting (pressing keys). If he was not, the money would stay the same.
Any help would be very much appreciated.
Getting input from the user with no discernible break in program execution is only possible in GUI programming. When working in the console, every request for user input will block for the obvious reason that the program has to wait to actually have the necessary data before proceeding.
This is also why you should initialize variables before declaring them; if you don't, stack-allocated variables will contain random (to you) data and the program will not function as intended. Conceptually, this is the same problem the console has, except it doesn't have the luxury of free will and can't simply choose to skip the wait.
Conceptually, programs that have a user interface work by operating with a loop. Every event that occurs, from a mouse movement to a button click, triggers an event in the Window procedure. In the Win32 API, it's just a switch statement that checks for each possible event against what actually happened. When there's a match, the system triggers that event handler.
It should be noted that it only seems like there is no lag, because usually graphical window procedures are fast enough to seem to respond instantaneously. In reality, any action on the window triggers a calculation by the computer to determine what part of the window was blocked and must be redrawn, as it is now called "invalid."
Lastly, I would highly recommend a different method for the scoreboard update. I know it's just a contrived example for you to experiment with, but that means it's just as good if not better for trying out some design patterns, namely the observer pattern. Rather than the program checking for input every possible clock cycle it can is just a waste. When you have a situation like this, it's common to use callback functions, which in C are just function pointers that you pass along. That way you don't have to check to find out when the event is triggered, you can just have the event invoke the function that you passed in as a parameter. This is how Node.js works, by the way, and how it seems to do so much at once despite being single-threaded.
If you've heard anything about Reactive programming lately -it's been getting talked about just about everywhere in the C# community these past few months- this is what it's talking about, and the reason I bring it up is because this is one of the more common, though trivial, examples of a textbook reactive programming scenario.
Hello I am looking for a signal for gtkmm. Basically I am doing some simulations and what I want is something like this :
I assume I do 5 simulations :
progressBar.set_fraction(0);
1 simulation
progressBar.set_fraction(progressBar.get_fraction()+1/5)
2 simulation
progressBar.set_fraction(progressBar.get_fraction()+1/5)
3 simulation
progressBar.set_fraction(progressBar.get_fraction()+1/5)
4 simulation
progressBar.set_fraction(progressBar.get_fraction()+1/5)
5 simulation
progressBar.set_fraction(progressBar.get_fraction()+1/5)
But I don't know which signal I have to use and how to translate to this.
Thank you a lot for your help !!!
The pseudo code which you presented in your question should actually work - no signal is necessary. However, you could introduce a signal into your simulation for update of the progress bar. IMHO this will not solve your problem and I will try to explain why and what to do to solve it:
You provided a little bit too less context, so, that I will introduce some more assumptions: You have a main window with a button or toolbar item or menu item (or even all of them) which start the simulation.
Let's imagine you set a breakpoint at Gtk::ProgressBar::set_fraction().
Once the debugger stopped at this break point you will find the following calls on the stack trace (probably with many other calls in between):
Gtk::Main::run()
the signal handler of the widget or action which started the simulation
the function which runs the five simulations
and last the call of Gtk::ProgressBar::set_fraction().
If you could inspect the internals of Gtk::ProgressBar you would notice that everything in Gtk::ProgressBar::set_fraction() is done properly. So what's wrong?
When you call Gtk::ProgressBar::set_fraction() it probably generates an expose event (i.e. adds an event to the event queue inside of Gtk::Main with a request for its own refresh). The problem is that you probably do not process the request until all five runs of the simulation are done. (Remember that Gtk::Main::run() which is responsible for this is the uppermost/outmost call of my imaginery stack trace.) Thus, the refresh does not happen until the simulation is over - that's too late. (Btw. the authors of Gtk+ stated somewhere in the manual about their cleverness to optimize events. I.e. there might be finally only one expose event for the Gtk::ProgressBar in the event queue but this does not make your situation better.)
Thus, after you called Gtk::ProgressBar::set_fraction() you must somehow flush the event queue before doing further progress with your simulation.
This sounds like leaving the simulation, leaving the calling widget signal handler, returning to Gtk::Main::run() for further event processing and finally coming back for next simulation step - terrible idea. But we did it much simpler. For this, we use essentially the following code (in gtkmm 2.4):
while (Gtk::Main::events_pending()) Gtk::Main::iteration(false);
(This should hopefully be the same in the gtkmm version you use but if in doubt consult the manual.)
It should be done immediately after updating the progress bar fraction and before simulation is continued.
This recursively enters (parts of) the main loop and processes all pending events in the event queue of Gtk::Main and thus, the progress bar is exposed before the simulation continues. You may be concerned to "recursively enter the main loop" but I read somewhere in the GTK+ manual that it is allowed (and reasonable to solve problems like this) and what to care about (i.e. to limit the number of recursions and to grant a proper "roll-back").
What in your case is the simulation we call in general long running functions. Because such long running functions are algorithms (in libraries for anything) which shall not be polluted with any GUI stuff, we built some administrational infra structure around this basic concept including
a progress "proxy" object with an update(double) method and a signal slot
a customized progress dialog which can connect a signal handler to such a progress object (i.e. its signal slot).
The long running function gets a progress object (as argument) and is responsible to call the Progress::update() method in appropriate intervals with an appropriate progress factor. (We simply use values in the range [0, 1].)
One issue is the interval of calling the progress update. If it is called to often the GUI will slow down your long running function significantly. The opposite case (calling it not often enough) results in less responsiveness of GUI. Thus, we decided for more often progress update. To lower the time consuming of GUI, we remember the time of last update in our progress dialog and skip the next refreshs until a certain duration since last refresh is measured. Thus, the long running function has still some extra effort for progress update but it is not recognizable anymore. (A good refresh interval is IMHO 0.1 s - the perception threshold of humans but you may choose 0.05 s if in doubt.)
Flushing all pending events results in processing of mouse events (and other GTK+ signals) also. This allows another useful feature: aborting the long running function.
When the "Cancel" button of our progress dialog is pressed it sets an internal flag. If the progress is updated next time it checks the flag. If the flag became true it throws a special exception. The throw aborts the caller of the progress update (the long running function) immediately. This exception must be catched in the signal handler of the button (or whatever called the long running function). Otherwise, it would "fall through" to the event dispatcher in Gtk::Main where it is catched definitely which would abort your application. (I saw it often enough whenever I forgot to catch.) On the other hand: catching the special exception tells clearly that the long running function has been aborted (in opposition to ended by regulary return). This may or may not be something which can be stated on GUI also.
Finally, the above solution can cause another issue: It enables to start the simulation (via GUI) while a simulation is already running. This is possible because button presses for simulation start could be processed while in progress update. To prevent this, there is actually a simple solution: set a flag at start of simulation in the GUI until it has finished and prevent further starts while the flag is set. Another option can be to make the widget/action insensitive when simulation is started. This topic becomes more complicated if you have multiple distinct long running functions in your application which may or may not exclude each other - leads to something like an exclusion matrix. Well, we solved it pragmatically... (but without the matrix).
And last but not least I want to mention that we use a similar concept for output of log views (e.g. visual logging of infos, warnings, and errors while anything long running is in progress). IMHO it is always good to provide some visual action for end users. Otherwise, they might get bored and use the telephone to complain about the (too) slow software which actually steals you the time to make it faster (a vicious cycle you have to break...)
So I'm pretty new with programming from scratch, have mainly used unity for a few years up untill now so my general programming knowledge is pretty good. Started studying game development at a university after summer though where we began programming from scratch and as a task we have to make a simple game in a 2D engine we made together in class.
So the game I decided to make was a copy of bomberman and I've gotten as far as where I'm now making the bombs functional.
The problem I'm having is that I don't know how to propperly add in a timer that counts down the time to where the bomb exlpode so the player can avoid it.
I've tried SDL_Delay and _sleep which both just pause the entire program so that doesn't work and I've searched around for more options but not really understood how things work. If I could get some expamples and links to pages that explains how to properly make something like this work (something easy and small hopfully :P) then that would be highly appreciated!
Note that we are using SDL in the engine.
Thanks!
Typically, a game uses a loop, in which you read user input (you are probably using SDL_PollEvent for that), advance the game state for a short time period and draw the screen. This loop is typically called the game loop, render loop or main loop.
A simple, accurate and typical way to delay an event (such as a timed explosion), is to store the future time into a queue. Then, each time the game state advances, check the first and therefore the oldest timestamp in the queue and if the current time is higher than the stored one, then we know that the the thing should now happen and you can call the function that executes the event without delay. Then remove the timestamp from the queue and check the next one until only future events remain or the queue is empty.
If the event delay can vary, then you'll need to use a priority queue to always get the event that should fire next.
skypjack points out in the comments that this is a problematic approach if you need to implement pausing the game. That can be solved by not measuring wall clock, but instead use a separate simulation time that drifts from the wall clock when the game is paused. They also propose a simpler solution:
store a timeToEvent (to be elapsed) and decrement it, so that you detach the game time from the real one. Once it's <= 0, it's its time.
That approach is simpler, but has more overhead for checking the expiration of deadlines.
In my project i'm running a train which stops moving when it reaches a particular point this moving is carried out by glutTimerFunc .I once again want the train to start from the location where i click my mouse to a particular location
BUT THE PROBLEM HERE IS,
My timer still running even after reaching that location,so even when i initialise the starting point its not working(it continues from the left location).
Now i need to stop the timer and start the train timer for the new location.
The API documentation has the following to say:
There is no support for canceling a registered callback. Instead, ignore a callback based on its value parameter when it is triggered.
So, add a boolean to your software and ignore the event whenever it is triggered. It would be better to use a clock-based timer rather than an event-driven timer and do your timed updates manually everytime the main loop runs (you detect the amount of time since the last update, and you determine whether to perform an update tick(s)), in the long run however. This is how physics and various other time-based simulations are handled in most professional software, using the event-driven model sets you up to miss or frequently wind up handling a timed event excessively late.
Welcome to the world of game engines and actors.
My recommendation is that you don't try to do this by turning glutTimerFunc on or off directly. The timer function should be the top level "heartbeat" for the entire program, and it's job is just to tell every object that has behaviour - an "actor" - that it should update itself. The train should have its own internal state that knows where it is and whether it should be moving or not.
I'm working on a data import job using the Go language, I want to write each step as a closure, and use channels for communication, that is, each step is concurrent. The problem can be defined by the following structure.
Get Widgets from data source
Add translations from source 1 to Widgets.
Add translations from source 2 to Widgets.
Add pricing from source 1 to Widgets.
Add WidgetRevisions to Widgets.
Add translations from source 1 to WidgetRevisions
Add translations from source 2 to WidgetRevisions
For the purposes of this question, I'm only dealing with the first three steps which must be taken on a new Widget. I assume on that basis that step four could be implemented as a pipeline step, which in itself is implemented in terms of a sub-three-step pipeline to control the *WidgetRevision*s
To that end I've been writing a small bit of code to give me the following API:
// A Pipeline is just a list of closures, and a smart
// function to set them all off, keeping channels of
// communication between them.
p, e, d := NewPipeline()
// Add the three steps of the process
p.Add(whizWidgets)
p.Add(popWidgets)
p.Add(bangWidgets)
// Start putting things on the channel, kick off
// the pipeline, and drain the output channel
// (probably to disk, or a database somewhere)
go emit(e)
p.Execute()
drain(d)
I've implemented it already ( code at Gist or at the Go Playground) but it's deadlocking with a 100% success failure rate
The deadlock comes when calling p.Execute(), because presumably one of the channels is ending up with nothing to do, nothing being sent on any of them, and no work to do...
Adding a couple of lines of debug output to emit() and drain(), I see the following output, I believe the pipelining between the closure calls is correct, and I'm seeing some Widgets being omitted.
Emitting A Widget
Input Will Be Emitted On 0x420fdc80
Emitting A Widget
Emitting A Widget
Emitting A Widget
Output Will Drain From 0x420fdcd0
Pipeline reading from 0x420fdc80 writing to 0x420fdd20
Pipeline reading from 0x420fdd20 writing to 0x420fddc0
Pipeline reading from 0x420fddc0 writing to 0x42157000
Here's a few things I know about this approach:
I believe it's not uncommon for this design to "starve" one coroutine or another, I believe that's why this is deadlocking
I would prefer if the pipeline had things fed into it in the first place (API would implement Pipeline.Process(*Widget)
If I could make that work, the drain could be a "step" which just didn't pass anything on to the next function, that might be a cleaner API
I know I haven't implemented any kind of rung buffers, so it's entirely possible that I'll just overload the available memory of the machine
I don't really believe this is good Go style... but it seems to make use of a lot of Go features, but that isn't really a benefit
Because of the WidgetRevisions also needing a pipeline, I'd like to make my Pipeline more generic, maybe an interface{} type is the solution, I don't know Go well enough to determine if that'd be sensible or not yet.
I've been advised to consider implementing a mutex to guard against race conditions, but I believe I'm save as the closures will each operate on one particular unit of the Widget struct, however I'd be happy to be educated on that topic.
In Summary: How can I fix this code, should I fix this code, and if you were a more experienced go programmer than I, how would you solve this "sequential units of work" problem?
I just don't think I would've built the abstractions that far away from the channels. Pipe explicitly.
You can pretty easily make a single function for all of the actual pipe manipulation, looking something like this:
type StageMangler func(*Widget)
func stage(f StageMangler, chi <-chan *Widget, cho chan<- *Widget) {
for widget := range chi {
f(widget)
cho <- widget
}
close(cho)
}
Then you can pass in func(w *Widget) { w.Whiz = true} or similar to the stage builder.
Your add at that point could have a collection of these and their worker counts so a particular stage could have n workers a lot more easily.
I'm just not sure this is easier than piecing channels together directly unless you're building these pipelines at runtime.