3 # troncode - write programs to play the classic lines game
5 # Copyright (C) 2008 Andy Balaam
7 # This program is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License
9 # as published by the Free Software Foundation; either version 2
10 # of the License, or (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
27 from pygame
.locals import *
32 from mopelib
import mopelib
33 from player_human
import HumanPlayer
34 from player_null
import NullPlayer
35 from player_turnright
import TurnRightPlayer
36 from troncode_values
import *
38 # ----------------------
39 class TronCodeConfig( mopelib
.Config
):
41 def default_config( self
):
45 self
.screen_size
= ( 640, 480 )
46 self
.colour_background
= ( 15, 45, 15 )
51 self
.sound_effects_on
= 1
53 self
.keys_menu
= mopelib
.MyInputEvent( "Escape" )
54 self
.keys_menu
.add( pygame
.KEYDOWN
, pygame
.K_ESCAPE
)
55 self
.keys_menu
.add( pygame
.JOYBUTTONDOWN
, 8 ) # GP2X Start
56 self
.keys_menu
.add( pygame
.JOYBUTTONDOWN
, 9 ) # GP2X Select
58 self
.keys_return
= mopelib
.MyInputEvent( "Return" )
59 self
.keys_return
.add( pygame
.KEYDOWN
, pygame
.K_RETURN
)
60 self
.keys_return
.add( pygame
.JOYBUTTONDOWN
, 13 ) # GP2X B button
62 self
.keys_startgame
= mopelib
.MyInputEvent( "any key" )
63 self
.keys_startgame
.add_all( pygame
.KEYDOWN
)
64 self
.keys_startgame
.add_all( pygame
.JOYBUTTONDOWN
)
65 self
.keys_startgame
.add_all( pygame
.MOUSEBUTTONDOWN
)
67 self
.keys_up
= mopelib
.MyInputEvent( "up" )
68 self
.keys_up
.add( pygame
.KEYDOWN
, ord( 'q' ) )
69 self
.keys_up
.add( pygame
.KEYDOWN
, pygame
.K_UP
)
70 self
.keys_up
.add( pygame
.JOYBUTTONDOWN
, 0 ) # GP2X Joy up
71 self
.keys_up
.add( pygame
.JOYBUTTONDOWN
, 15 ) # GP2X Y button
73 self
.keys_right
= mopelib
.MyInputEvent( "right" )
74 self
.keys_right
.add( pygame
.KEYDOWN
, ord( 'p' ) )
75 self
.keys_right
.add( pygame
.KEYDOWN
, pygame
.K_RIGHT
)
76 self
.keys_right
.add( pygame
.JOYBUTTONDOWN
, 6 ) # GP2X Joy right
77 self
.keys_right
.add( pygame
.JOYBUTTONDOWN
, 13 ) # GP2X B button
79 self
.keys_down
= mopelib
.MyInputEvent( "down" )
80 self
.keys_down
.add( pygame
.KEYDOWN
, ord( 'a' ) )
81 self
.keys_down
.add( pygame
.KEYDOWN
, pygame
.K_DOWN
)
82 self
.keys_down
.add( pygame
.JOYBUTTONDOWN
, 4 ) # GP2X Joy down
83 self
.keys_down
.add( pygame
.JOYBUTTONDOWN
, 14 ) # GP2X X button
85 self
.keys_left
= mopelib
.MyInputEvent( "left" )
86 self
.keys_left
.add( pygame
.KEYDOWN
, ord( 'o' ) )
87 self
.keys_left
.add( pygame
.KEYDOWN
, pygame
.K_LEFT
)
88 self
.keys_left
.add( pygame
.JOYBUTTONDOWN
, 2 ) # GP2X Joy left
89 self
.keys_left
.add( pygame
.JOYBUTTONDOWN
, 12 ) # GP2X A button
91 self
.keys_volup
= mopelib
.MyInputEvent( "+" )
92 self
.keys_volup
.add( pygame
.KEYDOWN
, ord( '+' ) )
93 self
.keys_volup
.add( pygame
.KEYDOWN
, ord( '=' ) )
94 self
.keys_volup
.add( pygame
.JOYBUTTONDOWN
, 16 ) # GP2X volume + button
96 self
.keys_voldown
= mopelib
.MyInputEvent( "-" )
97 self
.keys_voldown
.add( pygame
.KEYDOWN
, ord( '-' ) )
98 self
.keys_voldown
.add( pygame
.JOYBUTTONDOWN
, 17 ) # GP2X volume - button
100 self
.keys_p1_up
= mopelib
.MyInputEvent( "p1_up" )
101 self
.keys_p1_up
.add( pygame
.KEYDOWN
, pygame
.K_UP
)
102 self
.keys_p1_up
.add( pygame
.JOYBUTTONDOWN
, 0 ) # GP2X Joy up
104 self
.keys_p1_right
= mopelib
.MyInputEvent( "p1_right" )
105 self
.keys_p1_right
.add( pygame
.KEYDOWN
, pygame
.K_RIGHT
)
106 self
.keys_p1_right
.add( pygame
.JOYBUTTONDOWN
, 6 ) # GP2X Joy right
108 self
.keys_p1_down
= mopelib
.MyInputEvent( "p1_down" )
109 self
.keys_p1_down
.add( pygame
.KEYDOWN
, pygame
.K_DOWN
)
110 self
.keys_p1_down
.add( pygame
.JOYBUTTONDOWN
, 4 ) # GP2X Joy down
112 self
.keys_p1_left
= mopelib
.MyInputEvent( "p1_left" )
113 self
.keys_p1_left
.add( pygame
.KEYDOWN
, pygame
.K_LEFT
)
114 self
.keys_p1_left
.add( pygame
.JOYBUTTONDOWN
, 4 ) # GP2X Joy left
116 self
.keys_p2_up
= mopelib
.MyInputEvent( "p2_up" )
117 self
.keys_p2_up
.add( pygame
.KEYDOWN
, ord( '2' ) )
118 self
.keys_p2_up
.add( pygame
.JOYBUTTONDOWN
, 15 ) # GP2X Y button
120 self
.keys_p2_right
= mopelib
.MyInputEvent( "p2_right" )
121 self
.keys_p2_right
.add( pygame
.KEYDOWN
, ord( 'e' ) )
122 self
.keys_p2_right
.add( pygame
.JOYBUTTONDOWN
, 13 ) # GP2X B button
124 self
.keys_p2_down
= mopelib
.MyInputEvent( "p2_down" )
125 self
.keys_p2_down
.add( pygame
.KEYDOWN
, ord( 'w' ) )
126 self
.keys_p2_down
.add( pygame
.JOYBUTTONDOWN
, 14 ) # GP2X X button
128 self
.keys_p2_left
= mopelib
.MyInputEvent( "p2_left" )
129 self
.keys_p2_left
.add( pygame
.KEYDOWN
, ord( 'q' ) )
130 self
.keys_p2_left
.add( pygame
.JOYBUTTONDOWN
, 12 ) # GP2X A button
132 self
.keys_p3_up
= mopelib
.MyInputEvent( "p3_up" )
133 self
.keys_p3_up
.add( pygame
.KEYDOWN
, ord( 'i' ) )
135 self
.keys_p3_right
= mopelib
.MyInputEvent( "p3_right" )
136 self
.keys_p3_right
.add( pygame
.KEYDOWN
, ord( 'l' ) )
138 self
.keys_p3_down
= mopelib
.MyInputEvent( "p3_down" )
139 self
.keys_p3_down
.add( pygame
.KEYDOWN
, ord( 'k' ) )
141 self
.keys_p3_left
= mopelib
.MyInputEvent( "p3_left" )
142 self
.keys_p3_left
.add( pygame
.KEYDOWN
, ord( 'j' ) )
144 self
.keys_p4_up
= mopelib
.MyInputEvent( "p4_up" )
145 self
.keys_p4_up
.add( pygame
.KEYDOWN
, pygame
.K_KP8
)
147 self
.keys_p4_right
= mopelib
.MyInputEvent( "p4_right" )
148 self
.keys_p4_right
.add( pygame
.KEYDOWN
, pygame
.K_KP6
)
150 self
.keys_p4_down
= mopelib
.MyInputEvent( "p4_down" )
151 self
.keys_p4_down
.add( pygame
.KEYDOWN
, pygame
.K_KP5
)
152 self
.keys_p4_down
.add( pygame
.KEYDOWN
, pygame
.K_KP2
)
154 self
.keys_p4_left
= mopelib
.MyInputEvent( "p4_left" )
155 self
.keys_p4_left
.add( pygame
.KEYDOWN
, pygame
.K_KP4
)
158 # ----------------------
160 class TronCodeSoundManager( mopelib
.SoundManager
):
162 def __init__( self
, volume
):
163 mopelib
.SoundManager
.__init
__( self
, config
)
165 #self.add_sample_group( "waddles", ["waddle1"] )
167 # ----------------------
169 def intro_draw_instructions():
170 write_text( "Press %s for menu, or %s to start" % (
171 config
.keys_menu
.name
, config
.keys_startgame
.name
),
172 (0, 0, 0), 0.05, 0.99 )
174 # ----------------------
176 def general_menu_create_menu( menu
, config
, gamestate
):
178 if gamestate
== None: # We are on a title screen - Start Game option
179 menu
.add_item( "Start game", MENU_START
)
180 menu
.add_item( "Number of players: %d" % (config
.num_players
),
182 for player_num
in range( config
.num_players
):
183 cls_name
= "--unknown--"
184 if player_num
< len( config
.player_classes
):
185 cls_name
= config
.player_classes
[player_num
].GetName()
186 menu
.add_item( "P%d: %s" % ( player_num
, cls_name
),
187 MENU_CHANGE_PLAYER
+ player_num
)
189 menu
.add_item( "Continue", MENU_START
)
190 menu
.add_item( "End game", MENU_END
)
197 menu
.add_item( tmp_str
, MENU_MUSIC
)
199 tmp_str
= "Effects: "
200 if config
.sound_effects_on
:
204 menu
.add_item( tmp_str
, MENU_SOUND_EFFECTS
)
206 menu
.add_item( "Quit troncode", MENU_QUIT
)
210 def general_menu_screen( config
, gamestate
):
212 if gamestate
== None:
213 menu_title
= "troncode"
215 menu_title
= "troncode paused"
217 menu
= mopelib
.Menu()
218 general_menu_create_menu( menu
, config
, gamestate
)
219 menurender
.set_menu( menu
, menu_title
)
220 menurender
.repaint_full()
226 event
= pygame
.event
.wait()
227 if event
.type == QUIT
:
229 elif config
.keys_menu
.matches( event
):
231 elif config
.keys_down
.matches( event
):
232 menurender
.move_down()
233 elif config
.keys_up
.matches( event
):
235 elif config
.keys_return
.matches( event
):
236 code
= menu
.get_selected_item().code
237 if code
== MENU_START
:
240 elif code
== MENU_END
:
241 gamestate
.alive
= INGAME_QUIT
243 elif code
== MENU_MUSIC
:
244 if config
.music_on
== 1:
248 general_menu_create_menu( menu
, config
, gamestate
)
249 menurender
.repaint_full()
250 sound_mgr
.setup( gamestate
)
252 elif code
== MENU_SOUND_EFFECTS
:
253 if config
.sound_effects_on
:
254 config
.sound_effects_on
= 0
256 config
.sound_effects_on
= 1
257 general_menu_create_menu( menu
, config
, gamestate
)
258 menurender
.repaint_full()
259 sound_mgr
.setup( gamestate
)
261 elif code
== MENU_QUIT
:
266 # ----------------------
268 def intro_draw_title():
269 screen
.blit( intro_surface_title
, (0,0) )
270 write_text( "Version " + troncode_version
,
271 ( 0, 0, 0 ), 0.05, 0.88 )
272 write_text( "by Andy Balaam", ( 0, 0, 0 ), 0.06, 0.93 )
273 intro_draw_instructions()
275 def intro_draw_something( intro_mode
):
276 if intro_mode
== INTRO_MODE_TITLE
:
278 elif intro_mode
== INTRO_MODE_INSTR
:
279 screen
.blit( intro_surface_instr
, (0,0) )
280 intro_draw_instructions()
281 elif intro_mode
== INTRO_MODE_MUSIC
:
282 screen
.blit( intro_surface_music
, (0,0) )
283 intro_draw_instructions()
284 pygame
.display
.update()
286 def intro_input( event
, config
, intro_mode
):
287 if event
.type == QUIT
:
289 elif config
.keys_volup
.matches( event
):
290 config
.volume
= sound_mgr
.increase_volume()
292 elif config
.keys_voldown
.matches( event
):
293 config
.volume
= sound_mgr
.decrease_volume()
296 if event
.type == EVENTTYPE_TITLE_TICK
:
298 if intro_mode
== INTRO_MODE_ENDED
:
299 intro_mode
= INTRO_MODE_TITLE
300 intro_draw_something( intro_mode
)
301 elif config
.keys_menu
.matches( event
):
302 mopelib
.clear_events( EVENTTYPE_TITLE_TICK
)
303 start_game
= general_menu_screen( config
, None )
305 intro_mode
= INTRO_MODE_ENDED
307 intro_draw_something( intro_mode
)
308 pygame
.time
.set_timer( EVENTTYPE_TITLE_TICK
, TITLE_TICK_TIME
)
309 elif config
.keys_startgame
.matches( event
):
310 intro_mode
= INTRO_MODE_ENDED
313 # ----------------------
315 def intro_mainloop( config
):
318 pygame
.display
.update()
319 pygame
.time
.set_timer( EVENTTYPE_TITLE_TICK
, TITLE_TICK_TIME
)
321 intro_mode
= INTRO_MODE_TITLE
322 while intro_mode
< INTRO_MODE_ENDED
:
323 intro_mode
= intro_input( pygame
.event
.wait(), config
, intro_mode
)
325 mopelib
.clear_events( EVENTTYPE_TITLE_TICK
)
327 def draw_pixel( gamestate
, surface
, colour
, x
, y
):
328 col
= mopelib
.dim_colour( colour
, gamestate
.dim
)
329 adj_x
= screen_border
[0] + scale
* x
330 adj_y
= screen_border
[1] + scale
* y
332 surface
.set_at( ( int(adj_x
), int(adj_y
) ), col
)
334 pygame
.draw
.rect( surface
, col
,
335 (adj_x
, adj_y
, ceil_scale
, ceil_scale
) )
337 def inlevel_screen_blit( gamestate
):
338 screen
.blit( gamestate
.offscreen_buff
, (0,0) )
339 write_text_ingame( gamestate
)
340 pygame
.display
.update()
342 def inlevel_redraw_screen( gamestate
, arrows
):
343 gamestate
.offscreen_buff
= pygame
.Surface( gamestate
.config
.screen_size
)
344 gamestate
.offscreen_buff
.blit( ingame_surface_background
, (0,0) )
345 for x
, y
, colour
in gamestate
.pixels_list
:
346 draw_pixel( gamestate
, gamestate
.offscreen_buff
, colour
, x
, y
)
347 inlevel_draw_players( gamestate
)
349 inlevel_screen_blit( gamestate
)
351 def inlevel_draw_players( gamestate
):
352 for player
in gamestate
.players
:
353 x
, y
= gamestate
.GetPosition( player
)
354 draw_pixel( gamestate
, gamestate
.offscreen_buff
, player
.GetColour(),
357 def inlevel_update_screen( gamestate
):
358 inlevel_draw_players( gamestate
)
359 inlevel_screen_blit( gamestate
)
363 # ----------------------
365 def inlevel_input( event
, gamestate
):
366 if event
.type == QUIT
:
368 elif( ( event
.type == pygame
.ACTIVEEVENT
and event
.state
== 2 )
369 or config
.keys_menu
.matches( event
) ):
370 general_menu_screen( config
, gamestate
)
371 inlevel_redraw_screen( gamestate
, False )
372 elif config
.keys_volup
.matches( event
):
373 config
.volume
= sound_mgr
.increase_volume()
375 elif config
.keys_voldown
.matches( event
):
376 config
.volume
= sound_mgr
.decrease_volume()
378 elif event
.type == EVENTTYPE_INGAME_TICK
:
379 gamestate
.timer_tick()
380 gamestate
.key_events
= []
381 if gamestate
.alive
== INGAME_SOMEONE_DEAD
:
382 finishedlevel_mainloop( gamestate
)
384 inlevel_update_screen( gamestate
)
386 gamestate
.key_events
.append( event
)
389 # ----------------------
391 def finishedgame_input( event
, waiting
):
392 if event
.type == QUIT
:
394 elif config
.keys_volup
.matches( event
):
395 config
.volume
= sound_mgr
.increase_volume()
397 elif config
.keys_voldown
.matches( event
):
398 config
.volume
= sound_mgr
.decrease_volume()
400 elif config
.keys_startgame
.matches( event
):
404 # ----------------------
407 def __init__( self
, x
, y
, direction
, player
):
410 self
._dir
= direction
411 self
._colour
= player
.GetColour()
414 def GetPosition( self
):
415 return ( self
._x
, self
._y
)
417 def GetDirection( self
):
420 def SetDirection( self
, direction
):
421 self
._dir
= direction
423 def Move( self
, gamestate
):
424 """Moves the player one position depending on its direction, and
425 returns True if it hit anything, False otherwise."""
427 if self
._dir
== DIR_UP
:
429 elif self
._dir
== DIR_RIGHT
:
431 elif self
._dir
== DIR_DOWN
:
433 elif self
._dir
== DIR_LEFT
:
436 self
._dead
= gamestate
.AddPixel( self
._x
, self
._y
, self
._colour
)
441 def __init__( self
, gamestate
):
442 self
._gamestate
= gamestate
444 def GetRelativePixel( self
, start_pos
, facing_dir
,
445 offset_fwd
, offset_right
):
446 """Given a position to stand in the arena, and a direction to face,
447 return the status (0 for empty, >0 for non-empty) of a pixel that
448 is offset_fwd pixels in front, and offset_right pixels to the right
449 (negative values may be used to go backwards or left respectively).
450 Pixels outside the arena also return >0."""
452 if facing_dir
== DIR_UP
:
453 found_pos
= ( start_pos
[0] + offset_right
,
454 start_pos
[1] - offset_fwd
)
455 elif facing_dir
== DIR_RIGHT
:
456 found_pos
= ( start_pos
[0] + offset_fwd
,
457 start_pos
[1] + offset_right
)
458 elif facing_dir
== DIR_DOWN
:
459 found_pos
= ( start_pos
[0] - offset_right
,
460 start_pos
[1] + offset_fwd
)
461 elif facing_dir
== DIR_LEFT
:
462 found_pos
= ( start_pos
[0] - offset_fwd
,
463 start_pos
[1] - offset_right
)
465 if ( found_pos
[0] < 0 or
466 found_pos
[0] >= self
._gamestate
.config
.arena_size
[0] or
468 found_pos
[1] >= self
._gamestate
.config
.arena_size
[1] ):
470 elif found_pos
in self
._gamestate
.pixels_set
:
478 def TurnRight( self
, direction
):
479 """Return the direction found by turning 90 degrees right from
480 the supplied direction."""
482 if direction
> DIR_LEFT
:
486 def TurnLeft( self
, direction
):
487 """Return the direction found by turning 90 degrees left from
488 the supplied direction."""
490 if direction
< DIR_UP
:
495 def __init__( self
, config
):
500 for cls
in config
.player_classes
:
501 if "IsHuman" in cls
.__dict
__ and cls
.IsHuman():
502 self
.players
.append( cls( config
.keys_p1_up
,
503 config
.keys_p1_right
, config
.keys_p1_down
,
504 config
.keys_p1_left
) )
506 self
.players
.append( cls() )
508 self
.alive
= INGAME_ALL_ALIVE
511 self
.pixels_list
= []
512 self
.pixels_set
= set()
513 self
.create_initial_pixels()
516 for player
in self
.players
:
517 x
= random
.randint( config
.starting_border
, config
.arena_size
[0]
518 - config
.starting_border
)
519 y
= random
.randint( config
.starting_border
, config
.arena_size
[1]
520 - config
.starting_border
)
521 dr
= random
.randint( DIR_UP
, DIR_LEFT
)
522 self
.statuses
[player
] = PlayerStatus( x
, y
, dr
, player
)
523 self
.AddPixel( x
, y
, player
.GetColour() )
525 self
._gameboard
= GameBoard( self
)
527 def timer_tick( self
):
529 for player
in self
.players
:
530 status
= self
.statuses
[player
]
531 if( "IsHuman" in player
.__class
__.__dict
__ and
532 player
.__class
__.IsHuman() ):
533 new_dir
= player
.GetDirWithInput( status
.GetDirection(),
536 new_dir
= player
.GetDir( status
.GetPosition(),
537 status
.GetDirection(), self
._gameboard
)
538 status
.SetDirection( new_dir
)
539 # TODO: copy pixels list for "security"
541 dead
= self
.statuses
[player
].Move( self
)
546 self
.alive
= INGAME_SOMEONE_DEAD
548 def create_initial_pixels( self
):
549 colour
= (200, 200, 200)
550 size_x
, size_y
= config
.arena_size
551 for x
in range( size_x
):
552 self
.AddPixel( x
, 0, colour
)
553 self
.AddPixel( x
, size_y
- 1, colour
)
554 for y
in range( 1, size_y
- 1 ):
555 self
.AddPixel( 0, y
, colour
)
556 self
.AddPixel( size_x
- 1, y
, colour
)
558 def GetPosition( self
, player
):
559 return self
.statuses
[player
].GetPosition()
561 def AddPixel( self
, x
, y
, colour
):
562 if ( x
, y
) in self
.pixels_set
:
566 self
.pixels_set
.add( ( x
, y
) )
568 self
.pixels_list
.append( ( x
, y
, colour
) )
573 # ----------------------
575 def ingame_mainloop( config
):
576 gamestate
= GameState( config
)
577 gamestate
.key_events
= []
578 while gamestate
.alive
== INGAME_ALL_ALIVE
:
579 inlevel_mainloop( config
, gamestate
)
582 # ----------------------
584 def inlevel_mainloop( config
, gamestate
):
586 inlevel_redraw_screen( gamestate
, True )
588 inlevel_redraw_screen( gamestate
, False )
591 pygame
.time
.set_timer( EVENTTYPE_INGAME_TICK
, config
.tick_time
)
592 while gamestate
.alive
== INGAME_ALL_ALIVE
:
593 inlevel_input( pygame
.event
.wait(), gamestate
)
595 mopelib
.clear_events( EVENTTYPE_INGAME_TICK
)
597 ingame_surface_background
.fill( config
.colour_background
)
600 # ----------------------
602 def write_text( txt
, colour
, size
, y_pos
):
603 ft
= pygame
.font
.Font( None, int( config
.screen_size
[1] * size
) )
604 sf
= ft
.render( txt
, True, colour
)
605 screen
.blit( sf
, ( (config
.screen_size
[0] - sf
.get_width() )/2,
606 (config
.screen_size
[1] - sf
.get_height() ) * y_pos
) )
608 # ----------------------
610 def write_text_ingame( gamestate
):
613 #bgcol = mopelib.dim_colour( gamestate.cur_lev.background_colour,
615 #fgcol = mopelib.dim_colour( gamestate.cur_lev.text_colour, gamestate.dim )
617 #write_text_blank_font_coords( "Level: %d" % ( gamestate.level_num + 1 ),
618 # fgcol, ingame_font, bgcol, 0.3, 0.99 )
620 #write_text_blank_font_coords( "Time: %s" % gamestate.cur_lev.current_time,
621 # fgcol, ingame_font, bgcol, 0.7, 0.99 )
625 def write_text_blank_font_coords( txt
, colour
, font
, bgcolour
, x
, y
):
626 sf
= font
.render( txt
, True, colour
)
627 sf_bg
= pygame
.Surface( ( int( sf
.get_width() * 1.29 ), sf
.get_height() ) )
628 sf_bg
.fill( bgcolour
)
630 tlx
= ( config
.screen_size
[0] - sf_bg
.get_width() ) * x
631 tly
= ( config
.screen_size
[1] - sf_bg
.get_height() ) * y
633 dirty_rect
= Rect( tlx
, tly
, sf_bg
.get_width(), sf_bg
.get_height() )
634 screen
.blit( sf_bg
, dirty_rect
)
635 screen
.blit( sf
, ( tlx
* 1.01, tly
) )
637 # ----------------------
639 def finishedlevel_input( event
, waiting
):
640 if event
.type == QUIT
:
642 elif config
.keys_volup
.matches( event
):
643 config
.volume
= sound_mgr
.increase_volume()
645 elif config
.keys_voldown
.matches( event
):
646 config
.volume
= sound_mgr
.decrease_volume()
648 elif config
.keys_startgame
.matches( event
):
652 def finishedlevel_mainloop( gamestate
):
654 inlevel_redraw_screen( gamestate
, False )
657 waiting
= finishedlevel_input( pygame
.event
.wait(), waiting
)
659 def finishedgame_mainloop( config
, gamestate
):
661 #config.start_level = 0
664 # inlevel_redraw_screen( gamestate )
665 # write_text( "Congratulations!", (255,255,255), 0.125, 0.38 )
666 # write_text( "You won!", (255,255,255), 0.125, 0.52 )
668 # write_text( "Press %s" % config.keys_startgame.name, (255,255,255),
670 # pygame.display.update()
672 # waiting = finishedgame_input( pygame.event.wait(), waiting )
674 # ingame_surface_background.fill( config.colour_background )
677 # ----------------------
678 # Execution starts here
679 # ----------------------
692 MENU_SOUND_EFFECTS
= 4
694 MENU_CHANGE_PLAYER
= 100 # Must go at end of this list
697 INGAME_SOMEONE_DEAD
= 1
700 TITLE_TICK_TIME
= 4000
702 EVENTTYPE_INGAME_TICK
= pygame
.USEREVENT
703 EVENTTYPE_TITLE_TICK
= pygame
.USEREVENT
+ 1
705 num_args
= len( sys
.argv
)
707 if sys
.argv
[1] == "--help":
709 print "troncode.py [install_dir] [config_file] [resolution] "
710 print " [num_players] [--tournament]"
712 print "e.g. ./troncode.py . troncoderc.txt '(640,480)' 2 --tournament"
716 install_dir
= sys
.argv
[1]
721 config_filename
= sys
.argv
[2]
723 config_filename
= os
.path
.expanduser( "~/.troncode/config" )
725 config
= TronCodeConfig( config_filename
)
727 config
.install_dir
= install_dir
728 config
.unsaved
.append( "install_dir" )
730 config
.images_dir
= os
.path
.join( install_dir
, "images" )
731 config
.unsaved
.append( "images_dir" )
733 config
.music_dir
= os
.path
.join( install_dir
, "music" )
734 config
.unsaved
.append( "music_dir" )
739 pygame
.mouse
.set_visible( False )
742 config
.screen_size
= config
.parse_value( sys
.argv
[3] )
744 window
= pygame
.display
.set_mode( config
.screen_size
)
745 pygame
.display
.set_caption( 'duckmaze' )
746 screen
= pygame
.display
.get_surface()
748 config
.arena_size
= ( 200, 200 )
749 config
.unsaved
.append( "arena_size" )
751 config
.starting_border
= 35
752 config
.unsaved
.append( "starting_border" )
754 config
.player_classes
= []
755 config
.unsaved
.append( "player_classes" )
756 config
.player_classes
.append( TurnRightPlayer
)
757 config
.player_classes
.append( HumanPlayer
)
760 config
.unsaved
.append( "players" )
764 ( float( config
.screen_size
[0] - fixed_border
*2 )
765 / float( config
.arena_size
[0] ) ),
766 ( float( config
.screen_size
[1] - fixed_border
*2 )
767 / float( config
.arena_size
[1] ) ) )
769 screen_border
= ( float( config
.screen_size
[0] - config
.arena_size
[0]*scale
)
771 float( config
.screen_size
[1] - config
.arena_size
[1]*scale
) / 2.0, )
773 ceil_scale
= math
.ceil( scale
)
775 # General initialisation
777 num_joysticks
= pygame
.joystick
.get_count()
778 for j
in range( num_joysticks
):
779 pygame
.joystick
.Joystick( j
).init()
781 intro_surface_title
= mopelib
.load_and_scale_image( "title.png", config
)
782 intro_surface_instr
= mopelib
.load_and_scale_image( "instructions.png", config
)
783 intro_surface_music
= mopelib
.load_and_scale_image( "music.png", config
)
785 ingame_surface_background
= pygame
.Surface( screen
.get_size() ).convert()
786 ingame_surface_background
.fill( config
.colour_background
)
788 intro_mode
= INTRO_MODE_TITLE
790 sound_mgr
= TronCodeSoundManager( config
.volume
)
792 troncode_version
= mopelib
.read_version( config
)
794 ingame_font
= pygame
.font
.Font( None, int( config
.screen_size
[1] * 0.09 ) )
796 menurender
= mopelib
.MenuRenderer( screen
, config
, ingame_surface_background
,
797 (128, 128, 128), (128, 255, 128), (128, 128, 128) )
800 sound_mgr
.music_loud()
801 intro_mainloop( config
)
802 sound_mgr
.music_quiet()
803 gamestate
= ingame_mainloop( config
)
804 intro_mode
= finishedgame_mainloop( config
, gamestate
)