Skip to content

Instantly share code, notes, and snippets.

@vxgmichel
Created February 2, 2017 15:38
Show Gist options
  • Save vxgmichel/fd5bf7211d22ee34ea9067e23a6a2c4e to your computer and use it in GitHub Desktop.
Save vxgmichel/fd5bf7211d22ee34ea9067e23a6a2c4e to your computer and use it in GitHub Desktop.
Generate a twin dragon fractal using pygame
import pygame
import random
import imageio
from fractions import gcd
lcm = lambda x, y: x * y // gcd(x, y)
def random_color():
r = lambda: random.randint(0, 255)
return r(), r(), r()
def colorcycle(n):
lst = [random_color() for _ in range(n)]
while True:
yield from lst
def vectors(x=1, y=0, spiral=False):
while True:
yield x, y
x, y = (x-y, x+y) if spiral else (-x-y, x-y)
def translations(x=1, y=0, spiral=False):
g0 = vectors(x, y, spiral)
g1 = vectors(x, y, spiral)
next(g1)
return zip(g0, g1)
def shapes(shape=(0, 0, 1, 1), vector=(1, 0), spiral=False):
# First shape
x, y, w, h = shape
yield x, y, w, h
# Second shape
x += vector[0]
y += vector[1]
yield x, y, w, h
# Next shapes
for (i0, j0), (i1, j1) in translations(*vector, spiral):
x += i1 - max(0, i0)
y += j1 - max(0, j0)
w += abs(i0)
h += abs(j0)
yield x, y, w, h
def sprites(shape=(50, 50, 1, 1), vector=(1, 0), spiral=False):
shapegen = shapes(shape, vector, spiral)
tsgen = translations(*vector, spiral)
for _ in range(2):
x, y, w, h = next(shapegen)
surf = pygame.Surface((w, h))
last = Twin(surf, (x, y))
yield last
for shape, translation in zip(shapegen, tsgen):
last = Twin.from_sprite(last, translation, shape)
yield last
class Twin(pygame.sprite.Sprite):
colorgen = colorcycle(8)
def __init__(self, image, position):
pygame.sprite.Sprite.__init__(self)
self.image = image
self.image.fill(
(0, 0, 0), special_flags=pygame.BLEND_RGB_MIN)
self.image.fill(
next(self.colorgen), special_flags=pygame.BLEND_RGB_ADD)
self.rect = self.image.get_rect(topleft=position)
@classmethod
def from_sprite(cls, sprite, translation, shape):
x, y, w, h = shape
surf = pygame.Surface((w, h), flags=pygame.SRCALPHA)
surf.fill((0, 0, 0, 0))
(i0, j0), (i1, j1) = translation
x0, y0 = sprite.rect.topleft
a = (x0-i0+i1) - x
b = (y0-j0+j1) - y
surf.blit(sprite.image, (a, b))
a = (x0+i1) - x
b = (y0+j1) - y
surf.blit(sprite.image, (a, b))
return cls(surf, (x, y))
def main(width=161, height=161, nb_sprite=28, spiral=False,
speed=0.1, rotate=-0.15, fps=36, scale=1.5,
gif='twindragons.gif'):
pygame.init()
pygame.display.set_caption("Twin dragons")
steps = int(round(fps/speed))
display_width = int(scale*width/2**0.5)
display_height = int(scale*height/2**0.5)
rotate_steps = int(round(fps/rotate)) if rotate else 1
total_steps = lcm(abs(steps), abs(rotate_steps))
screen = pygame.display.set_mode((display_width, display_height))
clock = pygame.time.Clock()
group = pygame.sprite.Group()
spritegen = sprites((width*8, height*8, 1, 1), (0, 1), spiral)
surf = pygame.Surface((width*16, height*16), flags=pygame.SRCALPHA)
background_color = random_color()
images = []
frame = 0
screen.fill(background_color)
pygame.display.flip()
for i, sprite in zip(range(nb_sprite), spritegen):
group.add(sprite)
group.draw(surf)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_f:
pygame.display.toggle_fullscreen()
if pygame.key.get_pressed()[pygame.K_p]:
continue
frame += 1
ratio = (frame % steps)/steps
angle = 360 * (frame % rotate_steps) / rotate_steps
if angle >= 180:
angle -= 360
if angle < 180:
angle += 360
delta = (16 - 16 ** (1-ratio)) / 2
dx = int(round(delta * width))
dy = int(round(delta * height))
rect = pygame.Rect(dx, dy, 16*width-2*dx, 16*height-2*dy)
subsurf = surf.subsurface(rect)
scale_factor = scale * width / rect.width
rotated = pygame.transform.rotozoom(subsurf, angle, scale_factor)
rect = rotated.get_rect()
rect.inflate_ip(display_width-rect.width, display_height-rect.height)
screen.blit(rotated, (0, 0), rect)
pygame.display.flip()
if gif and len(images) < total_steps:
images.append(pygame.surfarray.array3d(screen))
if gif and len(images) == total_steps:
imageio.mimwrite(gif, images, fps=fps)
print("Gif written to {}".format(gif))
gif = None
screen.fill(background_color)
clock.tick(fps)
if __name__ == "__main__":
main()
@jaycedonovane
Copy link

bonjour vincent pourrais tu faire une video sur le premier niveaude double drago ou street of rage e pygame cr il n y a ren nul par sur youtube sauf des ados qui fon des trucks nul...
et aussi si tu eu tupeu just laisser la camera filmerton ecran je fais le montage video et aprs tu recuper les sous de youtube...ya zero français qui on fait y'a un creneau a prendre
voila bonne journée

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment