示例#1
0
文件: moin.py 项目: TUM-FAF/SatKit
class App(Tk):
    def __init__(self, ftimer):
        Tk.__init__(self)
          
        self.sats = Track()
        self.sats.load_local("data.txt")    # to be changed
        self.sats.add_satellite(7)          # achtung, hardcode
        
        menu = UserMenu(parent = self)
        self.config(menu = menu)
        self.title('SatKit Ground Tracking')

        self.timer = ftimer
        self.timer.callback_function = self.redraw
        self.time_speed = 1                 # normal speed
        
        self.var = IntVar()
        self.scale = Scale(self, variable = self.var, from_ = 1, to = 3600, 
                           orient = HORIZONTAL, showvalue=0, sliderlength=15,
                           length=400, command=self.set_time_speed)
        self.date = Label(self)
    def redraw(self):
        
        self.timer.set_speed(self.time_speed) # bad, should be improven,~event
        self.sats.update_satellites(self.time_speed * Time.TIMER_INTERVAL)
        #print self.time_speed 
        # recompute "current" time, later,,,
        self.date.config(text = str(self.timer.current_time)[0:21])
        self.date.grid(row = 0, column = 1)
        self.scale.grid(row = 0, column = 0)
        self.sats.anim.grid(row = 1, columnspan = 2)
        self.sats.draw() 

    def set_time_speed(self, secs):
        self.time_speed = int(secs)
示例#2
0
                paused = True
                while paused:
                    for event in pygame.event.get():
                        if event.type == pygame.KEYDOWN:
                            if event.key == pygame.K_p:
                                paused = False
                    clock.tick(constants.FRAME_RATE)  # fps

    # update game status and handle game logic
    car_list.update(track, frame_counter)
    particles.update(frame_counter)
    bayes.update(frame_counter)
    status_bar.update(frame_counter)

    # update draw buffer
    track.draw(screen)
    sprite_list.draw(screen)
    if draw_viewfield:
        for car in car_list:
            car.driver.draw_viewfield(screen)

    # draw particles
    particles.draw(screen)
    bayes.draw(screen)

    # update screen
    clock.tick(constants.FRAME_RATE)  # fps
    frame_counter += 1
    pygame.display.flip()

示例#3
0
class SpaceRacer():
    """Represents the game itself"""
    def __init__(self):
        """Creates all game objects needed, loads resources, initializes
        pygame library and sound mixer, sets display mode, etc."""
        self.state = STATE_TITLE
        pygame.mixer.pre_init(buffer=SOUND_BUFFER)
        pygame.init()
        self.clock = Clock()
        self.scr = pygame.display.set_mode(SCREEN_SIZE, VID_MODE_FLAGS)
        pygame.display.set_caption(WINDOW_CAPTION)
        pygame.mouse.set_visible(False)
        LoadingScreen(self.scr).draw()
        sound_box.init()

        self.level = GameLevel()
        self.stats = GameStats(self.scr)
        self.view_pt = ViewPoint(self.scr)
        self.stars = Stars(self.scr, self.view_pt)
        self.track = Track(self.scr, self.view_pt)
        self.explosions = Explosions(self.scr, self.view_pt)
        self.ship = Ship(self.scr, self.view_pt, self.explosions)
        self.asteroids = Asteroids(self.scr, self.view_pt, self.explosions,
                                   self.track)
        self.title_screen = TitleScreen(self.scr, self.view_pt, self.stars)
        self.level_start_screen = LevelStartScreen(self.scr)
        self.level_complete_effect = LevelCompleteEffect(self.scr)
        self.game_over_effect = GameOverEffect(self.scr)
        self.pause_screen = PauseScreen(self.scr)
        self.ending_screen = EndingScreen(self.scr)

        self._init_title()

    def run(self):
        """The only public method just runs the game. It starts infinite
        loop where game objects are updated, drawn and interacts with
        each other. Also system events are processed."""
        while True:
            self.clock.tick(FRAMERATE)
            # print(f"FPS: {round(self.clock.get_fps(), 2)}")
            self._process_events()
            self._update_objects()
            self._interact_objects()
            self._draw_objects()

    def _init_title(self):
        self.state = STATE_TITLE
        self.stats.reset()
        self.level.restart()
        self.title_screen.restart()
        self.title_screen.play_music()

    def _init_level_starting(self):
        self.state = STATE_LEVEL_STARTING
        self.level_start_screen.set_level_number(self.level.get_level())
        self.level_start_screen.set_subtitle_text(self.level.get_description())
        self.level_start_screen.restart()

    def _init_level_playing(self):
        self.state = STATE_LEVEL_PLAYING
        self.level.play_music()
        self.view_pt.reset()
        self.stars.respawn()
        self.track.set_tile_map(self.level.get_map())

        top_limit = (self.track.get_track_height() -
                     self.scr.get_rect().height / 2)
        bottom_limit = self.scr.get_rect().height / 2
        self.view_pt.set_limits(top=top_limit, bottom=bottom_limit)

        self.explosions.items.empty()
        self.asteroids.set_spawn_density(self.level.get_asteroids_density())
        self.asteroids.respawn(self.level.get_asteroid_spawns())

        self.ship.set_speed(self.level.get_ship_speed())
        self.ship.set_acceleration(self.level.get_ship_acceleration())
        self.ship.restore((0, 0), reset_control=True)

    def _init_level_finishing(self):
        self.state = STATE_LEVEL_FINISHING
        self.stats.increase_score(LEVEL_COMPLETE_PTS)
        self.level_complete_effect.restart()
        self.ship.set_autopilot()
        pygame.mixer.music.fadeout(MUSIC_FADEOUT)

    def _init_game_over(self):
        self.state = STATE_GAME_OVER
        self.game_over_effect.restart()
        pygame.mixer.music.fadeout(MUSIC_FADEOUT)

    def _init_ending(self):
        self.state = STATE_ENDING
        self.ending_screen.set_score(self.stats.score)
        self.ending_screen.restart()
        self.ending_screen.play_music()

    def _init_pause(self):
        self.state = STATE_PAUSE
        self.pause_screen.refresh_background()
        pygame.mixer.music.pause()

    def _ship_control(self, key, control_status):
        """Returns True if the key was a ship direction control key."""
        key_processed = True

        if key == pygame.K_UP:
            self.ship.moving_up = control_status
        elif key == pygame.K_DOWN:
            self.ship.moving_down = control_status
        elif key == pygame.K_LEFT:
            self.ship.moving_left = control_status
        elif key == pygame.K_RIGHT:
            self.ship.moving_right = control_status
        elif key == pygame.K_SPACE:
            self.ship.shooting = control_status
        else:
            key_processed = False

        return key_processed

    def _process_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

            if self.state == STATE_TITLE:
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_ESCAPE:
                        sys.exit()
                    elif event.key == pygame.K_RETURN:
                        pygame.mixer.music.fadeout(MUSIC_FADEOUT)
                        self._init_level_starting()

            elif self.state == STATE_PAUSE:
                if event.type == pygame.KEYDOWN:
                    if event.key in (pygame.K_ESCAPE, pygame.K_PAUSE):
                        self.state = STATE_LEVEL_PLAYING
                        pygame.mixer.music.unpause()
                    elif event.key == pygame.K_RETURN:
                        sys.exit()

            elif self.state == STATE_LEVEL_PLAYING:
                if event.type == pygame.KEYDOWN:
                    if event.key in (pygame.K_ESCAPE, pygame.K_PAUSE):
                        self._init_pause()
                    else:
                        self._ship_control(event.key, control_status=True)
                elif event.type == pygame.KEYUP:
                    self._ship_control(event.key, control_status=False)

            if self.state == STATE_ENDING:
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_ESCAPE:
                        sys.exit()
                    elif event.key == pygame.K_RETURN:
                        self._init_title()

    def _update_objects(self):
        if self.state == STATE_TITLE:
            self.title_screen.update()

        if self.state == STATE_LEVEL_STARTING:
            self.level_start_screen.update()

        if self.state in (STATE_LEVEL_PLAYING, STATE_LEVEL_FINISHING,
                          STATE_GAME_OVER):
            self.view_pt.update()
            self.stars.update()
            self.track.update()
            self.asteroids.update()
            self.ship.update()
            self.explosions.update()

        if self.state == STATE_LEVEL_FINISHING:
            self.level_complete_effect.update()

        if self.state == STATE_GAME_OVER:
            self.game_over_effect.update()

        if self.state == STATE_ENDING:
            self.ending_screen.update()

    def _crossed_finish_line(self):
        finish_line_y = (self.track.get_track_height() -
                         self.scr.get_rect().height / 2)
        return self.ship.y > finish_line_y

    def _interact_objects(self):
        if self.state == STATE_LEVEL_STARTING:
            if self.level_start_screen.finished():
                self._init_level_playing()

        elif self.state == STATE_LEVEL_PLAYING:
            if self.stats.game_over():
                self._init_game_over()
            elif self._crossed_finish_line():
                self._init_level_finishing()
            elif self.ship.status == SHIP_STATUS_NORMAL:
                self._check_collisions()
            elif self.ship.status == SHIP_STATUS_INACTIVE:
                self._ship_restore()

        elif self.state == STATE_LEVEL_FINISHING:
            if self.level_complete_effect.finished():
                if self.level.last_level():
                    self._init_ending()
                else:
                    self.level.next_level()
                    self._init_level_starting()

        elif self.state == STATE_GAME_OVER:
            if self.game_over_effect.finished():
                self._init_title()

    def _draw_objects(self):
        if self.state == STATE_TITLE:
            self.title_screen.draw()

        if self.state == STATE_PAUSE:
            self.pause_screen.draw()

        if self.state == STATE_LEVEL_STARTING:
            self.level_start_screen.draw()

        if self.state in (STATE_LEVEL_PLAYING, STATE_LEVEL_FINISHING,
                          STATE_GAME_OVER):

            self.scr.blit(self.level.get_background(), (0, 0))
            self.stars.draw()
            self.track.draw()
            self.asteroids.draw()
            self.ship.draw()
            self.explosions.draw()
            self.stats.draw()

        if self.state == STATE_LEVEL_FINISHING:
            self.level_complete_effect.draw()

        if self.state == STATE_GAME_OVER:
            self.game_over_effect.draw()

        if self.state == STATE_ENDING:
            self.ending_screen.draw()

        pygame.display.flip()

    def _ship_explode(self, collide_point=None):
        """collide_point is a tuple of absolute coordinates: (x, y)"""
        self.stats.lost_life()
        self.ship.explode(collide_point)

    def _ship_restore(self):
        restore_x, restore_y = self.ship.get_center()
        borders = self.track.get_track_borders(restore_y)
        if borders:
            restore_x = mean(borders)
        if self.ship.restore((restore_x, restore_y)):
            self.asteroids.explode_nearest(self.ship.get_center())

    def _check_ship_penalty(self):
        borders = self.track.get_track_borders(self.ship.get_center()[1])
        if borders:
            left = self.ship.x
            right = left + self.ship.rect.width
            if right < borders[0] or left > borders[1]:
                self._ship_explode()
                return True
        return False

    def _check_collisions(self):
        collide_point = self.track.collidemask(self.ship.mask, self.ship.rect)
        if collide_point:
            self._ship_explode(collide_point)
            return True

        collide_point = self.asteroids.collidemask(self.ship.mask,
                                                   self.ship.rect,
                                                   explode=True)
        if collide_point:
            self._ship_explode(collide_point)
            return True

        if self.ship.laser.shooting():
            if self.asteroids.collidemask(self.ship.laser.mask,
                                          self.ship.laser.rect,
                                          explode=True):
                self.stats.increase_score(ASTEROID_HIT_PTS)

        return self._check_ship_penalty()
示例#4
0
class Simulator(pyglet.window.Window):
    def __init__(self,
                 *args,
                 settings=None,
                 carnum=10,
                 width=960,
                 height=540,
                 vsync=True,
                 **kwargs):
        config = pyglet.gl.Config(sample_buffers=1,
                                  samples=1,
                                  depth_size=16,
                                  double_buffer=True)
        super().__init__(width=width,
                         height=height,
                         config=config,
                         resizable=True,
                         vsync=vsync)
        self.keystate = key.KeyStateHandler()
        self.push_handlers(self.keystate)

        self.settings = defaultdict(bool)
        if type(settings) == dict:
            self.settings.update(settings)

        self.init_speed = self.settings['speed'] if type(
            self.settings['speed']) == int else 25
        self.carnum = (carnum + 1) // 2 * 2  # need even number
        self.carnum = carnum
        self.cars = []
        self.car = Car(
            sensors=self.settings['sensors'],
            human=True)  # will be deleted later if simulation starts
        self.carline_colours = tuple()
        self.track = Track()
        self.car.put_on_track(self.track)
        self.generation = 0
        self.cars_pos_vbo = VertexBufferObject(self.carnum * 64,
                                               GL_ARRAY_BUFFER,
                                               GL_DYNAMIC_DRAW)
        self.cars_col_vbo = VertexBufferObject(self.carnum * 96,
                                               GL_ARRAY_BUFFER, GL_STATIC_DRAW)

        self.time = 0
        self.fps = pyglet.clock.ClockDisplay()
        self.times = defaultdict(list)
        self.counter = 0

        self.setup_labels()

        self.x = 0
        self.y = 0
        self.scale = 1

        pyglet.clock.schedule_interval(self.update, 1.0 / 60)

    def setup_labels(self):
        self.main_label = pyglet.text.Label(text="", x=10, y=self.height - 20)
        self.maintimes_label = pyglet.text.Label(text="",
                                                 x=10,
                                                 y=self.height - 40,
                                                 font_name="Lucida Console",
                                                 font_size=10)
        self.cartimes_label = pyglet.text.Label(text="",
                                                x=10,
                                                y=self.height - 60,
                                                font_name="Lucida Console",
                                                font_size=10)

    def start(self, makecars=False):
        if makecars:
            self.cars = [
                Car(sensors=self.settings['sensors'])
                for i in range(self.carnum)
            ]
            self.carline_colours = sum((car.line_colours for car in self.cars),
                                       ())
            self.cars_col_vbo.set_data(Vec(*self.carline_colours))
        self.car = self.cars[0]
        for car in self.cars:
            car.put_on_track(self.track)
            car.accelerate(self.init_speed)

    def evolve(self):
        self.generation += 1
        for car in self.cars[1:]:
            car.driver.learn_from(self.cars[0].driver)
            car.driver.randomize()
        return
        #self.maintimes_label.text = "Generation: %d" % self.generation
        cars = sorted(self.cars,
                      key=operator.attrgetter('section_idx', 'time'),
                      reverse=True)
        if cars[1:2] and cars[1].section_idx < 1:
            #print("Don't have at least two good specimen, randomizing")
            [car.driver.randomize() for car in self.cars]
            return
            pass
        best = cars[0].driver
        runnerup = cars[1].driver
        to_mutate = (self.carnum - 2) // 2
        #print("best section: %d, runnerup section: %d" % (best.section_idx, runnerup.section_idx))
        # something's wrong here, need to rethink
        for i, pair in enumerate(zip(self.cars[2::2], self.cars[3::2])):
            severity = 0.25 * i / to_mutate
            chance = 1 - i / to_mutate
            pair[0].driver.learn_from(best,
                                      mutate=i,
                                      chance=chance,
                                      severity=severity)
            pair[1].driver.learn_from(runnerup,
                                      mutate=i,
                                      chance=chance,
                                      severity=severity)
        #print("cars[0] == best: %s" % (self.cars[0].driver.network.layers[1].neurons[0].weights == best.driver.network.layers[1].neurons[0].weights))
        #print("cars[0] %d, best: %d" % (id(self.cars[0].driver.network.layers[1].neurons[0].weights), id(best.driver.network.layers[1].neurons[0].weights)))
        #print("copied and mutated!")

    def set_avg_time(self, cat, time, limit=10):
        self.times[cat].append(time)
        if len(self.times[cat]) > limit:
            self.times[cat].pop(0)

    def get_avg_time(self, cat):
        if len(self.times[cat]):
            return sum(self.times[cat]) / len(self.times[cat])
        else:
            return 0

    def set_and_get_avg_time(self, cat, time, limit=10):
        self.set_avg_time(cat, time, limit)
        return self.get_avg_time(cat)

    def update(self, dt):
        dt = min(
            dt, 1 / 30
        )  # slow down time instead of "dropping" frames and having quick jumps in space
        #dt = 1/40
        self.time += dt
        self.main_label.text = "Time: %.3f. Generation: %d" % (self.time,
                                                               self.generation)
        for key in self.keystate:
            if self.keystate[key]:
                self.dispatch_event('on_key_press', key, False)
        t1 = time.time()
        if len(self.cars):
            for car in self.cars:
                car.update(dt)
            if all(car.collided for car in self.cars):
                self.evolve()
                self.start()
                return
            s = [car for car in self.cars if not car.collided]
            leader = sorted(s, key=operator.attrgetter('section_idx'))[-1]
            #leader = sorted(self.cars, key=operator.attrgetter('section_idx'))[-1]
            if self.car.section_idx < leader.section_idx:
                self.car = leader
        else:
            self.car.update(dt)
        t2 = time.time()
        if not self.settings['nofollow']:
            self.x = self.car.x
            self.y = self.car.y
        self.draw()
        t3 = time.time()
        if self.settings['timings'] or self.settings['manual']:
            drawtime = 1000 * self.set_and_get_avg_time('draw', t3 - t2)
            cardraw = 1000 * self.get_avg_time('cardraw')
            coords = 1000 * self.get_avg_time('lines')
            drawcall = 1000 * self.get_avg_time('drawcall')
            updatetime = 1000 * self.set_and_get_avg_time('update', t2 - t1)
            sensors = 1000 * self.get_avg_time('sensors')
            extra = 1000 * self.get_avg_time('extra')
            percar = 1000 * updatetime
            if not self.settings['manual']:
                #percar /= sum(not car.collided for car in self.cars)
                percar /= len(self.cars)
                cardrawdetail = "(cars=%.2fms:coords:%.2fms,draw=%.2fms)" % (
                    cardraw, coords, drawcall)
            else:
                cardrawdetail = ""
            self.maintimes_label.text = "dt=%2dms,draw=%2dms%s,upd=%04.1fms(%.2fus/car)" % (
                1000 * dt, drawtime, cardrawdetail, updatetime, percar)

    def setup2d_init(self):
        glClear(GL_COLOR_BUFFER_BIT)
        #glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Vec(0,0,0,1))
        glColor3ub(255, 255, 255)
        glViewport(0, 0, self.width, self.height)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluOrtho2D(0, self.width, 0, self.height)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()

    def setup2d_camera(self):
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluOrtho2D(self.scale * -self.width / 2 + self.x,
                   self.scale * self.width / 2 + self.x,
                   self.scale * -self.height / 2 + self.y,
                   self.scale * self.height / 2 + self.y)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()

    def draw(self):
        self.clear()
        self.setup2d_init()

        self.fps.draw()
        self.draw_labels()

        self.setup2d_camera()
        self.track.draw()
        t1 = time.time()
        self.draw_cars()
        t2 = time.time()
        self.set_avg_time('cardraw', t2 - t1)

    def draw_cars(self):
        glLoadIdentity()
        t1 = time.time()
        if len(self.cars):
            if cmodule:
                pos = ((car.x, car.y, car.rot) for car in self.cars)
                self.coords = cmodule.car_lines(pos, self.carnum)
            else:
                coords = sum((car.linecoords for car in self.cars), ())
                self._coords = np.array(
                    coords, dtype=GLfloat)  # must keep the array ref in python
                self.coords = self._coords.ctypes.data
                #self.coords = Vec(*coords)

            t2 = time.time()

            self.cars_col_vbo.bind()
            glColorPointer(3, GL_FLOAT, 0, self.cars_col_vbo.ptr)
            self.cars_pos_vbo.set_data(self.coords)
            self.cars_pos_vbo.bind()
            glVertexPointer(2, GL_FLOAT, 0, self.cars_pos_vbo.ptr)
            glEnableClientState(GL_VERTEX_ARRAY)
            glEnableClientState(GL_COLOR_ARRAY)
            glDrawArrays(GL_LINES, 0, self.carnum * 16)
            glDisableClientState(GL_COLOR_ARRAY)
            glDisableClientState(GL_VERTEX_ARRAY)
            self.cars_col_vbo.unbind()
            self.cars_pos_vbo.unbind()
        else:
            t2 = time.time()
            self.car.draw()
        t3 = time.time()
        if self.settings['manual']:
            self.car.draw_section()
            self.car.draw_points()
        t4 = time.time()
        if self.settings['cameras']:
            self.car.draw_sensors()
        t5 = time.time()
        self.set_avg_time('lines', t2 - t1)
        self.set_avg_time('drawcall', t3 - t2)
        self.set_avg_time('extra', t4 - t3)
        self.set_avg_time('sensors', t5 - t4)

    def draw_labels(self):
        self.main_label.draw()
        self.maintimes_label.draw()

    def on_key_press(self, symbol, modifier):
        if symbol == key.ESCAPE:
            self.close()
        elif symbol == key.LEFT:
            self.car.steering = -math.pi / 4
        elif symbol == key.RIGHT:
            self.car.steering = math.pi / 4
        elif symbol == key.UP:
            self.car.accelerate(2)
        elif symbol == key.DOWN:
            self.car.accelerate(-2)
        elif symbol == key.SPACE:
            if self.car.speed >= 0:
                self.car.speed = max(0, self.car.speed - 8)
            else:
                self.car.speed = min(0, self.car.speed + 8)
        elif symbol == key.W:
            self.y += 10
        elif symbol == key.S:
            self.y -= 10
        elif symbol == key.A:
            self.x -= 10
        elif symbol == key.D:
            self.x += 10
        elif symbol == key.E:
            if self.scale > 0.2:
                self.scale -= 0.1
        elif symbol == key.Q:
            if self.scale < 3:
                self.scale += 0.1
        elif symbol == key.C:
            self.car.check_collision()
            self.keystate[symbol] = False
        elif symbol == key.R:
            if len(self.cars):
                self.start()
                return
            self.car.put_on_track(self.track)
        elif symbol == key.N:
            self.car.change_section(self.car.section_idx + 1)
            self.keystate[symbol] = False
        elif symbol == key.P:
            self.car.change_section(self.car.section_idx - 1)
            self.keystate[symbol] = False

    def on_key_release(self, symbol, modifier):
        if symbol in [key.LEFT, key.RIGHT]:
            self.car.steering = 0
示例#5
0
def main():
    """ Main function """
    # Load
    pygame.init()
    path = os.path.abspath('.') + '/'
    screen = pygame.display.set_mode((800, 600))
    font = pygame.font.Font(path + "arial.ttf", 24)
    quit_game = False

    key_up = False
    key_down = False
    key_left = False
    key_right = False
    key_z = False
    key_q = False
    key_s = False
    key_d = False

    car = Car(60, 300, path + "images/car.png")
    car2 = Car(500, 300, path + "images/car-alt.png")
    track = Track()

    dt = 60 / 1000
    clock = pygame.time.Clock()
    while not quit_game:
        # Inputs
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                quit_game = True

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    quit_game = True
                if event.key == pygame.K_UP:
                    key_up = True
                if event.key == pygame.K_DOWN:
                    key_down = True
                if event.key == pygame.K_LEFT:
                    key_left = True
                if event.key == pygame.K_RIGHT:
                    key_right = True
                if event.key == pygame.K_w:
                    key_z = True
                if event.key == pygame.K_a:
                    key_q = True
                if event.key == pygame.K_s:
                    key_s = True
                if event.key == pygame.K_d:
                    key_d = True
            
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_UP:
                    key_up = False
                if event.key == pygame.K_DOWN:
                    key_down = False
                if event.key == pygame.K_LEFT:
                    key_left = False
                if event.key == pygame.K_RIGHT:
                    key_right = False
                if event.key == pygame.K_w:
                    key_z = False
                if event.key == pygame.K_a:
                    key_q = False
                if event.key == pygame.K_s:
                    key_s = False
                if event.key == pygame.K_d:
                    key_d = False

        # Update
        # - Player 1
        if key_up:
            car.accelerate()
        if key_left:
            car.turn_left(dt)
        if key_right:
            car.turn_right(dt)
            
        car.update(dt)

        # - Player 2
        if key_z:
            car2.accelerate()
        if key_q:
            car2.turn_left(dt)
        if key_d:
            car2.turn_right(dt)
            
        car2.update(dt)

        # Draw
        screen.fill((0, 0, 0))

        track.draw(screen)
        car.draw(screen)
        car2.draw(screen)

        pygame.display.update()
        dt = clock.tick(60) / 1000