Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6937715
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 27, 20262026-05-27T12:23:58+00:00 2026-05-27T12:23:58+00:00

I’m new to both android and game development and have been trying to create

  • 0

I’m new to both android and game development and have been trying to create a pong clone to get to grips with everything. I have a “PongView” class which extends SurfaceView and a “PongThread” which extends thread.

I have found a way to detect if the ball or “bomb” has gotten past the paddle and reached the wall behind it. I’m not sure if my approach is the best (opinions welcome) but it seems to work as i have a little toast message displaying game over if it happens. Now i want to set it up so that, as well as displaying game over, the view restarts (or whatever the more appropriate term is) so that the bomb is in the center of the screen again and the user can play another round.

Due to inexperience im not really sure how i should handle the thread and what methods to call in the view to achieve this.

I’ve had several stabs at trying to figure it out but i have no idea if i’m on the right track, it’ll probably be pretty clear from my code that i don’t know what i’m doing. (at the moment my thread stops and my surface is just stuck displaying the last frame). Any advice will be welcome!

PongView.java: (scroll down to the update method to get to the section i’m trying to figure out)

package biz.hireholly.pirateponggame;

import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.widget.Toast;


public class PongView extends SurfaceView implements Callback{

    /*GLOBALS*/
    private static final String TAG = PongView.class.getSimpleName(); 
    private PongThread pongThread;
    private Bomb bomb;
    private Paddle paddleA;
    private int viewWidth;
    private int viewHeight;
    Handler handler;
    boolean gameOver;

    public PongView(Context context) {


        super(context);
        // sets current class as the handler for the events happening on the surface
        getHolder().addCallback(this);


        //instantiate thread, pass the current holder and view so that the thread can access them
        pongThread = new PongThread(getHolder(), this);

        //make the GameView focusable so it can handle events 
        setFocusable(true);

        handler = new Handler();
    }

    //CURRENTLY WHERE IM INITIALISING SPRITES
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {

        //INITIALISE viewWidth and viewHeight here
        //so that they can be passed as parameters
        viewWidth = getWidth();
        viewHeight = getHeight();


        //NEW BOMB, INITIAL BITMAP
        bomb = new Bomb(BitmapFactory.decodeResource(
                getResources(), R.drawable.bombsprite),
                getWidth() /2, getHeight() /2); //draws in middle
        //bombs random starting direction
        bomb.getSpeed().randomiseDirection();

        //NEW PADDLE, INITIAL BITMAP
        paddleA = new Paddle(BitmapFactory.decodeResource(
                        getResources(), R.drawable.paddlesprite),
                        getWidth() /2, getHeight() -(getHeight()/30) ); //middle bottom screen
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        pongThread = new PongThread(getHolder(), this); //needed if user exits and returns
        pongThread.setRunning(true);
        //.start() == PongThread.run() except PongThread does all the work
        pongThread.start();
    }


    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        boolean retry = true;
        while(retry){
            try{
                //tells thread to shut down and waits for it to finish. Clean shutdown
                pongThread.setRunning(false);
                pongThread.join();
                retry = false;
            } catch(InterruptedException e){
                //try again shutting down the thread
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        paddleA.onTouchEvents(event, viewWidth);

        return true;
    }


    /**
     * CHECKS FOR COLLISIONS, CALLS OBJECT UPDATE METHODS
     */
    public void update(){

        gameOver = false;

        //CHECK IF NULL as objects aren't created till surface change 
        if(bomb != null && paddleA != null){

            bomb.handlePaddleCollision(paddleA); 
            gameOver = bomb.handleWallCollision(viewWidth, viewHeight); 

            //object physics updates
            bomb.update();
            //paddleA.update();
        }

        //WHEN handleWallColision returns true, one player scored and its game over.
        if( gameOver ){


            //handler is needed as alerts and toasts can only be made in the ui thread, 
            handler.post(new Runnable(){
                public void run(){
                    Toast.makeText(getContext(), "GAME OVER", Toast.LENGTH_LONG).show();
                }
            });

            /*THIS IS WHERE I'M TRYING TO RESTART THE GAME*/
            ///////////////////////////////////////////////////////
            //could maybe call surfaceDestroyed here instead?
            boolean retry = true;
            while(retry){
                try{
                    //tells thread to shut down and waits for it to finish. Clean shutdown
                    pongThread.setRunning(false);
                    pongThread.join();
                    retry = false;
                } catch(InterruptedException e){
                    //try again shutting down the thread
                }
            }

            //copied from surfaceCreated
            pongThread = new PongThread(getHolder(), this); //needed if user exits and returns
            pongThread.setRunning(true);
            //.start() == PongThread.run() except PongThread does all the work
            pongThread.start();

            ////////////////////////////////////////////////////////
        }
    }

    protected void render(Canvas canvas)
    {
        canvas.drawColor(Color.GREEN);
        bomb.draw(canvas);
        paddleA.draw(canvas);
    }

}

PongThread.java:

package biz.hireholly.pirateponggame;

import android.graphics.Canvas;
import android.util.Log;
import android.view.SurfaceHolder;

public class PongThread extends Thread {

    /*GLOBALS*/
    private static final String TAG = PongThread.class.getSimpleName();
    //desired frames per second
    private final static int MAX_FPS = 30;
    //maximum number of frames to be skipped if drawing took too long last cycle
    private final static int MAX_FRAME_SKIPS = 5;
    //cycle period (cycle = update,draw,if excess time sleep)
    private final static int CYCLE_PERIOD = 1000 / MAX_FPS;
    //Surface holder that can access the physical surface
    private SurfaceHolder surfaceHolder;
    //the view that actually handles inputs and draws to the surface
    private PongView pongView;
    //flag to hold game state
    private boolean running;    

    public void setRunning(boolean running){
            this.running = running;
    }

    /**Takes PongView instance and surfaceHolder as parameters
    * so that we can lock the surface when drawing.
    * @param surfaceHolder
    * @param pongView
    */
    public PongThread(SurfaceHolder surfaceHolder, PongView pongView){
        super();
        this.surfaceHolder = surfaceHolder;
        this.pongView = pongView;
    }

    @Override
    public void run(){
        //canvas is a surface bitmap onto which we can draw/edit its pixels
        Canvas canvas;
        Log.i(TAG, "Starting pong thread");

        long beginTime =0; // time when cycle began
        long timeDiff =0; // time it took for the cycle to execute
        int sleepTime =0; // milliseconds to sleep (<0 if drawing behind schedule) 
        int framesSkipped =0; // number of frames skipped

        while (running) {
            canvas = null;
            //try locking canvas, so only we can edit pixels on surface
            try{
                canvas = this.surfaceHolder.lockCanvas();
                //sync so nothing else can modify while were using it
                synchronized (surfaceHolder){ 
                    beginTime = System.currentTimeMillis();
                    framesSkipped = 0; //reset frame skips

                    //UPDATE game state
                    this.pongView.update();
                    //RENDER state to screen, draws the canvas on the view
                    this.pongView.render(canvas);

                    //calculate how long cycle took
                    timeDiff = System.currentTimeMillis() - beginTime;
                    //calculate potential sleep time
                    sleepTime = (int)(CYCLE_PERIOD - timeDiff);

                    //sleep for remaining cycle
                    if (sleepTime >0){
                        try{
                            //saves battery
                            Thread.sleep(sleepTime);
                        } catch (InterruptedException e){}
                    }

                    //if there's no leftover cycle time then we're running behind
                    while (sleepTime < 0 
                            && framesSkipped < MAX_FRAME_SKIPS){
                        //we need to catch up so we update without rendering
                        this.pongView.update();
                        sleepTime += CYCLE_PERIOD;
                        framesSkipped++;
                    }
                }
            } finally{
                //in case of exception, 
                //surface is not left in an inconsistent state
                if (canvas != null){
                    surfaceHolder.unlockCanvasAndPost(canvas);
                }
            }//end finally
        }
    }
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-27T12:23:58+00:00Added an answer on May 27, 2026 at 12:23 pm

    If you want to “reboot” the thread so to speak, you have two options. Either start a fresh thread every time the game is supposed to restart or construct your initial thread to loop indefinitely and wait to be notified when it is able to run. Like so:

    public void run() {
    
        while(true) {
            signal.wait();
    
            // your previous run code here
        }
    }
    

    In this scenario, you start the thread initially and then signal it to actually start with signal.notify() (signal must be an object visible to both threads). Then, when the game ends, the thread will return to the call to wait. Then simply notify it again in order to restart from the beginning.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a jquery bug and I've been looking for hours now, I can't
Basically, what I'm trying to create is a page of div tags, each has
I'm trying to create an if statement in PHP that prevents a single post
I am trying to loop through a bunch of documents I have to put
I'm new to using the Perl treebuilder module for HTML parsing and can't figure
link Im having trouble converting the html entites into html characters, (&# 8217;) i
I have just tried to save a simple *.rtf file with some websites and
I am trying to understand how to use SyndicationItem to display feed which is
this is what i have right now Drawing an RSS feed into the php,
I want use html5's new tag to play a wav file (currently only supported

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.