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.

Mr

SAM Team--Southside High School's STEM and Computer Science extra-curricular club (Mr. Rogers Sponsor)

Android Developer Site

Mr. Rogers' Twitter Site

Mr. Rogers Teacher's Blog

Mr. Rogers T-shirts

Check out other web sites created by Mr. R:

 
Want to learn more about movie physics in Star Trek and find out :
  • what makes Star Trek unique
  • how Star Trek compares to Star Wars
  • why the star ship Enterprise needs to remain in space
  • what should and shouldn't be done in space battles
  • what it takes to blast off and travel the galaxy
  • the basics of orbiting
Insultingly Stupid Movie Physics is one of the most humorous, entertaining, and readable physics books available, yet is filled with all kinds of useful content and clear explanations for high school, 1st semester college physics students, and film buffs.

It explains all 3 of Newton's laws, the 1st and 2nd laws of thermodynamics, momentum, energy, gravity, circular motion and a host of other topics all through the lens of Hollywood movies using Star Trek and numerous other films.

If you want to learn how to think physics and have a lot of fun in the process, this is the book for you!

 

First the web site,

now the book!


Mr. Rogers Home | Common Sylabus | AP Comp Sci I | AP Comp Sci II | AP Physics Mech | AP Physics E&M | AP Statistics | IB Design Tech | Southside

[ Intuitor Home | Physics | Movie Physics | Chess | Forchess | Hex | Intuitor Store |

Copyright © 1996-2010 T. K. Rogers, all rights reserved. Forchess ® is a registered trademark of T. K. Rogers.
No part of this website may be reproduced in any form, electronic or otherwise, without express written approval.