diff --git a/assets/images/tiles/test/0.png b/assets/images/tiles/test/0.png new file mode 100644 index 0000000..c3dabeb Binary files /dev/null and b/assets/images/tiles/test/0.png differ diff --git a/assets/maps/test.json b/assets/maps/test.json new file mode 100644 index 0000000..97939a9 --- /dev/null +++ b/assets/maps/test.json @@ -0,0 +1 @@ +{"tilemap": {"7;5": {"type": "base", "variant": 0, "pos": [7, 5]}, "7;6": {"type": "base", "variant": 0, "pos": [7, 6]}, "8;6": {"type": "base", "variant": 0, "pos": [8, 6]}}, "tile_size": 16} \ No newline at end of file diff --git a/data/theme/theme.json b/assets/theme/theme.json similarity index 100% rename from data/theme/theme.json rename to assets/theme/theme.json diff --git a/constants.py b/constants.py deleted file mode 100644 index eec4dad..0000000 --- a/constants.py +++ /dev/null @@ -1,3 +0,0 @@ -class Config: - FPS=60 - WINDOW_SIZE=(800,600) \ No newline at end of file diff --git a/editor.py b/editor.py new file mode 100644 index 0000000..523c22d --- /dev/null +++ b/editor.py @@ -0,0 +1,133 @@ +import pygame as pg +from game.util import load_image, load_images +from game.tilemap import Tilemap + +RENDER_SCALE = 2.0 +WINDOW_SIZE=(640, 480) + +class Editor(): + def __init__(self): + self.screen = pg.display.set_mode(WINDOW_SIZE) + self.clock = pg.time.Clock() + + self.width, self.height = pg.display.get_surface().get_size() + self.tilemap = Tilemap(self) + self.display = pg.Surface((self.width/4*3, self.height/6*5)) + + self.map = 'test' + self.path = 'assets/maps/' + str(self.map) + '.json' + + try: + self.tilemap.load(self.path) + except FileNotFoundError: + print('File not Found') + + self.scroll = [0, 0] + + self.assets = { + "base": load_images("/tiles/test") + } + + self.tile_list = list(self.assets) + + self.tile_group = 0 + self.tile_variant = 0 + + self.movment = [False, False, False, False] + + self.clicking = False + self.right_clicking = False + self.shift = False + self.ongrid = True + + def run(self): + self.running = True + while self.running: + self.clock.tick(60) + self.update() + self.draw() + return self.running + + def update(self): + self.mpos = pg.mouse.get_pos() + self.mpos = (self.mpos[0] / RENDER_SCALE, self.mpos[1] / RENDER_SCALE) + self.tile_pos = (int((self.mpos[0] + self.scroll[0]) // self.tilemap.tile_size), int((self.mpos[1] + self.scroll[1]) // self.tilemap.tile_size)) + + self.scroll[0] += (self.movment[1] - self.movment[0]) * 2 + self.scroll[1] += (self.movment[3] - self.movment[2]) * 2 + + if self.clicking and self.ongrid: + self.tilemap.tilemap[str(self.tile_pos[0]) + ';' + str(self.tile_pos[1])] = {'type': self.tile_list[self.tile_group], 'variant': self.tile_variant, 'pos': self.tile_pos} + if self.right_clicking: + tile_loc = str(self.tile_pos[0]) + ';' + str(self.tile_pos[1]) + if tile_loc in self.tilemap.tilemap: + del self.tilemap.tilemap[tile_loc] + + self.current_tile_img = self.assets[self.tile_list[self.tile_group]][self.tile_variant].copy() + + for event in pg.event.get(): + if event.type == pg.QUIT: + self.running = False + if event.type == pg.MOUSEBUTTONDOWN: + if event.button == 1: + self.clicking = True + if event.button == 3: + self.right_clicking = True + if self.shift: + if event.button == 4: + self.tile_variant = (self.tile_variant - 1) % len(self.assets[self.tile_list[self.tile_group]]) + if event.button == 5: + self.tile_variant = (self.tile_variant + 1) % len(self.assets[self.tile_list[self.tile_group]]) + else: + if event.button == 4: + self.tile_group = (self.tile_group - 1) % len(self.tile_list) + self.tile_variant = 0 + if event.button == 5: + self.tile_group = (self.tile_group + 1) % len(self.tile_list) + self.tile_variant = 0 + if event.type == pg.MOUSEBUTTONUP: + if event.button == 1: + self.clicking = False + if event.button == 3: + self.right_clicking = False + + if event.type == pg.KEYDOWN: + if event.key == pg.K_a: + self.movment[0] = True + if event.key == pg.K_d: + self.movment[1] = True + if event.key == pg.K_w: + self.movment[2] = True + if event.key == pg.K_s: + self.movment[3] = True + if event.key == pg.K_LSHIFT: + self.shift = True + if event.key == pg.K_o: + self.tilemap.save(self.path) + if event.type == pg.KEYUP: + if event.key == pg.K_a: + self.movment[0] = False + if event.key == pg.K_d: + self.movment[1] = False + if event.key == pg.K_w: + self.movment[2] = False + if event.key == pg.K_s: + self.movment[3] = False + if event.key == pg.K_LSHIFT: + self.shift = False + + def draw(self): + self.display.fill((0, 0, 0)) + + render_scroll = (int(self.scroll[0]), int(self.scroll[1])) + + self.display.blit(self.current_tile_img, (10, 10)) + + self.tilemap.render(self.display, offset=render_scroll) + if self.ongrid: + self.display.blit(self.current_tile_img, (self.tile_pos[0] * self.tilemap.tile_size - self.scroll[0], self.tile_pos[1] * self.tilemap.tile_size - self.scroll[1])) + else: + self.display.blit(self.current_tile_img, self.mpos) + + self.screen.blit(pg.transform.scale(self.display, self.screen.get_size())) + pg.display.update() \ No newline at end of file diff --git a/game/game.py b/game/game.py index 79eeec1..9fe9200 100644 --- a/game/game.py +++ b/game/game.py @@ -1,40 +1,72 @@ -import pygame as pg +import pygame import pygame_gui -from constants import Config -class Game(): - def __init__(self, screen, clock, manager): - self.screen = screen - self.clock = clock - self.manager = manager - self.fps_label = pygame_gui.elements.UILabel( - relative_rect=pg.Rect((10, 10), (120, 40)), - text="FPS: 0", - manager=self.manager +from game.util import * +from game.tilemap import Tilemap +from game.screens.main_menu import MainMenu +from game.screens.game_play import GamePlay + +FPS=60 +WINDOW_SIZE=(960,540) +TILE=16 + +class Game: + + def __init__(self): + + pygame.init() + + self.window = pygame.display.set_mode(WINDOW_SIZE) + self.clock = pygame.time.Clock() + self.ui_manager = pygame_gui.UIManager( + WINDOW_SIZE, + "theme.json" ) + self.tilemap = Tilemap(self) + + self.assets={ + "base": load_images('/tiles/test') + } + + self.screens = { + "menu": MainMenu(self), + "game": GamePlay(self) + } + self.current_screen = self.screens["menu"] + + def change_screen(self, name): + + self.current_screen.hide() + + self.current_screen = self.screens[name] + + self.current_screen.show() def run(self): - self.running = True - while self.running: - self.clock.tick(Config.FPS) - self.update() - self.draw() - return self.running - def update(self): - fps = str(int(self.clock.get_fps())) - self.fps_label.set_text('fps: ' + fps) + running = True - for event in pg.event.get(): - if event.type == pg.QUIT: - self.running = False + while running: - self.manager.process_events(event) + dt = self.clock.tick(FPS) / 1000.0 - time_delta = self.clock.tick(Config.FPS)/1000.0 - self.manager.update(time_delta) + for event in pygame.event.get(): - def draw(self): - self.screen.fill(self.manager.get_theme().get_colour('normal_bg')) - self.manager.draw_ui(self.screen) - pg.display.update() \ No newline at end of file + if event.type == pygame.QUIT: + running = False + + self.ui_manager.process_events(event) + + self.current_screen.process_event(event) + + self.ui_manager.update(dt) + + self.window.fill((20, 20, 20)) + + self.current_screen.draw(self.window) + + self.ui_manager.draw_ui(self.window) + + pygame.display.update() + + pygame.quit() \ No newline at end of file diff --git a/game/player.py b/game/player.py deleted file mode 100644 index e69de29..0000000 diff --git a/game/screens/base_screen.py b/game/screens/base_screen.py new file mode 100644 index 0000000..ea7d2a9 --- /dev/null +++ b/game/screens/base_screen.py @@ -0,0 +1,23 @@ +class BaseScreen: + + def __init__(self, game): + self.game = game + + self.elements = [] + + def process_event(self, event): + pass + + def update(self, dt): + pass + + def draw(self, surface): + pass + + def show(self): + for element in self.elements: + element.show() + + def hide(self): + for element in self.elements: + element.hide() \ No newline at end of file diff --git a/game/screens/game_play.py b/game/screens/game_play.py new file mode 100644 index 0000000..0c1897f --- /dev/null +++ b/game/screens/game_play.py @@ -0,0 +1,35 @@ +from game.screens.base_screen import BaseScreen +import pygame as pg +import pygame_gui as pgi + +class GamePlay(BaseScreen): + def __init__(self, game): + super().__init__(game) + + self.tile_multiplicator = 2.0 + self.width, self.height = pg.display.get_surface().get_size() + self.map_screen = pg.surface.Surface((int(self.width/4*3),int(self.height/6*5))) + + self.scroll = [0, 0] + + self.map = 'test' + self.path = 'assets/maps/' + str(self.map) + '.json' + + try: + self.game.tilemap.load(self.path) + except FileNotFoundError: + print('File not Found') + + def process_event(self, event): + pass + + def update(self, dt): + pass + + def draw(self, surface): + self.map_screen.fill((40, 40, 40)) + + render_scroll = (int(self.scroll[0]), int(self.scroll[1])) + self.game.tilemap.render(self.map_screen, offset=render_scroll) + + self.game.window.blit(self.map_screen, (0, self.height/6)) diff --git a/game/screens/main_menu.py b/game/screens/main_menu.py new file mode 100644 index 0000000..2831a04 --- /dev/null +++ b/game/screens/main_menu.py @@ -0,0 +1,79 @@ +from game.screens.base_screen import BaseScreen + +import pygame as pg +import pygame_gui as pgi + +class MainMenu(BaseScreen): + def __init__(self, game): + + super().__init__(game) + + manager = game.ui_manager + + width, height = pg.display.get_surface().get_size() + + # Größen + title_width = 400 + title_height = 80 + + button_width = 250 + button_height = 60 + + center_x = width // 2 + + self.title = pgi.elements.UILabel( + + relative_rect=pg.Rect( + center_x - title_width // 2, + int(height * 0.2), + title_width, + title_height + ), + text="MAIN MENU", + manager=manager + ) + + self.play_button = pgi.elements.UIButton( + + relative_rect=pg.Rect( + center_x - button_width // 2, + int(height * 0.35), + button_width, + button_height + ), + + text="Play", + manager=manager + ) + + self.quit_button = pgi.elements.UIButton( + + relative_rect=pg.Rect( + center_x - button_width // 2, + int(height * 0.60), + button_width, + button_height + ), + + text="Quit", + manager=manager + ) + + self.elements = [ + self.title, + self.play_button, + self.quit_button + ] + + def process_event(self, event): + + if event.type == pgi.UI_BUTTON_PRESSED: + + if event.ui_element == self.play_button: + + # Zum Gameplay wechseln + self.game.change_screen("game") + + if event.ui_element == self.quit_button: + pg.quit() + exit() \ No newline at end of file diff --git a/game/tilemap.py b/game/tilemap.py new file mode 100644 index 0000000..9f6bc7a --- /dev/null +++ b/game/tilemap.py @@ -0,0 +1,29 @@ +import pygame, json + +class Tilemap: + def __init__(self, game, tile=16): + self.game = game + self.tile_size = tile + self.tilemap = {} + + def save(self, path): + f = open(path, 'w') + json.dump({'tilemap': self.tilemap, 'tile_size': self.tile_size}, f) + f.close() + + def load(self, path): + f = open(path, 'r') + map_data = json.load(f) + f.close() + + self.tilemap = map_data['tilemap'] + self.tile_size = map_data['tile_size'] + + + def render(self, surf, offset=(0, 0)): + for x in range(offset[0] // self.tile_size, (offset[0] + surf.get_width()) // self.tile_size + 1): + for y in range(offset[1] // self.tile_size, (offset[1] + surf.get_height()) // self.tile_size + 1): + loc = str(x) + ';' + str(y) + if loc in self.tilemap: + tile = self.tilemap[loc] + surf.blit(self.game.assets[tile['type']][tile['variant']], (tile['pos'][0] * self.tile_size - offset[0], tile['pos'][1] * self.tile_size - offset[1])) diff --git a/game/util.py b/game/util.py new file mode 100644 index 0000000..fd34f24 --- /dev/null +++ b/game/util.py @@ -0,0 +1,16 @@ +import pygame as pg +import os + +img_path='assets/images' +WINDOW_SIZE=(800,600) + +def load_image(path, colorkey=(0,0,0)): + img = pg.image.load(img_path + path).convert() + img.set_colorkey(colorkey) + return img + +def load_images(dir_path): + images = [] + for img_name in os.listdir(img_path+dir_path): + images.append(load_image(dir_path + '/' + img_name)) + return images diff --git a/main.py b/main.py index 64c1f95..205a8ef 100644 --- a/main.py +++ b/main.py @@ -1,29 +1,8 @@ -import pygame as pg -import pygame_gui - -from constants import Config from game.game import Game +from editor import Editor -def main(): +game = Game() +# editor = Editor() - running = True - - pg.init() - # pygame.mixer.init() - pg.display.set_caption('Portal') - screen = pg.display.set_mode(Config.WINDOW_SIZE) - manager = pygame_gui.UIManager(Config.WINDOW_SIZE, theme_path="data/theme/theme.json") - - clock = pg.time.Clock() - - # implement game - game = Game(screen, clock, manager) - - while running: - - running = game.run() - - pg.quit() - -if __name__ == "__main__": - main() \ No newline at end of file +game.run() +# editor.run() \ No newline at end of file