Li huaming himiOriginal, reprinted must be explicitly noted:
[Heimi gamedev block]Link: http://www.himigame.com/android-game/354.html
Today, a group of colleagues said they urgently need information about physical games ~ In the afternoon, I wrote a simpleCircular free dropDemo. Let's share it with you;
Let me talk about it first. I have introduced it to you in my previous articles.Gravity sensor,So what we want to talk about todayGravity system,They are 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
Package COM. himi; <br/> Import Java. util. random; <br/> Import android. graphics. canvas; <br/> Import android. graphics. color; <br/> Import android. graphics. paint; <br/> Import android. graphics. rectf; <br/>/** <br/> * @ author himi <br/> * @ custom circular class <br/> */<br/> public class myarc {< br/> private int arc_x, arc_y, arc_r; // X, Y coordinate and radius of the circle <br/> private float speed_x = 1.2f, speed_y = 1.2f; // speed of X and Y of the ball <br/> private F Loat vertical_speed; // acceleration <br/> private float horizontal_speed; // horizontal acceleration. Add it by yourself. <br/> private final float ACC = 0.135f; // offset value for simulating acceleration <br/> private final float recession = 0.2f; // The recession coefficient of each bounce <br/> private Boolean isdown = true; // whether it is falling <br/> private random ran; // immediately count the database <br/>/** <br/> * @ defines the circular constructor <br/> * @ Param x round X coordinate <br/> *@ param y circular y coordinate <br/> * @ Param R circular radius <br/> */<br/> Public myarc (int x, int y, Int R) {<br/> ran = new random (); <br/> This. arc_x = x; <br/> This. arc_y = y; <br/> This. arc_r = r; <br/>}< br/> Public void drawmyarc (canvas, paint) {// each circle should have a set of painting methods <br/> paint. setcolor (getrandomcolor (); // continuously obtain the color of the circle and fill the circle (to achieve the blinking effect of the circle) <br/> canvas. drawarc (New rectf (arc_x + speed_x, arc_y + speed_y, arc_x + 2 * <br/> arc_r + speed_x, arc_y + 2 * arc_r + speed_y), 0,360, true, paint); <br />}< Br/>/** <br/> * @ return <br/> * @ returns a color <br/> */<br/> Public int getrandomcolor () {<br/> int ran_color = ran. nextint (8); <br/> int temp_color = 0; <br/> switch (ran_color) {<br/> case 0: <br/> temp_color = color. white; <br/> break; <br/> case 1: <br/> temp_color = color. blue; <br/> break; <br/> case 2: <br/> temp_color = color. cyan; <br/> break; <br/> case 3: <br/> temp_color = color. dkgray; <br/> Break; <Br/> case 4: <br/> temp_color = color. red; <br/> break; <br/> case 6: <br/> temp_color = color. green; <br/> case 7: <br/> temp_color = color. gray; <br/> case 8: <br/> temp_color = color. yellow; <br/> break; <br/>}< br/> return temp_color; <br/>}< br/>/** <br/> * circular logic <br/> */<br/> Public void logic () {// each circle should have a set of logic <br/> If (isdown) {// circular descent logic <br/>/* -- Note 1-*/speed_y + = vertical_speed; // acceleration of the circular Y axis speed <br/> Int COUNT = (INT) vertical_speed ++; <br/> // take another variable here to write down the current speed offset <br/> // if the following for (INT I = 0; I <vertical_speed ++; I ++) {} Then the endless loop-<br/> for (INT I = 0; I <count; I ++) {// Note 1 <br/>/* -- Note 2-*/vertical_speed + = ACC; <br/>}< br/>} else {// round rebound logic <br/> speed_y-= vertical_speed; <br/> int COUNT = (INT) vertical_speed --; <br/> for (INT I = 0; I <count; I ++) {<br/> vertical_speed-= ACC; <br/>}< br /> If (iscollision () {<br/> isdown =! Isdown; // when a collision occurs, the direction of the circle should be changed! <Br/> vertical_speed-= vertical_speed * recession; // each collision degrades the rebound acceleration <br/>}< br/>/** <br/> * collision between the circle and the bottom of the screen <br/> * @ return <br/> * @ return true <br/> */<br/> Public Boolean iscollision () {<br/> return arc_y + 2 * arc_r + speed_y> = mysurfaceviee. screenh; <br/>}< br/>
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!
Package COM. himi; <br/> Import Java. util. random; <br/> Import Java. util. vector; <br/> Import android. content. context; <br/> Import android. graphics. canvas; <br/> Import android. graphics. color; <br/> Import android. graphics. paint; <br/> Import android. util. log; <br/> Import android. view. keyevent; <br/> Import android. view. surfaceholder; <br/> Import android. view. surfaceview; <br/> Import android. view. surfaceho Lder. callback; <br/> public class mysurfaceviee extends surfaceview implements callback, runnable {<br/> private thread th; <br/> private surfaceholder SFH; <br/> private canvas; <br/> private paint; <br/> private Boolean flag; <br/> Public static int screenw, screenh; <br/> private vector <myarc> VC; // here we define the container with the custom circle <br/> private random ran; // The repository <br/> Public mysurfaceviee (context) {< Br/> super (context); <br/> This. setkeepscreenon (true); <br/> Vc = new vector <myarc> (); <br/> ran = new random (); // Note 1 <br/> SFH = This. getholder (); <br/> SFH. addcallback (this); <br/> paint = new paint (); <br/> paint. setantialias (true); <br/> setfocusable (true); <br/>}< br/> Public void surfacecreated (surfaceholder holder) {<br/> flag = true; // This is what I just mentioned in the previous article... <Br/> TH = new thread (this); <br/> screenw = This. getwidth (); <br/> screenh = This. getheight (); <br/> th. start (); <br/>}< br/> Public void draw () {<br/> try {<br/> canvas = SFH. lockcanvas (); <br/> canvas. drawcolor (color. black); <br/> If (VC! = NULL) {// when the container is not empty, traverse all circular painting methods in the container <br/> for (INT I = 0; I <VC. size (); I ++) {<br/> VC. elementat (I ). drawmyarc (canvas, paint); <br/>}< br/>} catch (exception e) {<br/> // todo: handle exception <br/>} finally {<br/> try {<br/> If (canvas! = NULL) <br/> SFH. unlockcanvasandpost (canvas); <br/>}catch (exception E2) {<br/>}< br/> private void logic () {// main logic <br/> If (VC! = NULL) {// when the container is not empty, traverse all circular logic in the container <br/> for (INT I = 0; I <VC. size (); I ++) {<br/> VC. elementat (I ). logic (); <br/>}< br/> @ override <br/> Public Boolean onkeydown (INT keycode, keyevent event) {<br/> // when the key event is returned, we still have a circular instance in the container. <br/> VC. addelement (New myarc (ran. nextint (this. getwidth (), ran. nextint (100), ran. nextint (50); <br/> return true; <br/>}< br/> Public void run () {<br/> // todo auto-generated method stub <br/> while (FLAG) {<br/> logic (); <br/> draw (); <br/> try {<br/> thread. sleep (100); <br/>} catch (exception ex) {<br/>}< br/> Public void surfacechanged (surfaceholder holder, int format, int width, int height) {<br/> log. V ("himi", "surfacechanged"); <br/>}< br/> Public void surfacedestroyed (surfaceholder holder) {<br/> flag = false; <br/>}< br/>}
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.himigame.com/android-game/354.html
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!