I programmed an Android game via this Youtube tutorial, there you can see how the game should look like at the end.
Everything went fine until I added the Gameover Screen. When I start the emulator, the Game runs accordingly, but when I have used up all my lives and the View should change to the Gameover Screen, it only appears for 1 second and then crashes (the game exits).
This is what the LogCat says:
04-05 06:14:22.178: E/AndroidRuntime(1201): FATAL EXCEPTION: Thread-87
04-05 06:14:22.178: E/AndroidRuntime(1201): Process: com.skies.game, PID: 1201
04-05 06:14:22.178: E/AndroidRuntime(1201): java.lang.NullPointerException
04-05 06:14:22.178: E/AndroidRuntime(1201): at com.skies.game.GameView.draw(GameView.java:79)
04-05 06:14:22.178: E/AndroidRuntime(1201): at com.skies.game.GameLoopThread.run(GameLoopThread.java:30)
Here is my GameOverActivity class
package com.skies.game;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class GameOverActivity extends Activity implements OnClickListener {
private Button bReplay;
private Button bExit;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gameoverscreen);
bReplay = (Button) findViewById(R.id.bReplay);
bExit = (Button) findViewById(R.id.bExit);
bReplay.setOnClickListener(this);
bExit.setOnClickListener(this);
initialize();
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.bReplay:
Intent newGameScreen = new Intent(this, GameActivity.class);
startActivity(newGameScreen);
this.finish();
break;
case R.id.bExit:
this.finish();
break;
}
}
public int readHighscore() {
SharedPreferences pref = getSharedPreferences("GAME", 0);
return pref.getInt("HIGHSCORE", 0);
}
public void initialize() {
int score = this.getIntent().getExtras().getInt("score");
TextView tvScore = (TextView) findViewById(R.id.tvScore);
tvScore.setText("Your score is: " + Integer.toString(score));
TextView tvHighscore = (TextView) findViewById(R.id.tvHighScore);
tvHighscore.setText("Endless Game Highscore: "
+ Integer.toString(readHighscore()));
}
}
Here is my GameActivity class
package com.skies.game;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.view.Menu;
public class GameActivity extends Activity {
private GameView theGameView;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
theGameView = new GameView(this);
setContentView(theGameView);
}
public void onGameOver()
{
compareScore();
Intent theNextIntent = new Intent (getApplicationContext(), GameOverActivity.class);
theNextIntent.putExtra("score", theGameView.getScore());
startActivity(theNextIntent);
this.finish();
}
public int readHighscore()
{
SharedPreferences pref = getSharedPreferences("GAME", 0);
return pref.getInt("HIGHSCORE", 0);
}
public void writeHighscore(int highscore)
{
SharedPreferences pref = getSharedPreferences("GAME", 0);
SharedPreferences.Editor editor = pref.edit();
editor.putInt("HIGHSCORE", highscore);
editor.commit();
}
public void compareScore()
{
if(theGameView.getScore() > readHighscore())
{
writeHighscore(theGameView.getScore());
}
}
}
and here my GameView class
package com.skies.game;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GameView extends SurfaceView {
private List<Sprite> spriteList = new ArrayList<Sprite>();
private List<Integer> spriteListNum = new ArrayList<Integer>();
private SurfaceHolder surfaceHolder;
private Bitmap bmp;
private Bitmap livesPicture;
private GameLoopThread theGameLoopThread;
private boolean createSprites = true;
private long lastClick;
private int currentColorNum;
private int lives = 4;
private int score = 0;
private Paint paintRed, paintBlue, paintGreen, paintYellow;
private Paint currentColor;
private String scoreString;
private String livesString;
private float density;
private GameActivity theGameActivity= new GameActivity();
public GameView(Context context) {
super(context);
livesPicture = BitmapFactory.decodeResource(getResources(),
R.drawable.lives);
Random rnd = new Random();
theGameActivity = (GameActivity) context;
setColors();
currentColorNum = rnd.nextInt(4);
theGameLoopThread = new GameLoopThread(this);
surfaceHolder = getHolder();
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
theGameLoopThread.setRunning(false);
while (retry) {
try {
theGameLoopThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
theGameLoopThread.setRunning(true);
theGameLoopThread.start();
}
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
}
#Override
public void draw(Canvas canvas) {
canvas.drawColor(Color.DKGRAY);
if (createSprites == true) {
initialSprites();
}
for (Sprite sprite : spriteList) {
sprite.draw(canvas);
}
if (currentColorNum == 0) {
drawLines(paintBlue, canvas);
} else if (currentColorNum == 1) {
drawLines(paintRed, canvas);
} else if (currentColorNum == 2) {
drawLines(paintGreen, canvas);
} else if (currentColorNum == 3) {
drawLines(paintYellow, canvas);
}
final int fontSize = (int) (25 * density);
int yTextPos = (int) (25 * density);
Typeface font = Typeface.create("Arial", Typeface.NORMAL);
Paint paint = new Paint();
paint.setColor(Color.WHITE);
paint.setTypeface(font);
paint.setTextSize(fontSize);
paint.setAntiAlias(true);
scoreString = String.valueOf(score);
int x = (canvas.getWidth() * 5 / 7);
final String text = "Score: " + scoreString;
canvas.drawText(text, x, yTextPos, paint);
drawLives(canvas, paint);
}
private void createSprite(int index) {
Bitmap bmp = null;
switch (index) {
case 0:
bmp = BitmapFactory.decodeResource(getResources(),
R.drawable.alienspriteblue);
break;
case 1:
bmp = BitmapFactory.decodeResource(getResources(),
R.drawable.alienspritered);
break;
case 2:
bmp = BitmapFactory.decodeResource(getResources(),
R.drawable.alienspritegreen);
break;
case 3:
bmp = BitmapFactory.decodeResource(getResources(),
R.drawable.alienspriteyellow);
break;
}
Sprite sprite = new Sprite(this, bmp);
spriteList.add(sprite);
spriteListNum.add(index);
}
private void initialSprites() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 3; j++)
createSprite(i);
}
createSprites = false;
}
private void rndCreateSprite() {
Random rnd = new Random(System.currentTimeMillis());
int i = rnd.nextInt(4);
createSprite(i);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (System.currentTimeMillis() - lastClick > 300) {
lastClick = System.currentTimeMillis();
synchronized (getHolder()) {
for (int i = spriteList.size() - 1; i >= 0; i--) {
Sprite sprite = spriteList.get(i);
if (sprite.isTouched(event.getX(), event.getY())) {
if (currentColorNum == spriteListNum.get(i)) {
score++;
}else{
lives--;
if(lives==0){
theGameActivity.onGameOver();
}
}
if(score==3)
lives++;
rndCreateSprite();
removeSprite(i);
changeColor();
break;
}
}
}
}
return true;
}
private void removeSprite(int index) {
spriteList.remove(index);
spriteListNum.remove(index);
}
public void setColors() {
Paint paintRed = new Paint();
paintRed.setARGB(255, 236, 27, 36);
this.paintRed = paintRed;
Paint paintBlue = new Paint();
paintBlue.setARGB(255, 36, 72, 204);
this.paintBlue = paintBlue;
Paint paintGreen = new Paint();
paintGreen.setARGB(255, 34, 177, 76);
this.paintGreen = paintGreen;
Paint paintYellow = new Paint();
paintYellow.setARGB(255, 255, 242, 0);
this.paintYellow = paintYellow;
}
public void drawLines(Paint lineColor, Canvas canvas) {
int lineWidth = (int) (10*density);
int screenHeight = getHeight();
int screenWidth = getWidth();
canvas.drawRect(0, 0, lineWidth, getHeight(), lineColor);
canvas.drawRect(0, getHeight() - lineWidth, screenWidth, screenHeight,
lineColor);
canvas.drawRect(screenWidth - lineWidth, 0, screenWidth, screenHeight,
lineColor);
currentColor = lineColor;
}
public void changeColor() {
Random rnd = new Random();
int index = rnd.nextInt(spriteListNum.size());
this.currentColorNum = spriteListNum.get(index);
switch (index) {
case 0:
currentColor = paintBlue;
break;
case 1:
currentColor = paintRed;
break;
case 2:
currentColor = paintGreen;
break;
case 3:
currentColor = paintYellow;
break;
}
}
public float getDensity() {
density = getResources().getDisplayMetrics().density;
return density;
}
private void drawLives(Canvas canvas, Paint paint){
int xHeart= (int) (15*density);
int yHeart= (int) (12*density);
if (lives == 3) {
canvas.drawBitmap(livesPicture, xHeart,
yHeart, paint);
canvas.drawBitmap(livesPicture,
xHeart + livesPicture.getWidth() + 3*density,
yHeart, paint);
canvas.drawBitmap(livesPicture, xHeart + 2
* livesPicture.getWidth() + 6*density, yHeart, paint);
}
if (lives == 2) {
canvas.drawBitmap(livesPicture, xHeart,
yHeart, paint);
canvas.drawBitmap(livesPicture,
xHeart + livesPicture.getWidth() + 3,
yHeart, paint);
}
if (lives == 1) {
canvas.drawBitmap(livesPicture, xHeart,
yHeart, paint);
}
if (lives > 3) {
livesString = String.valueOf(lives);
final String lives = livesString + "x";
canvas.drawText(lives, 35 * getDensity(), 30 * getDensity(), paint);
canvas.drawBitmap(livesPicture, 15 * getDensity() + 2
* livesPicture.getWidth() + 6, 12 * getDensity(), paint);
}
}
public int getScore() {
return this.score;
}
}
I am a beginner so I really would appreciate some help.
Edit:
Don't create new variables inside the onDraw statement.
So the variables like yTextPos (int) or fontSize(int) from the draw-method should be created above with all the other global variables? Isn't this make it more confusing? Or what are the benefits?
Also, what is line 79 in GameView.java?
Do you mean
canvas.drawColor(Color.DKGRAY);
? This gives the background of the game the color DKGRAY. I don't have a specific image for the background yet.
I believe you should set your game running loop to false when you are in the game over state. You might need to join or something as well.
theGameLoopThread.setRunning(true);
theGameActivity.onGameOver();
Related
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 2 years ago.
When I run my android app, it crashes and says that Android app has stopped. It also gives this error message:
java.lang.NullPointerException: Attempt to invoke virtual method 'com.esimerkki.doodl2.DoodleView com.esimerkki.doodl2.FirstFragment.getDoodleView()' on a null object reference
What is wrong with this? Is the reference really null? How could I make this work? I thought these original settings in doodleView have start values?
Here is the code of doodleView class:
package com.esimerkki.doodl2;
import android.content.Context;
import android.view.View;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.provider.MediaStore;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.widget.Toast;
import androidx.print.PrintHelper;
import java.util.HashMap;
import java.util.Map;
public class DoodleView extends View {
public DoodleView(Context context, Paint paintScreen, Paint paintLine) {
super( context );
this.paintScreen = paintScreen;
this.paintLine = paintLine;
}
private static final float TOUCH_TOLERANCE = 10;
private Bitmap bitmap; // drawing area
private Canvas bitmapCanvas; //
private final Paint paintScreen; //
private final Paint paintLine; //
private final Map<Integer, Path> pathMap = new HashMap<>();
private final Map<Integer, Point> previousPointMap = new HashMap<>();
public DoodleView(Context context, AttributeSet attrs) {
super(context, attrs); // kutsutaan yliluokanalustajaa
paintScreen = new Paint(); // bittikartan näyttämiseen ruudulla
paintLine = new Paint();
paintLine.setAntiAlias(true);
paintLine.setColor(Color.BLACK);
paintLine.setStyle(Paint.Style.STROKE);
paintLine.setStrokeWidth(5);
paintLine.setStrokeCap(Paint.Cap.ROUND);
#Override
public void onSizeChanged(int w, int h, int OldW, int oldH) {
bitmap = Bitmap.createBitmap(getWidth(), getHeight(),
Bitmap.Config.ARGB_8888);
bitmapCanvas = new Canvas(bitmap);
bitmap.eraseColor(Color.WHITE);
}
public void clear() {
pathMap.clear();
previousPointMap.clear();
bitmap.eraseColor(Color.WHITE);
invalidate();
}
public void setDrawingColor(int color) {
paintLine.setColor(color);
}
public int getDrawingColor() {
return paintLine.getColor();
}
public void setLineWidth(int width) {
paintLine.setStrokeWidth(width);
}
public int getLineWidth() {
return (int) paintLine.getStrokeWidth();
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, 0, 0, paintScreen);
for (Integer key : pathMap.keySet())
canvas.drawPath(pathMap.get(key), paintLine); // piirretään viiva
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getActionMasked(); // tapahtumatyyppi
int actionIndex = event.getActionIndex(); // osoitin
if (action == MotionEvent.ACTION_DOWN ||
action == MotionEvent.ACTION_POINTER_DOWN) {
touchStarted(event.getX(actionIndex), event.getY(actionIndex),
event.getPointerId(actionIndex));
}
else if (action == MotionEvent.ACTION_UP ||
action == MotionEvent.ACTION_POINTER_UP) {
touchEnded(event.getPointerId(actionIndex));
}
else {
touchMoved(event);
}
invalidate();
return true;
}
private void touchStarted(float x, float y, int lineID) {
Path path; // tallennetaan tietyn id:n polku
Point point; // tallennetaan polun viimeinen piste
if (pathMap.containsKey(lineID)) {
path = pathMap.get(lineID);
path.reset();
point = previousPointMap.get(lineID);
}
else {
path = new Path();
pathMap.put(lineID, path);
point = new Point();
previousPointMap.put(lineID, point);
}
path.moveTo(x, y);
point.x = (int) x;
point.y = (int) y;
}
private void touchMoved(MotionEvent event) {
for (int i = 0; i < event.getPointerCount(); i++) {
// luetaan pointtein id ja indeksi
int pointerID = event.getPointerId(i);
int pointerIndex = event.findPointerIndex(pointerID);
if (pathMap.containsKey(pointerID)) {
float newX = event.getX(pointerIndex);
float newY = event.getY(pointerIndex);
Path path = pathMap.get(pointerID);
Point point = previousPointMap.get(pointerID);
// lasketaan kuinka kauas liikuttu
float deltaX = Math.abs(newX - point.x);
float deltaY = Math.abs(newY - point.y);
if (deltaX >= TOUCH_TOLERANCE || deltaY >= TOUCH_TOLERANCE) {
path.quadTo(point.x, point.y, (newX + point.x) / 2,
(newY + point.y) / 2);
point.x = (int) newX;
point.y = (int) newY;
}
}
}
}
private void touchEnded(int lineID) {
Path path = pathMap.get(lineID);
bitmapCanvas.drawPath(path, paintLine);
path.reset(); // tyhjennetään polku
}
public void saveImage() {
final String name = "Doodlz" + System.currentTimeMillis() + ".jpg";
String location = MediaStore.Images.Media.insertImage(
getContext().getContentResolver(), bitmap, name,
"Doodlz Drawing"
);
if (location != null) {
Toast message = Toast.makeText(getContext(),
R.string.message_saved,
Toast.LENGTH_SHORT);
message.setGravity(Gravity.CENTER, message.getXOffset() / 2,
message.getYOffset() / 2);
message.show();
}
else {
Toast message = Toast.makeText(getContext(),
R.string.message_error_saving, Toast.LENGTH_SHORT);
message.setGravity(Gravity.CENTER, message.getXOffset() / 2,
message.getYOffset() / 2);
message.show();
}
}
public void printImage() {
if (PrintHelper.systemSupportsPrint()) {
PrintHelper printHelper = new PrintHelper(getContext());
printHelper.setScaleMode(printHelper.SCALE_MODE_FIT);
printHelper.printBitmap("Doodlz Imate", bitmap);
}
else {
Toast message = Toast.makeText(getContext(),
R.string.message_error_printing, Toast.LENGTH_SHORT);
message.setGravity(Gravity.CENTER, message.getXOffset() / 2,
message.getYOffset() / 2);
message.show();
}
}
}
And here is the code of a LineWidthFragment class:
package com.esimerkki.doodl2;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
//import android.support.v4.app.DialogFragment;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import androidx.fragment.app.DialogFragment;
public class LineWidthFragment extends DialogFragment {
private ImageView widthImageView;
#Override
public Dialog onCreateDialog(Bundle bundle) {
AlertDialog.Builder builder =
new AlertDialog.Builder(getActivity());
View lineWidthDialogView =
getActivity().getLayoutInflater().inflate(
R.layout.fragment_line_width, null);
builder.setView(lineWidthDialogView); // lisätään GUI dialogiin
builder.setTitle(R.string.title_line_width_dialog);
widthImageView = (ImageView) lineWidthDialogView.findViewById(
R.id.widthImageView);
final DoodleView doodleView = getDoodleFragment().getDoodleView();
final SeekBar widthSeekBar = (SeekBar)
lineWidthDialogView.findViewById(R.id.widthSeekBar);
widthSeekBar.setOnSeekBarChangeListener(lineWidthChanged);
widthSeekBar.setProgress(doodleView.getLineWidth());
builder.setPositiveButton(R.string.button_set_line_width,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
doodleView.setLineWidth(widthSeekBar.getProgress());
}
}
);
return builder.create();
}
private FirstFragment getDoodleFragment() {
return (FirstFragment) getChildFragmentManager().findFragmentById(
R.id.doodleFragment);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
FirstFragment fragment = getDoodleFragment();
if (fragment != null)
fragment.setDialogOnScreen(true);
}
#Override
public void onDetach() {
super.onDetach();
FirstFragment fragment = getDoodleFragment();
if (fragment != null)
fragment.setDialogOnScreen(false);
}
private final OnSeekBarChangeListener lineWidthChanged =
new OnSeekBarChangeListener() {
final Bitmap bitmap = Bitmap.createBitmap(
400, 100, Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bitmap); // piirtää bittikarttaan
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
Paint p = new Paint();
p.setColor(
getDoodleFragment().getDoodleView().getDrawingColor());
p.setStrokeCap(Paint.Cap.ROUND);
p.setStrokeWidth(progress);
bitmap.eraseColor(
getResources().getColor(android.R.color.transparent,
getContext().getTheme()));
canvas.drawLine(30, 50, 370, 50, p);
widthImageView.setImageBitmap(bitmap);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) { // tarvitaan
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) { // tarvitaan
}
};
}
Your error says the following:
null object reference
This means that 1 object gives the value 0.
Your code looks fine but if you rewrite the code once again you may solve the mistake.
It is caused by a pitty error in your code.
When rewriting it. You can find that error.
Even if this was a bug with some plugin or anything else.
Also after you rewrote it, if you get the same error then you need to look onto a reference.
I am developing a coloring app and was able to fill white color of the image with different colors using the below code.
Here is the Java class
import java.util.LinkedList;
import java.util.Queue;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
public class Main extends Activity {
private RelativeLayout dashBoard;
private MyView myView;
public ImageView image;
Button b_red, b_blue, b_green, b_orange, b_clear;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myView = new MyView(this);
setContentView(R.layout.activity_main);
findViewById(R.id.dashBoard);
b_red = (Button) findViewById(R.id.b_red);
b_blue = (Button) findViewById(R.id.b_blue);
b_green = (Button) findViewById(R.id.b_green);
b_orange = (Button) findViewById(R.id.b_orange);
b_red.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.changePaintColor(0xFFFF0000);
}
});
b_blue.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.changePaintColor(0xFF0000FF);
}
});
b_green.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.changePaintColor(0xFF00FF00);
}
});
b_orange.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.changePaintColor(0xFFFF9900);
}
});
dashBoard = (RelativeLayout) findViewById(R.id.dashBoard);
dashBoard.addView(myView);
}
public class MyView extends View {
private Paint paint;
private Path path;
public Bitmap mBitmap;
public ProgressDialog pd;
final Point p1 = new Point();
public Canvas canvas;
//Bitmap mutableBitmap ;
public MyView(Context context) {
super(context);
this.paint = new Paint();
this.paint.setAntiAlias(true);
pd = new ProgressDialog(context);
this.paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(5f);
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.forme).copy(Bitmap.Config.ARGB_8888, true);
this.path = new Path();
}
#Override
protected void onDraw(Canvas canvas) {
this.canvas = canvas;
this.paint.setColor(Color.RED);
canvas.drawBitmap(mBitmap, 0, 0, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
p1.x = (int) x;
p1.y = (int) y;
final int sourceColor = mBitmap.getPixel((int) x, (int) y);
final int targetColor = paint.getColor();
new TheTask(mBitmap, p1, sourceColor, targetColor).execute();
invalidate();
}
return true;
}
public void clear() {
path.reset();
invalidate();
}
public int getCurrentPaintColor() {
return paint.getColor();
}
public void changePaintColor(int color){
this.paint.setColor(color);
}
class TheTask extends AsyncTask<Void, Integer, Void> {
Bitmap bmp;
Point pt;
int replacementColor, targetColor;
public TheTask(Bitmap bm, Point p, int sc, int tc) {
this.bmp = bm;
this.pt = p;
this.replacementColor = tc;
this.targetColor = sc;
pd.setMessage("Filling....");
pd.show();
}
#Override
protected void onPreExecute() {
pd.show();
}
#Override
protected void onProgressUpdate(Integer... values) {
}
#Override
protected Void doInBackground(Void... params) {
FloodFill f = new FloodFill();
f.floodFill(bmp, pt, targetColor, replacementColor);
return null;
}
#Override
protected void onPostExecute(Void result) {
pd.dismiss();
invalidate();
}
}
}
// flood fill
public class FloodFill {
public void floodFill(Bitmap image, Point node, int targetColor, int replacementColor) {
int width = image.getWidth();
int height = image.getHeight();
int target = targetColor;
int replacement = replacementColor;
if (target != replacement) {
Queue<Point> queue = new LinkedList<Point>();
do {
int x = node.x;
int y = node.y;
while (x > 0 && image.getPixel(x - 1, y) == target) {
x--;
}
boolean spanUp = false;
boolean spanDown = false;
while (x < width && image.getPixel(x, y) == target) {
image.setPixel(x, y, replacement);
if (!spanUp && y > 0 && image.getPixel(x, y - 1) == target) {
queue.add(new Point(x, y - 1));
spanUp = true;
} else if (spanUp && y > 0 && image.getPixel(x, y - 1) != target) {
spanUp = false;
}
if (!spanDown && y < height - 1 && image.getPixel(x, y + 1) == target) {
queue.add(new Point(x, y + 1));
spanDown = true;
} else if (spanDown && y < (height - 1) && image.getPixel(x, y + 1) != target) {
spanDown = false;
}
x++;
}
} while ((node = queue.poll()) != null);
}
}
}
}
As you can see i used fill flood algorithm for coloring the a white space in an image.
The image is below:
Image to be used to fill the color
Now question is how can i fill the white space region with the below pattern(or any other pattern) instead of the color.
Pattern image
Please any help is appreciated as i am new to android. Thankyou
Well after a little workaround I was able to fill the pattern in the closed region using Flood Fill Algorithm. Below is what I did.
1.Introduced a new bitmap with the pattern as u can see below.
bitmapPattern = BitmapFactory.decodeResource(getResources(),R.drawable.pattern1).copy(Bitmap.Config.ARGB_8888, true);
And passed this bitmapPattern to the Flood Fill Algorithm as follows.
FloodFillPattern f = new FloodFillPattern();
f.floodFillPattern(bmp, pt, targetColor, replacementColor, pattern);
Note you have to scale this bitmap equal to the size of your image in which you will fill this pattern.
Then simply replace the pixels of your original image with the pixels of the pattern bitmap in the flood fill algorithm. As Follows:
image.setPixel(x, y, pattern.getPixel(x,y));
pattern is the patternBitmap you passed.
May it help someone :)
I have two activities: a menu, and a game. I have them both set up as surface views, and when I click the "start" button on the menu activity, it starts the game activity. Then I want it to save the score and return to the menu activity when the player crashes. Both activities have separate threads that start with the activity, so when I tried to re-launch the menu activity from the game, I was getting an exception that the thread was already started. So to avoid this, I had the game activity finish the menu activity when it started so that relaunching the menu activity would also restart the thread. Now I'm getting an exception that the canvas is already locked. Do I need to unlock the canvas before finishing the activity? And is there a better way for me to handle switching between activities?
MainActivity:
package com.mikey.******;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
import android.view.WindowManager;
public class MainActivity extends Activity {
public static Activity activity;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activity = this;
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(new GamePanel(this));
}
}
GamePanel Layout:
package com.mikey.*****;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.preference.PreferenceManager;
import android.support.v4.app.NavUtils;
import android.util.AttributeSet;
import android.view.Display;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
import java.util.ArrayList;
import java.util.Random;
public class GamePanel extends SurfaceView implements SurfaceHolder.Callback {
private static SharedPreferences prefs;
public static int width;
public static int height;
public static int screenX, screenY;
private Canvas c;
private MainThread thread;
private Background bg;
private Scoreboard sb;
public int moveSpeed = 10;
private Player player;
private ArrayList<Smokepuff> smoke;
private Plunger plunger;
private Plunger plunger1;
private long smokeStart;
private long smokeTime;
public int score = 0;
public boolean isPlaying;
private Bitmap bgImg;
private Bitmap b;
private int scaleFactor = 2;
private long timer;
private long timeStart;
private Paint paint;
private ArrayList<Coin> coin;
private long coinTime;
private int coinDelay;
private Bitmap coinImg;
public boolean playable;
public int distance;
private int plungerDelay;
private int plungerReset;
private long plungerTime;
private int coinSet;
private Menu endMenu;
public GamePanel(Context context){
super(context);
prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
screenX=size.x;
screenY=size.y;
getHolder().addCallback(this);
thread = new MainThread(getHolder(), this);
setFocusable(true);
paint = new Paint();
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.FILL);
paint.setTextSize(40);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height){}
#Override
public void surfaceDestroyed(SurfaceHolder holder){
boolean retry = true;
int count = 0;
while(retry&&count<1000){
try{thread.setRunning(false);
thread.join();
retry=false;
}catch(InterruptedException e){}
count++;
}
}
#Override
public void surfaceCreated(SurfaceHolder holder){
thread.setRunning(true);
thread.start();
//moveSpeed = -20;
bgImg = BitmapFactory.decodeResource(getResources(), R.drawable.bg2);
width = bgImg.getWidth();
height = bgImg.getHeight();
bg = new Background(bgImg);
sb = new Scoreboard(getContext());
plunger = new Plunger(BitmapFactory.decodeResource(getResources(), R.drawable.plunger));
plunger1 = new Plunger(BitmapFactory.decodeResource(getResources(),R.drawable.plunger));
player = new Player(BitmapFactory.decodeResource(getResources(), R.drawable.potty));
smoke = new ArrayList<Smokepuff>();
coin = new ArrayList<Coin>();
//Random r = new Random();
coinImg = BitmapFactory.decodeResource(getResources(),R.drawable.coin2);
coin.add(new Coin(coinImg));
coinDelay = 5;
playable = true;
}
#Override
public boolean onTouchEvent(MotionEvent event){
if(event.getAction()==MotionEvent.ACTION_DOWN){
if(!isPlaying&&playable){
isPlaying=true;
smokeStart = System.nanoTime();
timeStart = System.nanoTime();
plungerReset = distance;
plungerDelay = 100;
coinSet = distance;
}
player.setAccelerate(true);
player.setUp(true);
return true;
}
else if(event.getAction()==MotionEvent.ACTION_UP){
player.setAccelerate(false);
player.setUp(false);
return true;
}
return super.onTouchEvent(event);
}
public void update(){
if(isPlaying) {
timer = (System.nanoTime() - timeStart) / 1000000;
distance+=(timer*moveSpeed)/1000;
if (timer > 50) {
if(player.getAccelerate()&&!player.maxAlt) {
moveSpeed += 1;
}else if(!player.getAccelerate()&&!player.maxAlt){
if(moveSpeed>0){
if(distance<200){
moveSpeed-=.05;
}else {
moveSpeed -= .18;
}
}
}
timeStart = System.nanoTime();
}
//moveSpeed += score;
smokeTime = (System.nanoTime()-smokeStart)/1000000;
if(smokeTime>100){
smoke.add(new Smokepuff(player.getX(),player.getY()+5));
smokeStart=System.nanoTime();
}
if(distance>300&&plungerDelay+plungerReset<distance){
plunger.setX(screenX);
plunger1.setX(screenX+500);
Random q = new Random();
plungerDelay = q.nextInt(150)+100;
plungerReset = distance;
}
if(distance-coinSet>coinDelay) {
Random z = new Random();
int num = z.nextInt(3) + 1;
for (int i = 0; i < num; i++) {
coin.add(new Coin(coinImg));
}
Random r = new Random();
coinDelay = r.nextInt(50) + 1;
coinSet=distance;
}
plunger.update(moveSpeed);
plunger1.update(moveSpeed);
int dy = player.update();
bg.update(moveSpeed, dy);
for(int i=0;i<coin.size();i++){
coin.get(i).update(moveSpeed);
if(coin.get(i).getX()<-10){
coin.remove(i);
}else if (collision(coin.get(i), player)) {
coin.remove(i);
score+=10;
}
}
if(collision(player,plunger)){
plunger.setX(player.getX() + player.getWidth() - 1);
plunger.setY(player.getY()+player.height/2);
if(!plunger.attached){
plungerTime = System.nanoTime();
plunger.attached = true;
}
if(moveSpeed>10){
moveSpeed--;
}
}
if(plunger.getX()<-100){
plunger.reset();
}
if(collision(player,plunger1)){
plunger1.setX(player.getX() + player.getWidth()-1);
plunger1.setY(player.getY()+player.height/2);
if(!plunger1.attached) {
plungerTime = System.nanoTime();
plunger1.attached=true;
}
if(moveSpeed>10){
moveSpeed--;
}
}
if(plunger1.getX()<-100){
plunger1.reset();
}
if((System.nanoTime()-plungerTime)/1000000>750){
if(collision(plunger,player)){
plunger.reset();
plunger.attached = false;
}
if(collision(plunger1,player)){
plunger1.reset();
plunger1.attached = false;
}
}
for(int i=0;i<smoke.size();i++){
smoke.get(i).update(moveSpeed);
if(smoke.get(i).getX()<-10||smoke.get(i).getY()<0){
smoke.remove(i);
}
}
sb.update(score, distance);
if(2*player.getY()>screenY-300){
SharedPreferences.Editor editor = prefs.edit();
if(!prefs.contains("highscore")) {
editor.putInt("highscore", score);
//return;
}else if(prefs.getInt("highscore",0)<score){
editor.putInt("highscore",score);
}
editor.commit();
isPlaying=false;
playable=false;
endGame();
//NavUtils.navigateUpFromSameTask(MainActivity.activity);
Intent intent = new Intent(getContext(),Menu.class);
getContext().startActivity(intent);
}
}
}
public boolean collision(GameObject a, GameObject b){
if(Rect.intersects(a.getRect(),b.getRect())){
return true;
}
return false;
}
#Override
public void draw(Canvas canvas){
final float scaleFactorX = (float) 2;
final float scaleFactorY = (float) 2;
if(canvas!=null){
c = canvas;
final int savedState = canvas.save();
canvas.scale(scaleFactorX, scaleFactorY);
bg.draw(canvas);
for(Coin c:coin){
c.draw(canvas);
}
plunger.draw(canvas);
plunger1.draw(canvas);
for(Smokepuff sp:smoke){
sp.draw(canvas);
}
player.draw(canvas);
if((isPlaying&&playable)||(!isPlaying&&!playable)) {
sb.draw(canvas);
}
canvas.restoreToCount(savedState);
canvas.drawText(Integer.toString(moveSpeed), screenX-100,40,paint);
}
//bg.draw(canvas);
}
public void endGame(){
SharedPreferences.Editor editor = prefs.edit();
if(!prefs.contains("highscore")) {
editor.putInt("highscore", score);
return;
}else if(prefs.getInt("highscore",0)<score){
editor.putInt("highscore",score);
}
editor.commit();
Intent intent = new Intent(getContext(),Menu.class);
getContext().startActivity(intent);
}
}
Menu Activity:
package com.mikey.*****;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageButton;
public class Menu extends Activity{
//private ImageButton upgrade;
private int screenY;
private int screenX;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
screenY = getWindow().getDecorView().getHeight();
screenX = getWindow().getDecorView().getWidth();
setContentView(new MenuLayout(this));
/*upgrade = (ImageButton) findViewById(R.id.upgrade);
upgrade.setX(-150);
upgrade.setY(1080-130);
upgrade.setScaleX(4);
upgrade.setScaleY(4);*/
}
#Override
protected void onPause(){
super.onPause();
finish();
}
}
MenuLayout:
package com.mikey.*****;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.RadialGradient;
import android.graphics.RectF;
import android.graphics.Shader;
import android.preference.PreferenceManager;
import android.view.Display;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
import java.util.ArrayList;
import java.util.Random;
public class MenuLayout extends SurfaceView implements SurfaceHolder.Callback {
private static SharedPreferences prefs;
private MenuThread thread;
private boolean played;
private int screenX, screenY;
private Bitmap upgrade;
private Bitmap map;
private Bitmap bg;
private Bitmap launch;
private Bitmap potty;
private Bitmap cloudA;
private Bitmap cloudB;
private ArrayList<Cloud> cloud;
private UpgradeBtn upgradeBtn;
private MapBtn mapBtn;
private LaunchBtn launchBtn;
//private Paint bg;
private Paint feature;
private Paint border;
private Paint featureRad;
private Paint stick;
private Paint text;
private Paint shadow;
private int x;
private int y;
private boolean upg;
private boolean showmap;
private boolean start;
public MenuLayout(Context context){
super(context);
prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
getHolder().addCallback(this);
thread = new MenuThread(getHolder(),this);
setFocusable(true);
screenX=size.x;
screenY=size.y;
upgrade = BitmapFactory.decodeResource(getResources(),R.drawable.blueprint);
map = BitmapFactory.decodeResource(getResources(),R.drawable.map);
launch = BitmapFactory.decodeResource(getResources(),R.drawable.launch);
bg = BitmapFactory.decodeResource(getResources(),R.drawable.menu_bg);
potty = BitmapFactory.decodeResource(getResources(),R.drawable.potty1);
cloudA = BitmapFactory.decodeResource(getResources(),R.drawable.cloud1);
cloudB = BitmapFactory.decodeResource(getResources(),R.drawable.cloud2);
upgradeBtn = new UpgradeBtn(upgrade,screenY);
mapBtn = new MapBtn(map);
launchBtn = new LaunchBtn(launch,screenX,screenY);
cloud = new ArrayList<>();
for(int i =0;i<4;i++){
addCloud();
}
start = true;
//bg = new Paint();
//bg.setColor(Color.WHITE);
shadow = new Paint();
shadow.setAntiAlias(true);
shadow.setColor(Color.WHITE);
shadow.setTextSize(45.0f);
shadow.setStrokeWidth(2.0f);
shadow.setStyle(Paint.Style.STROKE);
shadow.setShadowLayer(10.0f, 20.0f, -20.0f, Color.BLACK);
Shader shader = new LinearGradient(0, 0, 0, 90, Color.LTGRAY, Color.DKGRAY, Shader.TileMode.CLAMP);
feature = new Paint();
feature.setShader(shader);
border = new Paint();
border.setColor(Color.BLACK);
border.setStyle(Paint.Style.STROKE);
border.setStrokeWidth(8);
Shader shader1 = new RadialGradient(screenX-60,60,150,Color.LTGRAY,Color.DKGRAY, Shader.TileMode.MIRROR);
featureRad = new Paint();
featureRad.setShader(shader1);
stick = new Paint();
stick.setColor(Color.BLACK);
stick.setStrokeWidth(20);
text = new Paint();
text.setColor(Color.WHITE);
text.setTextSize(50);
}
public void addCloud(){
Bitmap img;
Random r = new Random();
Random p = new Random();
Random q = new Random();
int s = r.nextInt(10);
if(s>5){
Matrix m = new Matrix();
float h = r.nextFloat()+1;
m.setRectToRect(new RectF(0, 0, cloudA.getWidth(), cloudA.getHeight()),
new RectF(0, 0, cloudA.getWidth()*h, cloudA.getHeight()*h), Matrix.ScaleToFit.CENTER);
img = Bitmap.createBitmap(cloudA, 0, 0, cloudA.getWidth(), cloudA.getHeight(), m, true);
}else{
img = cloudB;
}
if(start){
x = -img.getWidth();
}
else{
x = p.nextInt(screenX);
}
cloud.add(new Cloud(img,x,p.nextInt(screenY-750)+100,q.nextInt(8)+1,screenX));
}
public Bitmap highlightImage(Bitmap src, int color,boolean x, boolean y) {
int xMod;
int yMod;
if(x){
xMod = 4;
}else{
xMod = -1;
}
if(y){
yMod = 2;
}
else{
yMod = -1;
}
// create new bitmap, which will be painted and becomes result image
Bitmap bmOut = Bitmap.createBitmap(src.getWidth()*5/4+30, src.getHeight()*5/4+30, Bitmap.Config.ARGB_8888);
// setup canvas for painting
Canvas canvas = new Canvas(bmOut);
canvas.scale(1.25f,1.25f);
// setup default color
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
// create a blur paint for capturing alpha
Paint ptBlur = new Paint();
ptBlur.setMaskFilter(new BlurMaskFilter(15, BlurMaskFilter.Blur.NORMAL));
int[] offsetXY = new int[2];
// capture alpha into a bitmap
Bitmap bmAlpha = src.extractAlpha(ptBlur, offsetXY);
// create a color paint
Paint ptAlphaColor = new Paint();
ptAlphaColor.setColor(color);
// paint color for captured alpha region (bitmap)
canvas.drawBitmap(bmAlpha, xMod*offsetXY[0]/2, yMod*offsetXY[1], ptAlphaColor);
// free memory
bmAlpha.recycle();
// paint the image source
canvas.drawBitmap(src, 0, 0, null);
// return out final image
return bmOut;
}
public void launchUpgrade(){
upg = true;
upgradeBtn.setImg(upgrade);
}
public void launchMap(){
showmap = true;
mapBtn.setImg(map);
}
public void launchProfile(){
}
public void startGame(){
launchBtn.setImg(launch);
Intent myIntent = new Intent(getContext(), MainActivity.class);
//myIntent.putExtra("key", value); //Optional parameters
getContext().startActivity(myIntent);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
if(!thread.getRunning()) {
thread.setRunning(true);
thread.start();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height){}
#Override
public void surfaceDestroyed(SurfaceHolder holder){
boolean retry = true;
int count = 0;
if(thread.getRunning()) {
thread.interrupt();
}
/*while(retry&&count<1000){
try{thread.setRunning(false);
thread.join();
retry=false;
}catch(InterruptedException e){}
count++;
}*/
}
#Override
public boolean onTouchEvent(MotionEvent event) {
x =(int) event.getX();
y =(int) event.getY();
if (x < 710 && y > 780) {
upgradeBtn.setImg(highlightImage(upgrade,Color.BLUE,false,true));
}else{
upgradeBtn.setImg(upgrade);
}
if (x < 520 && y < 275) {
mapBtn.setImg(highlightImage(map,Color.YELLOW,true,false));
}else{
mapBtn.setImg(map);
}
if(x>1500&&y>700){
launchBtn.setImg(highlightImage(launch,Color.RED,true,true));
}else{
launchBtn.setImg(launch);
}
if(event.getAction()==MotionEvent.ACTION_UP) {
if (x < 710 && y > 780) {
launchUpgrade();
return true;
}
if (x < 520 && y < 275) {
launchMap();
return true;
}
if(x>1700&&y<235){
launchProfile();
return true;
}
if(x>1500&&y>700){
startGame();
}
}
return true;
}
public void update(){
for(int i=0;i<cloud.size();i++){
cloud.get(i).update();
if(cloud.get(i).getX()>screenX){
cloud.remove(i);
addCloud();
}
}
}
#Override
public void draw(Canvas canvas){
if(canvas!=null) {
canvas.drawBitmap(bg,-3,0,null);
for(int i=0;i<cloud.size();i++){
cloud.get(i).draw(canvas);
}
canvas.drawBitmap(potty, screenX / 2 - 190, screenY / 2 - 190, null);
//canvas.drawBitmap(upgrade, -235, screenY - upgrade.getHeight() + 300, null);
canvas.drawRoundRect(screenX - 550, 5, screenX - 150, 105, 15, 15, feature);
canvas.drawRoundRect(screenX - 550, 5, screenX - 150, 105, 25, 25, border);
canvas.drawCircle(screenX - 60, 60, 150, featureRad);
canvas.drawCircle(screenX - 60, 60, 150, border);
canvas.drawCircle(screenX / 2 + 230, screenY / 2 + 110, 50, stick);
canvas.drawLine(screenX / 2 + 220, screenY / 2 + 110, screenX / 2 + 185, screenY / 2 + 340, stick);
canvas.drawLine(screenX / 2 + 185, screenY / 2 + 340, screenX / 2 + 270, screenY/2+440,stick);
canvas.drawLine(screenX/2+270,screenY/2+440,screenX/2+270,screenY,stick);
canvas.drawLine(screenX/2+270,screenY/2+440,screenX/2+340,screenY,stick);
canvas.drawLine(((screenX / 2 + 220)+(screenX / 2 + 185))/2,screenY/2+230,screenX/2+210,
screenY/2+250,stick);
canvas.drawLine(screenX/2+185,screenY/2+250,screenX/2+245,screenY/2+235,stick);
canvas.drawLine(screenX / 2 + 235, screenY / 2 + 245, ((screenX / 2 + 220) + (screenX / 2 + 185)) / 2,
screenY / 2 + 230, stick);
canvas.drawText(Integer.toString(prefs.getInt("highscore", 0)), 1000, 50, text);
upgradeBtn.draw(canvas);
mapBtn.draw(canvas);
launchBtn.draw(canvas);
canvas.drawText(Integer.toString(x)+","+Integer.toString(y),50,50,text);
/*if(upg){
canvas.drawText("UPGRADE",540,400,text);
canvas.drawBitmap(highlightImage(upgrade), -235, screenY - upgrade.getHeight() + 300,null);
}*/
if(showmap){
canvas.drawText("MAP",540,500,text);
}
}
}
}
I'm sure there is a lot more wrong with my code than just the issue I'm having because I'm very new to this, so if you have any general suggestions to clean up my code, I'd love to hear those as well.
Trying to get the ball where it moves back and forth across the screen (left-right).
I tried using the draw function to update the ball position using if statements
x += speed_x;
y += speed_y;
canvas.drawCircle(x, y, 20, paint);
if (x == 0)
speed_x=-1;
if (x == getHeight())
speed_x=1;
if (y == 0)
speed_y = -1;
if (y == getWidth())
speed_y = 1;
invalidate();
This did not work.
**game.java*
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.graphics.drawable.BitmapDrawable;
import android.os.Handler;
import android.util.AttributeSet;
import android.widget.ImageView;
public class GameWorld extends SurfaceView implements Runnable {
boolean isRunning;
GameObject obj;
SurfaceHolder holder;
Canvas canvas;
Thread gameThread;
Paint paint;
private Context mContext;
int x = -1;
int y = -1;
int speed_x=1, speed_y=1;
private int xVelocity = 10;
private int yVelocity = 5;
private Handler h;
private final int FRAME_RATE = 30;
public GameWorld(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
h = new Handler();
}
private Runnable r = new Runnable() {
#Override
public void run() {
invalidate();
}
};
public GameWorld(Context context){
super(context);
isRunning=true;
obj=new GameObject(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher),200,300);
paint=new Paint();
gameThread= new Thread(this);
gameThread.start();
holder=getHolder();
}
public void run(){
while(isRunning){
if(!holder.getSurface().isValid()){
continue;
}
update();
draw();
}
}
private void update(){
obj.update();
}
private void draw(){
canvas=holder.lockCanvas();
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
obj.draw(canvas);
canvas.drawColor(Color.WHITE);
x+=speed_x;
y+=speed_y;
canvas.drawCircle(x, y, 20, paint);
if(x==0)
speed_x=-1;
if(x== getHeight())
speed_x=1;
if(y==0)
speed_y=-1;
if(y==getWidth())
speed_y=1;
invalidate();
holder.unlockCanvasAndPost(canvas);
}
public boolean onTouchEvent(MotionEvent event){
obj.jump();
return super.onTouchEvent(event);
}
}
**main:**
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new GameWorld(this));
}
}
**gameobject.java**
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
public class GameObject {
int x,y;
int velY;
int width, height;
boolean jump;
Bitmap bitmap;
final int GRAVITY =2;
public GameObject(Bitmap bitmap, int x, int y){
this.x=x;
this.y=y;
this.width=bitmap.getWidth();
this.height=bitmap.getHeight();
this.bitmap=bitmap;
velY=0;
jump=false;
}
public void update(){
//handles input
if (jump){
velY=-30;
}
//add gravity
velY+=GRAVITY;
y+=velY;
//POSITION
if(y>300){
y=300;
velY=0;
}
jump=false;
}
public void jump(){
jump=true;
}
Paint paint = new Paint();
public void draw(Canvas canvas){
canvas.drawBitmap(bitmap,x,y,null);
int x=5; //ball
boolean game = true;
// while(game = true)
// {
int maxx = canvas.getWidth();
if (x <= maxx)
{
paint.setColor(Color.WHITE);
canvas.drawCircle(x, 305, 10, paint);
x= (x+2);
}
///else{
// x= (x-2);
// paint.setColor(Color.WHITE);
// canvas.drawCircle(x, 305, 10, paint);
// game = false;
//}
// }
}
public void moveball()
{
x= (x-2);
}
}
Here is my version of a ball moving based on the swipes it recives
import android.app.Activity;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.view.View;
public class BouncingBallActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View boundcingBallView = new BouncingBallView(this);
setContentView(boundcingBallView);
}
}
Here is the actual view that will make the ball
package com.example.bouncingball;
import java.util.Formatter;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
public class BouncingBallView extends View {
private int xMin=0,xMax,yMin=0,yMax;
private float ballRadius = 80,ballX = ballRadius+20, ballY= ballRadius+40,ballSpeedX=5,ballSpeedY=3,previousX,previousY;
private RectF ballBounds;
private Paint paint;
private StringBuilder statusmsg = new StringBuilder();
private Formatter formatter = new Formatter(statusmsg);
public BouncingBallView(Context context) {
super(context);
ballBounds = new RectF();
paint = new Paint();
paint.setDither(true);
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setHinting(Paint.HINTING_ON);
paint.setPathEffect(new DashPathEffect(new float[] {1,1}, 0));
paint.setTypeface(Typeface.MONOSPACE);
paint.setTextSize(16);
this.setFocusableInTouchMode(true);
}
#Override
protected void onDraw(Canvas canvas) {
ballBounds.set(ballX-ballRadius , ballY-ballRadius,ballX+ballRadius,ballY+ballRadius);
paint.setColor(Color.GREEN);
canvas.drawOval(ballBounds, paint);
paint.setColor(Color.BLACK);
canvas.drawText(statusmsg.toString(), 10, 30,paint);
update();
invalidate();
}
private void update() {
ballX +=ballSpeedX;
ballY+=ballSpeedY;
if(ballX+ballRadius> yMax) {
ballSpeedX =-ballSpeedX;
ballX = xMax -ballRadius;
}
else if(ballX - ballRadius < xMin) {
ballSpeedX = -ballSpeedX;
ballX = xMin+ballRadius;
}
if(ballY + ballRadius > yMax) {
ballSpeedY = -ballSpeedY;
ballY = yMax-ballRadius;
}
else if (ballY - ballRadius < yMin) {
ballSpeedY = -ballSpeedY;
ballY = yMin+ballRadius;
}
statusmsg.delete(0, statusmsg.length());
formatter.format("Ball#(%3.0f,%3.0f),Speed=(%2.0f,%2.0f)", ballX, ballY,ballSpeedX, ballSpeedY);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
xMax = w-1;
yMax = h-1;
}
#Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch(keyCode) {
case KeyEvent.KEYCODE_DPAD_RIGHT:
ballSpeedX++;
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
ballSpeedX--;
break;
case KeyEvent.KEYCODE_DPAD_UP:
ballSpeedY--;
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
ballSpeedY++;
break;
case KeyEvent.KEYCODE_DPAD_CENTER:
ballSpeedX = 0;
ballSpeedY = 0;
break;
case KeyEvent.KEYCODE_A:
float maxRadius = (xMax > yMax) ? yMax / 2* 0.9f : xMax / 2 * 0.9f;
if(ballRadius < maxRadius)
ballRadius*=1.05;
break;
case KeyEvent.KEYCODE_Z:
if(ballRadius>20){
ballRadius *=0.95;
}
break;
}
return true;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float currentX=event.getX();
float currentY = event.getY();
float deltaX,deltaY;
float scalingFactor = 5.0f / ((xMax > yMax) ? yMax : xMax);
switch(event.getAction()) {
case MotionEvent.ACTION_MOVE:
deltaX = currentX - previousX;
deltaY = currentY - previousY;
ballSpeedX += deltaX*scalingFactor;
ballSpeedY += deltaY*scalingFactor;
}
previousX = currentX;
previousY = currentY;
return true;
}
}
I am New to Android. My Requirement is to implement a color picker which scrolls the colors in rainbow model from that I want to pick a color.
for the color picker use the ColorPickerDialog class from API Demos, And how to use it's describe in this code. So it's try.
package com.SampleCanvas;
import java.util.ArrayList;
import com.SampleCanvas.ColorPickerDialog.OnColorChangedListener;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.FrameLayout;
public class SampleCanvasActivity extends Activity implements OnTouchListener, OnClickListener, OnColorChangedListener {
DrawPanel dp;
private ArrayList<Path> pointsToDraw = new ArrayList<Path>();
private Paint mPaint;
Path path;
int color;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dp = new DrawPanel(this);
setContentView(R.layout.main);
dp = new DrawPanel(this);
dp.setOnTouchListener(this);
Button btn=(Button)findViewById(R.id.btnColor);
btn.setOnClickListener(this);
mPaint = new Paint();
mPaint.setColor(Color.WHITE);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(5);
FrameLayout fl = (FrameLayout)findViewById(R.id.frameLayout);
fl.addView(dp,LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
dp.pause();
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
dp.resume();
}
public boolean onTouch(View v, MotionEvent me) {
// TODO Auto-generated method stub
synchronized(pointsToDraw)
{
if(me.getAction() == MotionEvent.ACTION_DOWN){
path = new Path();
path.moveTo(me.getX(), me.getY());
//path.lineTo(me.getX(), me.getY());
pointsToDraw.add(path);
}else if(me.getAction() == MotionEvent.ACTION_MOVE){
path.lineTo(me.getX(), me.getY());
}else if(me.getAction() == MotionEvent.ACTION_UP){
//path.lineTo(me.getX(), me.getY());
}
}
return true;
}
public class DrawPanel extends SurfaceView implements Runnable{
Thread t = null;
SurfaceHolder holder;
boolean isItOk = false ;
public DrawPanel(Context context) {
super(context);
// TODO Auto-generated constructor stub
holder = getHolder();
}
public void run() {
// TODO Auto-generated method stub
while( isItOk == true){
if(!holder.getSurface().isValid()){
continue;
}
Canvas c = holder.lockCanvas();
c.drawARGB(255, 0, 0, 0);
onDraw(c);
holder.unlockCanvasAndPost(c);
}
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
synchronized(pointsToDraw)
{
for (Path path : pointsToDraw) {
canvas.drawPath(path, mPaint);
}
}
}
public void pause(){
isItOk = false;
while(true){
try{
t.join();
}catch(InterruptedException e){
e.printStackTrace();
}
break;
}
t = null;
}
public void resume(){
isItOk = true;
t = new Thread(this);
t.start();
}
}
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.btnColor:
new ColorPickerDialog(this, this,mPaint.getColor()).show();
break;
default:
break;
}
}
public void colorChanged(int color) {
// TODO Auto-generated method stub
mPaint.setColor(color);
}
}
And The Color Picker Class is
package com.SampleCanvas;
import android.os.Bundle;
import android.app.Dialog;
import android.content.Context;
import android.graphics.*;
import android.view.MotionEvent;
import android.view.View;
public class ColorPickerDialog extends Dialog {
public interface OnColorChangedListener {
void colorChanged(int color);
}
private OnColorChangedListener mListener;
private int mInitialColor;
private static class ColorPickerView extends View {
private Paint mPaint;
private Paint mCenterPaint;
private final int[] mColors;
private OnColorChangedListener mListener;
ColorPickerView(Context c, OnColorChangedListener l, int color) {
super(c);
mListener = l;
mColors = new int[] {
0xFFFF0000, 0xFFFF00FF, 0xFF0000FF, 0xFF00FFFF, 0xFF00FF00,
0xFFFFFF00, 0xFFFF0000
};
Shader s = new SweepGradient(0, 0, mColors, null);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setShader(s);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(32);
mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mCenterPaint.setColor(color);
mCenterPaint.setStrokeWidth(5);
}
private boolean mTrackingCenter;
private boolean mHighlightCenter;
#Override
protected void onDraw(Canvas canvas) {
float r = CENTER_X - mPaint.getStrokeWidth()*0.5f;
canvas.translate(CENTER_X, CENTER_X);
canvas.drawOval(new RectF(-r, -r, r, r), mPaint);
canvas.drawCircle(0, 0, CENTER_RADIUS, mCenterPaint);
if (mTrackingCenter) {
int c = mCenterPaint.getColor();
mCenterPaint.setStyle(Paint.Style.STROKE);
if (mHighlightCenter) {
mCenterPaint.setAlpha(0xFF);
} else {
mCenterPaint.setAlpha(0x80);
}
canvas.drawCircle(0, 0,
CENTER_RADIUS + mCenterPaint.getStrokeWidth(),
mCenterPaint);
mCenterPaint.setStyle(Paint.Style.FILL);
mCenterPaint.setColor(c);
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(CENTER_X*2, CENTER_Y*2);
}
private static final int CENTER_X = 100;
private static final int CENTER_Y = 100;
private static final int CENTER_RADIUS = 32;
private int floatToByte(float x) {
int n = java.lang.Math.round(x);
return n;
}
private int pinToByte(int n) {
if (n < 0) {
n = 0;
} else if (n > 255) {
n = 255;
}
return n;
}
private int ave(int s, int d, float p) {
return s + java.lang.Math.round(p * (d - s));
}
private int interpColor(int colors[], float unit) {
if (unit <= 0) {
return colors[0];
}
if (unit >= 1) {
return colors[colors.length - 1];
}
float p = unit * (colors.length - 1);
int i = (int)p;
p -= i;
// now p is just the fractional part [0...1) and i is the index
int c0 = colors[i];
int c1 = colors[i+1];
int a = ave(Color.alpha(c0), Color.alpha(c1), p);
int r = ave(Color.red(c0), Color.red(c1), p);
int g = ave(Color.green(c0), Color.green(c1), p);
int b = ave(Color.blue(c0), Color.blue(c1), p);
return Color.argb(a, r, g, b);
}
private int rotateColor(int color, float rad) {
float deg = rad * 180 / 3.1415927f;
int r = Color.red(color);
int g = Color.green(color);
int b = Color.blue(color);
ColorMatrix cm = new ColorMatrix();
ColorMatrix tmp = new ColorMatrix();
cm.setRGB2YUV();
tmp.setRotate(0, deg);
cm.postConcat(tmp);
tmp.setYUV2RGB();
cm.postConcat(tmp);
final float[] a = cm.getArray();
int ir = floatToByte(a[0] * r + a[1] * g + a[2] * b);
int ig = floatToByte(a[5] * r + a[6] * g + a[7] * b);
int ib = floatToByte(a[10] * r + a[11] * g + a[12] * b);
return Color.argb(Color.alpha(color), pinToByte(ir),
pinToByte(ig), pinToByte(ib));
}
private static final float PI = 3.1415926f;
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX() - CENTER_X;
float y = event.getY() - CENTER_Y;
boolean inCenter = java.lang.Math.sqrt(x*x + y*y) <= CENTER_RADIUS;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mTrackingCenter = inCenter;
if (inCenter) {
mHighlightCenter = true;
invalidate();
break;
}
case MotionEvent.ACTION_MOVE:
if (mTrackingCenter) {
if (mHighlightCenter != inCenter) {
mHighlightCenter = inCenter;
invalidate();
}
} else {
float angle = (float)java.lang.Math.atan2(y, x);
// need to turn angle [-PI ... PI] into unit [0....1]
float unit = angle/(2*PI);
if (unit < 0) {
unit += 1;
}
mCenterPaint.setColor(interpColor(mColors, unit));
invalidate();
}
break;
case MotionEvent.ACTION_UP:
if (mTrackingCenter) {
if (inCenter) {
mListener.colorChanged(mCenterPaint.getColor());
}
mTrackingCenter = false; // so we draw w/o halo
invalidate();
}
break;
}
return true;
}
}
public ColorPickerDialog(Context context,
OnColorChangedListener listener,
int initialColor) {
super(context);
mListener = listener;
mInitialColor = initialColor;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OnColorChangedListener l = new OnColorChangedListener() {
public void colorChanged(int color) {
mListener.colorChanged(color);
dismiss();
}
};
setContentView(new ColorPickerView(getContext(), l, mInitialColor));
setTitle("Pick a Color");
}
}