init
This commit is contained in:
commit
38355d2442
9083 changed files with 1225834 additions and 0 deletions
212
.venv/lib/python3.8/site-packages/pygame/examples/mask.py
Normal file
212
.venv/lib/python3.8/site-packages/pygame/examples/mask.py
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
#!/usr/bin/env python
|
||||
""" pygame.examples.mask
|
||||
|
||||
A pygame.mask collision detection production.
|
||||
|
||||
|
||||
|
||||
|
||||
Brought
|
||||
|
||||
to
|
||||
you
|
||||
by
|
||||
|
||||
the
|
||||
|
||||
pixels
|
||||
0000000000000
|
||||
and
|
||||
111111
|
||||
|
||||
|
||||
This is 32 bits:
|
||||
11111111111111111111111111111111
|
||||
|
||||
There are 32 or 64 bits in a computer 'word'.
|
||||
Rather than using one word for a pixel,
|
||||
the mask module represents 32 or 64 pixels in one word.
|
||||
As you can imagine, this makes things fast, and saves memory.
|
||||
|
||||
Compute intensive things like collision detection,
|
||||
and computer vision benefit greatly from this.
|
||||
|
||||
|
||||
This module can also be run as a stand-alone program, excepting
|
||||
one or more image file names as command line arguments.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import random
|
||||
|
||||
import pygame as pg
|
||||
|
||||
|
||||
def maskFromSurface(surface, threshold=127):
|
||||
return pg.mask.from_surface(surface, threshold)
|
||||
|
||||
|
||||
def vadd(x, y):
|
||||
return [x[0] + y[0], x[1] + y[1]]
|
||||
|
||||
|
||||
def vsub(x, y):
|
||||
return [x[0] - y[0], x[1] - y[1]]
|
||||
|
||||
|
||||
def vdot(x, y):
|
||||
return x[0] * y[0] + x[1] * y[1]
|
||||
|
||||
|
||||
class Sprite:
|
||||
def __init__(self, surface, mask=None):
|
||||
self.surface = surface
|
||||
if mask:
|
||||
self.mask = mask
|
||||
else:
|
||||
self.mask = maskFromSurface(self.surface)
|
||||
self.setPos([0, 0])
|
||||
self.setVelocity([0, 0])
|
||||
|
||||
def setPos(self, pos):
|
||||
self.pos = [pos[0], pos[1]]
|
||||
|
||||
def setVelocity(self, vel):
|
||||
self.vel = [vel[0], vel[1]]
|
||||
|
||||
def move(self, dr):
|
||||
self.pos = vadd(self.pos, dr)
|
||||
|
||||
def kick(self, impulse):
|
||||
self.vel[0] += impulse[0]
|
||||
self.vel[1] += impulse[1]
|
||||
|
||||
def collide(self, s):
|
||||
"""Test if the sprites are colliding and
|
||||
resolve the collision in this case."""
|
||||
offset = [int(x) for x in vsub(s.pos, self.pos)]
|
||||
overlap = self.mask.overlap_area(s.mask, offset)
|
||||
if overlap == 0:
|
||||
return
|
||||
"""Calculate collision normal"""
|
||||
nx = self.mask.overlap_area(
|
||||
s.mask, (offset[0] + 1, offset[1])
|
||||
) - self.mask.overlap_area(s.mask, (offset[0] - 1, offset[1]))
|
||||
ny = self.mask.overlap_area(
|
||||
s.mask, (offset[0], offset[1] + 1)
|
||||
) - self.mask.overlap_area(s.mask, (offset[0], offset[1] - 1))
|
||||
if nx == 0 and ny == 0:
|
||||
"""One sprite is inside another"""
|
||||
return
|
||||
n = [nx, ny]
|
||||
dv = vsub(s.vel, self.vel)
|
||||
J = vdot(dv, n) / (2 * vdot(n, n))
|
||||
if J > 0:
|
||||
"""Can scale up to 2*J here to get bouncy collisions"""
|
||||
J *= 1.9
|
||||
self.kick([nx * J, ny * J])
|
||||
s.kick([-J * nx, -J * ny])
|
||||
return
|
||||
|
||||
# """Separate the sprites"""
|
||||
# c1 = -overlap/vdot(n,n)
|
||||
# c2 = -c1/2
|
||||
# self.move([c2*nx,c2*ny])
|
||||
# s.move([(c1+c2)*nx,(c1+c2)*ny])
|
||||
|
||||
def update(self, dt):
|
||||
self.pos[0] += dt * self.vel[0]
|
||||
self.pos[1] += dt * self.vel[1]
|
||||
|
||||
|
||||
def main(*args):
|
||||
"""Display multiple images bounce off each other using collision detection
|
||||
|
||||
Positional arguments:
|
||||
one or more image file names.
|
||||
|
||||
This pg.masks demo will display multiple moving sprites bouncing
|
||||
off each other. More than one sprite image can be provided.
|
||||
"""
|
||||
|
||||
if len(args) == 0:
|
||||
raise ValueError("Require at least one image file name: non given")
|
||||
print("Press any key to quit")
|
||||
pg.init()
|
||||
screen = pg.display.set_mode((640, 480))
|
||||
images = []
|
||||
masks = []
|
||||
for impath in args:
|
||||
images.append(pg.image.load(impath).convert_alpha())
|
||||
masks.append(maskFromSurface(images[-1]))
|
||||
|
||||
numtimes = 10
|
||||
import time
|
||||
|
||||
t1 = time.time()
|
||||
for x in range(numtimes):
|
||||
unused_mask = maskFromSurface(images[-1])
|
||||
t2 = time.time()
|
||||
|
||||
print("python maskFromSurface :%s" % (t2 - t1))
|
||||
|
||||
t1 = time.time()
|
||||
for x in range(numtimes):
|
||||
unused_mask = pg.mask.from_surface(images[-1])
|
||||
t2 = time.time()
|
||||
|
||||
print("C pg.mask.from_surface :%s" % (t2 - t1))
|
||||
|
||||
sprites = []
|
||||
for i in range(20):
|
||||
j = i % len(images)
|
||||
s = Sprite(images[j], masks[j])
|
||||
s.setPos(
|
||||
(
|
||||
random.uniform(0, screen.get_width()),
|
||||
random.uniform(0, screen.get_height()),
|
||||
)
|
||||
)
|
||||
s.setVelocity((random.uniform(-5, 5), random.uniform(-5, 5)))
|
||||
sprites.append(s)
|
||||
pg.time.set_timer(pg.USEREVENT, 33)
|
||||
while 1:
|
||||
event = pg.event.wait()
|
||||
if event.type == pg.QUIT:
|
||||
return
|
||||
elif event.type == pg.USEREVENT:
|
||||
|
||||
# Do both mechanics and screen update
|
||||
screen.fill((240, 220, 100))
|
||||
for i, sprite in enumerate(sprites):
|
||||
for j in range(i + 1, len(sprites)):
|
||||
sprite.collide(sprites[j])
|
||||
for s in sprites:
|
||||
s.update(1)
|
||||
if s.pos[0] < -s.surface.get_width() - 3:
|
||||
s.pos[0] = screen.get_width()
|
||||
elif s.pos[0] > screen.get_width() + 3:
|
||||
s.pos[0] = -s.surface.get_width()
|
||||
if s.pos[1] < -s.surface.get_height() - 3:
|
||||
s.pos[1] = screen.get_height()
|
||||
elif s.pos[1] > screen.get_height() + 3:
|
||||
s.pos[1] = -s.surface.get_height()
|
||||
screen.blit(s.surface, s.pos)
|
||||
pg.display.update()
|
||||
elif event.type == pg.KEYDOWN:
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: mask.py <IMAGE> [<IMAGE> ...]")
|
||||
print("Let many copies of IMAGE(s) bounce against each other")
|
||||
print("Press any key to quit")
|
||||
main_dir = os.path.split(os.path.abspath(__file__))[0]
|
||||
imagename = os.path.join(main_dir, "data", "chimp.png")
|
||||
main(imagename)
|
||||
|
||||
else:
|
||||
main(*sys.argv[1:])
|
||||
pg.quit()
|
||||
Loading…
Add table
Add a link
Reference in a new issue