/*
* Foogl (Friendly Object Oriented Game Library)
* Copyright (c) 2008 Wachirawut Thamviset.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package kku.cs.fgl;
import java.util.Vector;
import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.geom.Shape;
import org.newdawn.slick.geom.Transform;
import org.newdawn.slick.opengl.renderer.Renderer;
import org.newdawn.slick.opengl.renderer.SGL;
/**
*
* @author Wachirawut Thamviset
*
*/
public class Actor {
static SGL GL = Renderer.get();
static private int Actor_ID = 0;
static public float distance(float x1, float y1, float x2, float y2) {
float d = ((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2));
return (float) Math.sqrt(d);
}
ActorGroup parent;
protected Rectangle bound = new Rectangle(0, 0, 20, 20);
private float x_old, y_old;
private float speed_x = 0, speed_y = 0, speed_rotate = 0;
private boolean dead = false;
private boolean mouseEnterState = false;
private float alphaLevel = 1; /* 0 = transparent 1=solid */
private float rotation = 0;
private int zorder;
private boolean visible = true;
private String name = "";
protected AbstractScene scene = null;
protected Input input = null;
protected ActorControllerList controller = new ActorControllerList();
private float scalex = 1f, scaley = 1f;
private Color filter = new Color(1f, 1f, 1f, 1f);
/**
* set ʶҹ���� dead �� true �Ҥ��ա���� duration
*
* @param duration
* ����
*/
private int dead_duration = -1;
private Shape cacheShape = null;
private float cacheRotation = 0, cacheX = 0, cacheY = 0;
private boolean showBound = false;
public Actor() {
this(0, 0, 20, 20, 0, 0);
}
public Actor(float x, float y) {
this(x, y, 20, 20, 0, 0);
}
public Actor(float x, float y, int width, int height) {
this(x, y, width, height, 0, 0);
}
public Actor(float x, float y, int width, int height, float speed_x,
float speed_y) {
super();
this.bound.setBounds(x, y, width, height);
this.speed_x = speed_x;
this.speed_y = speed_y;
name = "a" + Actor_ID;
Actor_ID++;
}
public void afterAdded() {
}
/**
* ����Ѻ�ӹdz���˹�����ͧ Actor �¶١���¡�ҡ tick ����ö override
* ������ ����¹�ŧ��÷ӧҹ
*/
public void calculatePosition(int time) {
x_old = this.bound.getX();
y_old = this.bound.getY();
if (speed_x != 0 || speed_y != 0) {
float nx = x_old;
float ny = y_old;
if (speed_x != 0) {
nx = nx + (speed_x * time) / 10;
}
if (speed_y != 0) {
ny = ny + (speed_y * time) / 10;
}
this.bound.setLocation(nx, ny);
}
if (speed_rotate != 0) {
rotation += (speed_rotate * time) / 10;
if (rotation > 360)
rotation = 0;
if (rotation < 0)
rotation = 359;
}
}
/**
* ����Ѻ�ӹdz speed ����ͧ Actor �¶١���¡�ҡ tick ����ö override
* ������ ����¹�ŧ��÷ӧҹ
*/
public void calculateSpeed(int time) {
}
public void collide(Actor other, int x, int y, int type) {
}
/**
* ���ͺ��� �ش x2,y2 ����㹾�鹷��ͧ Actor ����������
*/
public boolean contains(float x2, float y2) {
return getShape().contains(x2, y2);
}
/**
* set ʶҹ���� dead �� true ��������¡ ActorGroup.removeDead() actor
* ����ж١ź�͡�ҡ list
*/
public void dead() {
dead = true;
}
public void dead(int duration) {
if (dead_duration < 0)
dead_duration = duration;
}
/**
* �ӹdz������ҧ�����ҧ �ش�ٹ���ҧ�ͧ Actor �Ѻ�ش x2,y2
*/
public float distance(float x2, float y2) {
float x1 = getCenterX();
float y1 = getCenterY();
float d = ((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2));
return (float) Math.sqrt(d);
}
/**
* @return Returns the alphaLevel.
*/
public float getAlphaLevel() {
return alphaLevel;
}
/**
* @return Returns the bound.
*/
public Rectangle getBound() {
return bound;
}
/**
* �Ҩش�ٹ���ҧ�ͧ Actor ��� X
*/
public float getCenterX() {
float n = bound.getCenterX();
if (scalex != 1f) {
float diff = n - getX();
n = getX() + diff * scalex;
}
return n;
}
/**
* �Ҩش�ٹ���ҧ�ͧ Actor ��� Y
*/
public float getCenterY() {
float n = bound.getCenterY();
if (scaley != 1f) {
n = getY() + (n - getY()) * scaley;
}
return n;
}
public Color getColor() {
return getFilter();
}
public ActorController getController() {
return controller;
}
public Color getFilter() {
return filter;
}
public int getHeight() {
return (int) Math.round(bound.getHeight());
}
/**
* @return Returns the name.
*/
public String getName() {
return name;
}
public float getRotateSpeed() {
return speed_rotate;
}
public float getRotation() {
return rotation;
}
public float getScalex() {
return scalex;
}
public float getScaley() {
return scaley;
}
public Shape getShape() {
Shape b = bound;
float sx = getX();
float sy = getY();
if (scalex != 1 || scaley != 1) {
b = new Rectangle(sx, sy, bound.getWidth() * scalex, bound
.getHeight()
* scaley);
}
if (rotation > 0.1f || rotation < -0.1f) {
if (cacheRotation == rotation && cacheShape != null && sx == cacheX
&& sy == cacheY) {
return cacheShape;
}
float angle = (float) Math.toRadians(rotation);
Shape s = b.transform(Transform.createRotateTransform(angle,
getCenterX(), getCenterY()));
cacheShape = s;
cacheRotation = rotation;
cacheX = getX();
cacheY = getY();
return s;
}
return b;
}
public float getSpeed_x() {
return speed_x;
}
public float getSpeed_y() {
return speed_y;
}
public int getWidth() {
return (int) bound.getWidth();
}
public float getX() {
return bound.getX();
}
public float getX_old() {
return x_old;
}
public float getY() {
return bound.getY();
}
public float getY_old() {
return y_old;
}
/**
* @return Returns the zorder.
*/
public int getZorder() {
return zorder;
}
public boolean hasColorAt(Image img, float x, float y) {
int cx = (int) ((x - getX()) / getScalex());
int cy = (int) ((y - getY()) / getScaley());
Color c = img.getColor(cx, cy);
return c.a > 0.1f;
}
public boolean isDead() {
return dead;
}
public boolean isMouseEnterState() {
return mouseEnterState;
}
/**
* @return Returns the visible.
*/
public boolean isVisible() {
if(dead)return false;
if(bound.getMaxX()<0 || bound.getMaxY()< 0) return false;
return visible;
}
/**
* mouseClicked �ж١���¡����� actor �١ click ����ö override
* ���ͷӧҹ���ҷ�� actor �١ click
*/
public void mouseClicked(int button) {
if (controller != null)
controller.mouseClicked(this, button);
}
/**
* mouseEntered �ж١���¡����� actor �� mouse �����㹾�鹷��
* ���ͷӧҹ���ҷ�� actor �١ click
*/
public void mouseEntered() {
if (controller != null)
controller.mouseEntered(this);
}
/**
* mouseClicked �ж١���¡����� actor �� mouse �͡�ҡ㹾�鹷��
* ���ͷӧҹ���ҷ�� actor �١ click
*/
public void mouseExited() {
if (controller != null)
controller.mouseExited(this);
}
/**
* Override �����ʴ��Ҿ�ͧ Actor ��� ���Ԩ��Ҵ�Ҿ
*
* @param g
* ����ͧ���¡��ҹ method ����ͧ method ���ж١���¡��ҹ�ҡ
* class GamePane
*/
public void paint(Graphics g) {
g.setColor(filter);
g.drawRect(0, 0, getWidth(), getHeight());
}
public void removeController(ActorController controller) {
this.controller.remove(controller);
}
final public void render(Graphics g) {
float x = getX();
float y = getY();
if (!isVisible() || isDead())
return;
GL.glPushMatrix();
if (rotation > 0.01f || rotation < -0.01f) {
g.rotate(getCenterX(), getCenterY(), rotation);
}
g.translate(x, y);
if (scalex != 1f || scaley != 1f) {
g.scale(scalex, scaley);
}
paint(g);
g.setDrawMode(Graphics.MODE_NORMAL);
// g.resetTransform();
GL.glPopMatrix();
if (showBound) {
g.setColor(Color.red);
g.draw(getShape());
}
}
public void resize(float w, float h) {
this.bound.setSize(w, h);
}
/**
* @param alphaLevel
* The alphaLevel to set.
*/
public void setAlphaLevel(float alphaLevel) {
if (alphaLevel > 1)
alphaLevel = 1f;
this.alphaLevel = alphaLevel;
if (this.alphaLevel <= 0)
this.alphaLevel = 0f;
this.filter.a = alphaLevel;
}
public void setCenter(float cx, float cy) {
Rectangle b = bound;
if (scalex != 1 || scaley != 1) {
b = new Rectangle(bound.getX(), bound.getY(), bound.getWidth()
* scalex, bound.getHeight() * scaley);
}
b.setCenterX(cx);
b.setCenterY(cy);
setLocation(b.getX(), b.getY());
}
public void setColor(Color color) {
setFilter(color);
}
public void setController(ActorController controller) {
if (controller == null) {
this.controller.clear();
} else {
this.controller.add(controller);
}
}
public void setFilter(Color filter) {
this.filter.r = filter.r;
this.filter.g = filter.g;
this.filter.b = filter.b;
this.filter.a = filter.a;
}
public void setHeight(int height) {
bound.setHeight(height);
}
/**
* ����Ѻ��˹����˹觢ͧ Actor �����Ҿ
*
* @param x
* @param y
*/
public void setLocation(float x, float y) {
bound.setLocation(x, y);
}
/**
* @param mouseEnterState
* The mouseEnterState to set.
*/
protected void setMouseEnterState(boolean mouseEnterState) {
if (this.mouseEnterState != mouseEnterState) {
this.mouseEnterState = mouseEnterState;
if (mouseEnterState)
mouseEntered();
else
mouseExited();
}
}
/**
* @param name
* The name to set.
*/
public void setName(String name) {
this.name = name;
}
public void setRotateSpeed(float speed_rotate) {
this.speed_rotate = speed_rotate;
}
public void setRotation(float rotation) {
this.rotation = rotation;
}
public void setScale(float x, float y) {
setScalex(x);
setScaley(y);
}
public void setScalex(float scalex) {
if (scalex >= 0.01f && scalex < 50)
this.scalex = scalex;
}
public void setScaley(float scaley) {
if (scaley >= 0.01 && scaley < 50)
this.scaley = scaley;
}
/**
* @param i
* @param j
*/
public void setSize(float w, float h) {
bound.setSize(w, h);
}
/**
* ����Ѻ��˹���������㹡���������
*
* @param speed_x
* @param speed_y
*/
public void setSpeed(float speed_x, float speed_y) {
this.speed_x = speed_x;
this.speed_y = speed_y;
}
public void setSpeed_x(float speed_x) {
this.speed_x = speed_x;
}
public void setSpeed_y(float speed_y) {
this.speed_y = speed_y;
}
/**
* @param visible
* The visible to set.
*/
public void setVisible(boolean visible) {
this.visible = visible;
}
public void setWidth(int width) {
bound.setWidth(width);
}
public void setX(float x) {
bound.setX(x);
}
public void setY(float y) {
bound.setY(y);
}
/**
* zorder ���ӴѺ�ͧ����ҧ actor Actor ����� zorder �ҡ�������ҹ˹�� �ͧ
* actor ����� zorder ���¡���
*
* @param zorder
* The zorder to set.
*/
public void setZorder(int zorder) {
this.zorder = zorder;
if (this.parent != null)
this.parent.sort();
}
/**
* @param time
* ���������ҧ�ͧ���� (1/1000 �Թҷ�) �����ҧ������¡ update
* �����ͺ
*/
public void update(int time) {
if (controller != null)
controller.update(this, time);
if (dead_duration > 0) {
dead_duration -= time;
if (dead_duration <= 0)
dead();
}
if(bound.getY()<-1000 || bound.getX()<-1000) dead();
calculatePosition(time);
calculateSpeed(time);
}
public ActorGroup getParent() {
return parent;
}
public AbstractScene getScene() {
return scene;
}
private int mouseX, mouseY;
public int getMouseX() {
return mouseX;
}
public int getMouseY() {
return mouseY;
}
public void setMouseXY(float x, float y) {
mouseX = (int) x;
mouseY = (int) y;
}
public boolean isShowBound() {
return showBound;
}
public void setShowBound(boolean showBound) {
this.showBound = showBound;
}
}