The Player SpritePlayerSprite represents the player and is a subclass of TiledSprite. The statechart for PlayerSprite in Figure 13-14 shows that the sprite performs three concurrent activities. The move( ) and tryPickup( ) transitions are triggered by the user from the keyboard. The hitByAlien( ) transition is initiated by the WorldDisplay object when an alien tells it that it has hit the player.
Figure 13-14. PlayerSprite statechartMoving (and Standing Still)A PlayerSprite TRies to move when the user presses one of the quadrant keys (9, 3, 1, or 7): public void move(int quad) { Point newPt = tryMove(quad); if (newPt == null) { // move not possible clipsLoader.play("slap", false); standStill( ); } else { // move is possible setTileLoc(newPt); // update the sprite's tile location if (quad == NE) setImage("ne"); else if (quad == SE) setImage("se"); else if (quad == SW) setImage("sw"); else // quad == NW setImage("nw"); world.playerHasMoved(newPt, quad); } } // end of move( ) The attempt is handled by TiledSprite's inherited tryMove( ) method, and the sprite's tile location is updated if it's successful. The move is dressed up with an image change for the sprite and the playing of a sound effect if the move is blocked. The player can press 5 to make the sprite stand still, which only changes its associated image. Normally, the sprite is poised in a running position, pointing in one of the quadrant directions. public void standStill( ) { setImage("still"); } Drawing the PlayerThe statechart includes a draw state, triggered by a draw( ) transition. The draw activity is implemented by using the setPosition( ) and draw( ) methods inherited from Sprite. The drawing isn't initiated by code in PlayerSprite but is by WorldDisplay's draw( ) method: public void draw(Graphics g) // in WorldDisplay { g.drawImage(floorIm, xOffset, yOffset, null); // draw floor image wItems.positionSprites(player, aliens); // add sprites wItems.draw(g, xOffset, yOffset); // draw things wItems.removeSprites( ); // remove sprites } As explained earlier, all the sprites, including the player, are added to WorldItems temporarily so they can be drawn in the correct z-order. Each sprite is stored as a TileOccupier object, and setPosition( ) and draw( ) are called from there. Being Hit by an AlienPlayerSprite maintains a hit counter, which is incremented by a call to hitByAlien( ) from the WorldDisplay object: public void hitByAlien( ) { clipsLoader.play("hit", false); hitCount++; if (hitCount == MAX_HITS) // player is dead atPanel.gameOver( ); } When hitCount reaches a certain value (MAX_HITS), it's all over. The sprite doesn't terminate though; it only notifies AlienTilePanel. This allows AlienTilesPanel to carry out "end of game" tasks, which in this case are reporting the game score and playing a sound clip of applause. AlienTilesPanel could do a lot more, such as ask users if they wanted to play another game. These kinds of game-wide activities should be done at the game panel level and not by a sprite. Trying to Pick Up a PickupThe user tries to pick up an item by pressing 2 on the numbers keypad. The hard work here is determining if the sprite's current tile location contains a pickup and to remove that item from the scene. The two operations are handled by WorldDisplay methods: public boolean tryPickup( ) { String pickupName; if ((pickupName = world.overPickup( getTileLoc( ))) == null) { clipsLoader.play("noPickup", false); // nothing to pickup return false; } else { // found a pickup clipsLoader.play("gotPickup", false); world.removePickup(pickupName); // tell WorldDisplay return true; } } The name of the pickup on the current tile is obtained and used in the deletion request. If the tile is empty, a sound clip will be played instead. |