hashir-Ali's picture
Upload folder using huggingface_hub
f386f57 verified
import pygame
import math
import random
import numpy as np
import time
# Game constants
WIDTH, HEIGHT = 800, 600
WHITE = (255, 255, 255)
RED = (255, 0, 0)
BROWN = (139, 69, 19)
# Terrain generation
terrain_height = 50
terrain_points = [terrain_height + random.randint(5, 15) for _ in range(WIDTH // 50)]
terrain = np.interp(range(WIDTH), np.linspace(0, WIDTH, len(terrain_points)), terrain_points)
class Rocket:
def __init__(self):
# Rocket properties
self.width = 40
self.height = 80
self.x = WIDTH // 2
self.y = HEIGHT // 2 # Start from middle height
self.angle = 0
self.velocity_x = 0
self.velocity_y = 0
self.gravity = 10 # Gravity pulls downward, adjusted for faster game
self.thrust_power = 30 # Thrust power, adjusted for faster game
self.angular_velocity = 0
self.thrusting = False # Flag for thrusting
self.rotation_speed = 1 # Rotation speed, adjusted for faster game
def update(self, thrusting, rotate_left, rotate_right, time_step=0.1):
"""Update the rocket state based on user inputs."""
self.thrusting = thrusting # Update thrusting flag
# Apply gravity to velocity_y (pulls downward)
self.velocity_y -= self.gravity * time_step
# Apply thrust only when thrusting is active
if self.thrusting:
# Thrust aligns with rocket's nose direction
self.velocity_y += self.thrust_power * math.cos(math.radians(self.angle)) * time_step
self.velocity_x += self.thrust_power * math.sin(math.radians(self.angle)) * time_step
# Update position based on velocity
self.x += self.velocity_x * time_step
self.y += self.velocity_y * time_step
# self.x = max(0, min(self.x, WIDTH))
# self.y = max(0, min(self.y, HEIGHT))
# Apply rotation, scaled by time_step
if rotate_left:
self.angle += self.rotation_speed * time_step
if rotate_right:
self.angle -= self.rotation_speed * time_step
def draw(self, screen):
"""Draw the rocket on the screen."""
rocket_surface = pygame.Surface((self.width, self.height), pygame.SRCALPHA)
pygame.draw.polygon(rocket_surface, RED, [
(self.width // 2, 0), # Nose
(0, self.height - 20), # Bottom left
(self.width, self.height - 20) # Bottom right
])
pygame.draw.rect(rocket_surface, (0, 0, 0), (self.width // 4, self.height - 20, self.width // 2, 20)) # Body
# Draw thrust flames if thrusting
if self.thrusting: # Only draw flames when thrusting
pygame.draw.polygon(rocket_surface, (255, 165, 0), [
(self.width // 4, self.height - 20),
(self.width // 2, self.height),
(3 * self.width // 4, self.height - 20)
])
rotated_rocket = pygame.transform.rotate(rocket_surface, self.angle)
rect = rotated_rocket.get_rect(center=(self.x, HEIGHT - self.y)) # Invert y for drawing
screen.blit(rotated_rocket, rect.topleft)
def state(self):
return [self.x, self.y, self.angle, self.velocity_x, self.velocity_y]
class RocketLandingGame:
def __init__(self,render):
self.render=render
if render:
pygame.init()
self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Rocket Landing Simulation")
self.clock = pygame.time.Clock()
self.running = True
self.game_over = False
self.win = False
self.rocket = Rocket() # Create the rocket instance
self.action_log = [] # Action log to track the game's state
def draw_terrain(self):
"""Draw the terrain at the bottom of the screen."""
for i in range(len(terrain) - 1):
pygame.draw.line(self.screen, BROWN, (i, HEIGHT - terrain[i]), (i + 1, HEIGHT - terrain[i + 1]), 3)
def returnState(self):
return self.rocket.state()
def game_step(self, thrusting, rotate_left, rotate_right, time_step=0.5):
"""Perform one step in the game (update physics, game state)."""
if not self.game_over:
reward = 0 # Initialize reward
self.rocket.update(thrusting, rotate_left, rotate_right, time_step)
# Check for landing or crash
rocket_bottom_y = self.rocket.y - self.rocket.height // 2
x_index = int(self.rocket.x)
terrain_y_at_x = terrain[x_index] if 0 <= x_index < WIDTH else float('inf')
if rocket_bottom_y <= terrain_y_at_x:
self.rocket.y = terrain_y_at_x + self.rocket.height // 2
if abs(self.rocket.velocity_y) <= 5.0 and abs(self.rocket.velocity_x) <= 5 and abs(self.rocket.angle) <= 10:
self.game_over = True
self.win = True # Successful landing
reward = 5 # Positive reward for successful landing
else:
self.game_over = True # Rocket destroyed
reward = -2 # Negative reward for crash
else:
if thrusting:
reward -= 0.002
else:
reward=0
reward += (5 - abs(self.rocket.velocity_y)) * 0.01 # Reward for reducing vertical speed
reward += (5 - abs(self.rocket.velocity_x)) * 0.01 # Reward for reducing horizontal speed
reward+=1/(self.rocket.y-99)
if abs(self.rocket.angle) <= 5: # Small angle threshold
reward += 0.02 # Reward for improving angle control
else:
reward -= 0.02 # Small penalty for poor angle control
if self.rocket.y>400:
self.game_over = True
reward = -2
if self.rocket.x>500 or self.rocket.x<300:
self.game_over = True
reward = -2
return reward, self.game_over, self.win
def draw_info(self):
"""Draw the game info (coordinates, angle, velocity) on the screen."""
font = pygame.font.SysFont('Arial', 18)
info_text = [
f"X: {self.rocket.x:.2f} Y: {self.rocket.y:.2f}",
f"Angle: {self.rocket.angle:.2f}",
f"Velocity X: {self.rocket.velocity_x:.2f} Velocity Y: {self.rocket.velocity_y:.2f}",
f"Thrusting: {'Yes' if self.rocket.thrusting else 'No'}",
]
for i, text in enumerate(info_text):
label = font.render(text, True, (0, 0, 0))
self.screen.blit(label, (10, 10 + i * 20)) # Display info
def draw_restart_button(self):
"""Draw the restart button if the game is over."""
font = pygame.font.SysFont('Arial', 30)
restart_text = font.render("Restart", True, (255, 255, 255))
button_rect = pygame.Rect(WIDTH // 2 - 75, HEIGHT // 2 - 50, 150, 50)
pygame.draw.rect(self.screen, (0, 128, 0), button_rect) # Green button
self.screen.blit(restart_text, button_rect.move(25, 10)) # Center the text on button
return button_rect
def add_to_action_log(self, action):
"""Add actions to the action log."""
timestamp = time.strftime("%H:%M:%S", time.gmtime(time.time()))
self.action_log.append(f"{action}")