def _attack(self,a,b): #Расчёт того, насколько глубоко проник удар I.3 OO = Vector(b.pos[0].x-a.pos[0].x, b.pos[0].y-a.pos[0].y, isPolar = False) # Вектор, соединяющий центры ботов at = Vector(a.radius + a._attack * a._attack_range * a.get_strong() * a.radius, a.pos[1], isPolar = True) #вектор атаки if abs(abs_angl(at.phi - OO.phi)) < pi / 2: ah = Vector(cos(at.phi - OO.phi)*OO.r, at.phi, isPolar = True) # вектор до высоты, опущенной из центра b f_at = at.r-ah.r # первая часть проникновения OH = (ah - OO).r # длинна высота из центра b if OH < b.radius: BH = sqrt(b.radius*b.radius - OH*OH) f_at += BH if f_at > 0: write_inf("Attack: %d --> %d, by Str %.3f" %(a._id,b._id,f_at)) if b.status != 0: f_at *= a._attack * a.get_strong() / a.radius #вычисляем силу атаки if BH > 0.001: # вычисляем угловое ускорение omega = f_at * sin(atan(OH/BH)) # учитываем энергию a и силу удара else: omega = 0 b.energy (- f_at) b._add_accel((OO.one() * f_at, omega)) #отталкиваем и крутим противника return f_at return 0
def subtractspeed(self): self.hook.vel = Vector(0, -1)
def addspeed(self): self.hook.vel = Vector(0, 1)
def within(self, pos): return (Vector.fTuple(pos) - self.pos).mag() <= self.r
def mouse(position): global ball if ball.within(position): ball = Ball(True) else: ball = Ball(True, Vector.fTuple(position))
def within(self, pos): return (Vector.fTuple(pos) - self.pos).mag() <= self.r def collides(self, rect: Rect): dx = min(abs(self.pos.x - rect.min.x), abs(self.pos.x - rect.max.x)) dy = min(abs(self.pos.y - rect.min.y), abs(self.pos.y - rect.max.y)) mid = (rect.max - rect.min) / 2 + rect.min - self.pos return not (dx * dx + dy * dy < self.r * self.r or (dx < self.r or dy < self.r) or (abs(mid.x) < rect.width / 2 and abs(mid.y) < rect.height / 2)) #stage = Rect(Vector(10,10),WIDTH-20,HEIGHT-20) stage = Rect(Vector(0, 0), WIDTH, HEIGHT) ball = Ball(True) def draw(canvas): ball.update(1 / 60) ball.draw(canvas) def mouse(position): global ball if ball.within(position): ball = Ball(True) else: ball = Ball(True, Vector.fTuple(position))
def __init__(self, pos: Vector, width, height): self.min = pos self.max = pos + Vector(width, height) self.width = width self.height = height
# next time step! t = t + dt print("Simulation ran for {} seconds".format(time.time()-start)) return time_list, altitude_list, drag_list, velocity_list, phi_list, thrust_list, mass_list recalculate = True earth = Earth() if recalculate: # 8000kg to LEO please. rocket = AtlasV401(8.0e3, Vector([0.0, earth.radius, 0.0]) ) rocket.velocity = earth.surface_speed(rocket.position) time_list, altitude_list, drag_list, velocity_list, phi_list, thrust_list, mass_list = run_simulation(earth, rocket, 150e3) np.savetxt('launch.txt', np.c_[time_list, altitude_list, drag_list, velocity_list, phi_list, thrust_list, mass_list], header='time, alt, drag, velocity, phi, thrust, mass_list', delimiter=',') altitude_list = np.array(altitude_list) phi_list = np.array(phi_list) else: C = np.loadtxt('launch.txt', delimiter=',') time_list = C[:,0] altitude_list = C[:,1] drag_list = C[:,2] velocity_list = C[:,3] phi_list = C[:,4] thrust_list = C[:,5] mass_list = C[:,6]
def run_simulation(body, rocket, target_orbit): # Time t = 0.0 # Our step size dt = 0.1 time_list = [] altitude_list = [] phi_list = [] drag_list = [] thrust_list = [] velocity_list = [] mass_list = [] start = time.time() rocket.throttle = 1.0 # Let's run our simulation for i in range(75000): # gravity depends on altitude! A_gravity = body.accelleration(rocket.position) # Valid up to 2500,000 meters P0, density = body.air_pressure_and_density(rocket.position) # AUTO PILOT # really crude pitch control. Once above target_orbit. start pushing along the surface of the earth # First find orientation of the rocket. We assume this is always # along the surface of the earth, which is the tangent of the # position vector. orientation = Vector([-rocket.position[1], rocket.position[0],0]) # In order to rotate the force vector 'upwards' a certain degree # we need to find the rotation axis. This is the vector orthogonal # to the position and the orientation. rotation_axis = rocket.position.cross( orientation ).normalize() # High tech auto pilot # Straight up first, then abruptly point force vector along the # surface of the earth at 200km up. Then when orbital velocity is # acchieved power down. delta = 1.0 if rocket.position.magnitude > body.radius + 1e3: delta = 0.5 if rocket.position.magnitude > body.radius + 200e3: delta = 0.1 # should really test for velocity parallel with Earth. if rocket.velocity.magnitude > 8672.0: rocket.throttle = 0.0 # Negative rotation means point the force vector out from earth # along the surface. orientation.rotate( - delta * math.pi/2.0, rotation_axis ) rocket.set_orientation(orientation.normalize()) # Force from rocket thurst depends on altitude F_rocket = rocket.thrust(P0) # Force from drag due to atmosphere F_drag = rocket.drag(density) # Force from Gravity F_gravity = A_gravity * rocket.mass() # Make sure our airframe can handle! F_rocket_mag = F_rocket.magnitude F_drag_mag = F_drag.magnitude F_gravity_mag = F_gravity.magnitude force_mag_list = [F_rocket_mag, F_drag_mag, F_gravity_mag] # if the drag magnitude becomes too big, the airframe will break. maxForce = sum( force_mag_list ) if ( maxForce > rocket.max_forces ): print("R.U.D. Rapid Unscheduled Dissambly, too much forces, your rocket broke up in mid flight, iteration {}".format(i)) print("velocity={} altitude={}, max_force={}, force_list={} delta={}".format(rocket.velocity, rocket.position.magnitude, maxForce, force_mag_list, delta)) break # Sum Forces: Weight, Rocket Thrust and Drag in 3 dimensions. Fs = F_rocket + F_drag + F_gravity dv = Fs * (dt / rocket.mass()) # Time step! rocket.velocity += dv rocket.position += rocket.velocity * dt # did we make it back to terra firma? # hope we are going slow. if rocket.position.magnitude < body.radius - 1: print("Current Forces = {}".format(force_mag_list)) if rocket.velocity.magnitude > 5: print("R.U.D. Rapid Unscheduled Dissambly, welcome home!") else: print("Level: Musk, Mars is next") break # debug print if i%5000==0: print("velocity={} pos={}, drag={} delta={}".format(rocket.velocity, rocket.position.magnitude, F_drag, delta)) # step the rocket time ahead, this burns the fuel and potentially does stage sep. rocket.time_step(dt, t) # keep a list of maxForce and position so we can plot. time_list.append(t) drag_list.append( ( F_drag_mag ) / 1000.0 ) thrust_list.append( (F_rocket_mag ) / 1000.0 ) altitude_list.append((rocket.position.magnitude - body.radius ) / 1000.0) phi_list.append( 180.0 * rocket.position.phi / math.pi ) velocity_list.append( rocket.velocity.magnitude ) mass_list.append(rocket.mass()) # next time step! t = t + dt print("Simulation ran for {} seconds".format(time.time()-start)) return time_list, altitude_list, drag_list, velocity_list, phi_list, thrust_list, mass_list
def draw(self, canvas): self.update() for ball in self.balls: ball.draw(canvas) for wall in self.walls: wall.draw(canvas) # The canvas dimensions CANVAS_WIDTH = 600 CANVAS_HEIGHT = 400 # Creating the objects84 ba = Ball(Vector(200, 200), Vector(0, 0), 20, 10, 'blue', True) bb = Ball(Vector(220, 200), Vector(-1, -1), 20, 10, 'green') bc = Ball(Vector(100, 100), Vector(2, 3), 50, 10, 'purple') bd = Ball(Vector(300, 200), Vector(0, 0), 20, 10, 'blue', True) be = Ball(Vector(400, 100), Vector(0, 0), 50, 10, 'blue', True) bf = Ball(Vector(500, 200), Vector(0, 0), 30, 10, 'blue', True) bg = Ball(Vector(1500, 100), Vector(2, 3), 20, 10, 'orange') wt = Wall(10, 5, 'red', "t") wb = Wall(CANVAS_HEIGHT - 10, 5, 'red', "b") wl = Wall(10, 5, "red", "l") wr = Wall(CANVAS_WIDTH - 10, 5, "red", "r") i = Interaction([wt, wb, wl, wr], [ba, bb, bc, bd, be, bf, bg]) # Create a frame and assign callbacks to event handlers frame = simplegui.create_frame("ball-wall", CANVAS_WIDTH, CANVAS_HEIGHT)
def mouse(position): global ball if ball.within(position): ball.vel = (Vector.fTuple(position)-ball.pos)*50 else: ball = Ball(True,Vector.fTuple(position))
class Rocket: """ Rocket Constructor takes a list of stages Rocket currently is simulated as a point mass. Real geometry will be later. Only simple stacked stages for now. Side boosters in next iteration. max_force = maximum force the airframe can handle. position = cartesian coordinates ( body center is 0,0 ) velocity = orientation, please face rocket pointing up! """ def __init__(self, stages, max_force, position, orientation = None): self.__stages = stages self.__current_stage = 0 self.__max_force = max_force self.__position = position if orientation == None: # pick orientation orthogonal to surface. self.__orientation = self.__position.deepcopy().normalize() else: self.__orientation = orientation self.__velocity = Vector() self.__drag = Vector() self.__thrust = Vector() self.__throttle = 0.0 @property def max_forces(self): return self.__max_force @property def position(self): return self.__position @position.setter def position(self, value): self.__position = value @property def velocity(self): return self.__velocity @velocity.setter def velocity(self, value): self.__velocity = value def drag_coefficient(self): # really this is dependent on velocity and vehicle configuration # see https://space.stackexchange.com/questions/12649 return 0.30 def drag(self, atmosphere_mass_density): # find the wides part of the rocket and # use that for drag calculations max_drag_surface = 0.0 for stage in self.__stages: if not stage.jettisoned and stage.drag_surface >= max_drag_surface: max_drag_surface = stage.drag_surface # Get velocity velocity = self.__velocity.magnitude # No speed, no drag! if ( velocity == 0.0 ): self.__drag.zero() return self.__drag # Calculate drag depends on atmosphere of course f = -0.5 * atmosphere_mass_density * velocity * velocity * self.drag_coefficient() * max_drag_surface # Force is directed against the velocity vector. return self.__drag.assign(self.velocity).mult(f / velocity) def mass(self): mass = 0.0 for stage in self.__stages: if not stage.jettisoned: mass += stage.mass return mass def thrust(self, p_external): # Only the lowest stage can be active at any time for now. # Once we get multiple stages running at the same time # this will change a bit. stage = self.__stages[self.__current_stage] if stage.propellant_mass <= 0.0: self.__thrust.zero() return self.__thrust F = stage.thrust(p_external) return self.__thrust.assign(self.__orientation).mult(F) def time_step(self, dt, t): stage = self.__stages[self.__current_stage] propellant_left = stage.burn(dt) if propellant_left <= 0.0 and stage.jettison_after_use and self.__current_stage < len(self.__stages) - 1: print("Staging! {} jettisoning {}, next stage = {}".format(t, self.__stages[self.__current_stage].name, self.__stages[self.__current_stage+1].name)) self.__current_stage = self.__current_stage + 1 stage.jettisoned = True self.__stages[self.__current_stage].throttle = self.__throttle print("Force from stage {} = {}".format(self.__stages[self.__current_stage].name, self.__stages[self.__current_stage].thrust(0.0))) @property def throttle(self): return self.__throttle @throttle.setter def throttle(self, value): self.__throttle = value stage = self.__stages[self.__current_stage] stage.throttle = value # Once we go away from point source we can calculate # orientation based on forces. For now fake it! def set_orientation(self, orientation): self.__orientation = orientation
def __init__(self, pos): self.pos = pos self.url = "https://raw.githubusercontent.com/CougarTasker/twenty-four/master/proto/images/Fishing%20hook.jpeg" self.img = simplegui.load_image(self.url) self.ratio = 1 / 46 self.vel = Vector()
def drawheart(self, canvas, img, i): canvas.draw_image(img, self.cen, self.dim, (self.pos + Vector(self.pading, self.pading) + self.offset * i).get_p(), self.draw_dim)
def draw(self, canvas): self.update() for ball in self.balls: ball.draw(canvas) for wall in self.walls: wall.draw(canvas) # The canvas dimensions CANVAS_WIDTH = 600 CANVAS_HEIGHT = 400 # Creating the objects84 ba = Ball(Vector(200, 200), Vector(2, -1), 20, 50, 'blue', True) bb = Ball(Vector(200.1, 200), Vector(-1, -1), 20, 50, 'green') #bc = Ball(Vector(100,100), Vector(2,3), 20, 50, 'purple') bd = Ball(Vector(300, 200), Vector(2, -1), 20, 50, 'blue', True) be = Ball(Vector(400, 200), Vector(2, -1), 20, 10, 'blue', True) bf = Ball(Vector(500, 200), Vector(2, -1), 30, 50, 'blue', True) wt = Wall(10, 5, 'red', "t") wb = Wall(CANVAS_HEIGHT - 10, 5, 'red', "b") wl = Wall(10, 5, "red", "l") wr = Wall(CANVAS_WIDTH - 10, 5, "red", "r") i = Interaction([wt, wb, wl, wr], [ba, bb, bd, be, bf]) # Create a frame and assign callbacks to event handlers frame = simplegui.create_frame("ball-wall", CANVAS_WIDTH, CANVAS_HEIGHT) frame.set_draw_handler(i.draw)
def fromstring(string): vals = string[1:len(string) - 1].rsplit(",") return Line(Vector.fromstring(vals[0]), Vector.fromstring(vals[1]))