I am currently working on a traffic simulator with Pygame, however i am struggling with implementing the logic of the traffic signals.

Any help is welcome.

My traffic simulation is grid based. The tiles in the grid are being drawn by looping trough a tile list.

    self.map = [['/','/','/','/','s','n','/','/','/','/'],

The characters t1, t2, t3 and t4 represent the traffic signals. In the code below i am looping trough the tile map.

def load_tiles(self):
    self.tiles = pygame.sprite.Group()
    self.trafficsignals = pygame.sprite.Group()
    type = ['c', 'n', 'w', 's', 'o']
    tsType = ['t1', 't2', 't3', 't4']

    x, y = 0, 0
    # iterate through the tile map list
    for row in self.map:
        x = 0
        for tile in row:
            if tile == '/':
                self.tiles.add(Tile((200, 200, 200), x * self.tile_size, y * self.tile_size, self.tile_size))
            elif tile in type: # add road tiles to tile sprite group
                self.tiles.add(Tile((100, 100, 100), x * self.tile_size, y * self.tile_size, self.tile_size))
            elif tile in tsType: # add trafficsignals to trafficsignal sprite group
                self.tiles.add(Tile((200, 200, 200), x * self.tile_size, y * self.tile_size, self.tile_size))
                self.trafficsignals.add(ts( x * self.tile_size, y * self.tile_size, tile, self.trafficsignals, self.screen))
            # Move to next tile in current row
            x += 1
        # Move to next row
        y += 1

This function is being called once in the init function of my main class since the tiles only need to be drawn once, however i am not sure if this is the right approach since the traffic signals are supposed to change color. after drawing the sprite groups to my screen the image below is the result i get.

enter image description here

The black bars are where my traffic signals are supposed to go. These traffic signals are objects made using a separate class.

class Trafficsignal(pygame.sprite.Sprite):
    def __init__(self,  x, y, tile, signals, screen):

        self.screen = screen

        self.red = pygame.image.load('images/signals/red.png').convert_alpha
        self.yellow = pygame.image.load('images/signals/yellow.png').convert_alpha
        self.green = pygame.image.load('images/signals/green.png').convert_alpha

        self.noOfSignals = signals # number of traffic signals
        self.currentRed = 0        # Indicates which signal is red currently
        self.currentYellow = 0     # Indicates which signal is yellow currently
        self.currentGreen = 0      # Indicates which signal is green currently

        self.redTime = 100
        self.yellowTime = 5
        self.greenTime = 20

        self.image = pygame.Surface([15, 42])
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y

        # rotate trafficsignal bar to corresponding angle
        if tile == 't1':
           self.image = pygame.transform.rotate(self.image, 180)
        if tile == 't2':
           self.image = pygame.transform.rotate(self.image, 90)
        if tile == 't3':
           self.image = pygame.transform.rotate(self.image, -90)

def update(self):

I am currently stuck on the logic of how a traffic signal changes color. I want the traffic signals to change color in a clockwise direction. Only one traffic signal is allowed to be green. I already made some variables like currentGreen to determine which color a traffic signal currently is, but i am not really sure on how to implement this logic since i'm still pretty new to game development.


1 Answer 1


You can use an array like this: [2, 1, 1, 0] and each number represents a color (in this example: 0 for red, 1 for yellow, 2 for green) and then increase all of the numbers every time you want the color to change (say, every turn or every 10 seconds), just remember to add a %3 so the numbers won't get more than 2.

Only one traffic signal is allowed to be green.

Well, I don't see how this can happens since you have more than three traffic signals. If you look at my example, you will get two green lights in the next turn.

  • \$\begingroup\$ Could you not increment your index into the array instead of incrementing the output? So [i] -> [2, 1, 0, 0] becomes [(i+1) % 4] -> [1, 0, 0, 2]? This is a bit like a barrel shift, rotating the access to the array. \$\endgroup\$
    – DMGregory
    Commented Apr 30, 2022 at 11:53
  • \$\begingroup\$ I'm not sure if I understood what you said, but doesn't the second light remains the same in your example? \$\endgroup\$
    – Arian_ki
    Commented Apr 30, 2022 at 14:20
  • \$\begingroup\$ In that case you can just make two red lights, so the light stays red longer, but a yellow light always lasts just one turn. I've shown that above. \$\endgroup\$
    – DMGregory
    Commented Apr 30, 2022 at 14:22
  • \$\begingroup\$ Thanks for editing your comment, it's more clear now. That's a good approach too. (called 'barrel shift' I presume?) Is it more efficient? \$\endgroup\$
    – Arian_ki
    Commented Apr 30, 2022 at 15:53
  • 1
    \$\begingroup\$ Efficiency isn't really a consideration when you're dealing with a list of 4 items. The main memory latency to pull that list into cache is greater than any cost of any operations we perform on it. The question here is correctness. If you're trying to obey the rule "only one signal is allowed to be green", then the barrel shift / ring buffer approach obeys that rule, while adding one the the output and taking the remainder does not. \$\endgroup\$
    – DMGregory
    Commented Apr 30, 2022 at 16:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .