Plate.java

/**
* Copyright (c) 2012-2013 Nokia Corporation. All rights reserved.
* Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation. 
* Oracle and Java are trademarks or registered trademarks of Oracle and/or its
* affiliates. Other product and company names mentioned herein may be trademarks
* or trade names of their respective owners. 
* See LICENSE.TXT for license information.
*/

package com.nokia.example.explonoid.game;

import javax.microedition.lcdui.game.Sprite;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Manages the plate that is used for hitting the ball.
 * 
 * For usage, see the Game class.
 * 
 * @see com.nokia.example.explonoid.game.Game
 */
public class Plate
        extends Sprite {

    public static final int ROWS = 10;
    private static final int INTERVAL = 40;
    private static final int PADDING_V = 6;
    private static final int PADDING_H = 7;
    private static final int INIT_WIDTH = 59;
    private static final int VELOCITY = 4;
    private int velocity;
    private int width;
    private int displayWidth;
    private Timer animator;
    private Resources r;

    public Plate(int displayWidth, Resources r) {
        super(r.plate, r.plate.getWidth(), r.plate.getHeight() / ROWS);
        this.displayWidth = displayWidth;
        this.r = r;
        width = r.scale(INIT_WIDTH);
        setCollisionRectangle();
        defineReferencePixel((int) (getWidth() * 0.5 + 0.5), (int) (getHeight() * 0.5 + 0.5));
        velocity = 0;
    }

    // Stretching the plate
    public void stretch() {
        animator = new Timer();
        TimerTask stretch = new TimerTask() {

            public void run() {
                if (getFrame() < getRawFrameCount() - 1) {
                    width += r.scale(4);
                    correctPosition();
                    nextFrame();
                    setCollisionRectangle();
                }
                else {
                    this.cancel();
                }
            }
        };
        animator.schedule(stretch, 0, INTERVAL);
    }

    // Shrinking the plate
    public void shrink() {
        animator = new Timer();
        TimerTask shrink = new TimerTask() {

            public void run() {
                if (getFrame() > 0) {
                    width -= r.scale(4);
                    correctPosition();
                    prevFrame();
                    setCollisionRectangle();
                }
                else {
                    this.cancel();
                }
            }
        };
        animator.schedule(shrink, 0, INTERVAL);
    }

    private void setCollisionRectangle() {
        defineCollisionRectangle((int) ((getWidth() - width) * 0.5 + 0.5) + r.scale(PADDING_H),
                                 r.scale(PADDING_V), width - r.scale(PADDING_H), getHeight());
    }

    // If the stretching happens near the edges, keep
    // the plate inside
    private void correctPosition() {
        if (getRightX() > displayWidth) {
            move(-2, 0);
        }
        else if (getLeftX() < 0) {
            move(2, 0);
        }
    }

    public void moveLeft() {
        velocity = -r.scale(VELOCITY);
        move(velocity, 0);
    }

    public void moveRight() {
        velocity = r.scale(VELOCITY);
        move(velocity, 0);
    }

    public int getLeftX() {
        return getX() + (int) ((getWidth() - width) * 0.5 + r.scale(PADDING_H) + 0.5);
    }

    public int getRightX() {
        return getLeftX() + width - 2 * r.scale(PADDING_H);
    }

    public int getTopY() {
        return getY() + r.scale(PADDING_V);
    }

    public int getPlateWidth() {
        return width;
    }

    public int getVelocity() {
        return velocity;
    }

    public void setMoving(int x) {
        velocity = x < this.getRefPixelX() ? -VELOCITY : VELOCITY;
    }

    public boolean isMoving() {
        return velocity != 0 ? true : false;
    }

    public void stop() {
        velocity = 0;
    }
}