0

我真的遇到了问题..我在谷歌和这里搜索了很多,并没有解决我的问题。我有创建和启动 3 个线程的主要活动(现在只有“gameThread”相关)。

当我点击后面的按钮时,它似乎没问题,但是当我回到活动并且线程继续运行时,它似乎运行重复 - 我在屏幕上只看到一个 ContentView,但还有一个正在运行(可能在后面) . 我希望我能很好地解释我的自我..

这是代码:

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();       
    }

}

和线程:

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;
    }
}
4

2 回答 2

0

每次启动 Activity 时,您都会在 onCreate 中创建一个新的 gameThread,因为 Activity 是一个新对象,并且 gameThread 为空。但你永远不会阻止他们。您可能应该在 onDestroy 中插入一些结束线程的内容。

目前,两个线程都修改了您的 Const 对象。这让我想到了主要问题:我认为主要问题是你所有的通信都是由 Const 对象中的一些“全局变量集合”处理的,随着游戏变得越来越大,这可能会非常混乱。目前,一个解决方案可能是让 Const 对象也处理线程,但从长远来看,这可能只会让情况变得更糟。

于 2013-09-02T17:20:59.877 回答
0

尝试使用计时器而不是线程。

并在 onBackPressed() 方法中使用 timer.cancel() 取消计时器。

于 2013-09-02T17:24:16.143 回答