def keyDown(self, list_entities): """ Sets the current active menu object to inactive and then selects the next element in down direction to active. If no element is found, it spins around and selects the topmost element as active. Very similar to keyUp, just different direction when searching. @list_entities: list including entities to be processed. """ # Find current active entity for entity in list_entities: state_comp = self.entity_manager.getComponent(entity, StateComponent.__name__) if state_comp.state == "active": active_entity = entity break # Get current location of active entity position_comp = self.entity_manager.getComponent(entity, PositionComponent.__name__) active_x, active_y = helper.xyToPygame(position_comp.x, position_comp.y) # Set current active button to inactive state_comp.state = "inactive" # Search the next button (top direction) active_y += 1 new_entity = None possible_entities = [] break_loop = False # First of all search for all possible entities for i in range(active_y, WIN_HEIGHT, 1): for entity in list_entities: position_comp = self.entity_manager.getComponent(entity, PositionComponent.__name__) x, y = helper.xyToPygame(position_comp.x, position_comp.y) if y == i: possible_entities.append(entity) break_loop = True if break_loop: break # If we didn't find any entity, the before button is set to active again if not possible_entities: state_comp.state = "active" return # If we did in fact find any new entity, select the one who is nearer # at a height level distances = [] for entity in possible_entities: position_comp = self.entity_manager.getComponent(entity, PositionComponent.__name__) x, y = helper.xyToPygame(position_comp.x, position_comp.y) distances.append((x - active_x) ** 2) distances = list(enumerate(distances)) # add enumeration from 0 to n distances.sort(key=lambda x: x[1]) # sort by distance from less to high n = distances[0][0] # select the enumeration of the first element after sorting new_entity = possible_entities[n] # the new entity will be the nearest one # Mark the found entity as active state_comp = self.entity_manager.getComponent(new_entity, StateComponent.__name__) state_comp.state = "active"
def keyLeft(self, list_entities): """ Setlects the left button in position to the actual active button if that's possible, else the current button remains active. @list_entities: list including entities to be processed. """ # Find current active entity for entity in list_entities: state_comp = self.entity_manager.getComponent(entity, StateComponent.__name__) if state_comp.state == "active": active_entity = entity break # Get current location of active entity position_comp = self.entity_manager.getComponent(entity, PositionComponent.__name__) active_x, active_y = helper.xyToPygame(position_comp.x, position_comp.y) # Set current active button to inactive state_comp.state = "inactive" # Search the next button (top direction) active_x -= 1 new_entity = None possible_entities = [] break_loop = False # First of all search for all possible entities for i in range(active_x, 0, -1): for entity in list_entities: position_comp = self.entity_manager.getComponent(entity, PositionComponent.__name__) x, y = helper.xyToPygame(position_comp.x, position_comp.y) if x == i: possible_entities.append(entity) break_loop = True if break_loop: break # If we didn't find any entity, the before button is set to active again if not possible_entities: state_comp.state = "active" return # If we did in fact find any new entity, select the one who is nearer # at a height level distances = [] for entity in possible_entities: position_comp = self.entity_manager.getComponent(entity, PositionComponent.__name__) x, y = helper.xyToPygame(position_comp.x, position_comp.y) distances.append((y - active_y) ** 2) distances = list(enumerate(distances)) # add enumeration from 0 to n distances.sort(key=lambda x: x[1]) # sort by distance from less to high n = distances[0][0] # select the enumeration of the first element after sorting new_entity = possible_entities[n] # the new entity will be the nearest one # Mark the found entity as active state_comp = self.entity_manager.getComponent(new_entity, StateComponent.__name__) state_comp.state = "active"
def createObstructor(self, x, y, width, height): """ @x, y: real coordinates (will be translated) """ new_entity = self.entity_manager.createEntity() pyg_x, pyg_y = helper.xyToPygame(x, y) rect = pygame.Rect(pyg_x, pyg_y, width, height) new_position_component = PositionComponent(x, y, rect) self.entity_manager.addComponent(new_entity, new_position_component) self.group_manager.add(new_entity, 'obstructor') return new_entity
def update(self): # Get hero entity hero = self.group_manager.get('hero')[0] # Get camera entity camera = self.group_manager.get('camera')[0] # Get components hero_pos_comp = self.entity_manager.getComponent(hero, PositionComponent.__name__) hero_state_comp = self.entity_manager.getComponent(hero, StateComponent.__name__) camera_pos_comp = self.entity_manager.getComponent(camera, PositionComponent.__name__) # Get level info component level_info = self.group_manager.get('level_info')[0] level_info_comp = self.entity_manager.getComponent(level_info, LevelInfoComponent.__name__) # Check if hero has got to the final of the level end = level_info_comp.player_finish x, y = helper.xyToPygame(end[0], end[1]) x -= camera_pos_comp.x y += camera_pos_comp.y if hero_pos_comp.rect.collidepoint(x, y): hero_state_comp.state = 'win' # Iterate over those components that have physics component. # If they no longer have body or shape, delete them. entity_list = self.entity_manager.getEntitiesHavingComponent(PhysicsComponent.__name__) for entity in entity_list: physics_comp = self.entity_manager.getComponent(entity, PhysicsComponent.__name__) if physics_comp.shape.group == REMOVE_GROUP: self.group_manager.removeCompletely(entity) self.entity_manager.removeEntity(entity) # Check music status # if self.first_time: # pygame.mixer.music.stop() # level_name = level_info_comp.level_name # pygame.mixer.music.load(MUSIC_MAP[level_name]) # pygame.mixer.music.play(-1, 0.0) # Indicate that we have, at least, updated the system once self.first_time = False
def update(self): list_entities = self.entity_manager.getEntitiesHavingComponents( PositionComponent.__name__, StateComponent.__name__ ) # Search if any element is active active = False for entity in list_entities: state_comp = self.entity_manager.getComponent(entity, StateComponent.__name__) if state_comp.state == 'active': active = True break # If we can't find any active element, we force the topmost to be active if active: return try: for height in range(WIN_HEIGHT): for entity in list_entities: position_comp = self.entity_manager.getComponent(entity, PositionComponent.__name__) x, y = helper.xyToPygame(position_comp.x, position_comp.y) if y == height: raise FoundException() except FoundException: state_comp = self.entity_manager.getComponent(entity, StateComponent.__name__) state_comp.state = 'active' # Manage sound # The first time we are on this system, we stop the music and play the # menu music. if self.first_time: if not pygame.mixer.music.get_busy(): pygame.mixer.music.stop() pygame.mixer.music.load(MENU_MUSIC) pygame.mixer.music.play(-1, 0.0) self.first_time = False
def update(self): #### JUST FOR DEBUG PURPOSES level_info = self.group_manager.get('level_info')[0] level_info_comp = self.entity_manager.getComponent(level_info, LevelInfoComponent.__name__) #### # Get all the lights list_entities = self.entity_manager.getEntitiesHavingComponents( LightComponent.__name__ ) # Get the camera information camera = self.group_manager.get('camera')[0] camera_pos_component = self.entity_manager.getComponent(camera, PositionComponent.__name__) camera_x = camera_pos_component.x camera_y = camera_pos_component.y # Get hero's information hero = self.group_manager.get('hero')[0] hero_pos_comp = self.entity_manager.getComponent(hero, PositionComponent.__name__) hero_state_comp = self.entity_manager.getComponent(hero, StateComponent.__name__) # Populate a list of the obstructors only if it's the first time we're # updating the system obstructors = [] if self.first_time: if self.group_manager.doesGroupExist('obstructor'): list_obstructors = self.group_manager.get('obstructor') for obstructor in list_obstructors: position_comp = self.entity_manager.getComponent(obstructor, PositionComponent.__name__) x, y = helper.xyToPygame(position_comp.x, position_comp.y) # x = x - camera_x # y = y + camera_y position_comp.rect.topleft = (x, y) obstructors.append(position_comp.rect) # Create a list for temporal (auxiliar) obstructors auxiliar_obstructors = [] # Add the dynamic obstructors to that list if self.group_manager.doesGroupExist('dynamic_obstructor'): list_obstructors = self.group_manager.get('dynamic_obstructor') for obstructor in list_obstructors: position_comp = self.entity_manager.getComponent(obstructor, PositionComponent.__name__) auxiliar_obstructors.append(position_comp.rect) # Update the lights for entity in list_entities: light_comp = self.entity_manager.getComponent(entity, LightComponent.__name__) state_comp = self.entity_manager.getComponent(entity, StateComponent.__name__) # If mask isn't created, we initiate it if light_comp.light.mask is None: light_comp.light.createMask() # If the light isn't active, don't update it if state_comp.state != 'active': continue # Update position x, y = helper.xyToPygame(light_comp.light.x, light_comp.light.y) x = x - camera_x y = y + camera_y light_comp.light.light_rect.center = x, y # Update obstructors if not light_comp.light.obstructors: light_comp.light.setObstructors(obstructors) if auxiliar_obstructors: light_comp.light.setObstructors(auxiliar_obstructors, auxiliar=True) ## May need to apply some logic around the update ## because it may be computationally intensive. ## Currently, we just update if there are any dynamic obstructors and ## or we are on the first update if self.first_time: # Update the constructors with the camera movement light_comp.light.updateObstructors(camera_x, camera_y) # Update the camera mask light_comp.light.update() # Without dynamic objects we will only render the mask once! elif auxiliar_obstructors: # Update the constructors with the camera movement light_comp.light.updateObstructors(camera_x, camera_y) # Update the light (update it's mask to be rendered) light_comp.light.update() ## Only update if the any obstructor is inside the light area # for obstructor in auxiliar_obstructors: # if light_comp.light.isRectInsideLight(obstructor, x, y, # camera_x, camera_y): # light_comp.light.update() # break # Draw the light onto the screen light_comp.light.blit(DISPLAYSURF) # Hero is in light range -> kill him hero_rect = hero_pos_comp.rect # print(hero_rect.topleft) if light_comp.light.isRectInsideLight(hero_rect, x, y, camera_x, camera_y): hero_state_comp.state = 'dead' # Clean the auxiliar obstructors light_comp.light.cleanAuxiliar() # Indicate that we have, at least, updated this system once self.first_time = False ##### ##### ## DEBUG THINGS if level_info_comp.debug: # draw obstructors for entity in list_entities: light_comp = self.entity_manager.getComponent(entity, LightComponent.__name__) for obstructor in light_comp.light.obstructors + light_comp.light.auxiliar_obstructors: pygame.draw.rect(DISPLAYSURF, BLACK, obstructor, 3) # draw light for entity in list_entities: # draw rect light_comp = self.entity_manager.getComponent(entity, LightComponent.__name__) rect = light_comp.light.light_rect pygame.draw.rect(DISPLAYSURF, YELLOW, rect, 3) # draw middle of rect pygame.draw.circle(DISPLAYSURF, BLUE, rect.center, 3)
def update(self): #### JUST FOR DEBUG PURPOSES has_level_info = self.group_manager.doesGroupExist('level_info') if has_level_info: level_info = self.group_manager.get('level_info')[0] level_info_comp = self.entity_manager.getComponent(level_info, LevelInfoComponent.__name__) #### list_entities = self.entity_manager.getEntitiesHavingComponents( PositionComponent.__name__, RenderComponent.__name__) has_camera = self.group_manager.doesGroupExist('camera') if has_camera: camera_entity = self.group_manager.get('camera')[0] camera_position = self.entity_manager.getComponent(camera_entity, PositionComponent.__name__) camera_x = camera_position.x camera_y = camera_position.y for entity in list_entities: position_comp = self.entity_manager.getComponent(entity, PositionComponent.__name__) render_comp = self.entity_manager.getComponent(entity, RenderComponent.__name__) x,y = helper.xyToPygame(position_comp.x, position_comp.y) if has_camera: x -= camera_x y += camera_y position_comp.rect.centerx = x position_comp.rect.centery = y self.surface.blit(render_comp.sprite, position_comp.rect) ##### ##### ## DEBUG THINGS if not has_level_info: return if level_info_comp.debug: # paint collision list_entities = self.group_manager.get('collision') for entity in list_entities: # collision rectangle physics_comp = self.entity_manager.getComponent(entity, PhysicsComponent.__name__) shape = physics_comp.shape vertices = shape.get_points() x,y = helper.toPygame(vertices[0]) width = helper.toPygame(vertices[1])[0] - x height = y - helper.toPygame(vertices[3])[1] x = int(x - camera_x) y = int(y + camera_y - height) rect = pygame.Rect(x, y, width, height) pygame.draw.rect(DISPLAYSURF, RED, rect, 3) # gravity center center = helper.toPygame(physics_comp.body.position) center = (int(center[0] - camera_x), int(center[1] + camera_y)) pygame.draw.circle(DISPLAYSURF, BLUE, center, 3) # paint hero center of gravity hero = self.group_manager.get('hero')[0] physics_comp = self.entity_manager.getComponent(hero, PhysicsComponent.__name__) center = helper.toPygame(physics_comp.body.position) center = (int(center[0] - camera_x), int(center[1] + camera_y)) pygame.draw.circle(DISPLAYSURF, BLUE, center, 3)
def update(self): #### JUST FOR DEBUG PURPOSES level_info = self.group_manager.get('level_info')[0] level_info_comp = self.entity_manager.getComponent(level_info, LevelInfoComponent.__name__) ######### # Get all entities that have light and pos component list_entities = self.entity_manager.getEntitiesHavingComponents( LightComponent.__name__, PositionComponent.__name__, StateComponent.__name__) # Get camera information camera = self.group_manager.get('camera')[0] camera_pos_component = self.entity_manager.getComponent(camera, PositionComponent.__name__) camera_x = camera_pos_component.x camera_y = camera_pos_component.y # Get hero's information hero = self.group_manager.get('hero')[0] hero_pos_comp = self.entity_manager.getComponent(hero, PositionComponent.__name__) hero_state_comp = self.entity_manager.getComponent(hero, StateComponent.__name__) # Fill a obstructors list with objects that must block light list_obstructors = self.group_manager.get('obstructor') obstructors = [] for obstructor in list_obstructors: position_comp = self.entity_manager.getComponent(obstructor, PositionComponent.__name__) x, y = helper.xyToPygame(position_comp.x, position_comp.y) x = x - camera_x y = y + camera_y position_comp.rect.topleft = (x, y) obstructors.append(position_comp.rect) # Add dynamic obstructors, such as crates, to the obstructors list list_obstructors = self.group_manager.get('dynamic_obstructor') for obstructor in list_obstructors: position_comp = self.entity_manager.getComponent(obstructor, PositionComponent.__name__) obstructors.append(position_comp.rect) # Iterate over the light entities and update them for entity in list_entities: # Get components for current entity state_comp = self.entity_manager.getComponent(entity, StateComponent.__name__) light_comp = self.entity_manager.getComponent(entity, LightComponent.__name__) position_comp = self.entity_manager.getComponent(entity, PositionComponent.__name__) # If it's not active we just ignore it and continue to the next one if state_comp.state != 'active': continue # Reset the containers and set to the new ones light_comp.light.clean() light_comp.light.addRectList(obstructors) # Get info and adapt it to camera x, y = helper.xyToPygame(position_comp.x, position_comp.y) x = int(x - camera_x) y = int(y + camera_y) size = light_comp.size # Set the border (limit) of the light light_comp.light.setBorderWithSize(x, y, size, input = 'pygame') # Set position light_comp.light.setLightLocation(x, y, input = 'pygame') # Run the sweep method (create light triangles) light_comp.light.sweep() # Finally paint the light onto the screen light_comp.light.blit(DISPLAYSURF, light_comp.color, light_comp.alpha) # Check if hero is inside the light hero_rect = hero_pos_comp.rect if light_comp.light.isRectInsideLight(hero_rect): hero_state_comp.state = 'dead' ##### ##### ## DEBUG THINGS if level_info_comp.debug: # draw obstructors for obstructor in obstructors: pygame.draw.rect(DISPLAYSURF, BLACK, obstructor, 3) # draw light for entity in list_entities: light_comp = self.entity_manager.getComponent(entity, LightComponent.__name__) position_comp = self.entity_manager.getComponent(entity, PositionComponent.__name__) # draw rect x, y = helper.xyToPygame(position_comp.x, position_comp.y) x = int(x - camera_x) y = int(y + camera_y) size = light_comp.size pygame.draw.rect(DISPLAYSURF, YELLOW, (x-size//2, y-size//2, size, size), 5) # draw light center pygame.draw.circle(DISPLAYSURF, RED, (x,y), 5)