Pygame is not drawing an object

Asked

Viewed 90 times

-1

I’m making a game in python using pygame. The game consists of a player who shoots small bullets depending on the position of the mouse and itself. Everything runs smoothly, the player moves as I want, the program records the position of the mouse, when I click on SPACE the program reads it and "shoots" a bullet, makes all the correct bullet calculations... The only problem is the bullet doesn’t show up on the screen, I’ve already tested the function where the bullet is "drawn" and the function that determines the position of the bullet and is being read correctly. Here is the code that I consider important:

Bullet code

class Bullet:
    doDraw = False
    def __init__(self, startx, starty, endx, endy):
        self.startx = startx
        self.starty = starty
        self.endx = endx
        self.endy = endy
        self.framenum = 0
        self.shootBullet()

    def shootBullet(self):
        self.declive = (self.endy-self.starty) / (self.endx-self.startx)
        self.bulletx = self.startx
        self.bullety = self.starty
        self.doDraw = True

    def draw(self):
        self.GetPosition()
        pygame.draw.rect(screen, (200, 200, 25), pygame.Rect(self.bulletx, self.bullety, 10, 10))


    def GetPosition(self):
        self.framenum += 1
        if self.endx > self.startx:
            self.bulletx += 1*self.framenum 
        elif self.endx < self.startx:
            self.bulletx -= 1*self.framenum
        self.bullety += self.declive*self.framenum
        if self.bulletx < 0 or self.bulletx > 800 or self.bullety < 0 or self.bullety > 600:
            self.stop()

    def stop(self):
        self.doDraw = False

Code in the Main Loop

if keyPressed[pygame.K_SPACE]:
    if 'bullet' in globals():
        if bullet.doDraw == False:
            bullet = Bullet(p.x, p.y, mousePoint[0], mousePoint[1])
            bullet.doDraw = True
    else:
        bullet = Bullet(p.x, p.y, mousePoint[0], mousePoint[1])
        bullet.doDraw = True

if 'bullet' in globals():
    if bullet.doDraw == True:
        bullet.draw()
  • 2

    Who gave the downvote on the question, please, the idea of downvotes is not "I do not know how to answer so I will give a negative vote". The code snippet is concise - there is something missing to be executable separately (the screen startup, and the mainloop code), but the code snippets are very clear, there is no more than needed, and allows to say a lot about what happens.

1 answer

1

You haven’t put all the mainloop code - but most likely the only problem is that you’re using a "global" variable for Bullet, but in the wrong way.

When there is a need for a global variable, it should be declared at the beginning of the function as global, and then be used normally:

bullet = Bullet()
...
def principal():
    global bullet
    ...
    if bullet.doDraw == False:

The way it’s done, the condition if 'bullet' in globals(): may be true, but if bullet is not declared as global within the function, the program will create a local variable bullet - which may not be what the program "sees" in other functions.

The bigger problem is that apparently there is no bullet in globals() when the mainloop starts, then the condition if 'bullet' in globals(): will always be false - and then he will create a new Bullet local, but in the drawing part:

if 'bullet' in globals():
    if bullet.doDraw == True:
        bullet.draw()

he will never enter (since the condition will be false)

The suggestion is:

  1. forget about that check in globals() - that’s just wrong.

  2. Use a local variable with content None, created at the beginning of your mainloop:

def principal():
     bullet = None
     ...
     while True:
         ... # código do mainloop
  1. Do not test if the variable exists, only if it has "None" or an existing Bullet:
if keyPressed[pygame.K_SPACE]:
    if bullet and not bullet.doDraw:  
         # Use "not variavel" em condiçoes, nunca "variavel == False"
         bullet = Bullet(p.x, p.y, mousePoint[0], mousePoint[1])
         bullet.doDraw = True
         # não precisa do "else" - se a bala já existe e está ativa,
         # não faz nada.

    ...
    # e para desenhar: 
    if bullet and bullet.doDraw == True:
        bullet.draw()

After this works, take a look at the "Sprite" class of pyagame and the "groups": pygame can automatically manage the lifecycle of your bullets (instead of "toDraw=False" self.kill() when it reaches the end of the screen, for example, and will be automatically removed from the group) - this will allow a cleaner logic to have more than one bullet on the screen at a time.

  • The problem is that, using my code, if I print ("Drawn bullet") on the drawing function of class Bullet, the message is written until the bullet exits the screen, your explanation has helped me greatly to improve my code anyway but the object is still not drawn, I have another class, which has a draw function that has exactly the same line of pygame.draw.rect(screen, (255, 255, 255), pygame.Rect(50, 50, 25, 25)) code and works perfectly well..

  • Without seeing the whole code - in particular how you are defining screen and how the other things are being drawn, I can’t get any more ideas.

  • The screen is simply set to screen = pygame.display.set_mode((800, 600)), the other objects are being drawn in the same way as the bullet, for example p.draw() with the function being def draw(self): pygame.draw.rect(screen, (255, 255, 255), pygame.Rect(self.x, self.y, self.width, self.height)) ....

Browser other questions tagged

You are not signed in. Login or sign up in order to post.