/******************************************************************************* * Copyright 2013 pyros2097 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package sink.map; import sink.core.SceneActor; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.g2d.Animation; import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.graphics.g2d.ParticleEffect; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.Intersector; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.scenes.scene2d.Action; import com.badlogic.gdx.scenes.scene2d.actions.Actions; import com.badlogic.gdx.scenes.scene2d.actions.MoveByAction; import com.badlogic.gdx.scenes.scene2d.actions.MoveToAction; import com.badlogic.gdx.utils.Array; /** The MapActor Class * <p> * The MapActor is a SceneActor that can be used as a static tile, animated tile, animated actor or as a plain * actor.<br> * 1.For using it as a Static Tile use:<br> * MapActor(TextureRegion region, int row, int col, int id, int tileSize)<br> * 2.For using it as a Animated Tile/Actor use:<br> * MapActor(Animation a, int row, int col, int id, int tileSize)<br> * 3.For using it as a plain Actor use:<br> * MapActor(int row, int col, int tileSize)<br> * * It has many important methods like moveTo, moveBy, collides, intersects, getCenterX, getCenterY * * <b>Note:</b> Only Use setPositionXY and SetPositionRC on this actor do not use the Actor's setPosition method * as it causes problems * @author pyros2097 */ public class MapActor extends SceneActor { private int row; private int col; private int tileSize; public TextureRegion tileImage; public int index; protected Animation animation; protected boolean isAnimationActive = false; protected boolean isAnimationLooping = true; protected TextureRegion keyFrame; // Particle public ParticleEffect particleEffect; public float particlePosX = 0.0f; public float particlePosY = 0.0f; public boolean isParticleEffectActive; private Array<MovedListener> movedListeners = new Array<MovedListener>(); // When tiles coords row and column are directly specified public MapActor(int row, int col, int tileSize){ setTileSize(tileSize); setPositionRC(row, col); setSize(tileSize, tileSize); // All map units are 24x24 } public MapActor(TextureRegion region, int row, int col, int id, int tileSize){ this(row, col, tileSize); index = id; if(region != null) tileImage = region; } public MapActor(Animation a, int row, int col, int id, int tileSize) { this(row, col, tileSize); index = id; if(a != null){ animation = a; isAnimationActive = true; } } @Override public void draw(Batch batch, float parentAlpha) { super.draw(batch, parentAlpha); batch.setColor(getColor()); if(tileImage != null) batch.draw(tileImage, getX(), getY(), tileSize, tileSize); //font("normal").draw(batch, ""+index, getX(), getY()+tileSize); if (isAnimationActive && animation != null) { keyFrame = animation.getKeyFrame(stateTime, isAnimationLooping); batch.draw(keyFrame, getX(), getY(), tileSize, tileSize); } drawParticleEffect(batch); } public void drawParticleEffect(Batch batch){ if (isParticleEffectActive) { particleEffect.draw(batch, Gdx.graphics.getDeltaTime()); particleEffect.setPosition(getX() + particlePosX, getY()+ particlePosY); } } /** * Set particle for this actor, centerPosition is used to center the * particle on this actor sizes * */ public void setParticleEffect(ParticleEffect particleEffect, boolean isParticleEffectActive, boolean isStart, boolean centerPosition) { this.particleEffect = particleEffect; this.isParticleEffectActive = isParticleEffectActive; if (!centerPosition) { this.particleEffect.setPosition(getX(), getY()); } else { particlePosX = getWidth() / 2.0f; particlePosY = getHeight() / 2.0f; this.particleEffect.setPosition(getX() + particlePosX, getY() + particlePosY); } if (isStart) { this.particleEffect.start(); } } /** * Set particle position * */ public void setParticlePositionXY(float x, float y) { particlePosX = x; particlePosY = y; } public void setTileSize(int tsize){ tileSize = tsize; } public int getTileSize(){ return tileSize; } public int getCol(){ return col; } public int getRow(){ return row; } /* * Col is always x-axis and Row is y-axis */ public void setPositionRC(int row, int col){ setPosition(col*tileSize, row*tileSize); } /* * The setPosition calls the super Actor's setPosition method and also updates the row and col * position of the tile */ @Override public void setPosition(float x, float y){ super.setPosition(x, y); this.row =(int)this.getY()/tileSize; this.col = (int)this.getX()/tileSize; } public void moveTo(float x, float y, float duration) { // Move to a specific position by time MoveToAction move = new MoveToAction(); move.setPosition(x, y); if (duration > 0.0f) { move.setDuration(duration); } Action over = new Action() { @Override public boolean act(final float it) { setPosition(this.getActor().getX(), this.getActor().getY()); fireMovedEvent(); return true; } }; addAction(Actions.sequence(move, over)); } public void moveBy(float x, float y, float duration) { // Move towards a direction during given time (NON-STOP) MoveByAction move = new MoveByAction(); move.setAmount(x, y); if (duration > 0.0f) { move.setDuration(duration); } Action over = new Action() { @Override public boolean act(final float it) { setPosition(this.getActor().getX(), this.getActor().getY()); fireMovedEvent(); return true; } }; addAction(Actions.sequence(move, over)); } /** * Translate actor in a direction of speed without stopping. Actor moves in * constants speed set without acceleration * * @param speedX * axis-X speed * @param speedY * axis-Y speed * @param delta * the delta time for accurate speed * */ public void translateWithoutAcc(float speedX, float speedY, float delta) { setPosition(getX() + (speedX * delta), getY() + (speedY * delta)); } /** * Get center x point of an object * <p> * EXAMPLE<br> * Object's width 200, and we touched the screen in 400 in position X, and * we want to center the object according to our touch position. (200 / 2 = * 100 then 400 - 100), so 300 our center position * * */ public static float getCenterX(float eventX, float objectWidth) { return eventX - (objectWidth / 2); } /** * @see getCenterX() * */ public static float getCenterY(float eventY, float objectHeight) { return eventY - (objectHeight / 2); } public boolean intersects(MapActor other){ //Sink.log(""+row+" : "+other.getRow()); if(col == other.getCol() && row == other.getRow()) return true; return false; } /** * Get the rectangle of an actor from its current POSITION and SIZE * */ public Rectangle getBoundingBox() { float posX = this.getX(); float posY = this.getY(); float width = this.getWidth(); float height = this.getHeight(); return new Rectangle(posX, posY, width, height); } public boolean collides(float x, float y) { Rectangle rectA1 = getBoundingBox(); Rectangle rectA2 = new Rectangle(x, y, 5, 5); // Check if rectangles collides if (Intersector.overlaps(rectA1, rectA2)) { return true; } else { return false; } } public boolean collides(MapActor other) { Rectangle rectA1 = getBoundingBox(); Rectangle rectA2 = other.getBoundingBox(); // Check if rectangles collides if (Intersector.overlaps(rectA1, rectA2)) { return true; } else { return false; } } public Animation getAnimation(){ return animation; } public void addListener(MovedListener ml){ movedListeners.add(ml); } public void fireMovedEvent(){ for(MovedListener ml: movedListeners) ml.onMoved(); } }