I started implementing touch controls to my android game (flappy bird type of clone) and I am having hard time making this work. I have implemented onTouchEvent that basically takes the whole screen and reacts to any touch but now I want to expand on that and have clickable buttons/icons etc. I learned about OnClickListener function that should do the job but I am stuck as hell on this, the game now crashes after initialization.
Based on my research, I have set my playbutton(PNG image) to ImageBitmap and then set that to OnClickListener, currently I am just testing this to give me something to console. In MainActivity, I have also set up the ImageButton with findViewById as advised. No errors in Android Studio but this comes up after running:
2020-05-11 21:23:34.526 6075-6075/com.markS.flappykillercrow E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.markS.flappykillercrow, PID: 6075
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.markS.flappykillercrow/com.markS.flappykillercrow.MainActivity}: android.view.InflateException: Binary XML file line #9: Binary XML file line #9: Error inflating class com.markS.flappykillercrow.GameManager
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2778)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: android.view.InflateException: Binary XML file line #9: Binary XML file line #9: Error inflating class com.markS.flappykillercrow.GameManager
Caused by: android.view.InflateException: Binary XML file line #9: Error inflating class com.markS.flappykillercrow.GameManager
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:334)
at android.view.LayoutInflater.createView(LayoutInflater.java:647)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:790)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:419)
at android.app.Activity.setContentView(Activity.java:2669)
at com.markS.flappykillercrow.MainActivity.onCreate(MainActivity.java:24)
at android.app.Activity.performCreate(Activity.java:7009)
at android.app.Activity.performCreate(Activity.java:7000)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageButton.setImageBitmap(android.graphics.Bitmap)' on a null object reference
at com.markS.flappykillercrow.sprites.GameOver.<init>(GameOver.java:33)
at com.markS.flappykillercrow.GameManager.initGame(GameManager.java:86)
at com.markS.flappykillercrow.GameManager.<init>(GameManager.java:75)
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:334)
at android.view.LayoutInflater.createView(LayoutInflater.java:647)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:790)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:419)
at android.app.Activity.setContentView(Activity.java:2669)
at com.markS.flappykillercrow.MainActivity.onCreate(MainActivity.java:24)
at android.app.Activity.performCreate(Activity.java:7009)
at android.app.Activity.performCreate(Activity.java:7000)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Here is the class where I have my playbutton implemented with the OnClickListener:
package com.markS.flappykillercrow.sprites;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.view.View;
import android.widget.ImageButton;
import android.widget.Toast;
import com.markS.flappykillercrow.MainActivity;
import com.markS.flappykillercrow.R;
public class GameOver implements Sprite {
private Bitmap gameOver;
private Bitmap playButton; //adding playButton Bitmap
private Bitmap rateUs;
private Bitmap volumeOn;
private Bitmap volumeOf;
private ImageButton imgButton;
private int screenHeight, screenWidth;
public GameOver(Resources resources, int screenHeight, int screenWidth) {
this.screenHeight = screenHeight;
this.screenWidth = screenWidth;
gameOver = BitmapFactory.decodeResource(resources, R.drawable.gameover);
playButton = BitmapFactory.decodeResource(resources, R.drawable.playbutton);
imgButton.setImageBitmap(playButton);
imgButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("THIS WORKS");
}
});
rateUs = BitmapFactory.decodeResource(resources, R.drawable.rateus);
volumeOn = BitmapFactory.decodeResource(resources, R.drawable.volumeon);
volumeOf = BitmapFactory.decodeResource(resources, R.drawable.volumeoff);
}
@Override
public void draw(Canvas canvas) {
canvas.drawBitmap(gameOver, screenWidth / 2 - gameOver.getWidth() / 2, screenHeight / 4, null);
}
//for drawing playbutton
public void drawplay(Canvas canvas) {
canvas.drawBitmap(playButton, (screenWidth / 2 - playButton.getWidth() / 2), screenHeight / (float) 2.5, null);
}
//for drawing rate us
public void drawrateus(Canvas canvas) {
canvas.drawBitmap(rateUs, (float) (screenWidth / 1.4 - rateUs.getWidth() / 21.7), screenHeight / (float) 3.2, null);
}
//for drawing volumes
public void drawvolumeon(Canvas canvas) {
canvas.drawBitmap(volumeOn, (screenWidth / 23 - volumeOn.getWidth() / 23), screenHeight / 50, null);
}
//later implement if statement
public void drawvolumeof(Canvas canvas) {
canvas.drawBitmap(volumeOf, (screenWidth / 20 - volumeOf.getWidth() / 20), screenHeight / 50, null);
}
@Override
public void update() {
}
}
MainActivity:
package com.markS.flappykillercrow;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.widget.ImageButton;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.MobileAds;
public class MainActivity extends Activity {
private AdView nAdView;
private ImageButton imgButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
imgButton=(ImageButton) findViewById(R.id.imgButton);
MobileAds.initialize(this,"ca-app-pub-9057526686789846~7828440247"); //just a test ID
nAdView=findViewById(R.id.adView);
AdRequest adRequest=new AdRequest.Builder().build();
nAdView.loadAd(adRequest);
}
}
Thank you guys for any helpful advice. I think once I get that "sout" to console working, I could manage from there but now I am just stuck for too long. Thank you!
The relevant (original) error in your traceback:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageButton.setImageBitmap(android.graphics.Bitmap)' on a null object reference
You need to initialize imgButton
.