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
Related
i am trying to make planets using pyglet but they end up looking like stars result
here is my code
also i need a way to convert a batch to a sprite (to move it easily)
import pyglet
from pyglet import shapes
import opensimplex
import math
import time
brtd = 0
######## planets###########
class planetobj():
def __init__(self,seed=1234,age=68,position=(0,0),color=(0,1,0),name="planet",description=" 127.0.0.1 , home sweet home never will thy become infected with the virus that has a closedcure"):
self.seed = seed
self.age = age
self.position = position
self.color = color
self.name = name
self.description = description
def gplanet(self,size):
opensimplex.seed(self.seed)
done = 0
xc = 0
c = 0
self.terrain = []
start = opensimplex.noise2(x=0, y=self.age)
while (done == 0 or xc < 50) and not xc > 100 :
xc = xc + 1
c = c + size
value = opensimplex.noise2(x=xc, y=self.age)
self.terrain.append(value * size)
if xc > 50:
if math.floor(value * 100 ) == math.floor(start * 100):
self.done = 1
def mkplanet(self, x,y):
self.batch = pyglet.graphics.Batch()
corner1 = (x,y)
self.trias = []
counter = 0
cornerback = [0,0]
for i in self.terrain:
counter += 1
radi = (360 / len(self.terrain)) * counter
radi2 = (360 / len(self.terrain)) * ((counter + 1 ) % len(self.terrain))
theta = self.terrain[(counter +1 ) % len(self.terrain)]
corner3 = (x + math.sin(radi) * ( i ) ,math.cos(radi) * ( i ) + y )
corner2 = (x + math.sin(radi2) * ( theta ) ,math.cos(radi2) * ( theta ) + y )
self.trias.append(shapes.Triangle( x,y,corner2[0], corner2[1], corner3[0], corner3[1], color=(255, counter % 255, 255), batch=self.batch) )
############ basic game logic & rendering ###########
scr_X = 400
scr_Y = 300
window = pyglet.window.Window(scr_X,scr_Y)
samplebatch = pyglet.graphics.Batch()
earth = planetobj()
earth.gplanet(200)
planets = []
planets.append(earth)
earth.mkplanet( 50 ,50)
#window.event
def on_draw():
window.clear()
earth.batch.draw()
pyglet.app.run()
i tried changing the values that get divided by 'len(self.terrain)'
but i could not find out how to make the planets look round
EDIT
thank you kind commenter (and also the rest of stackoverflow)
now i made a working version feel free to use it
'''
import opensimplex
import math
import pyglet
from pyglet import shapes
pi = 3.1459
debug = 0
class planetobj():
def __init__(self,seed=1234,age=68,position=(0,0),color=(0,1,0),name="planet",description=" 127.0.0.1 , home sweet home never will thy become infected with the virus that has a closedcure"):
self.seed = seed
self.age = age
self.position = position
self.color = color
self.name = name
self.description = description
def gplanet(self,size):
self.batch = pyglet.graphics.Batch()
opensimplex.seed(self.seed)
done = 0
xc = 0
c = 0
self.terrain = []
start = opensimplex.noise2(x=0, y=self.age)
while (done == 0 or xc < 50) and not xc > 100 :
xc = xc + 1
c = c + size
value = opensimplex.noise2(x=xc, y=self.age)
self.terrain.append(value * 10 + size)
if xc > 36:
if math.floor(value * 100 ) == math.floor(start * 100):
self.done = 1
def mkplanet(self, x,y):
global debug
corner1 = (x,y)
self.trias = []
deltatheta = 360 / len(self.terrain)
for counter,i in enumerate(self.terrain):
theta1 = ((deltatheta * counter)/180) * 3.1459
theta2 = (deltatheta * (counter + 2)/180) * 3.1459
radius = self.terrain[counter]
print(str(theta1) + "," + str(theta2))
radius2 = self.terrain[(counter + 1 )% len(self.terrain)]
corner2 = (x + radius2 * math.cos(theta1), y + radius * math.sin(theta1))
corner3 = ( (x + radius2 * math.cos(theta2)), (y + radius2 * math.sin(theta2)))
self.trias.append(shapes.Triangle(x,y,corner2[0], corner2[1], corner3[0], corner3[1], color=(255, counter % 255, 255), batch=self.batch) )
if debug == 1:
self.trias.append(shapes.Circle( corner2[0], corner2[1], 2, color=(255, counter % 255, 40), batch=self.batch) )
self.trias.append(shapes.Circle( corner3[0], corner3[1], 2, color=(255,255, 255), batch=self.batch) )
############ basic game logic & rendering ###########
scr_X = 400
scr_Y = 300
window = pyglet.window.Window(scr_X,scr_Y)
samplebatch = pyglet.graphics.Batch()
earth = planetobj()
earth.gplanet(150)
earth.mkplanet( 250,150)
print(earth.batch)
earth.batch.draw
#window.event
def on_draw():
window.clear()
earth.batch.draw()
print("drawing")
pyglet.app.run()
'''
OK, I've corrected your trigonometry, but there are some other issues. The random values you get back from the noise generator are between -1 and 1. You are then multiplying that by the planet size, which gives you wild variations from wedge to wedge. What you want is to have a basic wedge size, which you use the noise to adjust bit by bit. Here, I'm saying that the noise should be 3% of the wedge size (size/30).
I didn't want to download opensimplex, so I've used a uniform random number generator. I'm also using matplotlib to plot the triangle, but see if this is closer to what you intended.
import math
import random
import numpy as np
import matplotlib.pyplot as plt
class planetobj():
def __init__(self,seed=1234,age=68,position=(0,0),color=(0,1,0),name="planet",description=""):
self.seed = seed
self.age = age
self.position = position
self.color = color
self.name = name
self.description = description
def gplanet(self,size):
done = 0
xc = 0
self.terrain = []
start = random.uniform(-1,1)
while (done == 0 or xc < 50) and not xc > 100 :
xc = xc + 1
value = random.uniform(-1,1)
self.terrain.append(size + value * size / 30)
if xc > 50 and math.floor(value * 100) == math.floor(start * 100):
done = 1
def mkplanet(self, x,y):
corner1 = (x,y)
self.trias = []
deltatheta = 360 / len(self.terrain)
for counter,i in enumerate(self.terrain):
theta1 = deltatheta * counter
theta2 = deltatheta * (counter + 1)
radius = self.terrain[counter]
corner2 = (x + radius * math.cos(theta1), y + radius * math.sin(theta1))
corner3 = (x + radius * math.cos(theta2), y + radius * math.sin(theta2))
# self.trias.append(shapes.Triangle( x, y, corner2[0], corner2[1], corner3[0], corner3[1], color=(255, counter % 255, 255), batch=self.batch) )
self.trias.append(( x, y, corner2[0], corner2[1], corner3[0], corner3[1], (1.0,(counter%255)/255,1.0) ))
earth = planetobj()
earth.gplanet(200)
earth.mkplanet(50 ,50)
print(earth.trias)
plt.figure()
plt.scatter( [48,48,52,52],[-50,50,-50,50] )
for t in earth.trias:
tri = np.array(t[:6]).reshape(3,2)
plt.gca().add_patch(plt.Polygon( tri, color=t[6] ))
plt.show()
Output:
I want to visualize an algorithm (Graham scan) in python with tkinter.
I want to animate the algorithm and I am stuck.
I basically want to draw and delete lines but I don't understand canvas.after() well enough to make it work.
draw_line() returns the line object but when I call it in canvas.after(..., draw_line, ...) I don't see a way to get the return value or how to call another canvas.after() to change the color/delete that line if the function draw_line() hasn't been called yet because of the delay.
Thanks in advance.
from tkinter import *
import math
import random
class Point:
def __init__(self, _x, _y, _a=0):
self.x = _x
self.y = _y
self.angle = _a
def get_co(self):
return self.x, self.y
def draw_hull(hull):
for i in range(len(hull) - 1):
canvas.create_line(hull[i][0], hull[i][1], hull[i + 1][0], hull[i + 1][1], fill="red", width=2)
def draw_line(p1, p2, color="yellow"):
return canvas.create_line(p1.x, p1.y, p2.x, p2.y, fill=color, width=2)
def convex_hull(list_points):
# find bottom point
bottom_point = Point(math.inf, math.inf)
for point in list_points:
if point[1] < bottom_point.y:
bottom_point = Point(point[0], point[1])
# calculate angles between the bottom point and the other points
points = []
for point in list_points:
if point != bottom_point.get_co():
new_point = Point(point[0], point[1])
angle = calculate_angle(bottom_point, new_point)
new_point.angle = angle
points.append(new_point)
# sort the points by angle
swaps = None
while swaps != 0:
swaps = 0
for i in range(len(points) - 1):
point1 = points[i]
point2 = points[i + 1]
if point1.angle > point2.angle:
points[i], points[i + 1] = points[i + 1], points[i]
swaps += 1
# go through the points and add them to the convex hull
# if the angle between 3 points ever exeeds 180 degrees, discard the middle point
hull = [bottom_point, points[0]]
i = 1
while i < len(points):
####### DRAW LINE #######
canvas.after(i*500, draw_line, hull[-2], hull[-1])
##############
# check angle
angle = calculate_angle(hull[-2], hull[-1], points[i])
if angle == -1:
########## DELETE LINE ##########
# change color of line to red and delete it a bit later
# canvas.itemconfig(line, fill="red")
# canvas.after(i*500+250, canvas.delete, line)
####################
# pop the point of the stack
hull.pop()
else:
########## CHANGE COLOR OF LINE ##########
# change color of line to green
# canvas.itemconfig(line, fill="green")
####################
# move to the next point
hull.append(points[i])
i += 1
# add bottom point again for loop
hull.append(bottom_point)
# give easy return list (with coordinate-tupels not class objects)
output = []
for point in hull:
output.append(point.get_co())
return output
def calculate_angle(point1, point2, point3=None):
if point3 is None:
if point2.x - point1.x == 0:
return 90
elif point2.x - point1.x > 0:
return math.degrees(math.atan((point2.y - point1.y)/(point2.x - point1.x)))
else:
return 180 - math.degrees(math.atan((point2.y - point1.y)/(point1.x - point2.x)))
else:
v1 = Point(point1.x - point2.x, point1.y - point2.y)
v2 = Point(point3.x - point2.x, point3.y - point2.y)
det = (v1.x * v2.y) - (v2.x * v1.y)
if det < 0:
return 1
else:
return -1
window = Tk()
window.geometry("1000x600")
canvas = Canvas(window, width=1000, height=600)
canvas.pack()
POINTSIZE = 2
points = []
for i in range(100):
x = random.randint(50, 950)
y = random.randint(50, 550)
points.append((x, y))
canvas.create_oval(x - POINTSIZE, y - POINTSIZE, x + POINTSIZE, y + POINTSIZE, fill="black")
hull = convex_hull(points)
# draw_hull(hull)
window.mainloop()
If you have questions about the code, let me know. Because I dont know where to start to explain, since I made major changes to your code.
Anyway, I would be glad if you share your code again, once you are done with, on CodeReview and please do let me know. Because it was fun to work with and your code seems incomplete to me.
Happy Coding:
import tkinter as tk
import random
import math
class Point:
def __init__(self, _x, _y, _a=0):
self.x = _x
self.y = _y
self.angle = _a
return None
def get_co(self):
return self.x, self.y
class Window(tk.Tk):
def __init__(self,_w,_h):
super().__init__()
self.POINTSIZE = 2
self.points = []
self.swaps = None
self.count = 1
self.delay = 200
self.title('Graham scan simulation')
self.toolbar = tk.Frame(self,background='grey')
self.refresh_button = tk.Button(self.toolbar,text='Refresh',
command=self.refresh)
self.start_button = tk.Button(self.toolbar,text='Start',
command = self.convex_hull)
self.canvas = tk.Canvas(self,width=_w,height=_h)
self.toolbar.pack(side=tk.TOP,fill=tk.BOTH,expand=True)
self.refresh_button.pack(side=tk.LEFT)
self.start_button.pack(side=tk.LEFT)
self.canvas.pack(side=tk.BOTTOM,fill=tk.BOTH,expand=True)
def generate_points(self):
for point_instance in self.points:
yield point_instance
def find_bottom_point(self):
bottom_point = Point(math.inf,math.inf)
for point in self.generate_points():
if point.y < bottom_point.y:
bottom_point = point
return bottom_point
def calculate_angle(self,point1, point2):
if point2.x - point1.x == 0:
return 90
elif point2.x - point1.x > 0:
return math.degrees(math.atan((point2.y - point1.y)/(point2.x - point1.x)))
else:
return 180 - math.degrees(math.atan((point2.y - point1.y)/(point1.x - point2.x)))
def calculate_angels_by_bottom_point(self,bottom_point):
for point in self.generate_points():
if point != bottom_point:
angle = self.calculate_angle(bottom_point,point)
point.angle = angle
def sort_points(self,event_variable):
if self.swaps != 0:
self.swaps = 0
for i in range(len(self.points)-1):
point1 = self.points[i]
point2 = self.points[i + 1]
if point1.angle > point2.angle:
self.points[i], self.points[i + 1] = self.points[i + 1], self.points[i]
self.swaps += 1
if self.swaps == 0:
event_variable.set(1)
self.after(20,self.sort_points,event_variable)
def check_angle(self,point1,point2,point3):
v1 = Point(point1.x - point2.x, point1.y - point2.y)
v2 = Point(point3.x - point2.x, point3.y - point2.y)
det = (v1.x * v2.y) - (v2.x * v1.y)
if det < 0:
return 1
else:
return -1
def draw_line(self,p1,p2,color='yellow'):
return self.canvas.create_line(p1.x,p1.y, p2.x,p2.y, fill='yellow',tags='line')
def clear_red_lines(self,p1,p2):
shapes = self.canvas.find_withtag('line')
for shape in shapes:
if self.canvas.itemcget(shape,'fill') == 'red':
coords = self.canvas.coords(shape)
overlapped = self.canvas.find_overlapping(*coords)
for i in overlapped:
coords2 = self.canvas.coords(i)
if coords == coords2:
self.canvas.delete(i)
self.canvas.delete(shape)
def animated_draw(self,hull):
if self.count != len(self.points):
line = self.draw_line(hull[-2],hull[-1])
check_mark = self.check_angle(hull[-2],hull[-1],self.points[self.count])
if check_mark == -1:
self.canvas.itemconfig(line,fill='red')
self.after(self.delay-100,lambda:self.clear_red_lines(hull[-2],hull[-1]))
hull.pop()
else:
self.canvas.itemconfig(line,fill='green')
hull.append(self.points[self.count])
self.count += 1
self.after(self.delay,self.animated_draw,hull)
def convex_hull(self):
bottom_point = self.find_bottom_point()
self.calculate_angels_by_bottom_point(bottom_point)
event_variable = tk.IntVar(self,value=0)
self.sort_points(event_variable)
self.wait_variable(event_variable)
self.points.pop(0)
self.animated_draw(hull = [bottom_point, self.points[0]])
def generate_listpoints(self,_amount):
'''using a generator for memory purpose'''
for i in range(_amount):
x = random.randint(50, 950)
y = random.randint(50, 550)
yield x,y
def refresh(self):
self.swaps = None
self.count = 1
self.points= []
self.populate_canvas()
def populate_canvas(self):
self.canvas.delete('all')
for x,y in self.generate_listpoints(100):
self.points.append(Point(x, y))#instead of creating throwing instances away.
self.canvas.create_oval(x - self.POINTSIZE,
y - self.POINTSIZE,
x + self.POINTSIZE,
y + self.POINTSIZE,
fill="black")
root = Window(1000,600)
root.mainloop()
So I created this parabola class which can be instantiated with 3 parameters (a, b and c) or with 3 points belonging to the parabola. The punti() function returns all the points belonging to the parabola in a range defined by n and m. Here's the code (Most of this is in Italian, sorry):
class Parabola:
def __init__(self, tipo=0, *params):
'''
Il tipo è 0 per costruire la parabola con a, b, c; 1 per costruire la parabola con
tre punti per la quale passa
'''
if tipo == 0:
self.__a = params[0]
self.__b = params[1]
self.__c = params[2]
self.__delta = self.__b ** 2 - (4 * self.__a * self.__c)
elif tipo == 1:
matrix_a = np.array([
[params[0][0]**2, params[0][0], 1],
[params[1][0]**2, params[1][0], 1],
[params[2][0]**2, params[2][0], 1]
])
matrix_b = np.array([params[0][1], params[1][1], params[2][1]])
matrix_c = np.linalg.solve(matrix_a, matrix_b)
self.__a = round(matrix_c[0], 2)
self.__b = round(matrix_c[1], 2)
self.__c = round(matrix_c[2], 2)
self.__delta = self.__b ** 2 - (4 * self.__a * self.__c)
def trovaY(self, x):
y = self.__a * x ** 2 + self.__b * x + self.__c
return y
def punti(self, n, m, step=1):
output = []
for x in range(int(min(n, m)), int(max(n, m)) + 1, step):
output.append((x, self.trovaY(x)))
return output
Now my little game is about shooting targets with a bow and i have to use the parabola for the trajectory and it passes by 3 points:
The player center
A point with the cursor's x and player's y
A point in the middle with the cursors's y
The trajectory is represented by a black line but it clearly doesn't work and I can't understand why. Here's the code of the game (Don't mind about the bow's rotation, I still have to make it function properly):
import os
import sys
import pygame
from random import randint
sys.path.insert(
1, __file__.replace("pygame-prototype\\" + os.path.basename(__file__), "coniche\\")
)
import parabola
# Initialization
pygame.init()
WIDTH, HEIGHT = 1024, 576
screen = pygame.display.set_mode((WIDTH, HEIGHT))
# Function to rotate without losing quality
def rot_from_zero(surface, angle):
rotated_surface = pygame.transform.rotozoom(surface, angle, 1)
rotated_rect = rotated_surface.get_rect()
return rotated_surface, rotated_rect
# Function to map a range of values to another
def map_range(value, leftMin, leftMax, rightMin, rightMax):
# Figure out how 'wide' each range is
leftSpan = leftMax - leftMin
rightSpan = rightMax - rightMin
# Convert the left range into a 0-1 range (float)
valueScaled = float(value - leftMin) / float(leftSpan)
# Convert the 0-1 range into a value in the right range.
return rightMin + (valueScaled * rightSpan)
# Player class
class Player:
def __init__(self, x, y, width=64, height=64):
self.rect = pygame.Rect(x, y, width, height)
self.dirx = 0
self.diry = 0
def draw(self):
rectangle = pygame.draw.rect(screen, (255, 0, 0), self.rect)
# Target class
class Target:
def __init__(self, x, y, acceleration=0.25):
self.x, self.y = x, y
self.image = pygame.image.load(
__file__.replace(os.path.basename(__file__), "target.png")
)
self.speed = 0
self.acceleration = acceleration
def draw(self):
screen.blit(self.image, (self.x, self.y))
def update(self):
self.speed -= self.acceleration
self.x += int(self.speed)
if self.speed < -1:
self.speed = 0
player = Player(64, HEIGHT - 128)
# Targets init
targets = []
targets_spawn_time = 3000
previous_ticks = pygame.time.get_ticks()
# Ground animation init
ground_frames = []
for i in os.listdir(__file__.replace(os.path.basename(__file__), "ground_frames")):
ground_frames.append(
pygame.image.load(
__file__.replace(os.path.basename(__file__), "ground_frames\\" + i)
)
) # Load all ground frames
ground_frame_counter = 0 # Keep track of the current ground frame
frame_counter = 0
# Bow
bow = pygame.image.load(__file__.replace(os.path.basename(__file__), "bow.png"))
angle = 0
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# Spawning the targets
current_ticks = pygame.time.get_ticks()
if current_ticks - previous_ticks >= targets_spawn_time:
targets.append(Target(WIDTH, randint(0, HEIGHT - 110)))
previous_ticks = current_ticks
screen.fill((101, 203, 214))
player.draw()
for i, e in list(enumerate(targets))[::-1]:
e.draw()
e.update()
if e.x <= -e.image.get_rect().width:
del targets[i]
# Calculating the angle of the bow
mouse_pos = pygame.Vector2(pygame.mouse.get_pos())
angle = map_range(mouse_pos.x, 0, WIDTH, 90, 0)
# Rotate the bow
rotated_bow, rotated_bow_rect = rot_from_zero(bow, angle)
rotated_bow_rect.center = player.rect.center
screen.blit(rotated_bow, rotated_bow_rect)
# Animate the ground
if frame_counter % 24 == 0:
ground_frame_counter += 1
if ground_frame_counter >= len(ground_frames):
ground_frame_counter = 0
for i in range(round(WIDTH / ground_frames[ground_frame_counter].get_rect().width)):
screen.blit(
ground_frames[ground_frame_counter],
(
ground_frames[ground_frame_counter].get_rect().width * i,
HEIGHT - ground_frames[ground_frame_counter].get_rect().height,
),
)
# Calculating the trajectory
mouse_pos.x = (
mouse_pos.x if mouse_pos.x != rotated_bow_rect.centerx else mouse_pos.x + 1
)
# print(mouse_pos, rotated_bow_rect.center)
v_x = rotated_bow_rect.centerx + ((mouse_pos.x - rotated_bow_rect.centerx) / 2)
trajectory_parabola = parabola.Parabola(
1,
rotated_bow_rect.center,
(mouse_pos.x, rotated_bow_rect.centery),
(v_x, mouse_pos.y),
)
trajectory = [(i[0], int(i[1])) for i in trajectory_parabola.punti(0, WIDTH)]
pygame.draw.lines(screen, (0, 0, 0), False, trajectory)
pygame.draw.ellipse(
screen, (128, 128, 128), pygame.Rect(v_x - 15, mouse_pos.y - 15, 30, 30)
)
pygame.draw.ellipse(
screen,
(128, 128, 128),
pygame.Rect(mouse_pos.x - 15, rotated_bow_rect.centery - 15, 30, 30),
)
pygame.display.update()
if frame_counter == 120:
for i in trajectory:
print(i)
frame_counter += 1
You can run all of this and understand what's wrong with it, help?
You round the values of a, b and c to 2 decimal places. This is too inaccurate for this application:
self.__a = round(matrix_c[0], 2)
self.__b = round(matrix_c[1], 2)
self.__c = round(matrix_c[2], 2)
self.__a = matrix_c[0]
self.__b = matrix_c[1]
self.__c = matrix_c[2]
Similar to answer above... rounding is the issue here. This is magnified when the scale of the coordinates gets bigger.
However, disagree with other solution: It does not matter what order you pass the coordinates into your parabola construction. Any order works fine. points are points.
Here is a pic of your original parabola function "drooping" because of rounding error:
p1 = (0, 10) # left
p2 = (100, 10) # right
p3 = (50, 100) # apex
p = Parabola(1, p3, p2, p1)
traj = p.punti(0, 100)
xs, ys = zip(*traj)
plt.scatter(xs, ys)
plt.plot([0, 100], [10, 10], color='r')
plt.show()
I made a deep learning number guesser with python(in jupyter notebookand I used ten)when I run the code it should open a empty window(with pygame) that I can draw numbers to train the deep learning but I get tow AttributeErrors this is my code:
import tensorflow as tf
import pygame
import matplotlib.pyplot as plt
import numpy as np
from tkinter import *
from tkinter import messagebox
class pixel(object):
def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height
self.color = (255,2555,255)
self.neighbors = []
def draw(self, surface):
pygame.draw.rect(surface, self.color, (self.x, self.y, self.x + self.width, self.y + self.height))
def getNeighbors(self, g):
j = self.x // 20
i = self.y // 20
rows = 28
cols = 28
if i < cols -1:
self.neighbors.append(g.pixels[i + 1][j])
if i > 0:
self.neighbors.append(g.pixels[i - 1][j])
if j < rows -1:
self.neighbors.append(g.pixels[i][j + 1])
if j > 0:
self.neighbors.append(g.pixels[i - 1][j + 1])
if j > 0 and i > 0:
self.neighbors.append(g.pixels[i - 1][j - 1])
if j + 1 < rows and i > -1 and i - 1 > 0:
self.neighbors.append(g.pixels[i - 1][j + 1])
if j - 1 < rows and i < cols - 1 and j - 1 > 0:
self.neighbors.append(g.pixels[i + 1][j - 1])
if j < rows - 1 and i < cols - 1:
self.neighbors.append(g.pixels[i + 1][j + 1])
class grid(object):
pixels = []
def __init__(self, row, col, width, height):
self.rows = row
self.cols = col
self.len = row * col
self.width = width
self.height = height
self.generatePixels
pass
def draw(self, surface):
for row in self.pixels:
for col in row:
col.draw(surface)
def generatePixels(self):
x_gap = self.width // self.cols
y_gap = self.height // self.rows
self.pixels = []
for r in range(self.rows):
self.pixels.append([])
for c in range(self.cols):
self.pixels[r].append(pixel(x_gap * c, y_gap * r, y_gap * r, x_gap, y_gap))
for r in range(self.rows):
for c in range(self.cols):
self.pixels[r][c].getNeighbors(self)
def clicked(self, pos):
try:
t = pos[0]
w = pos[1]
g1 = int(t) // self.pixels[0][0].width
g1 = int(t) // self.pixels[0][0].width
g2 = int(w) // self.pixels[0][0].height
return self.pixels[g2][g1]
except:
pass
def convert_binary(self):
li = self.pixels
newMatrix = [[] for x in range(len(li))]
for i in range(len(li)):
for j in range(len(li[i])):
if li[i][j].color == (255,225,255):
newMatrix[i].append(0)
else:
newMatrix[i].append(1)
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_test = tf.keras.utils.normalize(x_test, axis=1)
for row in range(28):
for x in range(28):
x_test[0][row][x] = newMatrix[row][x]
return x_test[:1]
def guess(li):
model = tf.keras.models.load_model('m.model')
predictions = model.predict(li)
print(predictions[0])
t = (np.argmax(predictions[0]))
print("I predict this number is a:", t)
window = Tk()
window = withdraw()
messagebox.showinfow("prediction", "I predict this number is a:" + str(t))
#plt.imshow(li[0], cmap=plt.cm.binary)
#pit.show()
def main():
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
li = g.convert_binary()
guess(li)
g.generatePixels()
if pygame.mouse.get_pressed()[0]:
pos = pygame.mouse.get_pos()
clicked = g.clicked(pos)
clicked.color = (0,0,0)
for n in clicked.neighbors:
n.color = (0,0,0)
if pygame.mouse.get_pressed()[2]:
try:
pos = pygame.mouse.get_pos()
clicked = g.clicked(pos)
clicked.color = (255,255,255)
except:
pass
g.draw(win)
pygame.display.update()
pygame.init()
width = height = 560
win = pygame.display.set_mode((width, height))
pygame.display.set_caption("Number Guesser")
g = grid(28, 28, width, height)
main()
this is the output:
pygame 2.0.1 (SDL 2.0.14, Python 3.8.8)
Hello from the pygame community. https://www.pygame.org/contribute.html
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-1-a4fa9a8a2b5c> in <module>
149 pygame.display.set_caption("Number Guesser")
150 g = grid(28, 28, width, height)
--> 151 main()
<ipython-input-1-a4fa9a8a2b5c> in main()
129 pos = pygame.mouse.get_pos()
130 clicked = g.clicked(pos)
--> 131 clicked.color = (0,0,0)
132 for n in clicked.neighbors:
133 n.color = (0,0,0)
AttributeError: 'NoneType' object has no attribute 'color'
g.clicked() is clearly returning None for you to get a NoneType object error when accessing the return value.
If we look at the clicked() method, we can see there's a try: ... except: pass construct. It means that any and all errors that might happen are just thrown out of the window, and since a function that doesn't explicitly return returns None, we can assume that's what happening.
Takeaway 1: Never, ever use try: except: like that. Just let the exception happen and handle it elsewhere.
Reasons why there might be some exception we don't know about in that function could be e.g.
an IndexError when unpacking the argument
an IndexError accessing self.pixels
a ZeroDivisionError
a NameError or an AttributeError if we've typoed something
anything else too, heck if we know
For the time being, let's look at what initializes self.pixels... Looks like generatePixels is the thing.
What calls generatePixels? Well... nothing, since the "call" to it in grid's __init__ is missing the call parentheses: self.generatePixels should be self.generatePixels().
Takeaway 2: Use an IDE or linter that warns you about stuff like that.
So, tracing that back:
self.pixels never gets initialized because generatePixels is not called.
An exception accessing self.pixels is swallowed by the bare except:.
You get a None from the clicked() function.
You try accessing the None and you get the exception.
While there are other clear issues in the code, you might want to start by
fixing the call to generatePixels()
unwrapping try: except:s
How can I see if an x and y are on the edge or inside of the rectangle? Does anyone have any ideas of how to go about that?
I have tried to create a method that will do this called contains point but I am sure I have done this incorrectly
my code:
class Rectangle: # creates class Rectangle
def __init__(self, rX, rY, rW, rH): # initialized so we can call our variables
self.x = rX # x coord
self.y = rY # y coord
self.w = rW # width
self.h = rH # heigh
def __str__(self): # will return string
return 'Rectangle(' + str(self.x) + ',' + str(self.y) + ',' + str(self.w) + ',' + str(self.h)+')'
def right(self): # will check right edge
return self.x + self.w # returns right edge
def bottom(self):
return self.y + self.h
def size(self): # Method Size will obtain size of rectangle
return self.w, self.h
def position(self): # Method will show coords
return self.x, self.y
def area(self): # method will return area of rectangle
return self.w * self.h
def expand(self, offset): # expand will take in an offset value and apply it to a new rectangle
newX = self.x - offset
newY = self.y - offset
newW = self.w + (offset * 2)
newH = self.h + (offset * 2)
newRectangle = Rectangle(newX, newY, newW, newH)
return newRectangle
def contains_point(self, x, y): # contains point will take in 2 coords
# and check to see if they are in the rectangle
if x <= self.x and y <= self.y:
return True
else:
return False
r = Rectangle(30, 40, 100, 110)
print(r.expand(-5), r)
print(r.contains_point(0, 0))
If you have x1, x2 and y1, y2 defining the outer corners of your rectangle, then you can test a point.x, point.y by checking if point.x is between x1 and x2, and point.y is between y1 and y2.
def contains_point(self, x, y): # contains point will take in 2 coords
# and check to see if they are in the rectangle
if (self.x <= x <= self.right() and
self.y <= y <= self.bottom()):
return True
else:
return False