7 from kivy.app import App
8 from kivy.core.window import Window
9 from kivy.uix.widget import Widget
10 from kivy.uix.relativelayout import RelativeLayout
11 from kivy.uix.scrollview import ScrollView
12 from kivy.graphics import Color, Rectangle
13 from kivy.utils import platform
15 from erdslangetjie.level import LevelList
16 from erdslangetjie.player import ThePlayer, Nemesis
21 class GameWindow(RelativeLayout):
23 def __init__(self, level_list, view):
24 self.level_list = level_list
25 self.level_obj = self.level_list.get_current_level()
26 self.level_obj.load_tiles()
30 rows, cols = self.level_obj.get_size()
32 super(GameWindow, self).__init__(
33 size=(cols*TILE_SIZE, rows*TILE_SIZE),
34 size_hint=(None, None))
36 self.mouse_move = False
38 self.player = ThePlayer()
39 self.nemesis = Nemesis()
40 if not self.level_obj.enter_pos:
41 raise RuntimeError('No entry point')
42 self.player_tile = None
43 self.nemesis_tile = None
45 self.player.pos = self.level_obj.enter_pos
46 if platform() != 'android':
48 self.keyboard = Window.request_keyboard(self._closed, self)
49 self.keyboard.bind(on_key_down=self._on_key_down)
54 tiles = self.level_obj.get_tiles()
56 for tile_line in tiles:
58 for tile in tile_line:
59 node = Widget(size=(TILE_SIZE, TILE_SIZE),
61 size_hint=(None, None))
65 Rectangle(pos=node.pos, size=node.size,
67 self.tiles[(bx, by)] = node
74 def draw_player(self):
76 self.remove_widget(self.player_tile)
77 sprite_pos = (self.player.pos[0] * TILE_SIZE,
78 self.player.pos[1] * TILE_SIZE)
79 self.player_tile = Widget(size=(TILE_SIZE, TILE_SIZE),
81 with self.player_tile.canvas:
83 Rectangle(pos=sprite_pos, size=self.player_tile.size,
84 texture=self.player.get_texture())
85 self.add_widget(self.player_tile)
86 # Player position in viewpoint coordinates
87 check_point = (sprite_pos[0] + TILE_SIZE / 2,
88 sprite_pos[1] + TILE_SIZE / 2)
89 true_point = self.to_parent(*check_point)
90 if not self.included(true_point):
92 while true_point[0] >= self.view.size[0] - TILE_SIZE:
93 self.pos = (self.pos[0] - 1.5 * TILE_SIZE, self.pos[1])
94 true_point = self.to_parent(*check_point)
95 while true_point[0] < TILE_SIZE:
96 self.pos = (self.pos[0] + 1.5 * TILE_SIZE, self.pos[1])
97 true_point = self.to_parent(*check_point)
98 while true_point[1] >= self.view.size[1] - TILE_SIZE:
99 self.pos = (self.pos[0], self.pos[1] - 1.5 * TILE_SIZE)
100 true_point = self.to_parent(*check_point)
101 while true_point[1] < TILE_SIZE:
102 self.pos = (self.pos[0], self.pos[1] + 1.5 * TILE_SIZE)
103 true_point = self.to_parent(*check_point)
105 def included(self, point):
106 if point[0] < TILE_SIZE:
108 if point[0] >= self.view.pos[0] - TILE_SIZE:
110 if point[1] < TILE_SIZE:
112 if point[1] >= self.view.pos[1] - TILE_SIZE:
115 def draw_nemesis(self):
116 if not self.nemesis.on_board():
118 if self.nemesis_tile:
119 self.remove_widget(self.nemesis_tile)
120 sprite_pos = (self.nemesis.pos[0] * TILE_SIZE,
121 self.nemesis.pos[1] * TILE_SIZE)
122 self.nemesis_tile = Widget(size=(TILE_SIZE, TILE_SIZE),
124 with self.nemesis_tile.canvas:
126 Rectangle(pos=sprite_pos, size=self.nemesis_tile.size,
127 texture=self.nemesis.get_texture())
128 self.add_widget(self.nemesis_tile)
131 self.keyboard.unbind(on_key_down=self._on_key_down)
133 def _on_key_down(self, keyboard, keycode, text, modifiers):
134 # FIXME - likely portablity issues
136 if keycode[0] == pygame.K_UP:
138 elif keycode[0] == pygame.K_DOWN:
140 elif keycode[0] == pygame.K_LEFT:
142 elif keycode[0] == pygame.K_RIGHT:
145 self.do_move(direction)
147 def do_move(self, direction):
148 self.nemesis.move(self.level_obj)
150 self.player.move(direction, self.level_obj)
154 def check_state(self):
155 if self.level_obj.at_exit(self.player.pos):
157 self.level_obj = self.level_list.advance_to_next_level()
158 self.nemesis.reset_pos()
160 self.level_obj.load_tiles()
161 self.player.pos = self.level_obj.enter_pos
162 self.remove_widget(self.player_tile)
167 elif self.nemesis.pos == self.player.pos:
172 def _calc_mouse_pos(self, pos):
173 pos = self.to_local(*pos)
174 return (int(pos[0] / TILE_SIZE), int(pos[1] / TILE_SIZE))
176 def on_touch_down(self, touch):
177 pos = self._calc_mouse_pos(touch.pos)
178 if pos == self.player.pos:
179 self.mouse_move = True
180 self.mouse_start = pos
182 def on_touch_up(self, touch):
183 self.mouse_move = False
185 def on_touch_move(self, touch):
187 pos = self._calc_mouse_pos(touch.pos)
188 if (pos[0] - self.mouse_start[0] != 0) or (
189 pos[1] - self.mouse_start[1] != 0):
190 direction = (pos[0] - self.mouse_start[0],
191 pos[1] - self.mouse_start[1])
192 self.do_move(direction)
193 self.mouse_start = pos
199 self.levels = LevelList()
200 super(GameApp, self).__init__()
203 root = ScrollView(size=(640, 480), size_hint=(None, None))
204 game = GameWindow(self.levels, root)
206 root.add_widget(game)
207 # Ensure the player is visible
213 """ Erdslangetjie, a maze game of eluding nemesis