How to add a score counter in android game? - android

Hi I want to implement an 'image score counter' in my android game but it does not work well. However it compiles well but soon when ball reaches screen edge app returns error:
04-08 10:07:31.639: E/AndroidRuntime(8599): FATAL EXCEPTION: Thread-1176
04-08
10:07:31.639: E/AndroidRuntime(8599): java.lang.NullPointerException
04-08 10:07:31.639: E/AndroidRuntime(8599):at com.Pong.GameState.update(GameState.java:154)
04-08 10:07:31.639: E/AndroidRuntime(8599):at com.Pong.GameThread.run(GameThread.java:41)
I got 3 files that menage the game:
GameState.java GameView.java GameThread.java:
The errors are in:
GameState.java:
TopCounter.setImageResource(myImageList[i+1]);
GameThread.java:
_state.update();
This is how GameThread.java looks like:
package com.Pong;
import....
class GameThread extends Thread {
private SurfaceHolder surfaceHolder;
private GameView gameView;
private Paint _paint;
private GameState _state;
private boolean run = false;
public GameThread(SurfaceHolder surfaceHolder, GameView gameView, Context context, Handler handler) {
this.surfaceHolder = surfaceHolder;
this.gameView = gameView;
_paint = new Paint();
_state = new GameState();
}
public void setRunning(boolean run) {
this.run = run;
}
public SurfaceHolder getSurfaceHolder() {
return surfaceHolder;
}
#Override
public void run() {
Canvas c;
while (run) {
c = null;
try {
c = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder) {
gameView.onDraw(c);
_state.update(); //here is the error
_state.draw(c, _paint);
}
} finally {
if (c != null) {
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
public GameState getGameState()
{
return _state;
}
}
This is how GameState.java looks like (I cut unnecessary lines):
package com.Pong;
Import ...
public class GameState extends Activity implements View.OnTouchListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gamestate);
TopCounter = (ImageView) findViewById(R.id.counterT);
BottomCounter = (ImageView) findViewById(R.id.counterB);
}
int _screenWidth = 270;
int _screenHeight = 395;
int _ballSize = 10;
int _ballX = 100;
int _ballY = 100;
int _ballVelocityX = 3;
int _ballVelocityY = 3;
int _batLength = 75;
int _batHeight = 10;
int _topBatX = (_screenWidth / 2+25) - (_batLength / 2);
int _topBatY = 54;
int _bottomBatX = (_screenWidth / 2+25) - (_batLength / 2);
int _bottomBatY = 392;
int i=0;
// under is matrix that contains images to my counter.
int[] myImageList = new int[]{
R.drawable.counter00,
R.drawable.counter01,
R.drawable.counter02,
R.drawable.counter03,
R.drawable.counter04,
R.drawable.counter05,
R.drawable.counter06,
R.drawable.counter07,
R.drawable.counter08,
R.drawable.counter09
};
ImageView TopCounter;
ImageView BottomCounter;
public GameState()
{}
public void update() {
_ballX += _ballVelocityX;
_ballY += _ballVelocityY;
if( _ballY > _screenHeight){
_ballX = _screenWidth/2;
_ballY = _screenHeight/2;
TopCounter.setImageResource(myImageList[i+1]); //here is the error
_toppoint=_toppoint+1;
_topBatX =_screenWidth/2-10;
_bottomBatX =_screenWidth/2-10;
}
if( _ballY < 50){
_ballX = _screenWidth/2;
_ballY = _screenHeight/2;
BottomCounter.setImageResource(myImageList[i+1]);
_bottompoint=_bottompoint+1;
_topBatX =_screenWidth/2-10;
_bottomBatX =_screenWidth/2-10;
}
if (_toppoint==9){
}
else if (_bottompoint==9) {
}
if(_ballX > _screenWidth || _ballX <= 40){
_ballVelocityX *= -1;
}
if(_ballX > _topBatX && _ballX < _topBatX+_batLength && _ballY < _topBatY){
_ballVelocityY *= -1;
}
if(_ballX > _bottomBatX && _ballX < _bottomBatX+_batLength && _ballY > _bottomBatY){
_ballVelocityY *= -1;
}
if (_ballX == 40+_batLength) {
_topBatX=40;
} else if (_ballX > 40+_batLength && _ballX <= _screenWidth){
_topBatX=_ballX-_batLength+6;
}
if (_bottomBatX < 46) {
_bottomBatX=46;
} else if (_bottomBatX+_batLength > _screenWidth){
_bottomBatX=_screenWidth-_batLength+6;
}
}
public void draw(Canvas c, Paint paint) {
paint.setARGB(255, 234, 222, 199);
c.drawRect(new Rect(_ballX,_ballY,_ballX + _ballSize,_ballY + _ballSize), paint);
c.drawRect(new Rect(_topBatX, _topBatY, _topBatX + _batLength, _topBatY + _batHeight), paint); //top bat
c.drawRect(new Rect(_bottomBatX, _bottomBatY, _bottomBatX + _batLength, _bottomBatY + _batHeight), paint); //bottom bat
}
}
In my XML file:
<ImageView
android:id="#+id/counterT"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/counter00"
android:layout_gravity="left|center_vertical"
/>
<ImageView
android:id="#+id/counterB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/counter00" />
Can anybody help ?

I think this is your problem in GameState.java file
// under is matrix that contains images to my counter.
int[] myImageList = new int[]{
R.drawable.counter00,
R.drawable.counter01,
R.drawable.counter02,
R.drawable.counter03,
R.drawable.counter04,
R.drawable.counter05,
R.drawable.counter06,
R.drawable.counter07,
R.drawable.counter08,
R.drawable.counter09
};
this is not how you declare a Matrix! you want an array of integers
try to declare it as :
int[] myImageList = {
R.drawable.counter00,
R.drawable.counter01,
R.drawable.counter02,
R.drawable.counter03,
R.drawable.counter04,
R.drawable.counter05,
R.drawable.counter06,
R.drawable.counter07,
R.drawable.counter08,
R.drawable.counter09
};
EDIT:
if (TopCounter != null){
TopCounter.setImageResource(myImageList[i]);
i++;
}
also you don't increment you list index, it always equals 0, instead of that
initialize the index to 1 and then when you change the image source increment it by 1
but you'll also need to check that the index doesn't exceed the list size

Related

How to fill the color gradually on drawn view canvas Android

I am having a WaveFormView on which I want to change the color of it while playing Audio file and as the Audio is paused it should be stopped coloring at that certain point and when resumed it should continue forward with coloring. I am not getting how to do it in my code..
This is the screen shot of my generated waveform. Now when I will click on Play button it should change the color of waveform gradually with red color (from start to end slowly).
Here is my code to draw waveform view.
WaveFormView.class
public class WaveformView extends View {
public interface WaveformListener {
public void waveformFling(float x);
public void waveformDraw();
}
;
// Colors
private Paint mGridPaint;
private Paint mSelectedLinePaint;
private Paint mUnselectedLinePaint;
private Paint mUnselectedBkgndLinePaint;
private Paint mBorderLinePaint;
private Paint mPlaybackLinePaint;
private Paint mTimecodePaint;
private SoundFile mSoundFile;
private int[] mLenByZoomLevel;
private double[][] mValuesByZoomLevel;
private double[] mZoomFactorByZoomLevel;
private int[] mHeightsAtThisZoomLevel;
private int mZoomLevel;
private int mNumZoomLevels;
private int mSampleRate;
private int mSamplesPerFrame;
private int mOffset;
private int mSelectionStart;
private int mSelectionEnd;
private int mPlaybackPos;
private float mDensity;
private float mInitialScaleSpan;
private WaveformListener mListener;
private GestureDetector mGestureDetector;
private ScaleGestureDetector mScaleGestureDetector;
private boolean mInitialized;
Color color;
public WaveformView(Context context, AttributeSet attrs) {
super(context, attrs);
// We don't want keys, the markers get these
setFocusable(false);
mGridPaint = new Paint();
mGridPaint.setAntiAlias(false);
mGridPaint.setColor(
getResources().getColor(R.color.grid_line));
mSelectedLinePaint = new Paint();
mSelectedLinePaint.setAntiAlias(false);
mSelectedLinePaint.setColor(
getResources().getColor(R.color.waveform_selected));
mUnselectedLinePaint = new Paint();
mUnselectedLinePaint.setAntiAlias(false);
mUnselectedLinePaint.setColor(
getResources().getColor(R.color.waveform_unselected));
mUnselectedBkgndLinePaint = new Paint();
mUnselectedBkgndLinePaint.setAntiAlias(false);
mUnselectedBkgndLinePaint.setColor(
getResources().getColor(
R.color.selection_border));
mBorderLinePaint = new Paint();
mBorderLinePaint.setAntiAlias(true);
mBorderLinePaint.setStrokeWidth(1.5f);
mBorderLinePaint.setPathEffect(
new DashPathEffect(new float[]{3.0f, 2.0f}, 0.0f));
mBorderLinePaint.setColor(
getResources().getColor(R.color.selection_border));
mPlaybackLinePaint = new Paint();
mPlaybackLinePaint.setAntiAlias(false);
mPlaybackLinePaint.setColor(
getResources().getColor(R.color.playback_indicator));
mTimecodePaint = new Paint();
mTimecodePaint.setTextSize(12);
mTimecodePaint.setAntiAlias(true);
mTimecodePaint.setColor(
getResources().getColor(R.color.timecode));
mTimecodePaint.setShadowLayer(
2, 1, 1,
getResources().getColor(R.color.timecode_shadow));
mGestureDetector = new GestureDetector(
context,
new GestureDetector.SimpleOnGestureListener() {
public boolean onFling(
MotionEvent e1, MotionEvent e2, float vx, float vy) {
mListener.waveformFling(vx);
return true;
}
});
mSoundFile = null;
mLenByZoomLevel = null;
mValuesByZoomLevel = null;
mHeightsAtThisZoomLevel = null;
mOffset = 0;
mPlaybackPos = -1;
mSelectionStart = 0;
mSelectionEnd = 0;
mDensity = 1.0f;
mInitialized = false;
}
public boolean hasSoundFile() {
return mSoundFile != null;
}
public void setSoundFile(SoundFile soundFile) {
mSoundFile = soundFile;
mSampleRate = mSoundFile.getSampleRate();
mSamplesPerFrame = mSoundFile.getSamplesPerFrame();
computeDoublesForAllZoomLevels();
mHeightsAtThisZoomLevel = null;
}
/**
* Called once when a new sound file is added
*/
private void computeDoublesForAllZoomLevels() {
int numFrames = mSoundFile.getNumFrames();
int[] frameGains = mSoundFile.getFrameGains();
double[] smoothedGains = new double[numFrames];
if (numFrames == 1) {
smoothedGains[0] = frameGains[0];
} else if (numFrames == 2) {
smoothedGains[0] = frameGains[0];
smoothedGains[1] = frameGains[1];
} else if (numFrames > 2) {
smoothedGains[0] = (double)(
(frameGains[0] / 2.0) +
(frameGains[1] / 2.0));
for (int i = 1; i < numFrames - 1; i++) {
smoothedGains[i] = (double)(
(frameGains[i - 1] / 3.0) +
(frameGains[i ] / 3.0) +
(frameGains[i + 1] / 3.0));
}
smoothedGains[numFrames - 1] = (double)(
(frameGains[numFrames - 2] / 2.0) +
(frameGains[numFrames - 1] / 2.0));
}
// Make sure the range is no more than 0 - 255
double maxGain = 1.0;
for (int i = 0; i < numFrames; i++) {
if (smoothedGains[i] > maxGain) {
maxGain = smoothedGains[i];
}
}
double scaleFactor = 1.0;
if (maxGain > 255.0) {
scaleFactor = 255 / maxGain;
}
// Build histogram of 256 bins and figure out the new scaled max
maxGain = 0;
int gainHist[] = new int[256];
for (int i = 0; i < numFrames; i++) {
int smoothedGain = (int)(smoothedGains[i] * scaleFactor);
if (smoothedGain < 0)
smoothedGain = 0;
if (smoothedGain > 255)
smoothedGain = 255;
if (smoothedGain > maxGain)
maxGain = smoothedGain;
gainHist[smoothedGain]++;
}
// Re-calibrate the min to be 5%
double minGain = 0;
int sum = 0;
while (minGain < 255 && sum < numFrames / 20) {
sum += gainHist[(int)minGain];
minGain++;
}
// Re-calibrate the max to be 99%
sum = 0;
while (maxGain > 2 && sum < numFrames / 100) {
sum += gainHist[(int)maxGain];
maxGain--;
}
// Compute the heights
double[] heights = new double[numFrames];
double range = maxGain - minGain;
for (int i = 0; i < numFrames; i++) {
double value = (smoothedGains[i] * scaleFactor - minGain) / range;
if (value < 0.0)
value = 0.0;
if (value > 1.0)
value = 1.0;
heights[i] = value * value;
}
mNumZoomLevels = 5;
mLenByZoomLevel = new int[5];
mZoomFactorByZoomLevel = new double[5];
mValuesByZoomLevel = new double[5][];
// Level 0 is doubled, with interpolated values
mLenByZoomLevel[0] = numFrames * 2;
mZoomFactorByZoomLevel[0] = 2.0;
mValuesByZoomLevel[0] = new double[mLenByZoomLevel[0]];
if (numFrames > 0) {
mValuesByZoomLevel[0][0] = 0.5 * heights[0];
mValuesByZoomLevel[0][1] = heights[0];
}
for (int i = 1; i < numFrames; i++) {
mValuesByZoomLevel[0][2 * i] = 0.5 * (heights[i - 1] + heights[i]);
mValuesByZoomLevel[0][2 * i + 1] = heights[i];
}
// Level 1 is normal
mLenByZoomLevel[1] = numFrames;
mValuesByZoomLevel[1] = new double[mLenByZoomLevel[1]];
mZoomFactorByZoomLevel[1] = 1.0;
for (int i = 0; i < mLenByZoomLevel[1]; i++) {
mValuesByZoomLevel[1][i] = heights[i];
}
// 3 more levels are each halved
for (int j = 2; j < 5; j++) {
mLenByZoomLevel[j] = mLenByZoomLevel[j - 1] / 2;
mValuesByZoomLevel[j] = new double[mLenByZoomLevel[j]];
mZoomFactorByZoomLevel[j] = mZoomFactorByZoomLevel[j - 1] / 2.0;
for (int i = 0; i < mLenByZoomLevel[j]; i++) {
mValuesByZoomLevel[j][i] =
0.5 * (mValuesByZoomLevel[j - 1][2 * i] +
mValuesByZoomLevel[j - 1][2 * i + 1]);
}
}
if (numFrames > 5000) {
mZoomLevel = 3;
} else if (numFrames > 1000) {
mZoomLevel = 2;
} else if (numFrames > 300) {
mZoomLevel = 1;
} else {
mZoomLevel = 0;
}
mInitialized = true;
}
public boolean canZoomIn() {
return (mZoomLevel > 0);
}
public void zoomIn() {
if (canZoomIn()) {
mZoomLevel--;
mSelectionStart *= 2;
mSelectionEnd *= 2;
mHeightsAtThisZoomLevel = null;
int offsetCenter = mOffset + getMeasuredWidth() / 2;
offsetCenter *= 2;
mOffset = offsetCenter - getMeasuredWidth() / 2;
if (mOffset < 0)
mOffset = 0;
invalidate();
}
}
public boolean canZoomOut() {
return (mZoomLevel < mNumZoomLevels - 1);
}
public void zoomOut() {
if (canZoomOut()) {
mZoomLevel++;
mSelectionStart /= 2;
mSelectionEnd /= 2;
int offsetCenter = mOffset + getMeasuredWidth() / 2;
offsetCenter /= 2;
mOffset = offsetCenter - getMeasuredWidth() / 2;
if (mOffset < 0)
mOffset = 0;
mHeightsAtThisZoomLevel = null;
invalidate();
}
}
public double pixelsToSeconds(int pixels) {
double z = mZoomFactorByZoomLevel[mZoomLevel];
return (pixels * (double)mSamplesPerFrame / (mSampleRate * z));
}
public void setListener(WaveformListener listener) {
mListener = listener;
}
public void recomputeHeights(float density) {
mHeightsAtThisZoomLevel = null;
mDensity = density;
mTimecodePaint.setTextSize((int)(12 * density));
invalidate();
}
protected void drawWaveformLine(Canvas canvas,
int x, int y0, int y1,
Paint paint) {
canvas.drawLine(x, y0, x, y1, paint);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mSoundFile == null)
return;
if (mHeightsAtThisZoomLevel == null)
computeIntsForThisZoomLevel();
DisplayMetrics displaymetrics = getContext().getResources().getDisplayMetrics();
int height = displaymetrics.heightPixels;
int widths = displaymetrics.widthPixels;
// Draw waveform
int measuredWidth = getMeasuredWidth();
int measuredHeight = getMeasuredHeight();
int start = mOffset;
int width = mHeightsAtThisZoomLevel.length - start;
int ctr = measuredHeight / 2;
Log.e("wid",String.valueOf(width));
Log.e("widCal",String.valueOf(mHeightsAtThisZoomLevel.length));
Log.e("widstart",String.valueOf(start));
if (width > measuredWidth)
width = measuredWidth;
Log.e("measured",String.valueOf(measuredWidth));
// Draw grid
double onePixelInSecs = pixelsToSeconds(1);
boolean onlyEveryFiveSecs = (onePixelInSecs > 1.0 / 50.0);
double fractionalSecs = mOffset * onePixelInSecs;
int integerSecs = (int) fractionalSecs;
int i = 0;
while (i < width) {
i++;
fractionalSecs += onePixelInSecs;
int integerSecsNew = (int) fractionalSecs;
if (integerSecsNew != integerSecs) {
integerSecs = integerSecsNew;
if (!onlyEveryFiveSecs || 0 == (integerSecs % 5)) {
canvas.drawLine(i, 0, i, measuredHeight, mGridPaint);
}
}
}
// Draw waveform
for ( i = 0; i < width; i++) {
Paint paint;
if (i + start >= mSelectionStart &&
i + start < mSelectionEnd) {
paint = mSelectedLinePaint;
// paint.setColor(color);
} else {
drawWaveformLine(canvas, ((widths/width)*i), 0, measuredHeight,
mUnselectedBkgndLinePaint);
paint = mUnselectedLinePaint;
}
drawWaveformLine(
canvas, ((widths/width)*i),
ctr - mHeightsAtThisZoomLevel[start + i],
ctr + 1 + mHeightsAtThisZoomLevel[start + i],
paint);
if (i + start == mPlaybackPos) {
canvas.drawLine(i, 0, i, measuredHeight, mPlaybackLinePaint);
}
}
if (mListener != null) {
mListener.waveformDraw();
}
}
private void computeIntsForThisZoomLevel() {
int halfHeight = (getMeasuredHeight() / 2) - 1;
mHeightsAtThisZoomLevel = new int[mLenByZoomLevel[mZoomLevel]];
for (int i = 0; i < mLenByZoomLevel[mZoomLevel]; i++) {
mHeightsAtThisZoomLevel[i] =
(int)(mValuesByZoomLevel[mZoomLevel][i] * halfHeight);
}
}
}
MainActivity.class
public class MainActivity extends AppCompatActivity implements WaveformView.WaveformListener {
WaveformView mWaveformView;
SoundFile mSoundFile;
private float mDensity;
private File mFile;
private String mFilename;
private long mLoadingLastUpdateTime;
boolean mLoadingKeepGoing;
boolean mFinishActivity;
private ProgressDialog mProgressDialog;
String mTitle,mArtist;
private Thread mLoadSoundFileThread;
private Thread mRecordAudioThread;
private Thread mSaveSoundFileThread;
private boolean mIsPlaying;
private SamplePlayer mPlayer;
private String mInfoContent;
private int mWidth;
private int mMaxPos;
private int mStartPos;
private int mEndPos;
private boolean mStartVisible;
private boolean mEndVisible;
private int mLastDisplayedStartPos;
private int mLastDisplayedEndPos;
private int mOffset;
private int mOffsetGoal;
private int mFlingVelocity;
private int mPlayStartMsec;
private int mPlayEndMsec;
private Handler mHandler;
Button pla;
MediaPlayer mediaPlayer;
boolean ismIsPlaying;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pla = (Button)findViewById(R.id.play);
mWaveformView = (WaveformView)findViewById(R.id.waveform);
mWaveformView.setListener(this);
mHandler = new Handler();
Uri uri = Uri.parse("/sdcard/audio_file.mp3");
mediaPlayer = new MediaPlayer();
mediaPlayer = MediaPlayer.create(getApplicationContext(),uri);
loadGui();
loadFromFile();
}
/**
* Called from both onCreate and onConfigurationChanged
* (if the user switched layouts)
*/
private void loadGui() {
// Inflate our UI from its XML layout description.
setContentView(R.layout.activity_main);
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
mDensity = metrics.density;
mWaveformView = (WaveformView)findViewById(R.id.waveform);
mWaveformView.setListener(this);
if (mSoundFile != null && !mWaveformView.hasSoundFile()) {
mWaveformView.setSoundFile(mSoundFile);
mWaveformView.recomputeHeights(mDensity);
}
}
private void loadFromFile() {
mFilename = "/sdcard/audio_file.mp3";
mFile = new File(mFilename);
SongMetadataReader metadataReader = new SongMetadataReader(
this, mFilename);
mTitle = metadataReader.mTitle;
mArtist = metadataReader.mArtist;
String titleLabel = mTitle;
if (mArtist != null && mArtist.length() > 0) {
titleLabel += " - " + mArtist;
}
setTitle(titleLabel);
mLoadingLastUpdateTime = getCurrentTime();
mLoadingKeepGoing = true;
mFinishActivity = false;
mProgressDialog = new ProgressDialog(MainActivity.this);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setTitle("Loading...");
mProgressDialog.setCancelable(true);
mProgressDialog.setOnCancelListener(
new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
mLoadingKeepGoing = false;
mFinishActivity = true;
}
});
mProgressDialog.show();
final SoundFile.ProgressListener listener =
new SoundFile.ProgressListener() {
public boolean reportProgress(double fractionComplete) {
long now = getCurrentTime();
if (now - mLoadingLastUpdateTime > 100) {
mProgressDialog.setProgress(
(int) (mProgressDialog.getMax() * fractionComplete));
mLoadingLastUpdateTime = now;
}
return mLoadingKeepGoing;
}
};
// Load the sound file in a background thread
mLoadSoundFileThread = new Thread() {
public void run() {
try {
mSoundFile = SoundFile.create(mFile.getAbsolutePath(), listener);
if (mSoundFile == null) {
mProgressDialog.dismiss();
String name = mFile.getName().toLowerCase();
String[] components = name.split("\\.");
String err;
if (components.length < 2) {
err = getResources().getString(
R.string.no_extension_error);
} else {
err = getResources().getString(
R.string.bad_extension_error) + " " +
components[components.length - 1];
}
final String finalErr = err;
Runnable runnable = new Runnable() {
public void run() {
showFinalAlert(new Exception(), finalErr);
}
};
mHandler.post(runnable);
return;
}
mPlayer = new SamplePlayer(mSoundFile);
} catch (final Exception e) {
mProgressDialog.dismiss();
e.printStackTrace();
mInfoContent = e.toString();
runOnUiThread(new Runnable() {
public void run() {
}
});
Runnable runnable = new Runnable() {
public void run() {
showFinalAlert(e, getResources().getText(R.string.read_error));
}
};
mHandler.post(runnable);
return;
}
mProgressDialog.dismiss();
if (mLoadingKeepGoing) {
Runnable runnable = new Runnable() {
public void run() {
finishOpeningSoundFile();
}
};
mHandler.post(runnable);
} else if (mFinishActivity){
MainActivity.this.finish();
}
}
};
mLoadSoundFileThread.start();
}
private void finishOpeningSoundFile() {
mWaveformView.setSoundFile(mSoundFile);
mWaveformView.recomputeHeights(mDensity);
Log.e("sound file",mFilename);
Log.e("sound", String.valueOf(mSoundFile));
}
/**
* Show a "final" alert dialog that will exit the activity
* after the user clicks on the OK button. If an exception
* is passed, it's assumed to be an error condition, and the
* dialog is presented as an error, and the stack trace is
* logged. If there's no exception, it's a success message.
*/
private void showFinalAlert(Exception e, CharSequence message) {
CharSequence title;
if (e != null) {
Log.e("Ringdroid", "Error: " + message);
Log.e("Ringdroid", getStackTrace(e));
title = getResources().getText(R.string.alert_title_failure);
setResult(RESULT_CANCELED, new Intent());
} else {
Log.v("Ringdroid", "Success: " + message);
title = getResources().getText(R.string.alert_title_success);
}
new AlertDialog.Builder(MainActivity.this)
.setTitle(title)
.setMessage(message)
.setPositiveButton(
R.string.alert_ok_button,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
finish();
}
})
.setCancelable(false)
.show();
}
private void showFinalAlert(Exception e, int messageResourceId) {
showFinalAlert(e, getResources().getText(messageResourceId));
}
#Override
public void waveformTouchStart(float x) {
}
#Override
public void waveformTouchMove(float x) {
}
#Override
public void waveformTouchEnd() {
}
#Override
public void waveformFling(float x) {
}
#Override
public void waveformDraw() {
mWidth = mWaveformView.getMeasuredWidth();
if (mOffsetGoal != mOffset) {
// updateDisplay();
}
else if (mIsPlaying) {
// updateDisplay();
} else if (mFlingVelocity != 0) {
// updateDisplay();
}
}
private long getCurrentTime() {
return System.nanoTime() / 1000000;
}
private String getStackTrace(Exception e) {
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
return writer.toString();
}
public void buttonClick(View view) {
Toast.makeText(MainActivity.this, "test", Toast.LENGTH_SHORT).show();
mediaPlayer.start();
ismIsPlaying = true;
}
}
In your onDraw(Canvas canvas) add the following lines
if (i + start <= mPlaybackPos) {
Paint mPaint = new Paint(paint);
mPaint.setColor(Color.RED);
drawWaveformLine(
canvas, ((widths/width)*i),
ctr - mHeightsAtThisZoomLevel[start + i],
ctr + 1 + mHeightsAtThisZoomLevel[start + i],
mPaint);
}
add them above the line:
if (i + start == mPlaybackPos) {
And if this works, consider to allocate the Paint-object outside the onDraw() method.

Can't redraw my canvas bitmap with invalidate();

I need help with my game!
I am drawing my playermodel with a bitmap and I want to change the model with an ontouch event, but it is not working and I don't know, what I'm doing wrong: (
First of all here is my playerclass were I'm creating the bitmap:
public class Player extends GameObject{
private Bitmap spritesheet;
private String scoreText;
public int score;
private double dya;
private boolean up;
private boolean playing;
private Animation animation = new Animation();
private long startTime;
public boolean jumpable = false;
public boolean jumphigh;
public boolean falldown;
private int boden;
private boolean sliden;
public Player(Bitmap res, int w, int h, int numFrames) {
x = 100;
y = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 +26 ;
//y = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 - 100;
dy = 0;
score = 0;
height = h;
width = w;
boden = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 -100;
Bitmap[] image = new Bitmap[numFrames];
spritesheet = res;
for (int i = 0; i < image.length; i++)
{
image[i] = Bitmap.createBitmap(spritesheet, i*width, 0, width, height);
}
animation.setFrames(image);
animation.setDelay(40);
startTime = System.nanoTime();
}
public void setUp(boolean b){up = b;}
public void update()
{
//score
long elapsed = (System.nanoTime()-startTime)/1000000;
if(elapsed>100)
{
score = score+7;
startTime = System.nanoTime();
scoreText = ""+score ;
}
animation.update();
if(up == true && jumpable == true){
jumphigh = true;
// dy = -5;
// System.out.println(up);
}else{
jumphigh = false;
}
if (jumphigh == true){
dy = -5;
}
if (falldown == true){
dy = 5;
}
if(dy>14)dy = 14;
if(dy<-14)dy = -14;
y += dy*2;
if (y >= boden){
y = boden;
jumpable = true;
falldown = false;
dy = 0;
}else if (y <= 60){
y= 60;
up = false ;
jumphigh = false;
falldown = true;
dy = 0;
}
if (y < GamePanel.HEIGHT - GamePanel.HEIGHT / 4 -100){
jumpable = false;
}
}
public void restart(){
x = 100;
y = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 - 100;
dy = 0;
score = 0;
}
public void draw(Canvas canvas)
{
canvas.drawBitmap(animation.getImage(),x,y,null);
Paint paint = new Paint();
paint.setTypeface(Typeface.create(Typeface.SANS_SERIF,Typeface.NORMAL));
paint.setColor(Color.BLACK);
paint.setTextSize(50);
canvas.drawText(scoreText, 50 , 50 , paint);
}
public void setY(Canvas canvas){
y = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 -20 ;
boden = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 -20 ;
draw(canvas);
}
public int getScore(){return score;}
public void setSliden() {sliden = true; }
public boolean getPlaying(){return playing;}
public void setPlaying(boolean b){playing = b;}
public void resetP(){ x = 100;
y = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 - 100;
dy = 0;}
public void resetDYA(){dya = 0;}
public void resetScore(){score = 0;}
And here is my gamepanel code where I'm calling my bitmap ( I give you only the parts you need for this question):
private Player player;
private int PlayerSprite = R.drawable.test;;
private int Playerhight = 120;
private int Playerwight = 115;
private int PlayerFrames = 8;
#Override
public void surfaceCreated(SurfaceHolder holder) {
player = new Player(BitmapFactory.decodeResource(getResources(), PlayerSprite), Playerwight, Playerhight, PlayerFrames);
invalidate();
thread.setRunning(true);
thread.start();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN){
PlayerSprite = R.drawable.sliden;
Playerhight = 52;
Playerwight = 130;
PlayerFrames = 1;
return true;
}
if(event.getAction()==MotionEvent.ACTION_UP)
{
player.setUp(false);
PlayerSprite = R.drawable.test;
Playerhight = 120;
Playerwight = 115;
PlayerFrames = 8;
return true;
}
return super.onTouchEvent(event);
}
public void update() {
if (player.getPlaying() == true && State == STATE.INGAME) {
player.update();
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
final float scaleFactorX = getWidth() / (WIDTH*1.f);
final float scaleFactorY = getHeight() / (HEIGHT*1.f);
if (canvas != null && State == STATE.INGAME) {
final int savedState = canvas.save();
canvas.scale(scaleFactorX, scaleFactorY);
player.draw(canvas);
canvas.restoreToCount(savedState);
invalidate();
}
}
I want just want to change the image of the player with a onTouch event and its just not working.
Just call invalidate() in onTouchEvent(MotionEvent event)() and see the change.
Do not call invalidate in onDraw(), it will cause the permanent loop and reduce the performance of your app.

Out of memory ! Bitmap Vm memory exceds budget error when using lot of Bitmaps for my game

package com.anu;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.SurfaceHolder.Callback;
public class GameView extends SurfaceView {
public static int a,y;
private Bitmap bm ,hud;
private SurfaceHolder holder;
private GameLoopThread gameLoopThread;
private long lastClick;
private Bitmap bmpBlood ;
private static boolean ab=true;
Timex n = new Timex();
private List<Sprite> sprites = new ArrayList<Sprite>();
private List<Sprite> sprites2 = new ArrayList<Sprite>();
private List<Sprite> sprites3 = new ArrayList<Sprite>();
private List<Sprite> sprites4 = new ArrayList<Sprite>();
private List<Sprite> sprites5 = new ArrayList<Sprite>();
private List<Sprite> sprites6 = new ArrayList<Sprite>();
private List<TempSprite> temps = new ArrayList<TempSprite>();
public GameView(Context context) {
super(context);
gameLoopThread = new GameLoopThread(this);
holder = getHolder();
holder.addCallback(new Callback()
{
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
int t2 =Timex.a;
createSprites();
cs2();
cs3();
cs4();
/* if(t2>10){
cs2();}
if(t2>20){
cs3();}
if(t2>30){
cs4();}
if(t2>40){
cs5();
}*/
gameLoopThread.setRunning(true);
gameLoopThread.start();
n.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
bmpBlood = BitmapFactory.decodeResource(getResources(), R.drawable.blood2);
bm = BitmapFactory.decodeResource(getResources(), R.drawable.sky4);
Bitmap o = Bitmap.createScaledBitmap( bm, 800, 490, false);
bm=o;
}
private void createSprites() {
sprites.add(createSprite(R.drawable.act0));
sprites.add(createSprite(R.drawable.act0));
sprites.add(createSprite(R.drawable.act0));
sprites.add(createSprite(R.drawable.act0));
sprites.add(createSprite(R.drawable.act0));
}
private Sprite createSprite(int resouce) {
Bitmap bmp = BitmapFactory.decodeResource(getResources(), resouce);
return new Sprite(this, bmp);
}
private void cs2() {
sprites2.add(createSprite(R.drawable.act));
sprites2.add(createSprite(R.drawable.act));
sprites2.add(createSprite(R.drawable.act));
sprites2.add(createSprite(R.drawable.act));
sprites2.add(createSprite(R.drawable.act ));
}
private void cs3() {
sprites3.add(createSprite(R.drawable.act1));
sprites3.add(createSprite(R.drawable.act1));
sprites3.add(createSprite(R.drawable.act1));
sprites3.add(createSprite(R.drawable.act1));
sprites3.add(createSprite(R.drawable.act1));
}
private void cs4() {
sprites4.add(createSprite(R.drawable.act2));
sprites4.add(createSprite(R.drawable.act2));
sprites4.add(createSprite(R.drawable.act2));
sprites4.add(createSprite(R.drawable.act2));
sprites4.add(createSprite(R.drawable.act2));
}
private void cs5() {
sprites5.add(createSprite(R.drawable.act3));
sprites5.add(createSprite(R.drawable.act3));
sprites5.add(createSprite(R.drawable.act3));
sprites5.add(createSprite(R.drawable.act3));
sprites5.add(createSprite(R.drawable.act3));
}
private void cs6() {
sprites6.add(createSprite(R.drawable.act4));
sprites6.add(createSprite(R.drawable.act4));
sprites6.add(createSprite(R.drawable.act4));
sprites6.add(createSprite(R.drawable.act4));
sprites6.add(createSprite(R.drawable.act4));
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.rgb(21, 181, 195));
canvas.drawBitmap(bm, 0, 0, null);
for (int i = temps.size() - 1; i >= 0; i--) {
temps.get(i).onDraw(canvas);
}
int tt = Timex.a;
if(tt>0){
for (Sprite wave2 : sprites) {
wave2.onDraw(canvas);
}
if(tt>10){
for (Sprite wave2 : sprites2) {
wave2.onDraw(canvas);
}
if(tt>20){
for (Sprite wave2 : sprites3) {
wave2.onDraw(canvas);
}
}
if(tt>30){
for (Sprite wave2 : sprites4) {
wave2.onDraw(canvas);
}
if(tt>40){
for (Sprite wave2 : sprites5) {
wave2.onDraw(canvas);
}
}
}
}
canvas.drawBitmap(hud, 0, 0, null);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int kt=Timex.a;
if (System.currentTimeMillis() - lastClick > 500) {
lastClick = System.currentTimeMillis();
synchronized (getHolder()) {
float x = event.getX();
float y =event.getY();
if(kt>0){
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, bmpBlood));
break;
}
}}
if(kt>10){
for (int i = sprites2.size() - 1; i >= 0; i--) {
Sprite sprite = sprites2.get(i);
if (sprite.isCollition(x, y)) {
sprites2.remove(sprite);
temps.add(new TempSprite(temps, this, x, y, bmpBlood));
break;
}}
}
if(kt>20){
for (int i = sprites3.size() - 1; i >= 0; i--) {
Sprite sprite = sprites3.get(i);
if (sprite.isCollition(x, y)) {
sprites3.remove(sprite);
temps.add(new TempSprite(temps, this, x, y, bmpBlood));
break;
}
}}
if(kt>30)
for (int i = sprites4.size() - 1; i >= 0; i--) {
Sprite sprite = sprites4.get(i);
if (sprite.isCollition(x, y)) {
sprites4.remove(sprite);
temps.add(new TempSprite(temps, this, x, y, bmpBlood));
break;
}
}
if(kt>40)
for (int i = sprites5.size() - 1; i >= 0; i--) {
Sprite sprite = sprites5.get(i);
if (sprite.isCollition(x, y)) {
sprites5.remove(sprite);
temps.add(new TempSprite(temps, this, x, y, bmpBlood));
break;
}
}
if(kt>50)
for (int i = sprites6.size() - 1; i >= 0; i--) {
Sprite sprite = sprites6.get(i);
if (sprite.isCollition(x, y)) {
sprites6.remove(sprite);
temps.add(new TempSprite(temps, this, x, y, bmpBlood));
break;
}
}
}
}
return true;
}
}
This is my game code . where i get multiple sprite in list and use them to display in canvas with On draw method they game runs fine till cs4(); in my code runs ..when i call cs5(); i get error saying bitmap vm budget out of memory . i thought when i destroy sprites while playing game i could reduce the budget but i keep getting the same error . i want to usecs2();,cs3(),cs4(),cs5() again and again in my game without exceeding the vm budget . how to get this running by clearing the previous bitmap cleared in memory and create new image from the method and use them again .. i thought scaling would help but my bitmaps are very small so if i scale them they become very small to see so i want to use the same image with same size and display again and again in canvas
Thank you all !
UPDATE
my sprite class
package com.anu;
import java.util.Random;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
public class Sprite {
// direction = 0 up, 1 left, 2 down, 3 right,
// animation = 3 back, 1 left, 0 front, 2 right
int[] DIRECTION_TO_ANIMATION_MAP = { 3, 1, 0, 2 };
private static final int BMP_ROWS = 4;
private static final int BMP_COLUMNS = 3;
// private static final int MAX_SPEED = 9;
private GameView gameView;
private Bitmap bmp;
private int x = 0;
private int y = 0;
private int xSpeed =15;
private int ySpeed=15;
private int currentFrame = 0;
private int width;
private int height;
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];
}
public boolean isCollition(float x2, float y2) {
return x2 > x && x2 < x + width && y2 > y && y2 < y + height;
}
}
The following code is just wrong becuase you create in each of your cs2, cs3 etc 5 times the same bitmap/sprite. This is just wrong and the reason why you have the OOM. There is no reason why you should add the same bitmap 5 times to a list...
private Sprite createSprite(int resouce) {
Bitmap bmp = BitmapFactory.decodeResource(getResources(), resouce);
return new Sprite(this, bmp);
}
private void cs2() {
sprites2.add(createSprite(R.drawable.act));
sprites2.add(createSprite(R.drawable.act));
sprites2.add(createSprite(R.drawable.act));
sprites2.add(createSprite(R.drawable.act));
sprites2.add(createSprite(R.drawable.act ));
}
private void cs3() {
sprites3.add(createSprite(R.drawable.act1));
sprites3.add(createSprite(R.drawable.act1));
sprites3.add(createSprite(R.drawable.act1));
sprites3.add(createSprite(R.drawable.act1));
sprites3.add(createSprite(R.drawable.act1));
}
private void cs4() {
sprites4.add(createSprite(R.drawable.act2));
sprites4.add(createSprite(R.drawable.act2));
sprites4.add(createSprite(R.drawable.act2));
sprites4.add(createSprite(R.drawable.act2));
sprites4.add(createSprite(R.drawable.act2));
}
private void cs5() {
sprites5.add(createSprite(R.drawable.act3));
sprites5.add(createSprite(R.drawable.act3));
sprites5.add(createSprite(R.drawable.act3));
sprites5.add(createSprite(R.drawable.act3));
sprites5.add(createSprite(R.drawable.act3));
}
private void cs6() {
sprites6.add(createSprite(R.drawable.act4));
sprites6.add(createSprite(R.drawable.act4));
sprites6.add(createSprite(R.drawable.act4));
sprites6.add(createSprite(R.drawable.act4));
sprites6.add(createSprite(R.drawable.act4));
}
Update
i want to create 5 enemies each time i call the function later on i send enemies in different combos
So you should reuse one(!!) drawable for each of your enemies. That means: Create an enemy class which will use the same drawable. That would reduce the uses images to 1 per enemy type.

Android Move Image if Button Pressed

I want to move the player image when the upbutton is pressed. I tried the onClick() method, but it doesn't work.
The player should move up for some pixels when the upbutton is pressed.
I tried something like getButtonState which I have seen on the Android Developer Page,
but I did not understand how this works...
Any suggestions?
private Context mContext;
int enemy_x = -1;
int enemy_y = -1;
int player_x = -1;
int player_y = -1;
private int enemy_xVelocity = 15;
private int enemy_yVelocity = 0;
private int player_xVelocity = 0;
private int player_yVelocity = 10;
private Handler h;
private final int FRAME_RATE = 60;
Button upbutton = (Button) findViewById(R.id.upbutton);
public AnimatedView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
h = new Handler();
}
private Runnable r = new Runnable() {
#Override
public void run() {
invalidate();
}
};
protected void onDraw(Canvas c) {
BitmapDrawable enemy = (BitmapDrawable) mContext.getResources()
.getDrawable(R.drawable.enemy);
BitmapDrawable player = (BitmapDrawable) mContext.getResources()
.getDrawable(R.drawable.player);
// enemy movement
if (enemy_x < 0 && enemy_y < 0) {
enemy_x = this.getWidth() / 2;
enemy_y = this.getHeight() / 2;
} else {
enemy_x += enemy_xVelocity;
enemy_y += enemy_yVelocity;
if ((enemy_x > this.getWidth() - enemy.getBitmap().getWidth())
|| (enemy_x < 0)) {
enemy_xVelocity = enemy_xVelocity * -1;
}
if ((enemy_y > this.getHeight() - enemy.getBitmap().getHeight())
|| (enemy_y < 0)) {
enemy_yVelocity = enemy_yVelocity * -1;
}
}
// player movement
if (player_x < 0 && player_y < 0) {
player_x = (this.getWidth() / 2) - 20;
player_y = this.getHeight() - 150;
} else {
player_x += player_xVelocity;
player_y += player_yVelocity;
if ((player_x > this.getWidth() - player.getBitmap().getWidth())
|| (player_x < 0)) {
player_xVelocity = player_xVelocity * -1;
}
if ((player_y > this.getHeight() - player.getBitmap().getHeight())
|| (player_y < 0)) {
player_yVelocity = 0;
}
}
c.drawBitmap(enemy.getBitmap(), enemy_x, enemy_y, null);
c.drawBitmap(player.getBitmap(), player_x, player_y, null);
h.postDelayed(r, FRAME_RATE);
}

How to set-up automatic collision with just an update() function?

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...)

Categories

Resources