In my traffic simulation project, I want to change the states(color of lights) of the traffic light objects in a period. I wrote TrafficLightGroup class to group 7 traffic lights (t-lights) into 3 groups. In this class, there is a simulate() function which adds t-light to the groups and change their states in a period. Here is the TrafficLightGroup class:
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;
}
}
};
If you also want to look at the TrafficLight class, I added here:
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);
}
}
};
This is the main() function:
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);
I want to simulate t-lights with 10 second period. In simulate() function, I changed the states of t-lights at some specific time. However, I cannot see this change when I run the app, the program just draws the t-lights. For this reason, I added a std::cout command in simulate() function to see how elapsed time increase. Then, I saw that the elapsed time increases too fast; hence I cannot see the change in the states of t-lights.
I researched ctime header to find a function suitable for me, but I could not find anything for this issue.
How can I solve this time issue to simulate traffic lights correctly?