Als developer, wil ik elke vijand als één eigen object bijhouden in plaats van in losse, parallelle lijsten, zodat de x, y en snelheid van één vijand nooit meer uit elkaar kunnen lopen doordat ik een van de lijsten vergeet bij te werken.
Een blauwdruk maakt zoveel objecten als je wilt, en elk houdt zijn eigen status bij. Een hele vijandengolf wordt een lijst van objecten. Vijand 5 als neergeschoten markeren doet niets met vijand 6 — precies wat parallelle lijsten niet konden garanderen. En met de meegeleverde game-engine zie je die golf voor het eerst écht op je scherm vallen.
Je maakt meerdere objecten aan en stopt ze in een lijst. Elk object houdt zijn eigen status bij:
measurements = [
Measurement("height", 120),
Measurement("temp", 34),
Measurement("battery", 87),
]
measurements[0].logged = True # alleen de eerste meting
print(measurements[0].logged) # True
print(measurements[1].logged) # False — ongemoeid
Je verandert de status van precies één object. De rest blijft zoals hij was. Er is geen tweede lijst die je ook moet bijwerken — de status leeft in het object zelf.
enemy_x, enemy_speed en alive per index synchroon
blijven. Nu draagt elk object alles zelf, waardoor verschuiven niet meer mogelijk is. Invoegen,
verwijderen of herordenen: de status gaat gewoon mee.
Hieronder staat een route van vijf objecten uit dezelfde blauwdruk. Klik op een kaart om die stap als uitgevoerd te markeren. Let op: alleen die ene kaart verandert.
step.executed = True te zetten.
Een lijst measurements ligt klaar met drie Measurement-objecten (elk met
logged = False). Bewijs dat ze onafhankelijk zijn.
measurements[0].logged — startstatus.measurements[0].logged = True — markeer de eerste.measurements[0].logged en measurements[1].logged — vergelijk.measurements[1].kind — welke meting is dat?len(measurements) — hoeveel objecten zijn er?Gebruik je Enemy-class uit taak 2 en bouw er een hele golf mee — en zie hem vallen.
Zet game_engine.py naast je script (en installeer eenmalig pygame, zie hieronder).
Enemy-objecten met een willekeurige x
(gebruik random.randint) en verschillende snelheden.Player (een object met x, y,
width, height, color en speed).run_game(player, enemies) aan uit game_engine en kijk hoe de
zwerm valt en bovenaan herspawnt. Bestuur de speler met de pijltjestoetsen.alive = False en tel met een
for-loop hoeveel er nog "leven"; print dat aantal.Let op: y telt naar
beneden, dus vijanden vallen met een positieve snelheid. Kleuren zijn RGB-tuples zoals
(255, 80, 80). Sluit het venster met de vensterknop.
Nodig: download game_engine.py en zet hem in dezelfde map als je script (installeer eenmalig pygame: pip install pygame). Kun je niet downloaden? Klap de code uit en kopieer hem naar game_engine.py.
"""
game_engine.py - Arcade-engine voor Sprint 6 (v1, ATTRIBUUT-gebaseerd). NIET AANPASSEN.
Jij schrijft de classes; deze engine opent het venster, draait de game-loop,
leest de ATTRIBUTEN van jouw objecten en tekent ze als rechthoeken. Jouw classes
zijn dus pure data; de engine verzorgt alle beweging en het tekenwerk.
--------------------------------------------------------------------------
HET CONTRACT - wat de engine van jouw objecten verwacht:
player - een object met:
x, y (int) positie van de linkerbovenhoek
width (int) breedte in pixels
height (int) hoogte in pixels
color (tuple) RGB, bijvoorbeeld (0, 200, 255)
speed (int) pixels die de speler per toetsstap opschuift
health (int) OPTIONEEL - levens; bij 0 stopt het spel
enemies - een LIJST objecten, elk met:
x, y, width, height, color (zoals hierboven)
speed (int) pixels die deze enemy per frame ZAKT
world - OPTIONEEL (US4 + project) - een object met:
player, enemies, bullets, score, width, height
bullet_factory(player) -> bullet - OPTIONEEL, een gewone functie die een
nieuw bullet-object teruggeeft met: x, y, width, height, color, speed
(speed = pixels die de kogel per frame OMHOOG gaat)
y telt naar BENEDEN: y groter = lager op het scherm. Vijanden vallen dus met
een POSITIEVE speed; kogels gaan omhoog. Kleuren zijn RGB-tuples, geen strings.
--------------------------------------------------------------------------
"""
import random
import pygame
def _overlap(a, b):
"""True als twee rechthoeken (objecten met x/y/width/height) elkaar raken."""
return (a.x < b.x + b.width and a.x + a.width > b.x and
a.y < b.y + b.height and a.y + a.height > b.y)
def run_game(player, enemies, width=480, height=640, fps=60,
world=None, bullet_factory=None):
pygame.init()
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Sprint 6 - Arcade Dodge")
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 28)
bullets = getattr(world, "bullets", []) if world is not None else []
running = True
while running:
# 1) Vensterknop / afsluiten en schieten
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
if bullet_factory is not None:
bullets.append(bullet_factory(player))
# 2) Toetsen lezen -> speler-attribuut aanpassen
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
player.x -= player.speed
if keys[pygame.K_RIGHT]:
player.x += player.speed
player.x = max(0, min(player.x, width - player.width))
# 3) Vijanden laten vallen; onderaan -> herspawnen bovenaan
for enemy in enemies:
enemy.y += enemy.speed
if enemy.y > height:
enemy.y = -enemy.height
enemy.x = random.randint(0, width - enemy.width)
if world is not None:
world.score += 1
# 4) Kogels omhoog; buiten beeld -> weg
for bullet in bullets:
bullet.y -= bullet.speed
bullets[:] = [b for b in bullets if b.y + b.height > 0]
# 5) Botsing - kogel raakt vijand
for bullet in bullets:
for enemy in enemies:
if _overlap(bullet, enemy):
enemy.y = -enemy.height
enemy.x = random.randint(0, width - enemy.width)
bullet.y = -100
if world is not None:
world.score += 5
# 6) Botsing - vijand raakt speler
for enemy in enemies:
if _overlap(player, enemy):
enemy.y = -enemy.height
enemy.x = random.randint(0, width - enemy.width)
if hasattr(player, "health"):
player.health -= 1
if player.health <= 0:
running = False
# 7) Tekenen (alles als rechthoek, op basis van attributen)
screen.fill((15, 15, 22))
pygame.draw.rect(screen, player.color,
(player.x, player.y, player.width, player.height))
for enemy in enemies:
pygame.draw.rect(screen, enemy.color,
(enemy.x, enemy.y, enemy.width, enemy.height))
for bullet in bullets:
pygame.draw.rect(screen, bullet.color,
(bullet.x, bullet.y, bullet.width, bullet.height))
score = getattr(world, "score", 0) if world is not None else 0
hp = getattr(player, "health", None)
text = f"Score: {score}" + (f" HP: {hp}" if hp is not None else "")
screen.blit(font.render(text, True, (240, 240, 240)), (10, 10))
pygame.display.flip()
clock.tick(fps)
pygame.quit()
def run_world(world, bullet_factory=None):
"""Voor US4 + project: geef je hele Game/World-object mee."""
run_game(world.player, world.enemies,
width=world.width, height=world.height,
world=world, bullet_factory=bullet_factory)
Acceptatiecriteria
Enemy-objecten.for-loop telt hoeveel vijanden nog alive zijn.alive = False zetten laat de rest ongemoeid.