diff --git a/assets/backgrounds/background.png b/assets/backgrounds/background.png new file mode 100644 index 0000000..5edd4e7 Binary files /dev/null and b/assets/backgrounds/background.png differ diff --git a/assets/backgrounds/background_II-I.png b/assets/backgrounds/background_II-I.png new file mode 100644 index 0000000..3d3e07a Binary files /dev/null and b/assets/backgrounds/background_II-I.png differ diff --git a/assets/backgrounds/background_II.png b/assets/backgrounds/background_II.png new file mode 100644 index 0000000..38bafd4 Binary files /dev/null and b/assets/backgrounds/background_II.png differ diff --git a/assets/backgrounds/background_III.png b/assets/backgrounds/background_III.png new file mode 100644 index 0000000..b2c92e6 Binary files /dev/null and b/assets/backgrounds/background_III.png differ diff --git a/assets/images/fred.png b/assets/images/fred.png deleted file mode 100644 index e781f4c..0000000 Binary files a/assets/images/fred.png and /dev/null differ diff --git a/assets/images/fred_olli.png b/assets/images/fred_olli.png deleted file mode 100644 index 921d354..0000000 Binary files a/assets/images/fred_olli.png and /dev/null differ diff --git a/assets/images/player/fred.png b/assets/images/player/fred.png new file mode 100644 index 0000000..4b744cf Binary files /dev/null and b/assets/images/player/fred.png differ diff --git a/assets/images/player/fred_back.png b/assets/images/player/fred_back.png new file mode 100644 index 0000000..f5d4605 Binary files /dev/null and b/assets/images/player/fred_back.png differ diff --git a/assets/images/player/fred_olli.png b/assets/images/player/fred_olli.png new file mode 100644 index 0000000..48e684e Binary files /dev/null and b/assets/images/player/fred_olli.png differ diff --git a/assets/images/player/fred_turn.png b/assets/images/player/fred_turn.png new file mode 100644 index 0000000..63c68ab Binary files /dev/null and b/assets/images/player/fred_turn.png differ diff --git a/assets/obstacles/box.png b/assets/obstacles/box.png new file mode 100644 index 0000000..eb6c8fc Binary files /dev/null and b/assets/obstacles/box.png differ diff --git a/assets/obstacles/ramp.png b/assets/obstacles/ramp.png new file mode 100644 index 0000000..e72f183 Binary files /dev/null and b/assets/obstacles/ramp.png differ diff --git a/assets/obstacles/stange.png b/assets/obstacles/stange.png new file mode 100644 index 0000000..e12348f Binary files /dev/null and b/assets/obstacles/stange.png differ diff --git a/assets/world/ground_I.png b/assets/world/ground_I.png new file mode 100644 index 0000000..9015fe1 Binary files /dev/null and b/assets/world/ground_I.png differ diff --git a/assets/world/ground_II.png b/assets/world/ground_II.png new file mode 100644 index 0000000..7c6ef01 Binary files /dev/null and b/assets/world/ground_II.png differ diff --git a/src/main.py b/src/main.py index 3314c42..bee981c 100644 --- a/src/main.py +++ b/src/main.py @@ -1,3 +1,4 @@ +from player import Player import pygame import sys from menu import Menu # Menü importieren @@ -7,13 +8,13 @@ from world import World def main(): pygame.init() screen = pygame.display.set_mode((settings.SCREEN_WIDTH, settings.SCREEN_HEIGHT)) - pygame.display.set_caption("The Last Ollie \n A Fred Story") + pygame.display.set_caption("The Last Ollie - A Fred Story") clock = pygame.time.Clock() menu = Menu(screen) world = World(screen) - current_scene = "menu" # oder "world" + current_scene = settings.START_POINT running = True while running: @@ -38,6 +39,7 @@ def main(): if current_scene == "menu": menu.draw() elif current_scene == "world": + world.player.update(670) world.draw() pygame.display.flip() diff --git a/src/obstacle.py b/src/obstacle.py new file mode 100644 index 0000000..71ebe3e --- /dev/null +++ b/src/obstacle.py @@ -0,0 +1,14 @@ +import pygame +import settings + +class Obstacle: + def __init__(self, x, y, image_path): + self.image = pygame.image.load(image_path).convert_alpha() + self.image = pygame.transform.scale(self.image, (300, 150)) # Größe anpassen + self.rect = self.image.get_rect(topleft=(x, y)) + + def draw(self, screen, camera_offset): + screen.blit(self.image, (self.rect.x - camera_offset, self.rect.y)) + + def get_rect(self): + return self.rect \ No newline at end of file diff --git a/src/player.py b/src/player.py new file mode 100644 index 0000000..f4e5a6e --- /dev/null +++ b/src/player.py @@ -0,0 +1,69 @@ +import pygame +import settings + +class Player: + def __init__(self, x, y): + # PLAYER BILDER + # --- NORMAL + self.image_normal = pygame.transform.scale(pygame.image.load(settings.player.fred.normal).convert_alpha(),settings.player.size) + + # --- JUMP + self.image_jump = pygame.transform.scale(pygame.image.load(settings.player.fred.olli).convert_alpha(),settings.player.size) + + # --- BACK + self.image_left = pygame.transform.scale(pygame.image.load(settings.player.fred.left).convert_alpha(),settings.player.size) + + self.image = self.image_normal # Anfangszustand + self.rect = self.image.get_rect(topleft=(x, y)) + self.velocity_y = 0 + self.speed = settings.player.speed + self.gravity = settings.player.gravity + self.jump_strength = settings.player.jump_strength + self.on_ground = False + + def update(self, ground_y, obstacles=[]): + keys = pygame.key.get_pressed() + + # Bewegung seitlich + if keys[pygame.K_LEFT]: + self.rect.x -= self.speed + if keys[pygame.K_RIGHT]: + self.rect.x += self.speed + + # Sprung + if keys[pygame.K_SPACE] and self.on_ground: + self.velocity_y = self.jump_strength + self.on_ground = False + + # Gravitation + self.velocity_y += self.gravity + self.rect.y += self.velocity_y + self.on_ground = False # zurücksetzen + + # Plattform-Kollision prüfen + for obs in obstacles: + if self.rect.colliderect(obs.get_rect()): + # nur wenn Spieler von oben kommt + if self.velocity_y > 0 and self.rect.bottom <= obs.get_rect().top + 20: + self.rect.bottom = obs.get_rect().top + self.velocity_y = 0 + self.on_ground = True + + # Boden-Kollision + if self.rect.bottom >= ground_y: + self.rect.bottom = ground_y + self.velocity_y = 0 + self.on_ground = True + + # Bildlogik + if not self.on_ground: + self.image = self.image_jump + elif keys[pygame.K_LEFT]: + self.image = self.image_left + elif keys[pygame.K_RIGHT]: + self.image = self.image_normal + else: + self.image = self.image_normal + + def draw(self, screen): + screen.blit(self.image, self.rect) \ No newline at end of file diff --git a/src/settings.py b/src/settings.py index bb38d25..bf7e61f 100644 --- a/src/settings.py +++ b/src/settings.py @@ -1,14 +1,39 @@ # Einstellungen SCREEN_WIDTH = 1280 SCREEN_HEIGHT = 720 -FPS = 30 +FPS = 60 DEBUG = True Mute = True +START_POINT = "world" # world, menu +BACKGROUND_IMG = "../assets/backgrounds/background_III.png" # Schriftarten class fonts: PressStart2P = '../assets/fonts/PressStart2P-Regular.ttf' +class player: + size = (110, 200) + speed = 12 if DEBUG else 5 + gravity = 0.8 + jump_strength = -20 + + class fred: + normal = "../assets/images/player/fred.png" + olli = "../assets/images/player/fred_olli.png" + left = "../assets/images/player/fred_back.png" + +class world: + class ground: + img = "../assets/world/ground_II.png" + crop_top = 500 + crop_height = 300 + scale_height = 80 + scale_width = 300 + crop_scale_right = 1400 + + class obstacle: + box = "../assets/obstacles/box.png" + # Farben class MyColors: # Allgemein diff --git a/src/world.py b/src/world.py index d4d5cdb..df1c3ee 100644 --- a/src/world.py +++ b/src/world.py @@ -1,15 +1,59 @@ import pygame import settings +from player import Player +from obstacle import Obstacle +import random class World: def __init__(self, screen): + # Hindernisse + self.obstacles = [] + obstacle_count = random.randint(2, 3) + for _ in range(obstacle_count): + x = random.randint(500, 4000) # X-Position irgendwo in der Welt + self.obstacles.append(Obstacle(x, 520, settings.world.obstacle.box)) + + # Welt Generierung self.screen = screen - self.background_color = (135, 206, 235) # Himmelblau - self.ground_rect = pygame.Rect(0, 600, 1280, 120) # Boden + self.background = pygame.image.load(settings.BACKGROUND_IMG).convert() + self.bg_width = self.background.get_width() + + # Boden + self.ground_rect = pygame.Rect(0, 650, 5000 * 2.7, 80) # Boden + full_image = pygame.image.load(settings.world.ground.img).convert_alpha() + # --- Ausschneiden des Bereichs + cropped = pygame.Surface((settings.world.ground.crop_scale_right, settings.world.ground.crop_height), pygame.SRCALPHA) + cropped.blit(full_image, (0, 0), (0, settings.world.ground.crop_top, settings.world.ground.crop_scale_right, settings.world.ground.crop_height)) + # --- Skalieren für Anzeige + self.ground_image = pygame.transform.scale(cropped, (settings.world.ground.scale_width, settings.world.ground.scale_height)) + self.tile_width = self.ground_image.get_width() + + # Spieler + self.player = Player(200, 500) # Spieler def draw(self): - self.screen.fill(self.background_color) - pygame.draw.rect(self.screen, (124, 252, 0), self.ground_rect) # Grün für Boden + self.screen.fill((0, 0, 0)) # Bildschirm löschen, bevor gezeichnet wird + camera_offset = self.player.rect.centerx - settings.SCREEN_WIDTH // 2 + world_width = max(self.bg_width, max([obs.rect.right for obs in self.obstacles] + [self.ground_rect.right])) + camera_offset = max(0, min(camera_offset, world_width - settings.SCREEN_WIDTH)) + self.player.update(self.ground_rect.top, self.obstacles) + + bg_offset = int(camera_offset * 0.3) # Parallax: langsamer bewegen + self.screen.blit(self.background, (-bg_offset, 0)) + # Boden kacheln ohne Parallax + start_tile = (camera_offset // self.tile_width) * self.tile_width + end_x = camera_offset + settings.SCREEN_WIDTH + x = start_tile + while x < end_x: + screen_x = x - camera_offset + self.screen.blit(self.ground_image, (screen_x, self.ground_rect.top)) + x += self.tile_width + + for obs in self.obstacles: + obs.draw(self.screen, camera_offset) + + player_screen_x = self.player.rect.x - camera_offset + self.screen.blit(self.player.image, (player_screen_x, self.player.rect.y)) def handle_event(self, event): if event.type == pygame.KEYDOWN: @@ -17,4 +61,5 @@ class World: if settings.DEBUG: print("ESC-Pressed") return "menu" + # self.player.handle_event(event) return None \ No newline at end of file