Unable to ball show up in brick breaker game I am building with tkinter

I am currently writing a brickbreaker game in python to teach myself classes and such however I am unable to get the ball to show up. I have the bricks and the paddle, the paddle is moving but not seeing the ball. Any idea why?

import tkinter as tk #display graphic user interface

class PlayComponent(object):
    def __init__(self, canvas, item): #pass canvas and item
        self.item = item
        self.canvas = canvas
        
    def move(self, x, y):
        self.canvas.move(self.item,x,y)
    
    def position(self):
        return self.canvas.coords(self.item)

    def delete(self):
        self.canvas.delete(self.item)
        
        
class Paddle(PlayComponent): #incorporate all of the playcomponent class
    def __init__(self, canvas, x, y): #pass to our initialiation function
        self.height = 5
        self.width = 100
        self.ball = None
        item = canvas.create_rectangle(x-self.width/2, y-self.height/2, x+self.width/2, y+self.height/2, fill='green')
        super(Paddle,self).__init__(canvas,item)
        
    def set_ball(self,ball):
        self.ball = ball

    def move(self,dist):
        coord = self.position()
        width = self.canvas.winfo_width() #prevents paddle from changing size with screen size
        if coord[2] +dist <=width and coord[0] +dist >=0:
            super(Paddle,self).move(dist, 0)
            if self.ball is not None:
                self.ball.move(dist,0)
class Brick(PlayComponent):
    colorArray = {1:'lightsteelblue', 2: 'royalblue', 3: 'blue'}
    
    def __init__(self, canvas, x, y, hits):
        self.width = 60
        self.height = 20
        self.hits = hits
        color = Brick.colorArray[hits] #color changes with number of its
        item = canvas.create_rectangle(x-self.width/2,y-self.height/2, x+self.width/2, y+self.height/2, fill = color, tag = 'brick')
        super(Brick,self).__init__(canvas, item)
    def hit(self):
        self.hits -= 1
        if self.hits == 0:
            self.delete()
        else:
            self.canvas.itemconfig(self.item, fill=Brick.colorArray[self.hits])

class Ball(PlayComponent):
    def __init__(self,canvas, x, y):
        self.radius = 16
        self.speed = 8
        self.direction = [-1,1] #if ball hits a wall it goes in the opposite direction
        item = canvas.create_oval(x-self.radius, y-self.radius, x+self.radius, y+self.radius, fill = 'white')
        
        super(Ball,self).__init__(canvas,item) #calls the ball class

    def update(self):
        coord = self.position()
        width = self.canvas.winfo_width() #width of the ball and assigns it to the ball
        if coord[1] <=0: #if we are hitting top or bottom
            self.direction[1]*= -1 #will change the direction of the ball using the multiplication method
        if coord[2] >=width or coord[0] <=0: #if we are hitting left or right wall
            self.direction[0]*= -1
            
        #create moving ball
        x - self.direction[0] * self.speed
        y = self.direction[1] * self.speed
        self.move(x,y)

    def intersect(self,components):
        coord = self.position()
        x = (coord[0] + coord[2])*0.5
        if len(components) == 1:
            component = components[0]
            coord = component.position()
            if x < coord[0]:
                self.direction[0] =- 1
            elif x > coord[2]:
                self.direction[0] = 1
            else:
                self.direction[1]+= -1
        elif len(components)>1:
            self.diirection[1]*=1
        for component in components:
            if isinstance(component,Brick):
                component.hit()
class Game(tk.Frame):
    def __init__(self, master): #initialization function
        super(Game,self).__init__(master) #super class
        #create window
        self.width = 1000;
        self.height = 400;
       
        #create canvas
        self.canvas = tk.Canvas(self, bg = 'brown',
                                            width = self.width,
                                            height = self.height)
       
        self.canvas.pack()
        self.pack()
        self.items = {}
        self.ball = None
        self.paddle = Paddle(self.canvas, self.width/2, 320) #determins where paddle starts
        self.items[self.paddle.item] = self.paddle
        self.hud = None
        for x in range(100, self.width -100, 60):
            self.display_brick(x+20, 50,2)
            
        self.canvas.focus_set()
        self.canvas.bind('<Left>', lambda _:self.paddle.move(-30))
        self.canvas.bind('<Right>', lambda _:self.paddle.move(30))
                
        
    def init_game(self):
        self.display_ball()
        self.start_game()
        
    def display_ball(self):
        if self.ball is not None:
            self.ball.delete()
        paddle_coords = self.paddle.position()
        x = (paddle_coords[0] + paddle_coords[2])*0.5
        self.ball = Ball(self.canvas,x,310)
        self.paddle.set_ball(self.ball)
       
    def display_brick(self, x, y, hits):
        brick = Brick(self.canvas, x, y, hits)
        self.items[brick.item] = brick
    
    def start_game(self):
        self.canvas.unbind('<space>') #press space bar
        self.paddle.ball = None 
        
    def game_loop(self):
        self.verify_inter()
        num__bricks = len(self,canvas.find_withtag('brick'))
        if num_bricks == 0:
            self.ball.speed = None
        else:
            self.ball.update()
            self.after(50,self.game_loop())

    def verify_inter(self):
        ball_coords = self.ball.position()
        items = self.canvas.find_overlapping(*ball_coords)
        object = [self.items[x] for x in items if x in self.items]
        self.ball.intersect(object)
if __name__ == '__main__':
    root=tk.Tk()
    root.title('Brick Breaker')
    game = Game(root) #calling game function
    #print(game)
    #print(game.width)
    game.mainloop() #loops around game

I put a print statement in Ball.__init__. Nothing was printed, which means that it wasn’t called.

A ball is created in display_ball, so I put a print statement in there. Nothing was printed, which means that it wasn’t called.

display_ball is called by init_game, so I put a print statement in there. Nothing was printed, which means that it wasn’t called.

And, in fact, nothing in the code calls init_game. That’s the problem.

found the issue
I had setup a function called:

    def init_game(self):
        self.display_ball()
        self.start_game()

but I forgot to call it in the init function so I did this:

def __init__(self, master)
    self.init_game()