Space Invaders Aliens sollen sich nicht überlappen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Wired1.0.
User
Beiträge: 31
Registriert: Montag 23. Januar 2023, 20:25

Hi!

Ich programmiere gerade space invaders und ärgere mich darüber, dass sich die Aliens überlappen. Kann mir da evtl jemand weiterhelfen?

Code: Alles auswählen

import pygame
import random
import math




# ToDo
# - Nur ein enemy bei kollision --> bei remove wenn level implementiert
# - level implementieren
# - bei terminierung kleine explosion
# - Aliens sollen sich nicht überlappen
# - bosse grüner laserstrahl
# - t- fighter schießen 2 schuss auf einmal
# - bei Mauskick schießen
# - Vollbild implementieren
# - Pause implementieren
# - wenn alle 3 herzen weg, spaceship weg, riesen explosion, game over
# - class SpeedShootPU(PowerUps):
# - doube shoot PU erstellen



class Game:
    def __init__(self, width, height):
        pygame.init()
        self.width = width  # 7
        self.height = height  # 7
        self.screen = pygame.display.set_mode((self.width, self.height))  # 7
        pygame.display.set_caption("Space Invaders")  # 5
        self.running = True  # 4
        self.clock = pygame.time.Clock()  # 6
        self.background_img = pygame.image.load("background123.peg").convert()  # 20
        self.background_img = pygame.transform.scale(self.background_img, (width, height))
        self.spaceship = Spaceship(self, 368, 515, "battleship.png")  # 8
        self.y = 600
        self.hpu = []
        self.boss = []
        self.hearts = []
        self.enemies = []  # 15
        self.speed_enemy = []
        self.player_bullet_list = []
        self.speed_enemy_bullet_list = []
        self.score = 0
        self.counter = 0
        self.enemy_shoot_counter = 0
        self.clock = pygame.time.Clock()
        self.heart_lives = 3
        self.boss_lives = [1, 2, 3]
        self.speed_enemy_lives = [1, 2]
        self.ufo_lives = [1]
        self.start_boss_lives = 3
        self.start_speed_enemy_lives = 2
        self.start_ufo_lives = 1
        self.health_power_up_counter = random.randint(300, 600)
        self.double_shoot_pu_counter = random.randint(500, 900)
        self.shield_pu_counter = 0
        self.pixel = 64
        self.present_lives = 0
        self.normal_speed = 5
        self.speed_speed = 10

        # shield-Attributes
        self.shield_countdown = 6  # Countdown
        self.shield_bool = False
        self.shield_last_count = pygame.time.get_ticks()
        self.shield_pu = []
        self.shield_symbol = []
        self.spaceship_shield = []
        self.shield_pu_counter_pin = random.randint(100, 300)
        self.shield_pu.append(ShieldPU(self, random.randint(0, 736), random.randint(-130, -60), "shield_pu.png"))
        self.shield_symbol.append(ShieldSymbol(self, 20, 50, "shield_pu.png"))

        self.hearts.append(Hearts(self, 20, 30, "heart.png"))
        self.hearts.append(Hearts(self, 36, 30, "heart.png"))
        self.hearts.append(Hearts(self, 52, 30, "heart.png"))

        self.hpu.append(HealthPowerUp(self, random.randint(0, 736), random.randint(-130, -60), "passion.png"))

        for i in range(0):
            self.speed_enemy.append(
                SpeedEnemy(self, random.randint(0, 736), random.randint(-130, -60), "t-fighter.png"))

        for i in range(5):
            self.boss.append(Boss(self, random.randint(0, 736), random.randint(-130, -60), "death-star.png"))

        for i in range(3):  # 15
            self.enemies.append(Enemy(self, random.randint(0, 736), random.randint(-130, -60), "ufo.png"))  # 15

        while self.running:  # 4
            self.clock.tick(60)  # 6 setzt die FPS
            self.spaceship.check_collision_enemy(self.enemies)
            self.spaceship.check_collision_enemy(self.speed_enemy)
            self.spaceship.check_collision_enemy(self.boss)

            # Beweglicher Bildschirm
            self.rel_y = self.y % self.background_img.get_rect().height  # 20
            self.screen.blit(self.background_img, (0, self.rel_y - self.background_img.get_rect().height))
            if self.rel_y < height:
                self.screen.blit(self.background_img, (0, self.rel_y))
            self.y += 1

            for i in self.spaceship_shield:
                i.update(self.spaceship)

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.running = False
                if event.type == pygame.KEYDOWN:  # 10
                    if event.key == pygame.K_LEFT or event.key == pygame.K_a:
                        self.spaceship.move(-10)  # 10.4
                    if event.key == pygame.K_SPACE:  # 13
                        self.spaceship.fire_bullet(self.player_bullet_list, "laser.png", Bullet)
                    if event.key == pygame.K_RIGHT or event.key == pygame.K_d:
                        self.spaceship.move(10)
                    if event.key == pygame.K_UP or event.key == pygame.K_w:
                        self.spaceship.move_y(-10)
                    if event.key == pygame.K_DOWN or event.key == pygame.K_s:
                        self.spaceship.move_y(10)

                if event.type == pygame.KEYUP:  # 10.5
                    if event.key == pygame.K_LEFT or event.key == pygame.K_a:
                        self.spaceship.move(10)
                    if event.key == pygame.K_RIGHT or event.key == pygame.K_d:
                        self.spaceship.move(-10)
                    if event.key == pygame.K_UP or event.key == pygame.K_w:
                        self.spaceship.move_y(10)
                    if event.key == pygame.K_DOWN or event.key == pygame.K_s:
                        self.spaceship.move_y(-10)

            # t-fighter shoot back
            self.enemy_shoot_counter += 1
            if self.enemy_shoot_counter >= 100:
                for enemy in self.speed_enemy:
                    enemy.fire_bullet(self.speed_enemy_bullet_list, "laser_grey.png", SpeedBullet)
                    self.enemy_shoot_counter = 0

            for bullet in self.speed_enemy_bullet_list:
                if bullet.is_fired:
                    bullet.bullet_update()
                else:
                    self.speed_enemy_bullet_list.remove(bullet)
                if len(self.hearts) == 0:
                    self.speed_enemy_bullet_list.clear()

            self.spaceship.update(0, 0)  # 9
            # 13.3
            for bullet in self.player_bullet_list:
                if bullet.is_fired:
                    bullet.bullet_update()
                else:  # 14.1
                    self.player_bullet_list.remove(bullet)

            for enemy_speed in self.speed_enemy:
                enemy_speed.update(self.speed_speed, 60)
                enemy_speed.check_collision_player_bullet(self.player_bullet_list, self.speed_enemy_lives,
                                                          self.start_speed_enemy_lives)
                if enemy_speed.y >= 536:
                    self.change_position_g_o()
                    self.print_game_over()
                    break

            for end_boss in self.boss:
                end_boss.check_collision_player_bullet(self.player_bullet_list, self.boss_lives, self.start_boss_lives)
                end_boss.update(self.normal_speed, 60)
                if end_boss.y >= 536:
                    self.change_position_g_o()
                    self.print_game_over()
                    break

            for enemy in self.enemies:
                enemy.update(self.normal_speed, 60)
                enemy.check_collision_player_bullet(self.player_bullet_list, self.ufo_lives, self.start_ufo_lives)
                if enemy.y >= 536:  # 17
                    self.change_position_g_o()
                    self.print_game_over()
                    break

############################################################################################################################################################################
            for enemy in self.boss:
                enemy.check_collision_between_aliens(self.enemies)

            for boss in self.boss:
                boss.check_collision_between_aliens(self.boss)

            for speed_enemy in self.speed_enemy:
                speed_enemy.check_collision_between_aliens(self.speed_enemy)


            self.spaceship.check_collision_enemy_bullet(self.speed_enemy_bullet_list)

            # 23 Health PowerUp einfügen
            if len(self.hearts) < 3:
                self.counter += 1
                if self.counter >= self.health_power_up_counter:
                    for heart in self.hpu:
                        heart.update()
                        self.spaceship.check_collision_hpu(self.hpu)
                        if heart.y > 600:
                            self.counter = 0
                            heart.powerup = False
                            self.hpu.remove(heart)
                            self.hpu.append(
                                HealthPowerUp(self, random.randint(0, 736), random.randint(-130, -60), "passion.png"))
            # Shield Pu einfügen
            self.shield_pu_counter += 1
            if self.shield_pu_counter >= self.shield_pu_counter_pin:
                for i in self.shield_pu:
                    i.update()
                    self.spaceship.check_collision_spu(self.shield_pu)
                    if i.y > 600:
                        self.shield_pu_counter = 0
                        i.x = random.randint(0, 736)
                        i.y = random.randint(-130, -60)

            if self.shield_countdown > 0 and self.shield_bool == True:
                for i in self.shield_symbol:
                    i.update(i)
                self.print_shield_counter()
                self.shield_count_timer = pygame.time.get_ticks()
                if self.shield_count_timer - self.shield_last_count > 1000:
                    self.shield_countdown -= 1
                    self.shield_last_count = self.shield_count_timer
                if self.shield_countdown <= 0:
                    self.shield_bool = False
                    self.spaceship_shield.pop()

            self.check_0_hearts()
            for heart in self.hearts:
                heart.update(heart)

            self.print_score()
            pygame.display.update()

    def change_position_g_o(self):
        for i in self.enemies:
            i.y = 1000
        for i in self.speed_enemy:
            i.y = 1000
        for i in self.boss:
            i.y = 1000

    def print_game_over(self):
        go_font = pygame.font.Font("freesansbold.ttf", 64)
        go_text = go_font.render("GAME OVER", True, (255, 255, 255))
        score_font1 = pygame.font.Font("freesansbold.ttf", 16)
        go_text_score = score_font1.render("Dein Punktestand: " + str(self.score), True, (100, 200, 10))
        self.screen.blit(go_text, (200, 250))
        self.screen.blit(go_text_score, (325, 350))


    def print_score(self):
        score_font = pygame.font.Font("freesansbold.ttf", 16)
        score_text = score_font.render("Punkte: " + str(self.score), True, (155, 200, 255))
        self.screen.blit(score_text, (8, 8))

    def check_0_hearts(self):
        if len(self.hearts) <= 0:
            self.change_position_g_o()
            self.print_game_over()
            for i in self.hpu:
                i.powerup = False

    def print_shield_counter(self):  # countdown
        countdown_font = pygame.font.Font("freesansbold.ttf", 32)
        countdown_text = countdown_font.render(str(self.shield_countdown), True, (255, 255, 255))
        self.screen.blit(countdown_text, (20, 50))


########################################################################################################################


class Spaceships:

    def __init__(self, game, x, y, spaceship_img):
        self.x = x  # 8
        self.y = y  # 8
        self.change_y = 60  # 15.2 # 10
        self.game = game
        self.change_x = 5
        self.spaceship_img = pygame.image.load(spaceship_img)  # 9
        self.change_x_spaceship = 0
        self.change_y_spaceship = 0

    def fire_bullet(self, list_bullet_object, bullet_img, bullet_object):  # 13
        list_bullet_object.append(bullet_object(self.game, self.x, self.y, bullet_img))
        list_bullet_object[-1].fired()  # 13.2

    def move_y(self, speed):
        self.change_y_spaceship += speed

    def move(self, speed):  # 10.2
        self.change_x_spaceship += speed

    def check_collision_player_bullet(self, list_object, present_lives, total_enemy_lives):
        for bullet in list_object:
            distance = math.sqrt(math.pow(self.x - bullet.x, 2) + math.pow(self.y - bullet.y, 2))
            if distance < 35:
                bullet.is_fired = False
                present_lives.pop()
                if len(present_lives) == 0:
                    self.game.score += total_enemy_lives
                    self.x = random.randint(0, 736)
                    self.y = random.randint(-130, 60)
                    for i in range(total_enemy_lives):
                        present_lives.append(total_enemy_lives)
#ToDo###############################################################################################################################################################
    def check_collision_between_aliens(self, list_object):
        for bullet in list_object:
            distance = math.sqrt(math.pow(self.x - bullet.x, 2) + math.pow(self.y - bullet.y, 2))
            if distance < 35:
                bullet.x = 

#ToDo###############################################################################################################################################################
    def update(self, change_x, change_y):
        self.x += self.change_x  # 15.2
        if self.x >= 736:
            self.change_x = - change_x
            self.y += change_y
        elif self.x <= 0:
            self.y += change_y
            self.change_x = + change_x
        self.game.screen.blit(self.spaceship_img, (self.x, self.y))

    def check_collision_enemy(self, list_object):
        for enemy in list_object:  # 21
            distance = math.sqrt(math.pow(self.x - enemy.x, 2) + math.pow(self.y - enemy.y, 2))
            if (distance - self.game.pixel / 2) < 35:
                enemy.x = random.randint(0, 736)
                enemy.y = random.randint(-130, -60)
                if self.game.shield_bool == False:
                    self.game.hearts.pop()
                else:
                    pass
                self.game.check_0_hearts()
            # elif (distance - self.game.pixel/2) < 35 and ShieldPU.powerups():
            # print("")


############################################################################


class Spaceship(Spaceships):

    def update(self, change_x, change_y):  # 11
        self.x += self.change_x_spaceship  # 10.3
        self.y += self.change_y_spaceship
        if self.x < 0:  # 12
            self.x = 0
        elif self.x > 736:
            self.x = 736
        elif self.y < 0:
            self.y = 0
        elif self.y > 536:
            self.y = 536
        self.game.screen.blit(self.spaceship_img, (self.x, self.y))  # 9

    def check_collision_hpu(self, list_object):
        for pu in list_object:  # Health- PowerUp auf kollision checken
            distance = math.sqrt(math.pow(self.x - (pu.x - 13), 2) + math.pow(self.y - (pu.y - 10), 2))
            if distance < 35:
                if len(self.game.hearts) == 2:  # Wenn 2 Herzen: an letzter Stelle hinzufügen und hpu entfernen
                    self.game.hpu.pop()
                    self.game.hearts.append(Hearts(self.game, 52, 30, "heart.png"))
                    self.game.hpu.append(
                        HealthPowerUp(self.game, random.randint(0, 736), random.randint(-130, -60), "passion.png"))
                    self.game.counter = 0
                if len(self.game.hearts) == 1:
                    self.game.hpu.pop()
                    self.game.hearts.append(Hearts(self.game, 36, 30, "heart.png"))
                    self.game.hpu.append(
                        HealthPowerUp(self.game, random.randint(0, 736), random.randint(-130, -60), "passion.png"))
                    self.game.counter = 0

    def check_collision_spu(self, list_object):
        for pu in list_object:  # shield- PowerUp auf kollision checken
            distance = math.sqrt(math.pow(self.x - (pu.x - 13), 2) + math.pow(self.y - (pu.y - 10), 2))
            if distance < 35:
                list_object.pop()
                self.game.spaceship_shield.append(ShieldSpaceship(self.game, self.x, self.y, "shield.png"))
                self.game.shield_bool = True
                # start timer

    def check_collision_enemy_bullet(self, list_object):
        for bullets in list_object:
            distance = math.sqrt(math.pow(self.x - bullets.x, 2) + math.pow(self.y - bullets.y, 2))
            if distance < 35:
                bullets.is_fired = False
                if self.game.shield_bool == False:
                    self.game.hearts.pop()
                    self.game.check_0_hearts()
                else:
                    pass


########################################################################################################################
# Powerup classes

class PowerUps:

    def __init__(self, game, x, y, powerup_img):
        self.x = x
        self.y = y
        self.change_y = 5
        self.game = game
        self.powerup_img = pygame.image.load(powerup_img)
        self.powerup = False

    def powerups(self):
        self.powerup = True

    def update(self):
        self.y += self.change_y
        self.game.screen.blit(self.powerup_img, (self.x, self.y))


class HealthPowerUp(PowerUps):
    pass


class DoubleShootPU(PowerUps):
    pass


class ShieldPU(PowerUps):
    pass


class Hearts:
    def __init__(self, game, x, y, image):
        self.x = x
        self.y = y
        self.game = game
        self.heart = True  #################################################################################################################################################
        self.img = pygame.image.load(image)

    def heart(self):
        self.heart = True

    def update(self, object):
        self.game.screen.blit(self.img, (object.x, object.y))


class ShieldSymbol(Hearts):
    pass


class ShieldSpaceship(Hearts):
    pass


############################################################################
# Enemy-Classes

class SpeedEnemy(Spaceships):
    pass


class Boss(Spaceships):
    pass


class Enemy(Spaceships):  # 15
    pass


########################################################################################################
# Bullet Classes

class Bullet:  # 13
    def __init__(self, game, x, y, bullet_img):
        self.x = x
        self.y = y
        self.is_fired = False
        self.bullet_speed = 10
        self.game = game
        self.bullet_img = pygame.image.load(bullet_img)

    def fired(self):  # 13.2
        self.is_fired = True

    def bullet_update(self):
        self.y -= self.bullet_speed  # 14
        if self.y < -20:
            self.is_fired = False
        self.game.screen.blit(self.bullet_img, (self.x + 30, self.y))


class SpeedBullet(Bullet):
    def bullet_update(self):
        self.y += self.bullet_speed
        if self.y > 600:
            self.is_fired = False
        self.game.screen.blit(self.bullet_img, (self.x + 30, self.y))


if __name__ == "__main__":
    game = Game(800, 600)

# if len(enemy.bullets) > 0:
# unnötiger check, for loop läuft ja nur bei größer 0
# if bullet.fired(): # falscher check hier


# die update methode wird nur alle 10 ticks aufgerufen. das geht nicht


# unnötige if. for loop läuft nur wenn mehr als 0
# if len(self.spaceship.bullets) > 0:

Wired1.0.
User
Beiträge: 31
Registriert: Montag 23. Januar 2023, 20:25

Ps: ja ich weis, der code sieht aus wie der Fußboden nach ner Schießerei. Die "Optik" machen ich zum schluss
Benutzeravatar
grubenfox
User
Beiträge: 414
Registriert: Freitag 2. Dezember 2022, 15:49

Wired1.0. hat geschrieben: Montag 20. März 2023, 13:57 Ich programmiere gerade space invaders und ärgere mich darüber, dass sich die Aliens überlappen. Kann mir da evtl jemand weiterhelfen?
Wann überlappen sie sich? Bei der Initialisierung oder später im Flug oder beides?
Benutzeravatar
__blackjack__
User
Beiträge: 13007
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Wired1.0.: Da ist ein Syntaxfehler drin, das kommt nicht am Compiler vorbei.

Die `__init__()`-Methode ist dazu da ein Objekt zu initialisieren, so dass man das nach Ablauf des Codes in dieser Methode verwenden kann. Da gehört kein Code rein der ”ewig” läuft, also insbesondere nicht das Hauptprogramm/die Hauptschleife.

40 Attribute sind *viel* zu viel, das kann sich kein Mensch merken was es da so alles gibt, und das ist im Grunde ein Programm mit globalen Variabelen die in eine Klasse verschoben wurden, womit das vom Wesen her immer noch globale Variablen sind, also etwas was man nicht verwendet.

Und das ist auch keine Optik. Überhaupt „Optik mache ich zum Schluss“ ist Unsinn, denn das wird dann meistens doch nicht gemacht. Es geht ja nicht darum das etwas ”schön” aussieht, zum Selbstzweck, sondern das es leicht lesbar und verständlich ist, weil dann weniger Fehler gemacht werden, und Fehler leichter gefunden werden können, und auch Änderungen und Erweiterungen leichter sind. Und falls man Probleme hat und andere Leute reinschauen lässt, auch darum ob die überhaupt Lust haben sich das anzuschauen wenn es unnötig schwer zu verstehen ist.

Bei den Klassen ist der Name `Spaceships` falsch, weil die nur *ein* Raumschiff modelliert und es ist komisch das da mehrere Klassen von abgeleitet werden, deren Klassenkörper nur ``pass`` also gar nichts enthält.

`i` ist ein *ganz* schlechter Name für alles was keine ganze Zahl ist die einen Indexwert darstellt, insbesondere wenn das das dann auch noch eine Laufvariable ist.

`pygame` kennt Sprites und Spritegruppen.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
grubenfox
User
Beiträge: 414
Registriert: Freitag 2. Dezember 2022, 15:49

ja, am besten erst mal aufräumen und umorganisieren... dann sieht man vielleicht auch besser eventuelle verbleibende Fehler.
Die ganzen Methoden mit `collision` im Namen kann man doch sicherlich vereinfachen oder durch etwas andere ersetzen. Zur Kollisionserkennung gibt es doch in pygame schon einen ganzen Schwung an Methoden: von pygamepygame.sprite.spritecollide bis pygame.sprite.spritecollideany
Für den Rest finden sich vermutlich auch noch Vereinfachungen...

https://www.pygame.org/docs/tut/SpriteIntro.html
Wired1.0.
User
Beiträge: 31
Registriert: Montag 23. Januar 2023, 20:25

grubenfox hat geschrieben: Montag 20. März 2023, 14:26
Wired1.0. hat geschrieben: Montag 20. März 2023, 13:57 Ich programmiere gerade space invaders und ärgere mich darüber, dass sich die Aliens überlappen. Kann mir da evtl jemand weiterhelfen?
Wann überlappen sie sich? Bei der Initialisierung oder später im Flug oder beides?
Leider beides. Ich hänge dir mal ein Video an:
https://www.transfernow.net/dl/20230320XZUma2Xr
Wired1.0.
User
Beiträge: 31
Registriert: Montag 23. Januar 2023, 20:25

Ok dann mache ich mich erstmal ans aufräumen
imonbln
User
Beiträge: 149
Registriert: Freitag 3. Dezember 2021, 17:07

Ich würde auch sagen, mach dich erstmals ans Aufräumen/Refactoring

1.) deine Games Klasse ist zu Omnipotent. Sie erfüllt das Antipattern eines Gott-Objekts.

2.) Versuche Variablen sinnvoll zu kapseln, die Variable enemies sollte ein Objekt sein, dass alle Aspekte der Gegner modelliert, dazu gehören definitiv auch speed_enemy, speed_enemy_bullet_list, enemy_shoot_counter, speed_enemy_lives. Ähnliche Objekte sollten auch für die anderen Dinge wie zum Beispiel Player, Schilde etc, geschaffen werden.

3.) Code wird öfter gelesen als geschrieben, Variablen wie shield_pu erscheinen dir vielleicht Sinnvoll, aber ein Leser versteht nur Bahnhof. Sprechende Namen helfen anderen, das Konzept schneller zu verstehen und gute IDEs bieten dir Autovervollständigung an.

4.) Der While Loop in der __init__ Games, ist eine Designkatastrophe, diese solltest du schnell loswerden. Die Konsequenz aus diesem Loop ist das, dass Games Objekt erst nach Beendigung des Spiels voll initialisiert ist.
Du missbrauchst also das Erzeugen des Game-Objekts als run-loop, was dazu führt, dass Game eigentlich kein Objekt mehr ist nach OOP, sondern eher eine Art Namespace wird. Klassen sollten in Ihrer __init__ Methode das passende Objekt erzeugen (möglichst vollständig) oder eine geeignete Exception werfen, nicht mehr, aber auch nicht weniger.

5.) Dass die Klasse Spaceship von der Basisklasse Spaceships erbt, tut weh!
Zum einen, weil es wieder dafür sorgt, dass man immer ganz genau lesen muss, ob das Objekt jetzt Singular oder Plural ist und zum anderen, weil es nach dem allgemeinen Vererbung-Verständnis komisch ist. Die Basisklasse soll das allgemeine Verhalten beschreiben, die geerbte Klasse die Spezialisierung für einen bestimmten Fall. Meine Erwartung wäre das es eine Klasse BasisSpaceShip gibt (oder einen anderen Namen) und das davon dann mehre Klassen erben. EnemySpaceShip, BossSpaceShip, PlayerSpacShip und so weiter. Bei den Plural Spaceships, wäre meine Erwartung das es einfach Sammlung von mehreren Objekten der Basisklasse Spaceship ist. Ob es sich dabei um ein Dictionary, eine Liste oder ein wie auch immer selbst implementiertes Objekt handelt, sei mal dahingestellt.

6.) Das Klasse Powerups eine Methode Powerups hat ist Komisch. Als Daumenregel, wenn du sagen kannst "ist ein", handelt es sich um eine Klasse. Wenn du sagen kannst "hat ein" um eine methode. "Powerup hat ein powerup", ist keine Erklärung die ein Leser hilft das Konzept der Klasse zu verstehen.

7.) Vererbung ist kein Selbstzweck Sowohl HealthPowerUp, DoubleShootPU, ShieldPU als auch ShieldSymbol, ShieldSpaceship fügen Ihrer Basisklasse keine Eigenschaften hinzu. Man macht sowas zwar gelegentlich, um eigne Exceptions zu erzeugen, aber eigentlich das immer die gleichen Objekte, das Umbenennen bringt kaum Mehrwert. vielleicht solltest du stattdessen ein Enum mit den PowerUps-Arten erzeugen und dann diese Information was für ein PowerUp es ist in der __init__ Methode an die Klasse übergeben. Die Klasse kann das dann als attribute Speichern.
Wired1.0.
User
Beiträge: 31
Registriert: Montag 23. Januar 2023, 20:25

Wow vielen Dank für die nützlichen Tipps! Ich habe schon fleißig angefangen alles umzubauen (und komme leider nur langsam voran) zB möchte ich gerade die check_collision- Methoden auf max. 2 reduzieren. Aber leider wird bei der parameterübergabe das Atteibut immer ausgegraut (obwohl ich es benutze).
Bsp Code:
'''

def method_a(self, list_object, attribute, object_element)
for element in list_object:
if element.attribute.colliderect(object_element):
...

'''

Dann ist das parameter attribute immer ausgegraut und wenn ich drauf gehe dann sagt pycharm mir, dass ich das parameter nicht benutze? Wo liegt da der Fehler? Sollte ich statt attribute, element.attribute als parameter übergeben?
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

pycharm macht halt Fehler bei sowas, "wichtich is auffem Platz" wie es so schoen heisst - wenn der Code funktioniert, ist das der entscheidende Faktor.
Benutzeravatar
__blackjack__
User
Beiträge: 13007
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Wired1.0.: Zumindest in dem gezeigten Ausschnitt wird `attribute` ja auch gar nicht verwendet, da hätte PyCharm also recht. Wird es denn irgendwo in dem ...-Teil *tatsächlich* noch verwendet?
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Wired1.0.
User
Beiträge: 31
Registriert: Montag 23. Januar 2023, 20:25

__blackjack__ hat geschrieben: Donnerstag 23. März 2023, 16:28 @Wired1.0.: Zumindest in dem gezeigten Ausschnitt wird `attribute` ja auch gar nicht verwendet, da hätte PyCharm also recht. Wird es denn irgendwo in dem ...-Teil *tatsächlich* noch verwendet?
Aber ich benutze attribute doch? (Ich füge selbstverständlich stattdessen im gameloop was ein aber dann ist es trotzdem noch grau :(
Benutzeravatar
__blackjack__
User
Beiträge: 13007
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Wired1.0.: In den gezeigten drei Zeilen wird das Argument `attribute` nicht benutzt.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Wired1.0.
User
Beiträge: 31
Registriert: Montag 23. Januar 2023, 20:25

Hey habe den Code jetzt erstmal abgeändert. @__blackjack__ , @grubenfox , @__deets__ , @imonbin Ich bin zwar noch lange nicht fertig aber ich komme an einer Stelle absolut nicht weiter (auch wenn ich mir sicher bin, dass es bestimmt komplett easy zu lösen ist) evtl kann mir da jmd von euch helfen

Also dass ist erstmal der aktuelle Code:

Code: Alles auswählen

#####################################################23.03.2023####################################################

import pygame
import random

# ToDo
# - Nur ein enemy bei kollision --> bei remove wenn level implementiert
# - level implementieren
# - bei terminierung kleine explosion
# - Aliens sollen sich nicht überlappen
# - bosse grüner laserstrahl
# - t- fighter schießen 2 schuss auf einmal
# - bei Mauskick schießen
# - Vollbild implementieren
# - Pause implementieren
# - wenn alle 3 herzen weg, spaceship weg, riesen explosion, game over
# - class SpeedShootPU(PowerUps):
# - doube shoot PU erstellen
# ToDo morgen:
# shoot nur auf speed bezogen

class Game:
    def __init__(self, width, height):
        pygame.init()
        self.width = width  # 7
        self.height = height  # 7
        self.screen = pygame.display.set_mode((self.width, self.height))  # 7
        pygame.display.set_caption("Space Invaders")  # 5
        self.running = True  # 4
        self.clock = pygame.time.Clock()  # 6
        self.start_time = pygame.time.get_ticks()
        # Objekte
        self.spaceship = Spaceship(self, 368, 515, "battleship.png", 3, 0, 0, 0)  # 8
        self.background_img = pygame.image.load("background123.peg").convert()  # 20
        self.heart_lives = Hearts(self, 16, 30, "heart.png")
        self.shield_from_spaceship = ShieldSpaceship(self, self.spaceship.enemy_object_rect.x,
                                                     self.spaceship.enemy_object_rect.y, "shield.png")

        self.background_img = pygame.transform.scale(self.background_img, (width, height))

        self.hearts = []
        self.enemies = []  # 15
        self.player_bullet_list = []
        self.speed_enemy_bullet_list = []
        self.score = 0
        self.enemy_shoot_counter = 0  # present lives = 0

        # shield-Attributes
        self.total_seconds = 7
        self.shield_bool = False
        self.shield_symbol = ShieldSymbol(self, 20, 50, "shield_pu.png")  # muss noch eingefügt werden.

        self.hearts.append(Hearts(self, 20, 30, "heart.png"))
        self.hearts.append(Hearts(self, 36, 30, "heart.png"))
        self.hearts.append(Hearts(self, 52, 30, "heart.png"))

        self.powerups = []
        for i in range(1):
            self.powerups.append(ShieldPU(self, random.randint(0, 736), random.randint(-130, -60), "shield_pu.png"))
            self.powerups.append(HealthPowerUp(self, random.randint(0, 736), random.randint(-130, -60), "passion.png"))
        self.powerup_choice = random.choice(self.powerups)

        for i in range(0):
            self.enemies.append(Enemy(self, random.randint(0, 736), random.randint(-130, -60), "ufo.png", 1, 5, 5, 60))

        for i in range(1):
            self.enemies.append(Boss(self, 50, 50, "death-star.png", 3, 5, 5, 60))

        for i in range(1):  # 15
            self.enemies.append(SpeedEnemy(self, random.randint(0, 736), random.randint(-130, -60), "t-fighter.png", 2, 10, 10, 60))     # 15

        while self.running:  # 4
            self.clock.tick(60)  # 6 setzt die FPS

            # Beweglicher Bildschirm
            self.rel_y = height % self.background_img.get_rect().height  # 20
            self.screen.blit(self.background_img, (0, self.rel_y - self.background_img.get_rect().height))
            if self.rel_y < height:
                self.screen.blit(self.background_img, (0, self.rel_y))
            height += 1

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.running = False
                if event.type == pygame.KEYDOWN:  # 10
                    if event.key == pygame.K_LEFT or event.key == pygame.K_a:
                        self.spaceship.move(-10)  # 10.4
                    if event.key == pygame.K_SPACE:  # 13
                        self.spaceship.fire_bullet(self.player_bullet_list, "laser.png", Bullet)
                    if event.key == pygame.K_RIGHT or event.key == pygame.K_d:
                        self.spaceship.move(10)
                    if event.key == pygame.K_UP or event.key == pygame.K_w:
                        self.spaceship.move_y(-10)
                    if event.key == pygame.K_DOWN or event.key == pygame.K_s:
                        self.spaceship.move_y(10)

                if event.type == pygame.KEYUP:  # 10.5
                    if event.key == pygame.K_LEFT or event.key == pygame.K_a:
                        self.spaceship.move(10)
                    if event.key == pygame.K_RIGHT or event.key == pygame.K_d:
                        self.spaceship.move(-10)
                    if event.key == pygame.K_UP or event.key == pygame.K_w:
                        self.spaceship.move_y(10)
                    if event.key == pygame.K_DOWN or event.key == pygame.K_s:
                        self.spaceship.move_y(-10)

# Todo##########################################################Zusammen#####################################################

            for bullet in self.speed_enemy_bullet_list:     # Enemy shoot
                if bullet.is_fired:
                    bullet.bullet_update(10)
                    self.spaceship.check_collision_enemy_objects(self.spaceship, bullet.bullet_rect, self.hearts, self.speed_enemy_bullet_list)
                else:
                    self.speed_enemy_bullet_list.clear()

            for bullet in self.player_bullet_list:  # 13.3
                if bullet.is_fired:
                    bullet.bullet_update(-10)
                else:  # 14.1
                    self.player_bullet_list.remove(bullet)
# Todo##########################################################Zusammen#####################################################

            for enemy in self.enemies:
                enemy.check_collision_enemy_objects(self.spaceship, enemy.enemy_object_rect, self.hearts, self.speed_enemy_bullet_list)
                enemy.check_collision_player_bullet(enemy.enemy_object_rect, self.player_bullet_list)
                enemy.update()
                if self.enemy_shoot_counter >= 100:               # t-fighter shoot back
                    enemy.fire_bullet(self.speed_enemy_bullet_list, "laser_grey.png", SpeedBullet)
                    self.enemy_shoot_counter = 0

            for heart in self.hearts:
                heart.update(heart.enemy_object_rect.x, heart.enemy_object_rect.y)

            if len(self.hearts) < 3:        # 23 Health PowerUp einfügen
                self.powerup_choice.update_pu(self.total_seconds, self.powerup_choice, self.hearts, self.spaceship, self.shield_from_spaceship, self.heart_lives, self.powerups)
            self.current_time = pygame.time.get_ticks()
            if self.shield_bool:     # Countdown
                if self.current_time - self.start_time > 1000:
                    self.total_seconds -= 1
                    self.start_time = self.current_time
                if self.total_seconds <= 0:
                    self.shield_bool = False  # stop timer
                    self.total_seconds = 7

            self.enemy_shoot_counter += 1
            self.spaceship.update_spaceship()  # 9
            self.change_position_g_o(self.hearts, self.speed_enemy_bullet_list)
            self.print_score()
            pygame.display.update()

    def change_position_g_o(self, hearts, enemy_bullet_list):
        if len(hearts) == 0:
            for i in self.enemies:
                i.enemy_object_rect.y = 1000
            self.print_game_over()
            for i in enemy_bullet_list:
                i.is_fired = False

    def print_game_over(self):
        go_font = pygame.font.Font("freesansbold.ttf", 64)
        go_text = go_font.render("GAME OVER", True, (255, 255, 255))
        score_font1 = pygame.font.Font("freesansbold.ttf", 16)
        go_text_score = score_font1.render("Dein Punktestand: " + str(self.score), True, (100, 200, 10))
        self.screen.blit(go_text, (200, 250))
        self.screen.blit(go_text_score, (325, 350))

    def print_score(self):
        score_font = pygame.font.Font("freesansbold.ttf", 16)
        score_text = score_font.render("Punkte: " + str(self.score), True, (155, 200, 255))
        self.screen.blit(score_text, (8, 8))


class Hearts(pygame.sprite.Sprite):
    def __init__(self, game, x, y, image):
        pygame.sprite.Sprite.__init__(self)
        self.x = x
        self.y = y
        self.game = game
        self.bool = True
        self.bool2 = True
        self.img = pygame.image.load(image)
        self.enemy_object_rect = self.img.get_rect(midbottom=(x, y))
        self.img_copy = self.img.copy()
        self.copy_img_copy = self.img_copy.copy()

    def heart(self):
        self.bool = True

    def append_heart(self, list_object, vectorx, vectory):
        list_object.append(Hearts(self.game, vectorx, vectory, "heart.png"))

    def update(self, vectorx, vectory):
        self.game.screen.blit(self.img, (vectorx, vectory))


class ShieldSymbol(Hearts):
    pass


class ShieldSpaceship(Hearts):
    def update_shield(self, vector, total_seconds):
        if self.game.shield_bool:
            self.game.screen.blit(self.img, (vector.x, vector.y))
            if total_seconds > 0:
                self.print_shield_counter(total_seconds)

    def print_shield_counter(self, total_seconds):
        countdown_font = pygame.font.Font("freesansbold.ttf", 32)
        countdown_text = countdown_font.render(str(total_seconds), True, (255, 255, 255))
        self.game.screen.blit(countdown_text, (20, 50))


class HealthPowerUp(pygame.sprite.Sprite):
    def __init__(self, game, x, y, powerup_img):
        pygame.sprite.Sprite.__init__(self)
        self.x = x
        self.y = y
        self.change_y = 5
        self.game = game
        self.powerup_img = pygame.image.load(powerup_img)
        self.pu_rect = self.powerup_img.get_rect()
        self.powerup = False
        self.counter = 0
        self.pu_counter_pin = random.randint(400, 700)

    def update_pu(self, countdown, choice_object, heart_list, game_object, shield_from_spaceship, heart_lives, powerups):
        self.counter += 1
        print(self.counter)
        if self.counter >= self.pu_counter_pin:
            self.powerup = True
            if self.powerup:
                choice_object.pu_rect.y += self.change_y
                self.game.screen.blit(self.powerup_img, self.pu_rect)
        game_object.check_collision_pu(choice_object, self.game.powerup_choice.pu_rect, self.counter, countdown,
                                    heart_list, shield_from_spaceship, heart_lives, powerups)
        if self.pu_rect.y >= 600:
            choice_object = random.choice(powerups)
            choice_object.pu_rect.x = random.randint(0, 736)
            choice_object.pu_rect.y = random.randint(-130, -60)
            self.powerup = False
            self.counter -= self.counter


class ShieldPU(HealthPowerUp):
    pass


class Boss(pygame.sprite.Sprite):  # Sprite 1
    def __init__(self, game, x, y, spaceship_img, lives, speed, change_x, change_y):
        pygame.sprite.Sprite.__init__(self)
        self.x = x  # 8
        self.y = y  # 8
        self.spaceship_img = pygame.image.load(spaceship_img)  # 9
        self.enemy_object_rect = self.spaceship_img.get_rect(midbottom=(self.x, self.y))  # 1.1
        self.change_y = change_y  # 15.2 # 10
        self.game = game
        self.live = 0
        self.lives = lives
        self.speed = speed
        self.change_x = change_x

    def fire_bullet(self, list_bullet_object, bullet_img, bullet_object):  # 13
        list_bullet_object.append(bullet_object(self.game, self.enemy_object_rect.x, self.enemy_object_rect.y + 60, bullet_img))
        list_bullet_object[-1].fired()  # 13.2

    def move_y(self, speed):
        self.change_y += speed

    def move(self, speed):  # 10.2
        self.change_x += speed

    def check_collision_player_bullet(self, rect_object, player_bullet_list):
        for element in player_bullet_list:
            if element.bullet_rect.colliderect(rect_object):
                element.is_fired = False
                self.live += 1
                if self.live == self.lives:
                    self.game.score += self.lives
                    self.enemy_object_rect.x = random.randint(0, 736)
                    self.enemy_object_rect.y = random.randint(-130, 60)
                    self.live = 0

    def check_collision_enemy_objects(self, spaceship_object, list_object, hearts, bullet_list):
        if spaceship_object.enemy_object_rect.colliderect(list_object):
            list_object.x = random.randint(0, 736)
            list_object.y = random.randint(-130, -60)
            if not self.game.shield_bool:
                hearts.pop()
            else:
                pass

    def update(self):
        self.enemy_object_rect.x += self.speed  # 15.2
        if self.enemy_object_rect.x >= 736:
            self.speed = - self.speed
            self.enemy_object_rect.y += self.change_y
        elif self.enemy_object_rect.x <= 0:
            self.enemy_object_rect.y += self.change_y
            self.speed = - self.speed
        self.game.screen.blit(self.spaceship_img, self.enemy_object_rect)


class Spaceship(Boss):
    def update_spaceship(self):  # 11
        self.enemy_object_rect.x += self.change_x  # 10.3
        self.enemy_object_rect.y += self.change_y
        self.enemy_object_rect.x = min(max(self.enemy_object_rect.x, 0), 736)
        self.enemy_object_rect.y = min(max(self.enemy_object_rect.y, 0), 536)
        self.game.screen.blit(self.spaceship_img, self.enemy_object_rect)  # 9

    def check_collision_pu(self, choice_object, list_object, counter, total_seconds, heart_list, shield_from_spaceship, heart_lives, powerup_list):   # PowerUp auf kollision checke
        if self.game.spaceship.enemy_object_rect.colliderect(list_object):
            list_object.x = random.randint(0, 736)
            list_object.y = random.randint(-130, -60)
            if choice_object == self.game.powerups[1]:
                if len(heart_list) == 2:
                    heart_lives.append_heart(heart_list, heart_lives.enemy_object_rect.x + 46, 30)
                    
                elif len(heart_list) == 1:
                    heart_lives.append_heart(heart_list, heart_lives.enemy_object_rect.x + 32, 30)

            else:
                self.game.shield_bool = True  # timer
                return counter == 0
            self.game.powerup_choice = random.choice(powerup_list)
        shield_from_spaceship.update_shield(self.enemy_object_rect, total_seconds)


class SpeedEnemy(Boss):
    pass


class Enemy(Boss):  # 15
    pass


########################################################################################################
# Bullet Classes

class Bullet(pygame.sprite.Sprite):  # 13
    def __init__(self, game, x, y, bullet_img):
        pygame.sprite.Sprite.__init__(self)
        self.x = x
        self.y = y
        self.is_fired = False
        self.game = game
        self.bullet_img = pygame.image.load(bullet_img)
        self.bullet_rect = self.bullet_img.get_rect(midbottom=(self.x + 30, self.y))

    def fired(self):  # 13.2
        self.is_fired = True

    def bullet_update(self, speed): # 14
        self.bullet_rect.y += speed
        if self.bullet_rect.y < -20:
            self.is_fired = False
        self.game.screen.blit(self.bullet_img, self.bullet_rect)


class SpeedBullet(Bullet):
    pass


if __name__ == "__main__":
    game = Game(800, 600)


Und zwar ist mein momentanes Problem:
Ich habe alle Aliens in eine Liste gepackt weil es sehr Platzsparend ist (sind schonmal 2 Attribute weniger :D)
Und jetzt möchte ich natürlich die t-fighter (SpeedEnemy) die Waffen abfeuern lassen (die SpeedBullet Klasse mache ich noch weg) aber durch einen ganz normalen Aufruf der Elemente durch eine for -Schleife klappt es leider nicht mehr (jetzt feuert immer nur ein Boss- Objekt) meine Frage ist also: Wie kann ich auf die fire_bullet()-Methode nur für SpeedEnemy zugreifen ohne dafür eine separate Liste oder Attribut zu erstellen? Ich komme da einfach nicht drauf.


Und das zweite Problem: in der HealthPowerUp -Klasse habe ich mir einen counter definiert um die Häufigkeit der "aufbloppenden" powerups zu kontrollieren. Jetzt möchte ich aber wenn eine collision Stattgefunden hat (in der check_collision_pu()-Methode den counter wieder auf 0 setzen aber ich kann Ihn nicht als parameter übergeben(ist ausgegraut und wenn ich draufgehen sagt es mir, dass ich das parameter nicht verwende (funktionieren tut es auch nicjt)).

So. Sorry für das Buch :D
Benutzeravatar
__blackjack__
User
Beiträge: 13007
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Wired1.0.: Wenn Objekte unterschiedlich behandelt werden sollen, muss man sie getrennt aufbewahren. Wobei man natürlich auch fragen könnte warum auf die `fire_bullet()`-Methode von aussen zugegriffen werden muss. Das könnten die Raumschiffe auch selbst entscheiden, zum Beispiel in ihrer `update()`-Methode.

Das `__init__()` initialisiert nicht nur das `Game`-Objekt, sondern führt das gesamte Programm aus, Problem ist immer noch da. Und `game` sollte auch nicht auf Modulebene definiert sein, das gehört als lokale Variablen in eine Funktion.

`check_collision_pu()` ist komisch. Mit `counter` wird da nicht wirklich etwas gemacht und das ``return counter == 0`` macht keinen Sinn wenn `counter` übergeben wird, denn diesen Test kann der Aufrufer auch bei sich lokal machen. Zudem ist die Methode damit dann recht eigenartig was den Rückgabewert angeht: Implizites `None` oder in diesem einen Zweig dann `True` oder `False`. Was beim Aufrufer auch überhaupt nicht benutzt/ausgewertet wird.

Das ist übrigens das *einzige* ``return`` im gesamten Programm, also es gibt effektiv keine einzige Methode die etwas zurück gibt. Das ist ein bisschen komisch IMHO.

Was da alles von `Boss` erbt ist komisch. Da stellt man sich ja eher einen speziellen Endgegner vor, und *von* dem erben sicher keine normalen Gegner.

`Sprite` wird falsch verwendet. Die `update()` Methode ist dazu da den internen Zustand zu aktualisieren. Und die Objekte brauchen ein `image`- und ein `rect`-Attribut, die dann von der Sprite-Gruppe zum Zeichnen verwendet werden. Gruppen werden gar nicht verwendet.

Ich würde den Sprite-Objekten eher nicht das Spiel beim erstellen mitgeben. Das gehört nicht wirklich zum Zustand des einzelnen Sprites. Das kann man beim Aufruf von `update()` übergeben, wenn das jeweilige Schiff Zugriff auf den Spielzustand benötigt.

``for i in range(1):`` oder ``for i in range(0):`` sind offensichtlich unsinnige ”Schleifen”.

`Bullet.is_fired` ist komisch. Wenn das einmal abgefeuert ist, sehe ich logisch keine Möglichkeit das wieder rückgängig zu machen. Der Code macht das aber. Also heisst das wahrscheinlich falsch. Wenn ich das richtig sehe wird die `fired()`-Methode auch grundsätzlich aufgerufen nahezu direkt nachdem das Objekt erstellt wurde. Also ist das erstellen gleichzeitig das abfeuern, das muss man dann nicht noch mal über eine Methode die nichts anderes macht als ein Flag zu setzen, kurz danach noch mal anzeigen. Ist auch trivialer Setter der weg kann, denn selbst wenn man das so bräuchte, könnte man ja einfach das Flag setzen, statt die Methode aufzurufen.

Grunddatentypen haben nichts in Namen verloren. Während der Programmentwicklung ändert man die Typen gerne mal zu etwas spezialisierterem und dann hat man entweder falsche, irreführende Namen im Quelltext oder man muss überall betroffene Namen suchen und anpassen. Zum Beispiel gehören Sprites in Gruppen und damit wären dann Namen wie `player_bullet_list` falsch.

`enemy_object_rect` scheint mir auch als Name überall falsch. Das ist ja nicht das Rect von einem Feind von dem Objekt sondern das Rect von dem Objekt selbst. Das `Spaceship` ist ja der Spieler und ein Feind davon wäre nicht das `Spaceship` selbst. Und auch bei den Feind ist der Name für dieses Attribut irreführend, denn ein `enemy_object_rect`-Attribut *auf* einem Feind würde ja eigentlich den Spieler meinen, denn *der* ist ja der Feind vom Feind.

Namentlich verwirrend finde ich auch `ShieldSpaceship` und das Attribut `Game.shield_from_spaceship`. Ein „Schildraumschiff“ ist etwas anderes als ein „Raumschiff-Schild“ und `shield_from_spaceship` wäre eher `shield_of_spaceship`.

Ein `Hearts`-Objekt repräsentiert wie viele Herzen? `image` ist ein guter Name für ein Bild, also beispielsweise ein `Surface`-Objekt, aber nicht für einen Bild*dateinamen*. Und das Bild selbst sollte dann nicht kryptisch `img` heissen. `bool` und `bool2` sind keine guten Namen für Attribute auf `Hearts` weil die nichts darüber aussagen was die Werte *bedeuten*. Ausser das eines davon in einer `Hearts.heart()`-Methode (häh?) auf `True` gesetzt wird, also den Wert, den es sowieso schon hatte, werden diese Attribute auch nirgends verwendet. `img_copy` und `copy_img_copy` für eine Kopie von `img` und `img_copy` als Attribute, die dann ebenfalls nirgends verwendet werden, ist auch extrem verwirrend.

Bei der Ereignisverarbeitung sind einige Gelegenheiten für ``elif`` weil dort Bedingungen geprüft werden, die sich gegenseitig ausschliessen.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Wired1.0.
User
Beiträge: 31
Registriert: Montag 23. Januar 2023, 20:25

@__blackjack__ bester Mann dank dir!
Die bool- Werte in hearts habe ich, weil ich eigentlich noch die hearts-liste rausmachen will, und dann immer eine Kopie vom ersten Herz erstellen will wenn der Wert auf True ist. Kann man bestimmt auch etwas einfacher machen, war aber erstmal der erste Gedanke für die Umsetzung.
Wired1.0.
User
Beiträge: 31
Registriert: Montag 23. Januar 2023, 20:25

Hey, ich habe noch eine Frage @__blackjack__.

Bsp Code:


Code: Alles auswählen




def create_object(obj, objectx, objecty, image):
    return obj(objectx, objecty, image)


powerup = create_object(random.choice([HealthPowerUp, ShieldPowerUp, DoubleShootPowerUp]), random.randint(0, 736), random.randint(-130, -60), if obj=HealthPowerUp: image="passiion.png")



Und zwar möchte ich für den image-Teil für jedes Powerup ein anderes Bild wählen (also wenn choice= Health: "pasdion.png", wenn DoubleShoot: "fired.png",... Gibt es dafür eine Möglichkeit?
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dann mach einen choice von Tupeln, Klasse und Bild. Oder platzier das Bild als Klassenvariable in HealthPowerup & Co.
Wired1.0.
User
Beiträge: 31
Registriert: Montag 23. Januar 2023, 20:25

@__deets__ Wie meinst du das mit methode 1? Habe ich nicht richtig verstanden.
An methode 2 hatte ich auch schon gedacht aber ich versuche gerade auf weitere Attribute zu verzichten.
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Warum? Hast du ein beschraenktes Kontingent von Attributen? Wenn die Zuordnung von Klasse zu Bild immer gleich bleibt, ist ein Attribut der bessere Entwurf. Die auswahl aus Tupeln ist nur dann besser, wenn man das getrennt handhaben will.

Code: Alles auswählen

random.choice([("a", 1), ("a", 2), ("b", 3)]
Da kann dann a wahlweise mit 1 oder 2 ankommen. Doch selbst das ist im Zweifel schlechter, weil getrennt von sowas:

Code: Alles auswählen

class A:
    IMAGES = [1, 2] # moegliche Darstellungen
   def __init__(self):
        self._image = random.choice(self.IMAGES)
Antworten