import pygame import math pygame.init() # Screen setup WIDTH, HEIGHT = 1800, 1000 win = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("Grapple Game") clock = pygame.time.Clock() # Load images background = pygame.image.load("img/city.jpg") background = pygame.transform.scale(background, (WIDTH, HEIGHT)) building1_img = pygame.image.load("Building1.png") building2_img = pygame.image.load("Building2.png") crane_img = pygame.image.load("crane.png").convert_alpha() truck_img = pygame.image.load("truck.png").convert_alpha() # Make sure filename is correct # Scale crane taller and push left & down (visuals) scale_width = 750 scale_height = 1100 crane_img = pygame.transform.scale(crane_img, (scale_width, scale_height)) # Position crane (pushed left and down) crane_x = -30 crane_y = HEIGHT - scale_height + 50 # Rect for crane position (no collision) left_building_pos = pygame.Rect(crane_x, crane_y, scale_width, scale_height) middle_building = pygame.Rect(700, 500, 400, HEIGHT - 500) building1_img = pygame.transform.scale(building1_img, (middle_building.width, middle_building.height)) right_building_y = 700 right_building_height = HEIGHT - 600 right_building = pygame.Rect(1300, right_building_y, 350, right_building_height) building2_img = pygame.transform.scale(building2_img, (right_building.width, right_building.height)) # Scale and position truck (adjust these to size and move the truck) truck_scale_width = 250 # width of truck image truck_scale_height = 150 # height of truck image truck_img = pygame.transform.scale(truck_img, (truck_scale_width, truck_scale_height)) # Position truck relative to crane (adjust to move) truck_x = crane_x + 100 # move horizontally relative to crane_x truck_y = crane_y + scale_height - truck_scale_height + 20 # vertical position at bottom of crane plus offset truck_rect = pygame.Rect(truck_x, truck_y, truck_scale_width, truck_scale_height) # Buildings with collision (exclude crane and truck) all_buildings = [middle_building, right_building] # Swing zone rect on crane hook (where player can grapple) swing_zone_width = 60 swing_zone_height = 30 swing_zone_x = crane_x + scale_width - 75 # tweak to position near crane hook visually swing_zone_y = crane_y + 270 # tweak vertical position swing_zone = pygame.Rect(swing_zone_x, swing_zone_y, swing_zone_width, swing_zone_height) # Player radius and physics radius = 15 gravity = pygame.Vector2(0, 0.5) player_vel = pygame.Vector2(0, 0) # Spawn player on top of middle building player_pos = pygame.Vector2(middle_building.centerx, middle_building.top - radius) # Grapple grapple_state = "idle" grapple_target = pygame.Vector2(0, 0) grapple_tip = pygame.Vector2(0, 0) grapple_speed = 25 pull_speed = 1.0 reached_anchor_distance = 25 def draw(): win.blit(background, (0, 0)) win.blit(crane_img, left_building_pos.topleft) # crane image win.blit(truck_img, truck_rect.topleft) # truck image win.blit(building1_img, middle_building.topleft) win.blit(building2_img, right_building.topleft) # Draw rect around truck for debugging pygame.draw.rect(win, (255, 255, 255), truck_rect, 2) # Draw swing zone (invisible, but draw white rect for debug) pygame.draw.rect(win, (255, 255, 255), swing_zone, 2) if grapple_state in ("shooting", "pulling"): pygame.draw.line(win, (0, 0, 0), player_pos, grapple_tip, 2) pygame.draw.circle(win, (100, 100, 100), (int(grapple_tip.x), int(grapple_tip.y)), 5) pygame.draw.circle(win, (255, 0, 0), (int(player_pos.x), int(player_pos.y)), radius) pygame.display.flip() def collide_with_buildings(circle_pos, circle_radius): circle_rect = pygame.Rect(circle_pos.x - circle_radius, circle_pos.y - circle_radius, circle_radius*2, circle_radius*2) for b in all_buildings: if circle_rect.colliderect(b): return b return None def physics(): global player_pos, player_vel player_vel += gravity # Horizontal movement new_x = player_pos.x + player_vel.x temp_pos = pygame.Vector2(new_x, player_pos.y) collided_building = collide_with_buildings(temp_pos, radius) if collided_building: if player_vel.x > 0: new_x = collided_building.left - radius else: new_x = collided_building.right + radius player_vel.x = 0 player_pos.x = new_x # Vertical movement new_y = player_pos.y + player_vel.y temp_pos = pygame.Vector2(player_pos.x, new_y) collided_building = collide_with_buildings(temp_pos, radius) if collided_building: if player_vel.y > 0: new_y = collided_building.top - radius else: new_y = collided_building.bottom + radius player_vel.y = 0 player_pos.y = new_y # Screen boundaries if player_pos.x - radius < 0: player_pos.x = radius player_vel.x *= -0.5 elif player_pos.x + radius > WIDTH: player_pos.x = WIDTH - radius player_vel.x *= -0.5 if player_pos.y - radius < 0: player_pos.y = radius player_vel.y *= -0.5 elif player_pos.y + radius > HEIGHT: player_pos.y = HEIGHT - radius player_vel.y *= -0.5 def grapple_logic(): global grapple_state, grapple_tip, player_pos, player_vel if grapple_state == "shooting": direction = (grapple_target - grapple_tip).normalize() grapple_tip += direction * grapple_speed if (grapple_tip - grapple_target).length() < grapple_speed: grapple_tip = grapple_target grapple_state = "pulling" elif grapple_state == "pulling": direction = grapple_tip - player_pos dist = direction.length() if dist < reached_anchor_distance: player_vel = pygame.Vector2(0, 0) grapple_state = "idle" else: direction.normalize_ip() player_vel += direction * pull_speed # Main game loop running = True while running: clock.tick(60) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: mouse_pos = pygame.Vector2(pygame.mouse.get_pos()) grapple_allowed = False # Allow grapple if mouse clicks on any building for b in all_buildings: if b.collidepoint(mouse_pos): grapple_allowed = True break # Also allow grapple if click inside swing zone (crane hook) if not grapple_allowed and swing_zone.collidepoint(mouse_pos): grapple_allowed = True if grapple_allowed: grapple_state = "shooting" grapple_target = mouse_pos grapple_tip = player_pos.copy() if event.type == pygame.MOUSEBUTTONDOWN and event.button == 3: grapple_state = "idle" physics() grapple_logic() draw() pygame.quit()