Evenly distributed random lines - python

I want to draw evenly distributed random lines on a image.
My thought is to generate evenly distributed points on the image, and connect each two of them randomly. (Please ignore the bug of lacking coordinates on the 2 edges. I will fix them at last.)
from PIL import Image, ImageDraw
import random
# set attrs
gap = 170 # gap between points
err = 10 # volatility of coordinates
linewidth = 20 # line width
img = Image.open("img2.png", mode="r")
# initiation data/var
draw = ImageDraw.Draw(img)
width, height = img.size
class Coord:
def __init__(self, x, y):
self.x = x
self.y = y
currx = 0
curry = 0
coordlist = []
# generate the set of points
while currx <= width:
while curry <= height:
coordlist.append(Coord( \
currx + random.randint(-err,err), \
curry + random.randint(-err,err) \
))
curry += gap
curry = gap
currx += gap
# draw line between each two random points
while len(coordlist) >= 2:
# pick indices
index1 = random.randint(0, len(coordlist)-1)
index2 = random.randint(0, len(coordlist)-1)
while index1 == index2:
index2 = random.randint(0, len(coordlist)-1)
# draw line
draw.line((coordlist[index1].x,coordlist[index1].y, coordlist[index2].x,coordlist[index2].y), fill='black', width=linewidth)
# remove elements
coordlist = [v for i,v in enumerate(coordlist) if i not in frozenset((index1, index2))]
img.show()
However, this method is too inconsistent and sometimes some lines will stick together, causing some areas to be much more dense than other areas:
Good example:
Bad example:

I figured it out myself with help from the comments.
The idea is to set those evenly distributed grid points as the start points, and use a random angle with sin/cos to generate random lines.
async def process_img(gap: int, err: int, linewidth: int, url: str):
with urllib.request.urlopen(url) as webimg:
with open('temp.jpg', 'wb') as f:
f.write(webimg.read())
img = Image.open('temp.jpg')
# initiation data/var
draw = ImageDraw.Draw(img)
width, height = img.size
class Coord:
def __init__(self, x, y):
self.x = x
self.y = y
currx = 0
curry = 0
coordlist = []
# generate the set of points
while currx <= width:
while curry <= height:
coordlist.append(Coord( \
currx + random.randint(0,err), \
curry + random.randint(0,err) \
))
curry += gap
curry = gap
currx += gap
# calculate endpoint with angle/length
def calcEnd(x, y, angle, length):
endx = int(x - (math.cos(math.radians(angle)) * length))
endy = int(y - (math.sin(math.radians(angle)) * length))
return endx, endy
# draw line with random angle/length
for c in coordlist:
length = LENGTH
randangle = random.randint(0,359)
endx, endy = calcEnd(c.x, c.y, randangle, length)
draw.line((c.x, c.y, endx, endy), fill='black', width=linewidth)
img.convert('RGB').save('outtemp.jpg')
img_path = Path() / "outtemp.jpg"
return img_path.resolve()

Related

Modify the Quadtree algorithm's criteria to create nodes/ children based on difference in pixel ID values, instead of number of points in each node

Quadtree code are readily available on Github. However most of the Quadtrees (collision detection) work on following criteria:
if No. Points in each Node > Capacity
Divide the node into Four parts
else
Do Not divide further
I am instead looking to apply the following logic. Id there are more than one Instances in a node, divide it further into four until each node has only one instance.
if No. of Instance in each Node > 1
Divide the node into Four parts
else
Do Not Divide further
I already have an image with each pixel labelled as per the instance. For example
Instance Value
Background 0
Chair 1
Table 2
Plant 3
Teddy Bear 4
So with all the pixels labelled, I have an image that looks like this
So if we read this image into an array, each (x,y) coordinate has a value associated.
After quadtree is applied, this is what I would like the quadtree to do to my image. As an example only a portion of quadtree applied on chair is shown for demo
So how do I modify the Quadtree criteria in the following code, copied from Github to achieve what I am looking for?
import numpy as np
import math
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def distanceToCenter(self, center):
return math.sqrt((center.x-self.x)**2 + (center.y-self.y)**2)
class Rectangle:
def __init__(self, center, width, height):
self.center = center
self.width = width
self.height = height
self.west = center.x - width
self.east = center.x + width
self.north = center.y - height
self.south = center.y + height
def containsPoint(self, point):
return (self.west <= point.x < self.east and
self.north <= point.y < self.south)
def intersects(self, range):
return not (range.west > self.east or
range.east < self.west or
range.north > self.south or
range.south < self.north)
def draw(self, ax, c='k', lw=1, **kwargs):
x1, y1 = self.west, self.north
x2, y2 = self.east, self.south
ax.plot([x1,x2,x2,x1,x1], [y1,y1,y2,y2,y1], c=c, lw=lw, **kwargs)
class QuadTree:
def __init__(self, boundary, capacity = 4):
self.boundary = boundary
self.capacity = capacity
self.points = []
self.divided = False
def insert(self, point):
# if the point is in the range of current quadTree
if not self.boundary.containsPoint(point):
return False
# if has not reached capcaity
if len(self.points) < self.capacity:
self.points.append(point)
return True
if not self.divided:
self.divide()
if self.nw.insert(point):
return True
elif self.ne.insert(point):
return True
elif self.sw.insert(point):
return True
elif self.se.insert(point):
return True
return False
def queryRange(self, range):
found_points = []
if not self.boundary.intersects(range):
return []
for point in self.points:
if range.containsPoint(point):
found_points.append(point)
if self.divided:
found_points.extend(self.nw.queryRange(range))
found_points.extend(self.ne.queryRange(range))
found_points.extend(self.sw.queryRange(range))
found_points.extend(self.se.queryRange(range))
return found_points
def queryRadius(self, range, center):
found_points = []
if not self.boundary.intersects(range):
return []
for point in self.points:
if range.containsPoint(point) and point.distanceToCenter(center) <= range.width:
found_points.append(point)
if self.divided:
found_points.extend(self.nw.queryRadius(range, center))
found_points.extend(self.ne.queryRadius(range, center))
found_points.extend(self.sw.queryRadius(range, center))
found_points.extend(self.se.queryRadius(range, center))
return found_points
def divide(self):
center_x = self.boundary.center.x
center_y = self.boundary.center.y
new_width = self.boundary.width / 2
new_height = self.boundary.height / 2
nw = Rectangle(Point(center_x - new_width, center_y - new_height), new_width, new_height)
self.nw = QuadTree(nw)
ne = Rectangle(Point(center_x + new_width, center_y - new_height), new_width, new_height)
self.ne = QuadTree(ne)
sw = Rectangle(Point(center_x - new_width, center_y + new_height), new_width, new_height)
self.sw = QuadTree(sw)
se = Rectangle(Point(center_x + new_width, center_y + new_height), new_width, new_height)
self.se = QuadTree(se)
self.divided = True
def __len__(self):
count = len(self.points)
if self.divided:
count += len(self.nw) + len(self.ne) + len(self.sw) + len(self.se)
return count
def draw(self, ax):
self.boundary.draw(ax)
if self.divided:
self.nw.draw(ax)
self.ne.draw(ax)
self.se.draw(ax)
self.sw.draw(ax)

Add Depth to Each Instance's Quadtree Nodes

How can I modify the code shown below to apply different depth level of quadtree to each instance contained in the image. I would like to apply a finer quadtree level on instances such as the 'teddy bear' and 'plant' while a coarse quadtree level on the 'background', 'table' and 'plant vase' instances.
EFFORTS UNDERTAKEN SO FAR (BIT LONG TO READ)
I have an image such that each x,y coordinate already has a value associated based on the instance as follows:
INSTANCE PIXEL VALUE
background 0.0
chair 1.0
table 2.0
teddy bear 3.0
plant 4.0
vase 5.0
This is what the image looks like when plotted as follows
img_arr = np.loadtxt("seg_mask_retrieved.txt")
mask_image = plt.imshow(img_arr, cmap='hot', interpolation='nearest')
I am able to perform instance value based quadtree (Results shown at the end). All I need now is to modify this code in order to add depth level based on each instance:
import numpy as np
import math
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def distanceToCenter(self, center):
return math.sqrt((center.x-self.x)**2 + (center.y-self.y)**2)
class Rectangle:
def __init__(self, center, width, height):
self.center = center
self.width = width
self.height = height
self.west = center.x - width
self.east = center.x + width
self.north = center.y - height
self.south = center.y + height
def containsPoint(self, point):
return (self.west <= point.x < self.east and
self.north <= point.y < self.south)
def intersects(self, range):
return not (range.west > self.east or
range.east < self.west or
range.north > self.south or
range.south < self.north)
def draw(self, ax, c='g', lw=1, **kwargs):
x1, y1 = self.west, self.north
x2, y2 = self.east, self.south
ax.plot([x1,x2,x2,x1,x1], [y1,y1,y2,y2,y1], c=c, lw=lw, **kwargs)
class QuadTree:
def __init__(self, boundary, capacity = 1):
self.boundary = boundary
self.capacity = capacity
self.points = []
self.instances = []
self.unique_instances = []
self.divided = False
def insert(self, point, instance):
# if the point is in the range of current quadTree
if not self.boundary.containsPoint(point):
return False
if self.divided:
if self.nw.insert(point, instance):
return True
elif self.ne.insert(point, instance):
return True
elif self.sw.insert(point, instance):
return True
elif self.se.insert(point, instance):
return True
else:
assert "Should never happen"
else:
# if has not reached capcaity
instance_already_seen = instance in self.unique_instances
if instance_already_seen or len(self.unique_instances) < self.capacity:
self.points.append(point)
self.instances.append(instance)
if not instance_already_seen:
self.unique_instances.append(instance)
return True
self.divide()
assert self.insert(point, instance)
return True
def queryRange(self, range):
found_points = []
if not self.boundary.intersects(range):
return []
if self.divided:
found_points.extend(self.nw.queryRange(range))
found_points.extend(self.ne.queryRange(range))
found_points.extend(self.sw.queryRange(range))
found_points.extend(self.se.queryRange(range))
else:
for point in self.points:
if range.containsPoint(point):
found_points.append(point)
return found_points
def queryRadius(self, range, center):
if not self.boundary.intersects(range):
return []
found_points = []
if self.divided:
found_points.extend(self.nw.queryRadius(range, center))
found_points.extend(self.ne.queryRadius(range, center))
found_points.extend(self.sw.queryRadius(range, center))
found_points.extend(self.se.queryRadius(range, center))
else:
for point in self.points:
if range.containsPoint(point) and point.distanceToCenter(center) <= range.width:
found_points.append(point)
return found_points
def divide(self):
center_x = self.boundary.center.x
center_y = self.boundary.center.y
new_width = self.boundary.width / 2
new_height = self.boundary.height / 2
nw = Rectangle(Point(center_x - new_width, center_y - new_height), new_width, new_height)
self.nw = QuadTree(nw)
ne = Rectangle(Point(center_x + new_width, center_y - new_height), new_width, new_height)
self.ne = QuadTree(ne)
sw = Rectangle(Point(center_x - new_width, center_y + new_height), new_width, new_height)
self.sw = QuadTree(sw)
se = Rectangle(Point(center_x + new_width, center_y + new_height), new_width, new_height)
self.se = QuadTree(se)
self.divided = True
self.unique_instances = []
for (point, instance) in zip(self.points, self.instances):
assert self.insert(point, instance)
self.points = []
self.instances = []
def __len__(self):
if self.divided:
return len(self.nw) + len(self.ne) + len(self.sw) + len(self.se)
else:
return len(self.points)
def draw(self, ax):
if self.divided:
self.nw.draw(ax)
self.ne.draw(ax)
self.se.draw(ax)
self.sw.draw(ax)
else:
self.boundary.draw(ax)
The code is run using the following commands
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import gridspec
from quadtree import Point, Rectangle, QuadTree
DPI = 72
INPUT_FILE = 'seg_mask_retrieved.npy'
mask_image = np.load(INPUT_FILE)
height, width = mask_image.shape
domain = Rectangle(Point(width/2, height/2), width/2, height/2)
qtree = QuadTree(domain)
for y in range(height):
for x in range(width):
assert qtree.insert(Point(x, y), mask_image[y, x])
print('Total points: ', len(qtree))
# draw rectangles
fig = plt.figure(figsize=(700/DPI, 500/DPI), dpi=DPI)
ax = plt.subplot()
ax.imshow(mask_image, cmap='hot', interpolation='nearest')
ax.set_xlim(0, width)
ax.set_ylim(0, height)
qtree.draw(ax)
ax.invert_yaxis()
plt.tight_layout()
plt.savefig('search-quadtree.png', DPI=72)
plt.show()
The output looks like this
After adding depth to each instance, the output should somewhat look like this (only the chair instance has been modified to show the output just for demonstration of a coarse quadtree)

Remove all empty space from image

I need to remove all white-spaces from image but I don't know how to do it..
I am using trim functionality to trim white spaces from border but still white-spaces are present in middle of image I am attaching my original image from which I want to remove white-spaces
my code
from PIL import Image, ImageChops
import numpy
def trim(im):
bg = Image.new(im.mode, im.size, im.getpixel((0, 0)))
diff = ImageChops.difference(im, bg)
diff = ImageChops.add(diff, diff, 2.0, -100)
box = diff.getbbox()
if box:
im.crop(box).save("trim_pil.png")
im = Image.open("/home/einfochips/Documents/imagecomparsion/kroger_image_comparison/SnapshotImages/screenshot_Hide.png")
im = trim(im)
but this code only remove space from borders, I need to remove spaces from middle also. Please help if possible, it would be very good if I got all five images in different PNG file.
You could go the long way with a for loop
from PIL import Image, ImageChops
def getbox(im, color):
bg = Image.new(im.mode, im.size, color)
diff = ImageChops.difference(im, bg)
diff = ImageChops.add(diff, diff, 2.0, -100)
return diff.getbbox()
def split(im):
retur = []
emptyColor = im.getpixel((0, 0))
box = getbox(im, emptyColor)
width, height = im.size
pixels = im.getdata()
sub_start = 0
sub_width = 0
offset = box[1] * width
for x in range(width):
if pixels[x + offset] == emptyColor:
if sub_width > 0:
retur.append((sub_start, box[1], sub_width, box[3]))
sub_width = 0
sub_start = x + 1
else:
sub_width = x + 1
if sub_width > 0:
retur.append((sub_start, box[1], sub_width, box[3]))
return retur
This makes it easy to retrieve the crop boxes in the image like this:
im = Image.open("/home/einfochips/Documents/imagecomparsion/kroger_image_comparison/SnapshotImages/screenshot_Hide.png")
for idx, box in enumerate(split(im)):
im.crop(box).save("trim_{0}.png".format(idx))
If you already know the size of the images toy want to extract you could go with
def split(im, box):
retur = []
pixels = im.getdata()
emptyColor = pixels[0]
width, height = im.size;
y = 0;
while y < height - box[3]:
x = 0
y_step = 1
while x < width - box[2]:
x_step = 1
if pixels[y*width + x] != emptyColor:
retur.append((x, y, box[2] + x, box[3] + y))
y_step = box[3] + 1
x_step = box[2] + 1
x += x_step
y += y_step
return retur
Adding another parameter to the call
for idx, box in enumerate(split(im, (0, 0, 365, 150))):
im.crop(box).save("trim_{0}.png".format(idx))

PIL: Generating Vertical Gradient Image

In Android, I used the following code to generate a gradient background that I need:
<gradient
android:angle="90"
android:startColor="#40000000"
android:endColor="#00000000"
android:type="linear" />
The background goes from light to relatively dark from top to bottom. I wonder how to do the same in Python with PIL, since I need the same effect on another program written in Python.
Here's something that shows ways to draw multicolor rectangular horizontal and vertical gradients.
rom PIL import Image, ImageDraw
BLACK, DARKGRAY, GRAY = ((0,0,0), (63,63,63), (127,127,127))
LIGHTGRAY, WHITE = ((191,191,191), (255,255,255))
BLUE, GREEN, RED = ((0, 0, 255), (0, 255, 0), (255, 0, 0))
class Point(object):
def __init__(self, x, y):
self.x, self.y = x, y
class Rect(object):
def __init__(self, x1, y1, x2, y2):
minx, maxx = (x1,x2) if x1 < x2 else (x2,x1)
miny, maxy = (y1,y2) if y1 < y2 else (y2,y1)
self.min = Point(minx, miny)
self.max = Point(maxx, maxy)
width = property(lambda self: self.max.x - self.min.x)
height = property(lambda self: self.max.y - self.min.y)
def gradient_color(minval, maxval, val, color_palette):
""" Computes intermediate RGB color of a value in the range of minval
to maxval (inclusive) based on a color_palette representing the range.
"""
max_index = len(color_palette)-1
delta = maxval - minval
if delta == 0:
delta = 1
v = float(val-minval) / delta * max_index
i1, i2 = int(v), min(int(v)+1, max_index)
(r1, g1, b1), (r2, g2, b2) = color_palette[i1], color_palette[i2]
f = v - i1
return int(r1 + f*(r2-r1)), int(g1 + f*(g2-g1)), int(b1 + f*(b2-b1))
def horz_gradient(draw, rect, color_func, color_palette):
minval, maxval = 1, len(color_palette)
delta = maxval - minval
width = float(rect.width) # Cache.
for x in range(rect.min.x, rect.max.x+1):
f = (x - rect.min.x) / width
val = minval + f * delta
color = color_func(minval, maxval, val, color_palette)
draw.line([(x, rect.min.y), (x, rect.max.y)], fill=color)
def vert_gradient(draw, rect, color_func, color_palette):
minval, maxval = 1, len(color_palette)
delta = maxval - minval
height = float(rect.height) # Cache.
for y in range(rect.min.y, rect.max.y+1):
f = (y - rect.min.y) / height
val = minval + f * delta
color = color_func(minval, maxval, val, color_palette)
draw.line([(rect.min.x, y), (rect.max.x, y)], fill=color)
if __name__ == '__main__':
# Draw a three color vertical gradient.
color_palette = [BLUE, GREEN, RED]
region = Rect(0, 0, 730, 350)
width, height = region.max.x+1, region.max.y+1
image = Image.new("RGB", (width, height), WHITE)
draw = ImageDraw.Draw(image)
vert_gradient(draw, region, gradient_color, color_palette)
image.show()
#image.save("vert_gradient.png", "PNG")
#print('image saved')
And here's the image it generates and displays:
This calculates the intermediate colors in the RGB color space, but other colorspaces could be used — for examples compare results of my answers to the question Range values to pseudocolor.
This could easily be extended to generate RGBA (RGB+Alpha) mode images.
If you only need two colours, this can be done very simply:
def generate_gradient(
colour1: str, colour2: str, width: int, height: int) -> Image:
"""Generate a vertical gradient."""
base = Image.new('RGB', (width, height), colour1)
top = Image.new('RGB', (width, height), colour2)
mask = Image.new('L', (width, height))
mask_data = []
for y in range(height):
mask_data.extend([int(255 * (y / height))] * width)
mask.putdata(mask_data)
base.paste(top, (0, 0), mask)
return base
This creates a layer in each colour, then creates a mask with transparency varying according to the y position. You can replace y / height in line 10 with x / width for a horizontal gradient, or any function of x and y for another gradient.
Here is the technique spelled out. You need 2 layers on top of each other, one for each color. Then you make the transparency for each increasing for the top layer and decreasing for the bottom layer. For extra homework you can change the rate of transparency to an ascending logarithmic scale rather than linear. Have fun with it.
Making some modifications to #martineau's code, this function handles gradient orientation in degrees (not only vertical or horizontal):
from PIL import Image
import math
BLACK, DARKGRAY, GRAY = ((0,0,0), (63,63,63), (127,127,127))
LIGHTGRAY, WHITE = ((191,191,191), (255,255,255))
BLUE, GREEN, RED = ((0, 0, 255), (0, 255, 0), (255, 0, 0))
class Point(object):
def __init__(self, x, y):
self.x, self.y = x, y
def rot_x(self, degrees):
radians = math.radians(degrees)
return self.x * math.cos(radians) + self.y * math.sin(radians)
class Rect(object):
def __init__(self, x1, y1, x2, y2):
minx, maxx = (x1,x2) if x1 < x2 else (x2,x1)
miny, maxy = (y1,y2) if y1 < y2 else (y2,y1)
self.min = Point(minx, miny)
self.max = Point(maxx, maxy)
def min_max_rot_x(self, degrees):
first = True
for x in [self.min.x, self.max.x]:
for y in [self.min.y, self.max.y]:
p = Point(x, y)
rot_d = p.rot_x(degrees)
if first:
min_d = rot_d
max_d = rot_d
else:
min_d = min(min_d, rot_d)
max_d = max(max_d, rot_d)
first = False
return min_d, max_d
width = property(lambda self: self.max.x - self.min.x)
height = property(lambda self: self.max.y - self.min.y)
def gradient_color(minval, maxval, val, color_palette):
""" Computes intermediate RGB color of a value in the range of minval
to maxval (inclusive) based on a color_palette representing the range.
"""
max_index = len(color_palette)-1
delta = maxval - minval
if delta == 0:
delta = 1
v = float(val-minval) / delta * max_index
i1, i2 = int(v), min(int(v)+1, max_index)
(r1, g1, b1), (r2, g2, b2) = color_palette[i1], color_palette[i2]
f = v - i1
return int(r1 + f*(r2-r1)), int(g1 + f*(g2-g1)), int(b1 + f*(b2-b1))
def degrees_gradient(im, rect, color_func, color_palette, degrees):
minval, maxval = 1, len(color_palette)
delta = maxval - minval
min_d, max_d = rect.min_max_rot_x(degrees)
range_d = max_d - min_d
for x in range(rect.min.x, rect.max.x + 1):
for y in range(rect.min.y, rect.max.y+1):
p = Point(x, y)
f = (p.rot_x(degrees) - min_d) / range_d
val = minval + f * delta
color = color_func(minval, maxval, val, color_palette)
im.putpixel((x, y), color)
def gradient_image(color_palette, degrees):
region = Rect(0, 0, 600, 400)
width, height = region.max.x+1, region.max.y+1
image = Image.new("RGB", (width, height), WHITE)
degrees_gradient(image, region, gradient_color, color_palette, -degrees)
return image
This flexibility comes at the cost of having to set colors pixel by pixel instead of using lines.

Python NameError: name -- syntax error [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
I have a compiler error “not defined” although there is a definition
from gasp import *
GRID_SIZE = 30
MARGIN = GRID_SIZE
BACKGROUND_COLOR = color.BLACK # Colors we use
WALL_COLOR = (0.6 * 255, 0.9 * 255, 0.9 * 255)
# The shape of the maze. Each character
# represents a different type of object
# % - Wall
# . - Food
# o - Capsule
# G - Ghost
# P - Chomp
# Other characters are ignored
the_layout = [
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%",
"%.....%.................%.....%",
"%o%%%.%.%%%.%%%%%%%.%%%.%.%%%o%",
"%.%.....%......%......%.....%.%",
"%...%%%.%.%%%%.%.%%%%.%.%%%...%",
"%%%.%...%.%.........%.%...%.%%%",
"%...%.%%%.%.%%% %%%.%.%%%.%...%",
"%.%%%.......%GG GG%.......%%%.%",
"%...%.%%%.%.%%%%%%%.%.%%%.%...%",
"%%%.%...%.%.........%.%...%.%%%",
"%...%%%.%.%%%%.%.%%%%.%.%%%...%",
"%.%.....%......%......%.....%.%",
"%o%%%.%.%%%.%%%%%%%.%%%.%.%%%o%",
"%.....%........P........%.....%",
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"]
class Immovable:
def is_a_wall(self):
return False
class Nothing(Immovable):
pass
class Maze:
def __init__(self):
self.have_window = False
self.game_over = False
self.set_layout(the_layout)
set_speed(20)
def set_layout(self, layout):
height = len(layout)
width = len(layout[0])
self.make_window(width, height)
self.make_map(width, height)
max_y = height - 1
for x in range( width ):
for y in range(height):
char = layout[max_y - y][x]
self.make_object((x, y), char)
def make_window(self, width, height):
grid_width = (width -1) * GRID_SIZE
grid_height = (height - 1) * GRID_SIZE
screen_width = 2 * MARGIN + grid_width
screen_height = 2 * MARGIN + grid_height
begin_graphics(screen_width, screen_height,"Chomp",BACKGROUND_COLOR)
def to_screen(self, point):
(x,y) = point
x = x * GRID_SIZE + MARGIN
y = y * GRID_SIZE + MARGIN
return(x,y)
def make_map(self, width, height):
self.width = width
self.height = height
self.map = []
for y in range(width):
new_row = []
for x in range(width):
new_row.append(Nothing())
self.map.append(new_row)
def make_object(self,point,charactor):
(x,y) = point
if charactor == "%":
self.map[y][x] = Wall(self,point)
def finished(self):
return self.game_over
def play(self):
update_when('next_tick')
def done(self):
end_graphics()
self.map = []
def object_at(self,point):
(x,y) = point
if y < 0 or y >= self.height:
return Nothing()
if x < 0 or x >= self.width:
return Nothing()
return self.map[y][x]
class Wall(Immovable):
def __init__(self, maze, point):
self.place = point # Store our position
self.screen_point = maze.to_screen(point)
self.maze = maze # Keep hold of Maze
self.draw()
def draw(self):
(screen_x, screen_y) = self.screen_point
dot_size = GRID_SIZE * 0.2
Circle(self.screen_point, dot_size,
color = WALL_COLOR, filled = 1)
(x, y) = self.place
neighbors = [ (x+1, y), (x-1, y)]
for neighbor in neighbors:
self.check_neighbor(neighbor)
def check_neighbor(self,neighbor):
maze = self.maze
object = maze.object_at(neighbor)
if object.is_a_wall():
here = self.screen_point
there = maze.to_screen(neighbor)
Line(here, there, color = WALL_COLOR,thickness = 2)
def is_a_wall(self):
return True
the_maze = Maze()
while not the_maze.finished():
the_maze.play()
the_maze.done()
I got this error..
Traceback (most recent call last): File "chomp.py", line 110, in
class Wall(Immovable): File "chomp.py", line 124, in Wall
for neighbor in neighbors: NameError: name '
neighbors' is not defined
I spent lot of time still can't find what's wrong, need some help
You never close the function call to Circle() two lines about line 122, that's probably it. You're probably missing an argument based on the trailing comma.
dot_size = GRID_SIZE * 0.2
Circle(self.screen_point, dot_size, # No closing parentheses
(x, y) = self.place
neighbors = [ (x+1, y), (x-1, y)]
for neighbor in neighbors:
self.check_neighbor(neighbor)
Circle(self.screen_point, dot_size,
missing something at the end of that line

Categories