我试图学习表面视图,但确实读过它。

因此,我尝试制作一个游戏,我认为这将有助于我更好地学习。

我创建了一个如下所示的表面视图类:

class SnakeEngine extends SurfaceView implements Runnable,View.OnTouchListener {
    private Thread thread = null;
    private Context context;
    private SoundPool soundPool;
    private int eat_bob = -1;
    private int snake_crash = -1;
    private Rect rect2;
    private Rect rect1;
    private boolean snakeHungry=true;
    private boolean runThread=true;

    public enum Heading {UP, RIGHT, DOWN, LEFT}
    private Heading heading = Heading.RIGHT;
    private int screenX;
    private int screenY;
    private int snakeLength=1;

    private float x;
    private float y;
    private float bobX=0;
    private float bobY=0;
    private final int blockSize=40;
    private final int FPS = 10;
    private int score=0;
    private int[] snakeXs;
    private int[] snakeYs;
    private int xSpeed=FPS;
    private int yspeed=FPS;
    private boolean foodOnTable=false;
    private volatile boolean isPlaying=true;
    private SurfaceHolder surfaceHolder;
    private Paint paint;

    public SnakeEngine(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    public SnakeEngine(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

    }

    public SnakeEngine(Context context) {
        super(context);
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Display display = null;
        if (wm != null) {
            display = wm.getDefaultDisplay();
        }
        Point size = new Point();
        if (display != null) {
            display.getSize(size);
        }
        screenX = size.x;
        screenY = size.y;

        surfaceHolder=getHolder();
        setOnTouchListener(this);
        paint=new Paint();
        paint.setColor(Color.GREEN);
        snakeXs=new int[200];
        snakeYs=new int[200];
    }

    @Override
    public void run() {
        while (runThread) {

            try {
                long MILLIS_PER_SECOND = 20;
                Thread.sleep(MILLIS_PER_SECOND);
            } catch (InterruptedException e) {
                e.printStackTrace();
                thread.interrupt();
            }
            if(!surfaceHolder.getSurface().isValid())
                continue;
            Canvas canvas = surfaceHolder.lockCanvas();
            update();
            draw(canvas);
            surfaceHolder.unlockCanvasAndPost(canvas);
        }
    }

    public void resume() {
        thread=new Thread(this);
        thread.start();

    }


    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        canvas.drawColor(Color.argb(255, 26, 128, 182));
        int foodSize = 20;
        canvas.drawRect(x, y, (int) (x + foodSize), y + foodSize, paint);
        for (int i = 0; i < snakeLength; i++) {
            canvas.drawRect(snakeXs[i], snakeYs[i], snakeXs[i] + blockSize, snakeYs[i] + blockSize, paint);
        }
    }


    public void getLocation() {
        Random random = new Random();
        x= random.nextInt(screenX-blockSize);
        y= random.nextInt(screenY-blockSize);
    }

    private void update() {
        Log.e("here","here");
        if(!foodOnTable){
            getLocation();
            foodOnTable=true;
        }

        if(bobX<x && bobY<y && (bobX+blockSize)>x && (bobY+blockSize)>y){
            eatFood();
            getLocation();
            foodOnTable=true;
        }

        bobX+=xSpeed;
        bobY+=yspeed;


        moveSnake((int)bobX,(int)bobY);



        if(bobX+blockSize>=screenX || bobY+blockSize>=screenY ||
                (bobY+FPS<=0 && bobX!=0) || (bobX!=0 && bobY>=screenY) || (bobX==0 && bobY+FPS==0)
                ||(bobX+FPS==0 && bobY==0)|| (bobY!=0 && bobX+FPS<=0)){
            bobX-=xSpeed;
            bobY-=yspeed;
        }

    }

    private void moveSnake(int bobX,int bobY) {
        if (snakeHungry) {
            for (int i = 0; i < snakeLength - 1; i++) {
                snakeXs[i] = snakeXs[i + 1];
                snakeYs[i] = snakeYs[i + 1];
            }
        }else snakeHungry=!snakeHungry;
        snakeXs[snakeLength - 1] = bobX;
        snakeYs[snakeLength - 1] = bobY;
    }

    private void eatFood() {
        snakeLength++;
        snakeHungry=false;
    }

    public void pause() {
        if(thread!=null){
            runThread=false;
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void directSnake(Heading heading){
        switch (heading){
            case UP:
                xSpeed=0;
                yspeed=-FPS;
                break;
            case DOWN:
                xSpeed=0;
                yspeed=FPS;
                break;
            case LEFT:
                xSpeed=-FPS;
                yspeed=0;
                break;
            case RIGHT:
                xSpeed=FPS;
                yspeed=0;
                break;
        }
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        int x=(int)event.getX();
        int y=(int)event.getY();
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:{
                if(heading==Heading.LEFT || heading ==Heading.RIGHT){
                    if(y>(bobY+blockSize)){
                        directSnake(Heading.DOWN);
                        heading=Heading.DOWN;
                    }else {
                        directSnake(Heading.UP);
                        heading=Heading.UP;
                    }
                    break;

                }else if(heading==Heading.DOWN || heading==Heading.UP) {
                    if(x<(bobX+blockSize)){
                        directSnake(Heading.LEFT);
                        heading=Heading.LEFT;

                    }else {
                        directSnake(Heading.RIGHT);
                        heading=Heading.RIGHT;
                    }
                    break;
                }
                break;
            }
        }
        return true;
    }



}


我的mainactivity文件如下所示:

public class MainActivity extends AppCompatActivity {

    SnakeEngine snakeEngine;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        snakeEngine=new SnakeEngine(this);
        setContentView(R.layout.activity_main);
    }


    @Override
    protected void onResume() {
        super.onResume();
        snakeEngine.resume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        snakeEngine.pause();
    }
}


布局文件:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.snake.tilak.myapplication.MainActivity">
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <com.snake.tilak.myapplication.SnakeEngine
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/surfaceView">
            </com.snake.tilak.myapplication.SnakeEngine>
        <LinearLayout android:id="@+id/linearLayout1" android:layout_width="wrap_content" android:layout_height="wrap_content">
            <ImageButton android:contentDescription="@string/down_button" android:id="@+id/buttonDown" android:background="@mipmap/ic_keyboard_arrow_down_black_24dp" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
            <ImageButton android:contentDescription="@string/up_button"  android:id="@+id/buttonUp" android:background="@mipmap/ic_keyboard_arrow_up_black_24dp" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
            <ImageButton android:contentDescription="@string/left_button" android:id="@+id/buttonLeft" android:background="@mipmap/ic_keyboard_arrow_left_black_24dp" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
            <ImageButton android:contentDescription="@string/right_button"  android:id="@+id/buttonRight" android:background="@mipmap/ic_keyboard_arrow_right_black_24dp" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
        </LinearLayout>
    </FrameLayout>
</android.support.constraint.ConstraintLayout>


现在,当我运行它时,我只看到黑屏?

我哪里做错了 ?我应该改变什么?

我在这里阅读了有关此主题的各种问题,似乎无法使任何事情起作用。

最佳答案

那是因为您试图实例化新的SnakeEngine,但是您应该通过id找到它的实例,因为您已经将其添加到XML文件中:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // snakeEngine = new SnakeEngine(this);
    setContentView(R.layout.activity_main);
    snakeEngine = findViewById(R.id.surfaceView);
}


然后,在对其进行修复时,应将所有启动逻辑从public SnakeEngine(Context context)构造函数移至单独的方法,并从SnakeEngine的每个构造函数进行调用:

public SnakeEngine(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

public SnakeEngine(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init(context);
}

public SnakeEngine(Context context) {
    super(context);
    init(context);
}

private void init(Context context) {
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = null;
    if (wm != null) {
        display = wm.getDefaultDisplay();
    }
    Point size = new Point();
    if (display != null) {
        display.getSize(size);
    }
    screenX = size.x;
    screenY = size.y;

    surfaceHolder = getHolder();
    setOnTouchListener(this);
    paint = new Paint();
    paint.setColor(Color.GREEN);
    snakeXs = new int[200];
    snakeYs = new int[200];
}

10-04 11:58