我真的有线问题..我在谷歌和这里搜索了很多并且无法解决我的问题。 我有主要活动创建和启动3个线程(现在只有“gameThread”相关)。
当我点击后面的按钮似乎没问题,但是当我回到活动并且线程继续运行时,它似乎运行重复 - 我在屏幕上只看到一个ContentView,但还有更多的正在运行(也许落后)。 我希望我解释一下myselg好......
这是代码:
package com.example.newpingpong;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.widget.Toast;
/*
* The main activity class of the Ping Pong game
*/
public class MainActivity extends Activity
{
/*
* The following class variables hold references to the objects the game is composed of -
* PingPongView - main view,
* gameBall - the ball in the game,
* gamePaddle - the paddle in the game,
* gameThread - main thread updating the position of the ball,
* paddleMoverThread - another thread which is responsible for moving the paddle.
*/
private PingPongView gameView;
private Tray gamePaddle;
private GameLevel gameLevel;
private GameLevel [] levels;
//threads
private PingPongGame gameThread;
private PaddleMover paddleMoverThread;
private PresentThread giftThread;
private Messages message;
//balls container
private BallView [] ballViewArr;
private Ball [] ballArr;
//gifts container
private Gift[] giftArr;
private GiftView[] GiftViewArr;
public GameSounds gameSounds;
private int screenWidth;
private int screenHeight;
private TrayView paddleView;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
Toast.makeText(this, "onCreate!", Toast.LENGTH_SHORT).show();
// Get the message from the intent
Intent intent = getIntent();
String levelChosed = intent.getStringExtra(ImageAdapter.EXTRA_MESSAGE);
int levelChosed_int = Integer.parseInt(levelChosed);
Const.currentLevel = levelChosed_int;
Const.isCompleteThisLevel = false;
GameLevelView gameLevelView;
//for sounds
if(gameSounds == null){
gameSounds = new GameSounds();
gameSounds.addSound(Const.CATCH_GIFT, R.raw.cathc_gift, getBaseContext());
gameSounds.addSound(Const.GIFT_START_FALL, R.raw.gift_start_fall, getBaseContext());
gameSounds.addSound(Const.HIT_BLOCK, R.raw.hit_block, getBaseContext());
gameSounds.addSound(Const.HIT_KIR, R.raw.hit_kir, getBaseContext());
gameSounds.addSound(Const.GAME_OVER, R.raw.game_over, getBaseContext());
gameSounds.addSound(Const.HIT_PADDLE, R.raw.hit_paddle, getBaseContext());
}
if(this.ballViewArr == null){
this.ballViewArr = new BallView[Const.MAX_BALLS];
this.ballArr = new Ball[Const.MAX_BALLS];
this.giftArr = new Gift[Const.MAX_GIFTS];
this.GiftViewArr = new GiftView[Const.MAX_GIFTS];;
// Getting the screen width & height
screenWidth = this.getWindowManager().getDefaultDisplay().getWidth();
screenHeight = this.getWindowManager().getDefaultDisplay().getHeight();
for(int i=0 ; i< Const.MAX_BALLS ; i++){
this.ballArr[i] = new Ball(screenWidth / 2, screenHeight / 2, screenWidth, screenHeight);
this.ballViewArr[i] = new BallView(this, this.ballArr[i]);
this.ballArr[i].setMode(Const.NOT_ACTIVE);
}
this.ballArr[0].setMode(Const.ACTIVE);
for(int i=0 ; i< Const.MAX_GIFTS ; i++){
this.giftArr[i] = new Gift(screenWidth / 2, screenHeight / 4,screenWidth, null, Const.NOT_ACTIVE);
this.GiftViewArr[i] = new GiftView(this, this.giftArr[i]);
}
// Creating the paddle
gamePaddle = new Tray(screenWidth / 2, (int)(screenHeight * 0.75), screenWidth);
// Creating the paddle view, and giving it the gameBall as a parameter
paddleView = new TrayView(this, gamePaddle);
levels = new GameLevel[Const.LevelsAmount];
levels[0] = new GameLevel(Const.level0, screenWidth , screenHeight, this.giftArr);
levels[1] = new GameLevel(Const.level1, screenWidth , screenHeight, this.giftArr);
levels[2] = new GameLevel(Const.level2,screenWidth , screenHeight, this.giftArr);
}
gameLevel=levels[levelChosed_int];
gameLevelView = new GameLevelView(this,gameLevel);
// Creating the game view
this.gameView = new PingPongView(this);
message = new Messages(this , screenWidth , screenHeight);
// Give the gameView our ballView & paddleView.
gameView.setViews(paddleView,gameLevelView , message ,this.ballViewArr , this.GiftViewArr);
// Setting the gameView as the main view for the PingPong activity.
setContentView(gameView);
if(gameThread == null){
//create the main thread
gameThread = new PingPongGame(this.getResources(), gamePaddle, gameView, gameLevel , message , ballArr , gameSounds);
//create the thread responsible for moving the paddle
paddleMoverThread = new PaddleMover(gamePaddle, gameView);
//create the thread responsible for present
giftThread = new PresentThread(gamePaddle , gameView , gameLevel, message , giftArr , ballArr,gameSounds );
gameThread.start();
paddleMoverThread.start();
giftThread.start();
}
}
//This method is automatically called when the user touches the screen
@Override
public boolean onTouchEvent(MotionEvent event)
{
float destination;
// Toast.makeText(this, "try!", Toast.LENGTH_SHORT).show();
//get the x coordinate of users' press
destination = event.getX();
//notify the paddle mover thread regarding the new destination
gamePaddle.setPaddleDestination(destination);
return true;
}
@Override
protected void onPause() {
Toast.makeText(this, "onPause!", Toast.LENGTH_SHORT).show();
Const.toStop = true;
while(Const.toStopMessageHasRecieved == false){
} //the thread not see the message that he shoult stop
//here the thrad recived the message and stoped.
super.onPause();
}
@Override
public void onResume()
{
Toast.makeText(this, "onResume!", Toast.LENGTH_SHORT).show();
for(int i=0 ; i< Const.MAX_BALLS ; i++){
this.ballArr[i] = new Ball(screenWidth / 2, screenHeight / 2, screenWidth, screenHeight);
this.ballViewArr[i] = new BallView(this, this.ballArr[i]);
this.ballArr[i].setMode(Const.NOT_ACTIVE);
}
this.ballArr[0].setMode(Const.ACTIVE);
synchronized (Const.mPauseLock) {
Const.toStop = false;
Const.mPauseLock.notifyAll();
}
super.onResume();
}
}
和THE THREAD:
package com.example.newpingpong;
import android.content.res.Resources;
import android.graphics.Color;
public class PingPongGame extends Thread {
private PingPongView gameView;
private Tray gamePaddle;
private GameLevel gameLevel;
private Messages message;
private Ball [] ballArr;
private GameSounds gameSounds;
private Resources res;
//private int screenWidth;
//private int screenHight;
public PingPongGame(Resources res ,Tray theTray , PingPongView mainView , GameLevel gameLevel ,
Messages message , Ball ballArr[] ,GameSounds gameSounds)
{
this.gameView = mainView;
this.ballArr = ballArr;
this.gamePaddle = theTray;
this.gameLevel=gameLevel;
this.message = message;
this.gameSounds=gameSounds;
this.res=res;
//this.screenWidth = screenWidth;
//this.screenHight = screenHight;
//for stop and resume threads
}
//main method of the current thread
@Override
public void run()
{
try {
PingPongGame.sleep(2000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
this.message.setMessage(res.getString(R.string.lives) + gameLevel.getLives());
gameView.postInvalidate();
//infinitely loop, and move the balls accordingly
while ((Const.isLose == false) && (Const.isCompleteThisLevel==false))
{
for(int i=0; i<Const.MAX_BALLS ; i++){
if(ballArr[i].getMode() != Const.NOT_ACTIVE){
//move the ball one step
if(ballArr[i].move()) //hit kir
gameSounds.play(Const.HIT_KIR,false);
gameView.postInvalidate();
//check if the ball hit some block
if(gameLevel.updateIfHit(ballArr[i])){
ballArr[i].down();
gameSounds.play(Const.HIT_BLOCK,false);
}
gameView.postInvalidate();
if(gameLevel.getLives() == 0){
//gameLevel.restart();
this.message.setMessage(res.getString(R.string.game_over));
gameView.postInvalidate();
gameSounds.play(Const.GAME_OVER,false);
Const.isLose = true;
try
{
PingPongGame.sleep(2000);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
//check if the ball has reached the paddle
if(checkHitPaddle(i,ballArr[i]) == true){ //משתמש פספס and lives --
this.message.setMessage(res.getString(R.string.lives)+"" + gameLevel.getLives());
//send a request to refresh the display
gameView.postInvalidate();
}
}
}
try
{
PingPongGame.sleep(5);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
//public static boolean toStop = false;
//public static boolean toStopMessageHasRecieved = false;
//for stop and resume
//for stop and resume
synchronized (Const.mPauseLock) {
while (Const.toStop) {
Const.toStopMessageHasRecieved = true;
try {
Const.mPauseLock.wait();
} catch (InterruptedException e) {
}
}
}
}
// Const.toStopMessageHasRecieved = true;
}
//This method is responsible for handling the situation in which the ball has reached the height of the paddle
//return true if lives--
private boolean checkHitPaddle(int i , Ball ball)
{
// Checking if the ball had hit the paddle
if (ball.getBottom() >= gamePaddle.getTop())
{
// check if the paddle is in the right place
if ((ball.getRight() > gamePaddle.getLeft()) &&
(ball.getLeft() < gamePaddle.getRight()))
{
//The ball had hit the paddle - so it should be bounced
gameSounds.play(Const.HIT_PADDLE,false);
ball.bounceUp();
}
else
{
//The ball had missed the paddle - player looses - restart the game
gameSounds.play(Const.GAME_OVER,false); //not really game over - just lose live
boolean isMoreBall = false;
for(int j=0 ; j< Const.MAX_BALLS ; j++)
if( (j != i) && (ballArr[j].getMode() == Const.ACTIVE)){
isMoreBall = true;
break;
}
if(isMoreBall){
ball.setMode(Const.NOT_ACTIVE);
//for(int k=0; k<Const.MAX_BALLS ; k++){
//ballArr[k].downSpeed(0.25);
//}
}
else{
gameLevel.setLives(gameLevel.getLives()-1);
ball.restart();
return true;
}
}
}
return false;
}
}
答案 0 :(得分:0)
每次启动Activity时,都会在onCreate中创建一个新的gameThread,因为Activity是一个新对象,然后gameThread为null。但你永远不会阻止他们。你应该在onDestroy中插入一些结束你的线程的东西。
此时两个线程都会修改您的Const对象。这引出了我的主要问题: 我认为主要的问题是你的所有通信都是由Const对象中的一些“全局变量集合”处理的,这可能会让游戏变得越来越混乱。现在一个解决方案可能是让Const对象也处理Threads,但这可能只会让它在长期运行中变得更糟。
答案 1 :(得分:0)
尝试使用 计时器而不是线程。
使用onBackPressed()方法中的timer.cancel()取消计时器。