示例#1
0
class GameState (State):
    def __init__(self, window, level, diff, pair_generator, win_conditions, *args, **kwargs):
        print "++++ new game state"
        self.level = level
        self.diff = diff
        self.pair_generator = pair_generator
        self.win_conditions = win_conditions
        State.__init__(self, window, "game", *args, **kwargs)
        self.build_scene()
        self.current_rung = None
        self.longest_streak = 0
        self.time = 0
        self.mutation_counter = 0
        
    def build_scene(self):
        self.camera = Camera((0.0, -8.0, 1.0), (0,0,1.0))
        self.score = Score(0)
        self.streak = Streak(0)
        self.atcg_display = ATCGDisplay()
        self.endzone = EndZone((-1.4,0,-1.3), 2.8, 0.18)
        self.attaboy = MsgQueue()
        self.mutation = Mutation(0)
        if self.win_conditions.has_key('time'):
            self.timer = Timer(self.win_conditions['time'])	
        else:
            self.timer = None
#        speed_dif = self.level * 0.07 * (self.diff*0.8)
#        spawn_dif = self.level * 0.07 + (self.diff*0.03)

## lower down        
#        self.helix = Helix(speed = 0.7 + speed_dif, spawn_rate=0.7-spawn_dif,
#            starthgt=7, endhgt=-5, spins=2.5, pair_generator=self.pair_generator)
        if self.level >= 4:
            starthgt = 7
            endhgt = -2.5
            spins = 2.5
        else:
            starthgt = 5
            endhgt = -2.5
            spins = 1.5  

        l, d = self.level, self.diff 
        speed_dif = 0.8 + (l * 0.04 * (d*0.6))
        spawn_dif = 0.5 - (l * 0.07 * (d*0.09))

        self.helix = Helix(speed = speed_dif, spawn_rate=spawn_dif,
            starthgt=starthgt, endhgt=endhgt, spins=spins, pair_generator=self.pair_generator)
        self.helix.register_callbacks(self.enter_callback, self.exit_callback)
#        for n in range(100):
#            self.helix.update(0.1)

        
        self.attaboy.add_centered_fade("level %d\n%s\n%s" % (self.level,
            diff[self.diff], messages.EASY_LEVELS[self.level]), 0.2, 0.1)

    def enter_callback(self, r):
        self.current_rung = r

    def exit_callback(self, r):
        if r.get_pair_data()[0] == None or r.get_pair_data()[1] == None:
            self.bad_move()
        self.current_rung = None
        

    def destroy_scene(self):
        pass

    def on_draw(self):
        set3D(self.window)
        self.window.clear()
        glLoadIdentity()
        self.camera.focus()
        batch.get_batch().draw()
        set2D(self.window)
        return pyglet.event.EVENT_HANDLED

    def bad_move(self):
        audio.play_sound('lose_streak')
        r = self.current_rung
        if r:
            r.miss()
        self.camera.shake(1,2, 1)
        self.attaboy.add_centered_fade(messages.random_bad_move(), 0.25, 1, ([0.7,0.7,0.7,1.0], [0.1,0.1,0.1,1.0]))
        self.streak.reset()
        l, d = self.level, self.diff 
        self.helix.mutate(0.2 + (l * 0.04))
        self.mutation_counter += 5 * (self.level*0.5)
        if self.mutation_counter > 100:
            self.lose()
        self.mutation.set_mutation(self.mutation_counter)

    def good_move(self):
        audio.play_sound('hit')
        r = self.current_rung
        if r:
            r.hit()
        if self.mutation_counter > 1:
            self.mutation_counter -= 1
            self.mutation.set_mutation(self.mutation_counter)
        s = self.streak.inc()
        p = s*0.5*100
        self.attaboy.add_score_fade(p)
        self.score.inc_score(p)

    def on_key_press(self, k, args):
## =A++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++===
        if k == key.A:
            self.atcg_display.A.on()
            if check_hit('A', self.current_rung):
                self.good_move()
            else:
                self.bad_move()
## =S++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++===                
        elif k == key.S:
            self.atcg_display.T.on()
            if check_hit('T', self.current_rung):
                self.good_move()
            else:
                self.bad_move()
## =D++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=== 
        elif k == key.D:
            self.atcg_display.C.on()
            if check_hit('C', self.current_rung):
                self.good_move()
            else:
                self.bad_move()
## =F++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++===             
        elif k == key.F:
            self.atcg_display.G.on()
            if check_hit('G', self.current_rung):
                self.good_move()
            else:
                self.bad_move()
## ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=

        elif k == key.LEFT:
            pass
        elif k == key.RIGHT:
            pass
        elif k == key.ESCAPE:
            self.pause()
            return pyglet.event.EVENT_HANDLED
        elif k == key.F11:
            if self.window.fullscreen:
                self.window.set_fullscreen(False)
            else:
                self.window.set_fullscreen(True)
        return pyglet.event.EVENT_HANDLED


    def on_key_release(self, k, args):
        if k == key.A:
            self.atcg_display.A.off()
        elif k == key.S:
            self.atcg_display.T.off()
        elif k == key.D:
            self.atcg_display.C.off()
        elif k == key.F:
            self.atcg_display.G.off()
        return pyglet.event.EVENT_HANDLED

    def on_mouse_scroll(self, x, y, scroll_x, scroll_y):
        pass

    def lose(self):
        self.window.pop_state()
        self.window.replace_state(transitions.ScriptedTransition, script=script.lose, script_name="lose")

    def win(self):
        self.window.replace_state(transitions.ScriptedTransition, script=script.win, script_name="win")
        
    def on_lose_focus(self):
        pyglet.clock.unschedule(self.on_update)
        return pyglet.event.EVENT_HANDLED

    def on_gain_focus(self):
        self.helix.unobscure()
        self.helix.update(0.1)
        pyglet.clock.schedule_interval(self.on_update, 1.0/60.0)
        return pyglet.event.EVENT_HANDLED

    def check_win_conditions(self):
        if self.win_conditions.has_key('score'):
            if self.score.points > self.win_conditions['score']:
                self.win()
        elif self.win_conditions.has_key('streak'):
            if self.streak.streak >= self.win_conditions['streak']:
                self.win()
        elif self.win_conditions.has_key('time'):
            if self.timer.time < 0:
                self.win()
    
    def on_update(self, dt):
        self.camera.update(dt)
        self.attaboy.update(dt)
        self.atcg_display.update(dt)
        self.check_win_conditions()
        self.helix.update(dt)
        if self.win_conditions.has_key('time'):
            self.timer.update_time(dt)


    def pause(self):
        self.helix.obscure()
        self.helix.update(0.1)
        self.window.push_state(transitions.Pause, "game")
示例#2
0
文件: game.py 项目: BrettMcNeff/TBA
class Game(object):
    """this is the Game class"""
    def __init__(self):
        pygame.mixer.pre_init(48000,-16,2, 1024) #Sound Settings
        pygame.init()
        
        #sets the screen resolution for the game and sets a rect for the game screen
        self.screen = pygame.display.set_mode((1024,768))
        self.screen_rect = self.screen.get_rect()
        
        #initializes a clock for the game
        self.clock = pygame.time.Clock()
        
        #initializes a menu object and HUD object and Score object
        self.menu = Menu()
        self.hud = Hud()
        self.score = Score()
        #sets a boolean for whether you are still in the menu or not
        self.inMenu = True
        #sets a camera for the world
        self.camBorder = 32
        self.cam = Camera(pygame.Rect(100, 100, 1024, 768), pygame.Rect(self.camBorder, self.camBorder, 2048 - self.camBorder, 1536 - self.camBorder))
        self.camShakeFactor = 0 #Magnitude of shake
        self.camShakeDecayFactor = 0.08 #Lerp Amount
        
        #Timing
        self.timer = pygame.time.get_ticks()
        self.elapsed = 0
        
        #Sound Controller
        self.soundCon = SoundCon()
        
        #Game Values
        self.backgroundImg = pygame.image.load("Images/Arena/Arena2.png").convert_alpha()
        self.backgroundImgRect = self.backgroundImg.get_rect()
        self.player = Player( self.hud )
        
        #Effects
        self.effectInstances = []
        self.spawnSound = pygame.mixer.Sound("Sounds/ShipRev.wav")
        self.deathSound = pygame.mixer.Sound("Sounds/shipExplo.wav")
        self.enemyExplo = pygame.mixer.Sound("Sounds/enemyExplo.wav")
        self.clashSound = pygame.mixer.Sound("Sounds/clash.wav")
        self.boostSound = pygame.mixer.Sound("Sounds/boostLow.wav")
        
        #Game over fade out
        self.fadeImage = pygame.image.load("Images/HUD/CrackedGlass.png").convert_alpha()
        self.fadeRect = self.fadeImage.get_rect()
        self.fadeSurface = pygame.Surface((1024, 768), pygame.SRCALPHA)
        self.fadeSurfaceAlpha = 0
        self.fadeSurfaceRate = 1
        self.doFade = False
        self.restartGame = False
        
        #Enemies
        self.enemyList = []
        self.baseNumEnemies = 2
        self.spawnTime = 10
        self.currentSpawnTime = 30


    def process_events(self):
        """process all game events"""
        #sets a variable containing the position of the mouse
        self.mousePos = pygame.mouse.get_pos()

        for event in pygame.event.get():
            if self.inMenu:
                #passes the current event and mouse position to the menu's 'process_events' function
                self.inMenu = self.menu.process_events(event, self.mousePos)
            else:
                #Run everything else's 'process_events' functions
                #print("This is where the game would process events")
                self.readInputs( event )
                
            if event.type == pygame.KEYDOWN:
                #exits the program if the esc key is pressed
                if event.key == pygame.K_ESCAPE:
                    sys.exit(0)
    
    def readInputs(self, event):
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                sys.exit(0)
            if event.key == pygame.K_w or event.key == pygame.K_UP:
                self.player.moving[0] = True
            if event.key == pygame.K_s or event.key == pygame.K_DOWN:
                self.player.moving[1] = True
            if event.key == pygame.K_a or event.key == pygame.K_LEFT:
                self.player.moving[2] = True
            if event.key == pygame.K_d or event.key == pygame.K_RIGHT:
                self.player.moving[3] = True
            if event.key == pygame.K_SPACE or event.key == pygame.K_z:
                self.player.moving[4] = True
                self.boostSound.play()
            if event.key == pygame.K_p:
                self.soundCon.currentTime = 30
                self.currentSpawnTime = 1
                self.player.currentInvincTime = 1
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_w or event.key == pygame.K_UP:
                self.player.moving[0] = False
            if event.key == pygame.K_s or event.key == pygame.K_DOWN:
                self.player.moving[1] = False
            if event.key == pygame.K_a or event.key == pygame.K_LEFT:
                self.player.moving[2] = False
            if event.key == pygame.K_d or event.key == pygame.K_RIGHT:
                self.player.moving[3] = False
            if event.key == pygame.K_SPACE or event.key == pygame.K_z:
                self.player.moving[4] = False
                self.boostSound.stop()

        
        
    def update(self):
        """updates the game"""
        if not self.inMenu:
            self.player.update(self.cam )
            self.cam.move_to(self.player.pos[0], self.player.pos[1])
            self.soundCon.update()
            
            #Enemy Spawning
            self.elapsed = (pygame.time.get_ticks() - self.timer) / 1000.0
            self.currentSpawnTime -= self.elapsed
            if ( self.currentSpawnTime <= 0 ):
                self.currentSpawnTime = self.spawnTime
                self.spawnEnemy()
            
            #Enemy update
            for tempEnemy in self.enemyList:
                tempEnemy.update(self.cam)
                self.player.checkColl(tempEnemy, self.cam, self)
            #Check enemy deaths
            for tempEnemy in self.enemyList:
                if tempEnemy.deathFlag:
                    self.score.total += 100
                    self.makeLineBurst( tempEnemy.rect.centerx, tempEnemy.rect.centery, tempEnemy.deathAngle, 60, 200, 50, (255,255,0), 0.1, True )
                    self.makeLineBurst( tempEnemy.rect.centerx, tempEnemy.rect.centery, tempEnemy.deathAngle, 60, 200, 50, (255,255,255), 0.1, True )
                    self.makeLineBurst( self.player.rect.centerx, self.player.rect.centery, 0, 360, 100, 50, (255,255,255), 0.05, True )
                    self.makeLineBurst( self.player.rect.centerx, self.player.rect.centery, 0, 360, 100, 40, (255,0,0), 0.05, True )
                    self.enemyExplo.play()
                    self.enemyList.remove( tempEnemy )
                    self.spawnEnemy()

            
            #Effect update
            for effect in self.effectInstances:
                if not effect.active:
                    self.effectInstances.remove( effect )
            
            #Shake and Decay
            self.camShakeFactor = self.camShakeFactor - ( self.camShakeFactor * self.camShakeDecayFactor )
            if ( self.camShakeFactor < 1 ):
                self.camShakeFactor = 0
            self.cam.shake(random.random() * self.camShakeFactor, random.random() * self.camShakeFactor)
            
            #Player boost effect
            if ( self.player.boosting ):
                self.makeLineBurst( self.player.rect.centerx, self.player.rect.centery, -self.player.ang  * 180 / math.pi + 180, 30, 3, 30, (255,255,155), 0.1, True )
                self.makeLineBurst( self.player.rect.centerx, self.player.rect.centery, -self.player.ang  * 180 / math.pi + 180, 30, 3, 30, (255,0,0), 0.1, True )
            if ( self.player.thrusting ):
                self.makeLineBurst( self.player.rect.centerx, self.player.rect.centery, -self.player.ang  * 180 / math.pi + 180, 20, 2, 20, (255,255,255), 0.1, True )
                
            #Update Score in HUD
            self.hud.updateScore(self.score.getTotal())
            
            #Death
            if self.player.dead and self.player.canMakeDeadEffect:
                self.player.canMakeDeadEffect = False
                self.shakeScreen( 64 )
                self.soundCon.playDeathSound()
                self.deathSound.play()
                #self.makeExplosion( 500, 500, "Images/Effects/Explosion2Spr.png", 200, 200, 8, 8, True)
                self.makeLineBurst( self.player.rect.centerx, self.player.rect.centery, 0, 360, 200, 30, (255,255,0), 0.1, True )
                self.makeLineBurst( self.player.rect.centerx, self.player.rect.centery, 0, 360, 200, 30, (255,0,0), 0.1, True )
                self.makeLineBurst( self.player.rect.centerx, self.player.rect.centery, 0, 360, 100, 30, (255,155,0), 0.05, True )
                self.makeLineBurst( self.player.rect.centerx, self.player.rect.centery, 0, 360, 100, 40, (255,0,0), 0.05, True )
                self.makeLineBurst( self.player.rect.centerx, self.player.rect.centery, 0, 360, 100, 50, (255,255,255), 0.05, True )
                self.player.numLives -= 1
                if ( self.player.numLives <= 0 ):
                    self.doFade = True
                    self.player.currentDeadTime = 30
            if ( self.player.reformEffect ):
                self.player.reformEffect = False;
                self.spawnSound.play()
                self.makeLineBurst( self.player.rect.centerx, self.player.rect.centery, 0, 360, 150, 15, (255,255,255), 0.1, False )
                self.makeLineBurst( self.player.rect.centerx, self.player.rect.centery, 0, 360, 150, 30, (255,255,255), 0.1, False )
                self.makeLineBurst( self.player.rect.centerx, self.player.rect.centery, 0, 360, 150, 50, (255,255,255), 0.1, False )
            
            
            self.timer = pygame.time.get_ticks()
            
            
    def shakeScreen(self, magnitude):
        self.camShakeFactor = magnitude #Magnitude of shake
    
    def makeLineBurst(self, x, y, direction, spread, count, maxSpeed, color, lerpPercent, doRandom):
        newBurst = LineBurst( x, y, direction, spread, count, maxSpeed, color, lerpPercent, doRandom ) 
        self.effectInstances.append( newBurst )
        
    def makeExplosion(self, x, y, imagePath, imageWidth, imageHeight, numFrames, imageSpeed, doLoop):
        newAnim = EffectAnimation( x, y, imagePath, imageWidth, imageHeight, numFrames, imageSpeed, doLoop ) 
        self.effectInstances.append( newAnim )
    
    def spawnEnemy(self):
        if ( len(self.enemyList) == 0 ):
            for i in range( self.baseNumEnemies ):
                self.enemyList.append(AI(self.player, self.cam, self))
        else:
            self.enemyList.append(AI(self.player, self.cam, self))
        
    
    def draw(self):
        """draw the gameworld"""
        self.screen.fill((0,0,0))
        if self.inMenu:
            #calls the menu's draw function
            self.menu.draw(self.screen)
        else:
            #Draw the regular game
            backRect = self.backgroundImgRect.move(-self.cam.rect.x + self.camBorder / 2, -self.cam.rect.y + self.camBorder / 2)
            self.screen.blit(self.backgroundImg, backRect)
            self.player.draw( self.screen, self.cam )
            
            #Enemy draw
            for tempEnemy in self.enemyList:
                tempEnemy.draw(self.screen, self.cam)
            
            #Effect draw
            for effect in self.effectInstances:
                effect.draw(self.screen, self.cam)
                
            #HUD draw
            self.hud.draw(self.screen)
                
                
            #Game Over fade
            if self.doFade:
                self.fadeSurfaceAlpha += self.fadeSurfaceRate
                
                if ( self.fadeSurfaceAlpha >= 255 ):
                    self.inMenu = True
                    pygame.mixer.stop()
                    pygame.mixer.music.stop()
                    self.restartGame = True
                else:
                    self.fadeSurface.fill((0,0,0,self.fadeSurfaceAlpha))
                    self.fadeSurface.set_alpha( self.fadeSurfaceAlpha )
                    #tempRect = self.fadeRect.move(-self.cam.rect.x, -self.cam.rect.y)
                    self.fadeSurface.blit(self.fadeImage, (0,0))
                    self.screen.blit(self.fadeSurface,(-self.cam.rect.x + self.cam.rect.left,-self.cam.rect.y + self.cam.rect.top))
示例#3
0
class GameMode(mode.Mode):
    name = "game_mode"

    STEP_SIZE = 15
    SLOW_START = 120
    FPS_FONT_SIZE = 10

    def __init__(self, editor_mode=True, level_name=None):
        super(GameMode, self).__init__()
        self.editor_mode = editor_mode
        self.level_name = level_name

    def connect(self, controller):
        super(GameMode, self).connect(controller)
        self.tool = TriggerTool()
        self.alt_tool = EraseTool()

        self.init_opengl()

        self.skip_level = False
        self.game_complete = False

        self.fps_magic = pyglet.clock.ClockDisplay(font=pyglet.font.load([], self.FPS_FONT_SIZE))
        self.mouse_pos = (self.window.width / 2, self.window.height / 2)
        self.renderer = None

        if not self.level_name:
            self.level_name = self.get_default_level_name()

        grid, level_help = self.load_grid_from_file(self.level_name)
        self.game_session = session.Session(grid)
        self.game_status = None
        self.level_help = None
        self.charge_player = None

        if level_help and not self.editor_mode:
            level_help += '\n\nClick to continue.\n'
            font = gui.GameMenuFont()
            self.level_help = TextFloat(level_help, 0, -200, 500, font.name, 12)

        self.init_level()
        self.init_renderer()
        self.init_gui()
        self.init_camera()

    def init_camera(self):
        grid = self.game_session.game.grid
        if grid:
            minx = miny = float("Inf")
            maxx = maxy = float("-Inf")
            for x, y in grid:
                minx = min(minx, x)
                miny = min(miny, y)
                maxx = max(maxx, x)
                maxy = max(maxy, y)
        else:
            minx = miny = maxx = maxy = 0

        cx = minx + (maxx - minx) / 2
        cy = miny + (maxy - miny) / 2

        self.camera = Camera(Vector3(cx, cy, 20), Vector3(cx, cy, 0), Vector3(0, 1, 0))
        self.camera.resize(0, 0, self.window.width, self.window.height)

    def disconnect(self):
        self.delete_renderer()
        self.shutdown_opengl()

        self.stop_charge_player()

    def init_opengl(self):
        glLoadIdentity()

        glEnable(GL_COLOR_MATERIAL)
        glEnable(GL_LIGHTING)
        glEnable(GL_LIGHT0)
        glEnable(GL_DEPTH_TEST)

        glLightfv(GL_LIGHT0, GL_POSITION, ptr(5, 5, 5, 1))
        glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, ptr(5, 5, -5, 1))
        glLightfv(GL_LIGHT0, GL_DIFFUSE, ptr(.8, .8, .8, 1))
        glLightfv(GL_LIGHT0, GL_SPECULAR, ptr(.8, .8, .8, 1))

        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, ptr(.5, .5, .5, 1))
        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, ptr(0, 0, 0, 0))
        glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0)

    def shutdown_opengl(self):
        glDisable(GL_LIGHTING)
        glDisable(GL_DEPTH_TEST)

    def init_renderer(self):
        self.renderer = render.GameRenderer(self.game_session.game)

    def delete_renderer(self):
        if self.renderer:
            self.renderer.delete()
        self.renderer = None

    def init_gui(self):
        font = gui.GameMenuFont()
        build_menu = gui.Submenu([(cls.human_name, font, gui.SELECT, DrawTool(cls)) for cls in core.ALL_BLOCKS])
        build_menu.choices.append((gui.LABEL_REMOVE, font, gui.SELECT, EraseTool()))

        self.b_start_stop = gui.Button(gui.LABEL_START, font, self.on_game_start_stop)

        if self.editor_mode:
            self.gui.replace([
                gui.Button(u'\u270f Build\u2026', font, build_menu),
                gui.Button(u'\u2798 Save', font, self.on_save_pressed),
                gui.Button(u'\u2744 Lock', font, gui.SELECT, LockTool()),
                self.b_start_stop,
                gui.Button(gui.LABEL_BACK, font, self.on_back_pressed),
            ])
        else:
            self.block_buttons = {
                block_class: gui.CountButton(block_class.human_name, font, count, gui.SELECT, DrawTool(block_class))
                for block_class, count in self.game_session.game.inventory.items()
            }

            block_buttons = [self.block_buttons[cls] for cls in core.ALL_BLOCKS if cls in self.block_buttons]

            self.gui.replace(block_buttons + [
                gui.Button(gui.LABEL_REMOVE, font, gui.SELECT, EraseTool()),
                gui.Button(u'\u21ba Retry', font, self.on_game_reset),
                gui.Button(gui.LABEL_BACK, font, self.on_back_pressed),
            ])

    def tick(self):
        if not self.level_help:
            self.time += 1

        if self.time == 1 and not self.editor_mode:
            self.charge_player = sounds.play('charge.wav')

        new_status = self.game_session.get_status()
        if self.game_status == core.Game.STATUS_ON and new_status == core.Game.STATUS_DEFEAT:
            self.camera.shake(1)
            sounds.play('boom.wav', 0.4)
        self.game_status = new_status

        if not self.editor_mode:
            if new_status == core.Game.STATUS_VICTORY or self.skip_level:
                next_level_name = self.level_name if self.editor_mode else self.get_next_level_name()
                if next_level_name:
                    self.control.switch_handler("game_mode", False, next_level_name)
                    return
                elif not self.game_complete:
                    self.gui.show_popup("Congrats! You completed the game!")
                    self.game_complete = True

        if not self.editor_mode and self.time > self.SLOW_START and new_status == core.Game.STATUS_NEW:
            self.game_session.start()
            self.stop_charge_player()
            sounds.play('start.wav')

        if self.time > self.next_step and new_status == core.Game.STATUS_ON:
            self.game_session.step()
            self.next_step = self.time + self.STEP_SIZE # / (self.game_session.game.speed + 1)

        cam_idx = 2 if self.keys[key.LSHIFT] or self.keys[key.RSHIFT] else 1
        cam_pos = self.camera.eye.next_value
        if self.keys[key.UP]:
            cam_pos[cam_idx] += 0.2
        if self.keys[key.DOWN]:
            cam_pos[cam_idx] -= 0.2
        if self.keys[key.LEFT]:
            cam_pos.x -= 0.2
        if self.keys[key.RIGHT]:
            cam_pos.x += 0.2

        cam_pos.x = min(20, max(-20, cam_pos.x))
        cam_pos.y = min(20, max(-20, cam_pos.y))
        cam_pos.z = min(40, max(5, cam_pos.z))

        self.camera.tick()
        self.renderer.tick()

    def stop_charge_player(self):
        if self.charge_player:
            self.charge_player.pause()
            self.charge_player = None

    def on_resize(self, w, h):
        self.camera.resize(0, 0, w, h)
        return pyglet.event.EVENT_HANDLED

    def on_draw(self):
        self.window.clear()
        glLoadIdentity()

        self.camera.setup()

        if self.gui.selected:
            self.tool = self.gui.selected.args
        else:
            self.tool = TriggerTool()

        self.update_mouse()

        self.renderer.draw(self.tool.draw_locks)

        with gl_disable(GL_LIGHTING, GL_DEPTH_TEST):
            with gl_ortho(self.window):
                self.gui.draw()
                self.fps_magic.draw()
                if self.level_help:
                    self.level_help.draw(self.window)

    def update_mouse(self):
        self.mouse_pos_world = self.camera.unproject(self.mouse_pos)
        self.mouse_pos_grid = Vector3(*[int(round(v)) for v in self.mouse_pos_world])
        self.renderer.mouse.pos = self.mouse_pos_grid
        self.tool.update_cursor(self.renderer.mouse)

    def on_mouse_motion(self, x, y, dx, dy):
        self.mouse_pos = (x, y)

    def on_key_press(self, sym, mods):
        self.hide_help()
        if sym == key.F12:
            self.skip_level = True
            return pyglet.event.EVENT_HANDLED

    def hide_help(self):
        if self.level_help:
            self.level_help.delete()
            self.level_help = None

    def on_mouse_release(self, x, y, button, modifiers):
        if self.level_help:
            self.hide_help()
            return

        self.mouse_pos = (x, y)
        self.update_mouse()

        mpos = self.mouse_pos_grid.xy
        grid = self.game_session.game.grid
        block = grid.get(mpos)

        if block and block.locked and not self.editor_mode:
            self.camera.shake(0.1)
            sounds.play('noway.wav')
            return

        try:
            if button == mouse.LEFT:
                tool = self.tool
            if button == mouse.RIGHT or (button == mouse.LEFT and modifiers & key.MOD_SHIFT):
                tool = self.alt_tool

            if tool.apply(mpos, self.game_session.game, self.editor_mode):
                self.renderer.mark_dirty(mpos)

        except Exception as e:
            self.camera.shake(0.2)
            sounds.play('noway.wav')

        self.update_inventory()

    def update_inventory(self):
        if not self.editor_mode:
            for cls, count in self.game_session.game.inventory.items():
                self.block_buttons[cls].count = count

    def on_mouse_scroll(self, x, y, scroll_x, scroll_y):
        cam_pos = self.camera.eye.next_value
        cam_pos.z -= scroll_y

    def on_game_start_stop(self, manager, args):
        if self.game_session.get_status() == core.Game.STATUS_NEW:
            try:
                self.game_session.start()
                self.b_start_stop.label.text = gui.LABEL_STOP
            except Exception, e:
                self.gui.show_popup("%s" % e)
                self.init_level()
        else: