Entity.java

/*
 * Copyright © 2011 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.battletank.game.entities;

import com.nokia.example.battletank.game.Point;
import com.nokia.example.battletank.game.Resources;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import javax.microedition.lcdui.game.Sprite;

public abstract class Entity {
    public static final int DIRECTION_UP = 0;
    public static final int DIRECTION_RIGHT = 1;
    public static final int DIRECTION_DOWN = 2;
    public static final int DIRECTION_LEFT = 3;

    protected Sprite sprite = null;

    protected volatile int direction = DIRECTION_UP;
    private volatile boolean updateSpriteDirection = true;

    protected final Point position = new Point(0, 0);
    private volatile boolean updateSpritePosition = true;

    public final int width;
    public final int height;
    protected final Resources resources;

    protected Entity(int width, int height, Resources resources) {
        this.width = width;
        this.height = height;
        this.resources = resources;
    }

    public int getDirection() {
        return direction;
    }

    protected boolean changeDirection(int newDirection) {
        boolean changed = direction != newDirection;
        direction = newDirection;
        if(changed) {
            updateSpriteDirection = true;
            updateSpritePosition = true;
        }
        return changed;
    }

    public int getX() {
        return position.x;
    }

    public int getY() {
        return position.y;
    }

    public int getCenterX() {
        return position.x + width/2;
    }

    public int getCenterY() {
        return position.y + height/2;
    }

    public boolean collidesWith(Entity e) {
        return collidesWith(e.getX(), e.getY(), e.width, e.height);
    }

    public boolean collidesWith(int x, int y, int w, int h) {
        if(!isSolid()) return false;
        return overlaps(x, x + w, position.x, position.x + width) && overlaps(y, y + h, position.y, position.y + height);
    }

    protected boolean isSolid() {
        return true;
    }

    private boolean overlaps(int startA, int endA, int startB, int endB) {
        return startA < startB ? endA > startB : endB > startA;
    }

    protected boolean move(int distance) {
        int x = position.x;
        int y = position.y;

        switch(direction) {
            case DIRECTION_UP:
                y -= distance;
                break;
            case DIRECTION_DOWN:
                y += distance;
                break;
            case DIRECTION_LEFT:
                x -= distance;
                break;
            case DIRECTION_RIGHT:
                x += distance;
                break;
        }
        return setPosition(x, y);
    }

    protected boolean setPosition(int x, int y) {
        position.x = x;
        position.y = y;
        updateSpritePosition = true;
        return true;
    }

    public Sprite getSprite() {
        if(sprite == null) {
            sprite = createSprite();
        }
        return sprite;
    }

    protected abstract Sprite createSprite();

    public void refresh() {
        if(updateSpriteDirection) {
            updateSpriteDirection = false;
            switch(direction) {
                case DIRECTION_UP:
                    sprite.setTransform(Sprite.TRANS_NONE);
                    break;
                case DIRECTION_DOWN:
                    sprite.setTransform(Sprite.TRANS_ROT180);
                    break;
                case DIRECTION_LEFT:
                    sprite.setTransform(Sprite.TRANS_ROT270);
                    break;
                case DIRECTION_RIGHT:
                    sprite.setTransform(Sprite.TRANS_ROT90);
                    break;
            }
        }
        if(updateSpritePosition) {
            updateSpritePosition = false;
            sprite.setPosition(position.x, position.y);
        }
    }

    public void update() {
    }

    public void writeTo(DataOutputStream dout) throws IOException {
        dout.writeInt(direction);
        position.writeTo(dout);
    }

    protected void readFrom(DataInputStream din) throws IOException {
        direction = din.readInt();
        Point p = Point.readFrom(din);
        position.x = p.x;
        position.y = p.y;
    }
}