This article describes the Android game development Learning ① bouncing ball implementation method. Share to everyone for your reference. Specifically as follows:
After learning a little Android, feel the need to record down, so opened the new pit, slowly fill it.
1. Sports body Movable class
This example mainly simulates a group of different sizes of the ball at a certain level at the initial velocity from the height of the trajectory of the movement. The small ball is a movable object movable object, in addition to contain the small ball picture object, also includes such as the position coordinates, the horizontal velocity, the vertical speed and so on a series to simulate the small ball movement the member variable and some methods.
Movable class:
Package com.ball;
Import Android.graphics.Bitmap;
Import Android.graphics.Canvas; public class Movable {int startx = 0; initial x coordinate int starty = 0; Initial y-coordinate int x; Real-time x coordinate int y; Real-time y-coordinate float STARTVX = 0f; The initial horizontal direction of the velocity float startvy = 0f; The initial vertical direction of the velocity float v_x = 0f; Real-time horizontal direction of the speed float v_y = 0f; Real-time vertical direction of the speed int r; Movable object radius double TimeX; The motion time in the x direction is double timey; The movement time in the y direction is Bitmap bitmap=null; Movable object picture Ballthread bt=null; Responsible for small ball movement Boolean bfall=false; Whether the ball has been falling from the board of Float impactfactor=0.25f;
The loss coefficient of velocity after a small ball collision is public movable (int x,int y,int r,bitmap Bitmap) {this.startx=x;
This.x=x;
This.starty=y;
This.y=y;
This.r=r;
This.bitmap=bitmap; Timex=system.nanotime ();
Gets the system time initialization Timex this.v_x=ballview.v_min+ (int) (ballview.v_max-ballview.v_min) *math.random ()); Bt=new Ballthread (this);
Create and start Ballthread bt.start (); } public void Drawself (Canvas Canvas) {Canvas.drawbitmap (BitmaP,x,y,null);
}
}
The StartX and Starty variables record the initial x and y coordinates of the small ball at the start of each movement phase (such as falling from the highest point to the lowest point), and in subsequent physical calculations, the real-time x and Y coordinates of the ball will be the initial coordinates plus the displacement of the period.
STARTVX and Startvy are the velocities of the initial time in the horizontal x and vertical direction y in each phase of the ball, both of which will be used to calculate the real-time velocity of the ball v_x and v_y.
The Timex and Timey respectively represent the duration of the ball moving upward in both horizontal and vertical sides, and Timex and Timey will be reset when the ball moves from one stage to the next (such as when it bounces from the falling stage to the upper throw stage).
The Ballthread object inherits from Thread class, plays the role of physical engine, and is responsible for modifying the position coordinates of the ball according to the physical formula to change the motion trajectory of the ball.
The Boolean variable bfall is used to identify whether the ball has fallen off the board, and the upper-left part of the screen will have a plank when the program is running, with all the balls moving from the plank to the right. When BFall is false, the ball is still moving on the plank and not falling.
The float variable impactfactor action is when the ball hits the ground, and the velocity of the ball's horizontal and vertical direction is attenuated according to its value.
Initializes a partial member variable in the constructor and starts the physical engine.
The two constants v_min and V_max of the Ballview class in the constructor represent the minimum and maximum of the horizontal velocity of the ball, which is used to generate the random horizontal velocity of the ball.
2. Small ball physics engine Ballthread class
First, explain how the physical engine works and how it changes the trajectory of the ball.
In the motion phase, the motion of the ball is divided into several stages in the vertical direction, in which the velocity of the ball in the vertical direction increases (drops) or decreases (rises). That is, whenever the velocity of a small ball in the vertical direction changes (such as hitting the ground or reaching the highest point in the sky), the ball ends the movement of the stage into a new phase.
Numerical calculations, starting at each stage, record the start time, as well as the physical quantities of the initial x and Y coordinates of the ball at this stage, as well as the velocity in the initial x and y directions. Then, in this stage of motion, the real-time data of the ball are calculated based on the physical quantities of the records and the current time.
For zero judgment, it is necessary to determine whether the ball is zero when the ball rises in motion and the ball hits the ground. But different from the real world, in the program of the small ball of the physical quantities are discrete (that is, every fixed time to calculate the value of these physical values), the actual small ball motion trajectory of a discrete point. In this case, it is possible to make an error if the judgment is zero (for example, in the previous calculation, the ball velocity is positive, the next calculation is negative, skipping the speed zero this turning point, the ball will never appear as zero this moment). So the way the threshold is used in the program, the speed of the ball is determined to be zero once it is less than a threshold value.
Ballthread class:
Package com.ball; public class Ballthread extends thread {movable father;//Movable object reference Boolean flag = false;/thread execution identity bit int SLEEPSP an = 40; Dormant time float g = 200; Acceleration of the ball drop double current;
Record Current time public ballthread (movable father) {this.father = father;
This.flag = true; @Override public void Run () {s) {current = System.nanotime ()///Get the current time, in nanoseconds, to handle movement in the horizontal direction Doub Le Timespanx = (double) ((Current-father.timex)/1000/1000/1000);
Get the horizontal direction of the time passed father.x = (int) (FATHER.STARTX + father.v_x * timespanx); if (Father.bfall) {//handle motion in the vertical direction to determine whether the ball has been moved out of the bezel double timespany = (double) (Current-father.timey)/1000/1000/1
000);
FATHER.Y = (int) (Father.starty + father.startvy * timespany + timespany * timespany * G/2);
Father.v_y = (float) (Father.startvy + G * timespany); The code that detects and handles special events is omitted first, and then the complement} else if (father.x + FATHER.R/2 >= ballview.wood_edge) {//Determines whether the ball is moved out of the bezel father through the x-coordinate.Timey = System.nanotime (); Father.bfall = true;
Ok drop} try {Thread.Sleep (Sleepspan);
catch (Exception e) {e.printstacktrace ();
}
}
}
}
The variable g, which represents the acceleration of gravity, is initialized to 200, which is a reasonably measured value.
The Run method deals with the movement of a small ball in a horizontal direction, according to the current time to obtain the time from start to present in the horizontal side of the ball, and then use the movement of the small ball in this stage to the initial position of the ball at this stage, to find the x coordinates at this time.
The Run method deals with the movement of a small ball in a vertical direction by first checking whether the bfall of the ball is true, and if it is true that the ball is already falling and being physically computed; if false, use the x-coordinate to determine whether it needs to be set to true.
The constant wood_edge of the Ballview class is used to record the rightmost x-coordinate of a wooden picture, and if the ball's horizontal position exceeds that value, it needs to fall.
The detection code just omitted is as follows:
Determine if the ball reaches the highest point
if (Father.startvy < 0 && Math.Abs (father.v_y) <= Ballview.up_zero) {
Father.timey = System.nanotime ();
father.v_y = 0;
Father.startvy = 0;
Father.starty = father.y;
}
Determine if the ball hits the ground
if (father.y + FATHER.R * 2 >= ballview.ground_ling && father.v_y > 0) {
father.v_x = FA Ther.v_x * (1-father.impactfactor); Attenuation of the horizontal direction of the velocity
father.v_y = 0-father.v_y * (1-father.impactfactor);//decay the velocity in the vertical direction and change the direction
if (Math.Abs (father.v_y) < Ballview.down_zero) {//Judging the speed of the collision attenuation, too small to stop the movement
This.flag = false;
} else {
//crash speed can also bounce to continue the next stage of movement
father.startx = father.x;
Father.timex = System.nanotime ();
Father.starty = father.y;
Father.timey = System.nanotime ();
Father.startvy = father.v_y;
}
3. View class Ballview
Ballview is the view class that is responsible for rendering the screen, declaring some static constants to be used in physical computations, and declaring the picture resources to be drawn in the program and the list of small objects to draw. The Ballview class inherits from the Surfaceview class under the Android.view package. Surfaceview is different from the ordinary view, it has different drawing mechanism, it is suitable for developing the game program. The use of Surfaceview requires the implementation of Surfaceholder.callback interface, which can be edited for Surfaceview and other operations, but also can monitor surfaceview changes.
Ballview class:
Package com.ball;
Import java.util.ArrayList;
Import Java.util.Random;
Import Android.content.Context;
Import android.content.res.Resources;
Import Android.graphics.Bitmap;
Import Android.graphics.BitmapFactory;
Import Android.graphics.Canvas;
Import Android.graphics.Color;
Import Android.graphics.Paint;
Import Android.view.SurfaceHolder;
Import Android.view.SurfaceHolder.Callback;
Import Android.view.SurfaceView;
Import COM.BP.R;
public class Ballview extends Surfaceview implements Callback {public static final int v_max=35;
public static final int v_min=15;
public static final int wood_edge=60; public static final int ground_ling=450; Represents the y-coordinate of the ground, where the ball falls to play the public static final int up_zero=30; The ball in the ascent process, the speed is less than the value even if 0 public static final int down_zero=60;
When the ball hits the ground, the speed is less than the value of 0 bitmap[] Bitmaparray =new bitmap[6]; Bitmap Bmpback; Background picture Bitmap Bmpwood; Bezel picture String fps= "fps:n/a"; string int ballnumber = 8 to display the frame rate; Ball number arraylist<movable> AlmovabLe=new arraylist<movable> (); Small Ball Object array Drawthread dt;
Background screen drawing thread public ballview (context activity) {super (activity);
Getholder (). Addcallback (this); Initbitmaps (Getresources ()); Initialize the picture initmovables (); Initialization of small ball dt=new Drawthread (This,getholder ()); Initialize the redraw thread} public void Initbitmaps (resources R) {Bitmaparray[0]=bitmapfactory.decoderesource (R), R.drawable.ball_r
Ed_small);
Bitmaparray[1]=bitmapfactory.decoderesource (R, R.drawable.ball_purple_small);
Bitmaparray[2]=bitmapfactory.decoderesource (R, R.drawable.ball_green_small);
Bitmaparray[3]=bitmapfactory.decoderesource (R, r.drawable.ball_red);
Bitmaparray[4]=bitmapfactory.decoderesource (R, R.drawable.ball_purple);
Bitmaparray[5]=bitmapfactory.decoderesource (R, R.drawable.ball_green);
Bmpback=bitmapfactory.decoderesource (R, R.drawable.back);
Bmpwood=bitmapfactory.decoderesource (R, R.drawable.wood);
public void Initmovables () {Random r=new Random (); for (int i=0;i<ballnumber;i++) {int index=r.nextint (32);
Bitmap Tempbitmap=null;
if (I<BALLNUMBER/2) {//If the first half of the ball is initialized, a random tempbitmap=bitmaparray[3+index%3 from the big Ball is found];
else {//If the first half of the ball is initialized, find a random tempbitmap=bitmaparray[index%3 from the ball;
//Create movable object movable m=new movable (0, 70-tempbitmap.getheight (), Tempbitmap.getwidth ()/2, Tempbitmap); Almovable.add (m);
Join list}} public void Dodraw (Canvas Canvas) {//Picture required in the drawing program Canvas.drawbitmap (bmpback, 0, 0,null);
Canvas.drawbitmap (Bmpwood, 0, 60,null);
for (movable m:almovable) {//traverse to draw each movable object m.drawself (canvas);
} Paint p=new Paint ();
P.setcolor (Color.Blue);
P.settextsize (18); P.setantialias (TRUE); Set anti-aliasing Canvas.drawtext (FPS, p); Draw the frame rate string} @Override public void surfacechanged (Surfaceholder arg0, int arg1, int arg2, int arg3) {} @Overrid
e public void surfacecreated (Surfaceholder arg0) {if (!dt.isalive ()) {Dt.start (); }} @Override public void SuRfacedestroyed (Surfaceholder arg0) {dt.flag=false;
Dt=null;
}
}
Because the pictures in the Bitmaparray array are of large size and small size, the small size picture will not be blocked in order to draw the picture, so use the large size picture first.
The Dodraw method is called in Drawthread to draw the picture and the frame rate.
4. Draw thread Drawthread class
Drawthread class:
Package com.ball;
Import Android.graphics.Canvas;
Import Android.view.SurfaceHolder;
public class Drawthread extends Thread {Ballview bv;
Surfaceholder Surfaceholder;
Boolean flag=false;
int sleepspan=30; Long start =system.nanotime (); Record the start time, which is used to compute the frame rate int count=0;
Record frame number public drawthread (Ballview bv,surfaceholder surfaceholder) {THIS.BV=BV;
This.surfaceholder=surfaceholder;
This.flag=true;
public void Run () {Canvas canvas=null;
while (flag) {try {Canvas=surfaceholder.lockcanvas (null);//Get Ballview canvas synchronized (surfaceholder) {
Bv.dodraw (canvas);
} catch (Exception e) {e.printstacktrace ();
finally {if (canvas!=null) {surfaceholder.unlockcanvasandpost (canvas);//Surfaceholder unlock and pass the canvas back}
} this.count++;
if (count==20) {//Full 20 frames, calculate the first frame rate count=0;
Long Tempstamp=system.nanotime ();
Long Span=tempstamp-start;
Start=tempstamp; Double Fps=math.rounD (100000000000.0/span*20)/100.0;
bv.fps= "fps:" +FPS;
try {thread.sleep (Sleepspan);
catch (Interruptedexception e) {e.printstacktrace ();
}
}
}
}
The Ballview screen redraw function Dodraw is called in the Code, and the implementation mechanism is to lock the Balview canvas and then invoke the Ballview Dodraw method to repaint the Ballview canvas. Finally unlock the Ballview canvas and pass it back.
The frame rate is calculated by first finding the span of time that the program consumes for 20 frames, and then calculating how many spans can be contained within 100s. The number of spans in 100s is multiplied by 20 to draw several frames within 100s, and the number of frames drawn within 1s can be obtained by dividing by 100.
5.MainActivity class
Mainactivity class:
Package com.ball;
Import android.app.Activity;
Import Android.os.Bundle;
Import Android.view.Window;
Import Android.view.WindowManager;
public class Mainactivity extends activity {
Ballview bv;
@Override public
void OnCreate (Bundle savedinstancestate) {
super.oncreate (savedinstancestate);
Requestwindowfeature (Window.feature_no_title); Setting does not display title
GetWindow (). SetFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG _fullscreen); Set Full-screen
bv=new Ballview (this);
Setcontentview (BV);
}
Run Effect chart:
Resource files to use:
I hope this article will help you with your Android program.