1

I'm making a pygame game.When I click on the tanks button and then click on the screen(play area) a tank is blitted on that coordinate. Along with the tank a bullet is also blitted. I'm able to make my tank move but the bullets are not shooting. I want the tanks to keep shooting automatically after the bullet gets reset after travelling, say 40 pixels.

This is the function that gives the tanks and the bullets the coordinates

tank_pos_list = []
bullet_list = []

def spawn_tank():
    global tank_pos_list
    global bullet_list
    qx, qy = pygame.mouse.get_pos()
    tankxy = [(qx - 35), (qy - 35)]
    tank_pos_list.append(tankxy)
    bullet_list.append(tankxy)

This is my movement class for tanks and bullets.

class MovementClass:

    global bullet_list
    global tank_pos_list
    tank_surf = pygame.image.load("tank.png")
    bullet = pygame.image.load("bullet.png")

    def movetank(self, tankimg):
        for tank_pos in tank_pos_list:
            screen.blit(tankimg, (tank_pos[0], tank_pos[1]))
            tank_pos[0] += 0.2

    def movebullet(self, bulletimg):
        for j in range(len(bullet_list)):
            newx = (bullet_list[j][0] + 35)
            screen.blit(bulletimg, (newx, (bullet_list[j][1] + 34)))
            newx += 1

This is my main function

def main():
    global new_tanks
    global spawner
    global tank_pos_list
    global fire_bullet_tank
    run = True
    fps = 90
    tanks = Button((59, 255, 140), 100, 610, 80, 80, text="Tanks")
    tanks_over = Button((0, 255, 0), 100, 610, 80, 80, text="Tanks")
    towers = Button((59, 255, 140), 510, 610, 150, 80, text="Towers")
    towers_over = Button((0, 255, 0), 510, 610, 150, 80, text="Towers")
    blue = pygame.image.load("blue_base.png")
    red = pygame.image.load("red_base.png")
    spawner = False

    while run:

        mx, my = pygame.mouse.get_pos()
        pos = (mx, my)
        x = pos[0]
        y = pos[1]

        mouse_pos = (mx, my)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

            if event.type == pygame.MOUSEBUTTONDOWN:
                if spawner and my < 550 and mx < 500:
                    spawn_tank()

                    spawner = False
                if tanks.isOver(mouse_pos):
                    spawner = True

        screen.fill((50, 168, 66))

        if len(tank_pos_list) >= 11:
            tank_pos_list.pop(-1)

        pygame.draw.rect(screen, (201, 142, 47), (0, 600, 1000, 100))
        pygame.draw.line(screen, (0, 0, 0), (500, 0), (500, 600))

        if tanks.isOver(mouse_pos):
            tanks_over.draw(screen)
        else:
            tanks.draw(screen)

        if towers.isOver(mouse_pos):
            towers_over.draw(screen)
        else:
            towers.draw(screen)

        screen.blit(blue, (0, 100))
        screen.blit(red, (800, 100))

        #movement()

        movingtank = MovementClass()
        movingtank.movetank(pygame.image.load("tank.png"))
        movingbullet = MovementClass()
        movingbullet.movebullet(pygame.image.load("bullet.png"))

        pygame.display.flip()
        clock.tick(fps)
rishi
  • 643
  • 5
  • 21

1 Answers1

3

When you run

for tank_pos in tank_pos_list:
   ...
   tank_pos[0] += 0.2

you're changing the first value in a list inside the tank_pos_list list. Note that you add tankxy to both lists in spawn_tank so you can see the change in tank_pos_list and bullet_list. It's the same list in both lists you're changing here.

But when you run

for j in range(len(bullet_list)):
    newx = (bullet_list[j][0] + 35)
    ...
    newx += 1

you just create a new variable newx and change its value; but you never change any values of the lists in bullet_list.


Some more notes:

The MovementClass has no internal state; it's basically useless that you create 2 new instances every frame. Use global functions instead (without a class) or just inline those functions.

You load "tank.png" and "bullet.png" every frame from disk. You should just load the images once outside your main loop. Otherwise, it becomes a major performance killer soon.


Try to create a class or multiple classes that represents the different actors of your game (pygame offers the Sprite class for this) and implement the behaviour and state in that class. While that's not the most advanced technique it is the right way to go IMHO for small games.

For an example, maybe take a look at this answer I did for another questions, which is pretty much a step-by-step guide on how I would create such a game.

sloth
  • 99,095
  • 21
  • 171
  • 219
  • Thank you for your answer, now I understand what's happening, could you help me fix the issue, I also need the bullet to reset to the new position of tank every time it travels 40 pixels. I'm trying to learn classes and am still a beginner to pygame – rishi May 03 '20 at 17:31
  • The link you attached seems quite helpful, but I have no clue what vector is doing and I'm still new to classes. Sprites is also something I've never worked with. Any suggestions or resources to learn from would help. – rishi May 03 '20 at 17:43