【问题标题】:C++ make sprite appear every 3 secondsC ++使精灵每3秒出现一次
【发布时间】:2018-04-22 05:49:30
【问题描述】:

我正在为班级制作一个打地鼠游戏,我正在尝试让我的 mole1 精灵每 3 秒出现一次,但我不知道如何让它工作。现在我让游戏只运行 5 秒,最后它会是 60 秒。这是该项目的主要内容。我需要将mole1.visible 更改为true,以便他出现。得到这个后,我将在每个孔中添加另外 5 个痣。

编辑 出于某种原因,我无法编译chrono,但我想出了如何首先让痣出现,但我不能让它消失。我使用模数使其为假,我认为相反的 doig 会使它消失,但它不会

  if((60-now)%4==3){
  mole1.visible=true;
  mole1.paint_sprite(myscreen);
  }

  if ((60-now)%4!=3){
    mole1.visible=false;
    mole1.paint_sprite(myscreen);
  }

其余代码:

using namespace std;  // allows us to avoid std::cout 

#include <iostream>  // standard C++ include
#include <curses.h>  // this is required to use the Unix curses libraries
#include "screen.cpp" // screen class
#include "sprite2.cpp"  // generic sprite class
#include "nonblocking.h" // facilitates non-blocking keyboard events
#include <unistd.h> // used by sleep
#include <time.h>

long start_time, now;
int i;

main()  // main function
{
char c;  // used to get character input from keyboard

screen myscreen;  // screen data structure declaration
char aimage[80][24]={' '}; // fills in entire array with spaces
long start_time, now;
int i; // used for counters
int loop=0;
aimage[1][0]='_';
aimage[2][0]='_';
aimage[0][1]='(';
aimage[1][1]='_';
aimage[2][1]='(';
aimage[3][1]=')';
aimage[1][2]='|';
aimage[2][2]='|';

char bgimage[80][24]={' '}; // fills in entire array with spaces
bgimage[3][0]='"';
bgimage[4][0]='"';
bgimage[5][0]='"';
bgimage[2][0]='-';
bgimage[6][0]='-';
bgimage[1][0]='.';
bgimage[7][0]='.';
bgimage[0][1]='/';
bgimage[8][1]='\\';
bgimage[0][2]='|';
bgimage[8][2]='|';
bgimage[0][3]='\\';
bgimage[8][3]='/';
bgimage[1][4]='"';
bgimage[2][4]='-';
bgimage[3][4]='.';
bgimage[4][4]='.';
bgimage[5][4]='.';
bgimage[6][4]='-';
bgimage[7][4]='"';

char cimage[80][24]={' '}; // fills in entire array with spaces
cimage[1][0]='c';
cimage[2][0]='.';
cimage[3][0]='_';
cimage[4][1]='\'';
cimage[5][1]='-';
cimage[6][1]='.';
cimage[0][1]='C';
cimage[3][1]='o';
cimage[5][2]='\'';
cimage[4][2]='.';
cimage[3][2]='.';
cimage[2][3]='-';
cimage[1][3]='-';
cimage[0][2]='(';

char dimage[80][24]={' '}; // fills in entire array with spaces
dimage[0][0]='6';
dimage[1][0]='0';

sprite hammer(22,10,3,4,aimage,&myscreen);
sprite hole1(20,3,5,9,bgimage,&myscreen);
sprite hole2(40,3,5,9,bgimage,&myscreen);
sprite hole3(60,3,5,9,bgimage,&myscreen);
sprite hole4(20,15,5,9,bgimage,&myscreen);
sprite hole5(40,15,5,9,bgimage,&myscreen);
sprite hole6(60,15,5,9,bgimage,&myscreen);
sprite mole1(21,4,4,7,cimage,&myscreen);
sprite timer(5,10,1,2,dimage, &myscreen);

mole1.visible=false;  // bullet should be false until the player shoots
hole1.paint_sprite(myscreen);
hole2.paint_sprite(myscreen);
hole3.paint_sprite(myscreen);
hole4.paint_sprite(myscreen);
hole5.paint_sprite(myscreen);
hole6.paint_sprite(myscreen);
hammer.paint_sprite(myscreen);
mole1.paint_sprite(myscreen);
timer.paint_sprite(myscreen);

myscreen.display();  // cause the screen to paint for the first time

start_time=(unsigned)time(NULL);

for(;;)  // infinite loop
{
  now = (unsigned)time(NULL)-start_time;
  if((5-now)<=0) //ends game after 60 seconds
  {
    endwin();  // clean up curses (really never executed)
    return(1);
  }


  loop++;
  if (kbhit())
{

  c=getchar();  // get one character from the keyboard

  tcflush(0, TCIFLUSH);  // system call to flush the keyboard buffer 

  if (c=='a')   // if z, move ship left
    {
      hammer.move_sprite(-20,0,myscreen);
    }

  if (c=='d')  // if a, move ship right
    {
      hammer.move_sprite(20,0,myscreen);
    }

  if (c=='s')   // if z, move ship down
    {
      hammer.move_sprite(0,10,myscreen);
    }

  if (c=='w')   // if z, move ship up
    {

      hammer.move_sprite(0,-10,myscreen);
    }
}
  myscreen.display();  // refresh the screen
}

endwin();  // clean up curses (really never executed)
return(1);  // end program (also, never executed)
}

【问题讨论】:

  • 对于特定时间的需求,您通常会发现提供您正在使用的系统很有用。 -- 在 linux 中,#include &lt;unistd.h&gt;sleep(3)usleep(3000000000) 可以解决问题,而不是不断检查差异。 - 现在,时间可能不会返回秒,如果是微秒,那么两次迭代之间可能永远不会有 3 微秒。 -- 此外,您在检查 if 之前将 now2 设置为 now,因此在这种情况下它永远不会为真。 -- 如果您需要进一步、更精确的帮助,请显示真实代码。 ;)
  • 我怀疑第一行的评论。
  • 对不起,我编辑了它并提供了整个代码,不知道我是否应该导致这一切都与计时器无关,我也在 linux 上。
  • 提供一些minimal reproducible example。如果在 Linux 或 POSIX 上,您可能想使用 poll(2)。另请阅读time(7)

标签: c++ intervals


【解决方案1】:

您可以使用全局循环计算时间差,然后在经过 3.0 秒后设置visible=true;。 喜欢这里:

#include <iostream>
#include <chrono>
#include <unistd.h>

const float TIME_TO_SHOW = 3.0f;
//Function to update all objects
void Update( float dt )
{
    static float DeltaCounter = 0.0f;
    DeltaCounter+= dt;
    if ( DeltaCounter > TIME_TO_SHOW )
    {
        DeltaCounter -= TIME_TO_SHOW; //Keep overflow
        //Set object visible here. For example your mole1.visible=true;
    }
}

int main()
{
    typedef std::chrono::duration<float> FloatSeconds;
    auto OldMs = std::chrono::system_clock::now().time_since_epoch();

    const uint32_t SleepMicroseconds = 100;

    //Global loop
    while (true)
    {
        auto CurMs = std::chrono::system_clock::now().time_since_epoch();
        auto DeltaMs = CurMs - OldMs;
        OldMs = CurMs;

        //Cast delta time to float seconds
        auto DeltaFloat = std::chrono::duration_cast<FloatSeconds>(DeltaMs);

        std::cout << "Seconds passed since last update: " << DeltaFloat.count() << " seconds" << std::endl;

        //Update all object by time as float value.
        Update( DeltaFloat.count() );

        // Sleep to give time for system interaction
        usleep(SleepMicroseconds);

        // Any other actions to calculate can be here
        //...
    }

    return 0;
}

如果您有恒定的行为,您可以使用带有sleep 函数的简单循环。它让你的进程休眠给定的秒数:

const int32_t CountObjectToShow = 10;
const unsigned int TIME_TO_SHOW = 3;

for ( int32_t i = 0; i < CountObjectToShow; i++ )
{
    sleep(TIME_TO_SHOW);
    //Set object visible here. For example your mole1.visible=true;
    std::cout << "Object showed" << std::endl;
}

带有全局循环的代码更灵活,可以做许多其他有用的事情。

【讨论】:

    【解决方案2】:

    好吧,为了每隔一定的秒数显示一些东西,你需要一个变量来引用开始时间。然后,检查当前时间和存储时间之间的差值是否大于某个量。

    一个很好的工具是时钟类。

    时钟.h

    #ifndef CLOCK_H
    #define CLOCK_H
    
    #include <chrono>
    
    template<typename Clock_t = std::chrono::steady_clock>
    class Clock
    {
    public:
        using TimePoint = decltype(Clock_t::now());
    private:
        TimePoint m_start;
    public:
        Clock() : m_start(Clock_t::now()) {
    
        }
        ~Clock() {
    
        }
    
        void reset() {
            m_start = Clock_t::now():
        }
    
        float getSeconds() const {
            return std::chrono::duration_cast<std::chrono::duration<float>>(Clock_t::now() - m_start).count();
        }
    
        long long getMilliseconds() const {
            return std::chrono::duration_cast<std::chrono::milliseconds>(ClockType::now() - m_start).count();
        }
    };
    
    #endif
    

    示例

    #include <iostream>
    #include "Clock.h"
    
    int main() {
        Clock<> clock;
    
        constexpr long long spawnRate = 3000;
        while (true) {
            if (clock.getMilliseconds() >= spawnRate) {
                std::cout << "SPAWN\n";
                clock.reset();
            }
        }       
    }
    

    因此,对于你的情况,你会有一个游戏时钟,一个鼹鼠产卵器的时钟,等等。

    在游戏过程中,您只需检查时钟的当前经过时间是否大于某个增量。如果是这种情况,请做一些其他的事情。

    此外,请确保正确重置时钟,例如重置鼹鼠生成计时器时以及开始游戏时。

    这应该处理事情的时机。如果您有其他问题,那么您应该询问这些问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-14
      • 1970-01-01
      • 2020-06-15
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      • 2018-10-12
      • 1970-01-01
      相关资源
      最近更新 更多