Mr

 Mr. Rogers' IB Computer Science -- Android SmartPhone Programming Project
Help boost K-12 science, math, and computer education. Donate your obsolete Android phone to us (see below)! We promise to put it to good use in a classroom.

Mr Rogers Android Project Menu

Home

Projects

2010-2011


   3D Compass

   3D Accelerometer

   Friction Tester

   Drum

   Spherical Game

   Level

 


Greenville, SC

 

Spherical: A New Game for Android Devices

Description:

This application is a game that utilizes the android touch screen and gyroscope. The application is purely for entertainment purposes. The Hardwares Class creates the program and the pause menu for selecting difficulty. The Panel class creates the GUI, the sphere objects, and controls the operations of the game. The Circle class provides a template for the objects of the game.

       

Screenshot:

The yellow circle is the golden piece. The farthest right of the 3 larger spheres is the grey sphere. The other two large spheres are user-controlled. Part of the challenge is remembering which sphere is controlled by touch and which by tilt.

Features:

  • Utilizes gyroscope and touch screen
  • 3 levels of difficulty
  • User friendly
Version:

1.0

Future Plans:

Music and a high score feature.

Instructions:

Tap the screen to begin. One white sphere is controlled by touch. Tap the screen to have that sphere travel to that point. The other white sphere is controlled by tilting the device. The object of the game is collect as many golden pieces as possible without having either white sphere hit the continuously moving gray sphere.


Source Code:

Hardwares Class

C:\Programs\gVimPortable\Untitled.html
 

package com.random.name;   
import android.app.Activity;
import android.app.AlertDialog; 
import android.content.DialogInterface; 
import android.content.pm.ActivityInfo; 
import android.os.Bundle; 
import android.view.Menu; 
/**Starts the program and creates a difficulty menu 
 *  
 * @Akshay Chandrasekhar         
 * 10/23/10 
 */ 
public class Hardwares extends Activity { 
  
    public Panel p;
    
    /**Preconditions: Bundle to pass to Activity constructor
     * Postconditions: Starts Program and sets the view as
     * the Panel class
     */
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        p = new Panel(this);
        setContentView(p);
    }  
      
    /**Preconditions: DefaultMenu that is given when menu button 
     * is pressed.
     * Postconditions: Brings up an alert dialog to change the difficulty.
     */
    public boolean onPrepareOptionsMenu(Menu m) {  
        p.pause=true;  
                p.adb2 = new AlertDialog.Builder(this);  
                p.adb2.setMessage("What's your game?");  
                p.adb2.setNegativeButton("Insane", new DialogInterface.OnClickListener() {                                  
                        public void onClick(DialogInterface dialog, int which) {  
                                        p.difficulty = "Hard";  
                                        p.pause=false;  
                        }  
                });  
            p.adb2.setPositiveButton("Easy", new DialogInterface.OnClickListener() {  
                public void onClick(DialogInterface dialog, int id) {  
                                p.difficulty = "Easy";  
                                p.pause=false;  
                }  
            });  
            p.adb2.setNeutralButton("Medium", new DialogInterface.OnClickListener() {  
                public void onClick(DialogInterface dialog, int id) {  
                                p.difficulty = "Medium";  
                                p.pause=false;  
                }  
            });  
            AlertDialog adg = p.adb2.create();  
            adg.setTitle("Difficulty");  
            adg.show();  
                return true;  
        }  
}  

The onPrepareOptionsMenu(Menu m) method is called when the menu button on the phone is pressed. The OnCreate(Bundle savedInstanceState) is automatically called when the program starts.


 

Panel Class*

(*for reference, the sphere moved by the screen’s tilt is the first sphere, the sphere moving towards a point touched on the screen is the second sphere, and the grey sphere is the bouncing sphere)

F:\Computer science 2\Hardware\src\com\random\name\Panel.java.html




package com.random.name;    
import android.app.Activity;  
import android.app.AlertDialog;  
import android.content.Context;  
import android.content.DialogInterface;  
import android.content.pm.ActivityInfo;  
import android.graphics.Canvas;  
import android.graphics.Color;  
import android.graphics.Paint;  
import android.graphics.PointF;  
import android.hardware.Sensor;  
import android.hardware.SensorEvent;  
import android.hardware.SensorEventListener;  
import android.hardware.SensorManager;  
import android.os.CountDownTimer;  
import android.view.MotionEvent;  
import android.view.View;  
import android.view.View.OnTouchListener;  
/**Draws, moves, and controls all parts of GUI  
 *   
 * @Akshay Chandrasekhar  
 * 10/23/10  
 */  
  
public class Panel extends View implements OnTouchListener,SensorEventListener{  
        private Panel yes;  
        private CountDownTimer count;  
        private int z = 0, score = 0;  
        public boolean brighten = false, over = false, start = false, pause=false;  
        Paint p = new Paint();  
        public Circle [] c = new Circle[4];      
        public float [] f = new float[4];  
    int x2 = 0, y2 = 0;  
    public float dx, dy;  
    PointF co;  
    AlertDialog.Builder adb, adb2;  
    public Activity act;  
    public String e = "Easy",m="Medium", h="Hard", difficulty="Medium";  
      
    /**Preconditions: Context is that of the Activity Hardwares  
     * Postconditions: Initializes sensors, objects, and the timer   
     */  
        public Panel(Context context) {  
                super(context);  
                act = (Activity)context;  
                yes=this;  
                  
                setFocusable(true);  
                //Timer that serves as a repaint  
                count = new CountDownTimer(20, 1) {  
                        public void onTick(long f) {}  
                        public void onFinish() {  
                                yes.invalidate();  
                                restart();  
                        }  
                };   
                count.start();  
                //more initialization of variables and sensors   
                setOnTouchListener(this);  
                SensorManager m = (SensorManager) this.getContext().getSystemService(Context.SENSOR_SERVICE);  
                Sensor s = m.getDefaultSensor(Sensor.TYPE_ORIENTATION);  
                m.registerListener(this, s, SensorManager.SENSOR_DELAY_FASTEST);  
                c[0] = new Circle(20,50,250);  
                c[1] = new Circle(20,100,100);  
                c[2] = new Circle(20,0,0);  
                c[3] = new Circle(10,0,0);  
                for(int j=0; j<f.length; j++)  
                        f[j] = 0;  
        }  
          
        /**Preconditions: View of the program and a MotionEvent triggered  
         * in the program  
         * Postconditions: Brightens screen according to touch and sets the   
         * coordintes for the second sphere to go.  
         */  
        public boolean onTouch(View v, MotionEvent m) {  
                if(m.getAction() == MotionEvent.ACTION_DOWN) {  
                        co = new PointF(m.getX(), m.getY());  
                        dx=co.x-c[1].x;  
                        dy=co.y-c[1].y;  
                        brighten=true;  
                }  
                if(m.getAction() == MotionEvent.ACTION_UP)  
                        brighten=false;  
                if(m.getAction() == MotionEvent.ACTION_MOVE) {  
                }                 
                start=true;  
                return true;    
        }  
          
        /**Preconditions: Canvas of the view  
         * Postconditions: Draws the spheres and calls the methods that   
         * orchestrate the game's logistics.  
         */  
        public void onDraw(Canvas canvas) {  
                super.onDraw(canvas);  
                if (over)   
                        over();  
                else {  
                if(difficulty.equals(m))  
                        c[2].amount=4;  
                if(difficulty.equals(h))  
                        c[2].amount=8;  
                if(difficulty.equals(e))  
                        c[2].amount=2;  
                x2= getWidth();  
                y2 = getHeight();       
                int k = Color.rgb(z, z,z);  
        canvas.drawColor(k);  
        int f = Color.rgb(255, 255, 255);  
        p.setColor(f);  
        if(start) {  
                moove();  
        }  
            canvas.drawCircle(c[0].x, c[0].y, 20,p);  
            canvas.drawCircle(c[1].x,c[1].y,20,p);  
            f=Color.YELLOW;  
            p.setColor(f);  
        canvas.drawCircle(c[3].x,c[3].y,c[3].r, p);  
            f=Color.rgb(130, 130, 130);  
            p.setColor(f);  
            canvas.drawCircle(c[2].x,c[2].y, 20, p);  
            if(start) {  
                if(co!=null)  
                        if((c[1].x<(co.x-10)||c[1].x>(co.x+10))&&(c[1].y<(co.y-10)||c[1].y>(co.y+10)))  
                                moveTo();  
                if(!pause)  
                        c[2].rebound(x2,y2);  
                bright();  
                check();  
                check2();  
                }  
                }  
        }  
          
        /**Preconditions:  
         * Postconditions: Restarts the timer  
         */  
        public void restart() {  
                count.start();  
        }  
          
        /**Preconditions:  
         * Postconditions: moves the first sphere  
         */  
        public void moove() {  
                if(c[0].x>=20 && (c[0].x+20)<=x2)  
                c[0].x+=f[0];  
        if(c[0].x<20)  
                c[0].x=20;  
        if((c[0].x+20)>x2)  
                c[0].x=x2-20;  
          
        if(c[0].y>=20 && (c[0].y+20)<=y2)  
                c[0].y+=f[1];  
        if(c[0].y<20)  
                c[0].y=20;  
        if((c[0].y+20)>y2)  
                c[0].y=y2-20;  
        }  
          
        /**Preconditions:  
         * Postconditions: Resets all values when the game restarts  
         */  
        public void restart2() {  
                c[0].x=50;  
                c[0].y=250;  
                c[1].x=100;  
                c[1].y=100;  
                c[2].x=(float) (Math.random()*x2);  
                c[2].y = (float)(Math.random()*y2);  
                c[3].x= (float)(Math.random()*(getWidth()-c[3].r));  
                c[3].y=(float)(Math.random()*(getHeight()-c[3].r));     
                f[0]=0;  
                f[1]=0;  
                f[2]=0;  
                f[3]=0;  
                score=0;  
                start=false;  
                if(co!=null) {  
                        co.x=100;  
                        co.y=100;  
                }  
                z=0;  
        }  
        /**Preconditions:  
         * Postconditions: Brightens or Darkens the screen according to   
         * touch  
         */  
        public void bright() {  
                if(brighten && !(z==255))  
                z++;  
        else  
                if(z>0)  
                        z--;  
        }  
        /**Preconditions:   
         * Postconditions: Moves the second sphere.  
         */  
        public void moveTo() {  
                c[1].x+=dx/20.0;  
                c[1].y+=dy/20.0;  
        }  
  
        /**Preconditions:  
         * Postconditions: Checks if either of the two balls are hit by the   
         * bouncing ball  
         */  
        public void check() {  
                PointF coor = new PointF(c[2].x+20, c[2].y+20);  
                if(Math.sqrt(Math.pow(((c[1].x+20)-coor.x), 2) + Math.pow(((c[1].y+20)-coor.y),2))<37)   
                        over=true;  
                if(Math.sqrt(Math.pow(((c[0].x+20)-coor.x), 2) + Math.pow(((c[0].y+20)-coor.y),2))<37)   
                        over=true;     
        }  
          
        /**Preconditions:  
         * Postconditions: Checks if either ball gets the golden piece  
         */  
        public void check2() {  
                PointF coor2 = new PointF(c[3].x+10, c[3].y+10);  
                if(Math.sqrt(Math.pow(((c[1].x+20)-coor2.x), 2) + Math.pow(((c[1].y+20)-coor2.y),2))<37) {  
                        score+=10;  
                        c[3].x= (float)(Math.random()*(getWidth()-c[3].r));  
                        c[3].y=(float)(Math.random()*(getHeight()-c[3].r));  
                }  
                if(Math.sqrt(Math.pow(((c[0].x+20)-coor2.x), 2) + Math.pow(((c[0].y+20)-coor2.y),2))<37) {  
                                score+=10;  
                                c[3].x= (float)(Math.random()*(getWidth()-c[3].r));  
                                c[3].y=(float)(Math.random()*(getHeight()-c[3].r));  
                }  
        }  
        @Override  
        public void onAccuracyChanged(Sensor sensor, int accuracy) {  
        }  
          
        /**Preconditions: A triggered SensorEvent by the device  
         * Postconditions: sets the values for the first sphere to move  
         */  
        public void onSensorChanged(SensorEvent event) {  
                f[0]=(float)(Math.sin(Math.toRadians(event.values[2]))*-9.8*1.5);  
                f[1]=(float)(Math.sin(Math.toRadians(event.values[1]))*-9.8*1.5);  
        }  
        /**Preconditions:the dimensions of the new and old view sizes  
         * Postconditions: initializes the random positions of the bouncing  
         * sphere and the golden piece  
         */  
        public void onSizeChanged(int oldwidth, int oldheight, int newwidth, int newheight) {  
                c[2].x= (float)(Math.random()*(getWidth()-c[2].r));  
                c[2].y=(float)(Math.random()*(getHeight()-c[2].r));  
                c[3].x= (float)(Math.random()*(getWidth()-c[3].r));  
                c[3].y=(float)(Math.random()*(getHeight()-c[3].r));             
        }  
          
        /**Preconditions:  
         * Postconditions: Creates an alert dialog letting the user choose  
         * to restart or quit the game when it is over  
         */  
        public void over() {  
                adb = new AlertDialog.Builder(act);  
                adb.setMessage(difficulty + " Score: " + score);  
                adb.setPositiveButton("Restart", new DialogInterface.OnClickListener() {                            
                        public void onClick(DialogInterface dialog, int which) {  
                                act.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);  
                                over=false;  
                                restart2();  
                                count.start();  
                        }  
                });  
            adb.setNegativeButton("Quit", new DialogInterface.OnClickListener() {  
                public void onClick(DialogInterface dialog, int id) {  
                                act.finish();  
                                }  
            });  
            AlertDialog adg = adb.create();  
            adg.setTitle("GAME OVER");  
            adg.show();  
            count.cancel();  
        }  
}  

The countdown timer constantly updates the GUI by callling the onDraw(Canvas canvas) method repeatedly which in turn calls methods like check(), check2(), and bright(). When the screen is touched, the onTouch(View v, MotionEvent m)  method is called. Similarly, when the tilt of the screen is changed in any of the 3 axes, the onSensorChanged(SensorEvent event) method is called. Finally the onSizeChanged(int oldwidth, int oldheight, int newwidth, int newheight) method is called to initialize two of the circles because in this method, getWidth() and getHeight() are first defined.


 

Circle Class

 
F:\Computer science 2\Hardware\src\com\random\name\Circle.java.html




package com.random.name;  
/**Creates a circle object and a method to have the circle   
 * rebound  
 * @Akshay Chandrasekhar  
 * 10/23/10  
 */  
public class Circle {  
          
        public float x;  
        public float y;  
        public int changex;  
        public int changey;  
        public int r;  
        public boolean hitx, hity;  
        public float amount;  
          
        /**Preconditions: radius of the sphere, x position of the sphere, and  
         * y position of the sphere  
         * Postconditions: Intializes the spheres's preconditions with their  
         * respective fields  
         */  
        public Circle(int radius, float a, float b) {  
                r=radius;  
                x=a;  
                y=b;  
        }  
  
        /**Preconditions: width of view, height of view  
         * Postconditions: makes a circle object continuously rebound off the   
         * edge of the screen  
         */  
   public void rebound(int w, int h) {  
                if(x<0)  
                hitx=false;  
        if(x>w-r)  
                hitx=true;  
        if(y<r)  
                hity=false;  
        if(y>h-r)  
                hity=true;  
        if(hitx)  
                x-=amount;  
        else  
                x+=amount;  
        if(hity)  
                y-=amount;  
        else  
                y+=amount;  
        }  
}  

 

All 4 objects are Circle objects. Only the grey sphere utilizes the rebound method.

 

About the Author:

Akshay Chandrasekhar is a junior at Southside High School in Mr. Roger's IB Computer Science Class. He enjoys programming games, graphics, and useful everyday applications.


Warning: include(footerMrRstudentsAndroid.htm): failed to open stream: No such file or directory in /home/intuitor/intuitor.com/student/Comp Sci I Objectives/AP Com Sci Q2/Android Phone Site/AkshayAndroid1.php on line 527

Warning: include(): Failed opening 'footerMrRstudentsAndroid.htm' for inclusion (include_path='.:/usr/local/lib/php:/usr/local/php5/lib/pear') in /home/intuitor/intuitor.com/student/Comp Sci I Objectives/AP Com Sci Q2/Android Phone Site/AkshayAndroid1.php on line 527