Mr

 Mr. Rogers' IB Computer Science - Google 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

 

Akshay

Spherical: A New Game for Android Devices

 

This application is a game that utilizes the android touch screen and gyroscope. The object of the game is to collect as many golden pieces as possible. Each piece is 10 points. When a piece is collected, another one appears in another random part of the screen. Collecting the pieces must be done by touching the piece with either of the two white spheres. One of the spheres is controlled by tilting the screen where you want the sphere to roll. The other moves towards wherever you touch the screen. However, there will be a constantly bouncing grey sphere. If the grey sphere hits either one of the two white spheres, the game is over. The game starts when the screen is touched.

       

This is a screenshot of the game. 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.


 

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.


Hardwares Class

package com.random.name;

 

import android.app.Activity;

import android.app.AlertDialog;

import android.content.DialogInterface;

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;

   

   public void onCreate(Bundle savedInstanceState) {

           super.onCreate(savedInstanceState);

           p = new Panel(this);

           setContentView(p);

        }

        

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Creates and starts the program by instantiating the Panel class

   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;

   }

}

Creates a pause menu which lets the user choose the difficulty of the game.

 

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)

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];

   public 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";

   

 

   public Panel(Context context) {

           super(context);

           act = (Activity)context;

           yes=this;

           

           setFocusable(true);

 

           count = new CountDownTimer(20, 1) {

                   public void onTick(long f) {}

                   public void onFinish() {

                           yes.invalidate();

                           restart();

                   }

           };

           count.start();

           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;

   }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Creates all fields

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Creates timer that repaints the program

 

 

 

 

 

 

 

initializes some fields

   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;    

   }

 

Gets point touched and sets it as destination for the second ballsphere

 

The screen starts brightening

 

 

Starts darkening

 

 

Game will start

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(192, 192, 192);

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

                   }

           }

   }

 

Checks if game is over

 

 

sets the speed of the bouncing sphere according to difficulty

 

 

 

 

Draws background

 

 

 

 

 

 

Moves first sphere

 

Draws objects on screen

 

 

 

 

 

 

 

If coordinate of point on screen touched is within range of sphere, it moves the second sphere

 

 

 

If the game isn’t paused, the bouncing sphere keeps moving, the brightness is changing, and checks are performed to see if the game is over or a piece is collected

public void restart() {

           count.start();

   }

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;

   }

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;

   }

public void bright() {

           if(brighten && !(z==255))

                   z++;

           else

                   if(z>0)

                           z--;

   }

Restarts timer

 

 

Moves the first sphere according to tilt

 

 

 

 

 

 

 

 

 

 

 

 

 

Resets all values when the game restarts

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Brightens the screen slowly to white if the screen is being touched. Fades to black when the screen is not touched.

 

 

 

public void moveTo() {

           c[1].x+=dx/20.0;

           c[1].y+=dy/20.0;

   }

 

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;    

   }

   

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

           }

   }

   public void onAccuracyChanged(Sensor sensor, int accuracy) {

   }

   

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

   }

 

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

   }

   

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

   }

}

Moves the second sphere incrementally towards a point set when the screen is touched.

 

Checks if either white sphere is hit by the bouncing sphere.

 

 

 

 

 

 

 

 

Checks if either white sphere collects a golden piece.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Gets the values of the tilt of the screen

 

 

 

 

 

Initializes the positions of the bouncing sphere and golden piece

 

 

 

 

 

When the game is over, this creates a dialog which lets the user restart or quit the game.

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

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;

   

   public Circle(int radius, float a, float b) {

           r=radius;

           x=a;

           y=b;

   }

 

 

 

 

 

 

 

 

 

Initializes fields for circles

 

 

 

 

 

 

 

Creates a Circle object with a radius, an x, and a y position.

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;

   }

}

Moves the bouncing sphere which continues on its path until it hits a boundary of the phone. It then simply rebounds and continues.

 

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