def update(self): self.image.set_colorkey(BLACK) m1, m2, m3 = pg.mouse.get_pressed() self.rect = self.original_rect self.image = self.original_image if self.bullet_group != None: self.bullet_group.update() self.rect.y = self.player.rect.y - (self.height / 2) + (self.player.height / 2) self.cent_x, self.cent_y = self.player.rect.x + self.player.width / 2, self.player.rect.y + self.player.height / 2 #Pythag Theorm side1_length = math.sqrt((self.cent_x - self.mx)**2 + ( (self.cent_y + self.player.height / 2) - self.my)**2) side2_length = self.player.height / 2 side3_length = math.sqrt((self.cent_x - self.mx)**2 + (self.cent_y - self.my)**2) #Law of cos, and pythag theorm to find angle of mouse self.deg_rotate = math.degrees( math.acos(((side2_length**2) + (side3_length**2) - (side1_length**2)) / (2 * side2_length * side3_length))) if self.mx <= self.player.rect.x + (self.player.width / 2): self.deg_rotate *= -1 self.pivot_side = -1 self.rect.x = self.player.rect.x - (self.width / 2) + 10 self.pivot = self.player.width if self.mx >= self.player.rect.x + (self.player.width / 2): self.pivot_side = 1 self.rect.x = self.player.rect.x - (self.width / 2) + (self.player.width) - 10 self.pivot = self.player.width self.image = pg.transform.flip(self.image, True, False) self.pivot_offset = pg.math.Vector2( 0, self.pivot).rotate(-self.deg_rotate) self.rotated_image = pg.transform.rotate( self.image, self.deg_rotate).convert_alpha() self.rotated_rect = self.rotated_image.get_rect( center=self.rect.center + self.pivot_offset) self.image = self.rotated_image self.rect = self.rotated_rect if m1 == 0: self.shooting = False if self.shooting == False and m1 == 1: self.shooting = True self.shoot() if self.player.enemies_killed == self.next_upgrade: self.spread_shot += 1 self.next_upgrade *= 2
def update(self): self.image = pg.transform.scale( self.follow.game.spritesheet.get_image(5, 318, 243, 303), (60, 80)).convert_alpha() self.image.set_colorkey(BLACK) # Delete the object if all health is lost if self.health <= 0: self.kill() #Pythag to find distance from player self.c = math.sqrt((self.follow.rect.x - self.rect.x)**2 + (self.follow.rect.y - self.rect.y)**2) if self.c != 0: #Create a multiplier from the distance between the player self.x = (self.follow.rect.x - self.rect.x) / self.c self.y = (self.follow.rect.y - self.rect.y) / self.c #use multiplier to effect speed self.rect.x += self.x * self.speed self.rect.y += self.y * self.speed bullet_collisions = pg.sprite.spritecollide(self, self.bulletgroup, True) #If there is bullet from the player colliding with the enemy, it will add it to the group, and if there is anything in this group, remove health if bullet_collisions: self.health -= self.follow.weapon.damage self.weapon.update()
def update(self): self.mx, self.my = self.user.follow.rect.x, self.user.follow.rect.y m1, m2, m3 = pg.mouse.get_pressed() if self.bullet_group != None: self.bullet_group.update() self.rect.y = self.user.rect.y - (self.height / 2) + (self.user.height / 2) self.cent_x, self.cent_y = self.user.rect.x + self.user.width / 2, self.user.rect.y + self.user.height / 2 #Pythag Theorm side1_length = math.sqrt((self.cent_x - self.mx)**2 + ( (self.cent_y + self.user.height / 2) - self.my)**2) side2_length = self.user.height / 2 side3_length = math.sqrt((self.cent_x - self.mx)**2 + (self.cent_y - self.my)**2) #Law of cos, and pythag theorm to find angle of mouse self.deg_rotate = math.degrees( math.acos(((side2_length**2) + (side3_length**2) - (side1_length**2)) / (2 * side2_length * side3_length))) if self.mx <= self.user.rect.x + (self.user.width / 2): self.deg_rotate *= -1 self.pivot_side = -1 self.rect.x = self.user.rect.x - (self.width / 2) + 10 self.pivot = self.user.width if self.mx >= self.user.rect.x + (self.user.width / 2): self.pivot_side = 1 self.rect.x = self.user.rect.x - (self.width / 2) + (self.user.width) - 10 self.pivot = self.user.width self.pivot_offset = pg.math.Vector2( 0, self.pivot).rotate(-self.deg_rotate) self.rotated_image = pg.transform.rotate(self.image, self.deg_rotate) self.rotated_rect = self.rotated_image.get_rect( center=self.rect.center + self.pivot_offset) if (pg.time.get_ticks() - self.last_shot) > self.shot_interval: self.shoot() self.last_shot = pg.time.get_ticks()
def updateMovement(self, step): angle = self.angle self.prevAngle = angle # print("prevAngle ", math.degrees(self.prevAngle)) position = self.position self.prevPosition = position # print("PREV position = ", self.prevPosition) dx = self.position.x - planetCenter.x dy = self.position.y - planetCenter.y r = math.sqrt(dx ** 2 + dy ** 2) g = Physics.G * self.mass * planetMass / r ** 2 self.radialVelocity += g if (self.radialVelocity < PLAYER_MIN_SPEED): self.radialVelocity = PLAYER_MIN_SPEED self.radius += self.radialVelocity # print("radius ", self.radius) bottom = self.radius - self.halfHeight self.onGround = False if (bottom <= planetRadius): self.onGround = True self.radius = planetRadius + self.halfHeight self.radialVelocity = 0 if self.onGround == True and self.direction == 'none': self.angularVelocity = 0 self.angle += self.angularVelocity * planetRadius / self.radius # print("angle ", self.angle) # print("angle ", math.degrees(self.angle)) if (math.degrees(self.angle) >= 360.0): self.angle = 0.0 # self.position.x = planetCenter.x + self.radius * math.sin(self.angle) # self.position.y = planetCenter.y + self.radius * -math.cos(self.angle) newPosition = Vector2() newPosition.x = planetCenter.x + self.radius * math.sin(self.angle) newPosition.y = planetCenter.y + self.radius * -math.cos(self.angle) positionChange = newPosition - position # print("positionChange = ", positionChange) self.position.x += positionChange.x * step self.position.y += positionChange.y * step
def update(self): # Delete the object if all health is lost if self.health <= 0: self.follow.enemies_killed += 1 self.kill() #Pythag to find distance from player self.c = math.sqrt((self.follow.rect.x - self.rect.x)**2 + (self.follow.rect.y - self.rect.y)**2) if self.c != 0: #Create a multiplier from the distance between the player self.x = (self.follow.rect.x - self.rect.x) / self.c self.y = (self.follow.rect.y - self.rect.y) / self.c #use multiplier to effect speed # self.rect.x += self.x * self.speed # self.rect.y += self.y * self.speed if self.x > 0: self.move_player(self.speed, 0) self.x_direction = 'r' if self.x < 0: self.move_player(-self.speed, 0) self.x_direction = 'l' if self.y < 0: self.move_player(0, -self.speed) self.y_direction = 'd' if self.y > 0: self.move_player(0, self.speed) self.y_direction = 'u' bullet_collisions = pg.sprite.spritecollide(self, self.bulletgroup, True) #If there is bullet from the player colliding with the enemy, it will add it to the group, and if there is anything in this group, remove health if bullet_collisions: self.health -= self.follow.weapon.damage self.image.set_colorkey(BLACK)
def lineIntersectsCircle(x1, y1, x2, y2, cx, cy, cr): r = cr Q = pygame.math.Vector2((cx, cy)) P1 = pygame.math.Vector2((x1, y1)) V = pygame.math.Vector2((x2, y2)) - P1 a = V.dot(V) b = 2 * V.dot(P1 - Q) c = P1.dot(P1) + Q.dot(Q) - 2 * P1.dot(Q) - r**2 disc = b**2 - 4 * a * c if disc < 0: return False sqrt_disc = math.sqrt(disc) t1 = (-b + sqrt_disc) / (2 * a) t2 = (-b - sqrt_disc) / (2 * a) if not (0 <= t1 <= 1 or 0 <= t2 <= 1): return False t = max(0, min(1, - b / (2 * a))) return True
def update(self, coordsOffset): vector: pygame.math.Vector2 = self.nodeAnchor.connectedNodes[ self.nodeDestination][ 0] # Define variables for vector from nodeAnchor to destination carVector: pygame.math.Vector2 = pygame.math.Vector2([ b - a for a, b in zip(self.coords, self.nodeDestination.coords) ]) # variable vector from nodeAnchor to car try: normalized = vector.normalize() except ValueError: normalized = [0, 0] # Change the direction of the car if reached the end of the road change = False if normalized != carVector.normalize( ): # if length to car from nodeAnchor is more than length to destination, # set the destinationNode as node anchor, and pick one random nodeDestination from the list of the new nodeAnchor self.nodeAnchor = self.nodeDestination numOfConnectedRoads = len(self.nodeAnchor.connectedNodes) # Issue object deletion if numOfConnectedRoads == 0: Car.carCollisionGrid[self.gridPos].pop( Car.carCollisionGrid[self.gridPos].index(self)) del self return True nodeDestinationIndex = random.randint(0, numOfConnectedRoads - 1) self.nodeDestination = list( self.nodeAnchor.connectedNodes.keys())[nodeDestinationIndex] # Change the coords change = True # Then change the original from nodeAnchor to destination vector. if change: vector: pygame.math.Vector2 = self.nodeAnchor.connectedNodes[ self.nodeDestination][0] self.direction = 360 - (np.arctan2(*vector[::-1]) * 180 / math.pi ) # Fix this self.image, self.rect = GMfun.rotationAnchor( self.originalImage, self.direction, [0.28, 0.5]) #################################################### GridPos repositioning #################################################### currentGridPos = tuple([ int(self.coords[i] // Car.collisionGridSize[i]) for i in range(2) ]) if currentGridPos != self.gridPos: # Pop current car from the previous collisionGrid Car.carCollisionGrid[self.gridPos].pop( Car.carCollisionGrid[self.gridPos].index(self)) # Add current car to new grid, and assign new gridPos to self self.gridPos = currentGridPos try: Car.carCollisionGrid[self.gridPos].append(self) except KeyError: Car.carCollisionGrid[self.gridPos] = [self] #################################################### Collision checking #################################################### self.carInFront = False # Collision stuff. True if a car is detected in front. collisionCheckList = [] for i in range(-1, 2): for j in range(-1, 2): try: collisionCheckList += Car.carCollisionGrid[tuple( [self.gridPos[0] + i, self.gridPos[1] + j])] except KeyError: pass distanceFromNearestCar = 10000000000 viewConeBase = [ (Car.triangleHeight * normalized[i]) + self.coords[i] + 8 for i in range(2) ] offsetVector1 = [-normalized[1], normalized[0]] viewConeBase1 = [ a + (Car.triangleBase / 2 * c) for a, c in zip(viewConeBase, offsetVector1) ] offsetVector2 = [-vec for vec in offsetVector1] viewConeBase2 = [ a + (Car.triangleBase / 2 * c) for a, c in zip(viewConeBase, offsetVector2) ] for cars in collisionCheckList: # Ignore if the car object is self, or if the nodeAnchor of self is not the same as other nodeAnchor if cars == self: continue carCoords = cars.coords # If the coords is within the cone if isPointInTriangle(carCoords, self.coords, viewConeBase1, viewConeBase2): distanceVector = pygame.math.Vector2( *[b - a for a, b in zip(self.coords, carCoords)]) if distanceVector.length_squared() < distanceFromNearestCar: distanceFromNearestCar = distanceVector.length_squared() distanceFromNearestCar = math.sqrt(distanceFromNearestCar) self.carInFront = not cars.go if type( cars ).__name__ == "StopLight" and cars.nodeAnchor == self.nodeAnchor else True ################################################## END COLLISION CHECKING ################################################## accelAddition = GMvar.deltaTime * self.acceleration * GMvar.gameSpeed if distanceFromNearestCar < Car.triangleHeight and self.carInFront: # self.scalarSpeed = self.oldScalarSpeed * ( GMfun.clamp(distanceFromNearestCar - Car.stopDistance, 0, Car.triangleHeight - Car.stopDistance) / (Car.triangleHeight - Car.stopDistance) ) self.scalarSpeed -= self.brakeDeacceleration * GMvar.gameSpeed * GMvar.deltaTime * ( 1 - (GMfun.clamp(distanceFromNearestCar + Car.stopDistance, 0, Car.triangleHeight) / Car.triangleHeight)) if self.scalarSpeed * 1 >= 0 else 0 else: if not carVector.length_squared() < 112 ^ 2: self.scalarSpeed += accelAddition if self.scalarSpeed * 1 <= self.maxSpeed else 0 else: self.scalarSpeed -= accelAddition * 2 if self.scalarSpeed > kmhToPixels( 20) else 0 self.oldScalarSpeed = self.scalarSpeed self.scalarSpeed = GMfun.clamp(self.scalarSpeed, 0, 100000) self.speed = [ self.scalarSpeed * vec * GMvar.gameSpeed for vec in normalized ] super().update() if change: self.coords = self.nodeAnchor.coords * 1 self.surface.blit(self.image, [ a - b + c for a, b, c in zip(self.coords, coordsOffset, self.rect) ]) return False
def update(): # Update mouse coords when snapped to grid Canvas.mouseCoords = [ (GMvar.latestMouse[i] - ((GMvar.latestMouse[i] + MainCameraSurface.gridOffset[i]) % MainCameraSurface.cellSize[i])) for i in range(2) ] if Canvas.newRoad: Canvas.highlightGrid(1, 1) # Grid highlight size GMfun.insertDrawTopMostQueue(Canvas.addRoad, (5, 25)) # Instructions if pygame.K_ESCAPE in GMvar.keyboardPressedStates: bottomGui.addRoad.clicked = False del Canvas.tempRoadNodes[:] length = 0 # Road length for now canDrawRoad = True # If can draw road, not intersecting with others lengthFromIntersection = Canvas.snapLength + 1 # The length from the intersection point to the road to the mouse. (This is just the default valie) snap = False # If the length fo intersection is lower than constant snap. it means the road is snapped to another road. overDirection = False # Draw road estimation if len(Canvas.tempRoadNodes) > 0: startLine = [ a - b for a, b in zip(Canvas.tempRoadNodes[-1].coords, MainCameraSurface.cameraCoords) ] endLine = Canvas.mouseCoords length = math.sqrt( sum([(b - a)**2 for a, b in zip(startLine, endLine) ])) * 0.1875 # Road length in meters # If intersects, disable road drawing combinedNode = [Canvas.roadNodes, Canvas.tempRoadNodes[:-2]] realMouseCoords = [ a + b for a, b in zip(endLine, MainCameraSurface.cameraCoords) ] # Real mouse coordinates. (mouse coords current - camera coords) # To avoid any unwanted intersections, offset node coords a bit. try: newRoadVec = pygame.math.Vector2([ a - b for a, b in zip(realMouseCoords, Canvas.tempRoadNodes[-1].coords) ]).normalize() except: newRoadVec = [0, 0] intersectionCount = 0 # Code for drawing temporary road to mouse. for i in range(2): for j in range(len(combinedNode[i])): for k in range( len(combinedNode[i][j].connectedNodes.keys())): # Check for intersections between 2 lines. one line is from the last temporary node to mouse coord. second line is every possible road. state, pos = GMmat.checkLineIntersection( [ a + b for a, b in zip( newRoadVec, Canvas.tempRoadNodes[-1].coords) ], realMouseCoords, combinedNode[i][j].coords, list(combinedNode[i][j].connectedNodes.keys()) [k].coords, True) # If current mouse coordinates connects to road then snap road. # if realMouseCoords == combinedNode[i][j].coords: # state = True # pos = combinedNode[i][j].coords # If intersecting then if state: intersectionCount += 1 # Calculate length from intersection. lengthFromIntersection = math.sqrt( sum([(a - b)**2 for a, b in zip(pos, realMouseCoords) ])) snap = lengthFromIntersection < Canvas.snapLength canDrawRoad = True if snap else False # The node data for the one intersecting # If snap then if snap: # pos = [ pos[i] - (pos[i] % MainCameraSurface.cellSize[i]) for i in range(2) ] # If want to snap to grid, do this. firstNode: StreetNodes = combinedNode[i][j] secondNode: StreetNodes = list( combinedNode[i] [j].connectedNodes.keys())[k] break # Break from for loop if canDrawRoad == False or snap: break # Continue breaking if canDrawRoad == False or snap: break # Still breaking if intersectionCount > 1: canDrawRoad = False # This is the script to check if road is going back 180 degrees, overlapping the previous road. # This works by comparing the normalized vector2 of the before road, and the current road by mouse. # Fixed problem where you can't place roads if there is two or more connectedNodes if len(Canvas.tempRoadNodes) > 1: # vec1: pygame.math.Vector2 = list(Canvas.tempRoadNodes[-2].connectedNodes.values())[-1][0] # vec2 = pygame.math.Vector2( [ b - a for a, b in zip(realMouseCoords, Canvas.tempRoadNodes[-1].coords) ] ) # try: # if vec1.normalize() == vec2.normalize(): # canDrawRoad = False # snap = False # except: # pass # Redundant code roadMouseDirection = (np.arctan2(*newRoadVec[::-1]) * 180 / math.pi) roadMouseDirection = 360 + roadMouseDirection if roadMouseDirection < 0 else roadMouseDirection addDir = Canvas.addRoadDirection + Canvas.directionRange / 2 minDir = Canvas.addRoadDirection - Canvas.directionRange / 2 if not ((roadMouseDirection < addDir or (roadMouseDirection - 360 < addDir and roadMouseDirection - 360 > minDir)) and (roadMouseDirection > minDir or (roadMouseDirection + 360 > minDir and roadMouseDirection + 360 < addDir))): canDrawRoad = False overDirection = True snap = False color = (52, 139, 201) if snap else ((50, 150, 50) if canDrawRoad else (150, 50, 50)) GMfun.drawBetterLine( GMvar.mainScreenBuffer, color, *[ b + 16 if (b > a - c) else b for a, b, c in zip( pos, startLine, MainCameraSurface.cameraCoords) ] if snap else startLine, *[ a - b for a, b in zip(pos, MainCameraSurface.cameraCoords) ] if snap else endLine, 16 ) # If snaps to road, change the end line to the snapped position, else to mouse position GMfun.insertDrawTopMostQueue( GMvar.defFont12.render( "Length: {}m".format(str(round(length, 3))), True, (0, 0, 0)), (GMvar.latestMouse[0] + 20, GMvar.latestMouse[1])) # Draw road estimation description GMfun.insertDrawTopMostQueue( GMvar.defFont12.render( "Total length: {}m".format( str(round(Canvas.temporaryLength, 3))), True, (0, 0, 0)), (GMvar.latestMouse[0] + 20, GMvar.latestMouse[1] + 10)) # Draw road estimation description beginConnectRoad = False # If clicked on a road when temporary road is still empty. # This creates a new intersection point on the position where the mouse hovers, allowing the user to make a new road node from existing roads. if len(Canvas.tempRoadNodes) == 0: for i in range(len(Canvas.roadNodes)): for connectedNodes in Canvas.roadNodes[ i].connectedNodes.keys(): point = Point(Canvas.mouseCoords) line = LineString([ Canvas.roadNodes[i].coords, connectedNodes.coords ]) if point.intersection(line): pos = point firstNode: StreetNodes = Canvas.roadNodes[i] canDrawRoad = True beginConnectRoad = True break if beginConnectRoad: break # Draw temporary roads when left clicked if GMvar.mouseStateSingle[0] and GMvar.latestMouse[ 1] < bottomGui.guiHeightChange + bottomGui.sliderHeight and canDrawRoad and not overDirection: # Add length to total length Canvas.temporaryLength += length # If mouse is clicked on the canvas, if not snap: newMouseCoords = [ MainCameraSurface.getRealMouseCoords()[i] - ((MainCameraSurface.getRealMouseCoords()[i] % MainCameraSurface.cellSize[i])) for i in range(2) ] # New mouse coords adjusted with the camera newNode = StreetNodes( newMouseCoords, [], [firstNode] if beginConnectRoad else ([Canvas.tempRoadNodes[-1]] if len(Canvas.tempRoadNodes) > 0 else []), 0 ) # Create new object StreetNodes with current snapped mouse coordinates, empty front nodes, with back nodes from the last added. if beginConnectRoad: firstNode.connectTo(newNode) else: ###################### Creates entirely new node, deletes already preexisting node. # newNode = StreetNodes( pos, [secondNode], [Canvas.tempRoadNodes[-1]] if len(Canvas.tempRoadNodes) > 0 else [], 0 ) # for i in range(len(secondNode.backNodes)): # if secondNode.backNodes[i] == firstNode: # secondNode.backNodes[i] = newNode # del firstNode.connectedNodes[secondNode] # firstNode.connectedNodes[newNode] = pygame.math.Vector2( [ a - b for a, b in zip(firstNode.coords, pos) ] ) ###################### Creates new node, but overlaps with other node. newNode = StreetNodes( pos, [secondNode], [Canvas.tempRoadNodes[-1]] if len(Canvas.tempRoadNodes) > 0 else [], 0 ) # Draw new node, with the connected node to the second node. firstNode.connectTo(newNode) if len(Canvas.tempRoadNodes) > 0: Canvas.addRoadDirection = (np.arctan2(*[ b - a for a, b in zip(Canvas.tempRoadNodes[-1].coords[::-1], newNode.coords[::-1]) ]) * 180 / math.pi) Canvas.addRoadDirection = 360 + Canvas.addRoadDirection if Canvas.addRoadDirection < 0 else Canvas.addRoadDirection Canvas.tempRoadNodes[-1].connectTo( newNode ) # Add newNode to front node of the previous StreetNode Canvas.tempRoadNodes.append( newNode) # Add newNode to current roadNodes list # When Enter clicked, save current temp roads to road nodes if pygame.K_RETURN in GMvar.keyboardPressedStates: Canvas.roadNodes += Canvas.tempRoadNodes del Canvas.tempRoadNodes[:] else: Canvas.temporaryLength = 0 Canvas.addRoadDirection = 0 if Canvas.editRoad: Canvas.highlightGrid(1, 1) # Grid highlight size GMfun.insertDrawTopMostQueue(Canvas.editRoadText, (5, 25)) # Instructions # When mouse is held, draw selection rectangle if GMvar.mouseState[0]: del Canvas.tempRoadNodes[:] rectSize = [ a - b for a, b in zip(GMvar.latestMouse, GMvar.latestMouseLeft) ] rectSurface = pygame.Surface([abs(num) for num in rectSize]) rectSurface.set_alpha(100) rectSurface.fill((84, 184, 214)) rectCoords = GMvar.latestMouseLeft rectCoords = [ a + b if b < 0 else a for a, b in zip(rectCoords, rectSize) ] GMvar.mainScreenBuffer.blit(rectSurface, rectCoords) rectCoords = [ a + b for a, b in zip(rectCoords, MainCameraSurface.cameraCoords) ] Canvas.selectionRect = [ *rectCoords, *[ a + b for a, b in zip([abs(num) for num in rectSize], rectCoords) ] ] # When mouse is released, all the roads intersecting and the nodes inside of the selection is copied into a list if not GMvar.mouseState[0] and len(Canvas.selectionRect) > 0: # Make a rectangle shapely object from the selection made rectangleGeometry = box(*Canvas.selectionRect) # Check if nodes / line intersection is in selection for nodes in Canvas.roadNodes: for connectedNodes in nodes.connectedNodes.keys(): line = LineString( [nodes.coords, connectedNodes.coords]) # If line is intersecting with selection rect, then append to list if line.intersects(rectangleGeometry): Canvas.tempRoadNodes.append(nodes) break # If node is in selection rect, then append to list if nodes.coords[0] > Canvas.selectionRect[ 0] and nodes.coords[0] < Canvas.selectionRect[2]: if nodes.coords[1] > Canvas.selectionRect[ 1] and nodes.coords[1] < Canvas.selectionRect[ 3]: Canvas.tempRoadNodes.append(nodes) # Delete selection rect if mouse is not clicked if not GMvar.mouseState[0]: del Canvas.selectionRect[:] # Recreate new canvas.roadnodes without anything in canvas temproadnodes. so, basically Canvas.roadNodes = Canvas.roadNodes - Canvas.tempRoadNodes if pygame.K_DELETE in GMvar.keyboardPressedStates or pygame.K_BACKSPACE in GMvar.keyboardPressedStates and len( Canvas.tempRoadNodes) > 0: # If an element of roadnodes is in temproadnodes, delete the connectedRoads element of the roadnodes' backnode. # for i in range(len(Canvas.roadNodes)): # if Canvas.roadNodes[i] in Canvas.tempRoadNodes: # for j in range(len(Canvas.roadNodes[i].backNodes)): # del Canvas.roadNodes[i].backNodes[j].connectedNodes[Canvas.roadNodes[i]] # NEED SOME FIXING HOMIE # Delete from roadnodes Canvas.roadNodes = [ nodes for nodes in Canvas.roadNodes if nodes not in Canvas.tempRoadNodes ] # Delete any reference to deleted roads, to avoid car crossing the road even after deleted. # Dont forget to delete cars too. for deletedNodes in Canvas.tempRoadNodes: deletedNodes.connectedNodes = {} deletedCars = 0 for i in range(len(Canvas.cars)): i -= deletedCars if Canvas.cars[i].nodeAnchor == deletedNodes: # Delete from collision grid gridPos = tuple([ Canvas.cars[i].coords[j] // Car.collisionGridSize[j] for j in range(2) ]) del Car.carCollisionGrid[gridPos][ Car.carCollisionGrid[gridPos].index( Canvas.cars[i])] # Finally, delete form Canvas' list Canvas.cars.pop(i) deletedCars += 1 # add 1 to i deletedSpawners = 0 for i in range(len(Canvas.carSpawners)): i -= deletedSpawners if Canvas.carSpawners[i].nodeAnchor == deletedNodes: Canvas.carSpawners.pop(i) deletedSpawners += 1 deletedStopLights = 0 for i in range(len(Canvas.stopLights)): i -= deletedStopLights if Canvas.stopLights[i].nodeAnchor == deletedNodes: gridPos = tuple([ Canvas.stopLights[i].coords[j] // Car.collisionGridSize[j] for j in range(2) ]) del Car.carCollisionGrid[gridPos][ Car.carCollisionGrid[gridPos].index( Canvas.stopLights[i])] Canvas.stopLights.pop(i) deletedStopLights += 1 del Canvas.tempRoadNodes[:] else: del Canvas.selectionRect[:] if Canvas.addCarSpawner: if GMvar.mouseStateSingle[0]: selected = selectRoad(MainCameraSurface.getRealMouseCoords(), Canvas.roadNodes, 16) if selected != None: node, connectedNode, selectedCoord = selected Canvas.carSpawners.append( CarSpawner(node, selectedCoord, kmhToPixels(40), 30)) if Canvas.addCar: if GMvar.mouseStateSingle[0]: try: selected = selectRoad( MainCameraSurface.getRealMouseCoords(), Canvas.roadNodes, 16) except: selected = None if selected != None: node, connectedNode, selectedCoord = selected anotherCarIsNear = False carChecklist = [] gridPos = tuple([ int(selectedCoord[i] // Car.collisionGridSize[i]) for i in range(2) ]) for i in range(-1, 2): for j in range(-1, 2): try: carChecklist += Car.carCollisionGrid[tuple( [gridPos[0] + i, gridPos[1] + j])] except KeyError: pass for cars in carChecklist: pointToCarVector = pygame.math.Vector2([ a - b for a, b in zip(selectedCoord, cars.coords) ]) if pointToCarVector.length_squared() < 40**2: anotherCarIsNear = True del carChecklist if not anotherCarIsNear: # Search for the absolute end of the road (curEndNode) longestLength = 0 curEndNode: StreetNodes = None for connected in node.connectedNodes: curLength = node.connectedNodes[connected][ 0].length_squared() if curLength > longestLength: curEndNode = connected longestLength = curLength # Define start point and end point lineToCheck = LineString([[*selectedCoord], [*curEndNode.coords]]) roadSplitChoices = [] for connected in node.connectedNodes: if Point(connected.coords).intersects(lineToCheck): roadSplitChoices.append(connected) Canvas.cars.append( Car( node, roadSplitChoices[random.randint( 0, len(roadSplitChoices) - 1)], kmhToPixels(40), selectedCoord, GMvar.mainScreenBuffer)) del roadSplitChoices # Delete references if Canvas.addStopLight: if GMvar.mouseStateSingle[0]: selected = selectRoad(MainCameraSurface.getRealMouseCoords(), Canvas.roadNodes, 16) if selected != None: node, connectedNode, selectedCoord = selected gridPos = tuple([ int(selectedCoord[i] // Car.collisionGridSize[i]) for i in range(2) ]) stopLight = StopLight(node, GMvar.mainScreenBuffer, selectedCoord, 5, 10) try: Car.carCollisionGrid[gridPos].append(stopLight) except KeyError: Car.carCollisionGrid[gridPos] = [stopLight] Canvas.stopLights.append(stopLight) if Canvas.resetStopLight: for stopLights in Canvas.stopLights: stopLights.go = True stopLights.timer = GMfun.Timer(stopLights.greenDuration * 1000) Canvas.drawRoads(Canvas.roadNodes, (30, 30, 30)) Canvas.drawRoads(Canvas.tempRoadNodes, (50, 150, 50) if Canvas.newRoad else (52, 192, 217)) # Update and draw CarSpawners for spawners in Canvas.carSpawners: spawners.update(Canvas.cars, GMvar.mainScreenBuffer, MainCameraSurface.cameraCoords) # Update and draw cars deletedCars = 0 for i in range(len(Canvas.cars)): # If car has reached its end-destination then i -= deletedCars if Canvas.cars[i].update(MainCameraSurface.cameraCoords): # Delete car from list. Then, index is subtracted by 1, so not outOfRangeError Canvas.cars.pop(i) deletedCars += 1 # Update stoplights for stopLights in Canvas.stopLights: stopLights.update(MainCameraSurface.cameraCoords)