Skip to content

Instantly share code, notes, and snippets.

@Mnemoth42
Created July 11, 2015 00:39
Show Gist options
  • Save Mnemoth42/c79b7f7caca2efecffe9 to your computer and use it in GitHub Desktop.
Save Mnemoth42/c79b7f7caca2efecffe9 to your computer and use it in GitHub Desktop.
Various Game utility functions, designedto work together as a framework.
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;
}
}
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();
}
}
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