1

在我的交通模拟项目中,我想在一段时间内改变交通灯对象的状态(灯的颜色)。我编写了 TrafficLightGroup 类,将 7 个交通灯(T 灯)分成 3 组。在这个类中,有一个模拟()函数,可以将 t-light 添加到组中并在一段时间内更改它们的状态。这是 TrafficLightGroup 类:

class TrafficLightGroup
{
    TrafficLight* head, tail, greenLight;
    float duration; //Period
public:
    float time; //Current time elapsed in seconds
    // duration: TrafficLight period
    TrafficLightGroup(float duration): head(NULL), tail(NULL), greenLight(NULL), time(0){
        this->duration = duration;
    }
    // light: Pointer to the traffic light object to be added to the group
    void add(TrafficLight* light) {
        if(head == NULL) {
            head = light;
            head->state = light->getState();
            tail = head;
        }
        else {
            tail->next = light;
            tail = tail->next;
        }
    }

    /* If the traffic light group timer reaches the switching period (i.e., duration member variable) of
    the group, the next light in the group is turned into green while the others are turned into red
    */

    void simulate(float timestep) { //timestep in seconds
        this->duration = timestep;
        this->time = timestep * 6;

        TrafficLightGroup group1(timestep); //TTOP (road at t-top junction )
        TrafficLightGroup group2(timestep); //TRIGHT (road at t-right junction )

        TrafficLight* light1 = new TrafficLight(2*239 + 70, 250, 180, GREEN);
        light1->setState(GREEN);
        TrafficLight* light2 = new TrafficLight(2*239 + 240, 170, 90, RED);
        light2->setState(RED);

        group1.add(light1);
        group2.add(light2);
        //There are more t-lights but I don't include them

        float i = 0;
        while(i <= time) {
            if(i == time - 5 * timestep) {
                light1->setState(RED);
                light2->setState(GREEN);
            }

            else if(i == time - 4 * timestep) {
                light1->setState(GREEN);
                light2->setState(RED);
            }

            else if(i == time - 3 * timestep) {
                light1->setState(RED);
                light2->setState(GREEN);
            }

            else if(i == time - 2 * timestep) {
                light1->setState(GREEN);
                light2->setState(RED);
            }

            else if(i == time - timestep) {
                light1->setState(RED);
                light2->setState(GREEN);
            }

            else if(i == time) {
                light1->setState(GREEN);
                light2->setState(RED);
            }

            i += 1;
        }
    }
};

如果您还想查看 TrafficLight 类,我在此处添加:

typedef enum {
    GREEN = 0,
    RED = 1
}tLightState;

class TrafficLight {
    float x, y;
    float dir; //direction of the traffic light (determines the orientation of the traffic light on the map)
    sf::Texture redTexture;
    sf::Texture greenTexture;
    sf::Sprite sprite;

public:
    tLightState state; //current state of the light (either green or red). tLightState should be an enum
    TrafficLight* next; //pointer to the next traffic light in the traffic light group

    //x: x coordinate of the traffic light
    //y: y coordinate of the traffic light
    //dir: traffic light direction, i.e., orientation
    //state: initial state of the traffic light
    TrafficLight(float x, float y,  float dir, tLightState state)
    {
        this->x=x; this->y=y; this->dir=dir;
        if(state == GREEN){
            greenTexture.loadFromFile("images/trafficlights/green.png");
            sprite.setTexture(greenTexture);
        }
        else{
            redTexture.loadFromFile("images/trafficlights/red.png");
            sprite.setTexture(redTexture);
        }

        sprite.setPosition(sf::Vector2f(x,y));
        sprite.setRotation(dir);
        sprite.setOrigin(0, 0);
    }

    //Returns the position and the direction of the traffic light
    //dir: orientation
    void getPosition(float &x, float &y, float &dir) {x = this->x; y = this->y; dir = this->dir;}

    //Draws the traffic lights
    void draw(sf::RenderWindow *window) {window->draw(this->sprite);}

    //Returns current traffic light state
    tLightState getState() {return state;}

    //Sets the traffic light state
    void setState(tLightState state) {
        this->state = state;

        if(state == GREEN) {
            greenTexture.loadFromFile("images/trafficlights/green.png");
            sprite.setTexture(greenTexture);
        }
        else {
            redTexture.loadFromFile("images/trafficlights/red.png");
            sprite.setTexture(redTexture);
        }
    }
};

这是 main() 函数:

TrafficLight tlights[] = {
    {2*239 + 70, 250, 180, GREEN}, {2*239 + 240, 170, 90, RED},
    {4*239 + 70, 2*239 + 70, 180, RED}, {4*239 + 50, 2*239 + 170, 0, GREEN},
    {2*239 + 40, 2*239 + 170, 90, GREEN}, {2*239 + 70, 2*239 + 70, 180, RED},
    {2*239 + 200, 2*239 + 70, 270, RED}
};

TrafficLightGroup tlg1{10};
TrafficLightGroup tlg2{10};
TrafficLightGroup tlg3{10};

tlg1.add(new TrafficLight (2*239 + 70, 250, 180, GREEN));
tlg1.add(new TrafficLight (2*239 + 240, 170, 90, RED));
tlg2.add(new TrafficLight (4*239 + 70, 2*239 + 70, 180, RED));
tlg2.add(new TrafficLight (4*239 + 50, 2*239 + 170, 0, GREEN));
tlg3.add(new TrafficLight (2*239 + 40, 2*239 + 170, 90, GREEN));
tlg3.add(new TrafficLight (2*239 + 70, 2*239 + 70, 180, RED));
tlg3.add(new TrafficLight (2*239 + 200, 2*239 + 70, 270, RED));

tlg1.simulate(10); // these simulate calls are in *while (window.isOpen())* loop
tlg2.simulate(10);
tlg3.simulate(10);

我想模拟 10 秒周期的 t 灯。在模拟()函数中,我在某个特定时间更改了 t 灯的状态。但是,当我运行应用程序时,我看不到这种变化,程序只是绘制了 t 灯。出于这个原因,我在模拟()函数中添加了一个 std::cout 命令,以查看经过的时间如何增加。然后,我看到经过的时间增加得太快了;因此我看不到 t 灯状态的变化。

我研究了 ctime 标头以找到适合我的功能,但我找不到任何解决此问题的方法。

如何解决这个时间问题以正确模拟红绿灯?

4

1 回答 1

0

在 SFML 中有一个 sf::Clock 类可以解决您的确切问题。您可以使用 restart() 启动它,并以秒、毫秒或微秒为单位获取经过的时间。查看本教程以获取更多信息。

于 2021-02-25T05:34:38.157 回答