X-Git-Url: https://git.ctpug.org.za/?a=blobdiff_plain;f=erdslangetjie%2F__main__.py;h=b01c9ef8db1bbbf07d70add1dfe78e12cef67153;hb=bd424c20f83fb70cab857268c8bb81994799e123;hp=3234d1b2dab8242b954c5517729ccbcc83762797;hpb=c35ffdbdb0d011397b758489f3d22f2cf54bed35;p=erdslangetjie.git diff --git a/erdslangetjie/__main__.py b/erdslangetjie/__main__.py index 3234d1b..b01c9ef 100644 --- a/erdslangetjie/__main__.py +++ b/erdslangetjie/__main__.py @@ -1,38 +1,42 @@ -import sys import kivy import pygame kivy.require('1.6.0') from kivy.app import App -from kivy.core.window import Window from kivy.uix.widget import Widget +from kivy.logger import Logger, LoggerHistory from kivy.uix.relativelayout import RelativeLayout from kivy.uix.scrollview import ScrollView +from kivy.uix.button import Button from kivy.graphics import Color, Rectangle from kivy.utils import platform from erdslangetjie.level import LevelList +from erdslangetjie.data import load_image from erdslangetjie.player import ThePlayer, Nemesis - -TILE_SIZE = 40 +from erdslangetjie.constants import TILE_SIZE, QUIET class GameWindow(RelativeLayout): - def __init__(self, level_list, view): + def __init__(self, level_list, app): self.level_list = level_list self.level_obj = self.level_list.get_current_level() self.level_obj.load_tiles() self.tiles = {} - self.view = view + self.view = app.root + self.app = app - rows, cols = self.level_obj.get_size() + cols, rows = self.level_obj.get_size() super(GameWindow, self).__init__( - size=(cols*TILE_SIZE, rows*TILE_SIZE), + size=(cols * TILE_SIZE, rows * TILE_SIZE), size_hint=(None, None)) + self.x_scroll_margin = float(TILE_SIZE) / self.view.size[0] + self.y_scroll_margin = float(TILE_SIZE) / self.view.size[1] + self.mouse_move = False self.player = ThePlayer() @@ -45,6 +49,9 @@ class GameWindow(RelativeLayout): self.player.pos = self.level_obj.enter_pos if platform() != 'android': # Very hack'ish + # We need to delay this import until after the window creation by + # the app, else our size config doesn't work + from kivy.core.window import Window self.keyboard = Window.request_keyboard(self._closed, self) self.keyboard.bind(on_key_down=self._on_key_down) @@ -68,9 +75,6 @@ class GameWindow(RelativeLayout): bx += TILE_SIZE by += TILE_SIZE - self.draw_player() - self.draw_nemesis() - def draw_player(self): if self.player_tile: self.remove_widget(self.player_tile) @@ -83,34 +87,58 @@ class GameWindow(RelativeLayout): Rectangle(pos=sprite_pos, size=self.player_tile.size, texture=self.player.get_texture()) self.add_widget(self.player_tile) - # Player position in viewpoint coordinates - check_point = (sprite_pos[0] + TILE_SIZE / 2, - sprite_pos[1] + TILE_SIZE / 2) - true_point = self.to_parent(*check_point) - if not self.included(true_point): - # Scroll ourselves - while true_point[0] >= self.view.size[0] - TILE_SIZE: - self.pos = (self.pos[0] - 1.5 * TILE_SIZE, self.pos[1]) - true_point = self.to_parent(*check_point) - while true_point[0] < TILE_SIZE: - self.pos = (self.pos[0] + 1.5 * TILE_SIZE, self.pos[1]) - true_point = self.to_parent(*check_point) - while true_point[1] >= self.view.size[1] - TILE_SIZE: - self.pos = (self.pos[0], self.pos[1] - 1.5 * TILE_SIZE) - true_point = self.to_parent(*check_point) - while true_point[1] < TILE_SIZE: - self.pos = (self.pos[0], self.pos[1] + 1.5 * TILE_SIZE) - true_point = self.to_parent(*check_point) - - def included(self, point): - if point[0] < TILE_SIZE: + for offset in [(TILE_SIZE - 1, TILE_SIZE - 1), + (-TILE_SIZE + 1, TILE_SIZE - 1), + (TILE_SIZE - 1, -TILE_SIZE + 1), + (-TILE_SIZE + 1, -TILE_SIZE + 1), + (0, 2 * TILE_SIZE - 2), + (-2 * TILE_SIZE + 2, 0), + (2 * TILE_SIZE - 2, 0), + (0, -2 * TILE_SIZE + 2), + (0, 0)]: + # Aim is to ensure a 'neighbourhood' around the player + # is visible if possible + check_point = (sprite_pos[0] + offset[0] + TILE_SIZE / 2, + sprite_pos[1] + offset[1] + TILE_SIZE / 2) + true_point = self.to_parent(*check_point) + if check_point[0] < 0: + continue + if check_point[1] < 0: + continue + if check_point[0] >= self.size[0]: + continue + if check_point[1] >= self.size[1]: + continue + while not self.included(true_point, 0): + # Scroll ourselves + if true_point[0] >= self.view.size[0]: + self.view.scroll_x += self.x_scroll_margin + true_point = self.to_parent(*check_point) + #print '-x', self.view.scroll_x, self.view.scroll_y + elif true_point[0] < 0: + self.view.scroll_x -= self.x_scroll_margin + true_point = self.to_parent(*check_point) + #print '+x', self.view.scroll_x, self.view.scroll_y + elif true_point[1] >= self.view.size[1]: + self.view.scroll_y += self.y_scroll_margin + true_point = self.to_parent(*check_point) + #print '+y', self.view.scroll_x, self.view.scroll_y + elif true_point[1] < 0: + self.view.scroll_y -= self.y_scroll_margin + true_point = self.to_parent(*check_point) + #print '-y', self.view.scroll_x, self.view.scroll_y + #print true_point, self.view.size + + def included(self, point, margin): + if point[0] < margin: return False - if point[0] >= self.view.pos[0] - TILE_SIZE: + if point[0] >= self.view.size[0] - margin: return False - if point[1] < TILE_SIZE: + if point[1] < margin: return False - if point[1] >= self.view.pos[1] - TILE_SIZE: + if point[1] >= self.view.size[1] - margin: return False + return True def draw_nemesis(self): if not self.nemesis.on_board(): @@ -150,24 +178,37 @@ class GameWindow(RelativeLayout): self.player.move(direction, self.level_obj) self.draw_player() self.check_state() + self.reset_timer() + + def timed_move(self): + self.nemesis.move(self.level_obj) + self.draw_nemesis() + self.check_state() + self.reset_timer() + + def reset_timer(self): + pass def check_state(self): if self.level_obj.at_exit(self.player.pos): # Jump to next level self.level_obj = self.level_list.advance_to_next_level() + self.remove_widget(self.nemesis_tile) self.nemesis.reset_pos() if self.level_obj: self.level_obj.load_tiles() self.player.pos = self.level_obj.enter_pos self.remove_widget(self.player_tile) + self.view.scroll_x = 0 + self.view.scroll_y = 0 self.build() + self.draw_nemesis() + self.draw_player() else: - print 'You won!' - sys.exit(1) + self.app.game_over(True) elif self.nemesis.pos == self.player.pos: # Caught - print 'You lost!' - sys.exit(1) + self.app.game_over(False) def _calc_mouse_pos(self, pos): pos = self.to_local(*pos) @@ -193,23 +234,104 @@ class GameWindow(RelativeLayout): self.mouse_start = pos +class Screen(Widget): + + BACKGROUND = None + START = 'Start' + + def __init__(self, app): + super(Screen, self).__init__() + self.image = load_image(self.BACKGROUND) + self.app = app + with self.canvas: + Rectangle(pos=(0, 0), size=(1026, 760), + texture=self.image.texture) + + self.stop_button = Button( + text='Quit', size=(100, 50), + pos=((1026 - 100) / 2, 650)) + self.stop_button.bind(on_press=self.app.stop_app) + self.start_button = Button( + text=self.START, size=(500, 50), + pos=((1026 - 250) / 2, 600)) + self.start_button.bind(on_press=self.app.start_game) + self.add_widget(self.stop_button) + self.add_widget(self.start_button) + + +class IntroScreen(Screen): + + BACKGROUND = 'screens/intro_screen.png' + START = 'Start the Game' + + +class WonScreen(Screen): + + BACKGROUND = 'screens/won.png' + START = 'Play again?' + + +class LostScreen(Screen): + + BACKGROUND = 'screens/lost.png' + START = 'Retry?' + + class GameApp(App): + title = "Peter's thread snake" + def __init__(self): self.levels = LevelList() super(GameApp, self).__init__() def build(self): - root = ScrollView(size=(640, 480), size_hint=(None, None)) - game = GameWindow(self.levels, root) + root = ScrollView(size_hint=(None, None)) + return root + + def on_start(self): + from kivy.base import EventLoop + window = EventLoop.window + if platform() == 'android': + window.fullscreen = True + self.root.size = window.size + self.make_intro() + + def make_intro(self): + self.root.clear_widgets() + screen = IntroScreen(self) + self.root.add_widget(screen) + + def stop_app(self, button): + self.stop() + + def start_game(self, button): + """Start the game""" + game = GameWindow(self.levels, self) game.build() - root.add_widget(game) + self.root.clear_widgets() + self.root.add_widget(game) # Ensure the player is visible + self.root.scroll_x = 0 + self.root.scroll_y = 0 game.draw_player() - return root + game.draw_nemesis() + + def game_over(self, won): + if won: + screen = WonScreen(self) + self.levels.reset() + else: + screen = LostScreen(self) + self.root.clear_widgets() + self.root.add_widget(screen) def main(): """ Erdslangetjie, a maze game of eluding nemesis """ + if QUIET: + for hdlr in Logger.handlers[:]: + if not isinstance(hdlr, LoggerHistory): + Logger.removeHandler(hdlr) GameApp().run()