我发现了一个非常讨厌的问题。我在android中制作吃豆人。游戏活动有一些孩子,最重要的两个是GameView(位于SurfaceView中)和TextView,当吃豆人吃托盘,水果或其他类似事件时,TextView应该更新。
已经说了,让我们详细看。
首先是PlayActivity代码
package com.example.pacman;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class PlayActivity extends AppCompatActivity {
private TextView playerNickname;
private TextView score;
private TextView maxScore;
private SurfaceView gameSurfaceView;
private GameView gameView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Modified code
setContentView(R.layout.activity_game);
//we get text view that we will use
playerNickname=(TextView) this.findViewById(R.id.tv_player);
score=(TextView) this.findViewById(R.id.tv_current_score);
maxScore=(TextView) this.findViewById(R.id.tv_current_max_score);
gameSurfaceView= (GameView) this.findViewById(R.id.game_view);
//set text view initial values
playerNickname.setText(getIntent().getExtras().getString("playerNickname"));
score.setText("0");
maxScore.setText("To modify");
this.gameView=new GameView(gameSurfaceView.getContext());
this.gameView.setScoreTv(this);
this.gameSurfaceView.getHolder().addCallback(this.gameView);
}
protected void onResume(){
super.onResume();
this.gameView.resume();
}
protected void onPause(){
super.onPause();
this.gameView.pause();
}
}
现在带有构造函数的Gamview和
package com.example.pacman;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.TextView;
import androidx.annotation.RequiresApi;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Semaphore;
public class GameView extends SurfaceView implements Runnable, SurfaceHolder.Callback, GestureDetector.OnGestureListener {
private static final float SWIPE_THRESHOLD = 2;
private static final float SWIPE_VELOCITY = 2;
private GestureDetector gestureDetector;
private Thread thread; //game thread
private TextView scoreTv;
private double score;
private Semaphore drawSemaphore;
private int[][] map;
private CountdownBonusThread bonusCounter;
private int xPosBonus; //Added
private int yPosBonus; //Added
private int bonusResetTime = 5000;
private boolean bonusAvailable;
private SurfaceHolder holder;
private boolean canDraw = false;
private Paint paint;
private List<Node> path;
private int screenWidth; // Ancho de la pantalla
private int blockSize;
private static int movementFluencyLevel=8; //this movement should be a multiple of the blocksize, if note the pacman will pass walls
private CountdownGhostsState stateCounter;
private Ghost[] ghosts = new Ghost[4];
private Bitmap[] pacmanRight, pacmanDown, pacmanLeft, pacmanUp;
private Bitmap cherryBitmap;
int[] pacmanPos;
private int totalFrame = 4; // Cantidad total de animation frames por direccion
private int currentPacmanFrame = 0; // animation frame de pacman actual
private int currentArrowFrame = 0; // animation frame de arrow actual
private long frameTicker; // tiempo desde que el ultimo frame fue dibujado
private char direction = ' '; // direccion del movimiento, movimiento inicial nulo
private char nextDirection = ' '; // Buffer para la siguiente direccion de movimiento tactil
private char viewDirection = 'd'; // Direccion en la que pacman esta mirando
public GameView(Context context) {
super(context);
this.constructorHelper();
}
private void constructorHelper() {
this.gestureDetector = new GestureDetector(this);
this.setFocusable(true);
this.holder = getHolder();
this.holder.addCallback(this);
this.frameTicker = (long) (1000.0f / totalFrame);
this.map=this.loadOriginalMap();
this.screenWidth = getResources().getDisplayMetrics().widthPixels;
this.blockSize = ((this.screenWidth/this.map[0].length)/movementFluencyLevel)*movementFluencyLevel;
this.holder.setFixedSize(blockSize*this.map[0].length,blockSize*this.map.length);
this.map=loadOriginalMap();
paint = new Paint();
paint.setColor(Color.WHITE);
this.score=0;
this.pacmanPos=new int[2];
this.pacmanPos[0]=14*blockSize; //posX
this.pacmanPos[1]=23*blockSize; //posY
bonusCounter = new CountdownBonusThread(this);
loadBitmapImages();
}
public void setScoreTv(Context parentContext) {
this.scoreTv=(TextView) ((Activity) parentContext).findViewById(R.id.tv_current_score);
}
在游戏视图的最后一个方法中,分配为null,结果是当我尝试编辑文本时显示下一条消息:
E / AndroidRuntime:致命例外:线程5
处理:com.example.pacman,PID:12235
java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法'void android.widget.TextView.setText(java.lang.CharSequence)'
在com.example.pacman.GameView.movePacman(GameView.java:227)]中>
在com.example.pacman.GameView.run(GameView.java:163)]中>
在java.lang.Thread.run(Thread.java:919)
我不理解为什么如果我给setTextView分配了发送父级上下文,有什么建议吗?
我发现了一个非常讨厌的问题。我在android中制作吃豆人。游戏活动有一些子级,最重要的两个是GameView(位于SurfaceView中)和TextView,它们应为...
而不是将上下文传递给setScoreTV(Context ..)您可以传递已经拥有的参考textView。
在PlayActivity中,您获得了textView参考: