def process(self, kwargs): eventStore = kwargs.get('EVENT_STORE', None) for ent, (col, pos, vel) in self.world.get_components(Collidable, Position, Velocity): # update the position of the shape for shape in col.shapes: shape.pos = Vector(pos.x + pos.w // 2, pos.y + pos.h // 2) # col.shape.pos.angle = pos.angle # check for colisio for otherEnt, (otherCol, otherPos) in self.world.get_components(Collidable, Position): if otherEnt == ent: continue if otherPos.movable: for shape in otherCol.shapes: shape.pos = Vector(otherPos.x + otherPos.w // 2, otherPos.y + otherPos.h // 2) if self.checkCollide(col.shapes, otherCol.shapes): # Remove velocity from current entity vel.x = 0 vel.y = 0 vel.alpha = 0 # print(choice(COLORS) + # f'colision detected between {ent} and {otherEnt}') if eventStore: if col.event_tag == 'genericColision': print(f'Collision! {ent} - {otherEnt}') event = EVENT(col.event_tag, (ent, otherEnt)) # print(f'Firing event ent --> otherEnt: {event}') eventStore.put(event)
def check_colisions(box): collided = False # 1 # # # # 2 # # # # # # # # # # 3 # # # # 4 x = box[0] * X y = box[1] * Y w = box[2] * X h = box[3] * Y center_x = int(x + (w / 2)) center_y = int(y + (h / 2)) pt1 = Vector(center_x - w, center_y - h) pt2 = Vector(center_x - w, center_y + h) pt3 = Vector(center_x + w, center_y - h) pt4 = Vector(center_x + w, center_y + h) box_poly = Poly(Vector(center_x, center_y), [pt1, pt2, pt3, pt4]) #print(box, box_poly, end="\n") if collide(box_poly, LEFT_LINE_POLY) or collide(box_poly, RIGHT_LINE_POLY): collided = True return collided
def on_update(self, dt: float, window_width: int, window_height: int): handler = self.key_handler binds = self.key_binds vec = Vector(0, 0) if handler[binds.up]: vec += Vector(0, 1) if handler[binds.down]: vec += Vector(0, -1) if handler[binds.right]: vec += Vector(1, 0) if handler[binds.left]: vec += Vector(-1, 0) self.dx = vec * self.speed super(Player, self).on_update(dt, window_width, window_height)
def __init__(self, dx: Vector = Vector(0, 0), d2x: Vector = Vector(0, 0), mass: float = 1, *args, **kwargs): """ :param dx: velocity of the object at state 1, given with relative coordinates. :param d2x: acceleration of the object at state 1, given with relative coordinates. :param mass: mass given in mass relative to player (player mass = 1) """ super(PhysicsBody, self).__init__(*args, **kwargs) self.dx: Vector = dx self.d2x: Vector = d2x self.mass: float = mass
def draw_trapezoid_bottom(self, y=0, color=WHITE): """ " " " " " " " " " " " <-- """ polygon = Concave_Poly(Vector(0, 0), [ self.rotate_and_get_a_vector([ self.center_coords[0], self.center_coords[1] + (self.radius - y) ], math.radians(-30 + self.rotation)), self.rotate_and_get_a_vector([ self.center_coords[0], self.center_coords[1] + (self.radius - y) ], math.radians(30 + self.rotation)), self.rotate_and_get_a_vector([ self.center_coords[0], self.center_coords[1] + (self.radius - y) - self.trapezoid_height ], math.radians(30 + self.rotation)), self.rotate_and_get_a_vector([ self.center_coords[0], self.center_coords[1] + (self.radius - y) - self.trapezoid_height ], math.radians(-30 + self.rotation)) ]) pygame.draw.polygon(self.surface, color, (polygon.rel_points[0], polygon.rel_points[1], polygon.rel_points[2], polygon.rel_points[3])) return polygon
def update(self): self.angle += self.left - self.right - self.screen_rotation_speed self.rect.centerx = int(self.center_point[0] + (self.r + self.pump) * math.sin(self.theta)) self.rect.centery = int(self.center_point[1] + (self.r + self.pump) * math.cos(self.theta)) self.circle = Circle(Vector(self.rect.centerx, self.rect.centery), self.circle_radius)
def from_mxCell(el, batch, windowSize, lineWidth=10): # Parse style style = parse_style(el.attrib['style']) # Get parent style['parent'] = el.attrib['parent'] # Get geometry geometry = el[0] x = float(geometry.attrib.get('x', '0')) y = float(geometry.attrib.get('y', '0')) width = float(geometry.attrib['width']) height = float(geometry.attrib['height']) # Create drawing (x, y) = translate_coordinates((x, y), windowSize, height) pos = Position(x=x, y=y, w=width, h=height, movable=False) rotate = 0 if style.get('rotation', '') != '': rotate = int(style['rotation']) if rotate < 0: rotate = 360 + rotate pos.angle = rotate draw = None col_points = None center = (pos.x + pos.w // 2, pos.y + pos.h // 2) if 'ellipse' in style: draw = primitives.Ellipse(center, width, height, style, rotate) col_points = draw._get_points() else: draw = primitives.Rectangle(x, y, width, height, style, rotate) col_points = pos._get_box() label = el.attrib.get('value', '') if label: label = pyglet.text.HTMLLabel(label, batch=batch, x=center[0], y=center[1], anchor_x='center', anchor_y='center') batch_draw = draw.add_to_batch(batch) col_points = list(map(lambda x: Vector(x[0] - center[0], x[1] - center[1]), col_points)) collision_box = Poly(Vector(center[0], center[1]), col_points) return [pos, Collidable(shape=collision_box)], style, batch_draw
def process(kwargs: SystemArgs): logger = logging.getLogger(__name__) world = kwargs.get('WORLD', None) env = kwargs.get('ENV', None) event_store = kwargs.get('EVENT_STORE') if env is None: raise Exception("Can't find environment") # Local ref most used functions for performance get_components = world.get_components component_for_ent = world.component_for_entity sleep = env.timeout # while True: all_collidables = get_components(Collidable, Position) for ent, (hover, pos, velocity, col) in get_components(Hover, Position, Velocity, Collidable): # Check collision here for shape in col.shapes: shape.pos = Vector(*pos.center) shape.angle = pos.angle close_entities = list(map( lambda t: t[1][1], filter( lambda ent_and_components: ent_and_components[1][1].sector in pos.adjacent_sectors, all_collidables ) )) hover.crowded = close_entities try: (action, extra_args) = actions[hover.status] # logger.debug(f'entity {ent} - {hover} @ {pos} - related action: {action}') res: ActionResponse = action(ent, hover, pos, velocity, *extra_args) if res.control_response is not None: control_component = component_for_ent(1, Control) response = ControlResponseFormat(ent, res.control_response) control_component.channel.put(response) if res.change_state is not None: change_hover_state(world, ent, res.change_state) except KeyError: logger.error(f'No action for {hover.status}') req = event_store.get(lambda ev: ev.type == 'genericCollision') switch = yield req | sleep(hover_interval) if req in switch: ev = switch[req] ent = ev.payload.ent other_ent = ev.payload.other_ent for d in [ent, other_ent]: hover = component_for_ent(d, Hover) if world.has_component(d, Velocity): world.remove_component(d, Velocity) if hover.status != HoverState.CRASHED: control_component = component_for_ent(1, Control) change_hover_state(world, d, HoverState.CRASHED) warn_control = ControlResponseFormat(d, False) control_component.channel.put(warn_control)
def _is_valid_proposal(o1_x, o1_y, object1_index, bounding_boxes, placements): o1_x += bounding_boxes[object1_index, 0, 0] o1_y += bounding_boxes[object1_index, 0, 1] # Check if object collides with any of already placed objects. We use half-sizes, # but collision uses full-sizes. That's why we multiply by 2x here. o1_w, o1_h, _ = bounding_boxes[object1_index, 1] object1 = Poly.from_box(Vector(o1_x, o1_y), o1_w * 2.0, o1_h * 2.0) for object2_index in range(len(placements)): # Don't care about z placement o2_x, o2_y, _ = placements[object2_index] o2_x += bounding_boxes[object2_index, 0, 0] o2_y += bounding_boxes[object2_index, 0, 1] # Don't care about object depth. o2_w, o2_h, _ = bounding_boxes[object2_index, 1] object2 = Poly.from_box(Vector(o2_x, o2_y), o2_w * 2.0, o2_h * 2.0) if collide(object1, object2): return False return True
def from_mxCell(el, batch, windowSize, lineWidth=10): # Parse style style = parse_style(el.attrib['style']) if style.get('shape') != 'mxgraph.floorplan.wall': raise Exception("Cannot create Wall from {}: shape is not mxgraph.floorplan.wall".format(el)) # Get parent parent_element = el.attrib['parent'] style['parent'] = parent_element # Get geometry geometry = el[0] x = float(geometry.attrib.get('x', '0')) y = float(geometry.attrib.get('y', '0')) width = float(geometry.attrib['width']) height = float(geometry.attrib['height']) # Create drawing (x, y) = translate_coordinates((x, y), windowSize, height) pos = Position(x=x, y=y, w=width, h=height, movable=False) rotate = 0 if 'rotation' in style: rotate = int(style['rotation']) if rotate < 0: rotate = 360 + rotate pos.angle = rotate label = el.attrib.get('value', '') if label: label = pyglet.text.HTMLLabel(label, batch=batch, x=center[0], y=center[1], anchor_x='center', anchor_y='center') # Create collision box col_points = pos._get_box() center = (pos.x + pos.w // 2, pos.y + pos.h // 2) col_points = list(map(lambda x: Vector(x[0] - center[0], x[1] - center[1]), col_points)) collision_box = Poly(Vector(center[0], center[1]), col_points) rectangle = primitives.Rectangle(x, y, width, height, style, rotate) rectangle.add_to_batch(batch) return ([pos, Collidable(shape=collision_box)], style)
def __init__(self, points: Tuple[Tuple[float]] = None, radius: float = None, *args, **kwargs): """ :param points: A tuple of tuples of floats (x,y) that describes the boundary using relative coordinates from the top left most point going clockwise around the perimeter. Object becomes a polygon or point. :param radius: A relative coordinate describing the radius of a circular boundary from the center of the object. Object becomes a circle. """ super(Collidable, self).__init__(*args, **kwargs) if radius and not points: self.collider = Circle(self.rel_vector, radius) elif points and len(points) != 1: self.collider = Poly(self.rel_vector, points) elif points: self.collider = None else: if (len(args) > 1 and args[1]) or 'window_width' in kwargs: width = args[1] if len( args) > 1 and args[1] else kwargs['window_width'] else: raise InvalidArguments if (len(args) > 2 and args[2]) or 'window_height' in kwargs: height = args[2] if len( args) > 2 and args[2] else kwargs['window_height'] else: raise InvalidArguments self.collider = Poly( self.rel_vector, (Vector(self.image.width / width * 16 + self.rel_x, self.image.height / height * 9 + self.rel_y), Vector(self.image.width / width * 16 + self.rel_x, -self.image.height / height * 9 + self.rel_y), Vector(-self.image.width / width * 16 + self.rel_x, -self.image.height / height * 9 + self.rel_y), Vector(-self.image.width / width * 16 + self.rel_x, self.image.height / height * 9 + self.rel_y)))
def cells(self) -> [int, int]: """ Gives the row and column of the cell(s) that this object is in. Used for collision detection. """ if not self.collider: result = [[ floor(self.rel_x / Collidable.cell_width), floor(self.rel_y / Collidable.cell_height) ]] elif isinstance(self.collider, Poly): result = [] for point in self.collider.points: temp = [ floor(point[0] / Collidable.cell_width), floor(point[1] / Collidable.cell_height) ] if temp not in result: result.append(temp) elif isinstance(self.collider, Circle): points = [ self.rel_vector + Vector(0, self.collider.radius), self.rel_vector + Vector(self.collider.radius, 0), self.rel_vector + Vector(0, -self.collider.radius), self.rel_vector + Vector(-self.collider.radius, 0) ] result = [] for point in points: temp = [ floor(point[0] / Collidable.cell_width), floor(point[1] / Collidable.cell_height) ] if temp not in result: result.append(temp) else: return None return result
def process(self, kwargs: SystemArgs): # start = datetime.now() logger = logging.getLogger(__name__) eventStore = kwargs.get('EVENT_STORE', None) all_collidables = self.world.get_components(Collidable, Position) for ent, (col, pos, vel) in self.world.get_components(Collidable, Position, Velocity): # update the position of the shape for shape in col.shapes: shape.pos = Vector(*pos.center) shape.angle = pos.angle # self.logger.debug(f'Entity {ent} - Shapes = {col.shapes}') # check for colision ents_to_check = filter( lambda ent_and_components: ent_and_components[1][1].sector in pos.adjacent_sectors, all_collidables) for otherEnt, (otherCol, otherPos) in ents_to_check: if otherEnt == ent: continue if otherPos.movable: for shape in otherCol.shapes: shape.pos = Vector(*otherPos.center) shape.angle = otherPos.angle if self.checkCollide(col.shapes, otherCol.shapes): # Remove velocity from current entity vel.x = 0 vel.y = 0 vel.alpha = 0 if eventStore: # if col.event_tag == 'genericCollision': # self.logger.debug(choice(COLORS) + f'Collision! {ent} - {otherEnt}') event = EVENT(col.event_tag, CollisionPayload(ent, otherEnt)) # self.logger.debug(f'Firing event ent --> otherEnt: {event}') eventStore.put(event)
def collision_from_points(shape: ShapeType, center: typing.Tuple[int, int]) -> Poly: points = shape._get_points() col_points = list(map(lambda x: Vector(x[0] - center[0], x[1] - center[1]), points)) return Poly(tuple2vector(center), col_points)
LEFT_LINE_X = CENTER_X - 110 LEFT_LINE_Y = 640 RIGHT_LINE_X = CENTER_X + 110 RIGHT_LINE_Y = 640 LEFT_MIDDLE = ((LEFT_LINE_X + TOP_X) / 2, (LEFT_LINE_Y + TOP_Y) / 2) LEFT_MIDDLE = (320 + 110, 260) RIGHT_MIDDLE = ((RIGHT_LINE_X + TOP_X) / 2, (RIGHT_LINE_Y + TOP_Y) / 2) #print(f"TOP X {CENTER_X} Y {TOP_Y} | LEFT X {LEFT_LINE_X} Y {LEFT_LINE_Y} \ # MID {LEFT_MIDDLE} | RIGHT X {RIGHT_LINE_X} Y {RIGHT_LINE_Y} MID \ # {RIGHT_MIDDLE}") LEFT_LINE_POLY = Poly(Vector(LEFT_MIDDLE[0], LEFT_MIDDLE[1]), [Vector(TOP_X, TOP_Y), Vector(LEFT_LINE_X, LEFT_LINE_Y)]) RIGHT_LINE_POLY = Poly( Vector(RIGHT_MIDDLE[0], RIGHT_MIDDLE[1]), [Vector(TOP_X, TOP_Y), Vector(RIGHT_LINE_X, RIGHT_LINE_Y)]) thickness = 1 isClosed = True # Blue color in BGR color = (255, 0, 0) # Create some points ppt = np.array( [TWO_METERS_LEFT, TWO_METERS_RIGTH, TREE_METERS_RIGTH, TREE_METERS_LEFT],
def from_mxCell(el, batch, windowSize, lineWidth=10): # Parse style style = parse_style(el.attrib['style']) if style.get('shape', "") != 'mxgraph.floorplan.wallCorner': raise Exception( "Cannot create Wall from {}: shape is not mxgraph.floorplan.wallCorner" .format(el)) # Get parent parent_element = el.attrib['parent'] direction = style.get('direction', 'east') style['parent'] = parent_element # Get geometry geometry = el[0] x = float(geometry.attrib.get('x', '0')) y = float(geometry.attrib.get('y', '0')) width = float(geometry.attrib['width']) height = float(geometry.attrib['height']) # Create drawing (x, y) = translate_coordinates((x, y), windowSize, height) pos = Position(x=x, y=y, w=width, h=height, movable=False) center = (pos.x + pos.w // 2, pos.y + pos.h // 2) points = [(pos.x, pos.y), (pos.x, pos.y + pos.h), (pos.x - lineWidth // 2, pos.y + pos.h), (pos.x + pos.w, pos.y + pos.h)] # Collision box col_points = [(pos.x - lineWidth // 2, pos.y), (pos.x - lineWidth // 2, pos.y + pos.h + lineWidth // 2), (pos.x + pos.w, pos.y + pos.h + lineWidth // 2), (pos.x + pos.w, pos.y + pos.h - lineWidth // 2), (pos.x + lineWidth // 2, pos.y + pos.h - lineWidth // 2), (pos.x + lineWidth // 2, pos.y)] # Get the right corner if direction == 'north': points = map( lambda x: rotate_around_point(x, math.radians(-90), center), points) col_points = map( lambda x: rotate_around_point(x, math.radians(-90), center), col_points) elif direction == 'south': points = map( lambda x: rotate_around_point(x, math.radians(90), center), points) col_points = map( lambda x: rotate_around_point(x, math.radians(90), center), col_points) elif direction == 'west': points = map( lambda x: rotate_around_point(x, math.radians(180), center), points) col_points = map( lambda x: rotate_around_point(x, math.radians(180), center), col_points) # Check for rotation if style.get('rotation', '') != '': rotate = int(style['rotation']) if rotate < 0: rotate = 360 + rotate points = map( lambda x: rotate_around_point(x, math.radians(rotate), center), points) col_points = map( lambda x: rotate_around_point(x, math.radians(rotate), center), col_points) drawing = primitives.Line(list(points), style) drawing.add_to_batch(batch) label = el.attrib.get('value', '') if label: label = pyglet.text.HTMLLabel(label, batch=batch, x=center[0], y=center[1], anchor_x='center', anchor_y='center') col_points = map(lambda x: Vector(x[0] - center[0], x[1] - center[1]), col_points) box = Concave_Poly(Vector(center[0], center[1]), list(col_points)) return ([pos, Collidable(shape=box)], style)
def get_rel_points(center, points): return list(map(lambda x: Vector(x[0] - center[0], x[1] - center[1]), points))
def rotate_and_get_a_vector(self, point, angle): """ Return Vector from check collision """ qx, qy = self.rotate(point, angle) return Vector(qx, qy)
def tuple2vector(x: Point) -> Vector: return Vector(x[0], x[1])
def tuple2vector(x): return Vector(x[0], x[1])
def get_rel_points(center: Point, points: List[Point]) -> List[Vector]: return list(map(lambda x: Vector(x[0] - center[0], x[1] - center[1]), points))
def start(): """ The main function of the client. """ temp_window = pyglet.window.Window(caption='InvictusClient', visible=False) asset_batch = pyglet.graphics.Batch() overlay_batch = pyglet.graphics.Batch() objects: [Asset] = [] collidables: [Collidable] = [] physics_objects: [PhysicsBody] = [] players: [Player] = [] resource_path = Path('resources/') audio_path = resource_path.joinpath('audio/') image_path = resource_path.joinpath('images/') level_path = resource_path.joinpath('levels/') config_file = resource_path.joinpath('config.ini') if not os.path.exists(resource_path) or not os.path.exists( audio_path) or not os.path.exists(image_path): txt = pyglet.text.Label('Missing resource files, please reinstall.', font_name='Times New Roman', font_size=20, x=temp_window.width // 2, y=temp_window.height // 2, anchor_x='center', anchor_y='center', batch=overlay_batch) objects.append(txt) temp_window.set_visible() pyglet.app.run() return else: temp_window.close() if not os.path.exists(level_path): os.mkdir(level_path) if not os.path.exists(config_file): config = configparser.ConfigParser() config['Client'] = { 'resolution': '1920x1080', 'fullscreen': 'False', 'windowstyle': 'Borderless', 'monitor': '0', 'vsync': 'False' } with open(config_file, 'w') as f: config.write(f) else: config = configparser.ConfigParser() config.read(config_file) style = None if config['Client']['windowstyle'].lower( ) == 'default' else config['Client']['windowstyle'].lower() resolution = config['Client']['resolution'].split('x') window = pyglet.window.Window( caption='InvictusClient', width=int(resolution[0]), height=int(resolution[1]), style=style, fullscreen=config['Client']['fullscreen'].lower() == 'true', screen=pyglet.canvas.get_display().get_screens()[int( config['Client']['monitor'])], vsync=config['Client']['vsync'].lower() == 'true') del style, resolution pyglet.resource.path = [ str(resource_path), str(image_path), str(audio_path), str(level_path) ] test_obj = Collidable(rel_pos_vector=Vector(0, 0), window_width=window.width, window_height=window.height, image_path='green.png', batch=asset_batch) collidables.append(test_obj) test_plyr = Player(rel_pos_vector=Vector(16, 9), window_width=window.width, window_height=window.height, image_path='blue.png', batch=asset_batch) window.push_handlers(test_plyr.key_handler) collidables.append(test_obj) collidables.append(test_plyr) physics_objects.append(test_plyr) players.append(test_plyr) @window.event def on_draw(): window.clear() asset_batch.draw() overlay_batch.draw() def update(dt, window_width, window_height): cells: {Collidable} = {} for collidable in collidables: for cell in collidable.cells: if (cell[0] * cell[1]) not in cells: cells[cell[0] * cell[1]] = [] cells[cell[0] * cell[1]].append(collidable) for cell in cells: for collidable in cells[cell]: for collidable2 in cells[cell]: if collidable.is_colliding(collidable2): print("Colliding") for player in players: player.on_update(dt, window_width, window_height) pyglet.clock.schedule_interval(update, 1 / 120, window_width=window.width, window_height=window.height) pyglet.app.run()