I'm new in Android Programming I'm Trying to make slideshow animated live wallpaper and all ok but the problem is when I set the wallpaper the scale of image is stretched to screen I want it to scale to all the phone screens and when swipe the wallpaper get the right part of image I Want Advice about this problem.
my code is :
public class CustomWallpaper extends WallpaperService {
#Override
public Engine onCreateEngine() {
return new WallpaperEngine();
}
class WallpaperEngine extends Engine {
//Duration between slides in milliseconds
private final int SLIDE_DURATION = 8;
private int[] mImagesArray;
private int mImagesArrayIndex = 0;
private Thread mDrawWallpaper;
private String mImageScale = "Fit to screen";
private CustomWallpaperHelper customWallpaperHelper;
public WallpaperEngine() {
customWallpaperHelper = new CustomWallpaperHelper(getApplicationContext(), getResources());
mImagesArray = new int[] {R.drawable.image_1,R.drawable.image_2,R.drawable.image_3,R.drawable.image_4,R.drawable.image_5,R.drawable.image_6,R.drawable.image_7,R.drawable.image_8,R.drawable.image_9,R.drawable.image_10,R.drawable.image_11,R.drawable.image_12,R.drawable.image_13,R.drawable.image_14,R.drawable.image_15,R.drawable.image_16,R.drawable.image_17,R.drawable.image_18,R.drawable.image_19,R.drawable.image_20,R.drawable.image_21,R.drawable.image_22,R.drawable.image_23,R.drawable.image_24,R.drawable.image_25,R.drawable.image_26,R.drawable.image_27,R.drawable.image_28,R.drawable.image_29,R.drawable.image_30,R.drawable.image_31,R.drawable.image_32,R.drawable.image_33,R.drawable.image_34,R.drawable.image_35,R.drawable.image_36,R.drawable.image_37,R.drawable.image_38,R.drawable.image_39,R.drawable.image_40,R.drawable.image_41};
mDrawWallpaper = new Thread(new Runnable() {
#Override
public void run() {
try {
while (true) {
drawFrame();
incrementCounter();
Thread.sleep(SLIDE_DURATION);
}
} catch (Exception e) {
//
}
}
});
mDrawWallpaper.start();
}
private void incrementCounter() {
mImagesArrayIndex++;
if (mImagesArrayIndex >= mImagesArray.length) {
mImagesArrayIndex = 0;
}
}
private void drawFrame() {
final SurfaceHolder holder = getSurfaceHolder();
Canvas canvas = null;
try {
canvas = holder.lockCanvas();
if (canvas != null) {
drawImage(canvas);
}
} finally {
if (canvas != null) {
holder.unlockCanvasAndPost(canvas);
}
}
}
private void drawImage(Canvas canvas) {
//Get the image and resize it
Bitmap image = BitmapFactory.decodeResource(getResources(),
mImagesArray[mImagesArrayIndex]);
//Draw background
customWallpaperHelper.setBackground(canvas);
//Scale the canvas
PointF mScale = customWallpaperHelper.getCanvasScale(mImageScale, image.getWidth(), image.getHeight());
canvas.scale(mScale.x, mScale.y);
//Draw the image on screen
Point mPos = customWallpaperHelper.getImagePos(mScale, image.getWidth(), image.getHeight());
canvas.drawBitmap(image, mPos.x, mPos.y, null);
}
}
}
and the other class is:
public class CustomWallpaperHelper {
public final static String IMAGE_SCALE_STRETCH_TO_SCREEN = "Stretch to screen";
public final static String IMAGE_SCALE_FIT_TO_SCREEN = "Fit to screen";
private Context mContext;
private Resources mResources;
private Point screenSize = new Point();
private Bitmap bgImageScaled;
private Point bgImagePos = new Point(0, 0);
public CustomWallpaperHelper(Context mContext, Resources mResources) {
this.mContext = mContext;
this.mResources = mResources;
WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
screenSize.x = display.getWidth();
screenSize.y = display.getHeight();
;
}
private void scaleBackground() {
String imageScale = "Stretch to screen";
Bitmap bgImage = null;
if (imageScale.equals(IMAGE_SCALE_STRETCH_TO_SCREEN)) {
bgImagePos = new Point(0, 0);
bgImageScaled = Bitmap.createScaledBitmap(bgImage, screenSize.x, screenSize.y, true);
}
}
public void setBackground(Canvas canvas) {
if (bgImageScaled != null) {
canvas.drawBitmap(bgImageScaled, bgImagePos.x, bgImagePos.y, null);
} else {
canvas.drawColor(0xff000000);
}
}
public int getScreenWidth() {
return screenSize.x;
}
public int getScreenHeight() {
return screenSize.y;
}
public Point getImagePos(PointF canvasScale, int imageWidth, int imageHeight) {
Point imagePos = new Point();
imagePos.x = (int) (screenSize.x - (imageWidth * canvasScale.x)) / 2;
imagePos.y = (int) (screenSize.y - (imageHeight * canvasScale.y)) / 2;
return imagePos;
}
public PointF getCanvasScale(String imageScale, int imageWidth, int imageHeight) {
PointF canvasScale = new PointF(1f, 1f);
if (imageScale.equals(IMAGE_SCALE_STRETCH_TO_SCREEN)) {
canvasScale.x = getScreenWidth() / (1f * imageWidth);
canvasScale.y = getScreenHeight() / (1f * imageHeight);
} else {
boolean tooWide = false;
boolean tooTall = false;
if (getScreenWidth() < imageWidth) {
tooWide = true;
}
if (getScreenHeight() < imageHeight) {
tooTall = true;
}
if (tooWide && tooTall) {
int x = imageWidth / getScreenWidth();
int y = imageHeight / getScreenHeight();
if (x > y) {
canvasScale.x = getScreenWidth() / (1f * imageWidth);
canvasScale.y = 1;
} else {
canvasScale.x = 1;
canvasScale.y = getScreenHeight() / (1f * imageHeight);
}
} else if (tooWide) {
canvasScale.x = getScreenWidth() / (1f * imageWidth);
canvasScale.y = 1;
} else if (tooTall) {
canvasScale.x = 1;
canvasScale.y = getScreenHeight() / (1f * imageHeight);
}
}
return canvasScale;
}
}
I want Advice for this problem.
Thanks.
no need to do anything just Replace your below method with my code.
private void drawImage(Canvas canvas)
{
Bitmap image = BitmapFactory.decodeResource(getResources(),
mImagesArray[mImagesArrayIndex]);
Bitmap b=Bitmap.createScaledBitmap(image, canvas.getWidth(), canvas.getHeight(), true);
canvas.drawBitmap(b, 0,0, null);
}
I would suggest that you crop the images instead of resizing them. Something like:
Rect r = new Rect(left, top, right, bottom);
Bitmap croppedImage = null;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD_MR1){
InputStream in = mContentResolver.openInputStream(mSaveUri);
BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(in, false);
croppedImage = decoder.decodeRegion(r, null);
} else {
final int width = r.width();
final int height = r.height();
croppedImage = Bitmap.createBitmap(mBitmap, r.left, r.top, width, height);
croppedImage.setDensity(croppedImage.getDensity() * mOutputX / width);
}
return croppedImage;
Hope this helps...
Related
I am creating a moving animation for my Card Game, for this i have created a custom surface view, while calling invalidate method inside my Surface View i am getting following exception
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
My code:
Thread Class
class MySurfaceViewThread:BaseThread
{
private MySurfaceView mysurfaceview;
private ISurfaceHolder myThreadSurfaceHolder;
bool running;
public MySurfaceViewThread(ISurfaceHolder paramSurfaceHolder, MySurfaceView paramSurfaceView)
{
mysurfaceview = paramSurfaceView;
myThreadSurfaceHolder = paramSurfaceHolder;
}
public override void RunThread()
{
Canvas c;
while (running)
{
c = null;
try
{
c = myThreadSurfaceHolder.LockCanvas(null);
mysurfaceview.Render(c);
mysurfaceview.PostInvalidate();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
finally
{
if (c != null)
{
myThreadSurfaceHolder.UnlockCanvasAndPost(c);
}
// running = false;
}
}
}
public override void SetRunning(bool paramBoolean)
{
running = paramBoolean;
}
}
Surface View Class
class MySurfaceView : SurfaceView, ISurfaceHolderCallback
{
ISurfaceHolder holder;
MySurfaceViewThread thread;
Context context;
Deck DealtDeck;
DisplayMetrics metrics;
int Screen_Center_X;
int Screen_Center_Y;
int Screen_Width;
int Screen_Height;
int Screen_Top_Middle_X;
int Screen_Top_Middle_Y;
int Screen_Bottom_Middle_X;
int Screen_Bottom_Middle_Y;
float density;
int Card_Width;
int Card_Height;
int Down_Card_Gap;
Deck DiscardedDeck;
Deck MainPlayer;
int localdownanimationvalue=0;
Bitmap localimage;
Bitmap rotatedimage;
Cards localcard;
public MySurfaceView(Context context):base(context)
{
this.context = context;
metrics = Resources.DisplayMetrics;
SetWillNotDraw(false);
Init();
}
public MySurfaceView(Context context, IAttributeSet attrs):base(context, attrs)
{
this.context=context;
metrics = Resources.DisplayMetrics;
SetWillNotDraw(false);
Init();
}
private void Init()
{
Console.WriteLine("Init method start");
// SurfaceView surfaceview = this;
holder = Holder;
holder.AddCallback(this);
this.thread = new MySurfaceViewThread(holder,this);
Focusable=true;
}
public void SurfaceChanged(ISurfaceHolder holder, [GeneratedEnum] Format format, int width, int height)
{
//throw new NotImplementedException();
}
public void SurfaceCreated(ISurfaceHolder holder)
{
this.thread.SetRunning(true);
this.thread.Start();
Initializevariable();
AllocatedCardList();
SetWillNotDraw(false);
}
private void Initializevariable()
{
Screen_Width = metrics.WidthPixels;
Screen_Height = metrics.HeightPixels;
density = metrics.Density;
Card_Width = (int)(125.0F * density);
Card_Height = (int)(93.0F * density);
Screen_Center_X = Screen_Width / 2;
Screen_Center_Y = Screen_Height / 2;
Screen_Top_Middle_X = Screen_Center_X - Card_Width;
Screen_Top_Middle_Y = Screen_Center_Y - Card_Height;
Screen_Bottom_Middle_X = Screen_Center_X - Card_Width/2;
Screen_Bottom_Middle_Y = Screen_Height - Card_Height;
DealtDeck = new Deck();
MainPlayer = new Deck();
// FaceDownDeck = new Deck(Screen_Center_X - Card_Width/2, Screen_Center_Y- Card_Height/2);
}
public void SurfaceDestroyed(ISurfaceHolder holder)
{
bool retry = true;
this.thread.SetRunning(false);
while(retry)
{
thread.Join();
retry = false;
}
}
void AllocatedCardList()
{
Cards localcard;
//Allocate all cards to dealtdeck first
for (int i = 1; i <= 13; i++)
{
for (int j = 1; j <= 4; j++)
{
DealtDeck.Add(new Cards((Cards.Rank)i, (Cards.SuitType)j, true, (Screen_Center_X - Card_Width / 2), (Screen_Center_Y - Card_Height / 2)));
}
}
//Allocate to bottom player starting card should be bottom-center
localcard = DealtDeck.RemoveCard();
localcard.current_X = Screen_Bottom_Middle_X;
localcard.current_Y = Screen_Bottom_Middle_Y;
MainPlayer.Add(localcard);
}
public void Render(Canvas paramCanvas)
{
try
{
//
localcard = DealtDeck.getCard();
if (localdownanimationvalue <= Screen_Height)
{
paramCanvas.DrawColor(Android.Graphics.Color.Transparent, PorterDuff.Mode.Clear);
localimage = DecodeSampledBitmapFromResource(Resources, localcard.GetImageId(context), Card_Width, Card_Height);
rotatedimage = RotateBitmap(localimage, 180);
paramCanvas.DrawBitmap(rotatedimage, Screen_Center_X, localdownanimationvalue, null);
Updatedowncardvalue();
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
}
protected override void OnDraw(Canvas paramCanvas)
{
}
private void Updatedowncardvalue()
{
const int updatevalue = 50;
if (localdownanimationvalue + updatevalue > Screen_Height)
localdownanimationvalue = Screen_Height;
else
localdownanimationvalue = localdownanimationvalue + updatevalue;
Invalidate();
}
private Bitmap DecodeSampledBitmapFromResource(Resources resources, int cardid, int card_Width, int card_Height)
{
BitmapFactory.Options options = new BitmapFactory.Options
{
InJustDecodeBounds = true
};
Bitmap image = BitmapFactory.DecodeResource(resources, cardid,options);
options.InSampleSize = CalculateInSampleSize(options, card_Width, card_Height);
options.InJustDecodeBounds = false;
return BitmapFactory.DecodeResource(resources, cardid, options);
}
private int CalculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight)
{
// Raw height and width of image
int width = options.OutWidth;
int height = options.OutHeight;
int samplesize = 1;
if(height > reqHeight || width > reqWidth)
{
// Calculate ratios of height and width to requested height and width
int heightratio = (int)Math.Round((double)height / reqHeight);
int widthratio = (int)Math.Round((double)width / reqWidth);
// Choose the smallest ratio as inSampleSize value, this will guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
samplesize = heightratio < widthratio ? widthratio : heightratio;
}
return samplesize;
}
private Bitmap RotateBitmap(Bitmap localimage, float angle)
{
Matrix matrix = new Matrix();
matrix.PostRotate(angle);
Bitmap resized= Bitmap.CreateBitmap(localimage, 0, 0, localimage.Width, localimage.Height, matrix, true);
localimage.Recycle();
return resized;
}
}
Stacktrace:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6462)
at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:932)
at android.view.ViewGroup.invalidateChild(ViewGroup.java:4692)
at android.view.View.invalidateInternal(View.java:11806)
at android.view.View.invalidate(View.java:11770)
at android.view.View.invalidate(View.java:11754)
Only the original thread that created a view hierarchy can touch its views.
You need to use RunOnUiThread from within your thread code whenever you update your views:
RunOnUiThread (() => {
someView.SomeProperty = "SO";
});
re: https://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)
I am trying to set a sprite image as a background
and I didn't success to set the image size to screen size.
I'm trying this:
public class Game extends SurfaceView implements Runnable {
private SurfaceHolder holder;
private boolean isRunning = false;
private Thread gameThread;
private Sprite s;
private int screenWidth;
private int screenHeight;
Canvas canvas;
// private Sprite[] sprites;
private final static int MAX_FPS = 40; //desired fps
private final static int FRAME_PERIOD = 1000 / MAX_FPS; // the frame period
public Game(Context context) {
super(context);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
screenWidth = width;
screenHeight = height;
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
//====== not working
// Display display = ((Activity)context).getWindowManager().getDefaultDisplay();
// int sWidth = display.getWidth();
// int sHeight = display.getHeight();
//====== not working
// DisplayMetrics dm = new DisplayMetrics();
// ((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(dm);
// int sWidth = dm.widthPixels;
// int sHeight = dm.heightPixels;
//====== not working
// screenHeight=canvas.getHeight();
// screenWidth=canvas.getWidth();
s=new Sprite(0, 0, BitmapFactory.decodeResource(this.getResources(), R.mipmap.back));
}
/**
* Start or resume the game.
*/
public void resume() {
isRunning = true;
gameThread = new Thread(this);
gameThread.start();
}
/**
* Pause the game loop
*/
public void pause() {
isRunning = false;
boolean retry = true;
while (retry) {
try {
gameThread.join();
retry = false;
} catch (InterruptedException e) {
// try again shutting down the thread
}
}
}
class Sprite {
int x;
int y;
int directionX = 1;
int directionY = 1;
int speed = 10;
int color = 0;
Bitmap image;
public Sprite(int x, int y) {
this.x = x;
this.y = y;
}
public Sprite(int x, int y, Bitmap image) {
this(x, y);
this.image = image;
}
public Sprite(int x, int y, Bitmap image, int color) {
this(x, y, image);
this.color = color;
}
}
protected void step()
{
//blablabla
}
protected void render(Canvas canvas) {
canvas.drawColor(Color.BLACK);
Paint p = new Paint();
canvas.drawBitmap(s.image,s.x,s.y,p);
}
#Override
public void run() {
while(isRunning) {
// We need to make sure that the surface is ready
if (! holder.getSurface().isValid()) {
continue;
}
long started = System.currentTimeMillis();
// update
step();
// draw
canvas = holder.lockCanvas();
if (canvas != null) {
render(canvas);
holder.unlockCanvasAndPost(canvas);
}
float deltaTime = (System.currentTimeMillis() - started);
int sleepTime = (int) (FRAME_PERIOD - deltaTime);
if (sleepTime > 0) {
try {
gameThread.sleep(sleepTime);
}
catch (InterruptedException e) {
}
}
while (sleepTime < 0) {
step();
sleepTime += FRAME_PERIOD;
}
}
}
}
This options doesn't work:
//====== not working
// Display display = ((Activity)context).getWindowManager().getDefaultDisplay();
// int sWidth = display.getWidth();
// int sHeight = display.getHeight();
//====== not working
// DisplayMetrics dm = new DisplayMetrics();
// ((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(dm);
// int sWidth = dm.widthPixels;
// int sHeight = dm.heightPixels;
//====== not working
// screenHeight=canvas.getHeight();
// screenWidth=canvas.getWidth();
So how I can get the canvas or current screen size?
And set the Sprite.image to full screen ?
Try this for size in pixels,
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
Try this when you decode your bitmap.
final int width = context.getResources().getDisplayMetrics().widthPixels;
final int height = context.getResources().getDisplayMetrics().heightPixels;
BitmapFactory.Options options = new BitmapFactory.Options();
options.outHeight = height;
options.outWidth = width;
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher, options)
please tell me how can i remove the exception. or give me idea to implement zoom view with curlview.....
my xml file is like this,
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/relat">
<com.example.image.ZoomView
>
<com.example.image.PageCurlView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/dcgpagecurlPageCurlView1"
>
</com.example.image.PageCurlView>
my java file is
package com.example.image;
public class StandaloneExample extends Activity {
Button bt;LinearLayout lr;
/** Decoded bitmap image */
private Bitmap mBitmap;
private ZoomView zoomview;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.standalone_example);
View v1 = ((LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.standalone_example, null, false);
v1.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
zoomview.addView(v1);
lr = (LinearLayout) findViewById(R.id.relat);
lr.addView(zoomview);
}
#Override
public void onDestroy(){
super.onDestroy();
System.gc();
finish();
}
public void lockOrientationLandscape() {
lockOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
public void lockOrientationPortrait() {
lockOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
public void lockOrientation( int orientation ) {
setRequestedOrientation(orientation);
}
}
i have implemented zoomView.java as described in a link
pagecurlview.java class is
public class PageCurlView extends View {
private final static String TAG = "PageCurlView";
private Paint mTextPaint;
private TextPaint mTextPaintShadow;
private int mCurlSpeed;
private int mUpdateRate;
private int mInitialEdgeOffset;
private int mCurlMode;
public static final int CURLMODE_SIMPLE = 0;
public static final int CURLMODE_DYNAMIC = 1;
private boolean bEnableDebugMode = false;
private WeakReference<Context> mContext;
private FlipAnimationHandler mAnimationHandler;
private float mFlipRadius;
private Vector2D mMovement;
private Vector2D mFinger;
private Vector2D mOldMovement;
private Paint mCurlEdgePaint;
private Vector2D mA, mB, mC, mD, mE, mF, mOldF, mOrigin;
private int mCurrentLeft, mCurrentTop;
private boolean bViewDrawn;
private boolean bFlipRight;
private boolean bFlipping;
private boolean bUserMoves;
private boolean bBlockTouchInput = false;
private boolean bEnableInputAfterDraw = false;
private Bitmap mForeground;
private Bitmap mBackground;
private ArrayList<Bitmap> mPages;
private int mIndex = 0;
private class Vector2D
{
public float x,y;
public Vector2D(float x, float y)
{
this.x = x;
this.y = y;
}
#Override
public String toString() {
// TODO Auto-generated method stub
return "("+this.x+","+this.y+")";
}
public float length() {
return (float) Math.sqrt(x * x + y * y);
}
public float lengthSquared() {
return (x * x) + (y * y);
}
public boolean equals(Object o) {
if (o instanceof Vector2D) {
Vector2D p = (Vector2D) o;
return p.x == x && p.y == y;
}
return false;
}
public Vector2D reverse() {
return new Vector2D(-x,-y);
}
public Vector2D sum(Vector2D b) {
return new Vector2D(x+b.x,y+b.y);
}
public Vector2D sub(Vector2D b) {
return new Vector2D(x-b.x,y-b.y);
}
public float dot(Vector2D vec) {
return (x * vec.x) + (y * vec.y);
}
public float cross(Vector2D a, Vector2D b) {
return a.cross(b);
}
public float cross(Vector2D vec) {
return x * vec.y - y * vec.x;
}
public float distanceSquared(Vector2D other) {
float dx = other.x - x;
float dy = other.y - y;
return (dx * dx) + (dy * dy);
}
public float distance(Vector2D other) {
return (float) Math.sqrt(distanceSquared(other));
}
public float dotProduct(Vector2D other) {
return other.x * x + other.y * y;
}
public Vector2D normalize() {
float magnitude = (float) Math.sqrt(dotProduct(this));
return new Vector2D(x / magnitude, y / magnitude);
}
public Vector2D mult(float scalar) {
return new Vector2D(x*scalar,y*scalar);
}
}
class FlipAnimationHandler extends Handler {
#Override
public void handleMessage(Message msg) {
PageCurlView.this.FlipAnimationStep();
}
public void sleep(long millis) {
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0), millis);
}
}
public PageCurlView(Context context) {
super(context);
init(context);
ResetClipEdge();
}
public PageCurlView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
// Get the data from the XML AttributeSet
{
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PageCurlView);
// Get data
bEnableDebugMode = a.getBoolean(R.styleable.PageCurlView_enableDebugMode, bEnableDebugMode);
mCurlSpeed = a.getInt(R.styleable.PageCurlView_curlSpeed, mCurlSpeed);
mUpdateRate = a.getInt(R.styleable.PageCurlView_updateRate, mUpdateRate);
mInitialEdgeOffset = a.getInt(R.styleable.PageCurlView_initialEdgeOffset, mInitialEdgeOffset);
mCurlMode = a.getInt(R.styleable.PageCurlView_curlMode, mCurlMode);
Log.i(TAG, "mCurlSpeed: " + mCurlSpeed);
Log.i(TAG, "mUpdateRate: " + mUpdateRate);
Log.i(TAG, "mInitialEdgeOffset: " + mInitialEdgeOffset);
Log.i(TAG, "mCurlMode: " + mCurlMode);
// recycle object (so it can be used by others)
a.recycle();
}
ResetClipEdge();
}
private final void init(Context context) {
// Foreground text paint
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(16);
mTextPaint.setColor(0xFF000000);
// The shadow
mTextPaintShadow = new TextPaint();
mTextPaintShadow.setAntiAlias(true);
mTextPaintShadow.setTextSize(16);
mTextPaintShadow.setColor(0x00000000);
// Cache the context
mContext = new WeakReference<Context>(context);
// Base padding
setPadding(3, 3, 3, 3);
// The focus flags are needed
setFocusable(true);
setFocusableInTouchMode(true);
mMovement = new Vector2D(0,0);
mFinger = new Vector2D(0,0);
mOldMovement = new Vector2D(0,0);
// Create our curl animation handler
mAnimationHandler = new FlipAnimationHandler();
// Create our edge paint
mCurlEdgePaint = new Paint();
mCurlEdgePaint.setColor(Color.WHITE);
mCurlEdgePaint.setAntiAlias(true);
mCurlEdgePaint.setStyle(Paint.Style.FILL);
mCurlEdgePaint.setShadowLayer(10, -5, 5, 0x99000000);
// Set the default props, those come from an XML :D
mCurlSpeed = 30;
mUpdateRate = 33;
mInitialEdgeOffset = 20;
mCurlMode = 1;
// LEGACY PAGE HANDLING!
// Create pages
mPages = new ArrayList<Bitmap>();
mPages.add(BitmapFactory.decodeResource(getResources(), R.drawable.princess));
mPages.add(BitmapFactory.decodeResource(getResources(), R.drawable.temp));
// Create some sample images
mForeground = mPages.get(0);
mBackground = mPages.get(1);
}
public void ResetClipEdge()
{
// Set our base movement
mMovement.x = mInitialEdgeOffset;
mMovement.y = mInitialEdgeOffset;
mOldMovement.x = 0;
mOldMovement.y = 0;
// Now set the points
// TODO: OK, those points MUST come from our measures and
// the actual bounds of the view!
mA = new Vector2D(mInitialEdgeOffset, 0);
mB = new Vector2D(this.getWidth(), this.getHeight());
mC = new Vector2D(this.getWidth(), 0);
mD = new Vector2D(0, 0);
mE = new Vector2D(0, 0);
mF = new Vector2D(0, 0);
mOldF = new Vector2D(0, 0);
// The movement origin point
mOrigin = new Vector2D(this.getWidth(), 0);
}
private Context GetContext() {
return mContext.get();
}
public boolean IsCurlModeDynamic()
{
return mCurlMode == CURLMODE_DYNAMIC;
}
public void SetCurlSpeed(int curlSpeed)
{
if ( curlSpeed < 1 )
throw new IllegalArgumentException("curlSpeed must be greated than 0");
mCurlSpeed = curlSpeed;
}
public int GetCurlSpeed()
{
return mCurlSpeed;
}
public void SetUpdateRate(int updateRate)
{
if ( updateRate < 1 )
throw new IllegalArgumentException("updateRate must be greated than 0");
mUpdateRate = updateRate;
}
public int GetUpdateRate()
{
return mUpdateRate;
}
public void SetInitialEdgeOffset(int initialEdgeOffset)
{
if ( initialEdgeOffset < 0 )
throw new IllegalArgumentException("initialEdgeOffset can not negative");
mInitialEdgeOffset = initialEdgeOffset;
}
public int GetInitialEdgeOffset()
{
return mInitialEdgeOffset;
}
public void SetCurlMode(int curlMode)
{
if ( curlMode != CURLMODE_SIMPLE &&
curlMode != CURLMODE_DYNAMIC )
throw new IllegalArgumentException("Invalid curlMode");
mCurlMode = curlMode;
}
public int GetCurlMode()
{
return mCurlMode;
}
public void SetEnableDebugMode(boolean bFlag)
{
bEnableDebugMode = bFlag;
}
public boolean IsDebugModeEnabled()
{
return bEnableDebugMode;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int finalWidth, finalHeight;
finalWidth = measureWidth(widthMeasureSpec);
finalHeight = measureHeight(heightMeasureSpec);
setMeasuredDimension(finalWidth, finalHeight);
}
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text
result = specSize;
}
return result;
}
private int measureHeight(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
result = specSize;
}
return result;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!bBlockTouchInput) {
// Get our finger position
mFinger.x = event.getX();
mFinger.y = event.getY();
int width = getWidth();
// Depending on the action do what we need to
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mOldMovement.x = mFinger.x;
mOldMovement.y = mFinger.y;
// If we moved over the half of the display flip to next
if (mOldMovement.x > (width >> 1)) {
mMovement.x = mInitialEdgeOffset;
mMovement.y = mInitialEdgeOffset;
// Set the right movement flag
bFlipRight = true;
} else {
// Set the left movement flag
bFlipRight = false;
// go to next previous page
previousView();
// Set new movement
mMovement.x = IsCurlModeDynamic()?width<<1:width;
mMovement.y = mInitialEdgeOffset;
}
break;
case MotionEvent.ACTION_UP:
bUserMoves=false;
bFlipping=true;
FlipAnimationStep();
break;
case MotionEvent.ACTION_MOVE:
bUserMoves=true;
// Get movement
mMovement.x -= mFinger.x - mOldMovement.x;
mMovement.y -= mFinger.y - mOldMovement.y;
mMovement = CapMovement(mMovement, true);
// Make sure the y value get's locked at a nice level
if ( mMovement.y <= 1 )
mMovement.y = 1;
// Get movement direction
if (mFinger.x < mOldMovement.x ) {
bFlipRight = true;
} else {
bFlipRight = false;
}
// Save old movement values
mOldMovement.x = mFinger.x;
mOldMovement.y = mFinger.y;
// Force a new draw call
DoPageCurl();
this.invalidate();
break;
}
}
// TODO: Only consume event if we need to.
return true;
}
private Vector2D CapMovement(Vector2D point, boolean bMaintainMoveDir)
{
// Make sure we never ever move too much
if (point.distance(mOrigin) > mFlipRadius)
{
if ( bMaintainMoveDir )
{
// Maintain the direction
point = mOrigin.sum(point.sub(mOrigin).normalize().mult(mFlipRadius));
}
else
{
// Change direction
if ( point.x > (mOrigin.x+mFlipRadius))
point.x = (mOrigin.x+mFlipRadius);
else if ( point.x < (mOrigin.x-mFlipRadius) )
point.x = (mOrigin.x-mFlipRadius);
point.y = (float) (Math.sin(Math.acos(Math.abs(point.x-mOrigin.x)/mFlipRadius))*mFlipRadius);
}
}
return point;
}
public void FlipAnimationStep() {
if ( !bFlipping )
return;
int width = getWidth();
// No input when flipping
bBlockTouchInput = true;
// Handle speed
float curlSpeed = mCurlSpeed;
if ( !bFlipRight )
curlSpeed *= -1;
// Move us
mMovement.x += curlSpeed;
mMovement = CapMovement(mMovement, false);
// Create values
DoPageCurl();
// Check for endings :D
if (mA.x < 1 || mA.x > width - 1) {
bFlipping = false;
if (bFlipRight) {
//SwapViews();
nextView();
}
ResetClipEdge();
// Create values
DoPageCurl();
// Enable touch input after the next draw event
bEnableInputAfterDraw = true;
}
else
{
mAnimationHandler.sleep(mUpdateRate);
}
// Force a new draw call
this.invalidate();
}
private void DoPageCurl()
{
if(bFlipping){
if ( IsCurlModeDynamic() )
doDynamicCurl();
else
doSimpleCurl();
} else {
if ( IsCurlModeDynamic() )
doDynamicCurl();
else
doSimpleCurl();
}
}
private void doSimpleCurl() {
int width = getWidth();
int height = getHeight();
// Calculate point A
mA.x = width - mMovement.x;
mA.y = height;
// Calculate point D
mD.x = 0;
mD.y = 0;
if (mA.x > width / 2) {
mD.x = width;
mD.y = height - (width - mA.x) * height / mA.x;
} else {
mD.x = 2 * mA.x;
mD.y = 0;
}
double angle = Math.atan((height - mD.y) / (mD.x + mMovement.x - width));
double _cos = Math.cos(2 * angle);
double _sin = Math.sin(2 * angle);
mF.x = (float) (width - mMovement.x + _cos * mMovement.x);
mF.y = (float) (height - _sin * mMovement.x);
// If the x position of A is above half of the page we are still not
// folding the upper-right edge and so E and D are equal.
if (mA.x > width / 2) {
mE.x = mD.x;
mE.y = mD.y;
}
else
{
// So get E
mE.x = (float) (mD.x + _cos * (width - mD.x));
mE.y = (float) -(_sin * (width - mD.x));
}
}
private void doDynamicCurl() {
int width = getWidth();
int height = getHeight();
mF.x = width - mMovement.x+0.1f;
mF.y = height - mMovement.y+0.1f;
if(mA.x==0) {
mF.x= Math.min(mF.x, mOldF.x);
mF.y= Math.max(mF.y, mOldF.y);
}
// Get diffs
float deltaX = width-mF.x;
float deltaY = height-mF.y;
float BH = (float) (Math.sqrt(deltaX * deltaX + deltaY * deltaY) / 2);
double tangAlpha = deltaY / deltaX;
double alpha = Math.atan(deltaY / deltaX);
double _cos = Math.cos(alpha);
double _sin = Math.sin(alpha);
mA.x = (float) (width - (BH / _cos));
mA.y = height;
mD.y = (float) (height - (BH / _sin));
mD.x = width;
mA.x = Math.max(0,mA.x);
if(mA.x==0) {
mOldF.x = mF.x;
mOldF.y = mF.y;
}
// Get W
mE.x = mD.x;
mE.y = mD.y;
// Correct
if (mD.y < 0) {
mD.x = width + (float) (tangAlpha * mD.y);
mE.y = 0;
mE.x = width + (float) (Math.tan(2 * alpha) * mD.y);
}
}
#Deprecated
private void SwapViews() {
Bitmap temp = mForeground;
mForeground = mBackground;
mBackground = temp;
}
private void nextView() {
int foreIndex = mIndex + 1;
if(foreIndex >= mPages.size()) {
foreIndex = 0;
}
int backIndex = foreIndex + 1;
if(backIndex >= mPages.size()) {
backIndex = 0;
}
mIndex = foreIndex;
setViews(foreIndex, backIndex);
}
private void previousView() {
int backIndex = mIndex;
int foreIndex = backIndex - 1;
if(foreIndex < 0) {
foreIndex = mPages.size()-1;
}
mIndex = foreIndex;
setViews(foreIndex, backIndex);
}
private void setViews(int foreground, int background) {
mForeground = mPages.get(foreground);
mBackground = mPages.get(background);
}
#Override
protected void onDraw(Canvas canvas) {
mCurrentLeft = getLeft();
mCurrentTop = getTop();
if ( !bViewDrawn ) {
bViewDrawn = true;
onFirstDrawEvent(canvas);
}
canvas.drawColor(Color.WHITE);
Rect rect = new Rect();
rect.left = 0;
rect.top = 0;
rect.bottom = getHeight();
rect.right = getWidth();
// First Page render
Paint paint = new Paint();
// Draw our elements
drawForeground(canvas, rect, paint);
drawBackground(canvas, rect, paint);
drawCurlEdge(canvas);
// Draw any debug info once we are done
if ( bEnableDebugMode )
drawDebug(canvas);
// Check if we can re-enable input
if ( bEnableInputAfterDraw )
{
bBlockTouchInput = false;
bEnableInputAfterDraw = false;
}
// Restore canvas
//canvas.restore();
}
protected void onFirstDrawEvent(Canvas canvas) {
mFlipRadius = getWidth();
ResetClipEdge();
DoPageCurl();
}
private void drawForeground( Canvas canvas, Rect rect, Paint paint ) {
canvas.drawBitmap(mForeground, null, rect, paint);
// Draw the page number (first page is 1 in real life :D
// there is no page number 0 hehe)
drawPageNum(canvas, mIndex);
}
private Path createBackgroundPath() {
Path path = new Path();
path.moveTo(mA.x, mA.y);
path.lineTo(mB.x, mB.y);
path.lineTo(mC.x, mC.y);
path.lineTo(mD.x, mD.y);
path.lineTo(mA.x, mA.y);
return path;
}
private void drawBackground( Canvas canvas, Rect rect, Paint paint ) {
Path mask = createBackgroundPath();
// Save current canvas so we do not mess it up
canvas.save();
canvas.clipPath(mask);
canvas.drawBitmap(mBackground, null, rect, paint);
// Draw the page number (first page is 1 in real life :D
// there is no page number 0 hehe)
drawPageNum(canvas, mIndex);
canvas.restore();
}
private Path createCurlEdgePath() {
Path path = new Path();
path.moveTo(mA.x, mA.y);
path.lineTo(mD.x, mD.y);
path.lineTo(mE.x, mE.y);
path.lineTo(mF.x, mF.y);
path.lineTo(mA.x, mA.y);
return path;
}
private void drawCurlEdge( Canvas canvas )
{
Path path = createCurlEdgePath();
canvas.drawPath(path, mCurlEdgePaint);
}
private void drawPageNum(Canvas canvas, int pageNum)
{
mTextPaint.setColor(Color.WHITE);
String pageNumText = "- "+pageNum+" -";
drawCentered(canvas, pageNumText,canvas.getHeight()-mTextPaint.getTextSize()-5,mTextPaint,mTextPaintShadow);
}
public static void drawTextShadowed(Canvas canvas, String text, float x, float y, Paint textPain, Paint shadowPaint) {
canvas.drawText(text, x-1, y, shadowPaint);
canvas.drawText(text, x, y+1, shadowPaint);
canvas.drawText(text, x+1, y, shadowPaint);
canvas.drawText(text, x, y-1, shadowPaint);
canvas.drawText(text, x, y, textPain);
}
public static void drawCentered(Canvas canvas, String text, float y, Paint textPain, Paint shadowPaint)
{
float posx = (canvas.getWidth() - textPain.measureText(text))/2;
drawTextShadowed(canvas, text, posx, y, textPain, shadowPaint);
}
private void drawDebug(Canvas canvas)
{
float posX = 10;
float posY = 20;
Paint paint = new Paint();
paint.setStrokeWidth(5);
paint.setStyle(Style.STROKE);
paint.setColor(Color.BLACK);
canvas.drawCircle(mOrigin.x, mOrigin.y, getWidth(), paint);
paint.setStrokeWidth(3);
paint.setColor(Color.RED);
canvas.drawCircle(mOrigin.x, mOrigin.y, getWidth(), paint);
paint.setStrokeWidth(5);
paint.setColor(Color.BLACK);
canvas.drawLine(mOrigin.x, mOrigin.y, mMovement.x, mMovement.y, paint);
paint.setStrokeWidth(3);
paint.setColor(Color.RED);
canvas.drawLine(mOrigin.x, mOrigin.y, mMovement.x, mMovement.y, paint);
posY = debugDrawPoint(canvas,"A",mA,Color.RED,posX,posY);
posY = debugDrawPoint(canvas,"B",mB,Color.GREEN,posX,posY);
posY = debugDrawPoint(canvas,"C",mC,Color.BLUE,posX,posY);
posY = debugDrawPoint(canvas,"D",mD,Color.CYAN,posX,posY);
posY = debugDrawPoint(canvas,"E",mE,Color.YELLOW,posX,posY);
posY = debugDrawPoint(canvas,"F",mF,Color.LTGRAY,posX,posY);
posY = debugDrawPoint(canvas,"Mov",mMovement,Color.DKGRAY,posX,posY);
posY = debugDrawPoint(canvas,"Origin",mOrigin,Color.MAGENTA,posX,posY);
posY = debugDrawPoint(canvas,"Finger",mFinger,Color.GREEN,posX,posY);
}
private float debugDrawPoint(Canvas canvas, String name, Vector2D point, int color, float posX, float posY) {
return debugDrawPoint(canvas,name+" "+point.toString(),point.x, point.y, color, posX, posY);
}
private float debugDrawPoint(Canvas canvas, String name, float X, float Y, int color, float posX, float posY) {
mTextPaint.setColor(color);
drawTextShadowed(canvas,name,posX , posY, mTextPaint,mTextPaintShadow);
Paint paint = new Paint();
paint.setStrokeWidth(5);
paint.setColor(color);
canvas.drawPoint(X, Y, paint);
return posY+15;
}
}
I've just started with Android programming using eclipse and recently came across this problem. I have a bunch of sprites assigned to an arraylist. Now, I want to make it so that collision is detected automatically between sprites but the template I'm currently using can only detect collision between the surface's borders and the moving sprites. Each sprite's position and speed is generated randomly.
How can I change the update() function in my Sprite() class to detect collision between the moving sprites themselves and at the same changing/bouncing to the opposite direction?
Here's my Sprite class template:
package com.gameproject.cai_test;
import java.util.Random;
public Sprite(GameView gameView, Bitmap bmp) {
this.width = bmp.getWidth() / BMP_COLUMNS;
this.height = bmp.getHeight() / BMP_ROWS;
this.gameView = gameView;
this.bmp = bmp;
Random rnd = new Random();
x = rnd.nextInt(gameView.getWidth() - width);
y = rnd.nextInt(gameView.getHeight() - height);
xSpeed = rnd.nextInt(MAX_SPEED * 2) - MAX_SPEED;
ySpeed = rnd.nextInt(MAX_SPEED * 2) - MAX_SPEED;
}
private void update() {
if (x >= gameView.getWidth() - width - xSpeed || x + xSpeed <= 0) {
xSpeed = -xSpeed;
}
x = x + xSpeed;
if (y >= gameView.getHeight() - height - ySpeed || y + ySpeed <= 0) {
ySpeed = -ySpeed;
}
y = y + ySpeed;
currentFrame = ++currentFrame % BMP_COLUMNS;
}
public void onDraw(Canvas canvas) {
update();
int srcX = currentFrame * width;
int srcY = getAnimationRow() * height;
Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
Rect dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
private int getAnimationRow() {
double dirDouble = (Math.atan2(xSpeed, ySpeed) / (Math.PI / 2) + 2);
int direction = (int) Math.round(dirDouble) % BMP_ROWS;
return DIRECTION_TO_ANIMATION_MAP[direction];
}
//gameplay operations
//only values from 0 to 9 will be picked; each assigned its own sprite in the list
public int randomValue(){
Random rnd = new Random();
RandomValue = rnd.nextInt(10);
return RandomValue;
}
//sequence operation from addition, subtraction, multiplication, and division
public int produceSum(){
int addOne = 0;
int addTwo = 0;
Sum = addOne + addTwo;
return Sum;
}
public int produceDiff(){
int deductOne = 0;
int deductTwo = 0;
Difference = deductOne - deductTwo;
return Difference;
}
public int produceProduct(){
int multiOne = 0;
int multiTwo = 0;
Product = multiOne * multiTwo;
return Product;
}
public int produceQuotient(){
int divideOne = 0;
int divideTwo = 0;
Quotient = divideOne / divideTwo;
return Quotient;
}
//each time this returns true, the game is reset with new operation
//compares the value of the bubble picked to the random number being compared through operations
public boolean compareBubbleValue(int randomBubble, int bubbleValue){
if (randomBubble == bubbleValue){
return true;
}
return false;
}
}
As you can see, the update() method only checks the collision between the moving sprites and the borders.
Okey, so lets name your array of sprites spriteArray and loop through it twice
public Rect getBounds(){ //put this in your sprite and enemy-class.
return new Rect(x, y, x+width, y+height);
}
Public void checkCollision(){
for (int i = 0; i<spriteArray.size(); i++){
Rect mySprite = spriteArray.get(i).getBounds(); //create rect for every sprite in array
for (int j = 0; j<spriteArray.size(); i++){
Rect myOtherSprite = spriteArray.get(i).getBounds();
if(mySprite.intersect(myOtherSprite)){ //check if they touch
//Todo code here
}
}
}
}
then you just put this method in your update-method.
Here's the coding for the GameView class (pardon the mess, it's a jumble of codes and comments):
package com.gameproject.cai_test;
public class GameView extends SurfaceView {
private Bitmap bmp;
private Bitmap background;
private Bitmap backgroundImage;
private Bitmap pop;
private SurfaceHolder holder;
private GameLoopThread gameLoopThread;
private List<Sprite> sprites = new ArrayList<Sprite>();
private List<TempSprite> temps = new ArrayList<TempSprite>();
private int[] bubbleValue = {0,1,2,3,4,5,6,7,8,9,10};
private long lastClick;
private SpriteObject timer;
private SpriteObject morebanner;
private SpriteObject formulaBox;
private SpriteObject levelbanner1;
private SurfaceHolder surfaceHolder;
public GameView(Context context) {
super(context);
gameLoopThread = new GameLoopThread(this);
timer = new SpriteObject (BitmapFactory.decodeResource(getResources(), R.drawable.hourglass), 1200, 100);
morebanner = new SpriteObject(BitmapFactory.decodeResource(getResources(), R.drawable.morebanner), 650, 300);
formulaBox = new SpriteObject(BitmapFactory.decodeResource(getResources(), R.drawable.formulabox), 650, 600);
background = BitmapFactory.decodeResource(getResources(), R.drawable.background);
backgroundImage = BitmapFactory.decodeResource(getResources(), R.drawable.background);
pop = BitmapFactory.decodeResource(getResources(), R.drawable.pop);
final Toast toast1 = Toast.makeText(context, "LEVEL 1 start", Toast.LENGTH_LONG);
holder = getHolder();
holder.addCallback(new Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
//setSurfaceSize(getWidth(), getHeight());
toast1.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast1.show();
createSprites();
gameLoopThread.setRunning(true);
gameLoopThread.start();
//banner();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
}
private void createSprites() {
sprites.add(createSprite(R.drawable.bubble1));
sprites.add(createSprite(R.drawable.bubble2));
sprites.add(createSprite(R.drawable.bubble3));
sprites.add(createSprite(R.drawable.bubble4));
sprites.add(createSprite(R.drawable.bubble5));
sprites.add(createSprite(R.drawable.bubble6));
sprites.add(createSprite(R.drawable.bubble7));
sprites.add(createSprite(R.drawable.bubble8));
sprites.add(createSprite(R.drawable.bubble9));
sprites.add(createSprite(R.drawable.bubble10));
for (int i = 0; i <= 10; i++){
bubbleValue[i] = sprites.indexOf(i);
}
}
private Sprite createSprite(int resource) {
Bitmap bmp = BitmapFactory.decodeResource(getResources(), resource);
return new Sprite(this, bmp);
}
public void setSurfaceSize(int width, int height)
{
synchronized (surfaceHolder)
{
int canvasWidth = width;
int canvasHeight = height;
backgroundImage = Bitmap.createScaledBitmap(backgroundImage, width, height, true);
}
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
//levelbanner1.draw(canvas);//causes error when applied;for reference only
for (int i = temps.size() - 1; i >= 0; i--) {
temps.get(i).onDraw(canvas);
}
for (Sprite sprite : sprites) {
timer.draw(canvas);
//formulaBox.draw(canvas);
sprite.onDraw(canvas);
}
if (sprites.size() == 0){
morebanner.draw(canvas);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (System.currentTimeMillis() - lastClick > 300) {
lastClick = System.currentTimeMillis();
float x = event.getX();
float y = event.getY();
synchronized (getHolder()) {
for (int i = sprites.size() - 1; i >= 0; i--) {
Sprite sprite = sprites.get(i);
if (sprite.isCollition(x, y)) {
sprites.remove(sprite);
temps.add(new TempSprite(temps, this, x, y, pop));
break;
}
}
}
}
return true;
}
public void update(){
//for possible check of collision bet. sprites
//
}
}
I've tried assigning a Rect for the sprites here and checking collision on the bottom update() function but result gets awry and produces a runtime error. Probably would be better if its automated in the Sprite class update() function, just as it does for border collision.
If you want to have nice and proper collisions between your sprites, maybe looking at a physics engine like http://www.jbox2d.org/ would help.
It will handle a lot of the complex specific cases for you (tunnelling, time of impact, broadphase for early discard...)
I'm learning android and java and am trying to learn how to make a live wallpaper
I am using the aquarium tutorial, I put it all in one file instead of spreading it but what I am trying to do is get one scale number for everything, I want to get the height of the screen divide that by the background image height (which will always be bigger), this should give me a ratio to use for scaling everything, I tried this in a surfaceView code and it worked perfect, I tried it in livewallpaper and nada.
In the surfaceView test I use onSizeChange and got the height that way and it worked no problems.
This is what I did for the livewallpaper one
This is what I put for the onSurfaceChange
public int screenWidth;
public float rescaler;
public float totalHeight = theTemplate._backgroundImage.getHeight();
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//add rescale and width
screenWidth = width;
rescaler = (float) (height / totalHeight);
super.onSurfaceChanged(holder, format, width, height);
}
The background image comes from an inner class named TheTemplate
This is what I did there
The variables
private SpriteAnimationActivityEngine theTest;
private Bitmap theBackgroundImage;
private float theScaler = theTest.rescaler;
then I try and rescale it using theScaler
public void initialize(Context context, SurfaceHolder surfaceHolder) {
this.spriteThread = new SpriteThread(this);
this._surfaceHolder = surfaceHolder;
this._sprites = new ArrayList<Renderable>();
this._context = context;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
this._backgroundImage = BitmapFactory.decodeResource(context.getResources(),ca.samsstuff.testonepagewallpaper.R.drawable.sky, options);
this.theBackgroundImage = Bitmap.createScaledBitmap(_backgroundImage, (int) (theScaler * _backgroundImage.getWidth()), (int) (theScaler * _backgroundImage.getHeight()), true);
this.addSprites();
}
Then it passes it to draw the background
private void renderBackGround(Canvas canvas) {
canvas.drawBitmap(this.theBackgroundImage, 0, 0, null);
}
Which sends it to draw
protected void onDraw(Canvas canvas) {
this.renderBackGround(canvas);
for (Renderable renderable : this._sprites) {
renderable.render(canvas);
}
}
I keep getting errors and don't know what I am doing wrong. Like I said I am learning both android and java but this method worked in another test I did but I got the screen height from onSizeChange can I get the height by using onSurfaceChange?
Any help would be appreciated
Thanks in advance
sam
EDIT
I also tried to rescale within the theTemplate class just to see if it would work having everything within its own class and still having issues, I used the DisplayMetrics to get the screen height this time.
This might work if I can get it going properly.
Here is this attempt
public class TheTemplate {
private SpriteThread spriteThread;
private SurfaceHolder _surfaceHolder;
private ArrayList<Renderable> _sprites;
public Bitmap _backgroundImage = BitmapFactory.decodeResource(getResources(), R.drawable.sky);;
private Context _context;
// add rescale stuff
private Bitmap theBackgroundImage;
private float theScaler = initFrameParams() / _backgroundImage.getHeight();
private Bitmap oneBackImage = Bitmap.createScaledBitmap(_backgroundImage, (int) (theScaler * _backgroundImage.getWidth()), (int) (theScaler * _backgroundImage.getHeight()), true);
int initFrameParams()
{
//get the screen height to use to rescale everything
DisplayMetrics metrics = new DisplayMetrics();
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
display.getMetrics(metrics);
int screenHeight = display.getHeight();
return screenHeight;
}
public void render(){
Canvas canvas = null;
try{
canvas = this._surfaceHolder.lockCanvas(null);
synchronized (this._surfaceHolder) {
this.onDraw(canvas);
}
}finally{
if(canvas != null){
this._surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
protected void onDraw(Canvas canvas) {
this.renderBackGround(canvas);
for (Renderable renderable : this._sprites) {
renderable.render(canvas);
}
};
public void start(){
this.spriteThread.switchOn();
}
public void stop(){
boolean retry = true;
this.spriteThread.switchOff();
while (retry) {
try {
this.spriteThread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
public int getLeft() {
return 0;
}
public int getRight() {
return this.theBackgroundImage.getWidth();
}
public void initialize(Context context, SurfaceHolder surfaceHolder) {
this.spriteThread = new SpriteThread(this);
this._surfaceHolder = surfaceHolder;
this._sprites = new ArrayList<Renderable>();
this._context = context;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
this.theBackgroundImage = oneBackImage;
this.addSprites();
}
private void addSprites() {
Point startPoint = new Point(100, 100);
this._sprites.add(new SpriteOne(this._context, this, startPoint, 90));
Point startPoint1 = new Point(100, 300);
this._sprites.add(new SpriteOne(this._context, this, startPoint1, 50));
Point startPoint2 = new Point(200, 200);
this._sprites.add(new SpriteOne(this._context, this, startPoint2, 15));
}
private void renderBackGround(Canvas canvas)
{
canvas.drawBitmap(this.theBackgroundImage, 0, 0, null);
}
}
As I stated before any help would be appreciated.
Thanks again in advance
Sam
Edit SOLVED Here is an answer I came up with, The rescale code is where the comments are
Hope this helps someone out.
public class TheTemplate {
private SpriteThread spriteThread;
private SurfaceHolder _surfaceHolder;
private ArrayList<Renderable> _sprites;
public Bitmap _backgroundImage = BitmapFactory.decodeResource(getResources(), R.drawable.sky);;
private Context _context;
// add rescale stuff
//private SpriteAnimationActivityEngine theTest;
private Bitmap theBackgroundImage;
private float totalHeight = _backgroundImage.getHeight();
private int screenSized = initFrameParams();
private float theScaler = (float) (screenSized / totalHeight);
private Bitmap oneBackImage = Bitmap.createScaledBitmap(_backgroundImage, (int) (theScaler * _backgroundImage.getWidth()), (int) (theScaler * _backgroundImage.getHeight()), true);
int initFrameParams()
{
DisplayMetrics metrics = new DisplayMetrics();
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
display.getMetrics(metrics);
int screenHeight = display.getHeight();
return screenHeight;
}
public void render(){
Canvas canvas = null;
try{
canvas = this._surfaceHolder.lockCanvas(null);
synchronized (this._surfaceHolder) {
this.onDraw(canvas);
}
}finally{
if(canvas != null){
this._surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
protected void onDraw(Canvas canvas) {
this.renderBackGround(canvas);
for (Renderable renderable : this._sprites) {
renderable.render(canvas);
}
};
public void start(){
this.spriteThread.switchOn();
}
public void stop(){
boolean retry = true;
this.spriteThread.switchOff();
while (retry) {
try {
this.spriteThread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
public int getLeft() {
return 0;
}
public int getRight() {
return this.theBackgroundImage.getWidth();
}
public void initialize(Context context, SurfaceHolder surfaceHolder) {
this.spriteThread = new SpriteThread(this);
this._surfaceHolder = surfaceHolder;
this._sprites = new ArrayList<Renderable>();
this._context = context;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
this.theBackgroundImage = oneBackImage;
this.addSprites();
}
private void addSprites() {
Point startPoint = new Point(100, 100);
this._sprites.add(new SpriteOne(this._context, this, startPoint, 90));
Point startPoint1 = new Point(100, 300);
this._sprites.add(new SpriteOne(this._context, this, startPoint1, 50));
Point startPoint2 = new Point(200, 200);
this._sprites.add(new SpriteOne(this._context, this, startPoint2, 15));
}
private void renderBackGround(Canvas canvas)
{
canvas.drawBitmap(this.theBackgroundImage, 0, 0, null);
}
}
I added the answer to the original post, hope this helps someone.
Sam
Sorry about that folks, new to this method of using a forum
Here is the answer, I added comments in the code where I made the changes for scaling images.
This method can also be used for positioning also.
Here is the answer.
public class TheTemplate {
private SpriteThread spriteThread;
private SurfaceHolder _surfaceHolder;
private ArrayList<Renderable> _sprites;
public Bitmap _backgroundImage = BitmapFactory.decodeResource(getResources(), R.drawable.sky);;
private Context _context;
// add rescale stuff
//private SpriteAnimationActivityEngine theTest;
private Bitmap theBackgroundImage;
private float totalHeight = _backgroundImage.getHeight();
private int screenSized = initFrameParams();
private float theScaler = (float) (screenSized / totalHeight);
private Bitmap oneBackImage = Bitmap.createScaledBitmap(_backgroundImage, (int) (theScaler * _backgroundImage.getWidth()), (int) (theScaler * _backgroundImage.getHeight()), true);
int initFrameParams()
{
DisplayMetrics metrics = new DisplayMetrics();
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
display.getMetrics(metrics);
int screenHeight = display.getHeight();
return screenHeight;
}
public void render(){
Canvas canvas = null;
try{
canvas = this._surfaceHolder.lockCanvas(null);
synchronized (this._surfaceHolder) {
this.onDraw(canvas);
}
}finally{
if(canvas != null){
this._surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
protected void onDraw(Canvas canvas) {
this.renderBackGround(canvas);
for (Renderable renderable : this._sprites) {
renderable.render(canvas);
}
};
public void start(){
this.spriteThread.switchOn();
}
public void stop(){
boolean retry = true;
this.spriteThread.switchOff();
while (retry) {
try {
this.spriteThread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
public int getLeft() {
return 0;
}
public int getRight() {
return this.theBackgroundImage.getWidth();
}
public void initialize(Context context, SurfaceHolder surfaceHolder) {
this.spriteThread = new SpriteThread(this);
this._surfaceHolder = surfaceHolder;
this._sprites = new ArrayList<Renderable>();
this._context = context;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
this.theBackgroundImage = oneBackImage;
this.addSprites();
}
private void addSprites() {
Point startPoint = new Point(100, 100);
this._sprites.add(new SpriteOne(this._context, this, startPoint, 90));
Point startPoint1 = new Point(100, 300);
this._sprites.add(new SpriteOne(this._context, this, startPoint1, 50));
Point startPoint2 = new Point(200, 200);
this._sprites.add(new SpriteOne(this._context, this, startPoint2, 15));
}
private void renderBackGround(Canvas canvas)
{
canvas.drawBitmap(this.theBackgroundImage, 0, 0, null);
}
}