[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: [pygame] QuadMap
Hi
Since you posted your quad stuff, I got an idea and now finally I had
the time to try it out. But I encountered some problems! It does not
work as I expect it to work.
The idea is to take an image, slice it into rectangles, then randomize
the egdgepoints of the rects and apply your quad code to the quads
(rects with randomized edgepoints). But sometimes it works, sometimes
not. Because I do not fully understand what you are exactly doing in the
quad code I ask you to take a look.
I see no reason why it should not work since I do exactly the same as
you have done in the last example (at least I think I do what you do).
If you set 'CHAOS' to 0 then it works perfectly, but is a bit boring
because it is without randomness.
As soon you set 'CHAOS'!=0 it does not work anymore! (hmm, sometimes
single quads work, but the rest does not....)
I have modified mesh to my needs.
Thanks.
~DR0ID
Kamilche schrieb:
DR0ID wrote:
nice!
Some comments would be appreciated. Is it an affine transformation?
The hit test look like raytracing code; how does it work?
Well, no can do - I'm looking stuff up in books and online, and barely
understanding this myself. For instance - you must specify the
quadrilateral corners in topleft, bottomleft, bottomright, topright
order for the picture to be upright - why's that? Specifying them in a
different order gives various flipping and mirroring effects... but
sometimes it crashes. Anyways, if you can figure it out, let me know. :-D
But what I can give you, is a more interesting version that textures
the quadrilaterals.
import pygame, math, Numeric
WIDTH = 800
HEIGHT = 600
BLACK = ( 0, 0, 0, 255)
WHITE = (255, 255, 255, 255)
RED = (255, 0, 0, 255)
YELLOW = (255, 255, 0, 255)
BLUE = ( 0, 0, 255, 255)
GREEN = ( 0, 255, 0, 255)
GRAY = (212, 208, 200, 255)
MAGENTA = (255, 0, 255, 255)
class Mesh(object):
quads = None
texture = None
posx = 0
posy = 0
def __init__(self):
self.pic = pygame.Surface([WIDTH, HEIGHT], pygame.SRCALPHA,
32).convert_alpha()
self.quads = []
def Add(self, quads):
self.quads.append(quads)
def Texture(self, texture):
quad = None
w, h = self.pic.get_size()
tw, th = texture.get_size()
array = pygame.surfarray.pixels3d(texture)
alpha = pygame.surfarray.pixels_alpha(texture)
myarray = pygame.surfarray.pixels3d(self.pic)
myalpha = pygame.surfarray.pixels_alpha(self.pic)
for quad in self.quads:
for y in range(quad.miny, quad.maxy):
for x in range(quad.minx, quad.maxx):
offset = quad.PointToOffset([x, y])
if offset:
x1 = int((tw-1) * offset[0])
y1 = int((th-1) * offset[1])
myarray[x, y] = array[x1, y1]
myalpha[x, y] = alpha[x1, y1]
def Draw(self, bg):
bg.blit(self.pic, [self.posx, self.posy])
for quad in self.quads:
quad.Draw(bg)
def PointToOffset(self, pos):
for quad in self.quads:
offset = quad.PointToOffset(pos)
if offset:
return offset
return None
def OffsetToPoint(self, offset):
for quad in self.quads:
quad.point = quad.OffsetToPoint(offset)
class Quad(object):
data = None
point = None
def __init__(self, p1, p2, p3, p4):
self.p1 = list(p1)
self.p2 = list(p2)
self.p3 = list(p3)
self.p4 = list(p4)
self.polys = [self.p1, self.p2, self.p3, self.p4]
self.minx = 99999
self.maxx = -1
self.miny = 99999
self.maxy = -1
for x, y in self.polys:
self.minx = min(self.minx, x)
self.maxx = max(self.maxx, x)
self.miny = min(self.miny, y)
self.maxy = max(self.maxy, y)
def Draw(self, bg):
pygame.draw.line(bg, RED, self.p1, self.p2, 1)
pygame.draw.line(bg, YELLOW, self.p2, self.p3, 1)
pygame.draw.line(bg, BLUE, self.p3, self.p4, 1)
pygame.draw.line(bg, GREEN, self.p4, self.p1, 1)
if self.point:
pygame.draw.rect(bg, MAGENTA, [self.point[0]-2,
self.point[1]-2, 4, 4], 0)
def OffsetToPoint(self, offset):
if offset == None:
return None
s, t = offset
x1, y1 = self.p1
x2, y2 = self.p2
x3, y3 = self.p4
x4, y4 = self.p3
xa = x1 + t * (x2 - x1)
ya = y1 + t * (y2 - y1)
xb = x3 + t * (x4 - x3)
yb = y3 + t * (y4 - y3)
X = xa + s * (xb - xa)
Y = ya + s * (yb - ya)
return int(X), int(Y)
def PointToOffset(self, pos):
x, y = pos[0], pos[1]
if not (x >= self.minx and x <= self.maxx and y >= self.miny
and y <= self.maxy):
return None
x1, y1 = self.p1
x2, y2 = self.p2
x3, y3 = self.p4
x4, y4 = self.p3
Ax = x2 - x1
Ay = y2 - y1
Bx = x4 - x3
By = y4 - y3
Cx = x3 - x1
Cy = y3 - y1
Dx = x - x1
Dy = y - y1
Ex = Bx - Ax
Ey = By - Ay
a = -Ax * Ey + Ay * Ex
b = Ey * Dx - Dy * Ex + Ay * Cx - Ax * Cy
c = Dx * Cy - Dy * Cx
det = b * b - 4 * a * c
if det >= 0:
if abs(a) < 0.001:
t = -c / float(b)
else:
t = (-b - math.sqrt(det)) / float(2 * a)
denom = (Cx + Ex * t)
if denom > 0.01:
s = (Dx - Ax * t) / float(denom)
else:
s = (Dy - Ay * t) / float(Cy + Ey * t)
if (t >= 0) and (t <= 1) and (s >= 0) and (s <= 1):
return s, t
def LoadPic(filename = 'test2.jpg'):
try:
pic = pygame.image.load(filename).convert_alpha()
except:
pic = pygame.Surface([100, 100], pygame.SRCALPHA,
32).convert_alpha()
pic.fill(RED, [0, 0, 50, 50])
pic.fill(YELLOW, [50, 0, 50, 50])
pic.fill(BLUE, [0, 50, 50, 50])
pic.fill(GREEN, [50, 50, 50, 50])
pic = AdjustAlpha(pic, .3)
return pic
def AdjustAlpha(pic, adj = .5):
alphaarray = pygame.surfarray.array_alpha(pic).astype(Numeric.Float)
alphaarray[:, :] = Numeric.clip(alphaarray * adj, 0, 255)
pygame.surfarray.pixels_alpha(pic)[:, :] =
alphaarray.astype(Numeric.UInt8)
return pic
def main():
pygame.init()
bg = pygame.display.set_mode([WIDTH, HEIGHT], 0, 32)
quit = 0
pic = LoadPic()
mesh = Mesh()
w, h = pic.get_size()
x, y = 280, 20
mesh.Add(Quad([x, y], [x, y+h], [x+w, y+h], [x+w, y]) )
x, y = 280, 300
mesh.Add(Quad([x, y+h], [x, y], [x+w, y], [x+w, y+h]) )
x, y = 0, 400
w, h = 200, 150
mesh.Add(Quad([x+w, y], [x, y], [x, y+h], [x+w, y+h]) )
mesh.Add(Quad([ 20, 50], [120, 30], [150, 110], [ 10, 130]) )
mesh.Add(Quad([210, 170], [250, 260], [100, 240], [120, 150]) )
if mesh.Texture(pic):
pass
else:
while not quit:
bg.fill(GRAY)
mesh.Draw(bg)
pygame.display.flip()
pygame.event.pump()
moved = 0
for e in pygame.event.get():
if e.type == pygame.QUIT:
quit = 1
break
elif e.type == pygame.MOUSEMOTION:
if not moved:
moved = 1
offset = mesh.PointToOffset(e.pos)
mesh.OffsetToPoint(offset)
pygame.quit()
if __name__ == '__main__':
main()
import pygame, math, Numeric, random
WIDTH = 800
HEIGHT = 600
CELLSIZE = 50
CHAOS = 10
BLACK = ( 0, 0, 0, 255)
WHITE = (255, 255, 255, 255)
RED = (255, 0, 0, 255)
YELLOW = (255, 255, 0, 255)
BLUE = ( 0, 0, 255, 255)
GREEN = ( 0, 255, 0, 255)
GRAY = (212, 208, 200, 255)
MAGENTA = (255, 0, 255, 255)
class Mesh(object):
quads = None
texture = None
posx = 0
posy = 0
def __init__(self, orig):
self.pic = pygame.Surface([WIDTH, HEIGHT], pygame.SRCALPHA, 32).convert_alpha()
self.quads = []
self.orig = orig
def Add(self, quads):
self.quads.append(quads)
def Texture(self, texture):
quad = None
w, h = self.pic.get_size()
myarray = pygame.surfarray.pixels3d(self.pic)
myalpha = pygame.surfarray.pixels_alpha(self.pic)
texture = pygame.Surface((CELLSIZE, CELLSIZE), pygame.SRCALPHA).convert_alpha()
tw, th = texture.get_size()
for quad in self.quads:
texture = pygame.Surface((CELLSIZE, CELLSIZE), pygame.SRCALPHA).convert_alpha()
texture.blit(self.orig, (0,0), pygame.Rect(quad.coord, (CELLSIZE, CELLSIZE)))
## self.pic.blit(texture, quad.coord)
array = pygame.surfarray.pixels3d(texture)
alpha = pygame.surfarray.pixels_alpha(texture)
for y in range(quad.miny, quad.maxy):
for x in range(quad.minx, quad.maxx):
offset = quad.PointToOffset([x, y])
if offset:
x1 = int((tw-1) * offset[0])
y1 = int((th-1) * offset[1])
myarray[x, y] = array[x1, y1]
myalpha[x, y] = alpha[x1, y1]
def Draw(self, bg):
bg.blit(self.pic, [self.posx, self.posy])
for quad in self.quads:
quad.Draw(bg)
def PointToOffset(self, pos):
for quad in self.quads:
offset = quad.PointToOffset(pos)
if offset:
print ">>>>>>>>quad.pointToOffset:", pos, quad.minx, quad.maxx, quad.miny, quad.maxy
return offset
return None
def OffsetToPoint(self, offset):
for quad in self.quads:
quad.point = quad.OffsetToPoint(offset)
class Quad(object):
data = None
point = None
def __init__(self, p1, p2, p3, p4, coord):
self.p1 = list(p1)
self.p2 = list(p2)
self.p3 = list(p3)
self.p4 = list(p4)
self.polys = [self.p1, self.p2, self.p3, self.p4]
self.minx = 99999
self.maxx = -1
self.miny = 99999
self.maxy = -1
self.coord = coord
self.initok = False
print self.polys
for x, y in self.polys:
self.minx = min(self.minx, x)
self.maxx = max(self.maxx, x)
self.miny = min(self.miny, y)
self.maxy = max(self.maxy, y)
def Draw(self, bg):
pygame.draw.line(bg, RED, self.p1, self.p2, 1)
pygame.draw.line(bg, YELLOW, self.p2, self.p3, 1)
pygame.draw.line(bg, BLUE, self.p3, self.p4, 1)
pygame.draw.line(bg, GREEN, self.p4, self.p1, 1)
if self.point:
pygame.draw.rect(bg, MAGENTA, [self.point[0]-2, self.point[1]-2, 4, 4], 0)
def OffsetToPoint(self, offset):
if offset == None:
return None
s, t = offset
x1, y1 = self.p1
x2, y2 = self.p2
x3, y3 = self.p4
x4, y4 = self.p3
xa = x1 + t * (x2 - x1)
ya = y1 + t * (y2 - y1)
xb = x3 + t * (x4 - x3)
yb = y3 + t * (y4 - y3)
X = xa + s * (xb - xa)
Y = ya + s * (yb - ya)
return int(X), int(Y)
def PointToOffset(self, pos):
x, y = pos[0], pos[1]
if not (x >= self.minx and x <= self.maxx and y >= self.miny and y <= self.maxy):
print "quad.pointToOffset:", x, y, self.minx, self.maxx, self.miny, self.maxy
return None
if self.initok:
print ">>>>>>>>>>>>>quad.pointToOffset:", x, y, self.polys
x1, y1 = self.p1
x2, y2 = self.p2
x3, y3 = self.p4
x4, y4 = self.p3
Ax = x2 - x1
Ay = y2 - y1
Bx = x4 - x3
By = y4 - y3
Cx = x3 - x1
Cy = y3 - y1
Dx = x - x1
Dy = y - y1
Ex = Bx - Ax
Ey = By - Ay
a = -Ax * Ey + Ay * Ex
b = Ey * Dx - Dy * Ex + Ay * Cx - Ax * Cy
c = Dx * Cy - Dy * Cx
det = b * b - 4 * a * c
if det >= 0:
if abs(a) < 0.001:
t = -c / float(b)
else:
t = (-b - math.sqrt(det)) / float(2 * a)
denom = (Cx + Ex * t)
if denom > 0.01:
s = (Dx - Ax * t) / float(denom)
else:
fuk = float(Cy + Ey * t)
if fuk:
s = (Dy - Ay * t) / fuk
else:
s=100
if self.initok:
print "======>s,t",s,t, self.minx, self.maxx, self.miny, self.maxy
if (t >= 0) and (t <= 1) and (s >= 0) and (s <= 1):
return s, t
def LoadPic(filename = 'small.png'):
try:
pic = pygame.image.load(filename).convert_alpha()
except:
pic = pygame.Surface([100, 100], pygame.SRCALPHA, 32).convert_alpha()
pic.fill(RED, [0, 0, 50, 50])
pic.fill(YELLOW, [50, 0, 50, 50])
pic.fill(BLUE, [0, 50, 50, 50])
pic.fill(GREEN, [50, 50, 50, 50])
pic = AdjustAlpha(pic, .3)
return pic
def AdjustAlpha(pic, adj = .5):
alphaarray = pygame.surfarray.array_alpha(pic).astype(Numeric.Float)
alphaarray[:, :] = Numeric.clip(alphaarray * adj, 0, 255)
pygame.surfarray.pixels_alpha(pic)[:, :] = alphaarray.astype(Numeric.UInt8)
return pic
def main():
pygame.init()
bg = pygame.display.set_mode([WIDTH, HEIGHT], 0, 32)
quit = 0
pic = pygame.transform.scale(LoadPic(), (WIDTH, HEIGHT))
mesh = Mesh(pic)
points = {}
numy = HEIGHT/CELLSIZE
numx = WIDTH/CELLSIZE
print "numx, numy", numx, numy
for y in range(numy+1):
for x in range(numx+1):
offsetx = 0
offsety = 0
if x>0 and x<numx and y>0 and y<numy:
print "random x,y:", x,y
offsetx = random.randint(-CHAOS, CHAOS)
offsety = random.randint(-CHAOS, CHAOS)
points[(x, y)] = (x*CELLSIZE+offsetx,y*CELLSIZE+offsety)
for coord in points.keys():
x,y = coord
if x<numx and y<numy:
## mesh.Add(Quad(points[(x,y)],points[(x, y+1)],points[(x+1, y+1)],points[(x+1, y)], (x*CELLSIZE, y*CELLSIZE)))
mesh.Add(Quad(points[(x,y)],points[(x, y+1)],points[(x+1, y+1)],points[(x+1, y)], (x*CELLSIZE, y*CELLSIZE)))
mesh.Texture(pic)
for quad in mesh.quads:
quad.initok = True
while not quit:
bg.fill(GRAY)
mesh.Draw(bg)
pygame.display.flip()
pygame.event.pump()
moved = 0
for e in pygame.event.get():
if e.type == pygame.QUIT:
quit = 1
break
elif e.type == pygame.MOUSEMOTION:
if not moved:
moved = 1
offset = mesh.PointToOffset(e.pos)
print offset, e.pos
mesh.OffsetToPoint(offset)
pygame.quit()
if __name__ == '__main__':
main()