def set_orbit(self, e1, e2, distance, angle_in_degrees, clockwise=True): pc1 = self.manager.get_entity_comp(e1, PhysicsEcsComponent.name()) pc2 = self.manager.get_entity_comp(e2, PhysicsEcsComponent.name()) if pc1 == None or pc2 == None: return # TODO what if we want to orbit from where we are? ie no angle specified rad = math.radians(angle_in_degrees) x = pc2.pos.x + distance * math.cos(rad) y = pc2.pos.y + distance * math.sin(rad) pc1.pos.x = x pc1.pos.y = y gv = (pc1.pos - pc2.pos).normalized() ov = vec2d.vec2d(gv.y, gv.x) if clockwise: ov.y *= -1 else: ov.x *= -1 mag = math.sqrt((GRAV_CONSTANT * pc2.mass) / distance) ov *= mag pc1.vel = ov pc1.acc = vec2d.vec2d(0, 0) # make acceleration zero
def __init__(self, x, y, mass, static=False, vx=0.0, vy=0.0): super(PhysicsEcsComponent, self).__init__() self.pos = vec2d.vec2d(x, y) self.vel = vec2d.vec2d(vx, vy) self.acc = vec2d.vec2d(0, 0) self.mass = float(mass) self.static = static
def update(self, dt): player_sys = self.manager.get_system(player.PlayerEscSystem.name()) phys_comp_list = self.manager.comps[phys.PhysicsEcsComponent.name()] coll_comp_list = self.manager.comps[collision.CollisionEcsComponent.name()] aster_comp_list = self.manager.comps[AsteroidEcsComponent.name()] # generate if player_sys.player_entity_id: player_pc = self.manager.get_entity_comp(player_sys.player_entity_id, phys.PhysicsEcsComponent.name()) player_sc = self.manager.get_entity_comp(player_sys.player_entity_id, ship.ShipEcsComponent.name()) if player_pc and player_sc: time = player_sys.time_limit if time % 20 == 0: if player_pc.vel.length > random.randint(1, phys.SPEED_LIMIT): player_angle = player_pc.vel.get_angle() gen_angle = random.choice( [angle for angle in range(int(player_angle - 90), int(player_angle + 90))]) gen_pos = vec2d.vec2d(self.generate_radius, 0) gen_pos.rotate(gen_angle) gen_pos = player_pc.pos + gen_pos valid_pos = True for idx, physc in enumerate(phys_comp_list): if physc: collc = coll_comp_list[idx] if physc.pos.get_distance(gen_pos) < collc.radius: valid_pos = False gen_vel = vec2d.vec2d(random.randint(0, 80), random.randint(0, 80)) # create new asteroid if valid_pos: self.manager.create_entity([phys.PhysicsEcsComponent(gen_pos.x, gen_pos.y, mass=100, static=False, vx=gen_vel.x, vy=gen_vel.y), collision.CollisionEcsComponent(radius=14), AsteroidEcsComponent(impact_resistance=50.0, health=100), RenderAsteroidEcsComponent(img.IMG_ASTER)]) entities = self.manager.entities for idx, eid in enumerate(entities): asterc = aster_comp_list[idx] if asterc: physc = phys_comp_list[idx] if physc and player_pc: if player_pc.pos.get_distance(physc.pos) > self.generate_radius: self.manager.mark_entity_for_removal(eid)
def thrust_forward(self, eid): sc = self.manager.get_entity_comp(eid, ShipEcsComponent.name()) if sc.fuel > 0: rsc = self.manager.get_entity_comp(eid, RenderShipEcsComponent.name()) pc = self.manager.get_entity_comp(eid, phys.PhysicsEcsComponent.name()) if not sc or not pc: return dir_radians = math.radians(sc.rotation) dirv = vec2d.vec2d(math.cos(dir_radians), math.sin(dir_radians)) dirv.length = sc.thrust_force sc.fuel -= 1 pc.apply_force(dirv.x, dirv.y) rsc.thrust_started() else: print 'out of fuel'
def get_circle_closest_point(pos, cpos, cradius): dv = math.sqrt(math.pow(cpos.x - pos.x, 2) + math.pow(cpos.y - pos.y, 2)) cx = cpos.x + (cradius * (pos.x - cpos.x) / dv) cy = cpos.y + (cradius * (pos.y - cpos.y) / dv) return vec2d.vec2d(cx, cy)
def update(self, dt): phys_comp_list = self.manager.comps[phys.PhysicsEcsComponent.name()] coll_comp_list = self.manager.comps[CollisionEcsComponent.name()] entities_to_remove = set() # we use this guy to keep track of the collision 'matrix' entity_collision_dict = {} entities = self.manager.entities for idx, eid in enumerate(entities): physc = phys_comp_list[idx] collc = coll_comp_list[idx] if physc == None or collc == None: continue for oidx, oeid in enumerate(entities): if eid == oeid: continue ophysc = phys_comp_list[oidx] ocollc = coll_comp_list[oidx] if ophysc == None or ocollc == None: continue d = physc.pos.get_distance(ophysc.pos) coll_d = collc.radius + ocollc.radius if d <= coll_d: # collision e_coll_list = entity_collision_dict.setdefault(eid, []) if oeid not in e_coll_list: e_coll_list.append(oeid) entity_collision_dict.setdefault(oeid, []).append(eid) overlap = coll_d - d # resolve the collision dir = ophysc.pos- physc.pos if physc.static: dir.length = overlap ophysc.pos = ophysc.pos + dir * 2 elif ophysc.static: dir.length = overlap physc.pos = ophysc.pos + dir * 2 else: dir.length = overlap / 2 physc.pos = physc.pos - dir * 2 ophysc.pos = ophysc.pos + dir * 2 # calculate reflection here ocontact_point = get_circle_closest_point(physc.pos, ophysc.pos, ocollc.radius) normal = vec2d.vec2d(ocontact_point.x - ophysc.pos.x, ocontact_point.y - ophysc.pos.y).normalized() incidence = (physc.vel) - (ophysc.vel) mtotal = physc.mass + ophysc.mass c1 = physc.mass / mtotal c2 = ophysc.mass / mtotal r = incidence - (2 * incidence.dot(normal)) * normal impact_size = (ophysc.vel - physc.vel).length angle = abs(r.get_angle_between(normal)) if angle > 1: #print angle, angle * 0.3 mod = angle * 0.3 if r.length > mod: r.length -= mod else: r.length = 0 #r.length /= (angle * 0.3) # friction jobbie #j = max(-(1 + 0.1) * physc.vel.dot(normal), 0.0) #print j, impact_size #r += normal * j #contact.rigidBody->linearMomentum += j * contact.normal; self.manager.entity_collision(eid, oeid, impact_size, r * c2, CollisionEcsSystem.name(), 'collision') self.manager.entity_collision(oeid, eid, impact_size, ~r * c1, CollisionEcsSystem.name(), 'collision')
def apply_force(self, x, y): force = vec2d.vec2d(x / self.mass, y / self.mass) self.vel = self.vel + force
def update(self, dt): phys_comp_list = self.manager.comps[phys.PhysicsEcsComponent.name()] coll_comp_list = self.manager.comps[CollisionEcsComponent.name()] entities_to_remove = set() # we use this guy to keep track of the collision 'matrix' entity_collision_dict = {} entities = self.manager.entities for idx, eid in enumerate(entities): physc = phys_comp_list[idx] collc = coll_comp_list[idx] if physc == None or collc == None: continue for oidx, oeid in enumerate(entities): if eid == oeid: continue ophysc = phys_comp_list[oidx] ocollc = coll_comp_list[oidx] if ophysc == None or ocollc == None: continue d = physc.pos.get_distance(ophysc.pos) coll_d = collc.radius + ocollc.radius if d <= coll_d: # collision e_coll_list = entity_collision_dict.setdefault(eid, []) if oeid not in e_coll_list: e_coll_list.append(oeid) entity_collision_dict.setdefault(oeid, []).append(eid) overlap = coll_d - d # resolve the collision dir = ophysc.pos - physc.pos if physc.static: dir.length = overlap ophysc.pos = ophysc.pos + dir * 2 elif ophysc.static: dir.length = overlap physc.pos = ophysc.pos + dir * 2 else: dir.length = overlap / 2 physc.pos = physc.pos - dir * 2 ophysc.pos = ophysc.pos + dir * 2 # calculate reflection here ocontact_point = get_circle_closest_point( physc.pos, ophysc.pos, ocollc.radius) normal = vec2d.vec2d(ocontact_point.x - ophysc.pos.x, ocontact_point.y - ophysc.pos.y).normalized() incidence = (physc.vel) - (ophysc.vel) mtotal = physc.mass + ophysc.mass c1 = physc.mass / mtotal c2 = ophysc.mass / mtotal r = incidence - (2 * incidence.dot(normal)) * normal impact_size = (ophysc.vel - physc.vel).length angle = abs(r.get_angle_between(normal)) if angle > 1: #print angle, angle * 0.3 mod = angle * 0.3 if r.length > mod: r.length -= mod else: r.length = 0 #r.length /= (angle * 0.3) # friction jobbie #j = max(-(1 + 0.1) * physc.vel.dot(normal), 0.0) #print j, impact_size #r += normal * j #contact.rigidBody->linearMomentum += j * contact.normal; self.manager.entity_collision( eid, oeid, impact_size, r * c2, CollisionEcsSystem.name(), 'collision') self.manager.entity_collision( oeid, eid, impact_size, ~r * c1, CollisionEcsSystem.name(), 'collision')
def generate_system_data(): # create some working data member_names = [ 'Tamde', 'Yol', 'Trog', 'Mar', 'Een', 'Sila', 'Ado', 'Khem', 'Teim', 'Tamut', 'Beda', 'Ponni' ] member_position_angles = [i for i in xrange(0, 360, 40)] mass_mod = 10000 member_padding = 1000 member_grav_radius = member_padding // 2 satellite_grav_radius = member_grav_radius // 2 satellite_orbit_distance = member_grav_radius // 2 satellite_position_angles = [i for i in xrange(0, 360, 90)] planet_imgs = [img.IMG_P_64_1, img.IMG_P_64_2] moon_imgs = [ img.IMG_M_48_1, ] members = [] # player ship player_ship_data = { 'type': 'ship', 'size': 14, 'mass': 100, 'rotation': 90.0, 'rotation_speed': 6.0, 'thrust_force': 200.0, 'impact_resistance': 50.0, 'fuel': 700, 'passengers': 0, 'health': 350, 'orbit_distance': member_grav_radius * .75, 'orbit_angle': 0, 'orbit_clockwise': False } # sun members.append({ 'x': 0, 'y': 0, 'type': 'sun', 'img': 'sun.png', 'name': 'Sol', 'static': True, 'size': 128, 'mass': 128 * mass_mod, 'grav_radius': member_grav_radius, 'satellites': [ player_ship_data, ] }) crew_to_rescue = 0 #planets distance = 0 num_planets = xrange(0, 7) #7 for _ in num_planets: distance += member_padding planet_name = random.choice(member_names) member_names.remove(planet_name) # generate position pos = vec2d.vec2d(0, distance) angle = random.choice(member_position_angles) pos.rotate(angle) # member satellites satellites = [] num_satellites = xrange(0, 2) satellite_angle_options = satellite_position_angles[:] for _ in num_satellites: satelite_angle = random.choice(satellite_angle_options) satellite_angle_options.remove(satelite_angle) satellites.append({ 'type': 'planet', 'name': 'Satellite', 'img': random.choice(moon_imgs), 'size': 24, 'mass': 24 * mass_mod, 'grav_radius': satellite_grav_radius, 'orbit_distance': satellite_orbit_distance, 'orbit_angle': satelite_angle, 'orbit_clockwise': True }) # add one base satellite satelite_angle = random.choice(satellite_angle_options) satellite_angle_options.remove(satelite_angle) crew = 30 crew_to_rescue += 30 satellites.append({ 'type': 'base', 'name': 'Satellite', 'img': img.IMG_BASE, 'size': 14, 'mass': 300, 'service_radius': 65, 'fuel': True, 'repair': True, 'crew': crew, 'impact_resistence': 70, 'health': 800, 'orbit_distance': satellite_orbit_distance, 'orbit_angle': satelite_angle, 'orbit_clockwise': True }) members.append({ 'x': pos.x, 'y': pos.y, 'type': 'planet', 'img': random.choice(planet_imgs), 'name': planet_name, 'static': True, 'size': 64, 'mass': 64 * mass_mod, 'grav_radius': member_grav_radius, 'satellites': satellites }) data = { 'members': members, 'crew_to_rescue': crew_to_rescue, } return data
def generate_system_data(): # create some working data member_names = ['Tamde', 'Yol', 'Trog', 'Mar', 'Een', 'Sila', 'Ado', 'Khem', 'Teim', 'Tamut', 'Beda', 'Ponni'] member_position_angles = [i for i in xrange(0, 360, 40)] mass_mod = 10000 member_padding = 1000 member_grav_radius = member_padding // 2 satellite_grav_radius = member_grav_radius // 2 satellite_orbit_distance = member_grav_radius // 2 satellite_position_angles = [i for i in xrange(0, 360, 90)] planet_imgs = [img.IMG_P_64_1, img.IMG_P_64_2] moon_imgs = [img.IMG_M_48_1,] members = [] # player ship player_ship_data = {'type': 'ship', 'size': 14, 'mass': 100, 'rotation': 90.0, 'rotation_speed': 6.0, 'thrust_force': 200.0, 'impact_resistance': 50.0, 'fuel': 700, 'passengers': 0, 'health': 350, 'orbit_distance': member_grav_radius * .75, 'orbit_angle': 0, 'orbit_clockwise': False } # sun members.append({'x': 0, 'y':0, 'type': 'sun', 'img': 'sun.png', 'name':'Sol', 'static': True, 'size': 128, 'mass': 128 * mass_mod, 'grav_radius': member_grav_radius, 'satellites': [player_ship_data,] }) crew_to_rescue = 0 #planets distance = 0 num_planets = xrange(0, 7) #7 for _ in num_planets: distance += member_padding planet_name = random.choice(member_names) member_names.remove(planet_name) # generate position pos = vec2d.vec2d(0, distance) angle = random.choice(member_position_angles) pos.rotate(angle) # member satellites satellites = [] num_satellites = xrange(0, 2) satellite_angle_options = satellite_position_angles[:] for _ in num_satellites: satelite_angle = random.choice(satellite_angle_options) satellite_angle_options.remove(satelite_angle) satellites.append({'type': 'planet', 'name':'Satellite', 'img': random.choice(moon_imgs), 'size': 24, 'mass': 24 * mass_mod, 'grav_radius': satellite_grav_radius, 'orbit_distance': satellite_orbit_distance, 'orbit_angle': satelite_angle, 'orbit_clockwise': True }) # add one base satellite satelite_angle = random.choice(satellite_angle_options) satellite_angle_options.remove(satelite_angle) crew = 30 crew_to_rescue += 30 satellites.append({'type': 'base', 'name':'Satellite', 'img': img.IMG_BASE, 'size': 14, 'mass': 300, 'service_radius': 65, 'fuel': True, 'repair': True, 'crew': crew, 'impact_resistence': 70, 'health': 800, 'orbit_distance': satellite_orbit_distance, 'orbit_angle': satelite_angle, 'orbit_clockwise': True }) members.append({'x': pos.x, 'y': pos.y, 'type': 'planet', 'img': random.choice(planet_imgs), 'name': planet_name, 'static': True, 'size': 64, 'mass': 64 * mass_mod, 'grav_radius': member_grav_radius, 'satellites': satellites }) data = { 'members': members, 'crew_to_rescue': crew_to_rescue, } return data