How do I reliably pause the state of a game? - timer

So I have a couple instances where I want to be able to 'freeze' the state of my game. It's a top-down scroller, and I want to give the player the ability to pause the scrolling of the screen for a short time by using a powerup (if you fall to the bottom of the screen you die). I also want to pause the game as it is starting, and draw a 3, 2, 1, go! to give the player time to get ready, because right now as soon as you hit play, the screen starts scrolling.
I have been using Timer to accomplish this, however it doesn't work if I want to freeze the screen on consecutive occasions. Like if a player uses a freeze, the screen sucesssfully freezes, but if they quickly use another freeze, it doesn't work. There seems to be an unintended cool-down. I have a similar problem for the 'intro delay' I explained earlier. For some reason it only works on the first 2 levels. Here is how I am using Timer.
if(gameState != STATE.frozen) {
camera.translate(0, (float) scrollSpeed);
staminaBar.setPosition(staminaBar.getX(), (float) (staminaBar.getY()+scrollSpeed));
staminaMeter.setPosition(staminaMeter.getX(), (float) (staminaMeter.getY()+scrollSpeed));
healthBar.setPosition(healthBar.getX(), (float) (healthBar.getY()+scrollSpeed));
healthMeter.setPosition(healthBar.getX(), (float) (healthMeter.getY()+scrollSpeed));
boostBar.setPosition(boostBar.getX(), (float) (boostBar.getY()+scrollSpeed));
boostMeter.setPosition(boostMeter.getX(), (float) (boostMeter.getY()+scrollSpeed));
screenCeiling += (float) scrollSpeed;
screenFloor += (float) scrollSpeed;
}
else {
Timer.schedule(new Task() { //freeze the screen for 5 seconds
#Override
public void run() {
gameState = STATE.playing;
}
}, 5);
}
From what I understand, it waits 5 second before resuming the game to the 'playing' state. But like I said, this only works when activated between large intervals and I don't know why. Is there a better way I can be doing this?
As for the intro delay, this may be a question better asked seperate, but I use the same method, but it doesn't let me draw sprites over my tiledmap, so if anyone knows how to do that please include it in your response

Assuming the code you posted is in your render loop, then whenever you are not in the frozen state, you are creating a new timer task on every frame. So if you freeze for 5 seconds and your game is running at 60fps, you will create 300 timer tasks, each of which is going to force the game to go back to playing state. The last one won't fire until 5 seconds after the first one fires, so there will be a five second "cooldown" during which you cannot change the state to anything besides playing, because there will be another timer task firing on every frame during that time.
You need to ensure that you only create one timer task, only when you first enter frozen state.
I do have a suggestion...instead of using a state to freeze the game, use a variable that's multiplied by scrollSpeed. Change that variable from one to zero when the player uses the powerup. Then you can do fancy stuff like quickly interpolating from one to zero so the speed change isn't so abrupt. And it will probably make your code simpler since there would be one less state that must be handled differently in the algorithm.

Check your gameState variable in the render method and if the game is playing, then update the game as usual and draw it.
If the game is not playing then skip the game's update method and create a time delay from the current time:
endTime = TimeUtils.millis()+5000;
Then each time through the render method check to see if current time is greater than the end time. When the current time is past your delay time, set gameState back to playing and have the game go back to updating.
You'll have to have another boolean flag so you only set the endTime once (you don't want to keep resetting this each time through the render loop), or if "STATE" is an enum, then include an option for "justPaused" for the exact frame that you pause the game, set the end time, then set STATE to "notPlaying".
You can also use this to create an alternative "update" method where you can update your countdown sprites, but not update the game itself. When the game is playing this other update method will be skipped.

Related

Timer in games for multiple players React

I am making a typeracer on reactjs (I am new in the frontend languages) and so far, so good. The typeracing is working as expected (singleplayer for now). Now what I want to implement is two types of timers:
A typeracing game should last not more than 60 seconds. After 60 seconds I want to end the game.
Before a new game starts, there should be another time for 10 seconds. Which is the same timer after the game ends.
So, in perfect starting scenario, everything would look like this (for now):
I wait 10 seconds (where I have a button to either join the game or not and review the typeracer text), if I've joined the game I have 60 seconds to finish it (if I do, I wait until the end of the timer or until everyone has finished), and then this cycle repeats.
Here comes my question -> how can I set this timer so it is not possible to type in the box:
<div className="box userTypingBox">
<input type="text" onChange={onChange}></input>
</div>
until the timer finished (and also display the seconds left until the game starts/ends). And then how can I set a timer where the box is available for those who has joined and after 60 seconds, the cycle repeats.
Keep in mind (if important) that later I am going to use socket io to make the game for multiple players and multiple players to join one game.
NOT IMPORTANT FOR THE ANSWER: Of course I have also done a research but don't really have something as good as an idea which I could try. The only thing I can think of is make a while cycle for the box and have another class with a timer function which returns either false and true. And if its true the player can type, if its false it should display the 10 second timer.

Is there a way to render my Termbox game and handle keyboard events in the same loop?

I'm having issues with my termbox program rendering the screen and handling keyboard events. Recently, I've finished a C and C++ class at my university. I wanted to demonstrate my knowledge by creating a basic Snake game. The first steps, I wanted to get a simple render loop going and have a block of text simply move leftward and exit the game upon reaching the 0th x-coordinate. The issue arises when continuing to the next render frame, because the game is running single-threaded the next frame won't be rendered until a new keyboard event is accepted. Ordinarily, I would expect the game to continue rendering regardless of events, new events affecting the new frame.
As for potential solutions, I thought about using multiple threads to run the game loop and handle keyboard events. But, I think this would be overkill for such a small problem, there are likely easier alternatives than having to manage multiple threads for a simple snake game.
As for the code, it's as simple as:
while (1)
{
tb_clear();
draw(gameState);
tb_present();
struct tb_event event;
tb_poll_event(&event);
if (event.ch == 'q')
break;
}
After digging through the header file a bit more I found a method which doesn't wait forever.
/* Wait for an event up to 'timeout' milliseconds and fill the 'event'
* structure with it, when the event is available. Returns the type of the
* event (one of TB_EVENT_* constants) or -1 if there was an error or 0 in case
* there were no event during 'timeout' period.
*/
SO_IMPORT int tb_peek_event(struct tb_event *event, int timeout);

How to avoid timer stacking

I'm sorry if his question has already been asked in some way.
I'm currently re-writing a vibration driver in a Linux kernel. The reason why I changed it was due to overly strong vibrations caused by gaining a specific velocity of the vibration motor. To work that around I've implemented a PWM like controller that simply stops the motor at a specific time before reaching it's max acceleration, finally it keeps repeating this action.
There is one big issue that is mainly noticeable when using the keyboard. If the vibrator gets toggled too often in a very short time, the timer tends to stack up times, causing lag and vibration delays. This flaw can be easily achieved when typing multiple keys at once.
To demonstrate you this event visually I created a small graph.
The red area indicates timer overlap. The overlap between vibration 1 and 2 causes a delay for the second vibration, moving it out of place.
My main idea to prevent this issue is to merge vibrations into one if the previous vibration hasn't finished yet. For instance vibration 2 would simply join vibration 1.
Another way would be to simply use a single vibration for stacked vibrations, for instance, vibration 2 could simply use the last remaining bit of vibration 1. Why would this work? Well because the vibration controller that I've implemented only applies to times under 100ms, meaning vibration time differences would not be noticeable if one was to spam to keystrokes at once, instead both keystrokes should form and share single vibration.
Finally to my question, how could I make a function check itself it it's being called again. Or at least add a time for the function to check if keystrokes are being spammed multiple times in a short period?
int foo ()
{
static foo_counter;
if(foo_counter)
{
// If function has been called again
}
return(0);
foo_counter++;
}

Timer to represent AI reaction times

I'm creating a card game in pygame for my college project, and a large aspect of the game is how the game's AI reacts to the current situation. I have a function to randomly generate a number within 2 parameters, and this is how long I want the program to wait.
All of the code on my ai is contained within an if statement, and once called I want the program to wait generated amount of time, and then make it's decision on what to do.
Originally I had:
pygame.time.delay(calcAISpeed(AIspeed))
This would work well, if it didn't pause the rest of the program whilst the AI is waiting, stopping the user from interacting with the program. This means I cannot use while loops to create my timer either.
What is the best way to work around this without going into multi-threading or other complex solutions? My project is due in soon and I don't want to make massive changes. I've tried using pygame.time.Clock functions to compare the current time to the generated one, but resetting the clock once the operation has been performed has proved troublesome.
Thanks for the help and I look forward to your input.
The easiest way around this would be to have a variable within your AI called something like "wait" and set it to a random number (of course it will have to be tweaked to your program speed... I'll explain in the code below.). Then in your update function have a conditional that waits to see if that wait number is zero or below, and if not subtract a certain amount of time from it. Below is a basic set of code to explain this...
class AI(object):
def __init__(self):
#put the stuff you want in your ai in here
self.currentwait = 100
#^^^ All you need is this variable defined somewhere
#If you want a static number as your wait time add this variable
self.wait = 100 #Your number here
def updateAI(self):
#If the wait number is less than zero then do stuff
if self.currentwait <= 0:
#Do your AI stuff here
else:
#Based on your game's tick speed and how long you want
#your AI to wait you can change the amount removed from
#your "current wait" variable
self.currentwait -= 100 #Your number here
To give you an idea of what is going on above, you have a variable called currentwait. This variable describes the time left the program has to wait. If this number is greater than 0, there is still time to wait, so nothing will get executed. However, time will be subtracted from this variable so every tick there is less time to wait. You can control this rate by using the clock tick rate. For example, if you clock rate is set to 60, then you can make the program wait 1 second by setting currentwait to 60 and taking 1 off every tick until the number reaches zero.
Like I said this is very basic so you will probably have to change it to fit your program slightly, but it should do the trick. Hope this helps you and good luck with your project :)
The other option is to create a timer event on the event queue and listen for it in the event loop: How can I detect if the user has double-clicked in pygame?

Running two loops simultaneously for a game - C

I'm making a game in C for my programming class, and I have to place a time countdown on the game, but I can't make it work right, because if a put a countdown function and a delay(1000), it works for the countdown, but doesn't work for the game , because it makes wait the 1s every move.
My code so far is
while(tempo > 0)
{
tempo_na_tela(&tempo);
contador_tempo(&tempo);
if(kbhit())
{
mover_refem(getch(), p_refem, &refem.px, &refem.py,
numero_inimigos_na_tela(n, in1));
}
mover_inimigo(n, p_terrorista, in1);
}
The function tempo_na_tela(..) puts the string of time on the screen, the contador_tempo(..) is the countdown, the mover_refem(...) is the function to move the game character, and the mover_inimigo(..)is a function that randomly moves the enemy in the screen.
I need to place the tempo_na_tela and the contador_tempo functions in one loop, that run simultaneously with the other loop, that run the moving functions.
How can I do it?
You're experimenting a XY problem i think.
You don't need to run simultaneously thoses 2 functions. What you're trying to accomplish is a game loop, it's very common in video-games, especially early ones.
Ask yourself, when do you need to re-paint your elements ? The answer is probably after having updated all of your data (Time, ennemy position, and having logged your player's movement)
So, you don't need simultaneous looping (ie thread i would have suggested, even if it's not true simultaneous, but that's another story.)
Instead, you can stick with one loop, but you have to do something in this fashion :
while (game_not_ended())
{
update_data();
repaint_data();
}
I hope you'll take the time to reconsider your code and the scope of your issue.

Resources