Created
July 11, 2015 00:39
-
-
Save Mnemoth42/c79b7f7caca2efecffe9 to your computer and use it in GitHub Desktop.
Various Game utility functions, designedto work together as a framework.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.tkraindesigns.gameutility; | |
import android.graphics.Bitmap; | |
import android.graphics.Canvas; | |
import android.graphics.Paint; | |
import android.graphics.PointF; | |
import android.graphics.RectF; | |
/** | |
* This is the base class for all objects that can exist within the game universe. Paddle, bullet, enemy, etc should all | |
* descend from Actor | |
* Created by Brian on 7/6/2015. | |
*/ | |
public class Actor { | |
/** | |
* Center X of object | |
*/ | |
protected float centerX; | |
/** | |
* Center Y of object | |
*/ | |
protected float centerY; | |
/** | |
* Width of object | |
*/ | |
protected float width; | |
/** | |
* Height of object | |
*/ | |
protected float height; | |
/** | |
* Width of screen | |
*/ | |
protected float screenX; | |
/** | |
* Height of screen | |
*/ | |
protected float screenY; | |
/** | |
* X component vector (pixels/second) | |
*/ | |
protected float vectorX; | |
/** | |
* Y component vector (pixels/second) | |
*/ | |
protected float vectorY; | |
/** | |
* Last frame's Y position | |
* Used to backtrack object, to just outside the actual collision boundary | |
*/ | |
protected float lastY; | |
/** | |
* Last frame's X position | |
* Used to backtrack object, to just outside the actual collision boundary | |
*/ | |
protected float lastX; | |
/** | |
* No Bitmap, BitmapBuffer, or Spritesheet available | |
*/ | |
final public int NOTDEFINED=-1; | |
/** | |
* A {@link Bitmap} has been assigned. {@link Actor#draw(Canvas, Paint)} will use that bitmap to draw | |
* the actor. | |
*/ | |
final public int BITMAP=0; | |
/** | |
* A {@link BitmapBuffer} has been assigned. {@link Actor#draw(Canvas, Paint)} will use that | |
* BitmapBuffer to draw the actor. | |
*/ | |
final public int BITMAPBUFFER=1; | |
/** | |
* A {@link Spritesheet} has been assigned. {@link Actor#draw(Canvas, Paint)} will use that | |
* Spritesheet to draw the actor | |
*/ | |
final public int SPRITESHEET=2; | |
/** | |
* {@link BitmapBuffer} assigned to this Actor (if any) | |
*/ | |
protected BitmapBuffer bitmapBuffer; | |
/** | |
* {@link Spritesheet} assigned to this Actor (if any) | |
*/ | |
protected Spritesheet spriteSheet; | |
/** | |
* {@link Bitmap} assigned to this Actor (if any) | |
*/ | |
protected Bitmap bitmap; | |
/** | |
* Current frame, used by {@link Actor#draw(Canvas, Paint)} to determine which frame to use | |
* when drawing. This should always be set using {@link Actor#setFrame(int)} to avoid illegal | |
* bounds errors. | |
*/ | |
protected int frame; | |
/** | |
* Set by {@link Actor#setBitmap(Bitmap)}, {@link Actor#setBitmapBuffer(BitmapBuffer)}, or | |
* {@link Actor#setSpriteSheet(Spritesheet)}. Should not be set otherwise under most circumstances. | |
* Used by {@link Actor#draw(Canvas, Paint)} to determine how to draw the actor | |
*/ | |
protected int imagetype =NOTDEFINED; | |
/** | |
* BARE minimum to create an Actor, you must know screenX, screenY | |
* @param screenx Screen Resolution | |
* @param screeny Screen Resolution | |
*/ | |
@SuppressWarnings("unused") | |
public Actor(float screenx,float screeny) { | |
super(); | |
centerX = 0; | |
centerY = 0; | |
width = 0; | |
height = 0; | |
screenX = screenx; | |
screenY = screeny; | |
lastX=centerX; | |
lastY=centerY; | |
vectorX=0; | |
vectorY=0; | |
} | |
/** | |
* Actor at specified position. | |
* @param centerx Center position | |
* @param centery Center position | |
* @param Width Width of actor | |
* @param Height Height of actor | |
* @param screenx Screen resolution | |
* @param screeny Screen resolution | |
*/ | |
public Actor (float centerx,float centery, float Width, float Height, float screenx, float screeny) { | |
super(); | |
centerX = centerx; | |
centerY = centery; | |
width = Width; | |
height = Height; | |
screenX = screenx; | |
screenY = screeny; | |
lastX=centerX; | |
lastY=centerY; | |
vectorX=0; | |
vectorY=0; | |
} | |
/** | |
* Creates an actor in motion | |
* @param centerx Center position | |
* @param centery Center position | |
* @param Width Width of actor | |
* @param Height Height of actor | |
* @param screenx Screen resolution | |
* @param screeny Screen resolution | |
* @param vectorx X component of speed | |
* @param vectory Y component of speed | |
*/ | |
@SuppressWarnings("unused") | |
public Actor(float centerx,float centery,float Width, float Height, float screenx, float screeny, | |
float vectorx,float vectory) { | |
super(); | |
centerX = centerx; | |
centerY = centery; | |
width = Width; | |
height = Height; | |
screenX = screenx; | |
screenY = screeny; | |
lastX=centerX; | |
lastY=centerY; | |
vectorX=vectorx; | |
vectorY=vectory; | |
} | |
/** | |
* Used in Update calls... First set VectorX and VectorY (or leave unchanged, of course) | |
* Then in actor subclass update method, call MoveActor(fps) | |
* This will let the UncollideActor function work properly as well as maintain a consistent | |
* codebase for actors and movement. | |
* @param fps Frames Per Second | |
*/ | |
@SuppressWarnings("unused") | |
public void MoveActor(long fps) { | |
lastX=centerX; | |
lastY=centerY; | |
centerX+=vectorX/(float)fps; | |
centerY+=vectorY/(float)fps; | |
} | |
/** | |
* Used after a detected collision... moves this actor outside of the offending colliding actor | |
* This function simply calls EdgeRectF(actor.getRectF()); | |
* @param actor The other actor, who we want to get uncrossed with | |
*/ | |
@SuppressWarnings("unused") | |
public void UncollideActor(Actor actor) { | |
UncollideRectF(actor.getRect()); | |
} | |
/** | |
* Back away from left edge of screen | |
*/ | |
@SuppressWarnings("unused") | |
public void UncollideLeft() { | |
UncollideRectF(new RectF(-100,0,0,screenY)); | |
} | |
/** | |
* Back away from right edge of screen | |
*/ | |
@SuppressWarnings("unused") | |
public void UncollideRight() { | |
UncollideRectF(new RectF(screenX,0,screenX+100,screenY)); | |
} | |
/** | |
* Back away from top of screen | |
*/ | |
@SuppressWarnings("unused") | |
public void UncollideTop() { | |
UncollideRectF(new RectF(0,-100,screenX,0)); | |
} | |
/** | |
* Back away from bottom of screen | |
*/ | |
@SuppressWarnings("unused") | |
public void UncollideBottom() { | |
UncollideRectF(new RectF(0,screenY,screenX,screenY+100)); | |
} | |
/** | |
* pick up a bit of the speed of the object you hit | |
* @param other Other object to get some speed from | |
*/ | |
@SuppressWarnings("unused") | |
public void absorbX(Actor other) { | |
float otherX=other.getVectorX(); | |
otherX=otherX/2f; | |
vectorX+=otherX; | |
} | |
/** | |
* pick up a bit of the speed of the object you hit | |
* @param other Other object to get some speed from | |
*/ | |
@SuppressWarnings("unused") | |
public void absorbY(Actor other) { | |
vectorY+=other.vectorY/2; | |
} | |
private float sign(float f) { | |
if (f<0) { | |
return -1; | |
} else if (f>0) { | |
return 1; | |
} | |
else { | |
return 0; | |
} | |
} | |
/** | |
* <p><b>This only works if you've been using MoveActor and setting VectorX/VectorY properly.</b></p> | |
* <p>The logic here is that once the program's update phase has detected a collision with a rect, | |
* then it wants to move this object back to just the point where the two rectangles "collide" | |
* Sort of a clearObstacle type function. By handling both the X and Y component at the same time | |
* this should avoid some of the jerkier motion effects.</p> | |
* @param rect The RectF to avoid. | |
*/ | |
@SuppressWarnings("unused") | |
public void UncollideRectF(RectF rect) { | |
float vx; | |
float vy; | |
if (vectorX==0) { //Test case for 0/180 angles, to avoid division by zero | |
vx=0; | |
vy=sign(vectorY); | |
} else { //Test case for 90/270 angles, to avoid division by zero | |
if (vectorY==0) { | |
vx=sign(vectorX); | |
vy=0; | |
} | |
else { //This sets the vector logic... greatest vector becomes 1, smallest less than | |
if (vectorY>vectorX) { | |
vx=vectorX/vectorY; | |
vy=1; | |
} else { | |
vx=1; | |
vy=vectorY/vectorX; | |
} | |
} | |
} | |
//Now we can begin subtracting (backing away) until the object is cleared | |
while (collision(rect)) { | |
centerX-=vx; | |
centerY-=vy; | |
} | |
} | |
/** | |
* The bounding rectangle for the object. Useful for collision detection and drawing | |
* @return RectF | |
*/ | |
@SuppressWarnings("unused") | |
public RectF getRect() { | |
return new RectF(centerX-width/2,centerY-height/2,centerX+width/2,centerY+height/2); | |
} | |
/** | |
* The bounding rectangle for drawing the object. Override this in cases where the rectangle | |
* is non-standard | |
* @return RectF | |
*/ | |
@SuppressWarnings("unused") | |
public RectF getDrawRect() { | |
return new RectF(centerX-width/2,centerY-height/2,centerX+width/2,centerY+height/2); | |
} | |
/** | |
* Convenience function, determine if a given point is within the bounding rectangle. | |
* Equivilant to getRect().contains(x,y) | |
* @param x Coordinate | |
* @param y Coordinate | |
* @return True if x,y is within rectangle | |
*/ | |
@SuppressWarnings("unused") | |
public boolean rectContains(int x, int y) { | |
return getRect().contains(x, y); | |
} | |
/** | |
* Convenience function, determine if a given point is within the bounding rectangle. | |
* Equivilant to getRect().contains(x,y) | |
* @param x Coordinate | |
* @param y Coordinate | |
* @return True if x,y is within rectangle | |
*/ | |
@SuppressWarnings("unused") | |
public boolean rectContains(float x, float y) { | |
return getRect().contains(x, y); | |
} | |
/** | |
* Convenience function, determine if a given point is within the bounding rectangle | |
* Uses a PointF and breaks it out for the contains(x,y) function | |
* @param point Location to test | |
* @return True if within the bounding rectangle | |
*/ | |
@SuppressWarnings("unused") | |
public boolean rectContains(PointF point) { | |
return getRect().contains(point.x, point.y); | |
} | |
/** | |
* Useage: if (collision(rect)) | |
* | |
* @param rect rectangle of object to check | |
* @return true if intersection | |
*/ | |
@SuppressWarnings("unused") | |
public boolean collision(RectF rect) { | |
return getRect().intersect(rect); | |
} | |
/** | |
* Useage: if (collision(actor)) | |
* Checks to see if the two actors collide | |
* @param actor Actor to check collission. | |
* @return true if collision | |
*/ | |
@SuppressWarnings("unused") | |
public boolean collision(Actor actor) { | |
return getRect().intersect(actor.getRect()); | |
} | |
/** | |
* This is the logic: If the sphere intersects our rectangle, then the difference between | |
* the CenterX of the sphere and the rectangle will be less than the radius and 1/2 the width. | |
* The CenterY will also be similarly situated. | |
* @param x Coordinates of sphere | |
* @param y Coordinates of sphere | |
* @param radius radius of sphere | |
* @return True if intersects | |
*/ | |
public boolean collisionSphere(float x,float y, float radius) { | |
float deltaX=Math.abs(x-centerX); | |
float deltaY=Math.abs(y-centerY); | |
return deltaX <radius + width / 2f | |
& deltaY < radius + height / 2f; | |
} | |
/** | |
* Presumes that the other actor is a SPHERE not a rectangle... (e.g. BALL) | |
* This function calls collisionSphere(x, y, radius) using the other Actor's | |
* centerX, centerY, and treating Width as radius | |
* @param actor Other actor to be tested against | |
* @return True if intersects | |
*/ | |
@SuppressWarnings("unused") | |
public boolean collisionSphere(Actor actor) { | |
return collisionSphere(actor.getCenterX(), actor.getCenterY(), actor.getWidth() / 2f); | |
} | |
/** | |
* This function presumes that -=this=- actor is a sphere and that it is checking against | |
* another sphere. | |
* @param x CenterX of other sphere | |
* @param y CenterX of other sphere | |
* @param radius Radius of other sphere | |
* @return True if intersects | |
*/ | |
@SuppressWarnings("unused") | |
public boolean collisionSphereSphere(float x, float y, float radius) { | |
return Math.pow(radius+width/2,2)>Math.pow(centerY-y,2)+Math.pow(centerX-x,2); | |
} | |
/** | |
* This function calls collisionSphereSphere against actor, presuming both this actor | |
* is a sphere and target actor is a sphere | |
* @param actor Actor to check against | |
* @return True if collision occurred | |
*/ | |
@SuppressWarnings("unused") | |
public boolean collisionSphereSphere(Actor actor) { | |
return collisionSphereSphere(actor.getCenterX(), actor.getCenterY(), actor.getWidth() / 2); | |
} | |
/** | |
* Returns true if any portion of the object is on the screen | |
* @return True if on screen | |
*/ | |
@SuppressWarnings("unused") | |
public boolean onScreen() { | |
return getRect().intersect(0, 0, screenX, screenY); | |
} | |
/** | |
* Difference in centerX between this object and actor | |
* @param actor Other actor | |
* @return the distance | |
*/ | |
@SuppressWarnings("unused") | |
public float distanceX(Actor actor) { | |
return centerX-actor.getCenterX(); | |
} | |
/** | |
* Difference in centerX between this object and actor | |
* @param actor Other actor | |
* @return the distance | |
*/ | |
@SuppressWarnings("unused") | |
public float distanceY(Actor actor) { | |
return centerY-actor.getCenterY(); | |
} | |
/** | |
* @return centerX | |
*/ | |
@SuppressWarnings("unused") | |
public float getCenterX() { | |
return centerX; | |
} | |
/** | |
* Set object position. | |
* @param x Position to set | |
* @param y Position to set | |
*/ | |
@SuppressWarnings("unused") | |
public void setPosition(float x, float y) { | |
centerX=x; | |
centerY=y; | |
} | |
/** | |
* Set object position | |
* @param x Position to set | |
* @param y Position to set | |
*/ | |
@SuppressWarnings("unused") | |
public void setPosition(int x, int y) { | |
centerX=x; | |
centerY=y; | |
} | |
/** | |
* Set position using a PointF | |
* @param point PointF location | |
*/ | |
@SuppressWarnings("unused") | |
public void setPosition(PointF point) { | |
centerX=point.x; | |
centerY=point.y; | |
} | |
/** | |
* PointF of centerX,CenterY | |
* @return new PointF(centerX,CenterY) | |
*/ | |
@SuppressWarnings("unused") | |
public PointF getPosition() { | |
return new PointF(centerX,centerY); | |
} | |
/** | |
* Preferred to use setPosition(x,y); | |
* @param centerX X position to set | |
*/ | |
@SuppressWarnings("unused") | |
public void setCenterX(float centerX) { | |
this.centerX = centerX; | |
} | |
/** | |
* @return centerY | |
*/ | |
@SuppressWarnings("unused") | |
public float getCenterY() { | |
return centerY; | |
} | |
/** | |
* Preferred to use setPosition(x,y); | |
* @param centerY Y position to set | |
*/ | |
@SuppressWarnings("unused") | |
public void setCenterY(float centerY) { | |
this.centerY = centerY; | |
} | |
/** | |
* @return Width of object | |
*/ | |
@SuppressWarnings("unused") | |
public float getWidth() { | |
return width; | |
} | |
/** | |
* Sets width of object | |
* @param width desired width | |
*/ | |
@SuppressWarnings("unused") | |
public void setWidth(float width) { | |
this.width = width; | |
} | |
/** | |
* @return Height of object | |
*/ | |
@SuppressWarnings("unused") | |
public float getHeight() { | |
return height; | |
} | |
/** | |
* set Height of object | |
* @param height desired height | |
*/ | |
@SuppressWarnings("unused") | |
public void setHeight(float height) { | |
this.height = height; | |
} | |
/** | |
* @return Width of screen | |
*/ | |
@SuppressWarnings("unused") | |
public float getScreenX() { | |
return screenX; | |
} | |
/** | |
* @param screenX Width of screen | |
*/ | |
@SuppressWarnings("unused") | |
public void setScreenX(float screenX) { | |
this.screenX = screenX; | |
} | |
/** | |
* @return Height of screen | |
*/ | |
@SuppressWarnings("unused") | |
public float getScreenY() { | |
return screenY; | |
} | |
/** | |
* @param screenY Height of screen | |
*/ | |
@SuppressWarnings("unused") | |
public void setScreenY(float screenY) { | |
this.screenY = screenY; | |
} | |
/** | |
* Returns speed in pixels/second X Component | |
* @return pixels/second X | |
*/ | |
@SuppressWarnings("unused") | |
public float getVectorX() { | |
return vectorX; | |
} | |
/** | |
* @param vectorX Pixels/second X Component | |
*/ | |
@SuppressWarnings("unused") | |
public void setVectorX(float vectorX) { | |
this.vectorX = vectorX; | |
} | |
/** | |
* Returns speed in pixels/second Y Component | |
* @return Pixels/second Y component | |
*/ | |
@SuppressWarnings("unused") | |
public float getVectorY() { | |
return vectorY; | |
} | |
/** | |
* @param vectorY Pixels/second Y Component | |
*/ | |
@SuppressWarnings("unused") | |
public void setVectorY(float vectorY) { | |
this.vectorY = vectorY; | |
} | |
/** | |
* Draws the object's bounding box on the specified canvas | |
* @param canvas Canvas to draw to | |
* @param paint Paint to use | |
*/ | |
@SuppressWarnings("unused") | |
public void drawBoundingBox(Canvas canvas,Paint paint) { | |
canvas.drawRect(getRect(), paint); | |
} | |
/** | |
* Draws the object using specified bitmap | |
* @param canvas Canvas to draw to | |
* @param bitmap Bitmap to use | |
* @param paint Paint to use | |
*/ | |
@SuppressWarnings("unused") | |
public void draw(Canvas canvas,Bitmap bitmap, Paint paint) { | |
canvas.drawBitmap(bitmap, null, getDrawRect(), paint); | |
} | |
/** | |
* Draws the object using the default bitmap, whether from a BitmapBuffer, Spritesheet or a bitmap | |
* as set with setBitmap, setBitmapBuffer, or setSpritesheet. Frame is set in advance using setFrame | |
* @param canvas Canvas to draw on | |
* @param paint Pain to use | |
*/ | |
@SuppressWarnings("unused") | |
public void draw(Canvas canvas, Paint paint) { | |
switch (imagetype) { | |
case BITMAP: draw(canvas,bitmap,paint) ;break; | |
case BITMAPBUFFER: draw(canvas,bitmapBuffer.get(frame),paint);break; | |
case SPRITESHEET: draw(canvas,spriteSheet.getFrame(frame),paint);break; | |
} | |
} | |
@SuppressWarnings("unused") | |
public BitmapBuffer getBitmapBuffer() { | |
return bitmapBuffer; | |
} | |
@SuppressWarnings("unused") | |
public void setBitmapBuffer(BitmapBuffer bitmapBuffer) { | |
this.bitmapBuffer = bitmapBuffer; | |
imagetype =BITMAPBUFFER; | |
} | |
@SuppressWarnings("unused") | |
public Spritesheet getSpriteSheet() { | |
return spriteSheet; | |
} | |
@SuppressWarnings("unused") | |
public void setSpriteSheet(Spritesheet spriteSheet) { | |
this.spriteSheet = spriteSheet; | |
imagetype =SPRITESHEET; | |
} | |
@SuppressWarnings("unused") | |
public Bitmap getBitmap() { | |
return bitmap; | |
} | |
@SuppressWarnings("unused") | |
public void setBitmap(Bitmap bitmap) { | |
this.bitmap = bitmap; | |
imagetype =BITMAP; | |
} | |
@SuppressWarnings("unused") | |
public int getFrame() { | |
return frame; | |
} | |
/** | |
* Sets the current {@link Actor#frame} Do not set frame directly, use this function. If frame | |
* exceeds the actual number of frames available, it is wrapped back to zero. If frames is less | |
* than zero, it is set to the last frame of the animation. If there is no {@link BitmapBuffer} | |
* or {@link Spritesheet} set, then the actual frame is always set to zero. | |
* @param newframe Desired frame. | |
*/ | |
@SuppressWarnings("unused") | |
public void setFrame(int newframe) { | |
frame=newframe; | |
switch (imagetype) { | |
case BITMAPBUFFER: { | |
if (frame>bitmapBuffer.size()-1) { | |
frame=0; | |
} else | |
if (frame<0) { | |
frame = bitmapBuffer.size()-1; | |
} | |
break; | |
} | |
case SPRITESHEET: { | |
if (frame>spriteSheet.size()-1) { | |
frame = 0; | |
} else | |
if (frame<0) { | |
frame = spriteSheet.size()-1; | |
} | |
break; | |
} | |
default: { | |
frame=0; //If there is no BitMapBuffer or Spritesheet, then Frame makes no sense so Zero it | |
} | |
} | |
} | |
@SuppressWarnings("unused") | |
public int getImagetype() { | |
return imagetype; | |
} | |
@SuppressWarnings("unused") | |
public void setImagetype(int imagetype) { | |
this.imagetype = imagetype; | |
} | |
/** | |
* Last position since {@link Actor#MoveActor(long)} was called | |
* @return Last Y coordinate | |
*/ | |
@SuppressWarnings("unused") | |
public float getLastY() { | |
return lastY; | |
} | |
/** | |
* Position before {@link Actor#MoveActor(long)} was called | |
* @return Last X coordinate | |
*/ | |
@SuppressWarnings("unused") | |
public float getLastX() { | |
return lastX; | |
} | |
/** | |
* Returns the number of animation frames available in the object's bitmapBuffer or spritesheet | |
* @return Number of frames. One if a bitmap or zero if no frames available. | |
*/ | |
@SuppressWarnings("unused") | |
public int numframes() { | |
int result=0; | |
switch (imagetype) { | |
case BITMAP: result=1;break; | |
case BITMAPBUFFER: result=bitmapBuffer.size();break; | |
case SPRITESHEET: result=spriteSheet.size();break; | |
} | |
return result; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.tkraindesigns.gameutility; | |
import android.content.Context; | |
import android.graphics.Bitmap; | |
import android.graphics.BitmapFactory; | |
import android.graphics.Canvas; | |
import android.graphics.Matrix; | |
import android.graphics.Paint; | |
import android.graphics.RectF; | |
import java.util.ArrayList; | |
/** | |
* Holds an array of {@link Bitmap} for animations. Used to select specific graphics. Implements | |
* methods to scale and flip bitmaps as they are loaded. | |
*/ | |
public class BitmapBuffer { | |
/** | |
* The actual buffer | |
*/ | |
private ArrayList<Bitmap> buffer = new ArrayList<>(); | |
/** | |
* Holds an array of {@link Bitmap} for animations. Used to select specific graphics. Implements | |
* methods to scale and flip bitmaps as they are loaded. | |
*/ | |
public BitmapBuffer() { | |
super(); | |
buffer.clear(); | |
} | |
/** | |
* Adds a {@link Bitmap} to the existing buffer, read from the system resources. | |
* @param context - Theapplication Context provided to your custom SurfaceView | |
* @param resid - The R.drawable.bitmapname | |
* @return An integer index into the buffer. | |
*/ | |
@SuppressWarnings("unused") | |
public int AddBitMapFromRes(Context context,int resid) { | |
Bitmap tempbitmap; | |
tempbitmap= BitmapFactory.decodeResource(context.getResources(),resid); | |
buffer.add(tempbitmap); | |
return buffer.size()-1; | |
} | |
/** | |
* Adds bitmap to the existing buffer from R.drawable.resourcename. Scales image to x/y | |
* @param context The application context provided to your custom SurfaceView | |
* @param resid the R.drawable.bitmapname | |
* @param x Width to scale image | |
* @param y Height to scale image | |
* @return An integer index into the buffer. | |
*/ | |
@SuppressWarnings("unused") | |
public int AddandScaleBitmapFromRes(Context context, int resid,int x, int y) { | |
Bitmap tempbitmap; | |
tempbitmap= BitmapFactory.decodeResource(context.getResources(),resid); | |
if (x>0) //only rescale if it's valid to do so | |
{ | |
if (y > 0) { | |
tempbitmap = Bitmap.createScaledBitmap(tempbitmap, x, y, true); | |
} | |
} | |
buffer.add(tempbitmap); | |
return buffer.size()-1; | |
} | |
/** | |
* Adds bitmap to the existing buffer from R.drawable.resourcename. Scales image to x/y | |
* and flips the image right to left. Useful for creating direction. | |
* @param context The application context provided to your custom SurfaceView | |
* @param resid the R.drawable.bitmapname | |
* @param x Width to scale image | |
* @param y Height to scale image | |
* @return An integer index into the buffer. | |
*/ | |
@SuppressWarnings("unused") | |
public int AddandScaleFlippedBitmapFromRes(Context context,int resid,int x, int y) { | |
Bitmap tempbitmap; | |
Matrix matrix = new Matrix(); | |
matrix.setScale(-1,1); | |
tempbitmap=BitmapFactory.decodeResource(context.getResources(),resid); | |
if (x>0) { | |
if (y > 0) { | |
tempbitmap = Bitmap.createScaledBitmap(tempbitmap, x, y, true); | |
} | |
} | |
tempbitmap = Bitmap.createBitmap(tempbitmap, 0, 0, tempbitmap.getWidth(), tempbitmap.getHeight(), matrix, true); | |
buffer.add(tempbitmap); | |
return buffer.size()-1; | |
} | |
/** | |
* Returns {@link Bitmap} from the buffer | |
* @param i The specific bitmap you want | |
* @return a bitmap | |
*/ | |
public Bitmap get(int i) { | |
if (i<buffer.size()) { | |
return buffer.get(i); | |
} else { | |
return null; | |
} | |
} | |
/** | |
* @return True if there are no animations | |
*/ | |
@SuppressWarnings("unused") | |
public boolean isEmpty() { | |
return buffer.isEmpty(); | |
} | |
/** | |
* The size of the buffer. Remember that this is the total number of elements, but the array | |
* runs 0-size-1 | |
* @see ArrayList | |
* @return Number of elements in the buffer | |
*/ | |
@SuppressWarnings("unused") | |
public int size() { | |
return buffer.size(); | |
} | |
/** | |
* Adds a {@link Bitmap} to the buffer | |
* @param bitmap Bitmap to be added | |
* @return Index into the buffer | |
*/ | |
@SuppressWarnings("unused") | |
public int AddBitmap(Bitmap bitmap) { | |
buffer.add(bitmap); | |
return buffer.size()-1; | |
} | |
/** | |
* Adds {@link Bitmap} to buffer and scales it | |
* @param bitmap Bitmap to be added | |
* @param x width to scale | |
* @param y height to scale | |
* @return Index into the buffer | |
*/ | |
@SuppressWarnings("unused") | |
public int AddandScaleBitmap(Bitmap bitmap, int x, int y) { | |
Bitmap tempbitmap; | |
tempbitmap=bitmap; | |
if (x>0) { | |
if (y > 0) { | |
tempbitmap = Bitmap.createScaledBitmap(bitmap, x, y, true); | |
} | |
} | |
buffer.add(tempbitmap); | |
return buffer.size()-1; | |
} | |
/** | |
* Adds {@link Bitmap} to buffer and flips direction. | |
* @param bitmap The bitmap to be added | |
* @return Index into the buffer | |
*/ | |
@SuppressWarnings("unused") | |
public int AddFlippedBitmap(Bitmap bitmap) { | |
Bitmap tempbitmap; | |
Matrix matrix; | |
matrix=new Matrix(); | |
matrix.setScale(-1,1); | |
tempbitmap=Bitmap.createBitmap(bitmap, 0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true); | |
buffer.add(tempbitmap); | |
return buffer.size()-1; | |
} | |
/** | |
* Adds {@link Bitmap} to buffer, scales it, and flips direction | |
* @param bitmap Bitmap to add to buffer | |
* @param x Width to scale | |
* @param y Height to scale | |
* @return Index into buffer | |
*/ | |
@SuppressWarnings("unused") | |
public int AddandScaleFlippedBitmap(Bitmap bitmap, int x, int y) { | |
Bitmap tempbitmap; | |
Matrix matrix; | |
matrix=new Matrix(); | |
matrix.setScale(-1,1); | |
tempbitmap = Bitmap.createScaledBitmap(bitmap, x, y, true); | |
tempbitmap=Bitmap.createBitmap(tempbitmap, 0, 0, tempbitmap.getWidth(), tempbitmap.getHeight(), matrix, true); | |
buffer.add(tempbitmap); | |
return buffer.size()-1; | |
} | |
/** | |
* Converts the current buffer into a scaled buffer... Useful to load bitmaps at their native | |
* resolutions, and then scale them to the resolution you'll be using them in. Ideally, pre | |
* scaled bitmaps are faster than bitmaps that need to be scaled in the draw() phase. | |
* Note that this does nothing to this buffer, but instead returns a new copy of the buffer with the | |
* scaling applied. (i.e. this is a non-destructive method | |
* @param x desired width | |
* @param y desired height | |
* @return A scaled copy of the buffer | |
*/ | |
@SuppressWarnings("unused") | |
public BitmapBuffer scaleBuffer(int x, int y) { | |
BitmapBuffer temp = new BitmapBuffer(); | |
for (int i=0;i<buffer.size();i++) { | |
temp.AddandScaleBitmap(buffer.get(i),x,y); | |
} | |
return temp; | |
} | |
/** | |
* Converts the current buffer into a scaled buffer... Useful to load bitmaps at their native | |
* resolutions, and then scale them to the resolution you'll be using them in. Ideally, pre | |
* scaled bitmaps are faster than bitmaps that need to be scaled in the draw() phase. | |
* Note that this does nothing to this buffer, but instead returns a new copy of the buffer with the | |
* scaling applied. (i.e. this is a non-destructive method | |
* @param x desired width | |
* @param y desired height | |
* @return A scaled copy of the buffer | |
*/ | |
@SuppressWarnings("unused") | |
public BitmapBuffer scaleBuffer(float x, float y) { | |
BitmapBuffer temp = new BitmapBuffer(); | |
for (int i=0;i<buffer.size();i++) { | |
temp.AddandScaleBitmap(buffer.get(i),(int)x,(int)y); | |
} | |
return temp; | |
} | |
/** | |
* flips all images in the buffer left to right. Useful to load an image in one direction, | |
* and flip them at run time. | |
* Note that this does not change this buffer, but instead returns a new copy with the modifications | |
* changed. In other words, this is a non-destructive method. | |
* @return a BitmapBuffer with the images flipped left to right | |
*/ | |
@SuppressWarnings("unused") | |
public BitmapBuffer flipLeftBuffer() { | |
Matrix matrix; | |
matrix=new Matrix(); | |
matrix.setScale(-1,1); | |
BitmapBuffer temp = new BitmapBuffer(); | |
for (int i=0;i<buffer.size();i++) { | |
temp.AddFlippedBitmap(buffer.get(i)); | |
} | |
return temp; | |
} | |
/** | |
* Draw frame on the {@link Canvas} at location dest | |
* @param canvas Canvas provided by your Surface | |
* @param frame Index into buffer | |
* @param dest {@link RectF} location | |
* @param paint {@link Paint} object | |
*/ | |
@SuppressWarnings("unused") | |
public void draw(Canvas canvas, int frame, RectF dest,Paint paint) { | |
canvas.drawBitmap(buffer.get(frame),null,dest,paint); | |
} | |
/** | |
* Adds frames from selected {@link Spritesheet} | |
* @param spritesheet Initialized spritesheet | |
* @return number of frames | |
*/ | |
@SuppressWarnings("unused") | |
public int createFromSpriteSheet(Spritesheet spritesheet) { | |
for (int i=0;i<spritesheet.size();i++) { | |
buffer.add(spritesheet.getFrame(i)); | |
} | |
return buffer.size(); | |
} | |
/** | |
* Adds one buffer to another | |
* @param newbuffer Buffer to add | |
* @return The new size of the buffer | |
*/ | |
@SuppressWarnings("unused") | |
public int addBuffer(BitmapBuffer newbuffer) { | |
for (int i=0;i<newbuffer.size();i++) { | |
buffer.add(newbuffer.get(i)); | |
} | |
return buffer.size(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.tkraindesigns.gameutility; | |
import android.graphics.Bitmap; | |
import android.graphics.Canvas; | |
import android.graphics.Paint; | |
import android.graphics.Rect; | |
import android.graphics.RectF; | |
import android.util.Log; | |
/** | |
* Spritesheet - holds a single bitmap which contains a sprite sheet. | |
* Created by Brian on 7/5/2015. | |
*/ | |
public class Spritesheet { | |
/** | |
* The bitmap holding the sprite sheet. | |
*/ | |
private Bitmap bitmap; | |
/** | |
* Number of rows in the spritesheet | |
*/ | |
private int rows; | |
/** | |
* Number of columns in the spritesheet | |
*/ | |
private int columns; | |
/** | |
* Padding between columns in pixels | |
*/ | |
private int xPadding; | |
/** | |
* Padding between rows in pixels | |
*/ | |
private int yPadding; | |
/** | |
* Whitespace at top of sprite sheet, if any | |
*/ | |
private int whiteTop; | |
/** | |
* Whitespace at bottom of spritesheet, if any | |
*/ | |
private int whiteBottom; | |
/** | |
* Whitespace at right of spritesheet if any | |
*/ | |
private int whiteRight; | |
/** | |
* Whitespace at left of spritesheet if any | |
*/ | |
private int whiteLeft; | |
/** | |
* <p>A single bitmap holding a spritesheet arranged in rows and columns.</p> | |
* Use this constructor when there is no padding or whitespace between tiles. | |
* @param bmap The bitmap to use | |
* @param cols Number of columns | |
* @param rws Number of rows | |
*/ | |
@SuppressWarnings("unused") | |
public Spritesheet (Bitmap bmap, int cols, int rws) { | |
super(); | |
bitmap=bmap; | |
Log.e("Spritesheet",String.valueOf(bitmap.getByteCount())); | |
columns=cols; | |
rows=rws; | |
xPadding=0; | |
yPadding=0; | |
whiteTop=0; | |
whiteBottom=0; | |
whiteRight=0; | |
whiteLeft=0; | |
} | |
/** | |
* <p>A single bitmap holding a spritesheet arranged in rows and columns</p> | |
* Use this constructor when there is padding between tiles, but no whitespace around the tiles | |
* @param bmap The bitmap to use | |
* @param cols Number of columns | |
* @param rws Number of rows. | |
* @param xPad Padding in pixels between cells | |
* @param yPad Padding in pixels between cells | |
*/ | |
@SuppressWarnings("unused") | |
public Spritesheet (Bitmap bmap, int cols, int rws, int xPad, int yPad) { | |
super(); | |
bitmap=bmap; | |
columns=cols; | |
rows=rws; | |
xPadding=xPad; | |
yPadding=yPad; | |
whiteTop=0; | |
whiteBottom=0; | |
whiteRight=0; | |
whiteLeft=0; | |
} | |
/** | |
* <p>A single bitmap holding a spritesheet arranged in rows and columns</p> | |
* Use this constructor when there is padding between tiles, and whitespace around the tilesheet. | |
* @param bmap The bitmap to use | |
* @param cols Number of columns | |
* @param rws Number of rows | |
* @param xPad Padding in pixels between cells | |
* @param yPad Padding in pixels between cells | |
* @param wTop Whitespace on top of sheet | |
* @param wBottom Whitespace on bottom of sheet | |
* @param wRight Whitespace on right of sheet | |
* @param wLeft Whitespace on left of sheet | |
*/ | |
@SuppressWarnings("unused") | |
public Spritesheet (Bitmap bmap, int cols, int rws, int xPad, int yPad, | |
int wTop, int wBottom, int wRight, int wLeft) { | |
super(); | |
bitmap=bmap; | |
columns=cols; | |
rows=rws; | |
xPadding=xPad; | |
yPadding=yPad; | |
whiteTop=wTop; | |
whiteBottom=wBottom; | |
whiteRight=wRight; | |
whiteLeft=wLeft; | |
} | |
/** | |
* @return The number of cells in the spritesheet (rows*columns) | |
*/ | |
@SuppressWarnings("unused") | |
public int size() { | |
return rows*columns; | |
} | |
/** | |
* Convenience function. This draws the sprite at the specified RectF on the provided canvas | |
* @param canvas The canvas to draw on | |
* @param frame Which cell to use | |
* @param rect The destination RectF on the canvas | |
* @param paint Paint to use with the function | |
*/ | |
@SuppressWarnings("unused") | |
public void draw(Canvas canvas, int frame, RectF rect, Paint paint) { | |
canvas.drawBitmap(bitmap,fRect(frame),rect,null); | |
} | |
/** | |
* Convenience function. This draws the sprite at the specified Rect on the provided canvas | |
* @param canvas The {@link Canvas} to draw on | |
* @param frame Which cell to use | |
* @param rect The destination {@link RectF} on the canvas | |
* @param paint {@link Paint} to use with the function | |
*/ | |
@SuppressWarnings("unused") | |
public void draw(Canvas canvas, int frame, Rect rect, Paint paint) { | |
canvas.drawBitmap(bitmap, fRect(frame),rect, paint); | |
} | |
/** | |
* Returns an individual frame from the spritesheet | |
* @param frame Selected frame | |
* @return Selected {@link Bitmap} | |
*/ | |
@SuppressWarnings("unused") | |
public Bitmap getFrame(int frame) { | |
return Bitmap.createBitmap(bitmap,cellLeft(frame),cellTop(frame),cellwidth(),cellheight()); | |
} | |
private int whatrow(int frame) { | |
return frame/columns; | |
} | |
private int whatcol(int frame) { | |
return frame%columns; | |
} | |
private int cellwidth() { | |
return (bitmap.getWidth()-whiteRight-whiteLeft- xPadding*columns)/columns; | |
} | |
private int cellheight() { | |
return (bitmap.getHeight()-whiteTop-whiteBottom- yPadding*rows)/rows; | |
} | |
private int cellLeft(int frame) { | |
return whiteLeft+(cellwidth()+xPadding)*whatcol(frame); | |
} | |
private int cellRight(int frame) { | |
return cellLeft(frame)+cellwidth(); | |
} | |
private int cellTop(int frame) { | |
return whiteTop+(cellheight()+yPadding)*whatrow(frame); | |
} | |
private int cellBottom(int frame) { | |
return cellTop(frame)+cellheight(); | |
} | |
private Rect fRect(int frame) { | |
return new Rect(cellLeft(frame),cellTop(frame),cellRight(frame),cellBottom(frame)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment