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.
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 want to set my bitmap converted image in relative layout with the help of custom view but my image not set in the center of relative layout and its not showing complete image
My relative layout where I set my bitmap image`package org.boostram.justcolor;
import android.app.ActionBar;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.transition.TransitionManager;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.flask.colorpicker.ColorPickerView;
import com.flask.colorpicker.OnColorChangedListener;
import com.flask.colorpicker.OnColorSelectedListener;
import org.boostram.justcolor.Utils.util;
import static android.R.attr.src;
public class FillPaintActivity extends Activity implements View.OnTouchListener {
private RelativeLayout dashBoard;
Paint paint;
private MyView myView;
int a = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myView = new MyView(this);
setContentView(R.layout.activity_fill_paint);
ColorPickerView colorPickerView = (ColorPickerView) findViewById(R.id.color_picker_view);
// colorPickerView.setColor(Color.WHITE,true);
paint.setColor(Color.WHITE);
colorPickerView.setInitialColor(Color.WHITE, true);
colorPickerView.addOnColorChangedListener(new OnColorChangedListener() {
#Override
public void onColorChanged(int selectedColor) {
a = 1;
paint.setColor(selectedColor);
// Handle on color change
// Log.d("ColorPicker", "onColorChanged: 0x" + Integer.toHexString(selectedColor));
}
});
colorPickerView.addOnColorSelectedListener(new OnColorSelectedListener() {
#Override
public void onColorSelected(int selectedColor) {
paint.setColor(selectedColor);
// myView.changePaintColor(selectedColor);
Toast.makeText(FillPaintActivity.this, "selectedColor: " +
Integer.toHexString(selectedColor).toUpperCase(),
// Toast.LENGTH_SHORT).show();
}
});
dashBoard = (RelativeLayout) findViewById(R.id.dashBoard);
dashBoard.addView(myView);
}
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return false;
}
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;
public MyView(Context context) {
super(context);
paint = new Paint();
paint.setAntiAlias(true);
pd = new ProgressDialog(context);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
// paint.setStrokeWidth(5f);
// BitmapDrawable drawable = (BitmapDrawable)
context.getDrawable(R.drawable.unnamed);
// Bitmap bmp = drawable.getBitmap();
// Bitmap mBitmap = Bitmap.createScaledBitmap(bmp, 120, 120,
false);
mBitmap = BitmapFactory.decodeResource(getResources(),
util.Id).copy(Bitmap.Config.ARGB_8888, true);
//mBitmap =
Bitmap.createScaledBitmap((BitmapFactory.decodeResource(getResources(),
util.Id).copy(Bitmap.Config.ARGB_8888, true)),1500,1380,false);
this.path = new Path();
}
#Override
protected void onDraw(Canvas canvas) {
this.canvas = canvas;
// Display display = getWindowManager().getDefaultDisplay();
// int displayWidth = display.getWidth();
// BitmapFactory.Options options = new BitmapFactory.Options();
// options.inJustDecodeBounds = true;
// BitmapFactory.decodeResource(getResources(), util.Id, options);
// int width = options.outWidth;
// if (width > displayWidth)
// {
// int widthRatio = Math.round((float) width / (float)
displayWidth);
// options.inSampleSize = widthRatio;
// }
// options.inJustDecodeBounds = false;
// Bitmap scaledBitmap =
BitmapFactory.decodeResource(getResources(),util.Id , options);
canvas.drawBitmap(mBitmap,0,0 ,paint);
// mBitmap = BitmapFactory.decodeResource
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (a == 0) {
Toast.makeText(FillPaintActivity.this, "Select Any Color First",
Toast.LENGTH_SHORT).show();
}
// Toast.makeText(FillPaintActivity.this, myView.getWidth()+""+myView.getHeight(), Toast.LENGTH_LONG).show();
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
p1.x = (int) x;
p1.y = (int) y;
if (p1.x < mBitmap.getWidth() && p1.y < mBitmap.getHeight()) {
final int sourceColor = mBitmap.getPixel((int) x, (int) y);
final int targetColor = paint.getColor();
new TheTask(mBitmap, p1, sourceColor, targetColor).execute();
invalidate();
}
// else {
// Toast.makeText(FillPaintActivity.this, "You touched outside the Image", Toast.LENGTH_SHORT).show();
// }
}
return true;
}
public void clear() {
path.reset();
invalidate();
}
public void changePaintColor(int color) {
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;
}
#Override
protected void onPreExecute() {
// pd.show();
}
#Override
protected void onProgressUpdate(Integer... values) {
}
#Override
protected Void doInBackground(Void... params) {
FloodFill floodFill = new FloodFill(bmp, targetColor, replacementColor);
floodFill.floodFill(pt.x, pt.y);
return null;
}
#Override
protected void onPostExecute(Void result) {
invalidate();
}
}
}
}
https://i.stack.imgur.com/AHpcb.png
My bitmap converted image not set in center of relative layout through view. Kindly help me i'm stuck here for almost two week. Help
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 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();
If I want to add a button in this class so that I can call the onclicklistener, how should I do it?i have also provided the activity class onto which i am adding this view.
activity:
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.content.Context;
public class NewGame extends Activity {
View view;
Context context;
RelativeLayout layout;
GameView gameview;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
gameview=new GameView(this);
setContentView(gameview);
//layout = (RelativeLayout) findViewById(R.id.relative_layout);
//layout.addView(gameview);
}
}
view:
public class GameView extends View {
Path circle;
Paint cPaint;
Paint tPaint;
String z;
int i = 65, strt, arc, leftx, topy, rightx, bottomy, maxx, maxy;
boolean flag1, flag2, flag3;
double n1, n2;
int n, n3 = 180,n4,n5 = 90;
float f1 = 180, f2 = 90;
Button b1;
Random r = new Random();
RectF oval;
public GameView(Context context) {
super(context);
leftx = 0;
topy = 60;
rightx = 150;
bottomy = 120;
z = String.valueOf(Character.toChars(i));
cPaint = new Paint();
cPaint.setColor(Color.RED);
strt = 45;
arc = 315;
n1 = Math.random() * 600;
Log.d("random", z);
if (flag2 == false)
new DrawThread(this);
// cPaint.setStrokeWidth(2);
tPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
tPaint.setStyle(Paint.Style.FILL_AND_STROKE);
tPaint.setColor(Color.BLACK);
float scale = getResources().getDisplayMetrics().scaledDensity;
tPaint.setTextSize(20 * scale);
}
public void onSizeChanged(int w,int h,int oldh,int oldw) {
maxx = oldw;
maxy = oldh;
}
//#Override
protected void onDraw(Canvas canvas) {
// Drawing commands go here
oval = new RectF(leftx,topy,rightx,bottomy);
canvas.drawArc(oval, strt, arc, true, cPaint);
while (i < 90) {
canvas.drawText(String.valueOf(Character.toChars(i)),f1,f2, tPaint);
break;
}
}
}
You can do it like this:
Button bt = new Button(this);
bt.setText("A Button");
bt.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
linerLayout.addView(bt);
And then you can do this
bt.setOnClickListener(new View.OnClickListener() {
//TO DO
}
I hope that this can help you.
first of all in order to allow to your custom view to have an addView(View v) method it must extend ViewGroup instead of View; then you can use this code
b1=new Button(context);
b1.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT ));
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
this.addView(b1);