Kivy太空侵略者游戏多敌人创建问题求助
Hey there! I see you're stuck on adding multiple enemies without repeating code—let's fix that by using a list to manage all your enemies instead of handling each one individually. Here's a step-by-step solution that refactors your existing code:
1. Refactor the Enemy Class
First, let's clean up the collision logic. Each enemy only needs to handle its own collision with the ball, so we don't need to pass other enemy instances as arguments. We'll also fix the ball's reset logic to make more sense:
from kivy.uix.widget import Widget from random import randint class Enemy(Widget): def handle_collision(self, ball, game): if self.collide_widget(ball): # Reset this enemy to a random top position self.y = randint(300, 500) self.x = randint(2, game.width - 64) # Reset ball off-screen (you can adjust this to return to the ship later) ball.x = -1000 ball.y = -1000
2. Update the Main Game Class
We'll replace the duplicate enemy properties with a list to hold all enemies. All movement and collision logic will now loop through every enemy in the list:
from kivy.uix.widget import Widget from kivy.properties import ObjectProperty, NumericProperty from kivy.clock import Clock class SpaceGame(Widget): ball = ObjectProperty(None) ship = ObjectProperty(None) x_change = NumericProperty(3) y_change = NumericProperty(-50) enemy_list = [] # List to store all enemy instances def __init__(self, **kwargs): super().__init__(**kwargs) # Spawn initial enemies (adjust the number to your liking) self.spawn_enemies(5) def spawn_enemies(self, count): for _ in range(count): new_enemy = Enemy() new_enemy.x = randint(2, self.width - 64) new_enemy.y = randint(300, 550) self.enemy_list.append(new_enemy) self.add_widget(new_enemy) def enemy_movement(self): for enemy in self.enemy_list: enemy.x -= self.x_change # Handle right boundary hit if enemy.x >= self.width - 64: self.x_change = -3 self._move_all_enemies_down() # Handle left boundary hit elif enemy.x <= 0: self.x_change = 3 self._move_all_enemies_down() # Trigger game over if any enemy reaches the bottom elif enemy.y < 0: print('Game Over') Clock.unschedule(self.update) def _move_all_enemies_down(self): # Shift every enemy down once when the group hits a side for enemy in self.enemy_list: enemy.y += self.y_change def update(self, dt): self.enemy_movement() # Check collision between ball and each enemy every frame for enemy in self.enemy_list: enemy.handle_collision(self.ball, self)
3. Adjust the KV File
We'll remove the hardcoded Enemy instance since we're spawning enemies dynamically in the game class. Keep your existing ball and ship definitions:
<Enemy>: size: 64,64 canvas: Rectangle: pos:self.pos size: self.size source:'alien.png' <SpaceGame>: ball: pong_ball ship: space_ship # Keep your existing ball and ship widgets here Ball: id: pong_ball # ... your ball properties and logic ... Ship: id: space_ship # ... your ship properties and logic ...
4. Fix the App Class
You had a small typo here (PongGame instead of SpaceGame)—let's correct that:
from kivy.app import App class SpaceApp(App): def build(self): game = SpaceGame() Clock.schedule_interval(game.update, 1.0/60.0) return game SpaceApp().run()
Key Changes Explained
- Enemy List: Instead of hardcoding individual enemies, we use
enemy_listto store all instances. Adding more enemies is as simple as callingspawn_enemies(10)—no duplicate code needed. - Loop Through Enemies: All movement and collision logic now iterates over every enemy in the list, so every enemy gets updated each frame.
- Centralized Downward Movement: When any enemy hits a side, we shift the entire group down at once, matching classic Space Invaders behavior.
Now you can spawn as many enemies as you want with a single function call—no more repetitive code!
内容的提问来源于stack exchange,提问作者Lalli Garden

