Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import json
- import math
- import os
- import random
- import pygame
- pygame.init()
- # =========================
- # SCREEN
- # =========================
- SCREEN_WIDTH = 1000
- SCREEN_HEIGHT = 600
- screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
- pygame.display.set_caption("Dragon Adventure")
- clock = pygame.time.Clock()
- # =========================
- # COLORS
- # =========================
- SKY_BLUE = (135, 206, 235)
- OCEAN_BLUE = (35, 145, 210)
- SAND = (238, 218, 170)
- GRASS = (80, 170, 80)
- WHITE = (255, 255, 255)
- BLACK = (20, 20, 20)
- GOLD = (255, 215, 0)
- ENERGY_BLUE = (80, 200, 255)
- DARK_GRAY = (50, 50, 50)
- GRAY = (90, 90, 90)
- RED = (200, 60, 60)
- GREEN = (60, 180, 80)
- # =========================
- # WORLD
- # =========================
- WORLD_WIDTH = 2400
- WORLD_HEIGHT = 900
- # =========================
- # STORMFIN IMAGE
- # =========================
- IMAGE_PATH = r"C:\Users\johns\New folder\anime_art_of_Create_a_highly_d.png"
- stormfin_image = None
- if os.path.exists(IMAGE_PATH):
- try:
- stormfin_image = pygame.image.load(IMAGE_PATH).convert_alpha()
- except pygame.error:
- stormfin_image = None
- # =========================
- # ALPHA PITY
- # =========================
- ALPHA_CHANCE = 500
- ALPHA_PITY_LIMIT = 1000
- alpha_pity = 0
- # =========================
- # STORMFIN GENERATION
- # =========================
- def generate_stormfin():
- global alpha_pity
- # Guaranteed Alpha after 1000 failed rolls
- if alpha_pity >= ALPHA_PITY_LIMIT:
- alpha_pity = 0
- return "Alpha"
- # Normal 1 in 500 Alpha chance
- alpha_roll = random.randint(1, ALPHA_CHANCE)
- if alpha_roll == 389:
- alpha_pity = 0
- return "Alpha"
- # Failed Alpha roll
- alpha_pity += 1
- # 50/50 Male or Female
- sex_roll = random.randint(1, 2)
- if sex_roll == 1:
- return "Male"
- return "Female"
- stormfin_type = generate_stormfin()
- # =========================
- # STORMFIN SIZE
- # =========================
- def get_stormfin_size(stormfin_type):
- if stormfin_type == "Male":
- return 100
- if stormfin_type == "Female":
- return 260
- return 180
- stormfin_size = get_stormfin_size(stormfin_type)
- # =========================
- # STORMFIN SPEED
- # =========================
- def get_stormfin_speed(stormfin_type):
- if stormfin_type == "Male":
- return 10
- if stormfin_type == "Female":
- return 2.5
- return 5
- player_speed = get_stormfin_speed(stormfin_type)
- # Sprint is exactly twice normal speed
- sprint_speed = player_speed * 2
- # =========================
- # SPRINT ENERGY
- # =========================
- SPRINT_ENERGY_COST = 1
- SPRINT_DRAIN_FRAMES = 20
- sprint_frame_counter = 0
- # =========================
- # LIGHTNING RANGE
- # =========================
- BASE_LIGHTNING_RANGE = 300
- def get_lightning_range(stormfin_type):
- if stormfin_type == "Male":
- return BASE_LIGHTNING_RANGE * 0.5
- if stormfin_type == "Female":
- return BASE_LIGHTNING_RANGE * 2
- return BASE_LIGHTNING_RANGE
- lightning_range = get_lightning_range(stormfin_type)
- # =========================
- # LIGHTNING ENERGY COST
- # =========================
- def get_lightning_cost(stormfin_type):
- if stormfin_type == "Male":
- return 5
- if stormfin_type == "Female":
- return 20
- return 10
- lightning_cost = get_lightning_cost(stormfin_type)
- # =========================
- # PLAYER
- # =========================
- player_x = 1200
- player_y = 475
- facing_direction = 1
- jumping = False
- jump_velocity = 0
- gravity = 0.6
- jump_strength = 12
- # =========================
- # ENERGY
- # =========================
- MAX_ENERGY = 100
- energy = MAX_ENERGY
- ENERGY_REGEN_TIME = 2000
- last_energy_regen = pygame.time.get_ticks()
- # =========================
- # ATTACK
- # =========================
- ATTACK_DURATION = 150
- attacking = False
- attack_start_time = 0
- # =========================
- # SAVE / LOAD
- # =========================
- SAVE_FILE = "stormfin_save.json"
- def save_game():
- data = {
- "stormfin_type": stormfin_type,
- "x": player_x,
- "y": player_y,
- "energy": energy,
- "facing_direction": facing_direction,
- "jumping": jumping,
- "jump_velocity": jump_velocity,
- "alpha_pity": alpha_pity,
- }
- with open(SAVE_FILE, "w") as file:
- json.dump(data, file, indent=4)
- print("Game saved.")
- def load_game():
- global stormfin_type
- global player_x
- global player_y
- global energy
- global facing_direction
- global jumping
- global jump_velocity
- global stormfin_size
- global player_speed
- global sprint_speed
- global lightning_range
- global lightning_cost
- global sprint_frame_counter
- global last_energy_regen
- global alpha_pity
- if not os.path.exists(SAVE_FILE):
- print("No save file found.")
- return
- with open(SAVE_FILE, "r") as file:
- data = json.load(file)
- stormfin_type = data["stormfin_type"]
- player_x = data["x"]
- player_y = data["y"]
- energy = data["energy"]
- facing_direction = data["facing_direction"]
- jumping = data["jumping"]
- jump_velocity = data["jump_velocity"]
- # Older save files may not have this
- alpha_pity = data.get("alpha_pity", 0)
- stormfin_size = get_stormfin_size(stormfin_type)
- player_speed = get_stormfin_speed(stormfin_type)
- sprint_speed = player_speed * 2
- lightning_range = get_lightning_range(stormfin_type)
- lightning_cost = get_lightning_cost(stormfin_type)
- sprint_frame_counter = 0
- last_energy_regen = pygame.time.get_ticks()
- print("Game loaded.")
- # =========================
- # ISLAND
- # =========================
- SAND_CENTER_X = 1200
- SAND_CENTER_Y = 500
- SAND_RADIUS_X = 950
- SAND_RADIUS_Y = 260
- GRASS_CENTER_X = 1200
- GRASS_CENTER_Y = 475
- GRASS_RADIUS_X = 850
- GRASS_RADIUS_Y = 220
- def point_inside_ellipse(x, y, center_x, center_y, radius_x, radius_y):
- if radius_x == 0 or radius_y == 0:
- return False
- value = ((x - center_x) ** 2) / (radius_x**2) + ((y - center_y) ** 2) / (
- radius_y**2
- )
- return value <= 1
- def point_inside_island(x, y):
- sand = point_inside_ellipse(
- x,
- y,
- SAND_CENTER_X,
- SAND_CENTER_Y,
- SAND_RADIUS_X,
- SAND_RADIUS_Y,
- )
- grass = point_inside_ellipse(
- x,
- y,
- GRASS_CENTER_X,
- GRASS_CENTER_Y,
- GRASS_RADIUS_X,
- GRASS_RADIUS_Y,
- )
- return sand or grass
- def stormfin_inside_island(x, y):
- body_radius = stormfin_size * 0.25
- points = [
- (x, y),
- (x - body_radius, y),
- (x + body_radius, y),
- (x, y - body_radius),
- (x, y + body_radius),
- ]
- for point_x, point_y in points:
- if not point_inside_island(point_x, point_y):
- return False
- return True
- # =========================
- # DECORATIONS
- # =========================
- rocks = [
- (300, 500),
- (600, 360),
- (900, 570),
- (1300, 350),
- (1600, 580),
- (1900, 390),
- (2150, 500),
- ]
- trees = [
- (450, 420),
- (750, 470),
- (1050, 400),
- (1450, 450),
- (1750, 430),
- (2050, 470),
- ]
- bushes = [
- (350, 430),
- (850, 520),
- (1150, 500),
- (1550, 390),
- (1850, 520),
- (2200, 440),
- ]
- # =========================
- # DRAW ENVIRONMENT
- # =========================
- def draw_environment(camera_x, camera_y):
- screen.fill(SKY_BLUE)
- # Ocean
- pygame.draw.rect(
- screen,
- OCEAN_BLUE,
- (-camera_x, 300 - camera_y, WORLD_WIDTH, WORLD_HEIGHT),
- )
- # Ocean waves
- for x in range(0, WORLD_WIDTH, 80):
- screen_x = x - camera_x
- pygame.draw.arc(
- screen,
- (180, 225, 245),
- (screen_x, 320 - camera_y, 60, 20),
- math.pi,
- math.pi * 2,
- 2,
- )
- # Sand
- sand_rect = pygame.Rect(
- SAND_CENTER_X - SAND_RADIUS_X - camera_x,
- SAND_CENTER_Y - SAND_RADIUS_Y - camera_y,
- SAND_RADIUS_X * 2,
- SAND_RADIUS_Y * 2,
- )
- pygame.draw.ellipse(screen, SAND, sand_rect)
- # Grass
- grass_rect = pygame.Rect(
- GRASS_CENTER_X - GRASS_RADIUS_X - camera_x,
- GRASS_CENTER_Y - GRASS_RADIUS_Y - camera_y,
- GRASS_RADIUS_X * 2,
- GRASS_RADIUS_Y * 2,
- )
- pygame.draw.ellipse(screen, GRASS, grass_rect)
- # Rocks
- for rock_x, rock_y in rocks:
- if not point_inside_island(rock_x, rock_y):
- continue
- screen_x = rock_x - camera_x
- screen_y = rock_y - camera_y
- pygame.draw.circle(
- screen,
- (100, 100, 100),
- (int(screen_x), int(screen_y)),
- 18,
- )
- # Trees
- for tree_x, tree_y in trees:
- if not point_inside_island(tree_x, tree_y):
- continue
- screen_x = tree_x - camera_x
- screen_y = tree_y - camera_y
- pygame.draw.rect(
- screen,
- (100, 70, 35),
- (int(screen_x - 8), int(screen_y), 16, 45),
- )
- pygame.draw.circle(
- screen,
- (35, 120, 45),
- (int(screen_x), int(screen_y - 15)),
- 30,
- )
- # Bushes
- for bush_x, bush_y in bushes:
- if not point_inside_island(bush_x, bush_y):
- continue
- screen_x = bush_x - camera_x
- screen_y = bush_y - camera_y
- pygame.draw.circle(
- screen,
- (40, 130, 50),
- (int(screen_x - 12), int(screen_y)),
- 18,
- )
- pygame.draw.circle(
- screen,
- (45, 145, 55),
- (int(screen_x + 8), int(screen_y - 5)),
- 20,
- )
- pygame.draw.circle(
- screen,
- (35, 120, 45),
- (int(screen_x + 20), int(screen_y + 3)),
- 15,
- )
- # =========================
- # DRAW STORMFIN
- # =========================
- def draw_stormfin(camera_x, camera_y):
- screen_x = int(player_x - camera_x)
- screen_y = int(player_y - camera_y)
- if stormfin_image is not None:
- scaled_image = pygame.transform.smoothscale(
- stormfin_image,
- (stormfin_size, stormfin_size),
- )
- image_rect = scaled_image.get_rect(center=(screen_x, screen_y))
- screen.blit(scaled_image, image_rect)
- else:
- body_color = (20, 35, 90)
- fur_color = (45, 80, 180)
- pygame.draw.ellipse(
- screen,
- body_color,
- (
- screen_x - stormfin_size // 2,
- screen_y - stormfin_size // 2,
- stormfin_size,
- stormfin_size,
- ),
- )
- # Ears
- ear_size = max(10, stormfin_size // 6)
- pygame.draw.circle(
- screen,
- fur_color,
- (
- screen_x - stormfin_size // 4,
- screen_y - stormfin_size // 3,
- ),
- ear_size,
- )
- pygame.draw.circle(
- screen,
- fur_color,
- (
- screen_x + stormfin_size // 4,
- screen_y - stormfin_size // 3,
- ),
- ear_size,
- )
- # Golden eyes
- eye_size = max(5, stormfin_size // 12)
- pygame.draw.circle(
- screen,
- GOLD,
- (
- screen_x - stormfin_size // 7,
- screen_y - stormfin_size // 10,
- ),
- eye_size,
- )
- pygame.draw.circle(
- screen,
- GOLD,
- (
- screen_x + stormfin_size // 7,
- screen_y - stormfin_size // 10,
- ),
- eye_size,
- )
- # =========================
- # LIGHTNING
- # =========================
- def draw_lightning(camera_x, camera_y):
- if not attacking:
- return
- start_x = player_x + facing_direction * 25
- start_y = player_y - 10
- end_x = start_x + facing_direction * lightning_range
- end_y = start_y
- screen_start_x = int(start_x - camera_x)
- screen_start_y = int(start_y - camera_y)
- screen_end_x = int(end_x - camera_x)
- screen_end_y = int(end_y - camera_y)
- pygame.draw.line(
- screen,
- ENERGY_BLUE,
- (screen_start_x, screen_start_y),
- (screen_end_x, screen_end_y),
- 8,
- )
- pygame.draw.line(
- screen,
- WHITE,
- (screen_start_x, screen_start_y),
- (screen_end_x, screen_end_y),
- 3,
- )
- branch_length = lightning_range * 0.12
- branch_points = [0.25, 0.50, 0.75]
- for percentage in branch_points:
- branch_x = start_x + (end_x - start_x) * percentage
- branch_y = start_y
- branch_direction = random.choice([-1, 1])
- pygame.draw.line(
- screen,
- ENERGY_BLUE,
- (int(branch_x - camera_x), int(branch_y - camera_y)),
- (
- int(
- branch_x
- - camera_x
- + random.randint(5, int(branch_length)) * facing_direction
- ),
- int(
- branch_y
- - camera_y
- + branch_direction * random.randint(10, int(branch_length))
- ),
- ),
- 3,
- )
- # =========================
- # UI
- # =========================
- font = pygame.font.SysFont(None, 28)
- small_font = pygame.font.SysFont(None, 22)
- def draw_ui():
- # Stormfin type
- type_text = font.render(f"Stormfin: {stormfin_type}", True, WHITE)
- screen.blit(type_text, (20, 20))
- # Energy
- energy_text = font.render(f"Energy: {energy}/100", True, WHITE)
- screen.blit(energy_text, (20, 50))
- # Energy bar
- pygame.draw.rect(screen, BLACK, (20, 80, 200, 20))
- pygame.draw.rect(
- screen,
- ENERGY_BLUE,
- (20, 80, int(200 * (energy / MAX_ENERGY)), 20),
- )
- # Lightning range
- range_text = small_font.render(
- f"Lightning range: {int(lightning_range)}", True, WHITE
- )
- screen.blit(range_text, (20, 110))
- # Lightning cost
- cost_text = small_font.render(f"Lightning cost: {lightning_cost}", True, WHITE)
- screen.blit(cost_text, (20, 135))
- # Movement speed
- speed_text = small_font.render(f"Speed: {player_speed}", True, WHITE)
- screen.blit(speed_text, (20, 160))
- # Sprint speed
- sprint_text = small_font.render(f"Sprint speed: {sprint_speed}", True, WHITE)
- screen.blit(sprint_text, (20, 185))
- # Alpha pity
- pity_text = small_font.render(
- f"Alpha pity: {alpha_pity}/{ALPHA_PITY_LIMIT}", True, GOLD
- )
- screen.blit(pity_text, (20, 210))
- # Controls
- controls = [
- "WASD - Move",
- "Shift - Sprint",
- "Space - Jump",
- "E - Lightning",
- "1 - Save",
- "2 - Load",
- ]
- y = SCREEN_HEIGHT - 150
- for control in controls:
- text = small_font.render(control, True, WHITE)
- screen.blit(text, (20, y))
- y += 22
- # =========================
- # REROLL BUTTON
- # =========================
- reroll_button = pygame.Rect(SCREEN_WIDTH - 150, 20, 120, 40)
- def draw_reroll_button():
- pygame.draw.rect(screen, (70, 70, 70), reroll_button)
- text = small_font.render("Reroll", True, WHITE)
- text_rect = text.get_rect(center=reroll_button.center)
- screen.blit(text, text_rect)
- # =========================
- # ALPHA CONFIRMATION
- # =========================
- confirmation_active = False
- confirmation_box = pygame.Rect(300, 210, 400, 180)
- yes_button = pygame.Rect(350, 320, 120, 45)
- no_button = pygame.Rect(530, 320, 120, 45)
- def draw_confirmation():
- # Dark overlay
- overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
- overlay.fill((0, 0, 0, 150))
- screen.blit(overlay, (0, 0))
- # Confirmation box
- pygame.draw.rect(screen, DARK_GRAY, confirmation_box)
- pygame.draw.rect(screen, GOLD, confirmation_box, 3)
- # Message
- message_1 = small_font.render("Are you sure you want", True, WHITE)
- message_2 = small_font.render("to reroll your Alpha?", True, GOLD)
- screen.blit(
- message_1,
- (confirmation_box.centerx - message_1.get_width() // 2, 235),
- )
- screen.blit(
- message_2,
- (confirmation_box.centerx - message_2.get_width() // 2, 265),
- )
- # Yes button
- pygame.draw.rect(screen, GREEN, yes_button)
- yes_text = small_font.render("Yes", True, WHITE)
- screen.blit(yes_text, yes_text.get_rect(center=yes_button.center))
- # No button
- pygame.draw.rect(screen, RED, no_button)
- no_text = small_font.render("No", True, WHITE)
- screen.blit(no_text, no_text.get_rect(center=no_button.center))
- # =========================
- # REROLL STORMFIN
- # =========================
- def reroll_stormfin():
- global stormfin_type
- global stormfin_size
- global player_speed
- global sprint_speed
- global lightning_range
- global lightning_cost
- global player_x
- global player_y
- global energy
- global facing_direction
- global jumping
- global jump_velocity
- global sprint_frame_counter
- global last_energy_regen
- stormfin_type = generate_stormfin()
- stormfin_size = get_stormfin_size(stormfin_type)
- player_speed = get_stormfin_speed(stormfin_type)
- sprint_speed = player_speed * 2
- lightning_range = get_lightning_range(stormfin_type)
- lightning_cost = get_lightning_cost(stormfin_type)
- player_x = 1200
- player_y = 475
- energy = MAX_ENERGY
- facing_direction = 1
- jumping = False
- jump_velocity = 0
- sprint_frame_counter = 0
- last_energy_regen = pygame.time.get_ticks()
- print(f"Rerolled: {stormfin_type}")
- print(f"Alpha pity: {alpha_pity}/{ALPHA_PITY_LIMIT}")
- # =========================
- # MAIN LOOP
- # =========================
- running = True
- while running:
- clock.tick(60)
- # =========================
- # EVENTS
- # =========================
- for event in pygame.event.get():
- if event.type == pygame.QUIT:
- running = False
- if event.type == pygame.KEYDOWN:
- # Lightning
- if event.key == pygame.K_e:
- if energy >= lightning_cost:
- energy -= lightning_cost
- attacking = True
- attack_start_time = pygame.time.get_ticks()
- # Jump
- if event.key == pygame.K_SPACE:
- if not jumping:
- jumping = True
- jump_velocity = -jump_strength
- # Save
- if event.key == pygame.K_1:
- save_game()
- # Load
- if event.key == pygame.K_2:
- load_game()
- # =========================
- # MOUSE
- # =========================
- if event.type == pygame.MOUSEBUTTONDOWN:
- if event.button == 1:
- # Confirmation is open
- if confirmation_active:
- # YES
- if yes_button.collidepoint(event.pos):
- confirmation_active = False
- reroll_stormfin()
- # NO
- elif no_button.collidepoint(event.pos):
- confirmation_active = False
- # Normal game
- else:
- if reroll_button.collidepoint(event.pos):
- # Alpha requires confirmation
- if stormfin_type == "Alpha":
- confirmation_active = True
- else:
- reroll_stormfin()
- # =========================
- # ATTACK TIMER
- # =========================
- if attacking:
- current_time = pygame.time.get_ticks()
- if current_time - attack_start_time >= ATTACK_DURATION:
- attacking = False
- # =========================
- # MOVEMENT
- # =========================
- keys = pygame.key.get_pressed()
- sprinting = keys[pygame.K_LSHIFT] and energy > 0
- # =========================
- # SPRINT ENERGY DRAIN
- # =========================
- if sprinting:
- sprint_frame_counter += 1
- if sprint_frame_counter >= SPRINT_DRAIN_FRAMES:
- if energy > 0:
- energy -= SPRINT_ENERGY_COST
- sprint_frame_counter = 0
- else:
- sprint_frame_counter = 0
- # =========================
- # ENERGY REGEN
- # =========================
- current_time = pygame.time.get_ticks()
- if not sprinting:
- if current_time - last_energy_regen >= ENERGY_REGEN_TIME:
- if energy < MAX_ENERGY:
- energy += 1
- last_energy_regen = current_time
- else:
- last_energy_regen = current_time
- # =========================
- # SPEED
- # =========================
- if sprinting:
- speed = sprint_speed
- else:
- speed = player_speed
- # =========================
- # MOVEMENT INPUT
- # =========================
- move_x = 0
- move_y = 0
- if keys[pygame.K_a]:
- move_x -= speed
- facing_direction = -1
- if keys[pygame.K_d]:
- move_x += speed
- facing_direction = 1
- if keys[pygame.K_w]:
- move_y -= speed
- if keys[pygame.K_s]:
- move_y += speed
- # Horizontal collision
- new_x = player_x + move_x
- if stormfin_inside_island(new_x, player_y):
- player_x = new_x
- # Vertical movement
- new_y = player_y + move_y
- if stormfin_inside_island(player_x, new_y):
- player_y = new_y
- # =========================
- # JUMP PHYSICS
- # =========================
- if jumping:
- jump_velocity += gravity
- jump_y = player_y + jump_velocity
- if stormfin_inside_island(player_x, jump_y):
- player_y = jump_y
- else:
- jumping = False
- jump_velocity = 0
- # =========================
- # CAMERA
- # =========================
- camera_x = player_x - SCREEN_WIDTH // 2
- camera_y = player_y - SCREEN_HEIGHT // 2
- camera_x = max(0, min(camera_x, WORLD_WIDTH - SCREEN_WIDTH))
- camera_y = max(0, min(camera_y, WORLD_HEIGHT - SCREEN_HEIGHT))
- # =========================
- # DRAW
- # =========================
- draw_environment(camera_x, camera_y)
- draw_stormfin(camera_x, camera_y)
- draw_lightning(camera_x, camera_y)
- draw_ui()
- draw_reroll_button()
- # Confirmation dialog goes last
- # so it appears above everything.
- if confirmation_active:
- draw_confirmation()
- pygame.display.flip()
- pygame.quit()
Advertisement
Add Comment
Please, Sign In to add comment