# Kerbal Space Program 2D Inspired Game (Full Version) # Pygame + Simplified Orbital Physics + Part Builder + Map View import pygame import math import sys # === Initialization === pygame.init() WIDTH, HEIGHT = 1200, 800 screen = pygame.display.set_mode((WIDTH, HEIGHT)) clock = pygame.time.Clock() font = pygame.font.SysFont("consolas", 20) # === Constants === PLANET_RADIUS = 100 PLANET_POS = pygame.Vector2(WIDTH//2, HEIGHT + PLANET_RADIUS*2) G = 0.1 # Gravitational constant ATMOSPHERE_HEIGHT = 300 # === Part Definitions === class Part: def __init__(self, name, mass, fuel, thrust, isp): self.name = name self.mass = mass self.fuel = fuel self.max_fuel = fuel self.thrust = thrust self.isp = isp # Sample parts COMMAND_POD = Part("Pod", mass=500, fuel=0, thrust=0, isp=0) FUEL_TANK = Part("Tank", mass=200, fuel=500, thrust=0, isp=0) ENGINE = Part("Engine", mass=100, fuel=0, thrust=5000, isp=300) # === Rocket === class Rocket: def __init__(self, parts): self.parts = parts self.pos = pygame.Vector2(WIDTH//2, HEIGHT - 150) self.vel = pygame.Vector2(0, 0) self.angle = -90 # Degrees self.rotation_speed = 1.5 self.thrusting = False def total_mass(self): return sum(part.mass + part.fuel for part in self.parts) def apply_thrust(self): for part in self.parts: if part.thrust > 0 and part.fuel > 0: # Burn fuel burn = min(part.fuel, 0.1) part.fuel -= burn # Thrust force thrust = part.thrust * (burn / part.isp) rad = math.radians(self.angle) fx = math.cos(rad) * thrust fy = math.sin(rad) * thrust acc = pygame.Vector2(fx, fy) / self.total_mass() self.vel += acc break # Only one engine for now def update(self): # Gravity dir_to_planet = PLANET_POS - self.pos dist = dir_to_planet.length() if dist > PLANET_RADIUS: gravity_force = G * self.total_mass() / (dist**2) gravity = dir_to_planet.normalize() * gravity_force self.vel += gravity # Thrust if self.thrusting: self.apply_thrust() # Drag altitude = dist - PLANET_RADIUS if altitude < ATMOSPHERE_HEIGHT: drag_coef = (ATMOSPHERE_HEIGHT - altitude) / ATMOSPHERE_HEIGHT self.vel *= 1 - (drag_coef * 0.01) # Update position self.pos += self.vel def draw(self, surface, cam_pos): x, y = self.pos - cam_pos rad = math.radians(self.angle) points = [ (x + math.cos(rad)*10, y + math.sin(rad)*10), (x + math.cos(rad + 2.5)*10, y + math.sin(rad + 2.5)*10), (x + math.cos(rad - 2.5)*10, y + math.sin(rad - 2.5)*10) ] pygame.draw.polygon(surface, (200, 200, 255), points) if self.thrusting: tx = x - math.cos(rad)*20 ty = y - math.sin(rad)*20 pygame.draw.circle(surface, (255, 100, 0), (int(tx), int(ty)), 5) # === Main Loop === rocket = Rocket([COMMAND_POD, FUEL_TANK, ENGINE]) cam_pos = pygame.Vector2(0, 0) map_view = False running = True while running: dt = clock.tick(60) screen.fill((0, 0, 0)) # Event Handling for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_m: map_view = not map_view keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: rocket.angle -= rocket.rotation_speed if keys[pygame.K_RIGHT]: rocket.angle += rocket.rotation_speed rocket.thrusting = keys[pygame.K_UP] rocket.update() # Camera follows in normal mode if not map_view: cam_pos = rocket.pos - pygame.Vector2(WIDTH//2, HEIGHT//2) else: cam_pos = PLANET_POS - pygame.Vector2(WIDTH//2, HEIGHT//2) # Draw planet pygame.draw.circle(screen, (0, 100, 0), (int(PLANET_POS.x - cam_pos.x), int(PLANET_POS.y - cam_pos.y)), PLANET_RADIUS) # Draw rocket rocket.draw(screen, cam_pos) # UI altitude = (rocket.pos - PLANET_POS).length() - PLANET_RADIUS vel_text = font.render(f"Vel: {rocket.vel.length():.1f} m/s", True, (255,255,255)) alt_text = font.render(f"Alt: {altitude:.1f} m", True, (255,255,255)) screen.blit(vel_text, (10, 10)) screen.blit(alt_text, (10, 30)) mode_text = font.render("Map View" if map_view else "Flight View", True, (255,255,0)) screen.blit(mode_text, (10, 50)) pygame.display.flip() pygame.quit() sys.exit()