1 '''
2 controller.py
3
4 contrains the game controller
5 to play the game, run game.py
6 '''
7
8 from cocos.director import director
9 from cocos.layer import *
10 from cocos import collision_model
11 from pyglet.window import key
12 from cocos import audio
13 import cocos.euclid as eu
14 from cocos import tiles
15
16 from constants import *
17 from models import *
18 from maps import Vertex, Map
19 from utils import *
20 from imageLayer import *
21 from game_layers import *
22 from player import *
23 from tutorial import *
24
25 from music import theme_player
26
27 import os
28
29 options = {
30 "humanPlayerNum": 1,
31 "aiPlayerNum": 1
32 }
33
35 is_event_handler = True
36
38 super(GameController, self).__init__()
39 self.selectedUnits = []
40
41 self.map = Map(os.path.join("maps", "level1.map"))
42 self.map.draw_map()
43 self.cm = collision_model.CollisionManagerGrid(
44 0.0, self.map.w * CELL_SIZE, 0.0, self.map.h * CELL_SIZE, 32.0, 32.0)
45 self.map.cm = self.cm
46
47 self.scroller = ScrollingManager(viewport=director.window)
48 self.scroller.add(self.map)
49
50
51
52 self.scroller.set_focus((self.map.w * CELL_SIZE) /
53 16, (self.map.h * CELL_SIZE) / 16)
54 self.infoLayer = InfoLayer(self.map, self.scroller, None)
55 self.statusMenu = StatusMenu()
56 self.add(self.infoLayer)
57
58 self.curAction = None
59
60 self.level = 1
61 self.tutorial = Tutorial(self.level, self)
62
63 self.horizontalSize = CELL_SIZE * self.map.w
64 self.verticalSize = CELL_SIZE * self.map.h
65
66
67
68
69 self.is_shake_selected = False
70 self.source_handshake = None
71 self.handshake_units_selected = []
72
73
74 if self.horizontalSize < WINDOW_WIDTH:
75 self.horizontalSize = WINDOW_WIDTH
76 if self.verticalSize < WINDOW_HEIGHT:
77 self.verticalSize = WINDOW_HEIGHT
78
80 super(GameController, self).on_enter()
81
82
83
84 self.player = Player(0, self.map, self.cm, PLAYER_COLORS[0])
85 self.player.setup(
86 )
87
88 self.ai = ComputerPlayer(
89 1, self.map, self.cm, PLAYER_COLORS[1], self.player)
90 self.ai.setup(
91 )
92
93 self.players = [self.player, self.ai]
94 self.infoLayer.player = self.player.ID
95 self.ai.run_basic_ai()
96
97
98 if SHOW_TUTORIAL:
99 self.tutorial.first_prompt("on_enter")
100 self.player.push_handlers(
101 self.tutorial.player_add_troop, self.tutorial.player_unit_attack, self.tutorial.player_add_building)
102 self.push_handlers(
103 self.tutorial.click_on_move, self.tutorial.click_on_action)
104
105 self.player.push_handlers(self.on_loss)
106 self.ai.push_handlers(self.on_loss)
107
108 for player in self.players:
109 self.schedule(player.step)
110 self.schedule(self.step)
111
112 self.bindings = {
113 key.LEFT: 'left',
114 key.RIGHT: 'right',
115 key.UP: 'up',
116 key.DOWN: 'down'
117 }
118
119 self.buttons = {
120 'left': 0,
121 'right': 0,
122 'up': 0,
123 'down': 0
124 }
125
126 self.mouse_flag = {
127 'x': 0,
128 'y': 0
129 }
130
132 if loser.ID == 0:
133 director.push(Scene(self.lost))
134 else:
135 director.push(Scene(self.won))
136
137 - def step(self, dt):
138
139 if self.mouse_flag["x"] == 0 and self.mouse_flag["y"] == 0:
140 buttons = self.buttons
141 move_dir = eu.Vector2(buttons['right'] - buttons['left'],
142 buttons['up'] - buttons['down'])
143 else:
144 move_dir = eu.Vector2(self.mouse_flag['x'], self.mouse_flag['y'])
145 newPos = move_dir.normalize() * dt * MAP_SCROLL_SPEED
146 newx, newy = self.clamp(newPos)
147 self.scroller.set_focus(newx, newy)
148
150 x, y = pos
151 newx = self.scroller.fx + x
152 newy = self.scroller.fy + y
153 if newx <= 1:
154 newx = 1.0
155 elif newx >= self.horizontalSize - WINDOW_WIDTH:
156 newx = self.horizontalSize - WINDOW_WIDTH + 1.0
157 if newy <= 1:
158 newy = 1.0
159 elif newy >= self.verticalSize - WINDOW_HEIGHT:
160 newy = self.verticalSize - WINDOW_HEIGHT + 1.0
161 return newx, newy
162
182
184 if k == key.ESCAPE:
185 theme_player.fadeout()
186
187 binds = self.bindings
188 if k in binds:
189 self.buttons[binds[k]] = 1
190 return True
191 return False
192
194
195
196
197 selType = None
198
199 if len(self.selectedUnits) > 0:
200 selType = type(self.selectedUnits[0])
201
202 actNum = None
203 if selType != None and issubclass(selType, Troop):
204 actNum = {
205 key.A: 0,
206 key.S: 1,
207 key.D: 2
208 }.get(k, None)
209 elif selType != None and issubclass(selType, Building):
210 actNum = {
211 key.Q: 7,
212 key.W: 3,
213 key.E: 5,
214 key.A: 1,
215 key.D: 0,
216 key.Z: 6,
217 key.X: 2,
218 key.C: 4,
219 }.get(k, None)
220
221 if actNum != None:
222
223
224
225 for unit in self.selectedUnits:
226
227
228 if actNum < len(unit.actionList):
229
230
231
232 self.execute_action(unit.actionList[actNum], unit)
233
234
235 binds = self.bindings
236 if k in binds:
237 self.buttons[binds[k]] = 0
238 return True
239 return False
240
241
242
243
244
245
246
248
249
250
251
252
253 if self.statusMenu.cm.objs_touching_point(x,y):
254 director.pop()
255
256 if self.infoLayer.miniMapToggled:
257
258
259 minimap = self.infoLayer.cm.objs_touching_point(
260 x - self.infoLayer.position[0], y - self.infoLayer.position[1])
261 if self.infoLayer.miniMap in minimap:
262 return
263 x, y = self.scroller.pixel_from_screen(x, y)
264 clicked_units = self.cm.objs_touching_point(x, y)
265
266 for unit in clicked_units:
267 if type(unit) == SurrenderButton:
268 director.push(Scene(self.lost))
269
270
271
272 if buttons == 1:
273
274 actionButton = get_action_button_clicked(clicked_units)
275 if actionButton:
276
277 self.execute_action(actionButton.name, actionButton.unitParent)
278 elif clicked_units:
279 if self.curAction:
280
281 self.player.unit_attack(self.selectedUnits, clicked_units)
282 self.curAction = None
283 else:
284
285
286 self.select_units(clicked_units)
287 if constants.SOUND:
288 self.play_sound("click_troop.wav")
289
290 if clicked_units != set([]) and self.selectedUnits != []:
291 if buttons == 4:
292
293 self.execute_move(clicked_units)
294 return True
295
297
298 unitsToDeselect = []
299 for unit in self.selectedUnits:
300 if issubclass(type(unit), unitType):
301 unitsToDeselect.append(unit)
302 if unitsToDeselect != []:
303 self.player.switch_units_select_state(
304 unitsToDeselect, self.selectedUnits)
305
307
308
309 if len(clicked_units) >= 1:
310 clicked = None
311 for item in clicked_units:
312 if type(item) == Vertex:
313 clicked = item
314 break
315 else:
316 clicked = item
317
318
319 if type(clicked) == Handshake:
320
321 if(self.source_handshake != None):
322 if self.source_handshake == clicked:
323 self.is_shake_selected = False
324
325 if self.is_shake_selected:
326
327 adjacency_vid_list = []
328 for vertex in self.source_handshake.curVertex.adjacentVertices:
329 adjacency_vid_list.append(vertex.vid)
330
331
332 if clicked.curVertex.vid not in adjacency_vid_list:
333 dest_handshake = clicked
334 edge = self.source_handshake.shake(dest_handshake, self.map)
335 self.cm.remove_tricky(self.source_handshake)
336 self.cm.remove_tricky(dest_handshake)
337 self.is_shake_selected = False
338 self.source_handshake = None
339 else:
340 utils.play_sound("error.wav")
341 self.player.switch_units_select_state(
342 [clicked], self.selectedUnits)
343 self.is_shake_selected = False
344 pass
345 else:
346 self.is_shake_selected = False
347 self.source_handshake = None
348
349
350 if type(clicked) == Vertex:
351
352 self.__deselect_units_of_type(self.selectedUnits, Building)
353 self.player.switch_units_select_state(
354 clicked.troops, self.selectedUnits)
355
356 elif issubclass(type(clicked), Unit) and clicked.pid == 0:
357
358
359
360 if issubclass(type(clicked), Building):
361 if type(clicked) == SoftwareUpdater:
362 self.player.update_research_action_button(clicked)
363 if type(clicked) == AlgorithmFactory:
364 self.player.update_troop_action_button(clicked)
365 self.__deselect_units_of_type(self.selectedUnits, Troop)
366 elif issubclass(type(clicked), Troop):
367 self.__deselect_units_of_type(self.selectedUnits, Building)
368
369 self.player.switch_units_select_state(
370 [clicked], self.selectedUnits)
371
372 else:
373
374
375 self.player.switch_units_select_state(
376 clicked_units, self.selectedUnits)
377
379
380
381 dest = None
382 while type(dest) != Vertex and clickedUnits != ():
383 dest = clickedUnits.pop()
384 if type(dest) == Vertex:
385 for selectedUnit in self.selectedUnits:
386 if issubclass(type(selectedUnit), Troop):
387 if selectedUnit.player_move(dest, self.map, self.cm) == True and constants.SOUND:
388
389 self.play_sound("Move.wav")
390 selectedUnit.set_is_selected(False, self.map, self.cm, self.player)
391 self.selectedUnits = []
392 self.dispatch_event("click_on_move", type(selectedUnit), dest.vid)
393
395
396
397 self.curAction = None
398
399 self.player.switch_units_select_state([unit], self.selectedUnits)
400 if actionName[0] == "B":
401
402 if self.player.execute_build_building(actionName[1:], unit, self.selectedUnits) and constants.SOUND:
403 self.play_sound("Clock.wav")
404 elif actionName[0] == "T":
405
406 if self.player.execute_build_troop(actionName[1:], unit, self.selectedUnits) and constants.SOUND:
407 self.play_sound("Clock.wav")
408 elif actionName[0] == "R":
409
410 if self.player.perform_research(actionName, unit, self.cm) and constants.SOUND:
411 self.play_sound("Clock.wav")
412
413 elif actionName == "USinkhole":
414 unit.upgrade_to_sinkhole(self.player)
415 elif actionName == "UPingOfDeath":
416 unit.upgrade_to_pod(self.player)
417 elif actionName == "UNMap":
418 unit.upgrade_to_nmap(self.player)
419
420
421 elif actionName == "Shake":
422 self.is_shake_selected = True
423 self.source_handshake = unit
424
425
426
427
428
429
430
431
432
433
434 elif actionName == "DEL":
435
436 if issubclass(type(unit), Server):
437 if self.player.numServers == 1:
438 self.add_surrender_button(unit)
439 if constants.SOUND:
440 self.play_sound("Eraser.wav")
441 self.player.on_destruction(unit, self.selectedUnits)
442 elif actionName == "CANCEL":
443 self.player.cancel_cpu(unit)
444 elif actionName == "Encrypt":
445 unit.encrypt(unit.curVertex.troops, self.player)
446 elif actionName == "Decrypt":
447 unit.decrypt(self.player)
448 elif actionName == "Ping":
449 unit.ping(self.player.on_destruction, self.map, self.cm)
450
451 else:
452 self.curAction = actionName
453
454 self.dispatch_event("click_on_action", actionName)
455
457 sound = pyglet.resource.media('sounds/' + filename, streaming=False)
458 sound.play()
459
460
468
469
470 GameController.register_event_type("click_on_move")
471 GameController.register_event_type("click_on_action")
472