1cfd74d65d832137e20e193c960802afba73b5d38sm/* 23c1e67e433728684b5f228c5d4f3e5b1457bb271sm * Copyright (C) 2010 The Android Open Source Project 3cfd74d65d832137e20e193c960802afba73b5d38sm * 4cfd74d65d832137e20e193c960802afba73b5d38sm * Licensed under the Apache License, Version 2.0 (the "License"); 5cfd74d65d832137e20e193c960802afba73b5d38sm * you may not use this file except in compliance with the License. 6cfd74d65d832137e20e193c960802afba73b5d38sm * You may obtain a copy of the License at 7cfd74d65d832137e20e193c960802afba73b5d38sm * 8cfd74d65d832137e20e193c960802afba73b5d38sm * http://www.apache.org/licenses/LICENSE-2.0 9cfd74d65d832137e20e193c960802afba73b5d38sm * 10cfd74d65d832137e20e193c960802afba73b5d38sm * Unless required by applicable law or agreed to in writing, software 11cfd74d65d832137e20e193c960802afba73b5d38sm * distributed under the License is distributed on an "AS IS" BASIS, 12cfd74d65d832137e20e193c960802afba73b5d38sm * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cfd74d65d832137e20e193c960802afba73b5d38sm * See the License for the specific language governing permissions and 14cfd74d65d832137e20e193c960802afba73b5d38sm * limitations under the License. 15cfd74d65d832137e20e193c960802afba73b5d38sm */ 16cfd74d65d832137e20e193c960802afba73b5d38sm 17cfd74d65d832137e20e193c960802afba73b5d38smpackage com.replica.replicaisland; 18cfd74d65d832137e20e193c960802afba73b5d38sm 19cfd74d65d832137e20e193c960802afba73b5d38sm/** 20cfd74d65d832137e20e193c960802afba73b5d38sm * Provides an interface for controlling a sprite with animations. Manages a list of animations 21cfd74d65d832137e20e193c960802afba73b5d38sm * and provides a drawable surface with the correct animation frame to a render component each 22cfd74d65d832137e20e193c960802afba73b5d38sm * frame. Also manages horizontal and vertical flipping. 23cfd74d65d832137e20e193c960802afba73b5d38sm */ 24cfd74d65d832137e20e193c960802afba73b5d38smpublic class SpriteComponent extends GameComponent { 25cfd74d65d832137e20e193c960802afba73b5d38sm 26cfd74d65d832137e20e193c960802afba73b5d38sm private PhasedObjectManager mAnimations; 27cfd74d65d832137e20e193c960802afba73b5d38sm private float mAnimationTime; 28cfd74d65d832137e20e193c960802afba73b5d38sm private int mCurrentAnimationIndex; 29cfd74d65d832137e20e193c960802afba73b5d38sm private int mWidth; 30cfd74d65d832137e20e193c960802afba73b5d38sm private int mHeight; 31cfd74d65d832137e20e193c960802afba73b5d38sm private float mOpacity; 32cfd74d65d832137e20e193c960802afba73b5d38sm private RenderComponent mRenderComponent; 33cfd74d65d832137e20e193c960802afba73b5d38sm private DynamicCollisionComponent mCollisionComponent; 34cfd74d65d832137e20e193c960802afba73b5d38sm private boolean mVisible; 35cfd74d65d832137e20e193c960802afba73b5d38sm private SpriteAnimation mCurrentAnimation; 36cfd74d65d832137e20e193c960802afba73b5d38sm private boolean mAnimationsDirty; 37cfd74d65d832137e20e193c960802afba73b5d38sm 38cfd74d65d832137e20e193c960802afba73b5d38sm public SpriteComponent(int width, int height) { 39cfd74d65d832137e20e193c960802afba73b5d38sm super(); 40cfd74d65d832137e20e193c960802afba73b5d38sm mAnimations = new PhasedObjectManager(); 41cfd74d65d832137e20e193c960802afba73b5d38sm 42cfd74d65d832137e20e193c960802afba73b5d38sm reset(); 43cfd74d65d832137e20e193c960802afba73b5d38sm mWidth = width; 44cfd74d65d832137e20e193c960802afba73b5d38sm mHeight = height; 45cfd74d65d832137e20e193c960802afba73b5d38sm setPhase(ComponentPhases.PRE_DRAW.ordinal()); 46cfd74d65d832137e20e193c960802afba73b5d38sm } 47cfd74d65d832137e20e193c960802afba73b5d38sm 48cfd74d65d832137e20e193c960802afba73b5d38sm public SpriteComponent() { 49cfd74d65d832137e20e193c960802afba73b5d38sm super(); 50cfd74d65d832137e20e193c960802afba73b5d38sm mAnimations = new PhasedObjectManager(); 51cfd74d65d832137e20e193c960802afba73b5d38sm 52cfd74d65d832137e20e193c960802afba73b5d38sm reset(); 53cfd74d65d832137e20e193c960802afba73b5d38sm 54cfd74d65d832137e20e193c960802afba73b5d38sm setPhase(ComponentPhases.PRE_DRAW.ordinal()); 55cfd74d65d832137e20e193c960802afba73b5d38sm } 56cfd74d65d832137e20e193c960802afba73b5d38sm 57cfd74d65d832137e20e193c960802afba73b5d38sm @Override 58cfd74d65d832137e20e193c960802afba73b5d38sm public void reset() { 59cfd74d65d832137e20e193c960802afba73b5d38sm mWidth = 0; 60cfd74d65d832137e20e193c960802afba73b5d38sm mHeight = 0; 61cfd74d65d832137e20e193c960802afba73b5d38sm mVisible = true; 62cfd74d65d832137e20e193c960802afba73b5d38sm mCurrentAnimationIndex = -1; 63cfd74d65d832137e20e193c960802afba73b5d38sm mAnimations.removeAll(); 64cfd74d65d832137e20e193c960802afba73b5d38sm mAnimations.commitUpdates(); 65cfd74d65d832137e20e193c960802afba73b5d38sm mAnimationTime = 0.0f; 66cfd74d65d832137e20e193c960802afba73b5d38sm mRenderComponent = null; 67cfd74d65d832137e20e193c960802afba73b5d38sm mCollisionComponent = null; 68cfd74d65d832137e20e193c960802afba73b5d38sm mCurrentAnimation = null; 69cfd74d65d832137e20e193c960802afba73b5d38sm mOpacity = 1.0f; 70cfd74d65d832137e20e193c960802afba73b5d38sm mAnimationsDirty = false; 71cfd74d65d832137e20e193c960802afba73b5d38sm } 72cfd74d65d832137e20e193c960802afba73b5d38sm 73cfd74d65d832137e20e193c960802afba73b5d38sm @Override 74cfd74d65d832137e20e193c960802afba73b5d38sm public void update(float timeDelta, BaseObject parent) { 75cfd74d65d832137e20e193c960802afba73b5d38sm mAnimationTime += timeDelta; 76cfd74d65d832137e20e193c960802afba73b5d38sm final PhasedObjectManager animations = mAnimations; 77cfd74d65d832137e20e193c960802afba73b5d38sm final int currentAnimIndex = mCurrentAnimationIndex; 78cfd74d65d832137e20e193c960802afba73b5d38sm 79cfd74d65d832137e20e193c960802afba73b5d38sm if (mAnimationsDirty) { 80cfd74d65d832137e20e193c960802afba73b5d38sm animations.commitUpdates(); 81cfd74d65d832137e20e193c960802afba73b5d38sm mAnimationsDirty = false; 82cfd74d65d832137e20e193c960802afba73b5d38sm } 83cfd74d65d832137e20e193c960802afba73b5d38sm boolean validFrameAvailable = false; 84cfd74d65d832137e20e193c960802afba73b5d38sm if (animations.getCount() > 0 && currentAnimIndex != -1) { 85cfd74d65d832137e20e193c960802afba73b5d38sm SpriteAnimation currentAnimation = mCurrentAnimation; 86cfd74d65d832137e20e193c960802afba73b5d38sm 87cfd74d65d832137e20e193c960802afba73b5d38sm if (currentAnimation == null && currentAnimIndex != -1) { 88cfd74d65d832137e20e193c960802afba73b5d38sm currentAnimation = findAnimation(currentAnimIndex); 89cfd74d65d832137e20e193c960802afba73b5d38sm if (currentAnimation == null) { 90cfd74d65d832137e20e193c960802afba73b5d38sm // We were asked to play an animation that doesn't exist. Revert to our 91cfd74d65d832137e20e193c960802afba73b5d38sm // default animation. 92cfd74d65d832137e20e193c960802afba73b5d38sm // TODO: throw an assert here? 93cfd74d65d832137e20e193c960802afba73b5d38sm mCurrentAnimation = (SpriteAnimation)animations.get(0); 94cfd74d65d832137e20e193c960802afba73b5d38sm currentAnimation = mCurrentAnimation; 95cfd74d65d832137e20e193c960802afba73b5d38sm } else { 96cfd74d65d832137e20e193c960802afba73b5d38sm mCurrentAnimation = currentAnimation; 97cfd74d65d832137e20e193c960802afba73b5d38sm } 98cfd74d65d832137e20e193c960802afba73b5d38sm } 99cfd74d65d832137e20e193c960802afba73b5d38sm 100cfd74d65d832137e20e193c960802afba73b5d38sm GameObject parentObject = (GameObject)parent; 101cfd74d65d832137e20e193c960802afba73b5d38sm AnimationFrame currentFrame = currentAnimation.getFrame(mAnimationTime); 102cfd74d65d832137e20e193c960802afba73b5d38sm if (currentFrame != null) { 103cfd74d65d832137e20e193c960802afba73b5d38sm validFrameAvailable = true; 104cfd74d65d832137e20e193c960802afba73b5d38sm final RenderComponent render = mRenderComponent; 105cfd74d65d832137e20e193c960802afba73b5d38sm if (render != null) { 106cfd74d65d832137e20e193c960802afba73b5d38sm final DrawableFactory factory = sSystemRegistry.drawableFactory; 107cfd74d65d832137e20e193c960802afba73b5d38sm if (mVisible && currentFrame.texture != null && factory != null) { 108cfd74d65d832137e20e193c960802afba73b5d38sm // Fire and forget. Allocate a new bitmap for this animation frame, set it up, and 109cfd74d65d832137e20e193c960802afba73b5d38sm // pass it off to the render component for drawing. 110cfd74d65d832137e20e193c960802afba73b5d38sm DrawableBitmap bitmap = factory.allocateDrawableBitmap(); 111cfd74d65d832137e20e193c960802afba73b5d38sm bitmap.setWidth(mWidth); 112cfd74d65d832137e20e193c960802afba73b5d38sm bitmap.setHeight(mHeight); 113cfd74d65d832137e20e193c960802afba73b5d38sm bitmap.setOpacity(mOpacity); 114cfd74d65d832137e20e193c960802afba73b5d38sm updateFlip(bitmap, parentObject.facingDirection.x < 0.0f, 115cfd74d65d832137e20e193c960802afba73b5d38sm parentObject.facingDirection.y < 0.0f); 116cfd74d65d832137e20e193c960802afba73b5d38sm bitmap.setTexture(currentFrame.texture); 117cfd74d65d832137e20e193c960802afba73b5d38sm render.setDrawable(bitmap); 118cfd74d65d832137e20e193c960802afba73b5d38sm } else { 119cfd74d65d832137e20e193c960802afba73b5d38sm render.setDrawable(null); 120cfd74d65d832137e20e193c960802afba73b5d38sm } 121cfd74d65d832137e20e193c960802afba73b5d38sm } 122cfd74d65d832137e20e193c960802afba73b5d38sm 123cfd74d65d832137e20e193c960802afba73b5d38sm if (mCollisionComponent != null) { 124cfd74d65d832137e20e193c960802afba73b5d38sm mCollisionComponent.setCollisionVolumes(currentFrame.attackVolumes, 125cfd74d65d832137e20e193c960802afba73b5d38sm currentFrame.vulnerabilityVolumes); 126cfd74d65d832137e20e193c960802afba73b5d38sm } 127cfd74d65d832137e20e193c960802afba73b5d38sm } 128cfd74d65d832137e20e193c960802afba73b5d38sm } 129cfd74d65d832137e20e193c960802afba73b5d38sm 130cfd74d65d832137e20e193c960802afba73b5d38sm if (!validFrameAvailable) { 131cfd74d65d832137e20e193c960802afba73b5d38sm // No current frame = draw nothing! 132cfd74d65d832137e20e193c960802afba73b5d38sm if (mRenderComponent != null) { 133cfd74d65d832137e20e193c960802afba73b5d38sm mRenderComponent.setDrawable(null); 134cfd74d65d832137e20e193c960802afba73b5d38sm } 135cfd74d65d832137e20e193c960802afba73b5d38sm if (mCollisionComponent != null) { 136cfd74d65d832137e20e193c960802afba73b5d38sm mCollisionComponent.setCollisionVolumes(null, null); 137cfd74d65d832137e20e193c960802afba73b5d38sm } 138cfd74d65d832137e20e193c960802afba73b5d38sm } 139cfd74d65d832137e20e193c960802afba73b5d38sm } 140cfd74d65d832137e20e193c960802afba73b5d38sm 141cfd74d65d832137e20e193c960802afba73b5d38sm public final void playAnimation(int index) { 142cfd74d65d832137e20e193c960802afba73b5d38sm if (mCurrentAnimationIndex != index) { 143cfd74d65d832137e20e193c960802afba73b5d38sm mAnimationTime = 0; 144cfd74d65d832137e20e193c960802afba73b5d38sm mCurrentAnimationIndex = index; 145cfd74d65d832137e20e193c960802afba73b5d38sm mCurrentAnimation = null; 146cfd74d65d832137e20e193c960802afba73b5d38sm } 147cfd74d65d832137e20e193c960802afba73b5d38sm } 148cfd74d65d832137e20e193c960802afba73b5d38sm 149cfd74d65d832137e20e193c960802afba73b5d38sm public final SpriteAnimation findAnimation(int index) { 150cfd74d65d832137e20e193c960802afba73b5d38sm return (SpriteAnimation)mAnimations.find(index); 151cfd74d65d832137e20e193c960802afba73b5d38sm } 152cfd74d65d832137e20e193c960802afba73b5d38sm 153cfd74d65d832137e20e193c960802afba73b5d38sm public final void addAnimation(SpriteAnimation anim) { 154cfd74d65d832137e20e193c960802afba73b5d38sm mAnimations.add(anim); 155cfd74d65d832137e20e193c960802afba73b5d38sm mAnimationsDirty = true; 156cfd74d65d832137e20e193c960802afba73b5d38sm } 157cfd74d65d832137e20e193c960802afba73b5d38sm 158cfd74d65d832137e20e193c960802afba73b5d38sm public final boolean animationFinished() { 159cfd74d65d832137e20e193c960802afba73b5d38sm boolean result = false; 160cfd74d65d832137e20e193c960802afba73b5d38sm if (mCurrentAnimation != null 161cfd74d65d832137e20e193c960802afba73b5d38sm && !mCurrentAnimation.getLoop() 162cfd74d65d832137e20e193c960802afba73b5d38sm && mAnimationTime > mCurrentAnimation.getLength()) { 163cfd74d65d832137e20e193c960802afba73b5d38sm result = true; 164cfd74d65d832137e20e193c960802afba73b5d38sm } 165cfd74d65d832137e20e193c960802afba73b5d38sm return result; 166cfd74d65d832137e20e193c960802afba73b5d38sm } 167cfd74d65d832137e20e193c960802afba73b5d38sm 168cfd74d65d832137e20e193c960802afba73b5d38sm 169cfd74d65d832137e20e193c960802afba73b5d38sm public final float getWidth() { 170cfd74d65d832137e20e193c960802afba73b5d38sm return mWidth; 171cfd74d65d832137e20e193c960802afba73b5d38sm } 172cfd74d65d832137e20e193c960802afba73b5d38sm 173cfd74d65d832137e20e193c960802afba73b5d38sm public final float getHeight() { 174cfd74d65d832137e20e193c960802afba73b5d38sm return mHeight; 175cfd74d65d832137e20e193c960802afba73b5d38sm } 176cfd74d65d832137e20e193c960802afba73b5d38sm 177cfd74d65d832137e20e193c960802afba73b5d38sm public final void setSize(int width, int height) { 178cfd74d65d832137e20e193c960802afba73b5d38sm mWidth = width; 179cfd74d65d832137e20e193c960802afba73b5d38sm mHeight = height; 180cfd74d65d832137e20e193c960802afba73b5d38sm } 181cfd74d65d832137e20e193c960802afba73b5d38sm 182cfd74d65d832137e20e193c960802afba73b5d38sm protected final void updateFlip(DrawableBitmap bitmap, boolean horzFlip, boolean vertFlip) { 183cfd74d65d832137e20e193c960802afba73b5d38sm bitmap.setFlip(horzFlip, vertFlip); 184cfd74d65d832137e20e193c960802afba73b5d38sm } 185cfd74d65d832137e20e193c960802afba73b5d38sm 186cfd74d65d832137e20e193c960802afba73b5d38sm public final void setRenderComponent(RenderComponent component) { 187cfd74d65d832137e20e193c960802afba73b5d38sm mRenderComponent = component; 188cfd74d65d832137e20e193c960802afba73b5d38sm } 189cfd74d65d832137e20e193c960802afba73b5d38sm 190cfd74d65d832137e20e193c960802afba73b5d38sm public final void setCollisionComponent(DynamicCollisionComponent component) { 191cfd74d65d832137e20e193c960802afba73b5d38sm mCollisionComponent = component; 192cfd74d65d832137e20e193c960802afba73b5d38sm } 193cfd74d65d832137e20e193c960802afba73b5d38sm 194cfd74d65d832137e20e193c960802afba73b5d38sm public final boolean getVisible() { 195cfd74d65d832137e20e193c960802afba73b5d38sm return mVisible; 196cfd74d65d832137e20e193c960802afba73b5d38sm } 197cfd74d65d832137e20e193c960802afba73b5d38sm 198cfd74d65d832137e20e193c960802afba73b5d38sm public final void setVisible(boolean visible) { 199cfd74d65d832137e20e193c960802afba73b5d38sm mVisible = visible; 200cfd74d65d832137e20e193c960802afba73b5d38sm } 201cfd74d65d832137e20e193c960802afba73b5d38sm 202cfd74d65d832137e20e193c960802afba73b5d38sm public final float getCurrentAnimationTime() { 203cfd74d65d832137e20e193c960802afba73b5d38sm return mAnimationTime; 204cfd74d65d832137e20e193c960802afba73b5d38sm } 205cfd74d65d832137e20e193c960802afba73b5d38sm 206cfd74d65d832137e20e193c960802afba73b5d38sm public final void setCurrentAnimationTime(float time) { 207cfd74d65d832137e20e193c960802afba73b5d38sm mAnimationTime = time; 208cfd74d65d832137e20e193c960802afba73b5d38sm } 209cfd74d65d832137e20e193c960802afba73b5d38sm 210cfd74d65d832137e20e193c960802afba73b5d38sm public final void setOpacity(float opacity) { 211cfd74d65d832137e20e193c960802afba73b5d38sm mOpacity = opacity; 212cfd74d65d832137e20e193c960802afba73b5d38sm } 213cfd74d65d832137e20e193c960802afba73b5d38sm 214cfd74d65d832137e20e193c960802afba73b5d38sm public final int getCurrentAnimation() { 215cfd74d65d832137e20e193c960802afba73b5d38sm return mCurrentAnimationIndex; 216cfd74d65d832137e20e193c960802afba73b5d38sm } 217cfd74d65d832137e20e193c960802afba73b5d38sm 218cfd74d65d832137e20e193c960802afba73b5d38sm public final int getAnimationCount() { 219cfd74d65d832137e20e193c960802afba73b5d38sm return mAnimations.getConcreteCount(); 220cfd74d65d832137e20e193c960802afba73b5d38sm } 221cfd74d65d832137e20e193c960802afba73b5d38sm} 222