1 - McGill School Of Computer Science

advertisement
1 Objectives and initiatives
Describing the project is mandate of cs573 project.
Why we choose this topic.
What objectives we are going to acquire. What will completion of project benefit us?
2 Project outline and screen layout.
Show a couple of interfaces of the projects (with pictures)
Describe how to play the game.
3. Design Rationale
This vibrant discipline of computer science is teeming with design paradigms, patterns
and styles. It is often the case that a design cannot be described as being of a certain style,
because it does not complete follow the style’s specific rules or methodologies. Owing to
the large number of possible combinations of styles in the same design, there are many
ways to create good designs. Sometimes, the actual choice reflects a developer’s past
experience or preference; other times, the method is imposed by the system’s required
structure, or the nature of the data it processes.
As long as a solution does not blatantly contravene the characteristics of what constitutes
a good design, it is as good as any other, and the designers do not have to justify it. This,
however, does not dispense them with the obligation to explain the rationale (the
underlying reasons) behind the particular decisions they took regarding, say, the
decomposition into subsystems or modules, the choice of a specific development tool
instead of some other, and the programming language that will serve as a vehicle for the
implementation.
Here we describe the design rationale of this project, illustrating the way how we design
the system, the technique how we handle specific technical problems, the tools which we
use. Besides that, we justify our choices by specifying the reasons behind the choices.
3.1. Object Oriented Design for design
Since late of 1980s, Object Oriented Design (OOD) has captured the attention and
enthusiastic of most of programmers. OOD is being so successful because it provides
designer a very convenient and straightforward way to design their application. In OOD,
every thing is object, as what the human being see in their normal lives. It is easy for
human being to follow this way to see their programs.
In this project we also follow the OOD method to design our program. As we explain
above, it doesn’t mean OOD is the only way that can be used. Rather, it is the choice
among many. We made the choice of OOD simply because we, the authors of this
application, are more familiar with OOD than with other design method. Further, by
using OOD, we can get benefit a lot in designing by using Unified Modeling Language
(UML), as described below.
3.2. UML and Use Case Driven for modeling
Unlike OOD, which just attracted people recently after its emergence in 1960s, UML gets
designers’ attention since its birth. UML is a semi-formal language without API. It
mainly provides designers a way to build the skeleton of their programs without even
start writing a line of code. This is very important because after getting involved in
coding, programmers will narrow their views and just consider how to explore the coding
technique to get over the problem when they meet problem. Even if finally their
programs without design can work, they always look ugly and are hard to maintain and
incorporate with other programs.
Considering constructing a high-rise building, the civil engineers will not start to stack up
even one brick until they finish drawing the design layout on the paper. UML is a tool to
enable software designers to build their program design layout, corresponding to the tool
to enable civil engineer to draw their figures.
In UML, every thing is present in diagrams. There are totally 8 types of diagrams, e.g.
Use Case Diagram, Class Diagram, Interaction Diagram, State Chart Diagram,
Component Diagram, Activity Diagram etc. Normally software designer intends to use a
kind of methodology called use case driven design methodology. In this design
methodology, Use Case Diagram, Class Diagram and Interaction Diagram will be enough
for a design.
In use case driven design methodology, design starts from use case analysis. Designer
will consider the case how his application will be used by users, i.e. get use cases. For
each use case, there will be some scenarios. For each scenario, by drawing interaction
diagram, designer will analysis the sequence of actions which should take place in the
program. These actions represent the interactions between the possible objects in the
program. Then the designer will get classes based on the possible objects and get the
possible class methods based on the action between objects.
Above is an abstract of use case driven design methodology. In our project, we also
follow the way of use case driven design methodology, by providing Use Case Diagrams,
Class Diagrams and Interaction Diagrams. But we will not show you the intermediate
steps of design. Rather, in the design document, the final design will be presented.
3.3. Java (Swing) for programming language
We make the decision of Java as programming language based on the consideration of
java’s characteristics.
Since our product is a game, we would like to put them in the internet so that everyone
can access to it and share our happiness. As we know, Java is so called internet
programming language because java applications can be easily coupled into the internet.
It is one of the reasons that we use java.
Java is pure Object Oriented language. Since we use OOD in design, Java would be an
idea candidate of coding language to implement the design in OOD. Besides the Object
Oriented characteristic, Java has two other stuffs interesting us.
One is that Java has a set of API, Swing, which supports the construction of Graphic User
Interface (GUI) easily and with great quality. Since our project is a game with lots of
images and graphic interface, Java Swing is a good choice.
The other characteristic of Java interesting us is Event Handling. Java has a set of classes
that take care of the interaction between program and users. For example, user may press
a button and this will be interpreted by Java in sending an Event object to the program.
Since this game involves the interaction of users, the Event Handling of Java is explored
in the project.
Some of you may wonder that Java is slow, especially for the game which requires realtime playing. It is true that Java is not as fast as C or C++. However, for the game in this
project which is relatively small, the processing of CPU will be quite simple and light.
The speed of Java will be enough for this game.
3.4. How to handle animation in the game
This is a trick in programming. We didn’t write the program to make balls moving at any
time. Actually, at any moment, balls are displayed statically on the screen. However, after
a very short time, e.g. 100ms, we erase the balls on their previous position and display
them at the new position where is a few pixels away and in the path of ball moving. By
repeating this erasing and displaying again and again, the player will have the illusion
that the balls are moving along the path.
For the figure, it is the same mechanism. The difference between balls and figures is that
ball is displayed by filling a circle with solid color, i.e.
g.setColor(Color.red);
g.fillOval(x, y, width, height);
where g is a object of class Graphics, in Java.
Whereas, figure is displayed by drawing an object of class ImageIcon, i.e.:
ImageIcon img = tumpleItem[index].getImage();
img.paintIcon(p, g, x, y); // P-panel, g-Graphics,
Moreover, there is only one format of ball, i.e. circle. However, there are 14 formats of
figures, i.e. there are 14 images in discrete order of figure rolling motion. We just display
these 14 images one by one to get an illusion that the figure is rolling continually.
4. Use case analysis
First, let’s consider who the users will be for our application, bouncing ball game.
Absolutely, there will be only human being who can play the game. Let’s call these
human being users generally player. Is there any other user? Since the game is simple, we
don’t need any administrators to maintain it, as database application will do. Since the
game is stand-alone, there will not be any other programs that couple the game. So there
is also no other system user.
Let’s consider what the user, player, will do to the game, i.e. analysis possible use cases.
First, player can press a button and start to play the game. So we have a Use Case, start
playing.
How does player play the game? The only thing that player need to do is moving the
paddle by dragging the mouse over the paddle. We call this Use Case, move paddle.
During playing, player may want to stop the game or just pause for a while in order to, let
say, have a cup of water. We add this Use Case, pause playing.
When player wins one level, he will proceed to the next level. So we have another Use
Case, goto next level.
In case that player loses the game, as will happen definitely, he may want to start again
from the first level. So we have a Use Case, restart playing.
Is that all? No! In the use case above, we just assume that the game has been loaded on
the screen such that player can do whatever he wants. But who did the job loading the
program and initializing the interface? Operating System! Not to miss this step, we add
one more use case, initialization.
By further analyzing, we found that there are similar parts between Use Cases start
playing and restart playing. We called the similarity a Use Case, game running. Also,
restart playing involves resetting all objects, e.g. positions. Hence the restart playing
includes Use Case, reset objects.
The following figure is the UML use case diagram for the use case in this project.
start playing
<<include>>
pause playing
player
game running
<<include>>
<<include>>
restart playing
Reset Object
goto next level
move paddle
system
initialization
Figure 4.1. Use Case Diagram
5. Class analysis
5.1. A first view of the game
Let’s take a look at the screen layout picture, Figure 2.1. It is obvious that there are
objects like paddle, brick, ball, figure. All these objects lead to the derivation of the
classes, Paddle, Brick, Ball, Tumple(for figure). There also some buttons in the screen
layout. These buttons are objects of Java Swing Class, JButton. We didn’t count it as the
key class of our design.
Since Tumple is composed of 14 images, we have another class, TumpleItem, used by
Tumple. One object of Tumple will have 14 objects of TumpleItem, as shown in Figure
5.2.
Classes Paddle and Brick have some common characteristic. For instance, they are all in
the shape of rectangle. According to project outline, whenever ball meets the boundaries
of Paddle and Brick, ball will bounce. Based on that, we get a parent class, Rect, by
withdrawing the common attributes of Paddle and Brick.
Besides those obvious objects on the screen layout, notice that there are some control
buttons that enable player to start, pause or restart the game. These objects belong to
Java Swing Class, JButton. It is available in Java Swing API. We mentioned it simply
for the convenience of illustrating the interaction of player.
Also note that in Java Swing technology, every thing is drawn in the container, which is
an object of Java.Swing.Jpanel. There is no exception in our application since we use
Java Swing. We draw our objects in a container called gamePane.
Moreover, there is also a framework class, BallGame, for the whole application.
BallGame class provides a frame for all the objects, including gamePane. BallGame takes
care of creating all objects, initializing all objects etc. In one word, it provides an
environment for all objects to survive and interaction with each other.
5.2. Controlling the game.
In 5.1, we generate a set of classes, such as paddle, brick. These classes only record the
information about what the game is supposed to have. The information of how the game
is controlled has not been presented.
First we need a class, PaddleMouseMotionListener, to handle the action of dragging
mouse over paddle.
Recall that in section 3.4, we explain how to handle the animation of ball and figure.
Basically we just repeat the process of erasing and displaying the objects after certain
amount of time. So first we need a class, BallTimerListener, to trigger the erasing and
displaying actions on the objects. Remember we have to repeat this process. So we need
another class, Timer, to trigger BallTiimerListener after certain amount of time.
Who control, i.e. starts and stops, the timer then? Player! Player presses the control
button. This action will trigger an event to TimerControlListener, which will start or
stop the timer by executing its function, actionPerformed.
Those are all the classes going to be used in the program.
5.3. Class Diagrams
BallGame
initialize
main frame
BallGame.GamePane
display tumple
display brick
display ball
display paddle
Brick
break
Ball
hit
Paddle
save
Tumple
move
PaddleMouseMotionListener
keepmoving
keep running
ControlButton
BallTimerListener
fire event
trigger
BallGame.TimerControlListener
control(stop,start)
Timer
Figure 5.1. Class Diagram -- interaction
In the diagram, we connect the different classes with messages. It is straightforward to
understand what one class does to other class by sending messages.
BallGame initializes all the classes in the package.
GamePane is responsible for displaying the paddle, ball, bricks and tumple.
Ball will break the brick if it meets brick’s boundary. Ball will hit and bounce on the
paddle.
When there is no brick to support Tumple, Tumple will drop down. The paddle can save
the tumple by moving to the position beneath the tumple.
PaddleMouseMotionListener is responsible for moving the paddle by listening to the
interaction of player.
ControlButton will fire event to TimerControlListener, which will start or stop the timer.
The timer will repeat triggering BallTimerListener, which erase and display the paddle,
balls and tumples.
Timer
Ball
1..n
1
1
1
BallGame
1
1
Tumple
GamePane
1
1
1
10,20,30
Brick
14
TumpleItem
1
Paddle
Rect
Figure 5.2. Class Diagram – containing information
Figure 5.2. shows you a general idea of number of objects in the program. As you see,
BallGame contains all the objects and initializes them.
There could be several balls in the game depending on the level of game.
There is only one timer and one gamePane.
The paddle and brick inherit from Rect. There is only one paddle object but multiple
bricks in the game. Each level has 10 more bricks than the previous level.
There is only 1 tumple(figure) which has 14 tumpleItem objects in it.
6. Dynamic Modeling of Use cases
In this section, a list of sequence diagrams is presented. Sequence diagram is a kind of
interaction diagram which models the dynamic interactions between the objects. For each
use case, we present at least one scenario by showing its sequence diagram.
6.1. Use case -- Initialization
System
Initialization
Figure 6.1. Use Case diagram for Use Case, Initialization
: BallGame
: system
bricks : Brick
: Paddle
: Ball
: TumpleItem
: Tumple
gamePane: :
BallGame.GamePane
: Timer
:
BallTimerListener
init( )
loadImages( )
createBrick( )
new
init( )
createPaddl
e( )
new
init( )
createBal
l( )
new
init( )
createTumpleIte
m( )
new
createTumpl
e( )
init( )
new
init( )
makeGUI( )
paint()
paintBorder()
display(Graphics)
display(Graphics)
display(Graphics)
display(, , )
initTimer( )
new
init( )
new
Figure 6.2. Sequence Diagram for system initializing when loading the
program in Use Case, Initialization
init( )
Figure 6.2. shows step by step how program will work in the scenario of system
initializing when loading the program in Use Case, Initialization. Let’s explain it step by
step.
1. As soon as the program is loaded, BallGame.init() is called.
2. BallGame object calls its method, loadImages(), to load all the images needed in
the program.
3. BallGame creates bricks by calling BallGame.createBrick()
4. Bricks objects are created by using new Brick()
5. Each brick object is initialized.
6. BallGame creates Paddle objects by calling BallGame.createPaddle().
7. Paddle object is created by using new Paddle()
8. Paddle object is initialized.
9. BallGame creates Ball objects by calling BallGame.createBall().
10. Ball objects are created by using new Ball()
11. Ball objects are initialized.
12. BallGame creates TumpleItem objects by calling BallGame.createTumpleItem().
13. TumpleItem objects are created by using new TumpleItem()
14. TumpleItem objects are initialized.
15. BallGame creates Tumple object by calling BallGame.createTumple().
16. Tumple object is created by using new Tumple()
17. Tumple object is initialized.
18. BallGame object makes its Graphic User Interface.
19. GamePane is painted.
20. First paint the border in the gamePane
21. Then display the Paddle in the gamePane.
22. Then display the balls in the gamePane
23. Then display the tumple in the gamePane
24. Finally display the bricks in the gamePane
25. BallGame creates timer object
26. Calls new Timer()
27. Timer is initialized.
28. By the time when timer is initialized, a new BallTimerListener object is also
created.
29. BallTimerListener object is initialized.
6.2. Use case – Start playing
player
Start playing
Game running
Figure 6.3. Use Case diagram for Use Case, staring playing
playBtn :
ControlButton
: player
: BallGame.TimerControlListener
: Timer
:
BallTimerListener
: Ball
bricks : Brick
: Tumple
click
actionPerformed( )
start()
4.setText(“pause” )
actionPerformed()
ballRunning(, )
repeat after
timeDelay
runOneStep()
isHitted( )
return
[isHitted()=true] broken()
tumpleRunning()
running(, , )
return
Figure 6.4. Sequence Diagram for player pressing “play” button in Use
Case, start playing
moveX()
Let’s explain the sequence diagram step by step.
1. Player clicks the play button.
2. The method, actionPerformed(), in object TimerControlListner, will be
performed.
3. It starts a timer object.
4. The timer object triggers the actionPerformed() method in object
BallTimerListener.
5. BallTimerListener sets the text in controlBtn to be “pause”.
6. Ball starts to run
7. The ball object just moves a step to a new position.
8. Check if the ball object hits the bricks, i.e meet the boundaries of bricks.
9. Return a value to let BallTimerListener know if the ball hits the brick or not.
10. If hitted, the brick is broken.
11. Tumple object is also running.
12. Running method in Tumple object is called.
13. Actually Tumple object just moves a step.
14. Return once tumple finishes moving for a step.
Note that after step 13 has been executed, the process repeats by going back to step 4.
6.3. Use case – Pause playing
player
Pause playing
Figure 6.4. Use Case diagram for Use Case, Pause playing
playBtn :
ControlButton
: player
:
BallGame.TimerControlListener
: Timer
1.click
2. actionPerformed( )
3. stop( )
4. setText("Play")
Figure 6.6. Sequence Diagram for player pressing “pause” button in Use
Case, Pause playing
Let’s explain the sequence diagram step by step:
1. Player clicks playBtn. Remember in use case, Start playing, the playBtn has set its
text to be “Pause”. So here playBtn has the text, “Pause”, on the button.
2. TimerControlListener::actionPerformed() is triggered.
3. Timer is stopped. So the erase and display process will not be repeated. That
means the ball and tumple(figure) will stop after this method.
4. PlayBtn set its text as “Play” on the button to remind the player that the next click
will start playing.
6.4. Use case – restart playing
player
restart playing
Game running
Figure 6.7. Use Case diagram for Use Case, restart playing
: player
restartBtn :
ControlButton
click
timerControlListener
...
: BallGame
:
BallGame.GamePane
actionPerformed( )
bricks : Brick
: Paddle
: Tumple
Timer
stop( )
removeAll()
initBrick( )
Init()
initPaddle()
Init()
initTumple( )
Init()
initTimer( )
Init()
init( )
setGameLevel()
setWinningLevel()
repaint()
start()
trigger use case,
game playing
Figure 6.8. Sequence Diagram for player pressing “restart” button in Use
Case, restart playing
btns :
ControlButton
Let’s explain it step by step.
1. Player clicks restart button.
2. TimerControlListener::actionPerformed() is triggered.
3. Timer object is stopped.
4. Remove everything in GamePane. Clear up.
5. Initialize brick objects
6. Each brick object is initialized.
7. Initialize paddle object
8. Paddle::init() is called as a result.
9. Initialize tumple object
10. Tumple::init() is called as a result.
11. Initialize timer object
12. Timer::init() is called as a result.
13. Initialize the control buttons, such as play button and goto next level button.
14. Reset game level to be the first level.
15. Reset winning level to be 0, which means that player has not won any level yet.
16. Repaint the gamePane to show all the objects which have been initialized.
17. Start the timer to play again.
Note that after step 17, another use case, game playing, will be executed.
6.5. Use case – Move Paddle
player
Move paddle
Figure 6.9. Use Case diagram for Use Case, move paddle
: player
:
PaddleMouseMotionListener
:
BallGame.GamePane
: Paddle
1. mouseDragged()
2.getGraphics( )
3. return Graphics
4. disappear()
5. moveX()
6. display()
Figure 6.10. Sequence Diagram for player dragging the mouse to move
paddle in Use Case, move paddle.
Let’s explain it step by step.
1. Player puts the mouse over paddle and drags it. This will trigger mouseDragged()
in PaddleMouseMotionListener object
2. PaddleMouseMotionListener gets a graphics object from gamePane. The graphics
object is used to display object on gamePane.
3. GamePane returns its graphics object to paddleMouseMotionListener.
4. Erase paddle at the current position.
5. Move the paddle horizontally for a distance.
6. Display the paddle at its new position.
6.6. Use case – Goto Next Level
player
Goto next level
Figure 6.11. Use Case diagram for Use Case, goto next level
: player
nextLevelBtn :
ControlButton
click
timerControlListener
...
:
BallGame
:
BallGame.GamePan
e
bricks : Brick
actionPerformed( )
: Paddle
: Tumple
Timer
playBtn :
ControlButton
stop( )
removeAll()
initBrick( )
Init()
initPaddle()
Init()
initTumple(
)
Init()
initTimer( )
Init()
setGameLevel()
setWinningLevel()
setEnable( )
setEnable( )
repaint()
trigger use case,
game playing
Figure 6.12. Sequence Diagram for player winning the previous level and
goto the next level in Use Case, goto next level.
nextLevelBtn :
ControlButton
Let’s explain it step by step.
1. Player clicks on nextLevel button.
2. TimerControlListener::actionPerformed() is triggered.
3. Timer is stopped for the time being.
4. GamePane is cleared up by removing everything.
5. Initialize the bricks objects
6. Every brick object is initialized by calling Brick::init()
7. Initialize the paddle object
8. Paddle::init() is called.
9. Initialize the tumple object
10. Tumple::init() is called.
11. Initialize Timer object
12. Timer::init() is called.
13. Increase the game level
14. Increate the winning level
15. Enable the play button so that player can click play button to play the game again.
16. Disable the next level button so that player cannot go to the next level until he win
the current level
17. GamePane is repainted, ready for starting playing the next level.
6.7. Use case – Game running
Start playing
player
<<include>>
<<include>>
Game running
Restart playing
Figure 6.13. Use Case diagram for Use Case, Game running
This use case is included in two other use cases, i.e. start playing and restart playing. It
means that this use case has no user at all. It can only be called within the starting playing
or restart playing use cases.
We present this use case with 2 sequence diagrams which illustrate 2 different scenarios
happening in the system.
6.7.1. Scenario – Ball hit the border, paddle and brick.
: Timer
:
BallTimerListener
: Ball
bricks : Brick
: BallGame
:
BallGame.GamePane
repeat after
timeDelay
actionPerformed()
ballRunning(, )
runOneStep()
hitBorder( )
return
[hit bottom] setGameOver()
repaint()
return
hit paddle
return
[hit paddle]bounceOn(paddle)
return
isHitted( )
return
[isHitted()=true] broken()
tumpleRunning()
Figure 6.14. Sequence Diagram for ball hitting border, paddle and brick
in Use Case, game running.
Let's explain it step by step.
1. For every certain amount of time, i.e. time delay,
BallTimerListener::actionPerformed() is triggered.
2. Ball is running.
3. Let the ball move a small step in the direction in which it is running.
4. Check if the border hits the border.
5. Return to let BallTimerListener know.
6. If it hits the bottom of the border, game is over.
7.
GamePane is repainted to notify the player that he lost the game.
8.
Return and stop the game.
9. Else, check if ball hits the paddle, i.e. paddle receives the ball.
10. return to let BallTimerListener know
11. If ball hits the paddle, ball bounce on the paddle and change its direction.
12. Return and execute BallTimerListener::actionPerformed again after timeDelay.
13. Check if brick objects are hitted by ball.
14. Return to let ballTimerListener know.
15. If ball hits brick object, the brick is broken and disappear.
16. Go to the sub use case, Tumple Running in 6.7.2.
6.7.2. Scenario – Tumple is running, dropping and saved.
:
BallTimerListen
er
bricks : Brick
: Tumple
: BallGame
:
BallGame.GamePa
ne
there are sequence
of
steps omitted
here
tumpleRunning
()
running(, ,
)
moveX(
)
repaint(
)
inc TumpeItem
index
tumpleSupportedByBrick
()
getCurrentTumpleItemAtBric
k( )
return
brick
isHitted( )
return
[supporting brick is hitted] dropping
isSavedBy(paddle)
return
[saved] disappear()
incNumOfItemSaved
()
resetAtRandomBrick
()
Figure 6.15. Sequence Diagram for tumple running in Use Case, game
running.
Let’s explain it step by step.
1.
2.
3.
4.
Tumple is starting to run.
Call Tumple::running() method of tumple object.
Tumple moves a small step.
Let the gamePane repaint the tumple so that it is displayed at the new position
after MoveX().
5. Increase the index of tumpleItem. Recall that there are 14 images in one tumple
object and we need to display them in turn.
6. Check if tumple is still supported by brick. I.e. Does the brick supporting the
tumple at the current position has been broken?
7. Get the current TumpleItem index
8. Return to BallTimerListener
9. Check if the supporting brick is broken.
10. Return to let BallTimerListener know.
11. If the supporting brick is broken, tumple drops down.
12.
Check if tumple is saved by paddle.
13.
return to let BallTimerListener know.
14.
if tumple is saved by paddle, then tumple disppear from the current position
15.
Increase the number of item which has been saved.
16.
Reset Tumple object at the random brick which has not been broken.
7. Class Interface Design
Download