我试图学习表面视图,我确实读过它。
所以,我尝试制作一款游戏,我认为这对我的学习有所帮助。
我创建了一个表面视图类,如下所示:
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>
现在,当我运行它时,我看到的只是一个黑屏?
我哪里出错了?我应该改变什么?
我在这里阅读了关于这个主题的各种问题,似乎无法发挥作用。
答案 0 :(得分:1)
那是因为您尝试实例化新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];
}