How to acces my variable outside of my class? - python

I'm just starting to learn how to code, and I'm facing an issue. This is the first time I'm dealing with classes, and I have a simple program to make, but even though it is simple I'm have trouble making it work.
It is not finished, nor cleaned up so It'll look messy, but I need someone's help to move ahead.
In my code, I'm try to run a loop to creates instances of an object, and the number of instances is defined by the user in my Sousfenetre() class.
Inside that class, I have methods, including one which sets the variable 'nbrboules'
I'm trying to access its values at the end of my code, but can't seem to figure out how to.
(And if someone could explain why "nbr" Stringvar() isn't showing in "saisie" Entry widget, and why self.nbr.get() returns the wrong value, that would be nice as well :)
from tkinter import *
import random
fenetre = Tk()
fenetre.title("Boules")
fenetre.geometry("600x600")
Tx,Ty = 600,600
canvas = Canvas(fenetre,height=600,width=600,bg="yellow")
canvas.pack()
class Sousfenetre(Tk):
def __init__(self):
global label
Tk.__init__(self)
self.nbr = StringVar()
self.nbr.set("Entrez un nombre entier")
self.saisie = Entry(self, textvariable=self.nbr, width=200)
self.saisie.grid(row=0)
self.bouton = Button(self, text="VALIDER", font=(None, 30), command=self.valider)
self.bouton.grid(row=1)
self.label = Label(self, text="")
self.label.grid(row=2)
def valider(self):
global nbrboules,label
try:
nbrboules = int(self.saisie.get())
# POURQUOI SELF.NBR.GET() RENVOIE LA MAUVAISE VALEUR PUTAIN
self.destroy()
except ValueError:
self.label.config(text="Entrez un nombre entier !")
def access(self):
return self.nbrboules
class Boule():
def __init__(self):
self.x=random.randint(10,590)
self.y = random.randint(10, 590)
self.dx = random.randint(20,40)
self.dy = random.randint(20, 40)
self.r = random.randint(2,10)
def inversedx(self):
self.dx = -self.dx
def inversedy(self):
self.dy = -self.dy
def deplacementx(self):
self.x += self.dx
def deplacementy(self):
self.y += self.y
def setdx(self,param):
self.x = param
def setdy(self,param):
self.y = param
def collisionBords(self,Tx,Ty):
if self.x + self.dx > Tx - self.r or self.x + self.dx < 0 + self.r :
return self.x
if self.y + self.dy > Ty - self.r or self.y + self.dy < 0 + self.r :
return self.y
# def collisionBoule(self,boule):
# if abs(self.x - boule.x) and abs(self.y - boule.y) < self.r + boule.r:
Sousfenetre()
listeboule = []
Cercles = []
couleur = ["blue","red","green"]
listeboule.append(Boule())
listeboule.append(Boule())
listeboule.append(Boule())
listeboule.append(Boule())
listeboule.append(Boule())
listeboule.append(Boule())
listeboule.append(Boule())
listeboule.append(Boule())
listeboule.append(Boule())
listeboule.append(Boule())
listeboule.append(Boule())
listeboule.append(Boule())
#I know this isn't efficient, it was for testing purposes
f = Sousfenetre()
for i in range(0,f.access()):
Cercles.append(canvas.create_oval(listeboule[i].x-listeboule[i].r,listeboule[i].y-listeboule[i].r,listeboule[i].x+listeboule[i].r,listeboule[i].y+listeboule[i].r,fill=random.choice(couleur)))
print(listeboule)
def test():
print(nbrboules)
fenetre.mainloop()

This code works for me.
It uses Toplevel to creates Sousfenetre so Entry displays text from self.nbr.
Because mainloop starts program so everything before mainloop is executed before you press button. I sends listeboule, cercles to Sousfenetre as parameters and it can use them in valider when you press button.
I also used fenetre.after(100, f.lift) to move Sousfenetre to the front 100ms after creating main window so it is not hidden behind main window.
import tkinter as tk # `import *` is not preferred
import random
# --- classes ---
class Sousfenetre(tk.Toplevel):
def __init__(self, listeboule, cercles):
super().__init__() # in Python 3 you can use `super()` instead of class name
# remeber as class variable to have access in other methods
self.listeboule = listeboule
self.cercles = cercles
self.nbr = tk.StringVar()
self.nbr.set("Entrez un nombre entier")
self.saisie = tk.Entry(self, textvariable=self.nbr)
self.saisie.grid(row=0)
self.bouton = tk.Button(self, text="VALIDER", command=self.valider)
self.bouton.grid(row=1)
self.label = tk.Label(self, text="")
self.label.grid(row=2)
def valider(self):
try:
nbrboules = int(self.saisie.get())
# uses
for i in range(nbrboules):
b = self.listeboule[i]
c = random.choice(couleur)
self.cercles.append(canvas.create_oval(b.x-b.r, b.y-b.r, b.x+b.r, b.y+b.r, fill=c))
self.destroy()
except ValueError:
self.label.config(text="Entrez un nombre entier !")
class Boule():
def __init__(self):
self.x = random.randint(10,590)
self.y = random.randint(10, 590)
self.dx = random.randint(20,40)
self.dy = random.randint(20, 40)
self.r = random.randint(2,10)
def inversedx(self):
self.dx = -self.dx
def inversedy(self):
self.dy = -self.dy
def deplacementx(self):
self.x += self.dx
def deplacementy(self):
self.y += self.y
def setdx(self,param):
self.x = param
def setdy(self,param):
self.y = param
def collisionBords(self,Tx,Ty):
if self.x + self.dx > Tx - self.r or self.x + self.dx < 0 + self.r :
return self.x
if self.y + self.dy > Ty - self.r or self.y + self.dy < 0 + self.r :
return self.y
# --- functions ---
# empty
# --- main ---
#listeboule = []
#for _ in range(12):
# listeboule.append(Boule())
listeboule = [Boule() for _ in range(12)] # create 12 circles
cercles = []
couleur = ["blue", "red", "green"]
Tx = 600
Ty = 600
# ---
fenetre = tk.Tk()
fenetre.title("Boules")
fenetre.geometry("600x600")
canvas = tk.Canvas(fenetre, height=600, width=600, bg="yellow")
canvas.pack()
# send `listeboule`, `cercles` to class
f = Sousfenetre(listeboule, cercles)
# Move `Sousfenetre` to the front 100ms after creating main window.
# This way Sousfenetre is not hidden behind main window.
fenetre.after(100, f.lift)
# start program
fenetre.mainloop()

Related

Python - Tkinter event_generate not detected by bind

I have two classes (one called 'Point' one called 'PointConector'), both of which inherits 'Frame' (Im not sure If I need to but was seeing if it helped)
When I move the Point (mouse Enter/Leave) and drag the point around, I want to fire off an event for 'PointConnector' (which is a line thats joins the twp points) to pick up the event and redraw the line with the new position of the point.
If I use the event_generate from the canvas object and bind also from the canvas object then the event is picked up, but the object that is passed is the canvas object, not the Point object.
If I fire the event_generate from the Point object (which is inherited from Frame) then the event is ignored
I need the bind event to have the Widget field set to the 'Point' that generated the event. ie I need to have a handle to the point that fired the event. So the Field 'Widget' in the event should be the Point object that is being handled, not the canvas.
from tkinter import Tk, Canvas,Frame
class pointConnector(Frame):
point1 = None
point2 = None
connector = None
def __init__(self,canvas, point1,point2):
super(pointConnector,self).__init__(canvas)
self.point1 = point1
self.point2 = point2
self.canvas = canvas
p1 = self.canvas.translatePoint((self.point1.x,self.point1.y))
p2 = self.canvas.translatePoint((self.point2.x,self.point2.y))
self.connector = canvas.create_line(p1[0], p1[1], p2[0], p2[1],fill='red',state="hidden", width =2)
self.canvas.bind("<<foo>>",self.dummy)
def dummy(self,event):
print("Virtual Event Data: {}".format(event))
def show(self):
self.canvas.itemconfig(self.connector,state="normal")
class screen(Canvas):
width =0
height=0
cY = 0
cX = 0
items =[]
dragItem = None
mouseOverItem = None
def setScreenSize(self,width,height):
self.height = height
self.width = width
self.cX = int(width/2)
self.cY = int(height/2)
def __init__(self,root, unit,width,height):
super(screen,self).__init__(root,width=width,height=height)
self.root = root
self.width = width
self.height = height
self.setScreenSize(width,height)
self.tag_bind('DRAG_OBJECT','<ButtonPress-1>',self.onStartDrag)
self.tag_bind('DRAG_OBJECT','<ButtonRelease-1>',self.onEndDrag)
self.tag_bind('DRAG_OBJECT','<B1-Motion>',self.onDrag)
self.bind("<Configure>", self.configure)
def addObject(self,object):
self.items.append(object)
def findObject(self,tags):
for item in self.items:
if str(item.id) in tags:
return item
return None
def onStartDrag(self,event):
self.dragItem= self.find_closest(event.x,event.y)
wt = self.gettags(self.dragItem)
self.dragItem = self.findObject(wt)
def onEndDrag(self,event):
self.dragItem = None
def onDrag(self,event):
self.dragItem.move(event.x,event.y)
def draw(self):
# Draw array of items
for o in self.items:
o.show()
def translateX(self,x):
return (x + self.cX)
def translateY(self,y):
return (y + self.cY)
def translatePoint(self,pointxy):
return (self.translateX(pointxy[0]),self.translateY(pointxy[1]))
class point(Frame):
state = "normal"
x : int
y : int
def setPoint(self,x,y):
self.x = x
self.y = y
def __init__(self,canvas,x,y,radius,ObjectName):
super(point,self).__init__(canvas)
self.x = x
self.y = y
self.radius = radius
self.canvas = canvas
self.ObjectName= ObjectName
self.id = None
self.create_point()
def create_point(self):
x = self.canvas.translateX(self.x)
y = self.canvas.translateY(self.y)
self.circle = self.canvas.create_oval(x-self.radius,y-self.radius,x+self.radius,y+self.radius,state=self.state,fill='yellow')
self.text = self.canvas.create_text(x,y,text=self.ObjectName,state=self.state )
self.canvas.itemconfig(self.circle, tags=({"type":"POINT", "name":self.ObjectName},"DRAG_OBJECT"))
self.canvas.itemconfig(self.text, tags=({"type":"POINT", "name":self.ObjectName},"DRAG_OBJECT"))
self.id = {"type":"POINT", "name":self.ObjectName}
def show(self):
newX = self.canvas.translateX(self.x)
newY = self.canvas.translateY(self.y)
self.canvas.itemconfig(self.circle,state='normal')
self.canvas.coords(self.circle,(newX-self.radius,newY-self.radius,newX + self.radius, newY + self.radius))
self.canvas.coords(self.text,(newX,newY))
self.canvas.itemconfig(self.text,state='normal')
self.canvas.tag_raise(self.circle)
self.canvas.tag_raise(self.text)
def hide(self):
self.canvas.itemconfig(self.circle,state='hidden')
self.canvas.itemconfig(self.text,state='hidden')
def move (self,x,y):
delta_x = x- (self.x + self.canvas.cX)
delta_y = y- (self.y + self.canvas.cY)
self.canvas.move(self.circle,delta_x,delta_y)
self.canvas.move(self.text,delta_x,delta_y)
self.x = x - self.canvas.cX
self.y = y - self.canvas.cY
## If I use the canvas object (that is passed in) then the Point object picks up the event, but then I cant tell which 'Point' is begin dragged
#self.canvas.event_generate("<<foo>>",x=self.x,y=self.y,when='now')
## If I generate the event from the Point Object then the Event is lost
self.event_generate("<<foo>>",x=self.x,y=self.y,when='tail')
self.update()
# Start of program
print("Start --->")
tk = Tk()
mainScreen = screen(tk,20,700,700)
mainScreen.pack(fill="both",expand=1)
# Add Point A
pointA = point(mainScreen,0,0,10,"A",)
mainScreen.addObject(pointA)
# Add Point B
pointB = point(mainScreen,20,20,10,"B")
mainScreen.addObject(pointB)
LineA = pointConnector(mainScreen,pointA,pointB)
mainScreen.addObject(LineA)
mainScreen.draw()
tk.mainloop()

Tkinter canvas doesn't show my "player" symbol

I am beginner in Python and want just to make a red square that will move by pressed keys on keyboard. But after I had run this, only green canvas showed up, no red square. Here is the code:
Imports:
try:
import Tkinter
except:
import tkinter as Tkinter
import time
Here just some constants
__author__ = "Brano"
print(__author__)
GAME_WIDTH = 800
GAME_HEIGHT = 600
GAME_BG = 'green'
MOVE_SPEED = 10
Main class with initialization:
class Game(Tkinter.Tk):
def __init__(self, *args, **kwargs):
Tkinter.Tk.__init__(self, *args, **kwargs)
# Trigger Of Other Functions
self.x = GAME_WIDTH/2
self.y = GAME_HEIGHT/2
self.create_board()
self.create_men()
self.bind('<Any-KeyPress>',self.move)
Creating board:
def create_board(self):
self.board = Tkinter.Canvas(width=GAME_WIDTH, height=GAME_HEIGHT,
bg=GAME_BG)
self.board.pack(padx=10, pady=10)
return
Creating red square:
def create_men(self):
self.men = self.board.create_rectangle(300, 300, 310, 310, fill='red')
return
Move square after pressing keys:
def move(self, event=None):
key = event.keysym
if key=='Left':
self.x = MOVE_SPEED
elif key=='Right':
self.x = -MOVE_SPEED
elif key=='Up':
self.y = MOVE_SPEED
elif key=='Down':
self.y = -MOVE_SPEED
else:
pass
return
Just tkinter updates:
def TkUpdate(self):
self.update()
self.update_idletasks()
return
My main move update:
def GameUpdate(self):
self.board.move(self.men, self.x, self.y)
return
Checking if it is imported:
if __name__ == '__main__':
root=Game(className=" Snake Game ")
while True:
root.TkUpdate()
root.GameUpdate()
time.sleep(0.09)
else :
print("U cannot import me !")
Here is the canvas I have
Here is the whole class:
class Game(Tkinter.Tk):
def __init__(self, *args, **kwargs):
Tkinter.Tk.__init__(self, *args, **kwargs)
# Trigger Of Other Functions
self.x = GAME_WIDTH/2
self.y = GAME_HEIGHT/2
self.create_board()
self.create_men()
self.bind('<Any-KeyPress>',self.move)
def create_board(self):
self.board = Tkinter.Canvas(width=GAME_WIDTH, height=GAME_HEIGHT, bg=GAME_BG)
self.board.pack(padx=10, pady=10)
return
def create_men(self):
self.men = self.board.create_rectangle(300, 300, 310, 310, fill='red')
return
def move(self, event=None):
key = event.keysym
if key=='Left':
self.x = MOVE_SPEED
elif key=='Right':
self.x = -MOVE_SPEED
elif key=='Up':
self.y = MOVE_SPEED
elif key=='Down':
self.y = -MOVE_SPEED
else:
pass
return
def TkUpdate(self):
self.update()
self.update_idletasks()
return
def GameUpdate(self):
self.board.move(self.men, self.x, self.y)
return
Avoid calling update and sleep. Instead use after and mainloop. Your code should schedule your gameloop using after and enter the mainloop after setting up everything. Then keep scheduling the gameloop with after calls.
Your actual problem is you have confused using self.x and self.y as a position in the setup but then use these as a relative move in the game loop. So when you first call GameUpdate you move the rectangle by half the canvas size and it immediately moves out of view. Below is a version that uses these as the 'man' position and asserts the position using coords each time around the game loop.
import tkinter as tk
GAME_WIDTH = 800
GAME_HEIGHT = 600
GAME_BG = 'green'
MOVE_SPEED = 10
MAN_SIZE = 20
class Game(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
# Trigger Of Other Functions
self.x = GAME_WIDTH/2
self.y = GAME_HEIGHT/2
self.create_board()
self.create_men()
self.bind('<Any-KeyPress>',self.move)
def create_board(self):
self.board = tk.Canvas(width=GAME_WIDTH, height=GAME_HEIGHT, bg=GAME_BG)
self.board.pack(padx=10, pady=10)
def create_men(self):
self.men = self.board.create_rectangle((self.x, self.y, self.x + MAN_SIZE, self.y + MAN_SIZE), fill='red', outline='black')
def move(self, event=None):
key = event.keysym
print(key)
if key=='Left':
self.x = self.x - MOVE_SPEED
elif key=='Right':
self.x = self.x + MOVE_SPEED
elif key=='Up':
self.y = self.y - MOVE_SPEED
elif key=='Down':
self.y = self.y + MOVE_SPEED
else:
pass
return
def game_loop(self):
self.board.coords(self.men, (self.x, self.y, self.x + MAN_SIZE, self.y + MAN_SIZE))
self.after(10, self.game_loop)
def main():
game = Game(className="Snake")
game.after(10, game.game_loop)
game.mainloop()
if __name__ == '__main__':
main()

How to detect if a key is being held down in Tkinter?

As a novice when it comes to Python, I've tried programming my own game to start, with the advice of a guidebook. However, for this game, I'm trying to detect when a key is held down consistently instead of just pressed. The current code I'm using doesn't make the character move, and without the halt(self, evt) code being implemented, causes the ship to speed up uncontrollably after the button is held down for long enough.
from tkinter import *
import random
import time
class Game:
def __init__(self):
self.tk = Tk()
self.tk.title("Shooter")
self.tk.resizable(0, 0)
self.tk.wm_attributes("-topmost", 1)
self.canvas = Canvas(self.tk, width=500, height=1000, highlightthickness=0)
self.canvas.pack()
self.tk.update()
self.canvas_height = 1000
self.canvas_width = 500
self.bg = PhotoImage(file="background.gif")
w = self.bg.width()
h = self.bg.height()
for x in range(0, 5):
for y in range(0, 10):
self.canvas.create_image(x * w, y * h, \
image=self.bg, anchor='nw')
self.sprites = []
self.running = True
def mainloop(self):
while 1:
if self.running == True:
for sprite in self.sprites:
sprite.move()
self.tk.update_idletasks()
self.tk.update()
time.sleep(0.01)
class Coords:
def __init__(self, x1=0, y1=0, x2=0, y2=0):
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
class Sprite:
def __init__(self, game):
self.game = game
self.endgame = False
self.coordinates = None
def move(self):
pass
def coords(self):
return self.coordinates
class PlayerSprite(Sprite):
def __init__(self, game):
Sprite.__init__(self, game)
self.renderimage = [
PhotoImage(file="player_1.gif"),
PhotoImage(file="player_2.gif"),
PhotoImage(file="player_3.gif"),
PhotoImage(file="player_4.gif"),
]
self.image = game.canvas.create_image(225, 900, \
image=self.renderimage[0], anchor='nw')
self.x = 0
self.y = 0
self.velx = 0
self.current_image = 0
self.current_image_add = 1
self.shoot_timer = 0
self.last_time = time.time()
self.coordinates = Coords()
x_move = None
y_move = None
game.canvas.bind_all('<KeyPress-Left>', self.move_left)
game.canvas.bind_all('<KeyPress-Right>', self.move_right)
game.canvas.bind_all('<KeyPress-Up>', self.move_up)
game.canvas.bind_all('<KeyPress-Down>', self.move_down)
game.canvas.bind_all('<KeyPress-Left>', self.halt)
game.canvas.bind_all('<KeyPress-Right>', self.halt)
game.canvas.bind_all('<KeyPress-Up>', self.halt)
game.canvas.bind_all('<KeyPress-Down>', self.halt)
game.canvas.bind_all('<space>', self.shoot)
def move_left(self, evt):
x_move = self.x - 1.5
self.x = x_move
def move_right(self, evt):
x_move = self.x + 1.5
self.x = x_move
def move_up(self, evt):
y_move = self.y - 1.5
self.y = y_move
def move_down(self, evt):
y_move = self.y + 1.5
self.y = y_move
def halt(self, evt):
time.sleep(0.01)
if x_move < 0:
x_move = -1.5
elif x_move > 0:
x_move = 1.5
elif y_move < 0:
y_move = -1.5
elif y_move > 0:
y_move = 1.5
def shoot(self, evt):
print("Placeholder")
def move(self):
self.game.canvas.move(self.image, self.x, self.y)
def coords(self):
xy = self.game.canvas.coords(self.image)
self.coordinates.x1 = xy[0]
self.coordinates.y1 = xy[1]
self.coordinates.x2 = xy[0] + 24
self.coordinates.y2 = xy[1] + 32
return self.coordinates
g = Game()
sp = PlayerSprite(g)
g.sprites.append(sp)
g.mainloop()
My goal is to have my character move at a constant rate (as opposed to uncontrollably fast after a while) when the respective key is pressed.
The most straightforward solution to your question would be to avoid adding a value at every keypress, but rather set a constant value.
def move_left(self, evt):
x_move = -5
self.x = x_move
The movement would however lose its dynamic, but it will be constant. Otherwise, you could create a max value. Something like this:
def move_left(self, evt):
int max_val_left = -10
if( self.x < max_val_left):
x_move = self.x - 1.5
self.x = x_move
Thereby forcing self.x to remain capped and constant if it has reached the max_val.
Holding down a key is essentially the same as pressing that key repeatedly. What you're doing by adding to/subtracting from the self.x/self.y attributes in your move_* functions is you're increasing the amount that the canvas will move your player sprite in each function call (e.g. from 1.5 to 3 to 4.5 to 6, etc. as you hold down a direcitonal key).
Since the canvas will be moving your player by (self.x, self.y) units every time "move" is called under the "PlayerSprite" class, we want self.x and self.y to be either 0 or whatever speed you desire (1.5 in the following code). So instead of adding to self.x and self.y, we should assign it to a constant value:
def move_left(self, evt):
self.x = -1.5
def move_right(self, evt):
self.x = 1.5
def move_up(self, evt):
self.y = -1.5
def move_down(self, evt):
self.y = -1.5
Also, instead of using "halt", what you could do is include 'KeyRelease-*' bindings to stop your player once you've stopped holding down a directional key:
game.canvas.bind_all('KeyRelease-Left'>, self.stop_horz_move)
game.canvas.bind_all('KeyRelease-Right'>, self.stop_horz_move)
game.canvas.bind_all('KeyRelease-Up'>, self.stop_vert_move)
game.canvas.bind_all('KeyRelease-Down'>, self.stop_vert_move)
(I've generalized the left and right directions to horz as well as up and down to vert to save on the number of function definitions.)
Then you can create functions that assign your self.x value or self.y value to 0, so that your player doesn't move once "move" is called.
def stop_move_horz(self, evt):
self.x = 0
def stop_move_vert(self, evt):
self.y = 0

Trying to make a ball object bounce off a paddle

I'm new to python and am working on a final project for my intro to python class. I have the majority of a paddle ball game done, but can't figure out how to make the ball object bounce off of my paddle object.
I've looked on Stackoverflow for a while and have spent a few hours trying to figure it out on my own without any success. If anyone has any ideas I could really use the help.
If there's anything I need to explain better in order for you to get a better understanding please just comment.
GUI FILE:
Import tkinter, random, particle, and helpers
from tkinter import *
from ball import *
from paddle import *
from time import *
class PaddleBall:
def __init__(self, window):
''' Construct the paddle ball GUI '''
self.window = window
self.window.protocol('WM_DELETE_WINDOW', self.safe_exit)
self.width = 700
self.height = 900
self.canvas = Canvas(self.window, bg='black', width=self.width, height=self.height, highlightthickness=0)
self.canvas.bind_all("<KeyPress-Left>", self.move_left)
self.canvas.bind_all("<KeyPress-Right>", self.move_right)
self.canvas.pack()
# Create a label to indicate instructions
instructions = Label(window, text="Controls: Left & Right Arrow Keys")
instructions.pack(side=BOTTOM, expand=YES)
# Create a button to clear Ball
restart_button = Button(window, text="Play", command=self.reset)
restart_button.pack(side=BOTTOM, expand=YES)
self.ball = Ball(350, 350)
self.paddle = Paddle(300, 850, 400, 860, 0, 0)
self.terminated = False
self.render()
def ballobject(self):
self.ball = Ball(350, 350)
self.paddle = Paddle(300, 850, 400, 860, 0, 0)
self.render()
def reset(self):
self.terminated = True
def safe_exit(self):
''' Turn off the event loop before closing the GUI '''
self.terminated = True
self.window.destroy()
# Render everything
def render(self):
# While program is not terminated
if not self.terminated:
# Erase Canvas
self.canvas.delete(ALL)
# Move ball
self.ball.move(self.canvas, self.paddle)
# Render ball
self.ball.render(self.canvas)
# Render paddle
self.paddle.render(self.canvas)
# use distance() to detect collision between ball and paddle.
'''Ball.bounce(self)'''
# Animate the particles movement
self.canvas.after(10, self.render)
else:
# Erase Canvas
self.canvas.delete(ALL)
self.terminated = False
self.canvas.after(50, self.ballobject)
def move_left(self, event):
self.paddle.move_left(event)
def move_right(self, event):
self.paddle.move_right(event)
if __name__ == '__main__':
root = Tk()
root.option_add('*font', ('Verdana', 12, 'bold italic')) # Found at http://effbot.org/tkinterbook/tkinter-widget-styling.htm
root.resizable(0,0) # Found at https://mail.python.org/pipermail/tutor/2001-September/008504.html
root.title('Paddle Ball')
root.wm_attributes("-topmost", -1)
app = PaddleBall(root)
root.mainloop()
BALL CLASS FILE:
class Ball:
'''
Ball models a single ball that may be rendered to a canvas
'''
def __init__(self, x, y, radius = 15,):
'''
Constructor
'''
self._x = x
self._y = y
self._velX = randint(-10,10)
self._velY = randint(-10,-5)
self._radius = radius
self._color = 'white'
self._tx = 350
self._ty = 400
self._t = ""
self._tfill = "red"
self._tfont = ("Arial", 35, "bold italic")
# This method renders the ball
def render(self, canvas):
canvas.create_oval(self._x - self._radius, self._y - self._radius, self._x + self._radius, self._y + self._radius, fill = self._color)
canvas.create_text(self._tx, self._ty, text = self._t, fill = self._tfill, font = self._tfont)
# This method moves the ball
def move(self, canvas, Paddle):
# Update Position
self._x += self._velX
self._y += self._velY
# If the ball hits any of the wall negate the velocity
if (self._x + self._radius > canvas.winfo_reqwidth() and self._velX > 0) or (self._x - self._radius < 0 and self._velX < 0):
self._velX = -self._velX
if (self._y + self._radius < 0 and self._velY < 0):
self._velY = -self._velY
if (self._y + self._radius > canvas.winfo_reqheight() and self._velY > 0):
self._velY = 0
self._velX = 0
self._t = " GAME OVER! \n Click the play button to play again."
#*****THIS IS WHAT I'M HAVING TROUBLE WITH******
# Determine if the ball hits the paddle
if ((self._x + self._radius > Paddle._x(self) and self._velX > 0) or (self._x + self._radius < Paddle._x2(self))) and (self._y < Paddle._y(self)):
self._velX = -self._velX
PADDLE CLASS FILE:
# Import math and helpers
from tkinter import *
import math
from gui import *
class Paddle:
def __init__(self, x, y, x2, y2, velX, velY):
'''
Constructor
'''
self._x = x
self._y = y
self._x2 = x2
self._y2 = y2
self._velX = velX
self._velY = velY
self._color = 'white'
def getpadx(self):
return self._x
def getpady(self):
return self._y
def getpadx1(self):
return self._x2
def getpady2(self):
return self._y2
# This method renders the paddle
def render(self, canvas):
canvas.create_rectangle(self._x, self._y, self._x2, self._y2, fill = self._color)
# This method moves the paddle
def move(self, canvas):
# Update Position
# If the paddle hits any of the wall negate the velocity
if (self._x + self._radius > canvas.winfo_reqwidth() and self._velX > 0) or (self._x - self._radius < 0 and self._velX < 0):
self._velX = -self._velX
def move_left(self, event):
self._x -= 35
self._x2 -= 35
def move_right(self, event):
self._x += 35
self._x2 += 35
I figured it out with the help of a friend. All I had to do was change this code:
From this:
if ((self._x + self._radius > Paddle._x(self) and self._velX > 0) or (self._x + self._radius < Paddle._x2(self))) and (self._y < Paddle._y(self)):
self._velX = -self._velX
To this:
`if (self._x > Paddle._x) and (self._x < Paddle._x2):
if (self._y + self._radius > Paddle._y):
self._velY = -self._velY
self._velX = self._velX + randint(-2,2)`

Quick debugging question [Python, pygame]

It's still an incomplete program, but for some reason the value of the textbox doesn't increase when it should... Why is this??
When the Pizza sprite overlaps with the Pan sprite, the score in the textbox is supposed to increase in value by 10. Why does this not occur?
Thanks!
'''
Created on Jul 1, 2011
#author: ******* Louis
'''
#Watch me do.
from livewires import games, color
import random
games.init (screen_width = 640, screen_height = 480, fps = 50)
#Pizza Class
class Pizza (games.Sprite):
pizzaimage = games.load_image ("pizza.bmp", transparent = True)
def __init__(self, x = random.randrange(640), y = 90, dy = 4):
super (Pizza, self).__init__(x = x,
y = y,
image = Pizza.pizzaimage,
dy = dy)
def handle_caught (self):
self.destroy()
class Pan (games.Sprite):
panimage = games.load_image ("pan.bmp", transparent = True)
def __init__ (self, x = games.mouse.x, y = games.mouse.y):
super (Pan, self).__init__(x = x,
y = y,
image = Pan.panimage)
self.score = 0
self.textbox = games.Text (value = str(self.score),
size = 20,
color = color.black,
x = 550,
y = 50)
games.screen.add(self.textbox)
def update (self): #WWWWOW There is actually an *update* method
self.x = games.mouse.x
self.y = games.mouse.y
if self.left < 0:
self.left = 0
if self.right >640:
self.right = 640
if self.top < 0:
self.top = 0
if self.bottom > 480:
self.bottom = 480
self.check_collision()
def check_collision (self):
for Pizza in self.overlapping_sprites:
self.score = self.score + 10
Pizza.handle_caught()
#main
def main():
wallbackground = games.load_image ("wall.jpg", transparent = False)
games.screen.background = wallbackground
games.screen.add(Pizza())
games.screen.add(Pan())
games.mouse.is_visible = False
games.screen.event_grab = True
games.screen.mainloop()
main()
The textbox takes a value that is a string. When you create the textbox, you create a string from the current value of score, and set the text to that string. No lasting connection between score and textbox is made.
The textbox probably has a method available to update its text; call that method with the value str(self.score) after you increment the score.

Categories