-4

I have been trying for some time now to get a variable from MySurfaceView to use in my Player class. I cant seem to make it work... I tried getting the touch information from my MainActivity class but it wasn't really where I wanted it and also couldn't seem to make it work. Any help is appreciated!

MySurfaceView.java

package com.Frenchie.SurfaceView;

import ...

public class MySurfaceView extends SurfaceView implements Runnable {

    Bitmap bitmap;
    SurfaceHolder surfaceHolder;
    int LastTouchx;

    Player player;

    public MySurfaceView(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);

        player = new Player(context);

        surfaceHolder = getHolder();

        //Starts the run()
        Thread TestThread = new Thread(this);
        TestThread.start();
    }


    @Override
    public void run() {
        //TODO movement here when display is working
        while (true){
            Update();
            DrawPlayer();
        }
    }

    public void Update(){
        player.Update();
    }

    public void DrawPlayer(){

        Canvas canvas = surfaceHolder.lockCanvas();

        if (surfaceHolder.getSurface().isValid()) {

            canvas.drawColor(Color.BLUE);
            canvas.drawBitmap(player.getBitmap(), player.getX(), player.getY(), null);
            surfaceHolder.unlockCanvasAndPost(canvas);
        }
        else{

            Log.d("DrawPlayer", "Surface Not Valid");
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        LastTouchx = (int)event.getX();
        //LastTouchy= (int)event.getY();
        Log.d("Touch Value ",LastTouchx+"");
        return false;
    }

    public int getLastTouchx() {
        return LastTouchx;
    }

}

Player.java

package com.Frenchie.SurfaceView;

import ...

public class Player {
    //Bitmap to get character from image
    private Bitmap bitmap;

    //coordinates
    private int x;
    private int y;

    //motion speed of the character
    private int speed = 0;

    MySurfaceView mySurfaceView;

    //constructor
    public Player(Context context) {
        x = 75;
        y = 500;

        //Getting bitmap from drawable resource
        bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.player);
    }

    //Method to update coordinate of character
    public void Update(){

        //updating x coordinate

        if (x > mySurfaceView.getLastTouchx()){
            x++;
        }
        else if (x < mySurfaceView.getLastTouchx()){
            x--;
        }
        else{

            Log.d("Update","Else triggered");
        }

    }

    public Bitmap getBitmap() {
        return bitmap;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }
}

Messages

E/AndroidRuntime: FATAL EXCEPTION: Thread-4
    Process: com.Frenchie.SurfaceView, PID: 26348
    java.lang.NullPointerException: Attempt to invoke virtual method 'int com.Frenchie.SurfaceView.MySurfaceView.getLastTouchx()' on a null object reference
        at com.Frenchie.SurfaceView.Player.Update(Player.java:36)
        at com.Frenchie.SurfaceView.MySurfaceView.Update(MySurfaceView.java:68)
        at com.Frenchie.SurfaceView.MySurfaceView.run(MySurfaceView.java:62)
        at java.lang.Thread.run(Thread.java:762)

This was not a duplicate of the post suggested.

Frenchie
  • 131
  • 1
  • 1
  • 9

2 Answers2

1

Override another constructor in your MySurfaceView:

    public class MySurfaceView extends SurfaceView
    ...
    public MySurfaceView(Context context) {
        this(context, (AttributeSet)null)
    }

    public MySurfaceView(Context context, AttributeSet attributeSet) {
            super(context, attributeSet);
            player = new Player(context, this);
            bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.player);
            surfaceHolder = getHolder();
            //Starts the run()
            Thread TestThread = new Thread(this);
            TestThread.start();
        }
        ...

In your player in constructor you can pass a surfaceView: so no need to initialize:

MySurfaceView mySurfaceView;

    //constructor
    public Player(Context context, MySurfaceView surfaceView) {
        this.mySurfaceView = surfaceView;
        x = 75;
        ...
Viktor Yakunin
  • 2,777
  • 3
  • 21
  • 34
  • Absolutely spot on thank you very much! Would you possibly be able to shed some light on how this works? Marking as right answer. – Frenchie Nov 29 '17 at 12:54
  • 1
    @Frenchie view itself is required to override parent's constructors. If you declared your custom view in xml then one of constructors with two and more params would be called by OS. Programmatically you create a view with simple constructor View(context) and setting attributes with setters. – Viktor Yakunin Nov 29 '17 at 14:20
  • 1
    @Frenchie Your player class depends on your surface view, so surfaceView should be created in your player class or injected using constructor, like I did it above. Probably the best way to do that is to change order and put your logic to Player and make SurfaceView simple – Viktor Yakunin Nov 29 '17 at 14:27
0

Try:

 MySurfaceView mySurfaceView = new MySurfaceView();
global_warming
  • 785
  • 1
  • 6
  • 10
  • When I replace the original call in my player class with this I get the following error: Error:(19, 35) error: constructor MySurfaceView in class MySurfaceView cannot be applied to given types; required: Context,AttributeSet found: no arguments reason: actual and formal argument lists differ in length – Frenchie Nov 29 '17 at 12:31
  • Try defining an empty constructor in `MySurfaceView.java` – global_warming Nov 29 '17 at 12:33
  • Whenever you override a view, you should override constructors too. in your player you didn't initialized mySurfaceView – Viktor Yakunin Nov 29 '17 at 12:33
  • Would you mind elaborating Viktor, I dont quite understand. Also I get the following message when I add an empty constructor to MySurfaceView: "There is no default constructor available in 'android.view.SurfaceView'" – Frenchie Nov 29 '17 at 12:41