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