Today, a group of colleagues said they urgently need information about physical games ~ In the afternoon, I wrote a simple round free-body-dropping Demo. Let's share it with you;
Let's talk about it first. I have introduced Gravity Sensors in my previous articles. The gravity system we are talking about today is actually the same!
In the gravity sensor, although I have implemented a circle that will have different speeds based on the mobile phone's reverse angle, its built-in acceleration algorithms are encapsulated by Android OS, today, the gravity system we want to talk about is to simulate this acceleration, so as to let a circle freely fall into the body. It feels as qualitative as the ball in reality! The speed increases when you fall, and the speed decreases slowly after the rebound ~
OK. First, let's take a look at the last two images and then explain them:
Demo: Introduction: (it's a bit H to cough and play, and the full screen of the crazy button is --)
When you click any button in the simulator, a circle with random size, color, position, and blinking will be randomly generated on the screen, and the circle will have gravity, when the circle strikes the bottom of the screen, it will rebound and the bounce height is lower than once!
In this example, for good looks, I didn't make the circle slow until it finally stops, and it will continue to rebound and fall at a height;
Another point: when a circle falls freely from a height, it may not change in the X coordinate system. Of course, this is an ideal state in our code, because in real life, generally, the X/Y coordinate system will change. In this Demo, I mainly made the vertical drop and rebound function. I didn't do anything about horizontal acceleration, the first reason is that it is basically the same as the vertical processing method. Second, I don't have time --...
Okay, no nonsense! First, let's introduce my custom circular class:
MyArc. java
··· · 50 ······· · 90 ····· · 140 · 150
Package com. himi;
Import java. util. Random;
Import android. graphics. Canvas;
Import android. graphics. Color;
Import android. graphics. Paint;
Import android. graphics. RectF;
/**
* @ Author Himi
* @ Custom circular class
*/
Public class MyArc {
Private int arc_x, arc_y, arc_r; // the X and Y coordinates and radius of the circle
Private float speed_x = 1.2f, speed_y = 1.2f; // speed of x and y of the ball
Private float vertical_speed; // Acceleration
Private float horizontal_speed; // horizontal acceleration. Please add it by yourself.
Private final float ACC = 0.135f; // to simulate the offset of acceleration
Private final float RECESSION = 0.2f; // The RECESSION coefficient that pops up each time
Private boolean isDown = true; // whether it is in the falling state
Private Random ran; // Random database
/**
* @ Define the circular Constructor
* @ Param x round X coordinate
* @ Param y round Y coordinate
* @ Param r circle radius
*/
Public MyArc (int x, int y, int r ){
Ran = new Random ();
This. arc_x = x;
This. arc_y = y;
This. arc_r = r;
}
Public void drawMyArc (Canvas canvas, Paint paint) {// each circle should have a set of painting methods
Paint. setColor (getRandomColor (); // you can obtain the color of the circle and fill the circle with the color)
Canvas. drawArc (new RectF (arc_x + speed_x, arc_y + speed_y, arc_x + 2 *
Arc_r + speed_x, arc_y + 2 * arc_r + speed_y), 0,360, true, paint );
}
/**
* @ Return
* @ Returns a color immediately.
*/
Public int getRandomColor (){
Int ran_color = ran. nextInt (8 );
Int temp_color = 0;
Switch (ran_color ){
Case 0:
Temp_color = Color. WHITE;
Break;
Case 1:
Temp_color = Color. BLUE;
Break;
Case 2:
Temp_color = Color. CYAN;
Break;
Case 3:
Temp_color = Color. DKGRAY;
Break;
Case 4:
Temp_color = Color. RED;
Break;
Case 6:
Temp_color = Color. GREEN;
Case 7:
Temp_color = Color. GRAY;
Case 8:
Temp_color = Color. YELLOW;
Break;
}
Return temp_color;
}
/**
* Circular logic
*/
Public void logic () {// each circle should have a set of logic
If (isDown) {// circular drop Logic
/* -- Note 1-*/speed_y + = vertical_speed; // acceleration of the circular Y axis speed
Int count = (int) vertical_speed ++;
// Write down the current speed offset with another variable.
// If the for (int I = 0; I <vertical_speed ++; I ++) {} below is an endless loop --
For (int I = 0; I <count; I ++) {// Note 1
/* -- Note 2-*/vertical_speed + = ACC;
}
} Else {// round rebound Logic
Speed_y-= vertical_speed;
Int count = (int) vertical_speed --;
For (int I = 0; I <count; I ++ ){
Vertical_speed-= ACC;
}
}
If (isCollision ()){
IsDown =! IsDown; // when a collision occurs, the direction of the circle should be changed!
Vertical_speed-= vertical_speed * RECESSION; // each collision degrades the rebound acceleration.
}
}
/**
* Collision between the circle and the bottom of the screen
* @ Return
* @ Returns true for collision
*/
Public boolean isCollision (){
Return arc_y + 2 * arc_r + speed_y> = MySurfaceViee. screenH;
}
}
The code is relatively simple. The following are some notes:
Note 1:
It is estimated that some of the students are a little dizzy here. I explained that everyone knows that the speed is getting faster and faster when the body falls freely, which is affected by the acceleration, so here we add acceleration to the original round y speed!
NOTE 2:
Although acceleration affects the original velocity of the circle, our acceleration is not constant. to simulate the free fall of the real sphere, we not only increase the offset ACC for acceleration, in addition, we also need to simulate the changing law to multiply the next acceleration offset! So why is it necessary to regard the acceleration value as a criterion for determining the for loop!
Okay, let's look at SurfaceView!
··· · 50 ······· · 90 ····· · 140 · 150
Package com. himi;
Import java. util. Random;
Import java. util. Vector;
Import android. content. Context;
Import android. graphics. Canvas;
Import android. graphics. Color;
Import android. graphics. Paint;
Import android. util. Log;
Import android. view. KeyEvent;
Import android. view. SurfaceHolder;
Import android. view. SurfaceView;
Import android. view. SurfaceHolder. Callback;
Public class MySurfaceViee extends SurfaceView implements Callback, Runnable {
Private Thread th;
Private SurfaceHolder sfh;
Private Canvas canvas;
Private Paint paint;
Private boolean flag;
Public static int screenW, screenH;
Private Vector <MyArc> vc; // here we define the container for the custom circle
Private Random ran; // the instant Library
Public MySurfaceViee (Context context ){
Super (context );
This. setKeepScreenOn (true );
Vc = new Vector <MyArc> ();
Ran = new Random (); // Note 1
Sfh = this. getHolder ();
Sfh. addCallback (this );
Paint = new Paint ();
Paint. setAntiAlias (true );
SetFocusable (true );
}
Public void surfaceCreated (SurfaceHolder holder ){
Flag = true; // This is what I just mentioned in the previous article...
Th = new Thread (this );
ScreenW = this. getWidth ();
ScreenH = this. getHeight ();
Th. start ();
}
Public void draw (){
Try {
Canvas = sfh. lockCanvas ();
Canvas. drawColor (Color. BLACK );
If (vc! = Null) {// when the container is not empty, traverse all circular painting methods in the container
For (int I = 0; I <vc. size (); I ++ ){
Vc. elementAt (I). drawMyArc (canvas, paint );
}
}
} Catch (Exception e ){
// TODO: handle exception
} Finally {
Try {
If (canvas! = Null)
Sfh. unlockCanvasAndPost (canvas );
} Catch (Exception e2 ){
}
}
}
Private void logic () {// Master logic
If (vc! = Null) {// when the container is not empty, traverse all circular logic in the container
For (int I = 0; I <vc. size (); I ++ ){
Vc. elementAt (I). logic ();
}
}
}
@ Override
Public boolean onKeyDown (int keyCode, KeyEvent event ){
// When the key event is responded, we still enter our circular instance in the container.
Vc. addElement (new MyArc (ran. nextInt (this. getWidth (), ran. nextInt (100), ran. nextInt (50 )));
Return true;
}
Public void run (){
// TODO Auto-generated method stub
While (flag ){
Logic ();
Draw ();
Try {
Thread. sleep (100 );
} Catch (Exception ex ){
}
}
}
Public void surfaceChanged (SurfaceHolder holder, int format, int width, int height ){
Log. v ("Himi", "surfaceChanged ");
}
Public void surfaceDestroyed (SurfaceHolder holder ){
Flag = false;
}
}
OK. The code is very simple and clear! To put it a little bit: methods like logic () and draw () in MyArc, similar to those in MysurfaceView, can better manage our code structure and clarify our ideas, let us do what we should do. This saves us a lot of trouble ~
Source code: http://www.bkjia.com/uploadfile/2011/1115/20111115052234134.rar
Supplement: // Note 1 here! Some children's shoes can be abbreviated as "for loop": I want to remind you of the children's shoes ~
For (int I = 0; I <count; I ++ ){
Vertical_speed + = ACC;
}
The above code can indeed be expressed in one sentence:
Vertical_speed + = ACC * count; or vertical_speed = vertical_speed + ACC * count;
But note: because all the variables here are floating-point numbers, we all know that there is a limit on the number of digits for floating-point numbers, so I can use for writing here to avoid the product, if it is abbreviated, The results may be different !!!! Pay attention to this;
Do not enter vertical_speed = (vertical_speed + ACC) * count. This is incorrect!
Himi original, you are welcome to reprint, please note clearly! Thank you.
Address: http://blog.csdn.net/xiaominghimi/archive/2011/01/19/6153396.aspx