1

I am trying to learn OOP programing with python through making some games. Recently I encountered a strange problem:

Bullets which are shot by an enemy, significantly increase their fixed speed and fixed dmg - they are not supposed to do that. They are supposed to move at constant speed. For example they are supposed to travel with .speed 4 and do 2 .dmg(damage), but they travel with speed 12 and do 6 dmg. Sometimes their speed 8 and dmg 4... It looks like their speed and dmg is multiplied by enemy's attribute .speed.

The problem occurs with both types of enemies - green and red one. I tried explain the problem to rubber duck, but it doesn't work neither. I can't find a mistake in my code.

Also they not always make it to the end of the screen even though they didn't collide with anything.

Maybe somebody could help me to fix that and show where the error is?

Below is my main.py (main loop and logic) as well as static.py (all classes etc.)

#THIS IS MAIN.PY

import pygame as pg
from static2 import *
pg.init()

[...]

# ------------- GAME LOOP ------------- #
clock = pg.time.Clock()
run = True

while run:
    [...]
    # GAME LOGIC---------------------------------------------
    for red_enemy in redEnemyList:
        red_enemy.start_countdown()
        if red_enemy.countdown == 1:
            red_enemy.shot(redLaser)
        red_enemy.bullets_move()
        red_enemy.bullet_hit(player)
        update_player_hp_font()
        red_enemy.move()
        if red_enemy.hp <= 0:
            bg.score += 1
            update_score()
            red_enemy.die(redEnemyList)

    for green_enemy in greenEnemyList:
        green_enemy.start_countdown()
        if green_enemy.countdown == 1:
            green_enemy.shot(greenLaser)
        green_enemy.bullets_move()
        green_enemy.bullet_hit(player)
        update_player_hp_font()
        green_enemy.move()
        if green_enemy.hp <= 0:
            bg.score += 1
            update_score()
            green_enemy.die(greenEnemyList)


pg.quit()

#THIS IS STATIC.PY

import pygame as pg
import random
pg.font.init()

[...]

# ------------- CLASSES ------------- #
class Background():
    def __init__(self):
        self.img = pg.image.load('images/backgrounds/background_0.png')
        self.img_scaled = pg.transform.scale(self.img,
                                             (WIDTH, HEIGHT)).convert_alpha()
        self.x = 0
        self.y = 0
        self.score = 0

    def draw_bg(self, screen_var_name):
        screen_var_name.blit(self.img, (self.x, self.y))


class Eny_Laser:
    def __init__(self):
        self.img = None
        self.rect = None
        self.speed = 4
        self.dmg = 1

    def draw(self):
        window.blit(self.img, self.rect)

    def move(self):
        self.rect.y += self.speed


class RedLaser(Eny_Laser):
    def __init__(self):
        super().__init__()
        self.img = pg.image.load(
            'images/enemies/red_alien_bullet.png').convert_alpha()
        self.rect = self.img.get_rect()
        self.dmg = 2


class GreenLaser(Eny_Laser):
    def __init__(self):
        super().__init__()
        self.img = pg.image.load(
            'images/enemies/green_alien_bullet.png').convert_alpha()
        self.rect = self.img.get_rect()


class P_Bullet(Eny_Laser):
    def __init__(self):
        super().__init__()
        self.img = pg.image.load(
            'images/player/player_bullet.png').convert_alpha()
        self.rect = self.img.get_rect()
        self.speed = -10


class Player():
    def __init__(self):
        self.img = pg.image.load('images/player/player_ship.png')
        self.img_scaled = pg.transform.scale(self.img, (self.img.get_width() * 0.5,
                                                        self.img.get_height() * 0.5)).convert_alpha()
        self.rect = self.img_scaled.get_rect()
        self.rect.center = (WIDTH // 2, HEIGHT - self.rect.height // 2)

        self.bulletList = []
        self.speed = 6
        self.hp = 10

    def draw(self, screen_var_name):
        screen_var_name.blit(self.img_scaled, (self.rect.x, self.rect.y))
        for bullet in self.bulletList:
            bullet.draw()

    def shot(self, bulletObj):
        self.bulletList.append(bulletObj)
        bulletObj.rect.center = (
            self.rect.centerx, self.rect.y - bulletObj.rect.height // 2)

    def bullets_move(self):
        for bullet in self.bulletList:
            bullet.move()
            if bullet.rect.y <= 0:
                self.bulletList.remove(bullet)

    def bullet_hit(self, redEnemyList: list, greenEnemyList: list):
        for bullet in self.bulletList:
            for enemy in redEnemyList:
                if bullet.rect.colliderect(enemy.rect):
                    enemy.hp -= bullet.dmg
                    self.bulletList.remove(bullet)
            for enemy in greenEnemyList:
                if bullet.rect.colliderect(enemy.rect):
                    enemy.hp -= bullet.dmg
                    self.bulletList.remove(bullet)


class RedEnemy(Player):
    def __init__(self):
        self.img = pg.image.load('images/enemies/red_alien.png')
        # magic numbers 0.3 and 0.37 are for scaling
        # thanks to them, enemies will be same size as player
        self.img_scaled = pg.transform.scale(self.img, (self.img.get_width() * 0.3,
                                                        self.img.get_height() * 0.37)).convert_alpha()
        self.img_width = self.img_scaled.get_width()
        self.img_height = self.img_scaled.get_height()

        self.rect = self.img_scaled.get_rect()
        self.rect.x = random.randint(1, WIDTH - self.img_width)
        self.rect.y = random.randint(0, 170)

        self.bulletList = []
        self.speed = random.randint(3, 5)
        self.countdown = 0
        self.hp = 3

    def start_countdown(self):
        self.countdown = random.randint(1, 60 * 3)

    def move(self):
        if self.rect.x > 0 and self.rect.x + self.rect.width < WIDTH:
            self.rect.x += self.speed
        if self.rect.x + self.img_width >= WIDTH or self.rect.x <= 0:
            self.speed = -self.speed
            self.rect.x += self.speed

    def die(self, enemyList: list):
        enemyList.remove(self)

    def bullets_move(self):
        for bullet in self.bulletList:
            bullet.move()
            if bullet.rect.y >= HEIGHT:
                self.bulletList.remove(bullet)

    def bullet_hit(self, player: object):
        for bullet in self.bulletList:
            if bullet.rect.colliderect(player.rect):
                self.bulletList.remove(bullet)
                player.hp -= bullet.dmg


class GreenEnemy(RedEnemy):
    def __init__(self):
        super().__init__()
        self.img = pg.image.load('images/enemies/green_alien.png')
        self.img_scaled = pg.transform.scale(self.img, (self.img.get_width() * 0.3,
                                                        self.img.get_height() * 0.37)).convert_alpha()
        self.img_width = self.img_scaled.get_width()
        self.img_height = self.img_scaled.get_height()

        self.rect = self.img_scaled.get_rect()
        self.rect.x = random.randint(1, WIDTH - self.img_width)
        self.rect.y = random.randint(270, 370)

        self.hp = 2


# ------------- BACKGROUND AND LVL SETTINGS ------------- #
bg = Background()
lvl = 1
player = Player()

player_hp_font = main_font.render(f'Your health: {player.hp}', True, WHITE)
player_score_font = main_font.render(f'Your score: {bg.score}', True, WHITE)


def draw_whole_window(redEnemyList: list, greenEnemyList: list, player: object):
    window.fill(BLACK)
    window.blit(bg.img_scaled, (bg.x, bg.y))
    window.blit(player_hp_font, (10, 10))
    window.blit(player_score_font,
                (WIDTH - player_score_font.get_rect().width - 10, 10))
    for enemy in redEnemyList:
        enemy.draw(window)
    for enemy in greenEnemyList:
        enemy.draw(window)
    player.draw(window)
    pg.display.flip()


def update_score():
    global player_score_font
    player_score_font = main_font.render(f'Your score: {bg.score}',
                                         True, WHITE)


def update_player_hp_font():
    global player_hp_font
    player_hp_font = main_font.render(f'Your health: {player.hp}',
                                      True, WHITE)

hubert8520
  • 23
  • 3
  • 1
    Welcome to Stack Overflow. Please read [ask] and https://ericlippert.com/2014/03/05/how-to-debug-small-programs/. "I would love to understand where did I make a mistake." is not an answerable question, because it is not specific, and "Bullets which are shot by an enemy, multiply their fixed speed and fixed dmg" does not clearly explain the problem. What do you mean that they are "multiplied"? What should you see when you run the program, and how is that different from what you actually see? Do the bullets *accelerate*? Do they travel too quickly? Something else? – Karl Knechtel Jul 01 '22 at 09:23
  • 1
    Please also read [mre] and try to show a smaller code example that demonstrates the problem. How much of this code is actually relevant to the problem with the enemy bullets? For example, if there are only green enemies, or only red enemies, does the problem still occur? What if there is no player, and no keyboard control? – Karl Knechtel Jul 01 '22 at 09:26
  • As you suggested me - I edited my post and deleted some code which was not connected to the enemies and the bullets nor the displaying methods. I have also changed the description of the problem, so it is more specific. I tried debugging it with VSC, but I couldn't find a mistake that's why I asked for help here. I want to try by myself and only if I can't do something I ask others for help. – hubert8520 Jul 01 '22 at 10:28
  • What exactly do you mean with "dmg"? – The_spider Jul 01 '22 at 11:59
  • I edited the post and now it is explained that dmg = damage – hubert8520 Jul 01 '22 at 15:48

0 Answers0