def impulse(self, force, pos=None): #change in velo = impulse / mass if (pos is None): pos = self.pos self.velo += Vector2(force[0], force[1]) / self.mass #self.velo += force/self.mass; # think these r both V2s now? self.angularVelo += Vector2.cross(pos - self.pos, force) / self.momI
def impulse(self, imp, pos=None): self.vel += imp / self.mass if pos is None: pos = self.pos else: self.avel += Vector2.cross(pos - self.pos, imp) / self.momi # center of rotation = self.pos # angular velocity = w = self.avel # angle = theta = self.angle (radians) # moment of inertia (angular mass) = I = self.momi # torque T = self.torque = 0 (scalar) # need to add rotational motion to the update function # delta self.avel = t/self.momi * dt # delta self.angle = self.avel * dt # also clear the torque in clear_force() # def world(self, local) # rotated = rotated_rad() # return self.pos + rotated # def local(self, world) # return local_coordinate # point = pos + offset.roated_rad(angle) # def rotated_rad(angle) # rotated = Vector2(cosangle * offset.x - sinangle * offset.y, sinangle * offset.x + cosangle * offset.y) # return rotated
def addForce(self, force, pos=None): self.force += force if (pos is None): pos = self.pos self.torque = Vector2.cross( pos - self.pos, force ) # r = displacement to obj, and f = where force is being applied
def __init__(self, density=1, localOffsets=[], pos=[0, 0], value=1, **kwargs): self.value = value # for loop to set localOffsets #print("implement whatever logic is happening ") #calculate mass Triange, Inertia Triangle, massT times CenterMass Triangle #calculate M * I * R #adjust center and I #mass = density * area of Triangle #break all of our local offsets down into sub triangles????? #localOffsets=[[0,0], [100, 0], [100,20], [0,20]] # point1= offset[i] , point2= offset[i+1] , point Center = pos.center? even tho its not passed in totalMass = 0 totalMomi = 0 SumCenterMass = pygame.Vector2(0) for i in range(len(localOffsets)): #points are actually sides becuz local origin is zero zero point1 = Vector2( localOffsets[i - 1] ) # PYTHON WILL GRAB THE LAST INDEX CUZ ITS WEIRD, so this is desired point2 = Vector2(localOffsets[i]) triangleMass = (density * (0.5 * Vector2.cross(point2, point1))) totalMass += triangleMass triangleMomi = (triangleMass / 6) * ( point1.magnitude_squared() + point2.magnitude_squared() + pygame.Vector2.dot(point1, point2)) totalMomi += triangleMomi triangleCenterMass = (1 / 3) * (point1 + point2) SumCenterMass += triangleCenterMass * triangleMass centerOfMassActual = SumCenterMass / totalMass newOffsets = [] for offset in localOffsets: newOffsets.append(offset - centerOfMassActual) #print(f"newOffset: {offset - centerOfMassActual}") newPos = pos + centerOfMassActual momiCentered = totalMomi - totalMass * centerOfMassActual.magnitude_squared( ) #print(f"TotalMass= {totalMass} , centerOfMassActual= {centerOfMassActual} , momiCentered={momiCentered}") super().__init__(mass=totalMass, momentInertia=momiCentered, pos=newPos, localOffsets=newOffsets, **kwargs)
def __init__(self, density=1, pos=[0, 0], offsets=[], **kwargs): sides = [] for o in offsets: sides.append(Vector2(o)) polygon_mass_of_center_of_mass = Vector2(0) total_polygon_mass = 0 total_polygon_momi = 0 for i in range(len(sides)): triangle_area = (Vector2.cross(sides[i], sides[i - 1])) / 2 triangle_mass = density * triangle_area total_polygon_mass += triangle_mass triangle_momi = triangle_mass / 6 * ( sides[i - 1].magnitude()**2 + sides[i].magnitude()**2 + Vector2.dot(sides[i - 1], sides[i])) total_polygon_momi += triangle_momi triangle_mass_of_center_of_mass = triangle_mass * (1 / 3) * ( sides[i - 1] + sides[i]) polygon_mass_of_center_of_mass += triangle_mass_of_center_of_mass polygon_center_of_mass = polygon_mass_of_center_of_mass / total_polygon_mass # move origin to center of mass new_offsets = [] for o in offsets: new_offsets.append(o - polygon_center_of_mass) new_pos = pos + polygon_center_of_mass momi_center_of_mass = total_polygon_momi - ( total_polygon_mass * polygon_center_of_mass.magnitude()**2) # call superclass constructor super().__init__(mass=total_polygon_mass, momi=momi_center_of_mass, pos=new_pos, offsets=new_offsets, **kwargs)
def add_force(self, force, pos=None): self.force += force if pos is None: pos = self.pos else: self.torque += Vector2.cross(pos - self.pos, force)
class Head(object): def __init__(self, index, name="player", is_AI=False, Score=0): # basic data self.name = name self.index = index self.is_AI = is_AI self.color = viewconst.playerColor[index] screen_mid = Vec(viewconst.ScreenSize[1] / 2, viewconst.ScreenSize[1] / 2) #up down left right self.pos = screen_mid + modelconst.init_r * modelconst.Vec_dir[ self.index] self.theta = index * (pi / 2) self.direction = Vec(cos(self.theta), -sin(self.theta)) #information self.speed = modelconst.normal_speed self.is_dash = False self.dash_timer = 0 self.dash_cool = 0 self.radius = modelconst.head_radius self.is_alive = True self.score = Score self.body_list = [self] self.is_ingrav = False self.is_circling = True self.circling_radius = modelconst.init_r self.ori = 1 self.init_timer = 200 self.have_multibullet = False self.have_bigbullet = False self.always_multibullet = False self.always_bigbullet = False #if in grav self.grav_center = Vec(0, 0) self.pos_log = [Vec(self.pos)] self.is_rainbow = False def update(self, player_list, wb_list, bullet_list, item_list, score_list, tmp_score_list): if not self.is_alive: return 0 self.pos += self.direction * self.speed if self.is_circling: self.theta += self.speed / self.circling_radius * self.ori #print(self.theta, self.speed/self.circling_radius) self.direction = Vec(cos(self.theta), -sin(self.theta)) if self.init_timer != -1: self.init_timer -= 1 if self.init_timer > 0: return 0 elif self.init_timer == 0: self.is_circling = False self.init_timer = -1 #update pos log self.pos_log.append(Vec(self.pos)) if len(self.pos_log) > modelconst.pos_log_max: self.pos_log.pop(0) #is in circle self.is_ingrav = False for i in modelconst.grav: if (self.pos - i[0]).length_squared() < i[1]**2: self.is_ingrav = True self.grav_center = i[0] #collision with wall if (self.direction.x > 0 and self.pos.x + self.radius > viewconst.ScreenSize[1]-modelconst.eps) \ or (self.direction.x < 0 and self.pos.x - self.radius < 0 - modelconst.eps) : self.direction.x *= -1 if (self.direction.y > 0 and self.pos.y + self.radius > viewconst.ScreenSize[1]-modelconst.eps) \ or (self.direction.y < 0 and self.pos.y - self.radius < 0 - modelconst.eps) : self.direction.y *= -1 #collision with white ball for i in range(len(wb_list) - 1, -1, -1): wb = wb_list[i] if wb.following: continue if (self.pos - wb.pos).length_squared() < (self.radius + wb.radius)**2: wb_list.append(White_Ball(Vec(wb.pos), True, self.index)) wb_list.pop(i) #collision with competitor's body and bullet tmp = False if not self.is_dash: for enemy in player_list: if enemy.index == self.index: continue for j in enemy.body_list[1:]: if (self.pos - j.pos).length_squared() < (self.radius + j.radius)**2: #self die killer = enemy.index self.is_alive = False tmp = True self.add_score(player_list, score_list, tmp_score_list) break else: continue break for bullet in bullet_list: if (bullet.index != self.index) and \ (self.pos - bullet.pos).length_squared() < (self.radius + bullet.radius)**2 : killer = bullet.index self.is_alive = False if tmp == False: self.add_score(player_list, score_list, tmp_score_list) break ##player die if not self.is_alive: self.is_dash = True while len(self.body_list) > 1: if killer != -1 and player_list[killer].is_alive: wb_list.append( White_Ball(Vec(self.body_list[-1].pos), True, killer)) #player_list[killer].body_list.append(Body(player_list[killer].body_list[-1])) self.body_list.pop(-1) return 1 #collision with competitor's head if not self.is_dash: for enemy in player_list: if enemy.index == self.index or enemy.is_dash == True: continue if (self.pos - enemy.pos).length_squared() < (self.radius + enemy.radius)**2: rrel = enemy.pos - self.pos if (self.direction - enemy.direction).dot(rrel) > 0: self.direction.reflect_ip(rrel) enemy.direction.reflect_ip(rrel) self.is_circling = False enemy.is_circling = False #collision with item cnt = 0 for i in player_list: if i.is_alive: cnt += 1 if cnt != 1: for i in range(len(item_list) - 1, -1, -1): item = item_list[i] if (self.pos - item.pos).length_squared() < (self.radius + item.radius)**2: item.trigger(self.index, player_list, wb_list) item_list.pop(i) #dash timer if self.is_dash: self.dash_timer -= 1 if self.dash_timer == 0: self.is_dash = False #self.speed = modelconst.normal_speed # dash cool if self.dash_cool > 0: self.dash_cool -= 1 #update theta #self.theta = atan2(self.direction.x, -self.direction.y) for j in range(1, len(self.body_list)): self.body_list[j].update() if self.is_rainbow: self.rainbow_mode() return 0 def click(self, bullet_list, wb_list): if not self.is_alive: return if self.init_timer != -1: return if not self.is_dash: if self.is_circling or self.is_ingrav: self.is_circling = (not self.is_circling) if self.is_circling: self.circling_radius = (self.pos - self.grav_center).length() ori = self.direction.cross(self.pos - self.grav_center) if ori > 0: #counterclockwise self.theta = atan2( self.pos.y - self.grav_center.y, -self.pos.x + self.grav_center.x) - pi / 2 self.direction = Vec(cos(self.theta), -sin(self.theta)) self.ori = 1 else: self.theta = atan2( self.pos.y - self.grav_center.y, -self.pos.x + self.grav_center.x) + pi / 2 self.direction = Vec(cos(self.theta), -sin(self.theta)) self.ori = -1 else: self.circling_radius = 0 elif self.dash_cool == 0: self.is_dash = True self.dash_timer = modelconst.max_dash_time * modelconst.dash_speed_multiplier self.dash_cool = self.dash_timer + modelconst.dash_cool #self.speed = modelconst.dash_speed if len(self.body_list) > 1: self.body_list.pop(-1) if self.always_multibullet or self.have_multibullet: bullet_list.append( Bullet(self.pos, self.direction, self.index)) bullet_list.append( Bullet(self.pos, self.direction.rotate(30), self.index)) bullet_list.append( Bullet(self.pos, self.direction.rotate(-30), self.index)) self.have_multibullet = False elif self.always_bigbullet or self.have_bigbullet: bullet_list.append( Bullet(self.pos, self.direction, self.index, modelconst.bigbullet_r)) self.have_bigbullet = False else: bullet_list.append( Bullet(self.pos, self.direction, self.index)) def add_score(self, player_list, score_list, tmp_score_list): for enemy in player_list: if enemy.index == self.index: continue else: if enemy.is_alive: score_list[enemy.index] += 1 tmp_score_list[enemy.index] += 1 def blast(self, bullet_list): for i in range(len(self.body_list) - 1, 0, -1): cb = self.body_list[i] rndtheta = random.random() * 2 * pi bullet_list.append( Bullet(cb.pos, Vec(cos(rndtheta), sin(rndtheta)), self.index, 2 * modelconst.bullet_radius)) self.body_list.pop() def rainbow_mode(self): for ii in range(len(self.body_list) - 1, 0, -1): i = self.body_list[ii] if i.color == i.pre.color: i.color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))