From 11349988f7cb6499a046ff06bbea9fd606750c44 Mon Sep 17 00:00:00 2001 From: "lennart.wolfram" Date: Thu, 10 Sep 2026 13:57:49 +0000 Subject: [PATCH] Dateien nach "/" hochladen --- car.png | Bin 0 -> 611 bytes kart.py | 50 +++-- main.py | 687 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 714 insertions(+), 23 deletions(-) create mode 100644 car.png create mode 100644 main.py diff --git a/car.png b/car.png new file mode 100644 index 0000000000000000000000000000000000000000..6466db81dc5e3382eaf9825123bd44439ea1a35b GIT binary patch literal 611 zcmV-p0-XJcP)EX>4Tx04R}tk-tmBKpe$iTcuiB9PA+C5TtgpAS&W0RV;#q(pG5I!Q|3k(4-+r zad8w}3l9ERtU9+0Yt2!cOA`~$>E(M3x9UQ%cgDpQP}2|!Uz zJ)MXPx%{f&e?>n62qB75kr`StvzUeJ__~LOuXiz?<$mtZ5t0iA13Uup9Mg1@c!PLm z)6_Wc6Ngz@l!?!Y$91|O@gvtIhu=7tZ1(cZu%1oN6Nia~QWr~I%*wh#JWU*t6_xV6 zIfrG=Tbz|@owe`DUl=T?D;ciS96 zfRSSXH7F2mKlmT~?$#(yO*%=zIMDlISs!D7e-~&qEbIH&vRWsA?-{sKJN{Y|nEfQZ z(a|DDz`!YT&7<$q~U9=@1O>eOXyr0oG<$=LlAh722*51eI1CXVzmT!QA zLm*nB>~)uS_jUL7@0oUgKbpF24YJ`L;wH)0002_L%V+f000SaNLh0L z04^f{04^f|c%?sf00007bV*G`2kHq54KFw=U<2_0000?uMObu0Z*6U5Zgc=ca%Ew3 zWn>_CX>@2HM@dakSAh-}0000wNklalH%3%))<-llrT6bQhrT!%mjC56$jQWwFm$J002ovPDHLkV1gh;`*8pO literal 0 HcmV?d00001 diff --git a/kart.py b/kart.py index a81654e..743114b 100644 --- a/kart.py +++ b/kart.py @@ -14,9 +14,7 @@ class Kart: self.position = [0, 0] self.acceleration = acceleration self.lastRam = 0 - - def __str__(self): - return "Das Kart heißt:" + self.name + self.knockback = [0, 0] def acc(self, brk): #brk is true or false if brk == False: @@ -33,44 +31,50 @@ class Kart: self.rotation += dir * self.handling def pos(self): + # normale Eigenbewegung self.position[0] += math.cos(math.radians(self.rotation)) * self.speed self.position[1] += math.sin(math.radians(self.rotation)) * self.speed + # Bewegung durch Rammen + self.position[0] += self.knockback[0] + self.position[1] += self.knockback[1] + + # Knockback langsam abbauen + self.knockback[0] *= 0.90 + self.knockback[1] *= 0.90 + + if self.speed > 5: + self.speed *= 0.98 + def ram(self, other): current = time.time() if current - self.lastRam < 1: return - - self.lastRam = current - dx = self.position[0] - other.position[0] - dy = self.position[1] - other.position[1] + dx = other.position[0] - self.position[0] + dy = other.position[1] - self.position[1] distance = math.sqrt(dx**2 + dy**2) - if distance <= 200 and distance > 0: + if distance > 200 or distance == 0: + return - # Richtung vom anderen Kart zum eigenen Kart - direction_x = dx / distance - direction_y = dy / distance + self.lastRam = current - # Beide Karts bekommen eine schnelle Bewegung - # aufeinander zu bzw. vom Zusammenstoß weg. - ramSpeed = 12 + # Richtung VOM eigenen Kart ZUM Gegner + direction_x = dx / distance + direction_y = dy / distance - self.position[0] += direction_x * ramSpeed - self.position[1] += direction_y * ramSpeed + # Das eigene Kart macht einen schnellen Satz zum Gegner + self.speed = 10 - other.position[0] -= direction_x * ramSpeed - other.position[1] -= direction_y * ramSpeed + # Gegner fliegt in Bewegungsrichtung des Angreifers weg + knockbackSpeed = 18 - # Zufällige Drehung wie vorher - randrot = random.randint(-20, 20) - - self.rotation += randrot - other.rotation -= randrot + other.knockback[0] = direction_x * knockbackSpeed + other.knockback[1] = direction_y * knockbackSpeed class Item: diff --git a/main.py b/main.py new file mode 100644 index 0000000..86d31bf --- /dev/null +++ b/main.py @@ -0,0 +1,687 @@ +import pygame +import random +import time +from kart import Kart, Item + + +# ------------------------- +# Einstellungen +# ------------------------- + +WIDTH = 1000 +HEIGHT = 700 +FPS = 60 + +BACKGROUND = (40, 40, 40) +import pygame +import random +import time +from pathlib import Path +from kart import Kart, Item + + +# ------------------------- +# Einstellungen +# ------------------------- + +WIDTH = 1000 +HEIGHT = 700 +FPS = 60 + +BACKGROUND = (40, 40, 40) + +# Breite des Kart-Bildes auf dem Bildschirm. +# Die Höhe wird automatisch passend zum Seitenverhältnis berechnet. +KART_IMAGE_WIDTH = 60 + +# Falls die Vorderseite von car.jpg nicht nach rechts zeigt, kann dieser +# Wert angepasst werden, z. B. 90, -90 oder 180. +KART_IMAGE_ROTATION_OFFSET = 0 + +# Das Originalbild und bereits eingefärbte Varianten werden zwischengespeichert. +CAR_IMAGE = None +CAR_IMAGE_CACHE = {} + + +# ------------------------- +# Hilfsfunktionen zum Zeichnen +# ------------------------- + +def load_car_image(): + """Lädt car.jpg aus demselben Ordner wie main.py.""" + global CAR_IMAGE + + image_path = Path(__file__).resolve().with_name("car.jpg") + image = pygame.image.load(str(image_path)).convert_alpha() + + # Seitenverhältnis des Bildes beibehalten. + scale = KART_IMAGE_WIDTH / image.get_width() + new_height = max(1, round(image.get_height() * scale)) + CAR_IMAGE = pygame.transform.smoothscale( + image, + (KART_IMAGE_WIDTH, new_height) + ) + + +def get_colored_car_image(color): + """ + Gibt car.jpg in der gewünschten Kartfarbe zurück. + + Reine Grautöne bleiben unverändert. Rote Bereiche werden durch die + gewünschte Farbe ersetzt. Ein kleiner Toleranzbereich sorgt dafür, + dass auch durch JPEG-Kompression veränderte rote Randpixel mitgefärbt + werden. + """ + color = tuple(color) + + if color in CAR_IMAGE_CACHE: + return CAR_IMAGE_CACHE[color] + + image = CAR_IMAGE.copy() + pixels = pygame.PixelArray(image) + + for x in range(image.get_width()): + for y in range(image.get_height()): + pixel = image.unmap_rgb(pixels[x, y]) + r, g, b = pixel.r, pixel.g, pixel.b + + # Grautöne haben ungefähr r == g == b. + # Nur deutlich rotlastige Pixel werden eingefärbt. + gray = (g + b) / 2 + redness = r - max(g, b) + + if redness > 10: + # Stärke des roten Anteils. + # (255, 0, 0) -> 1.0, rote Übergangspixel entsprechend weniger. + strength = min(1.0, max(0.0, (r - gray) / 255.0)) + + new_r = round(gray + (color[0] - gray) * strength) + new_g = round(gray + (color[1] - gray) * strength) + new_b = round(gray + (color[2] - gray) * strength) + + pixels[x, y] = (new_r, new_g, new_b) + + del pixels + + CAR_IMAGE_CACHE[color] = image + return image + + +def draw_kart(screen, kart, car_image, car_cache): + color_key = tuple(kart.color) + + # Eingefärbtes Bild nur einmal pro Farbe erstellen + if color_key not in car_cache: + colored = colorize_car(car_image, kart.color) + + # Vergrößern ohne Glättung -> Pixel-Look bleibt erhalten + scale = 4 + + new_size = ( + colored.get_width() * scale, + colored.get_height() * scale + ) + + car_cache[color_key] = pygame.transform.scale( + colored, + new_size + ) + + surface = car_cache[color_key] + + # Kart entsprechend seiner Rotation drehen + rotated = pygame.transform.rotate(surface, -kart.rotation) + + rect = rotated.get_rect( + center=(int(kart.position[0]), int(kart.position[1])) + ) + + screen.blit(rotated, rect) + + +# ------------------------- +# Pool zeichnen +# ------------------------- + +def draw_pool(screen, pool): + pygame.draw.ellipse( + screen, + pool.color, + ( + int(pool.position[0] - pool.size), + int(pool.position[1] - pool.size / 2), + int(pool.size * 2), + int(pool.size) + ) + ) + +def colorize_car(image, color): + colored = image.copy() + + for x in range(colored.get_width()): + for y in range(colored.get_height()): + r, g, b, a = colored.get_at((x, y)) + + # Nur reines Rot wird durch die Kart-Farbe ersetzt + if (r, g, b) == (255, 0, 0): + colored.set_at((x, y), (*color, a)) + + return colored +# ------------------------- +# Main +# ------------------------- +def main(): + pygame.init() + + screen = pygame.display.set_mode((WIDTH, HEIGHT)) + pygame.display.set_caption("Kart Game") + + # car.jpg erst nach dem Erzeugen des Fensters laden, damit convert_alpha() + # das Bild für die aktuelle Anzeige optimieren kann. + load_car_image() + + clock = pygame.time.Clock() + car_image = pygame.image.load("car.png").convert_alpha() + car_cache = {} + # ------------------------- + # Karts erzeugen + # ------------------------- + + kart1 = Kart( + "Player 1", + (255, 50, 50), + acceleration=0.2, + vMax=5, + handling=4 + ) + + kart2 = Kart( + "Player 2", + (50, 100, 255), + acceleration=0.2, + vMax=5, + handling=4 + ) + + # Startpositionen + kart1.position = [250, 350] + kart1.rotation = 0 + + kart2.position = [750, 350] + kart2.rotation = 180 + + # ------------------------- + # Pool + # ------------------------- + + pool = None + + # Zeitpunkt, wann der nächste Pool erscheint + nextPoolTime = time.time() + random.uniform(3, 8) + + running = True + + while running: + + # ------------------------- + # Events + # ------------------------- + + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + + # ------------------------- + # Pool erzeugen / entfernen + # ------------------------- + + currentTime = time.time() + + # Wenn momentan kein Pool existiert + # und die Wartezeit vorbei ist + if pool is None and currentTime >= nextPoolTime: + + pool = Item("pool") + pool.typ() + + # Zufällige Position + pool.position = [ + random.randint(80, WIDTH - 80), + random.randint(80, HEIGHT - 80) + ] + + # Zufällige Größe + pool.size = random.randint(40, 80) + + # Pool bleibt unterschiedlich lange sichtbar + poolEndTime = currentTime + random.uniform(3, 7) + + # Pool verschwinden lassen + if pool is not None and currentTime >= poolEndTime: + + pool = None + + # Unregelmäßige Zeit bis zum nächsten Pool + nextPoolTime = currentTime + random.uniform(3, 10) + + keys = pygame.key.get_pressed() + + # ------------------------- + # Kart 1 + # WASD + E + # ------------------------- + + # W = Gas + if keys[pygame.K_w]: + kart1.acc(False) + + # S = Rückwärts / Bremsen + elif keys[pygame.K_s]: + kart1.acc(True) + + # Wenn kein Gas/Bremse -> langsam abbremsen + else: + kart1.speed *= 0.98 + + # A = links + if keys[pygame.K_a]: + kart1.turn(-1) + + # D = rechts + if keys[pygame.K_d]: + kart1.turn(1) + + # E = Rammen + if keys[pygame.K_e]: + kart1.ram(kart2) + + # ------------------------- + # Kart 2 + # IJKL + O + # ------------------------- + + # I = Gas + if keys[pygame.K_i]: + kart2.acc(False) + + # K = Rückwärts / Bremsen + elif keys[pygame.K_k]: + kart2.acc(True) + + else: + kart2.speed *= 0.98 + + # J = links + if keys[pygame.K_j]: + kart2.turn(-1) + + # L = rechts + if keys[pygame.K_l]: + kart2.turn(1) + + # O = Rammen + if keys[pygame.K_o]: + kart2.ram(kart1) + + # ------------------------- + # Position aktualisieren + # ------------------------- + + kart1.pos() + kart2.pos() + + # ------------------------- + # Bildschirm verlassen? + # -> auf andere Seite wechseln + # ------------------------- + + # Abstand zum Bildschirmrand + border = 20 + + for kart in [kart1, kart2]: + + # Linker Rand + if kart.position[0] < border: + kart.position[0] = border + + # Rechter Rand + if kart.position[0] > WIDTH - border: + kart.position[0] = WIDTH - border + + # Oberer Rand + if kart.position[1] < border: + kart.position[1] = border + + # Unterer Rand + if kart.position[1] > HEIGHT - border: + kart.position[1] = HEIGHT - border + + # ------------------------- + # Zeichnen + # ------------------------- + + screen.fill(BACKGROUND) + + # Pool zeichnen + if pool is not None: + draw_pool(screen, pool) + + draw_kart(screen, kart1, car_image, car_cache) + draw_kart(screen, kart2, car_image, car_cache) + + # Namen anzeigen + font = pygame.font.Font(None, 28) + + text1 = font.render( + f"{kart1.name}: {kart1.speed:.1f}", + True, + kart1.color + ) + + text2 = font.render( + f"{kart2.name}: {kart2.speed:.1f}", + True, + kart2.color + ) + + screen.blit(text1, (20, 20)) + screen.blit(text2, (20, 50)) + + pygame.display.flip() + + # FPS + clock.tick(FPS) + + pygame.quit() + + +if __name__ == "__main__": + main() + + +# ------------------------- +# Hilfsfunktion zum Zeichnen +# ------------------------- + +def draw_kart(screen, kart): + # Kart als Rechteck + width = 40 + height = 25 + + surface = pygame.Surface((width, height), pygame.SRCALPHA) + pygame.draw.rect(surface, kart.color, (0, 0, width, height)) + + # Richtung des Karts + rotated = pygame.transform.rotate(surface, -kart.rotation) + + rect = rotated.get_rect( + center=(int(kart.position[0]), int(kart.position[1])) + ) + + screen.blit(rotated, rect) + + +# ------------------------- +# Pool zeichnen +# ------------------------- + +def draw_pool(screen, pool): + pygame.draw.ellipse( + screen, + pool.color, + ( + int(pool.position[0] - pool.size), + int(pool.position[1] - pool.size / 2), + int(pool.size * 2), + int(pool.size) + ) + ) + +def apply_pool_slow(kart, pool): + if pool is None: + return + + dx = kart.position[0] - pool.position[0] + dy = kart.position[1] - pool.position[1] + + # Prüfen, ob das Kart innerhalb der Ellipse liegt + inside = ( + (dx / pool.size) ** 2 + + (dy / (pool.size / 2)) ** 2 + <= 1 + ) + + if inside: + kart.speed *= 0.8 + +# ------------------------- +# Main +# ------------------------- + +def main(): + pygame.init() + + screen = pygame.display.set_mode((WIDTH, HEIGHT)) + pygame.display.set_caption("Kart Game") + + clock = pygame.time.Clock() + + # ------------------------- + # Karts erzeugen + # ------------------------- + + kart1 = Kart( + "Player 1", + (255, 50, 50), + acceleration=0.2, + vMax=5, + handling=4 + ) + + kart2 = Kart( + "Player 2", + (50, 100, 255), + acceleration=0.2, + vMax=5, + handling=4 + ) + + # Startpositionen + kart1.position = [250, 350] + kart1.rotation = 0 + + kart2.position = [750, 350] + kart2.rotation = 180 + + # ------------------------- + # Pool + # ------------------------- + + pool = None + + # Zeitpunkt, wann der nächste Pool erscheint + nextPoolTime = time.time() + random.uniform(3, 8) + + running = True + + while running: + + # ------------------------- + # Events + # ------------------------- + + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + + # ------------------------- + # Pool erzeugen / entfernen + # ------------------------- + + currentTime = time.time() + + # Wenn momentan kein Pool existiert + # und die Wartezeit vorbei ist + if pool is None and currentTime >= nextPoolTime: + + pool = Item("pool") + pool.typ() + + # Zufällige Position + pool.position = [ + random.randint(80, WIDTH - 80), + random.randint(80, HEIGHT - 80) + ] + + # Zufällige Größe + pool.size = random.randint(40, 80) + + # Pool bleibt unterschiedlich lange sichtbar + poolEndTime = currentTime + random.uniform(3, 7) + + # Pool verschwinden lassen + if pool is not None and currentTime >= poolEndTime: + + pool = None + + # Unregelmäßige Zeit bis zum nächsten Pool + nextPoolTime = currentTime + random.uniform(3, 10) + + keys = pygame.key.get_pressed() + + # ------------------------- + # Kart 1 + # WASD + E + # ------------------------- + + # W = Gas + if keys[pygame.K_w]: + kart1.acc(False) + + # S = Rückwärts / Bremsen + elif keys[pygame.K_s]: + kart1.acc(True) + + # Wenn kein Gas/Bremse -> langsam abbremsen + else: + kart1.acc(None) + + # A = links + if keys[pygame.K_a]: + kart1.turn(-1) + + # D = rechts + if keys[pygame.K_d]: + kart1.turn(1) + + # E = Rammen + if keys[pygame.K_e]: + kart1.ram(kart2) + + # ------------------------- + # Kart 2 + # IJKL + O + # ------------------------- + + # I = Gas + if keys[pygame.K_i]: + kart2.acc(False) + + # K = Rückwärts / Bremsen + elif keys[pygame.K_k]: + kart2.acc(True) + + else: + kart1.acc(None) + + # J = links + if keys[pygame.K_j]: + kart2.turn(-1) + + # L = rechts + if keys[pygame.K_l]: + kart2.turn(1) + + # O = Rammen + if keys[pygame.K_o]: + kart2.ram(kart1) + + # ------------------------- + # Position aktualisieren + # ------------------------- + + # Pool-Effekt + apply_pool_slow(kart1, pool) + apply_pool_slow(kart2, pool) + + # Position aktualisieren + kart1.pos() + kart2.pos() + + # ------------------------- + # Bildschirm verlassen? + # -> auf andere Seite wechseln + # ------------------------- + + # Abstand zum Bildschirmrand + border = 20 + + for kart in [kart1, kart2]: + + # Linker Rand + if kart.position[0] < border: + kart.position[0] = border + + # Rechter Rand + if kart.position[0] > WIDTH - border: + kart.position[0] = WIDTH - border + + # Oberer Rand + if kart.position[1] < border: + kart.position[1] = border + + # Unterer Rand + if kart.position[1] > HEIGHT - border: + kart.position[1] = HEIGHT - border + + # ------------------------- + # Zeichnen + # ------------------------- + + screen.fill(BACKGROUND) + + # Pool zeichnen + if pool is not None: + draw_pool(screen, pool) + + draw_kart(screen, kart1) + draw_kart(screen, kart2) + + # Namen anzeigen + font = pygame.font.Font(None, 28) + + text1 = font.render( + f"{kart1.name}: {kart1.speed:.1f}", + True, + kart1.color + ) + + text2 = font.render( + f"{kart2.name}: {kart2.speed:.1f}", + True, + kart2.color + ) + + screen.blit(text1, (20, 20)) + screen.blit(text2, (20, 50)) + + pygame.display.flip() + + # FPS + clock.tick(FPS) + + pygame.quit() + + +if __name__ == "__main__": + main()