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
# 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 itertools import cycle, repeat
from pathlib import Path
import random
from typing import List, Optional
import pygame
from more_itertools import flatten
from pydantic import BaseModel
import pygame
from creeper_adventure.game import Game
@ -348,7 +350,6 @@ class MainMenu(Menu):
h = 50
x = self.game.screen.get_size()[0] / 2 - w / 2
y = 300
print(self.game.frames)
return Button(self.game, self.surf, self.button_text, x, y, w, h, self.toggle)
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 = [
"click",
"pygame",
"noise",
"more_itertools",
]
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