Beispiel #1
0
 def update(self):
     self.image = self.bkground.copy()
     fuel_msg = 'FUEL: %s (%s)' % (str(U.rint(self.plane.fuel)).zfill(3),
                 str(U.rint(self.plane.fuel_delta)).zfill(3))
     color = S.DARK_GREEN if self.plane.fuel > 100 else S.KO_COLOUR
     img = self.render_text('small', color, fuel_msg)
     self.image.blit(img, self.fuel_data_position)
     self.rect.y += cmp(self.target_y, self.rect.y) * \
                    min(3, abs(self.rect.y - self.target_y))
     # Master alarm
     if self.plane.flags.collision or self.plane.tcas.state \
                                   or not self.plane.fuel:
         img = self.master_alarm_on
     else:
         img = self.master_alarm_off
     self.image.blit(img, self.master_alarm_position)
     # Expedite arrow
     if self.plane.pilot.status['haste'] in ('expedite', 'emergency'):
         img = self.expedite_on
     else:
         img = self.expedite_off
     self.image.blit(img, self.expedite_position)
     # Drop
     if self.plane.fuel_delta > 0:
         img = self.drop_green
     elif self.plane.fuel:
         img = self.drop_yellow
     else:
         img = self.drop_red
     self.image.blit(img, self.drop_position)
     # Last order
     text = self.plane.pilot.order_being_processed
     if text:
         text = self.render_text('small', S.GRAY, text)
         self.image.blit(text, self.order_being_processed_position)
Beispiel #2
0
 def testRint(self):
     '''
     rint - round to integer and typecast to int
     '''
     self.assertEqual(U.rint(0.35), 0)
     self.assertEqual(U.rint(0.835), 1)
     self.assertIsInstance(U.rint(3465657.4545), int)
Beispiel #3
0
 def place(self):
     '''
     Place the tag according to the angle and radius properties. Return True
     if the tag is entirely on radar, False otherwise.
     '''
     cx, cy = self.plane.trail[0]
     rad = radians(self.angle)
     ox = U.rint(cos(rad) * self.radius)
     oy = -U.rint(sin(rad) * self.radius)  #minus because of screen coordinates
     x, y = cx + ox, cy + oy
     self.rect = U.get_rect_at_centered_pos(self.image, (x, y))
     return self.radar_rect.contains(self.rect)
Beispiel #4
0
 def __generate_flight_plan(self):
     '''
     Return intial position and velocity 3D vectors plus the origin and
     destination identifiers (airport or gate) for a plane. It also returns
     the initial amount of onboard fuel and the fuel_efficiency values.
     '''
     #TODO: foresee port to port and gate to gate
     #TODO: foresee a configurable ratio between ports and air
     #FIXME: consider passing gate and airport objects directly as orig/dest
     # Establish type of origin
     if self.__check_grounded_is_ok():
         options = ['gates', 'airports']
         random.shuffle(options)
         type_ = options.pop()
     else:
         type_ = 'gates'
     if type_ == 'gates':
         entry_data_gates = self.__entry_data['gates'][:]
         random.shuffle(entry_data_gates)
         # Attempt to make planes enter the aerospace without making them
         # collide with each other
         while entry_data_gates:
             orig, pos, vel, levels = entry_data_gates.pop()
             levels = levels[:]
             while levels:
                 # Prevent in-place modification on __entry_data
                 pos = pos.copy()
                 pos.z = levels.pop()
                 if not self.gamelogic.aerospace.check_proximity(pos):
                     vel = vel.copy()
                     tmp = random.choice(self.scenario.airports)
                     dest = tmp.iata
                     fuel = U.rint(U.ground_distance(pos, tmp.location)*
                                 4*self.fuel_per_metre)
                     return dict(origin=orig, position=pos, velocity=vel,
                                 destination=dest, fuel=fuel,
                                 fuel_efficiency=self.fuel_per_metre)
     elif type_ == 'airports':
         random.shuffle(self.__entry_data['airports'])
         orig, pos, vel = self.__entry_data['airports'][0]
         pos = pos.copy()
         vel = vel.copy()
         tmp = random.choice(self.scenario.gates)
         dest = tmp.name
         fuel = U.rint(U.ground_distance(pos, Vector3(*tmp.location))*
                             4*self.fuel_per_metre)
         return dict(origin=orig, position=pos, velocity=vel,
                     destination=dest, fuel=fuel,
                     fuel_efficiency=self.fuel_per_metre)
     return False
Beispiel #5
0
 def check(self, commands):
     """
     Check if the requested commands can be performed or not. Return True or
     an error message. ``commands`` is a dictionary in the form:
     {command_name = (args, flags)}. Return True or a message error.
     """
     pi = self.pilot
     pl = self.plane
     aspace = self.plane.aerospace
     cnames = set(commands.keys())
     # Reject orders if imminent collision
     if pl.tcas.state == True:
         return "Mayday, mayday!!!"
     # Reject orders other than SQUAWK if plane is locked
     if pl.flags.locked and cnames - set("SQUAWK"):
         return "You can only SQUAWK this plane."
     # Reject orders if busy
     if pl.flags.busy == True and cnames - set(["ABORT", "SQUAWK"]):
         return "We are still performing the previous command."
     # Reject orders other than TAKEOFF or SQUAWK if plane is on ground
     if pl.flags.on_ground and not ("TAKEOFF" in cnames or cnames == set(["SQUAWK"])):
         return "We should probably TAKEOFF first, uh?"
     # Reject orders if they contain an altitude beyond max_altitude
     if "ALTITUDE" in cnames and commands["ALTITUDE"][0][0] > pl.max_altitude:
         return "The target altitude is above the maximum one for our " + "aircraft."
     # Reject orders if they contain a speed out of speed limits (min/max)
     if "SPEED" in cnames and not self.plane.min_speed <= commands["SPEED"][0][0] <= self.plane.max_speed:
         mi = U.rint(self.plane.min_speed * 3.6)
         ma = U.rint(self.plane.max_speed * 3.6)
         return "Our speed must be between %d and %d kph!" % (mi, ma)
     # Reject LAND order if unexisting airport or runway
     if "LAND" in cnames:
         check = pi.navigator.check_existing_runway(*commands["LAND"][0])
         if check != True:
             return check
     # Reject TAKEOFF if one of the various no-go conditions is true
     if "TAKEOFF" in cnames:
         args, flags = commands["TAKEOFF"]
         if not pl.flags.on_ground:
             return "We can't take off if we are already airborne!"
         port = aspace.airports[pl.origin]
         if args[0] not in port.runways.keys():
             return "Uh? What runway did you say we should taxi to?"
         runway = port.runways[args[0]]
         twin = port.runways[runway["twin"]]
         if not aspace.runways_manager.check_runway_free(port, twin):
             return "Negative, that runway is currently in use."
     # If nothing else have stopped us...
     return True
Beispiel #6
0
 def draw(self, surface):
     '''
     Blit self on radar surface.
     '''
     x, y = U.sc(self.location)
     # GATE
     # In order to facilitate blitting information on the orientation of the
     # gate, we create the image already rotated 90° clockwise by swapping
     # width and height...
     gate_width_px = U.rint(self.width / S.METRES_PER_PIXEL)
     gate_length_px = S.RADAR_RECT.h / 4
     aaf = 5  #anti-alias factor
     g_img = pygame.surface.Surface((gate_length_px*aaf,
                                     gate_width_px*aaf), SRCALPHA)
     # BOUNDARIES OF THE GATE
     pygame.draw.line(
          g_img, S.GRAY, (0, aaf), (gate_length_px*aaf, aaf), aaf)
     pygame.draw.line(
          g_img, S.GRAY, (0, gate_width_px*aaf-aaf),
          (gate_length_px*aaf, gate_width_px*aaf-aaf), aaf)
     # INFO ON ORIENTATION and FLIGHT LEVELS
     fl = lambda x : str(x/100).zfill(2)
     lines = ['H:' + str(self.heading).zfill(3),
              'B:' + fl(self.bottom),
              'T:' + fl(self.top)]
     fontobj = pygame.font.Font(S.MAIN_FONT, S.HUD_INFO_FONT_SIZE * aaf)
     label = U.render_lines(fontobj, lines, S.GRAY)
     label = label.subsurface(label.get_bounding_rect())
     w, h = label.get_size()
     ypsilon = U.rint(gate_width_px*aaf/2.0-h/2)
     g_img.blit(label, (0, ypsilon))
     g_img.blit(label, (gate_length_px*aaf-w, ypsilon))
     # tranformation and blitting
     rotang = 90 if 0<= self.heading < 180 else 270
     g_img = pygame.transform.rotate(g_img, rotang-self.heading)
     g_img = g_img.subsurface(g_img.get_bounding_rect()).copy()
     r = g_img.get_rect()
     g_img = pygame.transform.smoothscale(g_img, (U.rint(r.w*1.0/aaf),
                                                  U.rint(r.h*1.0/aaf)))
     g_rect = g_img.get_rect()
     surface.blit(g_img, (x-g_rect.centerx, y-g_rect.centery))
     # LABEL
     fontobj = pygame.font.Font(S.MAIN_FONT, S.HUD_INFO_FONT_SIZE)
     label = fontobj.render(self.name, True, S.RED)
     w, h = label.get_size()
     signed_offset = lambda n : cmp(1,n)*w
     x += (signed_offset(x) if self.side <=0 else 0) - w/2
     y += (signed_offset(y) if self.side >=0 else 0) - h/2
     surface.blit(label, (x,y))
Beispiel #7
0
 def __init__(self, gamelogic):
     super(Score, self).__init__()
     self.gamelogic = gamelogic
     self.image = pygame.surface.Surface(S.SCORE_RECT.size, SRCALPHA)
     self.rect = self.image.get_rect()
     self.score = self.gamelogic.score
     self.fontobj = pygame.font.Font(S.MAIN_FONT, U.rint(self.rect.h * 0.8))
Beispiel #8
0
 def draw(self, surface):
     pos = U.sc(self.location)
     pygame.draw.circle(surface, S.GRAY, pos, 2)
     pygame.draw.circle(surface, S.GRAY, pos, 6, 1)
     fontobj = pygame.font.Font(S.MAIN_FONT, S.HUD_INFO_FONT_SIZE)
     label = fontobj.render(self.id, True, S.BLUE)
     label = label.subsurface(label.get_bounding_rect()).copy()
     w, h = label.get_size()
     x, y = pos
     # In order to keep the crammed central space free, beacons labels are
     # always placed towards the edges of the radar screen, if possible.
     offsets = [U.rint(6+w/3), -U.rint(6+w/3)-w]
     index = x < S.RADAR_RECT.w/2
     if not (0 < x+offsets[index] and x+offsets[index]+w < S.RADAR_RECT.w):
         index = not index
     surface.blit(label, (x+offsets[index], y-h/2))
Beispiel #9
0
 def __draw_radar_aid(self):
     '''
     Draw the radar aid.
     '''
     if not S.RADAR_AID:
         return
     centre = U.sc((S.RADAR_RANGE, S.RADAR_RANGE))
     # Find how many metres a step consist of, making sure the final value
     # is sensible (not 12735.5, for example...)
     sensibles = [n*1000 for n in (1, 5, 10, 20, 25, 50, 100)]
     attempts = [S.RADAR_RANGE * 2 / n for n in sensibles]
     closest = min(attempts, key = lambda x : abs(x-S.RADAR_AID_STEPS))
     metres_per_step = sensibles[attempts.index(closest)]
     if S.RADAR_AID == 'circles':
         step_range = range(metres_per_step, U.rint(S.RADAR_RANGE*2**0.5),
                            metres_per_step)
         for radius in step_range:
             pygame.draw.circle(self.surface, S.RADAR_AID_COLOUR, centre,
                                U.rint(radius/S.METRES_PER_PIXEL), 1)
     elif S.RADAR_AID in ('grid', 'crosses', 'dots'):
         # In the following line: since division is integer division, this
         # will ensure that on marking will pass from the radar position
         first = S.RADAR_RANGE - S.RADAR_RANGE/metres_per_step*metres_per_step
         step_range = range(first, S.RADAR_RANGE * 2 + metres_per_step,
                            metres_per_step)
         draw = lambda fm, to : pygame.draw.aaline(self.surface,
                                   S.RADAR_AID_COLOUR, U.sc(fm), U.sc(to))
         for step in step_range:
             if S.RADAR_AID == 'grid':
                 draw((step, 0), (step, S.RADAR_RANGE*2))
                 draw((0, step), (S.RADAR_RANGE*2, step))
             elif S.RADAR_AID in ('dots', 'crosses'):
                 for step2 in step_range:
                     if S.RADAR_AID == 'dots':
                         pygame.draw.circle(self.surface, S.RADAR_AID_COLOUR,
                                            U.sc((step, step2)), 2)
                     elif S.RADAR_AID == 'crosses':
                         x, y = step, step2
                         offset = U.rint(metres_per_step / 16.0)
                         draw((x-offset, y), (x+offset, y))
                         draw((x, y-offset), (x, y+offset))
     else:
             msg = 'Wrong value of `RADAR_AID` in config file!'
             raise BaseException(msg)
     S.RADAR_MARKING = metres_per_step
Beispiel #10
0
 def update(self):
     pl = self.plane
     render = self.fontobj.render
     lines = []
     # LINE 1 = Airplane code
     lines.append(pl.icao.upper())
     # LINE 2 = Altitude, speed
     # Remove last digit, add variometer
     alt = str(U.rint(pl.altitude/100.0))
     alt += pl.variometer
     # Convert m/s to kph AND remove last digit, add accelerometer
     spd = str(U.rint(pl.speed*3.6))
     spd += pl.accelerometer
     lines.append('%s%s' % (alt,spd))
     self.image = self.render_lines(lines)
     self.rect = self.image.get_rect()
     self.angle = self.default_angle
     self.radius = self.default_radius
Beispiel #11
0
 def update(self):
     STEP = U.rint(S.PING_PERIOD / 1000.0 + 1)  #arbitrary: ping in sec + 1
     self.image.fill(S.BLACK)
     delta = U.rint(self.gamelogic.score) - self.score
     if abs(delta) < STEP:
         colour = S.WHITE
         variation = delta
     elif delta > 0:
         colour = S.OK_COLOUR
         variation = STEP
     else:
         colour = S.KO_COLOUR
         variation = -STEP
     self.score += variation
     score = str(self.score).zfill(6)
     score_img = self.fontobj.render(score, True, colour)
     score_img.subsurface(score_img.get_bounding_rect()).copy()
     pos = U.get_rect_at_centered_pos(score_img, self.rect.center)
     self.image.blit(score_img, pos)
Beispiel #12
0
    def process_commands(self, commands):
        '''
        Process commands.

        This is a "subroutine" of ``execute`` which is also called by some of
        the procedures. This is such that is possible to process commands
        without triggering score events and setting flags (as it happens with
        ``execute()``).

        This method will silently pass if the command name has not been
        recognised. This is to allow the method to process set of commands that
        also contains *procedures* (such LAND, TAKEOFF, etc...).
        '''
        pi = self.pilot
        pl = self.plane
        tc = self.pilot.target_conf
        for cname, (args, flags) in commands.items():
            log.info('%s executes: %s' %
                     (pl.icao, ' '.join((cname, repr(args), repr(flags)))))
            # PROCESS COMMANDS
            # Since flags are "universal" across commands (they all do the same
            # thing if they are called the same), it is possible to process
            # them separately.
            if cname == 'HEADING':
                assert len(args) == 1
                tc.heading = args[0]
                pi.status['veer_dir'] = \
                                pi.navigator.get_shortest_veering_direction()
            elif cname == 'ALTITUDE':
                tc.altitude = args[0]
            elif cname == 'SPEED':
                tc.speed = args[0]
            elif cname == 'ABORT':
                self.abort()
            elif cname == 'SQUAWK':
                if pl.flags.on_ground:
                    pi.say('Currently at airport %s, our destination is %s' %
                              (pl.origin, pl.destination), S.OK_COLOUR)
                else:
                    pi.say('Currently heading %s, our destination is %s' %
                          (U.rint(pl.heading), pl.destination), S.OK_COLOUR)
            else:
                log.debug('process_commands() ignored: %s' % cname)
            # PROCESS FLAGS
            # Flags with the same name have the same meaning and therefore
            # can be processed independently from the command they are
            # associated with. Since they can modify the value set by their
            # command, they must follow the command processing
            if 'EXPEDITE' in flags:
                pi.status['haste'] = 'expedite'
            if 'LONG' in flags:
                pi.status['veer_dir'] *= -1  #invert direction
Beispiel #13
0
 def __get_fontobj(cls, size_str):
     '''
     Return the appropriate font object.
     '''
     if size_str not in cls.font_objects.keys():
         # set the big font
         size = 1
         while True:
             fontobj = pygame.font.Font(S.MAIN_FONT, size)
             w,h = fontobj.render('XXX0000', True, S.WHITE).get_size()
             if w > S.STRIPS_RECT.w/2 - cls.offset - cls.margin:
                 break
             last_ok = fontobj
             size += 1
         cls.font_objects['large'] = last_ok
         # set the small font
         cls.font_objects['small'] = pygame.font.Font(S.MAIN_FONT,
                                                      U.rint(size/3.0))
     return cls.font_objects[size_str]