wip
Some checks failed
Release / pypi-release (push) Failing after 37s
Release / release (ubuntu-latest) (push) Failing after 1m0s
Release / release (windows-latest) (push) Has been cancelled
Release / build-site (push) Has been cancelled

This commit is contained in:
Waylon Walker 2025-11-22 22:14:46 -06:00
parent f55c2fe32b
commit de1001dd57
30 changed files with 1451 additions and 3 deletions

1
.gitignore vendored
View file

@ -956,3 +956,4 @@ FodyWeavers.xsd
# Additional files built by Visual Studio # Additional files built by Visual Studio
# End of https://www.toptal.com/developers/gitignore/api/vim,node,data,emacs,python,pycharm,executable,sublimetext,visualstudio,visualstudiocode # End of https://www.toptal.com/developers/gitignore/api/vim,node,data,emacs,python,pycharm,executable,sublimetext,visualstudio,visualstudiocode
.null-ls_574349_tetris.py

108
aforest.py Normal file
View file

@ -0,0 +1,108 @@
import math
import noise
import pygame
# set up pygame
pygame.init()
# set up the window
screen_width, screen_height = 1280, 800
screen = pygame.display.set_mode((screen_width, screen_height))
# set up the noise surface
noise_width, noise_height = 1280, 800
noise_scale = 10
noise_width = int(screen_width / noise_scale)
noise_height = int(screen_height / noise_scale)
# noise_width, noise_height = round(1280 / 10), round(800 / 10)
noise_surface = pygame.Surface((noise_width, noise_height))
# set up the colors
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
colors = [(0, 128, 0), (0, 64, 0), (0, 32, 0)]
# set up the noise
octaves = 1
freq = 256 * octaves
# generate the noise
noise_map = [
[
noise.pnoise2(x / freq, y / freq, octaves, repeatx=3024, repeaty=3024)
for x in range(screen_width)
]
for y in range(screen_height)
]
# set up the clock
clock = pygame.time.Clock()
# set up the animation
frame = 0
# set up the noise surface cache
noise_surface_cache = []
# set up the noise surface cache index
noise_surface_cache_index = 0
# set up the noise surface cache size
noise_surface_cache_size = 120
# set up the noise surface cache
for i in range(noise_surface_cache_size):
print(f"caching {i} of {noise_surface_cache_size}")
# draw the background
for y in range(noise_height):
for x in range(noise_width):
color = colors[2]
if (
noise_map[y * noise_scale][x * noise_scale]
+ math.sin(i * (3.14 / noise_surface_cache_size))
> 0.2
):
color = colors[1]
elif (
noise_map[y * noise_scale][x * noise_scale]
+ math.sin(i * (3.14 / noise_surface_cache_size))
< 0.15
):
color = colors[0]
noise_surface.set_at((x, y), color)
# cache the noise surface
noise_surface_scaled = pygame.transform.scale(
noise_surface, (screen_width, screen_height)
)
# noise_surface_scaled_pil = Image.frombytes(
# "RGB",
# (screen_width, screen_height),
# pygame.image.tostring(noise_surface_scaled, "RGB", False),
# )
# noise_surface_scaled_pil = noise_surface_scaled_pil.filter(
# ImageFilter.GaussianBlur(radius=20)
# )
# noise_surface_scaled = pygame.image.fromstring(
# noise_surface_scaled_pil.tobytes(), (screen_width, screen_height), "RGB"
# )
noise_surface_cache.append(noise_surface_scaled)
noise_surface_cache.extend([n for n in noise_surface_cache[::-1]])
# main loop
running = True
print("running")
while running:
# keep loop running at the right speed
clock.tick(60)
# process events
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# increment the frame
frame += 0.2
if frame > noise_surface_cache_size - 1:
frame = 0
# draw the noise surface onto the screen
screen.blit(noise_surface_cache[int(frame)], (0, 0))
# display the fps on the screen
pygame.display.set_caption(str(clock.get_fps()))
# update the display
pygame.display.flip()
pygame.quit()

180
camera.py Normal file
View file

@ -0,0 +1,180 @@
"""Basic showcase on how the transform property on SpaceDebugDrawOptions can
be used as a camera to allow panning. Use arrows to move the camera.
"""
__docformat__ = "reStructuredText"
import random
import sys
import pygame
import pymunk.pygame_util
from pymunk.vec2d import Vec2d
random.seed(0)
def main():
pygame.init()
screen = pygame.display.set_mode((600, 600))
clock = pygame.time.Clock()
running = True
font = pygame.font.Font(None, 16)
text = font.render(
"Use Arrows (up, down, left, right) to move the camera, "
"a and z to zoom in / out and s and x to rotate.",
True,
pygame.Color("black"),
)
### Physics stuff
space = pymunk.Space()
space.gravity = Vec2d(0.0, 900.0)
draw_options = pymunk.pygame_util.DrawOptions(screen)
## Balls
balls = []
body = pymunk.Body()
body.position = pymunk.Vec2d(407, 354)
s1 = pymunk.Segment(body, Vec2d(-300, -30), Vec2d(0, 0), 1.0)
s2 = pymunk.Segment(body, Vec2d(0, 0), Vec2d(0, -100), 1.0)
s1.density = 0.1
s2.density = 0.1
s1.friction = 1
s2.friction = 1
space.add(body, s1, s2)
c1 = pymunk.constraints.DampedSpring(
space.static_body,
body,
(427, 200),
(0, -100),
Vec2d(407, 254).get_distance((427, 200)),
2000,
100,
)
c2 = pymunk.constraints.DampedSpring(
space.static_body,
body,
(87, 200),
(-300, -30),
Vec2d(107, 324).get_distance((87, 200)),
2000,
100,
)
space.add(c1, c2)
# extra to show how constraints are drawn when very small / large
body = pymunk.Body(1, 100)
body.position = 450, 305
c3 = pymunk.constraints.DampedSpring(
space.static_body, body, (450, 300), (0, 0), 5, 1000, 100
)
space.add(body, c3)
body = pymunk.Body(1, 100)
body.position = 500, 2025
c3 = pymunk.constraints.DampedSpring(
space.static_body, body, (500, 25), (0, 0), 2000, 1000, 100
)
space.add(body, c3)
ticks_to_next_ball = 10
translation = pymunk.Transform()
scaling = 1
rotation = 0
while running:
for event in pygame.event.get():
if (
event.type == pygame.QUIT
or event.type == pygame.KEYDOWN
and event.key == pygame.K_ESCAPE
):
running = False
elif event.type == pygame.KEYDOWN and event.key == pygame.K_p:
pygame.image.save(screen, "camera.png")
keys = pygame.key.get_pressed()
left = int(keys[pygame.K_LEFT])
up = int(keys[pygame.K_UP])
down = int(keys[pygame.K_DOWN])
right = int(keys[pygame.K_RIGHT])
zoom_in = int(keys[pygame.K_a])
zoom_out = int(keys[pygame.K_z])
rotate_left = int(keys[pygame.K_s])
rotate_right = int(keys[pygame.K_x])
translate_speed = 10
translation = translation.translated(
translate_speed * left - translate_speed * right,
translate_speed * up - translate_speed * down,
)
zoom_speed = 0.1
scaling *= 1 + (zoom_speed * zoom_in - zoom_speed * zoom_out)
rotation_speed = 0.1
rotation += rotation_speed * rotate_left - rotation_speed * rotate_right
# to zoom with center of screen as origin we need to offset with
# center of screen, scale, and then offset back
draw_options.transform = (
pymunk.Transform.translation(300, 300)
@ pymunk.Transform.scaling(scaling)
@ translation
@ pymunk.Transform.rotation(rotation)
@ pymunk.Transform.translation(-300, -300)
)
ticks_to_next_ball -= 1
if ticks_to_next_ball <= 0:
ticks_to_next_ball = 100
mass = 10
radius = 25
inertia = pymunk.moment_for_circle(mass, 0, radius, (0, 0))
body = pymunk.Body(mass, inertia)
x = random.randint(115, 350)
body.position = x, 100
if random.random() > 0.5:
shape = pymunk.Circle(body, radius)
else:
shape = pymunk.Poly.create_box(
body, size=(radius * 2, radius * 2), radius=2
)
shape.friction = 1
space.add(body, shape)
balls.append(shape)
### Clear screen
screen.fill(pygame.Color("white"))
### Draw stuff
space.debug_draw(draw_options)
balls_to_remove = []
for ball in balls:
if ball.body.position.y > 500:
balls_to_remove.append(ball)
for ball in balls_to_remove:
space.remove(ball, ball.body)
balls.remove(ball)
screen.blit(text, (5, 5))
### Update physics
dt = 1.0 / 60.0
space.step(dt)
### Flip screen
pygame.display.flip()
clock.tick(50)
pygame.display.set_caption("fps: " + str(clock.get_fps()))
if __name__ == "__main__":
sys.exit(main())

250
constraints.py Normal file
View file

@ -0,0 +1,250 @@
"""
Pymunk constraints demo. Showcase of all the constraints included in Pymunk.
Adapted from the Chipmunk Joints demo:
https://github.com/slembcke/Chipmunk2D/blob/master/demo/Joints.c
"""
import inspect
import math
import pygame
import pymunk.pygame_util
from pymunk.vec2d import Vec2d
pygame.init()
screen = pygame.display.set_mode((1200, 600))
clock = pygame.time.Clock()
font = pygame.font.Font(None, 24)
help_txt = font.render(
"Pymunk constraints demo. Use mouse to drag/drop. Hover to see descr.",
True,
pygame.Color("darkgray"),
)
space = pymunk.Space()
space.gravity = (0.0, 900.0)
draw_options = pymunk.pygame_util.DrawOptions(screen)
# containers
box_size = 200
w = screen.get_width()
h = screen.get_height()
for i in range(6):
sw = pymunk.Segment(space.static_body, (0, i * box_size), (w, i * box_size), 1)
sw.friction = 1
sw.elasticity = 1
sh = pymunk.Segment(
space.static_body, (i * box_size, 0), (i * box_size, h - box_size), 1
)
sh.friction = 1
sh.elasticity = 1
space.add(sw, sh)
def add_ball(space, pos, box_offset):
body = pymunk.Body()
body.position = Vec2d(*pos) + box_offset
shape = pymunk.Circle(body, 20)
shape.mass = 1
shape.friction = 0.7
space.add(body, shape)
return body
def add_bar(space, pos, box_offset):
body = pymunk.Body()
body.position = Vec2d(*pos) + box_offset
shape = pymunk.Segment(body, (0, 40), (0, -40), 6)
shape.mass = 2
shape.friction = 0.7
space.add(body, shape)
return body
def add_lever(space, pos, box_offset):
body = pymunk.Body()
body.position = pos + Vec2d(*box_offset) + (0, -20)
shape = pymunk.Segment(body, (0, 20), (0, -20), 5)
shape.mass = 1
shape.friction = 0.7
space.add(body, shape)
return body
def main():
txts = {}
box_offset = 0, 0
b1 = add_ball(space, (50, 60), box_offset)
b2 = add_ball(space, (150, 60), box_offset)
c: pymunk.Constraint = pymunk.PinJoint(b1, b2, (20, 0), (-20, 0))
txts[box_offset] = inspect.getdoc(c)
space.add(c)
box_offset = box_size, 0
b1 = add_ball(space, (50, 60), box_offset)
b2 = add_ball(space, (150, 60), box_offset)
c = pymunk.SlideJoint(b1, b2, (20, 0), (-20, 0), 40, 80)
txts[box_offset] = inspect.getdoc(c)
space.add(c)
box_offset = box_size * 2, 0
b1 = add_ball(space, (50, 60), box_offset)
b2 = add_ball(space, (150, 60), box_offset)
c = pymunk.PivotJoint(b1, b2, Vec2d(*box_offset) + (100, 60))
txts[box_offset] = inspect.getdoc(c)
space.add(c)
box_offset = box_size * 3, 0
b1 = add_ball(space, (50, 60), box_offset)
b2 = add_ball(space, (150, 60), box_offset)
c = pymunk.GrooveJoint(b1, b2, (50, 50), (50, -50), (-50, 0))
txts[box_offset] = inspect.getdoc(c)
space.add(c)
box_offset = box_size * 4, 0
b1 = add_ball(space, (50, 60), box_offset)
b2 = add_ball(space, (150, 60), box_offset)
c = pymunk.DampedSpring(b1, b2, (30, 0), (-30, 0), 20, 5, 0.3)
txts[box_offset] = inspect.getdoc(c)
space.add(c)
box_offset = box_size * 5, 0
b1 = add_bar(space, (50, 80), box_offset)
b2 = add_bar(space, (150, 80), box_offset)
# Add some joints to hold the circles in place.
space.add(pymunk.PivotJoint(b1, space.static_body, (50, 80) + Vec2d(*box_offset)))
space.add(pymunk.PivotJoint(b2, space.static_body, (150, 80) + Vec2d(*box_offset)))
c = pymunk.DampedRotarySpring(b1, b2, 0, 3000, 60)
txts[box_offset] = inspect.getdoc(c)
space.add(c)
box_offset = 0, box_size
b1 = add_lever(space, (50, 100), box_offset)
b2 = add_lever(space, (150, 100), box_offset)
# Add some joints to hold the circles in place.
space.add(pymunk.PivotJoint(b1, space.static_body, (50, 100) + Vec2d(*box_offset)))
space.add(pymunk.PivotJoint(b2, space.static_body, (150, 100) + Vec2d(*box_offset)))
# Hold their rotation within 90 degrees of each other.
c = pymunk.RotaryLimitJoint(b1, b2, math.pi / 2, math.pi / 2)
txts[box_offset] = inspect.getdoc(c)
space.add(c)
box_offset = box_size, box_size
b1 = add_lever(space, (50, 100), box_offset)
b2 = add_lever(space, (150, 100), box_offset)
# Add some pin joints to hold the circles in place.
space.add(pymunk.PivotJoint(b1, space.static_body, (50, 100) + Vec2d(*box_offset)))
space.add(pymunk.PivotJoint(b2, space.static_body, (150, 100) + Vec2d(*box_offset)))
# Ratchet every 90 degrees
c = pymunk.RatchetJoint(b1, b2, 0, math.pi / 2)
txts[box_offset] = inspect.getdoc(c)
space.add(c)
box_offset = box_size * 2, box_size
b1 = add_bar(space, (50, 100), box_offset)
b2 = add_bar(space, (150, 100), box_offset)
# Add some pin joints to hold the circles in place.
space.add(pymunk.PivotJoint(b1, space.static_body, (50, 100) + Vec2d(*box_offset)))
space.add(pymunk.PivotJoint(b2, space.static_body, (150, 100) + Vec2d(*box_offset)))
# Force one to sping 2x as fast as the other
c = pymunk.GearJoint(b1, b2, 0, 2)
txts[box_offset] = inspect.getdoc(c)
space.add(c)
box_offset = box_size * 3, box_size
b1 = add_bar(space, (50, 100), box_offset)
b2 = add_bar(space, (150, 100), box_offset)
# Add some pin joints to hold the circles in place.
space.add(pymunk.PivotJoint(b1, space.static_body, (50, 100) + Vec2d(*box_offset)))
space.add(pymunk.PivotJoint(b2, space.static_body, (150, 100) + Vec2d(*box_offset)))
# Make them spin at 1/2 revolution per second in relation to each other.
c = pymunk.SimpleMotor(b1, b2, math.pi)
txts[box_offset] = inspect.getdoc(c)
space.add(c)
# TODO add one or two advanced constraints examples, such as a car or rope
mouse_joint = None
mouse_body = pymunk.Body(body_type=pymunk.Body.KINEMATIC)
# Build rendered help texts
box_texts = {}
for k in txts:
l = 0
box_texts[k] = []
# Only take the first 5 lines.
for line in txts[k].splitlines()[:5]:
txt = font.render(line, True, pygame.Color("black"))
box_texts[k].append(txt)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
if mouse_joint is not None:
space.remove(mouse_joint)
mouse_joint = None
p = Vec2d(*event.pos)
hit = space.point_query_nearest(p, 5, pymunk.ShapeFilter())
if hit is not None and hit.shape.body.body_type == pymunk.Body.DYNAMIC:
shape = hit.shape
# Use the closest point on the surface if the click is outside
# of the shape.
if hit.distance > 0:
nearest = hit.point
else:
nearest = p
mouse_joint = pymunk.PivotJoint(
mouse_body,
shape.body,
(0, 0),
shape.body.world_to_local(nearest),
)
mouse_joint.max_force = 50000
mouse_joint.error_bias = (1 - 0.15) ** 60
space.add(mouse_joint)
elif event.type == pygame.MOUSEBUTTONUP:
if mouse_joint is not None:
space.remove(mouse_joint)
mouse_joint = None
screen.fill(pygame.Color("white"))
screen.blit(help_txt, (5, screen.get_height() - 20))
mouse_pos = pygame.mouse.get_pos()
# Display help message
x = mouse_pos[0] // box_size * box_size
y = mouse_pos[1] // box_size * box_size
if (x, y) in box_texts:
txts = box_texts[(x, y)]
i = 0
for txt in txts:
pos = (5, box_size * 2 + 10 + i * 20)
screen.blit(txt, pos)
i += 1
mouse_body.position = mouse_pos
space.step(1.0 / 60)
space.debug_draw(draw_options)
pygame.display.flip()
clock.tick(60)
pygame.display.set_caption(f"fps: {clock.get_fps()}")
if __name__ == "__main__":
main()

0
creeper_adventure/assets/bee/idle/1.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 630 B

After

Width:  |  Height:  |  Size: 630 B

Before After
Before After

0
creeper_adventure/assets/creeper/idle/1.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 769 B

After

Width:  |  Height:  |  Size: 769 B

Before After
Before After

0
creeper_adventure/assets/creeper/idle/2.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 769 B

After

Width:  |  Height:  |  Size: 769 B

Before After
Before After

0
creeper_adventure/assets/creeper/idle/3.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 769 B

After

Width:  |  Height:  |  Size: 769 B

Before After
Before After

0
creeper_adventure/assets/creeper/idle/4.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 769 B

After

Width:  |  Height:  |  Size: 769 B

Before After
Before After

0
creeper_adventure/assets/creeper/idle/5.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 776 B

After

Width:  |  Height:  |  Size: 776 B

Before After
Before After

0
creeper_adventure/assets/leaf.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 599 B

After

Width:  |  Height:  |  Size: 599 B

Before After
Before After

0
creeper_adventure/assets/oak_trees/1.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Before After
Before After

0
creeper_adventure/assets/oak_trees/2.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Before After
Before After

0
creeper_adventure/assets/oak_trees/4.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Before After
Before After

0
creeper_adventure/assets/oak_trees/5.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Before After
Before After

0
creeper_adventure/assets/spotlight.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 2 KiB

Before After
Before After

7
creeper_adventure/creeper.py Executable file → Normal file
View file

@ -1,10 +1,12 @@
import random
from copy import copy from copy import copy
from itertools import cycle, repeat from itertools import cycle, repeat
from pathlib import Path from pathlib import Path
import random
from typing import List, Optional
import pygame
from more_itertools import flatten from more_itertools import flatten
from pydantic import BaseModel
import pygame
from creeper_adventure.game import Game from creeper_adventure.game import Game
@ -348,7 +350,6 @@ class MainMenu(Menu):
h = 50 h = 50
x = self.game.screen.get_size()[0] / 2 - w / 2 x = self.game.screen.get_size()[0] / 2 - w / 2
y = 300 y = 300
print(self.game.frames)
return Button(self.game, self.surf, self.button_text, x, y, w, h, self.toggle) return Button(self.game, self.surf, self.button_text, x, y, w, h, self.toggle)
def set_button_text(self): def set_button_text(self):

0
creeper_adventure/game.py Executable file → Normal file
View file

63
forest.py Normal file
View file

@ -0,0 +1,63 @@
import math
from noise import pnoise2
import pygame
# Initialize pygame
pygame.init()
base = 0
persistence = 0.4
lacunarity = 2.0
more_x = 0
# Set up the drawing window
screen = pygame.display.set_mode([800, 600])
def S():
i = 0
while True:
i += 0.1
yield math.sin(i)
s = S()
# Run until the user asks to quit
running = True
while running:
# Did the user click the window close button?
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Fill the background with white
screen.fill((255, 255, 255))
m = next(s)
# Generate Perlin noise
for x in range(800):
for y in range(600):
noise = pnoise2(
x / 10,
y / 10,
octaves=4,
persistence=persistence + m / 10,
lacunarity=lacunarity,
repeatx=1024,
repeaty=1024,
base=base,
)
if noise > 0.2:
pygame.draw.rect(screen, (0, 255, 0), (x, y, 1, 1))
elif noise > 0:
pygame.draw.rect(screen, (0, 128, 0), (x, y, 1, 1))
else:
pygame.draw.rect(screen, (0, 64, 0), (x, y, 1, 1))
# Flip the display
pygame.display.flip()
# Done! Time to quit.
pygame.quit()

85
gpt-menu.py Normal file
View file

@ -0,0 +1,85 @@
import pygame
# Initialize Pygame
pygame.init()
EVENTS = []
# Set screen size
screen = pygame.display.set_mode((800, 600))
# Set title
pygame.display.set_caption("My RPG Game")
# Load font
font = pygame.font.Font(None, 30)
# Define button class
class Button:
def __init__(self, text, x, y, w, h, on_click=lambda: ...):
self.text = text
self.x = x
self.y = y
self.w = w
self.h = h
self.on_click = on_click
def draw(self, surface):
pygame.draw.rect(surface, (255, 255, 255), (self.x, self.y, self.w, self.h))
label = font.render(self.text, True, (0, 0, 0))
label_rect = label.get_rect()
label_rect.center = (self.x + self.w / 2, self.y + self.h / 2)
surface.blit(label, label_rect)
for event in EVENTS:
if event.type == pygame.MOUSEBUTTONDOWN:
if self.is_clicked(event.pos):
self.on_click()
# elif quit_button.is_clicked(event.pos):
# running = False
# if self.is_clicked:
# self.on_click()
def is_clicked(self, pos):
if pos[0] > self.x and pos[0] < self.x + self.w:
if pos[1] > self.y and pos[1] < self.y + self.h:
return True
return False
# Create buttons
start_button = Button(
"Start Game", 300, 300, 200, 50, lambda: print("start this thing")
)
running = True
def stop():
global running
running = False
quit_button = Button("Quit Game", 300, 400, 200, 50, stop)
# Main loop
while running:
EVENTS = pygame.event.get()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Check for button clicks
# Draw background
screen.fill((0, 0, 0))
# Draw title
title = font.render("Creeper Adventure", True, (255, 255, 255))
screen.blit(title, (250, 200))
# Draw buttons
start_button.draw(screen)
quit_button.draw(screen)
pygame.display.update()
# Quit Pygame
pygame.quit()

42
gradients.py Normal file
View file

@ -0,0 +1,42 @@
from noise import pnoise2
import pygame
import random
# Initialize pygame
pygame.init()
# Set the size of the window
width, height = 800, 600
screen = pygame.display.set_mode((width, height))
# Create a list of 3 random blues
blues = []
for i in range(3):
blues.append(
(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
)
# Create a perlin noise surface
noise_surface = pygame.Surface((width, height))
for x in range(width):
for y in range(height):
# Calculate the perlin noise value
noise_value = pnoise2(x / 100, y / 100)
# Map the noise value to a color
color_index = int(noise_value * (len(blues) - 1))
color = blues[color_index]
# Set the color of the pixel
noise_surface.set_at((x, y), color)
# Blit the noise surface to the screen
screen.blit(noise_surface, (0, 0))
# Update the display
pygame.display.flip()
# Keep the window open until it is closed
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()

BIN
grass.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

56
iso.py Normal file
View file

@ -0,0 +1,56 @@
import sys
import pygame
from pygame.locals import DOUBLEBUF, K_ESCAPE, KEYUP, QUIT
pygame.init()
DISPLAYSURF = pygame.display.set_mode(
(640, 480), DOUBLEBUF
) # set the display mode, window title and FPS clock
pygame.display.set_caption("Map Rendering Demo")
FPSCLOCK = pygame.time.Clock()
map_data = [
[1, 1, 1, 1, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 1, 1, 1, 1],
] # the data for the map expressed as [row[tile]].
wall = pygame.image.load("wall.png").convert_alpha() # load images
grass = pygame.image.load("grass.png").convert_alpha()
TILEWIDTH = 64 # holds the tile width and height
TILEHEIGHT = 64
TILEHEIGHT_HALF = TILEHEIGHT / 2
TILEWIDTH_HALF = TILEWIDTH / 2
for row_nb, row in enumerate(map_data): # for every row of the map...
for col_nb, tile in enumerate(row):
if tile == 1:
tileImage = wall
else:
tileImage = grass
cart_x = row_nb * TILEWIDTH_HALF
cart_y = col_nb * TILEHEIGHT_HALF
iso_x = cart_x - cart_y
iso_y = (cart_x + cart_y) / 2
centered_x = DISPLAYSURF.get_rect().centerx + iso_x
centered_y = DISPLAYSURF.get_rect().centery / 2 + iso_y
DISPLAYSURF.blit(tileImage, (centered_x, centered_y)) # display the actual tile
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYUP:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
pygame.display.flip()
FPSCLOCK.tick(30)

View file

@ -26,6 +26,7 @@ classifiers = [
dependencies = [ dependencies = [
"click", "click",
"pygame", "pygame",
"noise",
"more_itertools", "more_itertools",
] ]
dynamic = ["version"] dynamic = ["version"]

0
requirements.txt Executable file → Normal file
View file

0
site/static/creeper-1.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 769 B

After

Width:  |  Height:  |  Size: 769 B

Before After
Before After

99
spacegame.py Normal file
View file

@ -0,0 +1,99 @@
import pygame
# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
# Define some constants
WIDTH = 800
HEIGHT = 600
FPS = 60
GRAVITY = 0.5
# Define some variables
x = WIDTH / 2
y = HEIGHT / 2
vx = 0
vy = 0
# Define some functions
def draw_dot(x, y):
pygame.draw.circle(window, BLACK, (int(x), int(y)), 10)
def move_dot(x, y, vx, vy):
x += vx
y += vy
return x, y
def apply_gravity(vy):
vy += GRAVITY
return vy
def jump(vy):
vy = -10
return vy
# Initialize pygame
pygame.init()
# Create a window
# Create a clock
clock = pygame.time.Clock()
# Create a window
window = pygame.display.set_mode((WIDTH, HEIGHT))
# Set window title
pygame.display.set_caption("My Game")
# Game loop
running = True
# Set the frame rate
clock.tick(FPS)
while running:
# Process events
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
vx = -5
if event.key == pygame.K_d:
vx = 5
if event.key == pygame.K_SPACE:
vy = jump(vy)
if event.type == pygame.KEYUP:
if event.key == pygame.K_a:
vx = 0
if event.key == pygame.K_d:
vx = 0
running = False
x, y = move_dot(x, y, vx, vy)
vy = apply_gravity(vy)
# Render
# Clear the screen
# Draw the dot
draw_dot(x, y)
# Update the display
# Update
# Render
window.fill((255, 255, 255))
pygame.display.update()
# Close window on quit
pygame.quit()

521
tetris.py Normal file
View file

@ -0,0 +1,521 @@
# Tetromino (a Tetris clone)
# By Al Sweigart al@inventwithpython.com
# http://inventwithpython.com/pygame
# Released under a "Simplified BSD" license
import random
import time
import pygame
import sys
from pygame.locals import *
FPS = 25
WINDOWWIDTH = 640
WINDOWZE = 20
BOARHEIGHT = 480
BOXSIDWIDTH = 10
BOARDHEIGHT = 20
BLANK = '.'
MOVESIDEWAYSFREQ = 0.15
MOVEDOWNFREQ = 0.1
XMARGIN = int((WINDOWWIDTH - BOARDWIDTH * BOXSIZE) / 2)
TOPMARGIN = WINDOWHEIGHT - (BOARDHEIGHT * BOXSIZE) - 5
# R G B
WHITE = (255, 255, 255)
GRAY = (185, 185, 185)
BLACK = (0, 0, 0)
RED = (155, 0, 0)
LIGHTRED = (175, 20, 20)
GREEN = (0, 155, 0)
LIGHTGREEN = (20, 175, 20)
BLUE = (0, 0, 155)
LIGHTBLUE = (20, 20, 175)
YELLOW = (155, 155, 0)
LIGHTYELLOW = (175, 175, 20)
BORDERCOLOR = BLUE
BGCOLOR = BLACK
TEXTCOLOR = WHITE
TEXTSHADOWCOLOR = GRAY
COLORS = (BLUE, GREEN, RED, YELLOW)
LIGHTCOLORS = (LIGHTBLUE, LIGHTGREEN, LIGHTRED, LIGHTYELLOW)
assert len(COLORS) == len(LIGHTCOLORS) # each color must have light color
TEMPLATEWIDTH = 5
TEMPLATEHEIGHT = 5
S_SHAPE_TEMPLATE = [['.....',
'.....',
'..OO.',
'.OO..',
'.....'],
['.....',
'..O..',
'..OO.',
'...O.',
'.....']]
Z_SHAPE_TEMPLATE = [['.....',
'.....',
'.OO..',
'..OO.',
'.....'],
['.....',
'..O..',
'.OO..',
'.O...',
'.....']]
I_SHAPE_TEMPLATE = [['..O..',
'..O..',
'..O..',
'..O..',
'.....'],
['.....',
'.....',
'OOOO.',
'.....',
'.....']]
O_SHAPE_TEMPLATE = [['.....',
'.....',
'.OO..',
'.OO..',
'.....']]
J_SHAPE_TEMPLATE = [['.....',
'.O...',
'.OOO.',
'.....',
'.....'],
['.....',
'..OO.',
'..O..',
'..O..',
'.....'],
['.....',
'.....',
'.OOO.',
'...O.',
'.....'],
['.....',
'..O..',
'..O..',
'.OO..',
'.....']]
L_SHAPE_TEMPLATE = [['.....',
'...O.',
'.OOO.',
'.....',
'.....'],
['.....',
'..O..',
'..O..',
'..OO.',
'.....'],
['.....',
'.....',
'.OOO.',
'.O...',
'.....'],
['.....',
'.OO..',
'..O..',
'..O..',
'.....']]
T_SHAPE_TEMPLATE = [['.....',
'..O..',
'.OOO.',
'.....',
'.....'],
['.....',
'..O..',
'..OO.',
'..O..',
'.....'],
['.....',
'.....',
'.OOO.',
'..O..',
'.....'],
['.....',
'..O..',
'.OO..',
'..O..',
'.....']]
PIECES = {'S': S_SHAPE_TEMPLATE,
'Z': Z_SHAPE_TEMPLATE,
'J': J_SHAPE_TEMPLATE,
'L': L_SHAPE_TEMPLATE,
'I': I_SHAPE_TEMPLATE,
'O': O_SHAPE_TEMPLATE,
'T': T_SHAPE_TEMPLATE}
def main():
global FPSCLOCK, DISPLAYSURF, BASICFONT, BIGFONT
pygame.init()
FPSCLOCK = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
BASICFONT = pygame.font.Font('freesansbold.ttf', 18)
BIGFONT = pygame.font.Font('freesansbold.ttf', 100)
pygame.display.set_caption('Tetromino')
showTextScreen('Tetromino')
while True: # game loop
# if random.randint(0, 1) == 0:
# pygame.mixer.music.load('tetrisb.mid')
# else:
# pygame.mixer.music.load('tetrisc.mid')
#pygame.mixer.music.play(-1, 0.0)
runGame()
# pygame.mixer.music.stop()
showTextScreen('Game Over')
def runGame():
# setup variables for the start of the game
board = getBlankBoard()
lastMoveDownTime = time.time()
lastMoveSidewaysTime = time.time()
lastFallTime = time.time()
movingDown = False # note: there is no movingUp variable
movingLeft = False
movingRight = False
score = 0
level, fallFreq = calculateLevelAndFallFreq(score)
fallingPiece = getNewPiece()
nextPiece = getNewPiece()
while True: # game loop
if fallingPiece == None:
# No falling piece in play, so start a new piece at the top
fallingPiece = nextPiece
nextPiece = getNewPiece()
lastFallTime = time.time() # reset lastFallTime
if not isValidPosition(board, fallingPiece):
return # can't fit a new piece on the board, so game over
checkForQuit()
for event in pygame.event.get(): # event handling loop
if event.type == KEYUP:
if (event.key == K_p):
# Pausing the game
DISPLAYSURF.fill(BGCOLOR)
pygame.mixer.music.stop()
showTextScreen('Paused') # pause until a key press
pygame.mixer.music.play(-1, 0.0)
lastFallTime = time.time()
lastMoveDownTime = time.time()
lastMoveSidewaysTime = time.time()
elif (event.key == K_LEFT or event.key == K_a):
movingLeft = False
elif (event.key == K_RIGHT or event.key == K_d):
movingRight = False
elif (event.key == K_DOWN or event.key == K_s):
movingDown = False
elif event.type == KEYDOWN:
# moving the piece sideways
if (event.key == K_LEFT or event.key == K_a) and isValidPosition(board, fallingPiece, adjX=-1):
fallingPiece['x'] -= 1
movingLeft = True
movingRight = False
lastMoveSidewaysTime = time.time()
elif (event.key == K_RIGHT or event.key == K_d) and isValidPosition(board, fallingPiece, adjX=1):
fallingPiece['x'] += 1
movingRight = True
movingLeft = False
lastMoveSidewaysTime = time.time()
# rotating the piece (if there is room to rotate)
elif (event.key == K_UP or event.key == K_w):
fallingPiece['rotation'] = (
fallingPiece['rotation'] + 1) % len(PIECES[fallingPiece['shape']])
if not isValidPosition(board, fallingPiece):
fallingPiece['rotation'] = (
fallingPiece['rotation'] - 1) % len(PIECES[fallingPiece['shape']])
elif (event.key == K_q): # rotate the other direction
fallingPiece['rotation'] = (
fallingPiece['rotation'] - 1) % len(PIECES[fallingPiece['shape']])
if not isValidPosition(board, fallingPiece):
fallingPiece['rotation'] = (
fallingPiece['rotation'] + 1) % len(PIECES[fallingPiece['shape']])
# making the piece fall faster with the down key
elif (event.key == K_DOWN or event.key == K_s):
movingDown = True
if isValidPosition(board, fallingPiece, adjY=1):
fallingPiece['y'] += 1
lastMoveDownTime = time.time()
# move the current piece all the way down
elif event.key == K_SPACE:
movingDown = False
movingLeft = False
movingRight = False
for i in range(1, BOARDHEIGHT):
if not isValidPosition(board, fallingPiece, adjY=i):
break
fallingPiece['y'] += i - 1
# handle moving the piece because of user input
if (movingLeft or movingRight) and time.time() - lastMoveSidewaysTime > MOVESIDEWAYSFREQ:
if movingLeft and isValidPosition(board, fallingPiece, adjX=-1):
fallingPiece['x'] -= 1
elif movingRight and isValidPosition(board, fallingPiece, adjX=1):
fallingPiece['x'] += 1
lastMoveSidewaysTime = time.time()
if movingDown and time.time() - lastMoveDownTime > MOVEDOWNFREQ and isValidPosition(board, fallingPiece, adjY=1):
fallingPiece['y'] += 1
lastMoveDownTime = time.time()
# let the piece fall if it is time to fall
if time.time() - lastFallTime > fallFreq:
# see if the piece has landed
if not isValidPosition(board, fallingPiece, adjY=1):
# falling piece has landed, set it on the board
addToBoard(board, fallingPiece)
score += removeCompleteLines(board)
level, fallFreq = calculateLevelAndFallFreq(score)
fallingPiece = None
else:
# piece did not land, just move the piece down
fallingPiece['y'] += 1
lastFallTime = time.time()
# drawing everything on the screen
DISPLAYSURF.fill(BGCOLOR)
drawBoard(board)
drawStatus(score, level)
drawNextPiece(nextPiece) # Here
if fallingPiece != None:
drawPiece(fallingPiece)
pygame.display.update()
FPSCLOCK.tick(FPS)
def makeTextObjs(text, font, color):
surf = font.render(text, True, color)
return surf, surf.get_rect()
def terminate():
pygame.quit()
sys.exit()
def checkForKeyPress():
# Go through event queue looking for a KEYUP event.
# Grab KEYDOWN events to remove them from the event queue.
checkForQuit()
for event in pygame.event.get([KEYDOWN, KEYUP]):
if event.type == KEYDOWN:
continue
return event.key
return None
def showTextScreen(text):
# This function displays large text in the
# center of the screen until a key is pressed.
# Draw the text drop shadow
titleSurf, titleRect = makeTextObjs(text, BIGFONT, TEXTSHADOWCOLOR)
titleRect.center = (int(WINDOWWIDTH / 2), int(WINDOWHEIGHT / 2))
DISPLAYSURF.blit(titleSurf, titleRect)
# Draw the text
titleSurf, titleRect = makeTextObjs(text, BIGFONT, TEXTCOLOR)
titleRect.center = (int(WINDOWWIDTH / 2) - 3, int(WINDOWHEIGHT / 2) - 3)
DISPLAYSURF.blit(titleSurf, titleRect)
# Draw the additional "Press a key to play." text.
pressKeySurf, pressKeyRect = makeTextObjs(
'Press a key to play.', BASICFONT, TEXTCOLOR)
pressKeyRect.center = (int(WINDOWWIDTH / 2), int(WINDOWHEIGHT / 2) + 100)
DISPLAYSURF.blit(pressKeySurf, pressKeyRect)
while checkForKeyPress() == None:
pygame.display.update()
FPSCLOCK.tick()
def checkForQuit():
for event in pygame.event.get(QUIT): # get all the QUIT events
terminate() # terminate if any QUIT events are present
for event in pygame.event.get(KEYUP): # get all the KEYUP events
if event.key == K_ESCAPE:
terminate() # terminate if the KEYUP event was for the Esc key
pygame.event.post(event) # put the other KEYUP event objects back
def calculateLevelAndFallFreq(score):
# Based on the score, return the level the player is on and
# how many seconds pass until a falling piece falls one space.
level = int(score / 10) + 1
fallFreq = 0.27 - (level * 0.02)
return level, fallFreq
def getNewPiece():
# return a random new piece in a random rotation and color
shape = random.choice(list(PIECES.keys()))
newPiece = {'shape': shape,
'rotation': random.randint(0, len(PIECES[shape]) - 1),
'x': int(BOARDWIDTH / 2) - int(TEMPLATEWIDTH / 2),
'y': -2, # start it above the board (i.e. less than 0)
'color': random.randint(0, len(COLORS) - 1)}
return newPiece
def addToBoard(board, piece):
# fill in the board based on piece's location, shape, and rotation
for x in range(TEMPLATEWIDTH):
for y in range(TEMPLATEHEIGHT):
if PIECES[piece['shape']][piece['rotation']][y][x] != BLANK:
board[x + piece['x']][y + piece['y']] = piece['color']
def getBlankBoard():
# create and return a new blank board data structure
board = []
for i in range(BOARDWIDTH):
board.append([BLANK] * BOARDHEIGHT)
return board
def isOnBoard(x, y):
return x >= 0 and x < BOARDWIDTH and y < BOARDHEIGHT
def isValidPosition(board, piece, adjX=0, adjY=0):
# Return True if the piece is within the board and not colliding
for x in range(TEMPLATEWIDTH):
for y in range(TEMPLATEHEIGHT):
isAboveBoard = y + piece['y'] + adjY < 0
if isAboveBoard or PIECES[piece['shape']][piece['rotation']][y][x] == BLANK:
continue
if not isOnBoard(x + piece['x'] + adjX, y + piece['y'] + adjY):
return False
if board[x + piece['x'] + adjX][y + piece['y'] + adjY] != BLANK:
return False
return True
def isCompleteLine(board, y):
# Return True if the line filled with boxes with no gaps.
for x in range(BOARDWIDTH):
if board[x][y] == BLANK:
return False
return True
def removeCompleteLines(board):
# Remove any completed lines on the board, move everything above them down, and return the number of complete lines.
numLinesRemoved = 0
y = BOARDHEIGHT - 1 # start y at the bottom of the board
while y >= 0:
if isCompleteLine(board, y):
# Remove the line and pull boxes down by one line.
for pullDownY in range(y, 0, -1):
for x in range(BOARDWIDTH):
board[x][pullDownY] = board[x][pullDownY - 1]
# Set very top line to blank.
for x in range(BOARDWIDTH):
board[x][0] = BLANK
numLinesRemoved += 1
# Note on the next iteration of the loop, y is the same.
# This is so that if the line that was pulled down is also
# complete, it will be removed.
else:
y -= 1 # move on to check next row up
return numLinesRemoved
def convertToPixelCoords(boxx, boxy):
# Convert the given xy coordinates of the board to xy
# coordinates of the location on the screen.
return (XMARGIN + (boxx * BOXSIZE)), (TOPMARGIN + (boxy * BOXSIZE))
def drawBox(boxx, boxy, color, pixelx=None, pixely=None):
# draw a single box (each tetromino piece has four boxes)
# at xy coordinates on the board. Or, if pixelx & pixely
# are specified, draw to the pixel coordinates stored in
# pixelx & pixely (this is used for the "Next" piece).
if color == BLANK:
return
if pixelx == None and pixely == None:
pixelx, pixely = convertToPixelCoords(boxx, boxy)
pygame.draw.rect(DISPLAYSURF, COLORS[color],
(pixelx + 1, pixely + 1, BOXSIZE - 1, BOXSIZE - 1))
pygame.draw.rect(
DISPLAYSURF, LIGHTCOLORS[color], (pixelx + 1, pixely + 1, BOXSIZE - 4, BOXSIZE - 4))
def drawBoard(board):
# draw the border around the board
pygame.draw.rect(DISPLAYSURF, BORDERCOLOR, (XMARGIN - 3, TOPMARGIN - 7,
(BOARDWIDTH * BOXSIZE) + 8, (BOARDHEIGHT * BOXSIZE) + 8), 5)
# fill the background of the board
pygame.draw.rect(DISPLAYSURF, BGCOLOR, (XMARGIN, TOPMARGIN,
BOXSIZE * BOARDWIDTH, BOXSIZE * BOARDHEIGHT))
# draw the individual boxes on the board
for x in range(BOARDWIDTH):
for y in range(BOARDHEIGHT):
drawBox(x, y, board[x][y])
def drawStatus(score, level):
# draw the score text
scoreSurf = BASICFONT.render('Score: %s' % score, True, TEXTCOLOR)
scoreRect = scoreSurf.get_rect()
scoreRect.topleft = (WINDOWWIDTH - 150, 20)
DISPLAYSURF.blit(scoreSurf, scoreRect)
# draw the level text
levelSurf = BASICFONT.render('Level: %s' % level, True, TEXTCOLOR)
levelRect = levelSurf.get_rect()
levelRect.topleft = (WINDOWWIDTH - 150, 50)
DISPLAYSURF.blit(levelSurf, levelRect)
def drawPiece(piece, pixelx=None, pixely=None):
shapeToDraw = PIECES[piece['shape']][piece['rotation']]
if pixelx == None and pixely == None:
# if pixelx & pixely hasn't been specified, use the location stored in the piece data structure
pixelx, pixely = convertToPixelCoords(piece['x'], piece['y'])
# draw each of the boxes that make up the piece
for x in range(TEMPLATEWIDTH):
for y in range(TEMPLATEHEIGHT):
if shapeToDraw[y][x] != BLANK:
drawBox(None, None, piece['color'], pixelx
+ (x * BOXSIZE), pixely + (y * BOXSIZE))
def drawNextPiece(piece):
# draw the "next" text
nextSurf = BASICFONT.render('Next:', True, TEXTCOLOR)
nextRect = nextSurf.get_rect()
nextRect.topleft = (WINDOWWIDTH - 120, 80)
DISPLAYSURF.blit(nextSurf, nextRect)
# draw the "next" piece
drawPiece(piece, pixelx=WINDOWWIDTH - 120, pixely=100)
if __name__ == '__main__':
main()

41
tmp.py Normal file
View file

@ -0,0 +1,41 @@
import noise
import pygame
# Initialize pygame
pygame.init()
# Set up the drawing window
screen = pygame.display.set_mode([800, 600])
# Run until the user asks to quit
running = True
while running:
# Did the user click the window close button?
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Fill the background with black
screen.fill((0, 0, 0))
# Draw stars
for i in range(2000):
x = int(noise.pnoise1(i / 10.0, octaves=4) * 800)
y = int(noise.pnoise1(i / 10.0 + 1000, octaves=4) * 600)
pygame.draw.circle(screen, (255, 255, 255), (x, y), 2)
# Draw the moon
pygame.draw.circle(screen, (180, 180, 180), (400, 5600 - 200), 5000, 0) # moon
# Draw craters on the surface of the moon (masked by the shape of the moon)
for i in range(20):
x = int(noise.pnoise1(i / 10.0, octaves=4) * 800)
y = int(noise.pnoise1(i / 10.0 + 1000, octaves=4) * 600)
pygame.draw.circle(screen, (100, 100, 100), (x, y), 20, 0)
# Flip the display
pygame.display.flip()
# Done! Time to quit.
pygame.quit()

BIN
wall.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB