# breakout.py
# YOUR NAME(S) AND NETID(S) HERE
# DATE COMPLETED HERE
"""Primary module for Breakout application
This module contains the main controller class for the Breakout application. There is no
need for any any need for additional classes in this module. If you need more classes,
99% of the time they belong in either the play module or the models module. If you
are ensure about where a new class should go,
post a question on Piazza."""
from constants import *
from game2d import *
from play import *
# PRIMARY RULE: Breakout can only access attributes in play.py via getters/setters
# Breakout is NOT allowed to access anything in models.py
class Breakout(GameApp):
"""Instance is the primary controller for the Breakout App
This class extends GameApp and implements the various methods necessary for processing
the player inputs and starting/running a game.
Method start begins the application.
Method update either changes the state or updates the Play object
Method draw displays the Play object and any other elements on screen
Because of some of the weird ways that Kivy works, you SHOULD NOT create an
initializer __init__ for this class. Any initialization should be done in
the start method instead. This is only for this class. All other classes
behave normally.
Most of the work handling the game is actually provided in the class Play.
Play should have a minimum of two methods: updatePaddle(input) which moves
the paddle, and updateBall() which moves the ball and processes all of the
game physics. This class should simply call that method in update().
The primary purpose of this class is managing the game state: when is the
game started, paused, completed, etc. It keeps track of that in an attribute
called _state.
INSTANCE ATTRIBUTES:
view [Immutable instance of GView; it is inherited from GameApp]:
the game view, used in drawing (see examples from class)
input [Immutable instance of GInput; it is inherited from GameApp]:
the user input, used to control the paddle and change state
_state [one of STATE_INACTIVE, STATE_COUNTDOWN, STATE_PAUSED, STATE_ACTIVE]:
the current state of the game represented a value from constants.py
_game [Play, or None if there is no game currently active]:
the controller for a single game, which manages the paddle, ball, and bricks
_mssg [GLabel, or None if there is no message to display]
the currently active message
STATE SPECIFIC INVARIANTS:
Attribute _game is only None if _state is STATE_INACTIVE.
Attribute _mssg is only None if _state is STATE_ACTIVE or STATE_COUNTDOWN.
For a complete description of how the states work, see the specification for the
method update().
You may have more attributes if you wish (you might need an attribute to store
any text messages you display on the screen). If you add new attributes, they
need to be documented here.
LIST MORE ATTRIBUTES (AND THEIR INVARIANTS) HERE IF NECESSARY
"""
# DO NOT MAKE A NEW INITIALIZER!
# THREE MAIN GAMEAPP METHODS
def start(self):
"""Initializes the application.
This method is distinct from the built-in initializer __init__ (which you
should not override or change). This method is called once the game is running.
You should use it to initialize any game specific attributes.
This method should make sure that all of the attributes satisfy the given
invariants. When done, it sets the _state to STATE_INACTIVE and create a message
(in attribute _mssg) saying that the user should press to play a game."""
# IMPLEMENT ME
pass
def update(self,dt):
"""Animates a single frame in the game.
It is the method that does most of the work. It is NOT in charge of playing the
game. That is the purpose of the class Play. The primary purpose of this
game is to determine the current state, and -- if the game is active -- pass
the input to the Play object _game to play the game.
As part of the assignment, you are allowed to add your own states. However, at
a minimum you must support the following states: STATE_INACTIVE, STATE_NEWGAME,
STATE_COUNTDOWN, STATE_PAUSED, and STATE_ACTIVE. Each one of these does its own
thing, and so should have its own helper. We describe these below.
STATE_INACTIVE: This is the state when the application first opens. It is a
paused state, waiting for the player to start the game. It displays a simple
message on the screen.
STATE_NEWGAME: This is the state creates a new game and shows it on the screen.
This state only lasts one animation frame before switching to STATE_COUNTDOWN.
STATE_COUNTDOWN: This is a 3 second countdown that lasts until the ball is
served. The player can move the paddle during the countdown, but there is no
ball on the screen. Paddle movement is handled by the Play object. Hence the
Play class should have a method called updatePaddle()
STATE_ACTIVE: This is a session of normal gameplay. The player can move the
paddle and the ball moves on its own about the board. Both of these
should be handled by methods inside of class Play (NOT in this class). Hence
the Play class should have methods named updatePaddle() and updateBall().
STATE_PAUSED: Like STATE_INACTIVE, this is a paused state. However, the game is
still visible on the screen.
The rules for determining the current state are as follows.
STATE_INACTIVE: This is the state at the beginning, and is the state so long
as the player never presses a key. In addition, the application switches to
this state if the previous state was STATE_ACTIVE and the game is over
(e.g. all balls are lost or no more bricks are on the screen).
STATE_NEWGAME: The application switches to this state if the state was
STATE_INACTIVE in the previous frame, and the player pressed a key.
STATE_COUNTDOWN: The application switches to this state if the state was
STATE_NEWGAME in the previous frame (so that state only lasts one frame).
STATE_ACTIVE: The application switches to this state after it has spent 3
seconds in the state STATE_COUNTDOWN.
STATE_PAUSED: The application switches to this state if the state was
STATE_ACTIVE in the previous frame, the ball was lost, and there are still
some tries remaining.
You are allowed to add more states if you wish. Should you do so, you should
describe them here.
Parameter dt: The time in seconds since last update
Precondition: dt is a number (int or float)
"""
# IMPLEMENT ME
pass
def draw(self):
"""Draws the game objects to the view.
Every single thing you want to draw in this game is a GObject. To draw a GObject
g, simply use the method g.draw(self.view). It is that easy!
Many of the GObjects (such as the paddle, ball, and bricks) are attributes in Play.
In order to draw them, you either need to add getters for these attributes or you
need to add a draw method to class Play. We suggest the latter. See the example
subcontroller.py from class."""
# IMPLEMENT ME
pass
# HELPER METHODS FOR THE STATES GO HERE