Example #1
0
def main():
    window = Window(width=VIEW_WINDOW_SIZE, height=VIEW_WINDOW_SIZE, caption='MindCraft', resizable=True, vsync=False)
    
    #p = Player()
    p = DeepMindPlayer()
    
    window.set_player(p)
    p.setGame(window)
    world_file = "test%d.txt" % random.randrange(10)
    generateGameWorld(world_file)
    window.model.loadMap("maps/%s" % world_file)

    opengl_setup()
    
    #pyglet.app.run()
    return window
Example #2
0
def main():
    window = Window(width=VIEW_WINDOW_SIZE,
                    height=VIEW_WINDOW_SIZE,
                    caption='MindCraft',
                    resizable=True,
                    vsync=False)

    #p = Player()
    p = DeepMindPlayer()

    window.set_player(p)
    p.setGame(window)
    world_file = "test%d.txt" % random.randrange(10)
    generateGameWorld(world_file)
    window.model.loadMap("maps/%s" % world_file)

    opengl_setup()

    #pyglet.app.run()
    return window
Example #3
0
    def reset(self):
        # Setup grayscale conversion color component scaling values
        glPixelTransferf(GL_RED_SCALE, 1)
        glPixelTransferf(GL_GREEN_SCALE, 1)
        glPixelTransferf(GL_BLUE_SCALE, 1)

        self.model = Model()
        self.world_counter = 0
        self.exclusive = False
        self.sector = None
        self.reticle = None
        self.game_over = 0
        self.player = DeepMindPlayer()
        self.player.setGame(self)
        world_file = "test%d.txt" % random.randrange(10)
        generateGameWorld(world_file)
        self.model.loadMap("maps/%s" % world_file)
        #self.set_game_frame_limit(10000) ??

        glPixelTransferf(GL_RED_SCALE, 0.299)
        glPixelTransferf(GL_GREEN_SCALE, 0.587)
        glPixelTransferf(GL_BLUE_SCALE, 0.114)
Example #4
0
 def reset(self):
     # Setup grayscale conversion color component scaling values
     glPixelTransferf(GL_RED_SCALE, 1)
     glPixelTransferf(GL_GREEN_SCALE, 1)
     glPixelTransferf(GL_BLUE_SCALE, 1)
 
     self.model = Model()
     self.world_counter = 0
     self.exclusive = False
     self.sector = None
     self.reticle = None
     self.game_over = 0
     self.player = DeepMindPlayer()
     self.player.setGame(self)
     world_file = "test%d.txt" % random.randrange(10)
     generateGameWorld(world_file)
     self.model.loadMap("maps/%s" % world_file)
     #self.set_game_frame_limit(10000) ??
     
     glPixelTransferf(GL_RED_SCALE, 0.299)
     glPixelTransferf(GL_GREEN_SCALE, 0.587)
     glPixelTransferf(GL_BLUE_SCALE, 0.114)
Example #5
0
class Window(pyglet.window.Window):

    def __init__(self, *args, **kwargs):
        super(Window, self).__init__(*args, **kwargs)

        # Whether or not the window exclusively captures the mouse.
        self.exclusive = False

        # Which sector the player is currently in.
        self.sector = None

        # The crosshairs at the center of the screen.
        self.reticle = None

        # Convenience list of num keys.
        self.num_keys = [
            key._1, key._2, key._3, key._4, key._5,
            key._6, key._7, key._8, key._9, key._0]

        # Instance of the model that handles the world.
        self.model = Model()

        # Number of ticks gone by in the world
        self.world_counter = 0

        # The label that is displayed in the top left of the canvas.
        # self.label = pyglet.text.Label('', font_name='Arial', font_size=22, bold=True,
        #     x=20, y=self.height - 10, anchor_x='left', anchor_y='top', 
        #     color=(0,0,0,255))

        # This call schedules the `update()` method to be called
        # TICKS_PER_SEC. This is the main game event loop.
        #pyglet.clock.set_fps_limit(1000)
        #pyglet.clock.schedule_interval(self.update, 1.0 / TICKS_PER_SEC)
        #pyglet.clock.schedule(self.update)

        self.current_frame = [[.76, .67],[.88, .91]]
        
        # Int flag to indicate the end of the game
        # This is set to 1 whenever the max frames are reached
        # or the player dies
        self.game_over = 0
        
    def reset(self):
        # Setup grayscale conversion color component scaling values
        glPixelTransferf(GL_RED_SCALE, 1)
        glPixelTransferf(GL_GREEN_SCALE, 1)
        glPixelTransferf(GL_BLUE_SCALE, 1)
    
        self.model = Model()
        self.world_counter = 0
        self.exclusive = False
        self.sector = None
        self.reticle = None
        self.game_over = 0
        self.player = DeepMindPlayer()
        self.player.setGame(self)
        world_file = "test%d.txt" % random.randrange(10)
        generateGameWorld(world_file)
        self.model.loadMap("maps/%s" % world_file)
        #self.set_game_frame_limit(10000) ??
        
        glPixelTransferf(GL_RED_SCALE, 0.299)
        glPixelTransferf(GL_GREEN_SCALE, 0.587)
        glPixelTransferf(GL_BLUE_SCALE, 0.114)
       

    def set_player(self, player):
        self.player = player
        
    def set_game_frame_limit(self, max_frames):
        self.max_frames = max_frames

    def set_exclusive_mouse(self, exclusive):
        """ If `exclusive` is True, the game will capture the mouse, if False
        the game will ignore the mouse.
        """
        super(Window, self).set_exclusive_mouse(exclusive)
        self.exclusive = exclusive


    def update(self, dt):
        """ This method is scheduled to be called repeatedly by the pyglet
        clock.

        Parameters
        ----------
        dt : float
            The change in time since the last call.

        """
     
        self.world_counter += 1
        if self.world_counter >= MAXIMUM_GAME_FRAMES:
            self.game_over = 1
     
        self.model.process_queue()
        sector = sectorize(self.player.position)
        if sector != self.sector:
            self.model.change_sectors(self.sector, sector)
            if self.sector is None:
                self.model.process_entire_queue()
            self.sector = sector
        m = 8
        dt = min(dt, 0.2)
        for _ in xrange(m):
            self._update(dt / m)

        PIXEL_BYTE_SIZE = 1  # Use 1 for grayscale, 4 for RGBA
        
        # Initialize an array to store the screenshot pixels
        # Add two extra bytes on the end: one for reward and one for terminal flag
        screenshot = (GLubyte * (PIXEL_BYTE_SIZE * self.width * self.height + 2))(0)
        
        # Grab a screenshot
        # Use GL_RGB for color and GL_LUMINANCE for grayscale!
        #glReadPixels(0, 0, self.width, self.height, GL_RGB, GL_UNSIGNED_BYTE, screenshot)
        glReadPixels(0, 0, self.width, self.height, GL_LUMINANCE, GL_UNSIGNED_BYTE, screenshot)
        
        # If your viewing window is larger than the size required
        # by DeepMind, then scale it down before setting the current_frame
        if VIEW_WINDOW_SIZE > SCALED_WINDOW_SIZE:
            im = Image.frombytes(mode="L", size=(VIEW_WINDOW_SIZE, VIEW_WINDOW_SIZE), data=screenshot)
            #im = Image.frombytes(mode="RGB", size=(VIEW_WINDOW_SIZE, VIEW_WINDOW_SIZE), data=screenshot)
            maxsize = (SCALED_WINDOW_SIZE, SCALED_WINDOW_SIZE)
            im.thumbnail(maxsize, Image.ANTIALIAS)
            #imdata = im.getdata()
            #self.current_frame = imdata
            
            #self.request.sendall(window.current_frame.convert("RGBA").tobytes("raw", "RGB"))

            self.current_frame = im.tobytes("raw", "L")
            print("********** USING DIFFERENT SIZE VIEW WINDOW DOESN'T CURRENTLY WORK!")
            sys.exit(1)
        else:
            self.current_frame = screenshot


    def _update(self, dt):
        """ Private implementation of the `update()` method. This is where most
        of the motion logic lives, along with gravity and collision detection.

        Parameters
        ----------
        dt : float
            The change in time since the last call.

        """
        # walking
        speed = FLYING_SPEED if self.player.flying else WALKING_SPEED
        d = dt * speed # distance covered this tick.
        dx, dy, dz = self.player.get_motion_vector()
        # New position in space, before accounting for gravity.
        dx, dy, dz = dx * d, dy * d, dz * d
        # gravity
        if not self.player.flying:
            # Update your vertical speed: if you are falling, speed up until you
            # hit terminal velocity; if you are jumping, slow down until you
            # start falling.
            self.player.dy -= dt * GRAVITY
            self.player.dy = max(self.player.dy, -TERMINAL_VELOCITY)
            dy += self.player.dy * dt
        # collisions
        x, y, z = self.player.position
        x, y, z = self.collide((x + dx, y + dy, z + dz), PLAYER_HEIGHT)
        self.player.position = (x, y, z)


    def collide(self, position, height):
        """ Checks to see if the player at the given `position` and `height`
        is colliding with any blocks in the world.

        Parameters
        ----------
        position : tuple of len 3
            The (x, y, z) position to check for collisions at.
        height : int or float
            The height of the player.

        Returns
        -------
        position : tuple of len 3
            The new position of the player taking into account collisions.

        """
        # How much overlap with a dimension of a surrounding block you need to
        # have to count as a collision. If 0, touching terrain at all counts as
        # a collision. If .49, you sink into the ground, as if walking through
        # tall grass. If >= .5, you'll fall through the ground.
        pad = 0.25
        p = list(position)
        np = normalize(position)
        for face in FACES:  # check all surrounding blocks
            for i in xrange(3):  # check each dimension independently
                if not face[i]:
                    continue
                # How much overlap you have with this dimension.
                d = (p[i] - np[i]) * face[i]
                if d < pad:
                    continue
                for dy in xrange(height):  # check each height
                    op = list(np)
                    op[1] -= dy
                    op[i] += face[i]
                    if tuple(op) not in self.model.world:
                        continue
                    p[i] -= (d - pad) * face[i]
                    if face == (0, -1, 0) or face == (0, 1, 0):
                        # You are colliding with the ground or ceiling, so stop
                        # falling / rising.
                        self.player.dy = 0
                    break
        return tuple(p)


        




    def on_key_press(self, symbol, modifiers):
        """ Called when the player presses a key. See pyglet docs for key
        mappings.

        Parameters
        ----------
        symbol : int
            Number representing the key that was pressed.
        modifiers : int
            Number representing any modifying keys that were pressed.

        """

        if symbol == key.P:
            print "SAVING WORLD!"
            self.model.saveWorld()
        elif symbol == key.ESCAPE:
            self.set_exclusive_mouse(False)
            pyglet.app.exit()


    def on_key_release(self, symbol, modifiers):
        """ Called when the player releases a key. See pyglet docs for key
        mappings.

        Parameters
        ----------
        symbol : int
            Number representing the key that was pressed.
        modifiers : int
            Number representing any modifying keys that were pressed.

        """
        pass


    def on_resize(self, width, height):
        """ Called when the window is resized to a new `width` and `height`.

        """
        # label
        #self.label.y = height - 10
        
        # reticle
        # if self.reticle:
        #     self.reticle.delete()
        # x, y = self.width / 2, self.height / 2
        # n = 10
        # self.reticle = pyglet.graphics.vertex_list(4,
        #     ('v2i', (x - n, y, x + n, y, x, y - n, x, y + n))
        # )


    def set_2d(self):
        """ Configure OpenGL to draw in 2d.

        """
        width, height = self.get_size()
        glDisable(GL_DEPTH_TEST)
        glViewport(0, 0, width, height)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(0, width, 0, height, -1, 1)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()

    def set_3d(self):
        """ Configure OpenGL to draw in 3d.

        """
        width, height = self.get_size()
        glEnable(GL_DEPTH_TEST)
        glViewport(0, 0, width, height)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(65.0, width / float(height), 0.1, 60.0)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        x, y = self.player.rotation
        glRotatef(x, 0, 1, 0)
        glRotatef(-y, math.cos(math.radians(x)), 0, math.sin(math.radians(x)))
        x, y, z = self.player.position
        glTranslatef(-x, -y, -z)

    

    def on_draw(self):
        """ Called by pyglet to draw the canvas."""
        self.clear()
        self.set_3d()
        glColor3d(1, 1, 1)
        self.model.batch.draw()
        self.draw_focused_block()
        self.set_2d()
        self.draw_labels()
        #self.draw_reticle()
        
        
    def draw_focused_block(self):
        """ Draw black edges around the block that is currently under the
        crosshairs.

        """
        vector = self.player.get_sight_vector()
        block = self.model.hit_test(self.player.position, vector)[0]
        if block:
            x, y, z = block
            vertex_data = cube_vertices(x, y, z, 0.51)
            glColor3d(0, 0, 0)
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
            pyglet.graphics.draw(24, GL_QUADS, ('v3f/static', vertex_data))
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)

    def draw_labels(self):
        """ Draw the label in the top left of the screen.

        """
        #x, y, z = self.position
        #self.label.text = '%02d (%.2f, %.2f, %.2f) %d / %d -- Current spell: %s' % (
        #    pyglet.clock.get_fps(), x, y, z,
        #    len(self.model._shown), len(self.model.world), str(self.current_spell))
        #self.label.text = 'Spell: %s' % (str(self.player.current_spell))
        #self.label.draw()

    def draw_reticle(self):
        """ Draw the crosshairs in the center of the screen.

        """
        glColor3d(0, 0, 0)
        self.reticle.draw(GL_LINES)
Example #6
0
class Window(pyglet.window.Window):
    def __init__(self, *args, **kwargs):
        super(Window, self).__init__(*args, **kwargs)

        # Whether or not the window exclusively captures the mouse.
        self.exclusive = False

        # Which sector the player is currently in.
        self.sector = None

        # The crosshairs at the center of the screen.
        self.reticle = None

        # Convenience list of num keys.
        self.num_keys = [
            key._1, key._2, key._3, key._4, key._5, key._6, key._7, key._8,
            key._9, key._0
        ]

        # Instance of the model that handles the world.
        self.model = Model()

        # Number of ticks gone by in the world
        self.world_counter = 0

        # The label that is displayed in the top left of the canvas.
        # self.label = pyglet.text.Label('', font_name='Arial', font_size=22, bold=True,
        #     x=20, y=self.height - 10, anchor_x='left', anchor_y='top',
        #     color=(0,0,0,255))

        # This call schedules the `update()` method to be called
        # TICKS_PER_SEC. This is the main game event loop.
        #pyglet.clock.set_fps_limit(1000)
        #pyglet.clock.schedule_interval(self.update, 1.0 / TICKS_PER_SEC)
        #pyglet.clock.schedule(self.update)

        self.current_frame = [[.76, .67], [.88, .91]]

        # Int flag to indicate the end of the game
        # This is set to 1 whenever the max frames are reached
        # or the player dies
        self.game_over = 0

    def reset(self):
        # Setup grayscale conversion color component scaling values
        glPixelTransferf(GL_RED_SCALE, 1)
        glPixelTransferf(GL_GREEN_SCALE, 1)
        glPixelTransferf(GL_BLUE_SCALE, 1)

        self.model = Model()
        self.world_counter = 0
        self.exclusive = False
        self.sector = None
        self.reticle = None
        self.game_over = 0
        self.player = DeepMindPlayer()
        self.player.setGame(self)
        world_file = "test%d.txt" % random.randrange(10)
        generateGameWorld(world_file)
        self.model.loadMap("maps/%s" % world_file)
        #self.set_game_frame_limit(10000) ??

        glPixelTransferf(GL_RED_SCALE, 0.299)
        glPixelTransferf(GL_GREEN_SCALE, 0.587)
        glPixelTransferf(GL_BLUE_SCALE, 0.114)

    def set_player(self, player):
        self.player = player

    def set_game_frame_limit(self, max_frames):
        self.max_frames = max_frames

    def set_exclusive_mouse(self, exclusive):
        """ If `exclusive` is True, the game will capture the mouse, if False
        the game will ignore the mouse.
        """
        super(Window, self).set_exclusive_mouse(exclusive)
        self.exclusive = exclusive

    def update(self, dt):
        """ This method is scheduled to be called repeatedly by the pyglet
        clock.

        Parameters
        ----------
        dt : float
            The change in time since the last call.

        """

        self.world_counter += 1
        if self.world_counter >= MAXIMUM_GAME_FRAMES:
            self.game_over = 1

        self.model.process_queue()
        sector = sectorize(self.player.position)
        if sector != self.sector:
            self.model.change_sectors(self.sector, sector)
            if self.sector is None:
                self.model.process_entire_queue()
            self.sector = sector
        m = 8
        dt = min(dt, 0.2)
        for _ in xrange(m):
            self._update(dt / m)

        PIXEL_BYTE_SIZE = 1  # Use 1 for grayscale, 4 for RGBA

        # Initialize an array to store the screenshot pixels
        # Add two extra bytes on the end: one for reward and one for terminal flag
        screenshot = (GLubyte *
                      (PIXEL_BYTE_SIZE * self.width * self.height + 2))(0)

        # Grab a screenshot
        # Use GL_RGB for color and GL_LUMINANCE for grayscale!
        #glReadPixels(0, 0, self.width, self.height, GL_RGB, GL_UNSIGNED_BYTE, screenshot)
        glReadPixels(0, 0, self.width, self.height, GL_LUMINANCE,
                     GL_UNSIGNED_BYTE, screenshot)

        # If your viewing window is larger than the size required
        # by DeepMind, then scale it down before setting the current_frame
        if VIEW_WINDOW_SIZE > SCALED_WINDOW_SIZE:
            im = Image.frombytes(mode="L",
                                 size=(VIEW_WINDOW_SIZE, VIEW_WINDOW_SIZE),
                                 data=screenshot)
            #im = Image.frombytes(mode="RGB", size=(VIEW_WINDOW_SIZE, VIEW_WINDOW_SIZE), data=screenshot)
            maxsize = (SCALED_WINDOW_SIZE, SCALED_WINDOW_SIZE)
            im.thumbnail(maxsize, Image.ANTIALIAS)
            #imdata = im.getdata()
            #self.current_frame = imdata

            #self.request.sendall(window.current_frame.convert("RGBA").tobytes("raw", "RGB"))

            self.current_frame = im.tobytes("raw", "L")
            print(
                "********** USING DIFFERENT SIZE VIEW WINDOW DOESN'T CURRENTLY WORK!"
            )
            sys.exit(1)
        else:
            self.current_frame = screenshot

    def _update(self, dt):
        """ Private implementation of the `update()` method. This is where most
        of the motion logic lives, along with gravity and collision detection.

        Parameters
        ----------
        dt : float
            The change in time since the last call.

        """
        # walking
        speed = FLYING_SPEED if self.player.flying else WALKING_SPEED
        d = dt * speed  # distance covered this tick.
        dx, dy, dz = self.player.get_motion_vector()
        # New position in space, before accounting for gravity.
        dx, dy, dz = dx * d, dy * d, dz * d
        # gravity
        if not self.player.flying:
            # Update your vertical speed: if you are falling, speed up until you
            # hit terminal velocity; if you are jumping, slow down until you
            # start falling.
            self.player.dy -= dt * GRAVITY
            self.player.dy = max(self.player.dy, -TERMINAL_VELOCITY)
            dy += self.player.dy * dt
        # collisions
        x, y, z = self.player.position
        x, y, z = self.collide((x + dx, y + dy, z + dz), PLAYER_HEIGHT)
        self.player.position = (x, y, z)

    def collide(self, position, height):
        """ Checks to see if the player at the given `position` and `height`
        is colliding with any blocks in the world.

        Parameters
        ----------
        position : tuple of len 3
            The (x, y, z) position to check for collisions at.
        height : int or float
            The height of the player.

        Returns
        -------
        position : tuple of len 3
            The new position of the player taking into account collisions.

        """
        # How much overlap with a dimension of a surrounding block you need to
        # have to count as a collision. If 0, touching terrain at all counts as
        # a collision. If .49, you sink into the ground, as if walking through
        # tall grass. If >= .5, you'll fall through the ground.
        pad = 0.25
        p = list(position)
        np = normalize(position)
        for face in FACES:  # check all surrounding blocks
            for i in xrange(3):  # check each dimension independently
                if not face[i]:
                    continue
                # How much overlap you have with this dimension.
                d = (p[i] - np[i]) * face[i]
                if d < pad:
                    continue
                for dy in xrange(height):  # check each height
                    op = list(np)
                    op[1] -= dy
                    op[i] += face[i]
                    if tuple(op) not in self.model.world:
                        continue
                    p[i] -= (d - pad) * face[i]
                    if face == (0, -1, 0) or face == (0, 1, 0):
                        # You are colliding with the ground or ceiling, so stop
                        # falling / rising.
                        self.player.dy = 0
                    break
        return tuple(p)

    def on_key_press(self, symbol, modifiers):
        """ Called when the player presses a key. See pyglet docs for key
        mappings.

        Parameters
        ----------
        symbol : int
            Number representing the key that was pressed.
        modifiers : int
            Number representing any modifying keys that were pressed.

        """

        if symbol == key.P:
            print "SAVING WORLD!"
            self.model.saveWorld()
        elif symbol == key.ESCAPE:
            self.set_exclusive_mouse(False)
            pyglet.app.exit()

    def on_key_release(self, symbol, modifiers):
        """ Called when the player releases a key. See pyglet docs for key
        mappings.

        Parameters
        ----------
        symbol : int
            Number representing the key that was pressed.
        modifiers : int
            Number representing any modifying keys that were pressed.

        """
        pass

    def on_resize(self, width, height):
        """ Called when the window is resized to a new `width` and `height`.

        """
        # label
        #self.label.y = height - 10

        # reticle
        # if self.reticle:
        #     self.reticle.delete()
        # x, y = self.width / 2, self.height / 2
        # n = 10
        # self.reticle = pyglet.graphics.vertex_list(4,
        #     ('v2i', (x - n, y, x + n, y, x, y - n, x, y + n))
        # )

    def set_2d(self):
        """ Configure OpenGL to draw in 2d.

        """
        width, height = self.get_size()
        glDisable(GL_DEPTH_TEST)
        glViewport(0, 0, width, height)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(0, width, 0, height, -1, 1)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()

    def set_3d(self):
        """ Configure OpenGL to draw in 3d.

        """
        width, height = self.get_size()
        glEnable(GL_DEPTH_TEST)
        glViewport(0, 0, width, height)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(65.0, width / float(height), 0.1, 60.0)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        x, y = self.player.rotation
        glRotatef(x, 0, 1, 0)
        glRotatef(-y, math.cos(math.radians(x)), 0, math.sin(math.radians(x)))
        x, y, z = self.player.position
        glTranslatef(-x, -y, -z)

    def on_draw(self):
        """ Called by pyglet to draw the canvas."""
        self.clear()
        self.set_3d()
        glColor3d(1, 1, 1)
        self.model.batch.draw()
        self.draw_focused_block()
        self.set_2d()
        self.draw_labels()
        #self.draw_reticle()

    def draw_focused_block(self):
        """ Draw black edges around the block that is currently under the
        crosshairs.

        """
        vector = self.player.get_sight_vector()
        block = self.model.hit_test(self.player.position, vector)[0]
        if block:
            x, y, z = block
            vertex_data = cube_vertices(x, y, z, 0.51)
            glColor3d(0, 0, 0)
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
            pyglet.graphics.draw(24, GL_QUADS, ('v3f/static', vertex_data))
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)

    def draw_labels(self):
        """ Draw the label in the top left of the screen.

        """
        #x, y, z = self.position
        #self.label.text = '%02d (%.2f, %.2f, %.2f) %d / %d -- Current spell: %s' % (
        #    pyglet.clock.get_fps(), x, y, z,
        #    len(self.model._shown), len(self.model.world), str(self.current_spell))
        #self.label.text = 'Spell: %s' % (str(self.player.current_spell))
        #self.label.draw()

    def draw_reticle(self):
        """ Draw the crosshairs in the center of the screen.

        """
        glColor3d(0, 0, 0)
        self.reticle.draw(GL_LINES)