def __init__(self, x1, y1, x2, y2, color=(255, 255, 255)): self.p1 = Vector2D(x1, y1) self.p2 = Vector2D(x2, y2) self.vec = self.p2 - self.p1 #print self.vec self.color = color self.thickness = 1
def step(self, op: str, value: int) -> None: if op in DIRECTIONS: self.waypoint += value * DIRECTIONS[op] elif op == "R": angle = radians(-1 * value) self.waypoint = Vector2D( round( self.waypoint.x * cos(angle) - self.waypoint.y * sin(angle), 6), round( self.waypoint.x * sin(angle) + self.waypoint.y * cos(angle), 6)) elif op == "L": angle = radians(value) self.waypoint = Vector2D( round( self.waypoint.x * cos(angle) - self.waypoint.y * sin(angle), 6), round( self.waypoint.x * sin(angle) + self.waypoint.y * cos(angle), 6)) elif op == "F": self.pos += value * self.waypoint else: raise ValueError(f"Unrecognised operation: {op}")
def add_rocket(self): rocket = Rocket(self.cwidth, self.cheight) rocket.rotation_speed = random.uniform(-.3,.3) rocket.engine_throttle = 1 rocket.position = Vector2D((random.randint(-self.cwidth/2,self.cwidth/2), random.randint(0,self.cheight))) rocket.velocity = Vector2D((random.uniform(-10,10), random.uniform(-4,4))) self.rockets.append(rocket)
def assignJump(self, bot, ballPred, game, action): mfhTime = self.maxFlightHalfTime count = int(mfhTime / 0.01) # точность моделирования gameStub = copy.deepcopy(game) states = [] for i in range(count): t = i * 0.01 ballState = ballPred.predictedBall(game.ball, t) gameStub.ball = ballState strikePoint = self.getStrikePoint(gameStub) strikePt2D = Vector2D(strikePoint.x, strikePoint.z) botPt2D = Vector2D(bot.x + bot.velocity_x * t, bot.z + bot.velocity_z * t) dst = (strikePt2D - botPt2D).len() states.append([t, strikePoint, dst]) def elemVal(elem): return elem[2] minState = min(states, key=elemVal) if (minState[2] < 0.55): # можно попробовать requiredY = minState[1].y print(minState, requiredY, end=' ') if (requiredY > self.maxReachableZ): return requiredVelY = ( requiredY - self.rules.ROBOT_MIN_RADIUS \ + self.rules.GRAVITY * minState[0] ** 2 / 2 ) / t #print(requiredVelY) if (requiredVelY > self.rules.ROBOT_MAX_JUMP_SPEED): return action.jump_speed = requiredVelY
def setSize(self, width=0, height=0, radius=None): if radius: self.radius = radius self.size = Vector2D() else: self.size = Vector2D(width, height) self.max = self.min + self.size self.radius = None
def draw_calls(self): def call(method, *vargs, **kwargs): return method, vargs, kwargs calls = [] screen_offset = Vector2D((self.world_width / 2, 10)) screen_offset += self.position scale = 6 # rotate and position the rocket points = [Vector2D(xy) for xy in self.rocket_vertices] points = [ v.rotate_around(self.rotation_point, self.rotation) for v in points ] points = [scale * v + screen_offset for v in points] points = [(v.x, self.world_height - v.y) for v in points] calls.append( call("create_polygon", points, fill="blue", outline="lightgrey")) if self.engine_throttle: # rotate and position the engine flame points = [ Vector2D((x, y * self.engine_throttle)) for x, y in self.engine_flame_vertices ] points = [ v.rotate_around(self.rotation_point, self.rotation) for v in points ] points = [scale * v + screen_offset for v in points] points = [(v.x, self.world_height - v.y) for v in points] calls.append( call("create_polygon", points, outline="orange", fill="yellow")) # rotate and position the left and right thrusters points = [Vector2D(xy) for xy in self.thruster_positions] points = [ v.rotate_around(self.rotation_point, self.rotation) for v in points ] points = [scale * v + screen_offset for v in points] points = [(v.x, self.world_height - v.y) for v in points] if self.left_thruster_on: calls.append( call("create_oval", points[0][0] - 3, points[0][1] - 3, points[0][0] + 3, points[0][1] + 3, outline="orange", fill="yellow")) if self.right_thruster_on: calls.append( call("create_oval", points[1][0] - 3, points[1][1] - 3, points[1][0] + 3, points[1][1] + 3, outline="orange", fill="yellow")) return calls
def __init__(self, x, y, ship_angle, screen): self.screen = screen self.speed = 16 self.direction = ship_angle; self.velocity = Vector2D().create_from_angle(self.direction, self.speed, return_instance=True) self.pos = Vector2D(x, y) self.color = colors.green self.size = 4 self.box = (0, 0, 0, 0)
def nearest_coin(self): min_coin = None min_dist = Vector2D.magnitude(self.pacman.pos - Vector2D(self.coins[0].pos[0], self.coins[0].pos[1])) for c in self.coins: dist = Vector2D.magnitude(self.pacman.pos - Vector2D(c.pos[0], c.pos[1])) if dist <= min_dist: min_coin = c min_dist = dist return min_coin
def nearest_ghost(self): min_ghost = None min_dist = Vector2D.magnitude(self.pacman.pos - self.ghosts[0].pos) for g in self.ghosts: dist = Vector2D.magnitude(self.pacman.pos - g.pos) if dist <= 128.0 and dist <= min_dist: min_ghost = g min_dist = dist return min_ghost
def __init__(self, screen, pos=Vector2D(0, 0), size=24, vert_count=10): self.screen = screen self.pos = pos self.size = size self.color = colors.green self.velocity = Vector2D(0, 0) self.points = [] self.generate_random_shape(vert_count) self.type = 1
def doDecideJump(self, ballTrajectory, game, bot, action): if (ballTrajectory[0].tick != game.current_tick): print('doDecideJump(): trajectory error') return #pdb.set_trace() if (bot.z > game.ball.z or bot.touch == False): return # полагая, что робот прыгнет прям сейчас botMovePerTick = Vector2D(bot.velocity_x * self.tik, bot.velocity_z * self.tik) botStartRVec = Vector2D(bot.x, bot.z) radiusSum = self.rules.ROBOT_MIN_RADIUS + self.rules.BALL_RADIUS collisionTick = None for i in range(1, 32): botPos2d = botStartRVec + botMovePerTick * i ballPos2d = Vector2D(ballTrajectory[i].x, ballTrajectory[i].z) dst2d = (ballPos2d - botPos2d).len() if (dst2d < radiusSum): collisionTick = i break if (collisionTick == None): #pdb.set_trace() return # требуемая высота minDeltaH = (radiusSum**2 - dst2d**2)**0.5 if (minDeltaH < 0): print('doDecideJump(): minDeltaH error') return #standardBotCY = game.ball.y - radiusSum + 0.5 standardBotCY = ballTrajectory[i].y - radiusSum + 0.5 if (standardBotCY < self.rules.ROBOT_MIN_RADIUS): # прыжок не требуется #pdb.set_trace() return # needed bot center y needBotCY = min( ballTrajectory[i].y - minDeltaH, #max? standardBotCY) if (needBotCY > self.maxReachableZ): # не допрыгнем #pdb.set_trace() return jumpTicks, v0 = self.calculateJump(needBotCY) # check #print(jumpTicks, v0) #if (jumpTicks == collisionTick): if (jumpTicks in [collisionTick, collisionTick - 1, collisionTick + 1]): action.jump_speed = v0
def set_touchdown_position(self, x_position): self.position = Vector2D((x_position, 0)) self.velocity = Vector2D((0, 0)) self.acceleration = Vector2D((0, 0)) self.rotation = 0.0 self.rotation_speed = 0.0 self.rotation_acceleration = 0.0 self.crashed = False self.touchdown = True self.engine_throttle = 0.0 self.right_thruster_on = False self.left_thruster_on = False
def __init__(self, x, y): self.ID = None #Position vectors that describe the shape of the box self.min = Vector2D(x, y) self.size = Vector2D() self.max = self.min + self.size self.radius = None #self.position = Vector2D(x, y) self.velocity = Vector2D() self.acceleration = Vector2D() self.Fnet = Vector2D()
def __init__(self, x, y, screen): self.screen = screen self.pos = Vector2D(x, y) self.size = 18 self.color = colors.green self.rotation = 0 self.points = [ (-self.size, self.size), (0, self.size / 3), (self.size, self.size), (0, -self.size) ] self.translate((self.pos.x, self.pos.y)) self.velocity = Vector2D(0, 0) self.projectiles = []
def __init__(self, pos, width, height): self.x, self.y = (pos) #self.coord = (self.x*width*1.0, self.y*height*1.0) self.position = Vector2D(self.x * width, self.y * height) self.neighbors = [] self.target = None self.directions = []
def __init__(self, position, drawer): self._matrix = [(None, None, 1, None), (None, None, 1, None), (None, None, 1, None), (None, None, 1, None)] self._drawer = drawer self.position = Vector2D(position)
def __init__(self, x, y): self.name = "pellet" self.position = Vector2D(x, y) self.color = YELLOW self.radius = 2 self.value = 10 self.draw = True
def collide(self, other): # Exit early for optimization if (self.position - other.position).length() > max(self.width, self.height) + max(other.width, other.height): return False, None, None def project(vertices, axis): dots = [vertex.dot(axis) for vertex in vertices] return Vector2D(min(dots), max(dots)) collision_depth = sys.maxsize collision_normal = None for edge in self.edges + other.edges: axis = Vector2D(edge).orthogonal().normalize() projection_1 = project(self.vertices, axis) projection_2 = project(other.vertices, axis) min_intersection = max(min(projection_1), min(projection_2)) max_intersection = min(max(projection_1), max(projection_2)) overlapping = min_intersection <= max_intersection if not overlapping: return False, None, None else: overlap = max_intersection - min_intersection if overlap < collision_depth: collision_depth = overlap collision_normal = axis return True, collision_depth, collision_normal
def move_to(self, position): """ Moves object to a target position :param position: an absolute target position """ self._last_position = self.position self.position = Vector2D(position)
def move(self, pacnode, nodelist, alg): new_node = self.find_node(nodelist) if (new_node): self.currentnode = new_node self.moving = False if (not self.moving): node = self.currentnode keyerrorFlag = False #this is to catch keyerror exception, as child key is not present always try: map = search_pacnode_by_alg(node, pacnode, alg) child = pacnode parent = pacnode while True: parent = map[child] if (parent == node): break else: child = parent except: keyerrorFlag = True if not keyerrorFlag: direct = child.position - parent.position direct = direct.normalize() self.direction = direct else: self.direction = Vector2D(0, 0) self.moving = True self.pos += self.direction * self.speed
def AddSegment(self, segment): '''Turn segment into unit vector perpendicular to segment''' self.segments.append(segment) if self.direction is None: d = Vector2D(segment.vec.y, segment.vec.x * -1) d = d.norm() self.direction = d
def __init__(self, row, column): self.row, self.column = row, column self.position = Vector2D(column*WIDTH, row*HEIGHT) self.neighbors = {UP:None, DOWN:None, LEFT:None, RIGHT:None} self.portalNode = None self.home = False self.nowayUp = False
def update_manual(self, nodelist): #if pacman position is same as any node then detect for key pressing node = self.find_node(nodelist) if (node): self.currentnode = node key_pressed = pygame.key.get_pressed() if (key_pressed[K_UP] and UP in node.directions): self.pos = node.position self.direction = UP elif (key_pressed[K_DOWN] and DOWN in node.directions): self.pos = node.position self.direction = DOWN elif (key_pressed[K_LEFT] and LEFT in node.directions): self.pos = node.position self.direction = LEFT elif (key_pressed[K_RIGHT] and RIGHT in node.directions): self.pos = node.position self.direction = RIGHT #if no key is pressed and current direction is not available.. elif (self.direction not in node.directions): self.pos = node.position self.direction = Vector2D(0, 0) #code to update position self.pos += self.direction * self.speed
def __init__(self, nodes, spritesheet, row): MazeRunner.__init__(self, nodes, spritesheet) self.name = "ghost" self.color = PINK self.goal = Vector2D() self.modeStack = self.setup_mode_stack() self.mode = self.modeStack.pop() self.modeTimer = 0 self.spawnNode = self.find_spawn_node() self.set_guide_stack() self.set_start_position() self.points = 200 self.released = True self.pelletsForRelease = 0 self.bannedDirections = [] self.speed = GHOST_SPEED self.animate = AnimationGroup() self.animateName = "left" self.define_animations(row) self.animate.set_animation(self.animateName, 0) self.image = self.animate.get_image() self.previousDirection = self.direction self.started = True self.hide = True
def __init__(self, node, dim, pos=(0, 0)): AbstractEntity.__init__(self, dim, pos) self.COLOR = (255, 255, 0) self.direction = Vector2D(0, 0) self.speed = 3.2 self.currentnode = node self.moving = False self.count_pacman_animate = 1
def vertices(self): return [ self.position + Vector2D(v).rotate(-self.angle) for v in ( (-self.width / 2, -self.height / 2), (self.width / 2, -self.height / 2), (self.width / 2, self.height / 2), (-self.width / 2, self.height / 2) ) ]
def edges(self): return [ Vector2D(v).rotate(self.angle) for v in ( (self.width, 0), (0, self.height), (-self.width, 0), (0, -self.height), ) ]
def __init__(self, speed, node, color, dim, pos=(0, 0)): AbstractEntity.__init__(self, dim, pos) self.COLOR = color self.direction = Vector2D(0, 0) self.speed = speed self.currentnode = node self.moving = False self.scatter = False self.rand_move_count = 1
def boost(self): # print(self.velocity.x, ',', self.velocity.y) force = Vector2D().create_from_angle(self.rotation, 0.1, True) # Limits the speed if (((self.velocity.x <= 4) and (self.velocity.x >= -4)) or ((self.velocity.y <= 4) and (self.velocity.y >= -4))): self.velocity.add(force)
def moveHomeNodes(self): nodeA = self.getNode(*MAZEDATA[self.level]["home"], nodeList=self.nodeList) nodeB = nodeA.neighbors[LEFT] mid = (nodeA.position + nodeB.position) / 2.0 mid = Vector2D(int(mid.x), int(mid.y)) vec = Vector2D(self.homeList[0].position.x, self.homeList[0].position.y) for node in self.homeList: node.position -= vec node.position += mid nodeA.neighbors[LEFT] = self.homeList[0] nodeB.neighbors[RIGHT] = self.homeList[0] self.homeList[0].neighbors[RIGHT] = nodeA self.homeList[0].neighbors[LEFT] = nodeB self.homeList[0].home = True ghostHome = self.homeList[0].neighbors[DOWN] MAZEDATA[self.level]["start"]["ghost"] = ghostHome.position.toTuple()
def botToPoint(self, targetPoint, bot, action): # TODO добавить параметров botVec = Vector2D(bot.x, bot.z) vecToTarget = targetPoint - botVec velocityVec = vecToTarget.normalize( ) * self.rules.ROBOT_MAX_GROUND_SPEED action.target_velocity_x = velocityVec.x action.target_velocity_z = velocityVec.z
def approxTimeToPoint(self, targetPoint, game, bot, timeAsTicks=True): botVec = Vector2D(bot.x, bot.z) vecToTarget = targetPoint - botVec # составляющие скорости мяча: проекция скорости на вектор, направленный # на целевую точку, и перпендикулярная ей составляющая # ( работаем только с направленной на точку ) botVelocity = Vector2D(bot.velocity_x, bot.velocity_z) velTgtScalar = botVelocity.scalarProjectOn(vecToTarget) tToTarget = 0.0 # время разворота if (velTgtScalar < 0): tToTarget += 2 * abs(velTgtScalar) / self.rules.ROBOT_ACCELERATION velTgtScalar = -velTgtScalar dst = vecToTarget.len() # время разгона tAccel = (self.rules.ROBOT_MAX_GROUND_SPEED - velTgtScalar) / \ self.rules.ROBOT_ACCELERATION sAccel = velTgtScalar * tAccel + \ self.rules.ROBOT_ACCELERATION * tAccel ** 2 / 2 #pdb.set_trace() if (sAccel < dst): tToTarget += tAccel + \ (dst - sAccel) / self.rules.ROBOT_MAX_GROUND_SPEED else: # придется потиково, ничего не поделать tik = 1 / self.rules.TICKS_PER_SECOND auxVelocity = self.rules.ROBOT_MAX_GROUND_SPEED while (sAccel < dst): auxVelocity -= tik * self.rules.ROBOT_ACCELERATION ds = auxVelocity * tik + \ self.rules.ROBOT_ACCELERATION * tik ** 2 / 2 sAccel -= ds tAccel -= tik if (tAccel < 0): print('approxTimeToPoint() unexpected behavior') return tik if (timeAsTicks == False) else 1 tToTarget = tAccel if (timeAsTicks == True): return round(tToTarget / self.tik) else: return tToTarget
def make_key(self): s0 = 0 s1 = 0 s2 = 0 s3 = 0 s4 = 0 s5 = 0 s6 = 0 s7 = 0 s8 = 0 s9 = 0 directions = self.pacman.currentnode.directions if Vector2D(-1, 0) in directions: global s0 s0 = 1 if Vector2D(1, 0) in directions: global s1 s1 = 1 if Vector2D(0, -1) in directions: global s2 s2 = 1 if Vector2D(0, 1) in directions: global s3 s3 = 1 #labels for directions avail_dirs = {(-1, 0):1, (1, 0):2, (0, -1):3, (0, 1):4} g = self.nearest_ghost() #if nearest ghost exists(distance lesser than some specified value) if g: global s4 dmax = 64 index = 0 for i in range(len(self.pacman.currentnode.neighbors)): n = self.pacman.currentnode.neighbors[i] mdist = Vector2D.magnitude(n.position-g.pos) if (mdist >= dmax): index = i dmax = mdist preferred_direction = self.pacman.currentnode.directions[index] s4 = avail_dirs[(preferred_direction.x, preferred_direction.y)] else: c = self.nearest_coin() coinVector = Vector2D(c.pos[0], c.pos[1]) global s4 dmin = Vector2D.magnitude(self.pacman.pos - coinVector) index = 0 for i in range(len(self.pacman.currentnode.neighbors)): n = self.pacman.currentnode.neighbors[i] mdist = Vector2D.magnitude(n.position-coinVector) if (mdist <= dmin): index = i dmin = mdist preferred_direction = self.pacman.currentnode.directions[index] s4 = avail_dirs[(preferred_direction.x, preferred_direction.y)] #following block to see from which direction ghost approaches for g in self.ghosts: if Vector2D(-1, 0).dotpro(g.direction) == -1 and \ (self.pacman.currentnode.position-g.currentnode.position).normalize().dotpro(g.direction) == 1: global s5 s5 = 1 if Vector2D(1, 0).dotpro(g.direction) == -1 and \ (self.pacman.currentnode.position-g.currentnode.position).normalize().dotpro(g.direction) == 1: global s6 s6 = 1 if Vector2D(0, -1).dotpro(g.direction) == -1 and \ (self.pacman.currentnode.position-g.currentnode.position).normalize().dotpro(g.direction) == 1: global s7 s7 = 1 if Vector2D(0, 1).dotpro(g.direction) == -1 and \ (self.pacman.currentnode.position-g.currentnode.position).normalize().dotpro(g.direction) == 1: global s8 s8 = 1 traplist = [] if Vector2D(-1, 0) in directions: global s5 traplist.append(s5) if Vector2D(1, 0) in directions: global s6 traplist.append(s6) if Vector2D(0, -1) in directions: global s7 traplist.append(s7) if Vector2D(0, 1) in directions: traplist.append(s8) if len(traplist) == sum(traplist): global s9 s9 = 1 key = [str(s0), str(s1), str(s2), str(s3), str(s4), str(s5), str(s6), str(s7), str(s8), str(s9)] return ''.join(key)
def find_node(self, nodelist): for n in nodelist: if Vector2D.magnitude(self.pos-n.position) <= 0.1: return n return None