Delay time in GMS2 - game-maker

I am trying to make it so that when you click it will show a different cursor_sprite for 0.25 seconds. I currently need some way to add a delay to this. Here is my code so far:
In create event:
/// #description Set cursor
cursor_sprite = spr_cursor;
In step event:
/// #description If click change cursor
if mouse_check_button_pressed(mb_left)
{
cursor_sprite = spr_cursor2;
// I want to add the delay here.
}

You could use the build-in Alarms for this, but I don't like these much when it becomes nested with parent objects.
So instead of Alarms, this is the way I would do it:
Create Event:
cursor_sprite = spr_cursor;
timer = 0;
timermax = 0.25;
I create 2 variables: the timer will be used to count down, and the timermax to reset it's time.
Step Event:
if (timer > 0)
{
timer -= 1/room_speed //decrease in seconds
}
else
{
cursor_sprite = spr_cursor;
}
if mouse_check_button_pressed(mb_left)
{
cursor_sprite = spr_cursor2;
timer = timermax;
}
For each timer, I let it count down in the Step Event through 1/room_speed, that way, it will decrease the value in real-time seconds.
Then you can set the timer through timer = timermax
Then if the timer reaches zero, it'll do the given action afterwards.
Though a reminder that it's in the Step Event, so once the timer reaches zero, it'll always reach the else statement if there are no other conditions before. Usually I use the else-statement to change conditions so it doesn't reach the timer code multiple times.

#Steven:
This is useful as far as it goes, but I think you mixed up the starting values for timer and timermax. If timer is counting down, then it obviously can't start at 0.
Also, starting timer at your intended duration completely obviates the need for even having a second variable (timermax).
So it could go:
Create Event:
cursor_sprite = spr_cursor;
timer = 0.25;
Step Event:
if mouse_check_button_pressed(mb_left)
{
cursor_sprite = spr_cursor2;
timer = 0.25;
}
if (timer > 0)
{
timer -= 1/room_speed //decrease in seconds
}
else
{
cursor_sprite = spr_cursor;
}

Related

my while loop only take the first value even if it redefined in arduino

hello i try to make an interruption in my arduino code to execute only one time a part of it. i use 2 while loop, the first is suppose to detecte when i press a button and the second when i release it. between the two the code i want to execute only one time for one press.
but even if the condition of the while is good it don't want to stop.
my serial monitor
my code :
void loop()
{
long button = cs_4_6.capacitiveSensor(5);
while(button < 1000)
{
long button = cs_4_6.capacitiveSensor(5);
Serial.println(button);
Serial.println("not ok");
}
if(nbButton[3] == 0)
{
nbButton[counter] = 1;
counter++;
}
else
{
int nbButton[] = {0, 0, 0, 0};
}
while(button > 1000)
{
long button = cs_4_6.capacitiveSensor(5);
Serial.println(button); // print sensor output 2
Serial.println("ok");
}
delay(50);
}
You are declaring long button each time in your while loops. As you are already declaring it at the beginning of your loop there is no need to do it at any other place. The while loops are taking your first declaration, which is not changing, whereas the Serial.print takes the new one defined only in the while loops.
In your two while loops change long button = cs_4_6.capacitiveSensor(5); to button = cs_4_6.capacitiveSensor(5);
Hope it helps,

Jump buffer not playing nice with variable jumping

I'm having an issue where my player object always jumps to maximum height when jumping because of my buffer. This is my first game, so I'm playing around with Heartbeast's engine. I figure I'm missing something fairly obvious, and just hoping y'all can help!
Here's what I'm working with in my jump action script:
///enable_movement_jump(height, input, release_input)
/*
Call this script to enable platform jumping
on a movement entity.
*/
var height = argument[0]; // The jump height (Should be positive)
var input = argument[1]; // The input for jumping
var release_input = argument[2]; // The input for jump height control (release)
var coyoteFrames = 10; // The grace period, in frames, for coyote time
var jumpBufferFrames = 10; // The buffer, in frames, for the jump buffer
// Check for ground collision
if (place_meeting(x, y+1, collision_object) || place_meeting(xprevious, yprevious+1, collision_object)) {
coyoteTimer = 0; // Reset coyote timer
if ((input) || (jumpBufferTimer < jumpBufferFrames))
{
vsp[0] = -height;
coyoteTimer = coyoteFrames; // Max coyote timer
jumpBufferTimer = jumpBufferFrames; // Max buffer timer
}
} else {
if (input)
{
jumpBufferTimer = 0; // Reset buffer timer
if (coyoteTimer < coyoteFrames) // During coyote time
{
vsp[0] = -height;
coyoteTimer = coyoteFrames; // Max coyote timer
jumpBufferTimer = jumpBufferFrames; // Max buffer timer
}
}
if (release_input && vsp[0] <= -height/3) {
vsp[0] = -height/3;
}
}
++coyoteTimer; // Increase coyote
++jumpBufferTimer; // Increase buffer
When you hit the ground, you reset the coyoteTimer, but you place the jumpBufferTimer in a different condition, perhaps these should be set to 0 under the same conditions?

Capacitive Touch Sensor: "When touched for 100 ms"

I'm facing a programming question in which I want to trigger some code whenever a capacitive touch sensor has been touched for 100 ms (to distinguish false positives in my prototype). My sensor is touched by this code
if (digitalRead(touchPin))
Now whenever it has been touched for 100ms I want some other code (for instance, activating a LED) to run. I can't really seem to find a solution because my startTime = millis() variable keeps resetting.
Does anyone know how to tackle this problem?
You need a bool variable, to store last state (TRUE if touched and FALSE if not)
Also, you need to store time when it has been changed to TRUE. Time could be taken by millis() function
If your bool variable is true, check, if time passed is more than your 100 ms.
So:
// In your global scope:
...
// Last touch state
bool isTouched = FALSE;
// time, when last touch happened
int touched_t = 0;
// In your loop:
...
bool isTouchedNow = (digitalRead(touchPin) == HIGH);
// Touch state is changed till last measure:
if (isTouchedNow != isTouched)
{
// Set "last isTouched state" to new one
isTouched = isTouchedNow;
// If it wasn't touched before, store current time (else zero):
touched_t = isTouched ? millis() : 0;
}
else //If touch state isn't changed till last time:
{
//If state was "touched" and now it "touched", and 100ms has passed:
if (isTouched && touched_t > 0 && millis() - touched_t > 100)
{
// Call your function, that should be called,
// whan sensor is touched for 100 ms (activate a LED of something)
DOTHESTUFF();
}
}
...

QProgressDialog does not display immediately

I have a QProgressDialog that I want to display immediately
QProgressDialog *progress = new QProgressDialog("Downloading files...",
"Cancel", 0, 2*selection.size()+1);
progress->setMinimumDuration(0);
progress->setWindowModality(Qt::WindowModal);
progress->setValue(0);
Then I run a for loop with the task and finally assign the maximum value:
for (int i = 1; i < selection.size()+1; ++i)
{
progress->setValue(2*i-1);
if (progress->wasCanceled())
break;
do_half_task();
progress->setValue(2*i);
if (progress->wasCanceled())
break;
do_second_half();
}
progress->setValue(2*selection.size()+1);
But with this code, the dialog window borders appear, transparents without any widgets inside, and only gets filled with the label and progressbar when a full for loop has completed.
I think this is because only after a full loop has completed is that Qt can compute the duration of each step, and check that it will be >0 which I am setting as minimum duration. However, from the docs I see
minimumDuration : int
If set to 0, the dialog is always shown as soon as any progress is set. The default is 4000 milliseconds.
From where I would've expected the dialog to show up immediately in the first loop pass after setting progress->setValue(1).
How can I get my QProgressDialog to appear immediately?
Not sure if this matches for Qt too
but in C# if you run the execution of your code in the same thread like
ProcessBar p = new ProcessBar();
this.Controls.Add(p);
...
for (int i = 0; i < 100; i++) {
p.Value = i;
Thread.Sleep(1);
}
then you have the problem that your Form does not get to the code where it is redrawn.
Maybe try making your execution loop in a nother thread?
When you make the main thread go into a loop, it can't do any event processing until the loop ends and your method returns.
So it can only process all "paint update" requests once you are done.
You can call QCoreApplication::processEvents() inside the loop to allow it to return to event processing for a while.
To show the dialog immediately then just call QProgressDialog::show().

How to disuse Delay Function it cause a bad effect (how to solve this scenario)?

I have one scenario problem and I don't want to use interrupts cause the same problem will be there I will be forced to use delay to insure that specific time did pass.
the problem:
I don't want to use the delay function cause it stops the other tasks to be checked or executed taking a situation:
I have motor that run 6 seconds if button1 is pressed and if a man press button2 the motor 2 immediately need to be turned on and work for 2 second.
so the code will be like this:
main ()
{
if( Rd0 == 0 ) // is button1 is pressed
{
RunMotre1();
__delay_ms(6000);
StopMotor1();
}
if( Rd1 == 0 ) // is button2 is pressed
{
RunMotor2();
__delay_ms(2000);
StopMotor2();
}
}
the problem of this code if we pressed the button b to start Motor 2 he will
not work cause the system is blocked on delay and wait it to be finished .
and that cause that if we start -> press button 1->motor 1 runing -> pressing buTTon2 to start Motor2-> Motor2 not working until the 6 seconds be passed.
so is there a way to resolve this problem case.
for example if exists comparing who mutch time Motor1 did run if is greate or = 6 secound then stop the motor 1 example (samthing like this if exist) :
Time counter1;
Time Counter2;
main()
{
if( Rd0 == 0 ) // is button 1 to start motor1 is presed ?
{
RunMotre1();
counter1.start();
}
if(counter1.CurentElapsedTimes==6 Secound) // is motor1 did run 6 seconds
{
counter1.stop();
counter1.Initialise();
StopMotor1();
}
if( Rd1 == 0 ) // is button 2 to start motor2 is pressed.
RunMotor2();
counter2.start();
}
if(counter2.CurentElapsedTimes==2 Secound) // is motor2 did run 2 seconds
{
counter2.stop();
counter2.Initialise();
StopMotor2();
}
or any solution
platform pic microcontroller using xc8 compiler
PRESUPPOSITION: I don't know which PIC you are using, but I assume that it has at least a free timer.
The problem here is that you need something to track the time as it passes. My suggestion is to use the same technique that the Arduino FW uses: setup a timer to fire an interrupt every X milliseconds/seconds, then in the interrupt service routine (ISR) update a counter.
When you press the button set the counter, then wait for the counter to reach another value before turning the motor off.
I'll write here a small pseudo-code example, since I don't remember how to properly write an ISR with a PIC compiler nor I know what is your PIC (and, so, the commands to initialize the timer).
I chose to use a timer granularity of 100ms, but you can change it as you prefer.
I also chose to set counter as a 8-bit variable; it can count up to 25.5 seconds, but since the highest delay is 6 seconds it's ok.
Note that you need just ONE timer, so you can add any number of motors without the need for adding counters
char counter;
char motor1StartTime;
char motor2StartTime;
bool motor1Running;
bool motor2Running;
Timer1_ISR()
{
counter++;
}
main()
{
counter = 0;
motor1StartTime = 0;
motor2StartTime = 0;
motor1Running = false;
motor2Running = false;
// Setup the timer to trigger the Timer1_ISR every 100ms
...
while(1)
{
if( Rd0 == 0 )
{ // If the button is pressed start the motor and save the counter
RunMotor1();
motor1StartTime = counter;
motor1Running = true;
}
if ((motor1Running) && ((counter - motor1StartTime) >= 60))
{ // If the motor is running from more than 6 seconds, shut it down
StopMotor1();
motor1Running = false;
}
if( Rd1 == 0 )
{ // If the button is pressed start the motor and save the counter
RunMotor2();
motor2StartTime = counter;
motor2Running = true;
}
if ((motor2Running) && ((counter - motor2StartTime) >= 20))
{ // If the motor is running from more than 2 seconds, shut it down
StopMotor2();
motor2Running = false;
}
}
}

Resources