Search code examples
pythonpython-2.7pygamepong

I can't locate the source of my 'NoneType' error in my version of Pong


I posted a version of Pong to another popular site yesterday and got a lot of advice on how I can clean it up, and got a lot of tips in general. One is that all coordinates should be tuples.

I've been rewriting it all morning to try to improve it(specifically with the tuple thing), but I'm stuck with a NoneType somewhere, which I can't find for the life of me.

Traceback (most recent call last): File "C:\Users\Jassie\Desktop\Pygame_Pong_v2.py", line 172, in my_ball.update() File "C:\Users\Jassie\Desktop\Pygame_Pong_v2.py", line 64, in update self.pos = (self.pos[0] + self.vel[0], self.pos[1] + self.vel[1]) TypeError: 'NoneType' object has no attribute 'getitem'

def update(self):
    #Update ball's position
    self.pos = (self.pos[0] + self.vel[0], self.pos[1] + self.vel[1])
    self.pos_x = int(self.pos[0])
    self.pos_y = int(self.pos[1])

There is the error and the bit of code referenced in the error.

https://github.com/Jassie411/pong

There is a link to the full code if anyone could take a look and help me out. I have looked at the code all morning(since about 4AM actually), looking at where the initial velocity tuple comes from, where the initial position tuple comes from, and where they're going. I just can't see where the NoneType is coming from. I've also tried completely rewriting that part of it, but I can't solve this myself.

If someone could please help me with this, I would be so grateful. I know after I get past this I can finish the rest of it simply. But this error is killing me.

Edit: Sorry, I should probably describe the behavior and such. I know it's an error with either the position or velocity attribute becoming None, but I don't know which it is, and I don't know where.

What I do know, is that it only throws the error when the ball hits the gutter or paddle. It doesn't matter which it hits, it throws the same error either way. Naturally I thought it would be in the code that checks that collision, but I can't find it there.


Solution

  • The problem is spawn_ball function:

    def spawn_ball(direction = random.choice('01')):
        #direction should always be left if AI is enabled for paddle2.
        #0 is left, 1 is right
        if direction == 0:
            return (random.uniform(1.0, 3.0) * -1, random.uniform(1.0, 3.0) * -1)
        elif direction == 1:
            return (random.uniform(1.0, 3.0), random.uniform(1.0, 3.0) * -1)
    

    First of all you shouldn't initialize default variables like this. random.choice('01') is evaluated once, when function object is created. So default direction will always be the same. But what is causing your error is that 0 != '0'. So when you call spawn_ball without arguments no if statement is matched and function returns None.

    Here's correct variant:

    def spawn_ball(direction=None):
        if direction is None:
            direction = random.choice((0, 1))
        #direction should always be left if AI is enabled for paddle2.
        #0 is left, 1 is right
        if direction == 0:
            return (random.uniform(1.0, 3.0) * -1, random.uniform(1.0, 3.0) * -1)
        elif direction == 1:
            return (random.uniform(1.0, 3.0), random.uniform(1.0, 3.0) * -1)