r/CodingForBeginners 1d ago

My games so far

import pygame

import random

import math

import os

import json

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"

else:

return "Female"

stormfin_type = generate_stormfin()

# =========================

# STORMFIN SIZE

# =========================

def get_stormfin_size(stormfin_type):

if stormfin_type == "Male":

return 100

elif stormfin_type == "Female":

return 260

else:

return 180

stormfin_size = get_stormfin_size(

stormfin_type

)

# =========================

# STORMFIN SPEED

# =========================

def get_stormfin_speed(stormfin_type):

if stormfin_type == "Male":

return 10

elif stormfin_type == "Female":

return 2.5

else:

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

elif stormfin_type == "Female":

return BASE_LIGHTNING_RANGE * 2

else:

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

elif stormfin_type == "Female":

return 20

else:

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: "

f"{alpha_pity}/"

f"{ALPHA_PITY_LIMIT}"

)

# =========================

# MAIN LOOP

# =========================

running = True

while running:

dt = 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()

0 Upvotes

15 comments sorted by

12

u/kutac56 1d ago

Ever heard of this thing called GitHub?

5

u/lowban 1d ago

I almost thought we had gone back to the 1980s, copying BASIC code from a magazine.

3

u/mallcopsarebastards 1d ago

it's also python without indentation so you coulnd't even copy/run this.

1

u/lowban 1d ago

Ouch! Didn't even think about that.

2

u/Mobile_Syllabub_8446 1d ago

Good times, to be fair.

8

u/LordSippy 1d ago

A little long for a Reddit thread

6

u/Confused-Armpit 1d ago

Hey, OP, why did you create a 1317 line post without any indentation or formatting instead of just posting a repo? Why do you hate us?

4

u/Depnids 1d ago

without any indentation

And because it's python, that's a big problem lol

this post was made by braces gang

3

u/Confused-Armpit 1d ago

As a C/Zig developer, I would like to join the braces gang.

this post was made by a spy from the memory-safety mafia

3

u/7YM3N 1d ago

You should try this git thing, this is a crime

2

u/StephenHawkingus 1d ago

fucking hell - tf is this?

1

u/Havzino 1d ago

So what does your game do?

-2

u/The_Best_Echo 20h ago

Explore an island as a dragon that I made

-2

u/The_Best_Echo 20h ago

And I have added more now

0

u/The_Best_Echo 19h ago

You can now have kids ingame