def distance(self, x, y): angle = Vec2D(self.x, self.y).angle((self.x2, self.y2)) offset = Vec2D(self.x, self.y) newEnd = (Vec2D(self.x2, self.y2) - offset).rotate(angle) newPoint = (Vec2D(x, y) - offset).rotate(angle) pointY = max(min(newPoint[1], newEnd[1]),0) return pythag(0, pointY, *newPoint)
def update_particleSpeedAndPosition(self, particle, dt_s): # Чистая результирующая сила на частицу. particle_forces_2d_N = (self.g_2d_mps2 * particle.mass) + ( particle.SprDamp_force_2d_N + particle.jet_force_2d_N + particle.cursorString_spring_force_2d_N + particle.cursorString_particleDrag_force_2d_N + particle.impulse / dt_s) # Ускорение, по закону Ньютона. acceleration = particle_forces_2d_N / particle.mass # Изменение скорости: dv = a * dt # Скорость в конце отметки времени. particle.velocity = particle.velocity + (acceleration * dt_s) # Рассчитывание новой физической позиции частицы, используя скорость в конце отметки времени. # Изменение позиции с помощью скорости: dx = v * dt particle.position_in_meters = particle.position_in_meters + ( particle.velocity * dt_s) # Сбрасывание совокупности силы. particle.SprDamp_force_2d_N = Vec2D(0.0, 0.0) particle.cursorString_spring_force_2d_N = Vec2D(0.0, 0.0) particle.cursorString_particleDrag_force_2d_N = Vec2D(0.0, 0.0) particle.impulse = Vec2D(0.0, 0.0)
def on_mouse_release(self, x, y, button, key_modifiers): if button == arcade.MOUSE_BUTTON_LEFT: self.orb.acc = Vec2D(0, 0) self.buttons_down['lmb'] = False if button == arcade.MOUSE_BUTTON_RIGHT: self.orb.acc = Vec2D(0, 0) self.buttons_down['rmb'] = False
def lineDistance(self, x1, y1, x2, y2, pointX, pointY): angle = Vec2D(x1, y1).angle((x2, y2)) offset = Vec2D(x1, y1) newEnd = (Vec2D(x2, y2) - offset).rotate(angle) newPoint = (Vec2D(pointX, pointY) - offset).rotate(angle) pointY = max(min(newPoint[1], newEnd[1]), 0) return pythag(0, pointY, *newPoint)
def tangent_vector(self,p,orientation): vr = (p - self.pos).normalized() if orientation < 0: return Vec2D(-vr.y,vr.x) else: return Vec2D(vr.y,-vr.x)
def cast(self, minError=1, maxError=500): offset = Vec2D(self.x, self.y) pos = Vec2D(0, 0) distance = self.window.closest(*(offset + pos.rotate(self.angle))) while maxError > distance[0] > minError: pos += Vec2D(0, distance[0]) distance = self.window.closest(*(offset + pos.rotate(self.angle))) return offset + pos.rotate(self.angle)
def traj_from_response(response): traj = [] for w in response: x = float(w[0]) / 1000 y = float(w[1]) / 1000 vx = float(w[2]) / 1000 vy = float(w[3]) / 1000 t = float(w[4]) / 1000 traj.append((Vec2D(x, y), Vec2D(vx, vy), t)) return traj
def update(self, delta_time): ## updating gravitational effects ## forces = [Vec2D(0, 0) for _ in range(len(self.bodies))] for i, bodie in enumerate(self.bodies): for other_bodie in self.bodies: if bodie != other_bodie and not isinstance(other_bodie, Ship): forces[i] += bodie.get_force_applyed(other_bodie, G) for ship in self.ships: for bodie in self.bodies: ship.apply_force_from(bodie, G) ## ############################ ## for i, bodie in enumerate(self.bodies): bodie.apply_force(forces[i]) bodie.update() for ship in self.ships: ship.update() ## calculating collisions and collision effects ## ## Needs Rewrite: potential to break with multiple collisions absorbed = [] for bodie in self.bodies: for other_bodie in self.bodies: if bodie.is_colliding(other_bodie): if bodie.mass > other_bodie.mass: bodie.absorb(other_bodie) absorbed.append(other_bodie) if self.orb == other_bodie: self.orb = bodie for ship in self.ships: if bodie.is_colliding(ship): bodie.absorb(ship) for bodie in absorbed: self.bodies.remove(bodie) ## ########################################## ## ## reset acceleration of all bodies to 0 for next update for bodie in self.bodies: bodie.acc = Vec2D(0, 0) self.apply_button_effects() ## center view-port on selected orb arcade.set_viewport(self.orb.pos.x - self.window_width / 2, self.orb.pos.x + self.window_width / 2, self.orb.pos.y - self.window_height / 2, self.orb.pos.y + self.window_height / 2)
def main(): c1 = Circle(Vec2D(1.5, 1), 0.3) c2 = Circle(Vec2D(0.4, 1.3), 0.3) c3 = Circle(Vec2D(0.2, 0.22), 0.1) c4 = Circle(Vec2D(0.4, 0.6), 0.2) c5 = Circle(Vec2D(1.5, 1), 0.3) c6 = Circle(Vec2D(0.75, 0.5), 0.3) null = Vec2D(0, 0) circles = [c1, c2, c3, c4] start = Vec2D(0.6, 0.9) end = Vec2D(2.4, 0.9) obstacles = [] #clock = pygame.time.Clock() paused = False while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_p: paused = not paused if not paused: screen.fill(black) screen.blit(background, (0, 0)) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('127.0.0.1', 1337)) s.send( json.dumps( to_request(start, null, end, null, 0.05, 120, obstacles))) json_response = json.loads(s.recv(4096).strip()) #print json.dumps(json_response,indent=2) #print traj = traj_from_response(json_response) s.close() draw_env(Environment(Globals.STATIC_OBSTACLES), start, end) draw_path(traj) #print clock.tick() pygame.display.update()
def __init__(self, walls_dic): self.gON_mps2 = Vec2D(-0.0, -9.0) self.gOFF_mps2 = Vec2D(-0.0, -0.0) self.g_2d_mps2 = self.gOFF_mps2 self.g_ON = False self.particles = [] self.controlled_particles = [] self.springs = [] self.walls = walls_dic self.collision_count = 0 self.coef_rest_particle = 0.90 self.coef_rest_table = 0.90 self.color_transfer = False
def __init__(self, screenSize_in_pixels, length_x_in_meters): self.screenSize_in_pixels = Vec2D(screenSize_in_pixels) self.viewOffset_in_pixels = Vec2D(0, 0) self.viewCenter_in_pixels = Vec2D(0, 0) self.viewZoom = 1 self.viewZoom_rate = 0.01 self.time_s = 0 self.clients = {'local': Client(THECOLORS["green"])} self.pixels_to_meters = length_x_in_meters / float( self.screenSize_in_pixels.x) self.meters_to_pixels = (float(self.screenSize_in_pixels.x) / length_x_in_meters)
def calc_string_forces_on_particles(self): # Вычисление струнных сил на выбранную частицу и добавления совокупности, # которая хранится в объекте частицы. # Проверка только выбранной частицы, если она ещё не выбрана. Это удерживает частицу # от смены выбора, если курсор перетащен с частцы if (self.selected_particle == None): if self.buttonIsStillDown: self.selected_particle = space.checkForParticleAtThisPosition( self.cursor_location_in_pixels) else: if not self.buttonIsStillDown: self.selected_particle.selected = False self.selected_particle = None return None # Используйте разницу в dx для расчета силы зацепки, применяемой линией привязи. # Если вы отпустите кнопку мыши после перетаскивания, она будет швырять частицу. # Эта сила привязи будет уменьшаться, когда частица приближается к точке мыши. dx_in_meters = nature.ConvertScreenToWorld( Vec2D(self.cursor_location_in_pixels) ) - self.selected_particle.position_in_meters stringName = "string" + str(self.mouse_button) self.selected_particle.cursorString_spring_force_2d_N += dx_in_meters * self.mouse_strings[ stringName]['k_Npm'] self.selected_particle.cursorString_particleDrag_force_2d_N += ( self.selected_particle.velocity * -1 * self.mouse_strings[stringName]['c_drag'])
def ConvertScreenToWorld(self, point_in_pixels): x_in_meters = (point_in_pixels.x + self.viewOffset_in_pixels.x) / ( self.meters_to_pixels * self.viewZoom) y_in_meters = (self.screenSize_in_pixels.y - point_in_pixels.y + self.viewOffset_in_pixels.y) / (self.meters_to_pixels * self.viewZoom) return Vec2D(x_in_meters, y_in_meters)
def circle_tangents(self,other,invert_second_radius): dx = other.pos.x - self.pos.x dy = other.pos.y - self.pos.y if not invert_second_radius: dr = other.r - self.r else: dr = - other.r - self.r d = sqrt(dx*dx + dy*dy) x = dx/d y = dy/d r = dr/d a1 = r*x - y*sqrt(1 - r*r) b1 = r*y + x*sqrt(1 - r*r) c1 = self.r - (a1*self.pos.x + b1*self.pos.y) a2 = r*x + y*sqrt(1 - r*r) b2 = r*y - x*sqrt(1 - r*r) c2 = self.r - (a2*self.pos.x + b2*self.pos.y) x11 = (b1*(b1*self.pos.x - a1*self.pos.y) - a1*c1) y11 = (a1*(-b1*self.pos.x + a1*self.pos.y) - b1*c1) x12 = (b1*(b1*other.pos.x - a1*other.pos.y) - a1*c1) y12 = (a1*(-b1*other.pos.x + a1*other.pos.y) - b1*c1) x21 = (b2*(b2*self.pos.x - a2*self.pos.y) - a2*c2) y21 = (a2*(-b2*self.pos.x + a2*self.pos.y) - b2*c2) x22 = (b2*(b2*other.pos.x - a2*other.pos.y) - a2*c2) y22 = (a2*(-b2*other.pos.x + a2*other.pos.y) - b2*c2) start1 = Vec2D(x11,y11) end1 = Vec2D(x12,y12) orient11 = orientation(end1,start1,self.pos) orient12 = orientation(start1,end1,other.pos) start2 = Vec2D(x21,y21) end2 = Vec2D(x22,y22) orient21 = orientation(end2,start2,self.pos) orient22 = orientation(start2,end2,other.pos) tan1 = Tangent(start1,self,orient11,end1,other,orient12) tan2 = Tangent(start2,self,orient21,end2,other,orient22) return [tan1,tan2]
def ConvertWorldToScreen(self, point_in_meters): x_in_pixels = (point_in_meters.x * self.meters_to_pixels * self.viewZoom) - self.viewOffset_in_pixels.x y_in_pixels = (point_in_meters.y * self.meters_to_pixels * self.viewZoom) - self.viewOffset_in_pixels.y y_in_pixels = self.screenSize_in_pixels.y - y_in_pixels return Vec2D(x_in_pixels, y_in_pixels, "int").tuple()
def draw(self): topLeft_in_pixels = nature.ConvertWorldToScreen( Vec2D(self.walls['L_m'], self.walls['T_m'])) topRight_in_pixels = nature.ConvertWorldToScreen( Vec2D(self.walls['R_m'] - 0.01, self.walls['T_m'])) botLeft_in_pixels = nature.ConvertWorldToScreen( Vec2D(self.walls['L_m'], self.walls['B_m'] + 0.01)) botRight_in_pixels = nature.ConvertWorldToScreen( Vec2D(self.walls['R_m'] - 0.01, self.walls['B_m'] + 0.01)) pygame.draw.line(surface_window.surface, THECOLORS["orangered1"], topLeft_in_pixels, topRight_in_pixels, 1) pygame.draw.line(surface_window.surface, THECOLORS["orangered1"], topRight_in_pixels, botRight_in_pixels, 1) pygame.draw.line(surface_window.surface, THECOLORS["orangered1"], botRight_in_pixels, botLeft_in_pixels, 1) pygame.draw.line(surface_window.surface, THECOLORS["orangered1"], botLeft_in_pixels, topLeft_in_pixels, 1)
def __init__(self, screen, screen_title): self.screen_width = screen[0] self.screen_height = screen[1] self.UpperRight = nature.ConvertScreenToWorld( Vec2D(self.screen_width, 0)) self.surface = pygame.display.set_mode(screen) self.update_caption(screen_title) self.surface.fill(THECOLORS["black"]) pygame.display.update()
def draw_map(bodies, window_width, window_height): map_shape_list = arcade.ShapeElementList() view = arcade.get_viewport() map_width = window_width / 3.5 map_height = window_height / 3.5 map_padding = window_height / 80 map_center_x = view[1] - (map_width / 2 + map_padding) map_center_y = view[2] + (map_height / 2 + map_padding) #view[0] = left, view[1] = right, view[2] = bottom, view[3] = top rec = arcade.create_rectangle_filled(map_center_x, map_center_y, map_width, map_height, arcade.color.BLACK) rec2 = arcade.create_rectangle_outline(map_center_x, map_center_y, map_width, map_height, arcade.color.WHITE, window_width / 400) map_shape_list.append(rec) map_shape_list.append(rec2) max_mass = 0 cm = None # find_center_of_mass(bodies) for bodie in bodies: if max_mass < bodie.mass: max_mass = bodie.mass cm = bodie.pos max_dist = 1 for bodie in bodies: this_dist = (cm - bodie.pos).get_mag() if max_dist < this_dist: max_dist = this_dist scaler = max_dist / ((map_height - map_padding) / 2) # print(scaler) # scaler = 60 for bodie in bodies: map_pos = (bodie.pos - cm) map_pos.x /= scaler map_pos.y /= scaler map_pos += Vec2D(map_center_x, map_center_y) map_shape_list.append( arcade.create_ellipse_filled(map_pos.x, map_pos.y, window_width / 300, window_width / 300, bodie.color)) # map_shpe_list.append( arcade. ) map_shape_list.draw()
def __init__(self, particle1, particle2, length_in_meters=3.0, strength_Npm=0.5, spring_color=THECOLORS["yellow"], width_in_meters=0.025): self.particle1 = particle1 self.particle2 = particle2 self.particle1particle2_separation_2d_m = Vec2D(0, 0) self.particle1particle2_separation_m = 0 self.particle1particle2_normalized_2d = Vec2D(0, 0) self.length_in_meters = length_in_meters self.strength_Npm = strength_Npm self.damper_Ns2pm2 = 0.5 #5.0 #0.05 #0.15 self.unstretched_width_in_meters = width_in_meters #0.05 self.spring_vertices_in_meters = [] self.spring_vertices_in_pixels = [] self.spring_color = spring_color self.draw_as_line = False
def circle_tangents(self, other, invert_second_radius): dx = other.pos.x - self.pos.x dy = other.pos.y - self.pos.y if not invert_second_radius: dr = other.r - self.r else: dr = -other.r - self.r d = sqrt(dx * dx + dy * dy) x = dx / d y = dy / d r = dr / d a1 = r * x - y * sqrt(1 - r * r) b1 = r * y + x * sqrt(1 - r * r) c1 = self.r - (a1 * self.pos.x + b1 * self.pos.y) a2 = r * x + y * sqrt(1 - r * r) b2 = r * y - x * sqrt(1 - r * r) c2 = self.r - (a2 * self.pos.x + b2 * self.pos.y) x11 = (b1 * (b1 * self.pos.x - a1 * self.pos.y) - a1 * c1) y11 = (a1 * (-b1 * self.pos.x + a1 * self.pos.y) - b1 * c1) x12 = (b1 * (b1 * other.pos.x - a1 * other.pos.y) - a1 * c1) y12 = (a1 * (-b1 * other.pos.x + a1 * other.pos.y) - b1 * c1) x21 = (b2 * (b2 * self.pos.x - a2 * self.pos.y) - a2 * c2) y21 = (a2 * (-b2 * self.pos.x + a2 * self.pos.y) - b2 * c2) x22 = (b2 * (b2 * other.pos.x - a2 * other.pos.y) - a2 * c2) y22 = (a2 * (-b2 * other.pos.x + a2 * other.pos.y) - b2 * c2) tan1 = Tangent(Vec2D(x11, y11), self, Vec2D(x12, y12), other) tan2 = Tangent(Vec2D(x21, y21), self, Vec2D(x22, y22), other) return [tan1, tan2]
def find_center_of_mass(bodies): mass_weighted_average_x = 0 mass_weighted_average_y = 0 total_mass = 0 for bodie in bodies: mass_weighted_average_x += bodie.mass * bodie.pos.x mass_weighted_average_y += bodie.mass * bodie.pos.y total_mass += bodie.mass x_cm = mass_weighted_average_x / total_mass y_cm = mass_weighted_average_y / total_mass return Vec2D(x_cm, y_cm)
def main(): c1 = Circle(Vec2D(1.5,1),0.3) c2 = Circle(Vec2D(0.4,1.3),0.3) c3 = Circle(Vec2D(0.2,0.22),0.1) c4 = Circle(Vec2D(0.4,0.6),0.2) circles = [c1,c2,c3,c4] env = Environment([Obstacle(c1,Vec2D(-0.0001,0)),Obstacle(c2,Vec2D(0,-0.0001)),Obstacle(c3,Vec2D(0.0001,0)),Obstacle(c4,Vec2D(0,0.0001))]) #env = Environment([Obstacle(c1,Vec2D(0.0000,0.0001)),Obstacle(c4,Vec2D(0,-0.0001))]) #env = Environment([Obstacle(c1,Vec2D(0,-0.0001))]) start = Vec2D(0.01,0.01) end = Vec2D(2.99,1.99) path = env.path(start,end) clock = pygame.time.Clock() paused = False while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_p: paused = not paused if not paused: screen.fill(black) env.update() draw_env(env,start,end) draw_path(env.path(start,end)) #print clock.tick() pygame.display.update()
def distance(self, x, y): if self.w == self.h: return pythag(x, y, self.x + self.w / 2, self.y + self.w / 2) - self.w / 2 else: #TODO: make this actually work properly # fociDistance = (max((self.w / 2) ** 2, (self.h / 2) ** 2) - min((self.w / 2) ** 2, # (self.h / 2) ** 2)) ** 0.5 # length = fociDistance*2+self.w-(fociDistance*2) angle = -Vec2D(self.x + self.w / 2, self.y + self.h / 2).angle( (x, y)) l = sqrt(1 / ((sin(radians(angle)) / self.w * 2)**2 + (cos(radians(angle)) / self.h * 2)**2)) lx = self.x + self.w / 2 + l * sin(radians(angle)) ly = self.y + self.h / 2 + l * cos(radians(angle)) return pythag(lx, ly, x, y)
def checkForParticleAtThisPosition(self, x_in_pixels_or_tuple, y_in_pixels=None): if y_in_pixels == None: self.x_in_pixels = x_in_pixels_or_tuple[0] self.y_in_pixels = x_in_pixels_or_tuple[1] else: self.x_in_pixels = x_in_pixels_or_tuple self.y_in_pixels = y_in_pixels test_position_m = nature.ConvertScreenToWorld( Vec2D(self.x_in_pixels, self.y_in_pixels)) for particle in self.particles: vector_difference_m = test_position_m - particle.position_in_meters # Используется квадрат длины для скорости(избегаем квадратного корня) mag_of_difference_m2 = vector_difference_m.length_squared() if mag_of_difference_m2 < particle.r_in_meters**2: particle.selected = True return particle return None
def __init__(self, width, height, title): super().__init__(WIDTH, HEIGHT, 'Space?') arcade.set_background_color(arcade.color.BLACK) self.bodies = [] self.ships = [] self.orb = None self.dest = None self.center_mass = None # self.stars = make_stars() self.buttons_down = {'rmb': False, 'lmb': False, 'v': False} self.orb_index = 0 self.dest_index = 0 self.mouse_pos = Vec2D(0, 0) self.window_width = WIDTH self.window_height = HEIGHT self.zoom_speed = 20 self.map_on = True
def handle(self): try: data = json.loads(self.request.recv(2048).strip()) start_info = data[0] end_info = data[1] delta_t = float(data[2]) / 1000 #ms -> s nb_of_waypoints = data[3] obstacles = data[4] start = Vec2D( float(start_info[0]) / 1000, float(start_info[1]) / 1000) v_start = Vec2D( float(start_info[2]) / 1000, float(start_info[3]) / 1000) end = Vec2D(float(end_info[0]) / 1000, float(end_info[1]) / 1000) v_end = Vec2D(0, 0) obstacle_list = [] for o in obstacles: pos = Vec2D(float(o[0]) / 1000, float(o[1]) / 1000) speed = Vec2D(float(o[2]) / 1000, float(o[3]) / 1000) r = float(o[4]) / 1000 obstacle_list.append( Obstacle(Circle(pos, r + Globals.ROBOT_RADIUS), speed)) traj = trajectory(start, v_start, end, v_end, delta_t, obstacle_list)[:nb_of_waypoints] response = [] for w in traj: pos = w[0] x = int(pos.x * 1000) y = int(pos.y * 1000) v = w[1] vx = int(v.x * 1000) vy = int(v.y * 1000) t = int(w[2] * 1000) response.append([x, y, vx, vy, t]) self.request.sendall(json.dumps(response).strip()) except Exception, e: print "Exception wtf?", e
def __init__(self, position_in_meters, r_in_meters, particle_density, particle_color=THECOLORS["grey"]): self.r_in_meters = r_in_meters self.r_in_px = int( round(nature.pixels_from_meters(self.r_in_meters * nature.viewZoom))) self.particle_density = particle_density # масса на единицу площади self.mass = self.particle_density * math.pi * self.r_in_meters**2 self.position_in_meters = position_in_meters self.velocity = Vec2D(0.0, 0.0) self.SprDamp_force_2d_N = Vec2D(0.0, 0.0) self.jet_force_2d_N = Vec2D(0.0, 0.0) self.cursorString_spring_force_2d_N = Vec2D(0.0, 0.0) self.cursorString_particleDrag_force_2d_N = Vec2D(0.0, 0.0) self.impulse = Vec2D(0.0, 0.0) self.color = particle_color
def check_for_collisions(self): for i, particle in enumerate(self.particles): # Проверка верхней, нижней стенки. if (((particle.position_in_meters.y - particle.r_in_meters) < self.walls["B_m"]) or ((particle.position_in_meters.y + particle.r_in_meters) > self.walls["T_m"])): if self.correct_for_wall_penetration: if (particle.position_in_meters.y - particle.r_in_meters) < self.walls["B_m"]: penetration_y_in_meters = self.walls["B_m"] - ( particle.position_in_meters.y - particle.r_in_meters) particle.position_in_meters.y += 2 * penetration_y_in_meters if (particle.position_in_meters.y + particle.r_in_meters) > self.walls["T_m"]: penetration_y_in_meters = ( particle.position_in_meters.y + particle.r_in_meters) - self.walls["T_m"] particle.position_in_meters.y -= 2 * penetration_y_in_meters particle.velocity.y *= -1 * self.coef_rest_table # Проверка боковых стенок. if (((particle.position_in_meters.x - particle.r_in_meters) < self.walls["L_m"]) or ((particle.position_in_meters.x + particle.r_in_meters) > self.walls["R_m"])): if self.correct_for_wall_penetration: if (particle.position_in_meters.x - particle.r_in_meters) < self.walls["L_m"]: penetration_x_in_meters = self.walls["L_m"] - ( particle.position_in_meters.x - particle.r_in_meters) particle.position_in_meters.x += 2 * penetration_x_in_meters if (particle.position_in_meters.x + particle.r_in_meters) > self.walls["R_m"]: penetration_x_in_meters = ( particle.position_in_meters.x + particle.r_in_meters) - self.walls["R_m"] particle.position_in_meters.x -= 2 * penetration_x_in_meters particle.velocity.x *= -1 * self.coef_rest_table # Столкновение с другими частицами. for otherparticle in self.particles[i + 1:]: # Проверка на прикрывание частиц друг с другом. # Параллельно нормальному particle_to_particle_in_meters = otherparticle.position_in_meters - particle.position_in_meters # ПАралелльно касательной tanget_p_to_p_in_meters = Vec2D.rotate90( particle_to_particle_in_meters) p_to_p_in_meters2 = particle_to_particle_in_meters.length_squared( ) # Проверка быстрее, если избегать квадратных корней if (p_to_p_in_meters2 < (particle.r_in_meters + otherparticle.r_in_meters)**2): self.collision_count += 1 # Используется ветор p_to_p(между двумя сталкивающимися частицами) в качестве цели проекции # для нормального расчета # Вычислить компоненты скорости вдоль и перпендикулярно нормали. particle_normal = particle.velocity.projection_onto( particle_to_particle_in_meters) particle_tangent = particle.velocity.projection_onto( tanget_p_to_p_in_meters) otherparticle_normal = otherparticle.velocity.projection_onto( particle_to_particle_in_meters) otherparticle_tangent = otherparticle.velocity.projection_onto( tanget_p_to_p_in_meters) relative_normal_velocity = otherparticle_normal - particle_normal if self.correct_for_particle_penetration: # Отступы в общей сложности 2х проникновений по нормали. Количество отступов для каждой частицы # зависит от скорости каждой частицы 2DT, где DT - время проникновения. DT рассчитывается # из относительной скорости и расстояния проникновения. relative_normal_spd_mps = relative_normal_velocity.length( ) penetration_m = ( particle.r_in_meters + otherparticle.r_in_meters) - p_to_p_in_meters2**0.5 if (relative_normal_spd_mps > 0.00001): penetration_time_s = penetration_m / relative_normal_spd_mps penetration_time_scaler = 1.0 # Это может быть полезно для тестирования, чтобы усилить и увидеть коррецию. # Сначала перевенуть две щайбы к точке их столкновения по траектории их входящей траектории. particle.position_in_meters = particle.position_in_meters - ( particle_normal * (penetration_time_scaler * penetration_time_s)) otherparticle.position_in_meters = otherparticle.position_in_meters - ( otherparticle_normal * (penetration_time_scaler * penetration_time_s)) # Рассчитывание скорости по нормали ПОСЛЕ столкновения. Используется CR(коэффициент возвращения) # лучше всего 1, чтобы избежать липкости. CR_particle = 1 particle_normal_AFTER_mps, otherparticle_normal_AFTER_mps = self.AandB_normal_AFTER_Calculation( particle_normal, particle.mass, otherparticle_normal, otherparticle.mass, CR_particle) # Наконец, пройти ещё один раз по величине времени проникновения, используя эти скорости ПОСЛЕ столкновения. # Это поместит частицу туда, где она должна бы была быть в момент столкновения. particle.position_in_meters = particle.position_in_meters + ( particle_normal_AFTER_mps * (penetration_time_scaler * penetration_time_s)) otherparticle.position_in_meters = otherparticle.position_in_meters + ( otherparticle_normal_AFTER_mps * (penetration_time_scaler * penetration_time_s)) else: pass # Присвоить скорости ПОСЛЕ (используя фактический CR) частице для использования в следуюзем расчете кадра. CR_particle = self.coef_rest_particle particle_normal_AFTER_mps, otherparticle_normal_AFTER_mps = self.AandB_normal_AFTER_Calculation( particle_normal, particle.mass, otherparticle_normal, otherparticle.mass, CR_particle) # Теперь, когда закончили использовать текущие значения, установите их для вновь рассчитанных AFTER. particle_normal, otherparticle_normal = particle_normal_AFTER_mps, otherparticle_normal_AFTER_mps # Сложение компонентов, чтобы получить векторы общей скорости для каждой частицы. particle.velocity = particle_normal + particle_tangent otherparticle.velocity = otherparticle_normal + otherparticle_tangent
def get_local_user_input(self): local_user = self.clients['local'] # Get all the events since the last call to get(). for event in pygame.event.get(): if (event.type == pygame.QUIT): sys.exit() elif (event.type == pygame.KEYDOWN): if (event.key == K_ESCAPE): sys.exit() elif (event.key == K_1): return 1 elif (event.key == K_2): return 2 elif (event.key == K_3): return 3 elif (event.key == K_4): return 4 elif (event.key == K_5): return 5 elif (event.key == K_6): return 6 elif (event.key == K_7): return 7 elif (event.key == K_8): return 8 elif (event.key == K_9): return 9 elif (event.key == K_0): return 0 elif (event.key == K_c): # Toggle color option. space.color_transfer = not space.color_transfer elif (event.key == K_f): for Particle in space.particles: Particle.velocity = Vec2D(0, 0) elif (event.key == K_g): if space.g_ON: space.g_2d_mps2 = space.gOFF_mps2 space.coef_rest_Particle = 1.00 space.coef_rest_table = 1.00 else: space.g_2d_mps2 = space.gON_mps2 space.coef_rest_Particle = 0.90 space.coef_rest_table = 0.90 space.g_ON = not space.g_ON print("g", space.g_ON) elif (event.key == K_F2): # Toggle menu on/off pass # Zoom keys elif (event.key == K_b): local_user.key_b = 'D' elif (event.key == K_n): local_user.key_n = 'D' elif (event.key == K_m): local_user.m = 'D' elif (event.key == K_h): local_user.key_h = 'D' # Penetration correction elif (event.key == K_p): space.correct_for_particle_penetration = not space.correct_for_particle_penetration else: return "nothing set up for this key" elif (event.type == pygame.KEYUP): # Zoom keys if (event.key == K_b): local_user.key_b = 'U' elif (event.key == K_n): local_user.key_n = 'U' elif (event.key == K_m): local_user.key_m = 'U' elif (event.key == K_h): local_user.key_h = 'U' elif event.type == pygame.MOUSEBUTTONDOWN: local_user.buttonIsStillDown = True (button1, button2, button3) = pygame.mouse.get_pressed() if button1: local_user.mouse_button = 1 elif button2: local_user.mouse_button = 2 elif button3: local_user.mouse_button = 3 else: local_user.mouse_button = 0 elif event.type == pygame.MOUSEBUTTONUP: local_user.buttonIsStillDown = False local_user.mouse_button = 0 # In all cases, pass the event to the Gui. #app.event(event) if local_user.buttonIsStillDown: # This will select a Particle when the Particle runs into the cursor of the mouse with it's button still down. local_user.cursor_location_in_pixels = ( mouseX, mouseY) = pygame.mouse.get_pos()
def create(user_input): surface_window.update_caption("Platform" + str(user_input)) if user_input == 1: space.particles.append( Particle(Vec2D(2.5, 7.5), 0.25, 0.3, THECOLORS["orange"])) space.particles.append(Particle(Vec2D(6.0, 2.5), 0.45, 0.3)) space.particles.append(Particle(Vec2D(7.5, 2.5), 0.65, 0.3)) space.particles.append(Particle(Vec2D(2.5, 5.5), 1.65, 0.3)) space.particles.append(Particle(Vec2D(7.5, 7.5), 0.95, 0.3)) elif user_input == 4: spacing_factor = 1.0 grid_size = 9, 6 #9,6 for j in range(grid_size[0]): for k in range(grid_size[1]): if ((j, k) == (2, 2)): space.particles.append( Particle( Vec2D(spacing_factor * (j + 1), spacing_factor * (k + 1)), 0.25, 5.0, THECOLORS["orange"])) else: space.particles.append( Particle( Vec2D(spacing_factor * (j + 1), spacing_factor * (k + 1)), 0.25, 5.0)) elif user_input == 3: spacing_factor = 1.5 grid_size = 5, 3 for j in range(grid_size[0]): for k in range(grid_size[1]): if ((j, k) == (2, 2)): space.particles.append( Particle( Vec2D(spacing_factor * (j + 1), spacing_factor * (k + 1)), 0.55, 0.3, THECOLORS["orange"])) else: space.particles.append( Particle( Vec2D(spacing_factor * (j + 1), spacing_factor * (k + 1)), 0.55, 0.3)) elif user_input == 2: spacing_factor = 2.0 grid_size = 4, 2 for j in range(grid_size[0]): for k in range(grid_size[1]): if ((j, k) == (1, 1)): space.particles.append( Particle( Vec2D(spacing_factor * (j + 1), spacing_factor * (k + 1)), 0.75, 0.3, THECOLORS["orange"])) else: space.particles.append( Particle( Vec2D(spacing_factor * (j + 1), spacing_factor * (k + 1)), 0.75, 0.3)) elif user_input == 6: space.particles.append(Particle(Vec2D(2.00, 3.00), 0.65, 0.3)) space.particles.append(Particle(Vec2D(3.50, 4.50), 0.65, 0.3)) space.particles.append(Particle(Vec2D(5.00, 3.00), 0.65, 0.3)) space.particles.append(Particle(Vec2D(3.50, 7.00), 0.95, 0.3)) spring_strength_Npm2 = 200.0 spring_length_in_meters = 2.5 spring_width_in_meters = 0.07 space.springs.append( Spring(space.particles[0], space.particles[1], spring_length_in_meters, spring_strength_Npm2, width_in_meters=spring_width_in_meters)) space.springs.append( Spring(space.particles[1], space.particles[2], spring_length_in_meters, spring_strength_Npm2, width_in_meters=spring_width_in_meters)) space.springs.append( Spring(space.particles[2], space.particles[0], spring_length_in_meters, spring_strength_Npm2, width_in_meters=spring_width_in_meters)) elif user_input == 5: space.particles.append(Particle(Vec2D(2.00, 3.00), 0.4, 0.3)) space.particles.append(Particle(Vec2D(3.50, 4.50), 0.4, 0.3)) spring_strength_Npm2 = 20.0 spring_length_in_meters = 1.5 space.springs.append( Spring(space.particles[0], space.particles[1], spring_length_in_meters, spring_strength_Npm2, width_in_meters=0.2)) else: print("Nothing set up for this key.")