Exemplo n.º 1
0
class AsteroidsGame:
    def setup(self, startWindow=None, playerName=None):
        self.params = GameParams()  # To be filled by user input

        # Set up scorekeeping
        self.score = 0
        self.scoreKeeper = ScoreKeeper()
        self.scoreKeeper.setFile('asteroidScore.txt')

        # Set up window
        width = 800
        height = 600
        font = sf.Font.from_file("rust.ttf")
        self.params.setFont(font)

        if startWindow is None:
            # startWindow is None unless this is a restart
            startWindow = sf.RenderWindow(sf.VideoMode(width, height),
                                          "Asteroids")
            startWindow.framerate_limit = 60
            startWindow.clear(sf.Color.BLACK)

            #Display Welcome
            welcomeText = utils.drawText(startWindow,
                                         string="Asteroids",
                                         size=60,
                                         font=font,
                                         position='center')
            startWindow.display()

        # Wait for any input
        while (True):
            setup = False
            for event in startWindow.events:
                if type(event) is sf.CloseEvent:
                    exit()
                elif (type(event) is sf.MouseButtonEvent
                      or type(event) is sf.KeyEvent):
                    setup = True
            if setup:
                break

        # Select Player Name
        if playerName is None:
            playerName = utils.textInput(startWindow,
                                         "Enter Name:",
                                         font,
                                         maxLength=10)
        self.params.setPlayerName(playerName.lower())

        #Choose Difficulty
        difficulty = utils.selectOptions(startWindow,
                                         ["Easy", "Medium", "Hard"], [0, 1, 2],
                                         font)
        makeTimes = [20, 15, 12]
        timeModifiers = [0.98, 0.95, 0.92]
        self.params.setDifficulty(difficulty)
        self.timeToMakeAsteroid = makeTimes[difficulty]
        self.makeTimeModifier = timeModifiers[difficulty]
        self.lastAsteroidTime = time.time() - self.timeToMakeAsteroid

        self.timeToMakePowerup = 20
        self.lastPowerupTime = time.time() - self.timeToMakePowerup
        self.powerupProbability = 1 / 600

        # Set up Board
        self.board = Board(title="Asteroids", width=700, height=700)

        # Set up Ship
        self.ship = Ship(position=(self.board.getBoundary()[0] / 2,
                                   self.board.getBoundary()[1] / 2))
        self.ship.setWrapping(True)
        self.ship.setBoundary(self.board.getBoundary())

        startWindow.close()

    def endGame(self):
        gameOverText = utils.drawText(self.board.window,
                                      string="Game Over",
                                      font=self.params.font,
                                      size=60,
                                      position='center',
                                      color=sf.Color.RED)

        oldScore = self.scoreKeeper.checkScore(self.params.playerName,
                                               self.params.getDifficulty())
        scoreTextYPosition = gameOverText.position[
            1] + gameOverText.local_bounds.height + 10

        if self.score > oldScore:
            # display a "New Highscore" screen
            self.scoreKeeper.setScore(self.params.playerName, self.score,
                                      self.params.getDifficulty())

            utils.drawText(self.board.window,
                           string="New High Score! {}".format(self.score),
                           font=self.params.font,
                           size=30,
                           position='center',
                           yposition=scoreTextYPosition,
                           color=sf.Color.GREEN)
        else:
            # Display the old highscore
            utils.drawText(self.board.window,
                           string="High Score: {}".format(oldScore),
                           font=self.params.font,
                           size=30,
                           position='center',
                           yposition=scoreTextYPosition,
                           color=sf.Color.WHITE)

        utils.drawText(self.board.window,
                       string="Press ENTER to Relplay",
                       font=self.params.font,
                       size=15,
                       position='center',
                       yposition=self.board.window.height - 20,
                       color=sf.Color.WHITE)

        self.board.window.display()
        while (True):
            for event in self.board.window.events:
                if (type(event) is sf.CloseEvent
                        or (type(event) is sf.KeyEvent
                            and event.code is sf.Keyboard.ESCAPE)):
                    exit()
                if (type(event) is sf.KeyEvent
                        and event.code is sf.Keyboard.RETURN):
                    # Reset
                    self.setup(self.board.window, self.params.getPlayerName())
                    self.playGame()

    def _generateAsteroid(self, asteroidManager, velocityLimit=2):
        if (time.time() - self.lastAsteroidTime >= self.timeToMakeAsteroid):
            self.lastAsteroidTime = time.time()
            self.timeToMakeAsteroid *= self.makeTimeModifier  #make asteroids appear faster as time progresses

            # Generate beyond the border so it doesn't appear in middle of screen
            # random velocity will make it appear evenly on either side
            position = (random.uniform(-20, 0), random.uniform(-20, 0))
            velocity = (random.uniform(-velocityLimit, velocityLimit),
                        random.uniform(-velocityLimit, velocityLimit))
            asteroid = Asteroid(4,
                                position,
                                velocity,
                                wrapping=True,
                                boundary=self.board.getBoundary())
            asteroidManager.addObject(asteroid)

    def _generatePowerup(self, powerupManager, velocityLimit=2):
        if ((time.time() - self.lastPowerupTime >= self.timeToMakePowerup)
                and random.random() < self.powerupProbability):

            typeNum = random.randint(0, 2)
            typeNames = ["cooldown", "agility", "acceleration"]
            typeColors = [sf.Color.BLUE, sf.Color.GREEN, sf.Color.YELLOW]

            # Lots of calculations to make it start evenly on any side of the board
            # and ensure that it moves across the board no matter where it starts
            positionX = None
            positionY = None
            velocityX = None
            velocityY = None
            boundary = self.board.getBoundary()
            if random.random() < 0.5:
                positionX = random.uniform(-20, 0)
            else:
                positionX = random.uniform(boundary[0], boundary[0] + 20)
            if random.random() < 0.5:
                positionY = random.uniform(-20, 0)
            else:
                positionY = random.uniform(boundary[0], boundary[0] + 20)

            if (positionX < 0):
                velocityX = random.uniform(0, velocityLimit)
            else:
                velocityX = random.uniform(-velocityLimit, 0)
            if (positionY < 0):
                velocityY = random.uniform(0, velocityLimit)
            else:
                velocityY = random.uniform(-velocityLimit, 0)

            velocity = (velocityX, velocityY)
            position = (positionX, positionY)
            powerup = Powerup(position=position,
                              velocity=velocity,
                              color=typeColors[typeNum],
                              powerupType=typeNames[typeNum])
            powerupManager.addObject(powerup)
            self.lastPowerupTime = time.time()

    def playGame(self):
        self.board.window.clear(sf.Color.BLACK)
        self.ship.draw(self.board.window)
        self.board.displayBoard()

        play = False
        while not play:
            for event in self.board.window.events:
                if type(event) is sf.CloseEvent:
                    exit()
                elif (type(event) is sf.KeyEvent):
                    play = True

        bulletManager = ObjectManager(cleanSize=10)
        asteroidManager = ObjectManager(cleanSize=10)
        powerupManager = ObjectManager(cleanSize=5)

        while (True):
            self.board.window.clear(sf.Color.BLACK)

            self._generateAsteroid(asteroidManager)
            self._generatePowerup(powerupManager)

            # Input handler
            for event in self.board.window.events:
                if type(event) is sf.CloseEvent:
                    exit()
                if type(
                        event
                ) is sf.KeyEvent and event.code is sf.Keyboard.SPACE and event.pressed:
                    bullet = self.ship.shootBullet(
                        boundary=self.board.getBoundary())
                    if bullet:
                        bulletManager.addObject(bullet)
            if sf.Keyboard.is_key_pressed(sf.Keyboard.RIGHT):
                self.ship.turnRight()
            if sf.Keyboard.is_key_pressed(sf.Keyboard.UP):
                self.ship.accelerate()
            if sf.Keyboard.is_key_pressed(sf.Keyboard.LEFT):
                self.ship.turnLeft()

            # Move and draw bullets
            for i in range(bulletManager.getLength()):
                bullet = bulletManager.getItem(i)
                bullet.move()
                bullet.draw(self.board.window)

            # Move and draw Asteroids
            for i in range(asteroidManager.getLength()):
                asteroid = asteroidManager.getItem(i)
                asteroid.move()
                asteroid.draw(self.board.window)

            # Move and draw Powerups
            for i in range(powerupManager.getLength()):
                powerup = powerupManager.getItem(i)
                powerup.move()
                powerup.draw(self.board.window)

            # Move and draw Ship
            self.ship.moveForward()
            self.ship.draw(self.board.window)

            # Check for collisions
            newAsteroids = []
            for i in reversed(range(asteroidManager.getLength())):
                asteroid = asteroidManager.getItem(i)
                # Asteroid-Ship collision
                if (self.ship.circleTriangleCollision(asteroid.getShape())):
                    self.endGame()

                for j in reversed(range(bulletManager.getLength())):
                    bullet = bulletManager.getItem(j)
                    # if collision: break asteroid
                    if asteroid.didCollide(bullet):
                        self.score += 1
                        if asteroid.breakAsteroid():
                            for newAsteroid in asteroid.breakAsteroid():
                                newAsteroids.append(newAsteroid)
                        bulletManager.removeIndex(j)
                        asteroidManager.removeIndex(i)
                        break
            asteroidManager.addObjects(newAsteroids)

            # Check for powerup collisions
            for i in reversed(range(powerupManager.getLength())):
                powerup = powerupManager.getItem(i)
                if self.ship.circleTriangleCollision(powerup.getShape()):
                    power = powerup.getType()
                    if power == "acceleration":
                        oldAcc = self.ship.getAcceleration()
                        self.ship.setAcceleration(1.1 * oldAcc)
                    elif power == "cooldown":
                        oldCool = self.ship.getCooldown()
                        self.ship.setCooldown(0.9 * oldCool)
                    elif power == "agility":
                        oldSpeed = self.ship.getRotateSpeed()
                        self.ship.setRotateSpeed(1.1 * oldSpeed)
                    powerupManager.removeIndex(i)

            self._drawScore(self.board.window)

            self.board.window.display()

    def _drawScore(self, window):
        if hasattr(self, 'scoreText'):
            self.scoreText.string = str(self.score)
        else:
            self.scoreText = utils.drawText(window,
                                            size=25,
                                            font=self.params.font,
                                            string=str(self.score))
        window.draw(self.scoreText)