如何创建从99%倒数到0%的计时器,每秒减少1%

时间:2019-04-03 08:12:39

标签: c timer

我正在尝试创建一个计时器,以显示在游戏的右上角,该计时器从99%下降到0%,每秒下降1%,并且计数器在屏幕上刷新。 ps(我是编码的新手,如果这是一个愚蠢的问题,对不起)

我尝试使用一个简单的倒计时循环,但它会一次减少所有计数,并且不会将计数器另存为变量,因此我可以在屏幕上的特定位置打印它

void battery_life(){
     int w, h;
    get_screen_size(&w, &h);

    int y=99;
    while (y !=0)
    y--;
    draw_int (2*w/3+5,h-h+2,y);
    draw_char(2*w/3+7,h-h+2,'%');
}

我希望当我运行此计数器时,它每秒每秒-1%,但它只是一次倒数并显示0%

4 个答案:

答案 0 :(得分:1)

这是一个相当广泛的问题,但是这里有几种通用方法,都需要:

  1. 将游戏逻辑与渲染分开,并且
  2. 使用状态机更新游戏状态,而不是暂停执行。

这是两种不同的方法:

  1. 游戏循环

    由于您正在设计游戏,因此您可能会拥有某种game loop,即:

    while (!ending)
    {
        process_input();
        update_state();
        draw();
    }
    

    您的update_statedraw函数应具有不同的职责,类似于:

    static int current_percentage = 100;
    void update_state(void)
    {
        // keep the time of last update
        static timestamp last_update_time = 0;
    
        // decrease 'current_percentage' when needed
        timestamp now = get_current_game_time();
        if (seconds_elapsed(now, last_update_time) >= 1)
        {
            last_update_time = now;
            current_percentage--;
        }
    }
    
    void draw(void)
    {
        // just handle the drawing
        draw_percentage(current_percentage);
    }
    
  2. 多线程

    反之,如果您使用多个线程,则可能会采用完全不同的方法:

    static atomic_int current_percentage = 100;
    void decrease_percentage(void)
    {
         atomic_fetch_sub(&current_percentage, 1);
    }
    
    void draw(void)
    {
        // just handle the drawing
        int percentage = atomic_load(&current_percentage);
        draw_percentage(percentage);
    }
    
    // no game loop - we will need to configure function callbacks
    // for different events
    void on_game_start(void)
    {
        // one thread should update the timer
        call_periodically(1000 /* period in ms */, decrease_percentage /* what to call */);
    
        // this should run at max possible fps
        call_when_idle(draw /* what to call when idle */);
    }
    

后一种方法略短一些,尽管主要原因是因为在配置回调的函数中隐藏了许多功能。前一种方法更容易推论,并且没有多线程代码引起的问题(死锁,竞争条件-请注意使用atomic_int来确保原子更新),这就是为什么在以下情况下首选游戏循环的原因可能。

如果您的游戏需要利用多个内核,那么您将需要涉及某种线程,这带来了额外的复杂性。第二种方法的实现也将取决于您的平台,因为计时器不是C标准的一部分。

最后,如果您使用的是游戏引擎/框架(libgdx,Unity),则可能仅需实现updatedraw回调,而框架将负责调用这些函数在需要的时候。

答案 1 :(得分:0)

while循环中缺少括号,因此一开始就行不通!

您确实需要实现一个计时器,以便您可以实际知道什么时候过去了,因为代码的操作速度可能会有所不同,并且绝对会在您进行任何更改时确定。 您如何执行此操作完全取决于您正在编写的系统,并且您没有提供足够的信息来帮助我们。 大多数情况下,运行C的硬件都有硬件计时器和您需要定位的特定寄存器。

答案 2 :(得分:0)

几件事:

  • 您一会儿什么也不做。如果您不将代码放在方括号内,则只会执行循环中的下一行。
  • 您不在任何地方等待第二次。
  • 您可能应该重新考虑您的方法-如果解决了上述问题,则在调用该函数时,程序中的其他所有内容将冻结99秒,除了更改电池文本。

也许更好的方法是编写一个具有static int y = 99的函数,并且每次调用它时,绘制电池文本并将y减小1(静态或多或少意味着该值为记得在通话之间)。

然后,在您的主游戏循环中,您可以检查是否已过去一秒钟,如果已过,请执行该功能。

答案 3 :(得分:-1)

如果您使用统一,则可以简单地使用协程来每秒倒数百分比。

void countDown()
{
    int percent = 99;
    StartCoroutine(CountDownToZero(percent));
}


IEnumerator CountDownToZero(int percentage)
{
    WaitForSeconds wait1sec = new WaitForSeconds(1f);
    while(percentage > 0)
    {
        percentText.text = percentage.ToString()+"%";
        yield return wait1sec;
        percentage= percentage- 1;
    }
    percentText.text = "0%";
}

对于其他引擎,它们还提供了计划程序以计划功能的执行。