Li huaming himiOriginal, reprinted must be explicitly noted:
Reprinted from[Heimi gamedev block]Link: http://www.himigame.com/android-game/384.html
,
This chapter is part of the game development book being created. It has not been updated for a long time due to the writing of the book. Sorry, I am sorry for everyone. So let's release a part of the book today and let everyone get started first;
On Android phones, some do not have physical buttons for navigation up or down the left and right. Therefore, many games use Android phones with touch screens to create degree joystick to replace the game's arrow keys, this not only makes the UI more beautiful, but also easier to operate;
Let's look at the effect first:
Implementation is started as follows:
First, it must be two circles. Undoubtedly, the center points overlap. In order to distinguish them, different colors are set;
Gray: Fixed rocker background (also indicates the active range of the joystick );
RED: joystick;
Then consider: The Red joystick must move along with the touch screen of the finger. This is easy. You only need to handle the touch screen event and assign the obtained touch screen XY coordinate to the XY coordinate of the joystick; this is okay, but now we are thinking about one problem:
Generally, it is impossible for the joystick to keep following the position of the finger. Therefore, an active area of the joystick is required, just like the gray area in which the joystick can move with the user's touch screen position, however, once the user's touch screen is located outside the active area, the joystick should not run out of the gray area. The specific implementation steps are as follows:
1) obtain the angle formed by the coordinate of the joystick and the coordinate of the touch screen point.
2) Calculate the current X and Y coordinates of circular motion on the gray circle where the joystick is located based on angle and the radius of the known circle;
First step: Calculate the angle between the joystick coordinate and the touch screen Coordinate
We certainly know the current coordinates of the joystick, and the coordinates of the user's touch screen can also be obtained by pressing the touch screen. The method to obtain the coordinates can be written as follows:
/*** <Br/> * obtain the radian between two points <br/> */<br/> Public double getrad (float px1, float py1, float px2, float py2) {<br/> // obtain the distance between two points x <br/> float x = px2-px1; <br/> // obtain the distance between two y points. <br/> float y = py1-py2; <br/> // calculate the oblique edge length <br/> float Xie = (float) math. SQRT (math. pow (x, 2) + math. pow (Y, 2); <br/> // obtain the cosine of this angle (through the theorem in the trigonometric function: adjacent edge/Oblique Edge = angle cosine value) <br/> float cosangle = x/Xie; <br/> // obtain the radians of the angle using the arccosine theorem. <br/> float rad = (float) math. ACO S (cosangle); <br/> // Note: When the touch screen position y coordinate <Y coordinate of the joystick, we need to take the inverse value-0 ~ -180 <br/> If (py2 <py1) {<br/> rad =-rad; <br/>}< br/> return rad; <br/>}
In Java, the arccosine function in the math class does not return degrees in radians, so pay special attention to this;
Another point is that the angle of the trigonometric function ranges from 0 ~ 180 degrees, so the opposite is-0 ~ -180 degrees;
After obtaining the angle between the joystick and the user's touch screen position, we can use the circumference formula to obtain the XY coordinate of the joystick. The method is as follows:
/** <Br/> * @ Param r <br/> * rotation point of the circular motion <br/> * @ Param centerx <br/> * Rotation point x <br/> * @ Param centery <br/> * rotation point Y <br/> * @ Param rad <br/> * rotation radians <br/> */< br/> Public void getxy (float centerx, float centery, float R, double rad) {<br/> // obtain the X coordinate of the circular motion <br/> smallrockercirclex = (float) (R * Math. cos (RAD) + centerx; <br/> // obtain the Y coordinate of the circular motion <br/> smallrockercircley = (float) (R * Math. sin (RAD) + centery; <br/>}
Circular Motion formula: obtained through trigonometric function theorem:
X coordinate: returns the cosine of * angle of the circle radius.
Y coordinate: the sine value of * angle of the circular radius.
The circumference is determined by the radius R of the circle;
Through the above formula, we can let the joystick do circular motion on the gray circle. Of course, we also need to pay attention to three points:
1: the size of the circular motion should be the same as the radius of the gray area;
2: In the touch screen event, you should first determine whether the user's touch screen is in the gray area. If not, we should obtain the angle between the joystick and the touch-screen point and then obtain the XY coordinate of the joystick on the circular motion. If it is in, it will not be processed, you only need to set the joystick position along with the user's clicking position;
3: In a touch screen event, when the user's finger leaves the screen, the joystick should be restored to the initial position State;
The following is all the code in mysurfaceview of the entire project:
Package COM. RP; <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. motionevent; <br/> Import android. view. surfaceholder; <br/> Import android. view. surfaceview; <br/> Import android. view. surfaceholder. callback; <br/> public class mysurfaceview extends surf Aceview implements callback, runnable {<br/> private thread th; <br/> private surfaceholder SFH; <br/> private canvas; <br/> private paint; <br/> private Boolean flag; <br/> // fixed X, Y coordinate, and radius of the circle on the rocker background. <br/> private int rockercirclex = 100; <br/> private int rockercircley = 100; <br/> private int rockercircler = 50; <br/> // X of the joystick, Y coordinate and rocker radius <br/> private float smallrockercirclex = 100; <br/> private flo At smallrockercircley = 100; <br/> private float smallrockercircler = 20; <br/> Public mysurfaceview (context) {<br/> super (context ); <br/> log. V ("himi", "mysurfaceview"); <br/> This. setkeepscreenon (true); <br/> SFH = This. getholder (); <br/> SFH. addcallback (this); <br/> paint = new paint (); <br/> paint. setantialias (true); <br/> setfocusable (true); <br/> setfocusableintouchmode (true); <br/>}< br/> Publ IC void surfacecreated (surfaceholder holder) {<br/> TH = new thread (this); <br/> flag = true; <br/> th. start (); <br/>}< br/>/*** <br/> * obtain the radian between two points. <br/> */<br/> Public double getrad (float px1, float py1, float px2, float py2) {<br/> // obtain the distance between two points x <br/> float x = px2-px1; <br/> // obtain the distance between two y points. <br/> float y = py1-py2; <br/> // calculate the oblique edge length <br/> float Xie = (float) math. SQRT (math. pow (x, 2) + math. pow (Y, 2); <br/> // get Cosine of this angle (through the theorem in the trigonometric function: adjacent edge/Oblique Edge = angle cosine) <br/> float cosangle = x/Xie; <br/> // obtain the radians of the angle using the arccosine theorem <br/> float rad = (float) math. ACOs (cosangle); <br/> // Note: When the touch screen position y coordinate <Y coordinate of the joystick, we need to take the inverse value-0 ~ -180 <br/> If (py2 <py1) {<br/> rad =-rad; <br/>}< br/> return rad; <br/>}< br/> @ override <br/> Public Boolean ontouchevent (motionevent event) {<br/> If (event. getaction () = motionevent. action_down | <br/> event. getaction () = motionevent. action_move) {<br/> // when the touch screen area is not within the activity range <br/> If (math. SQRT (math. pow (rockercirclex-(INT) event. getx (), 2) <br/> + math. pow (rockercircley-(INT) event. gety (), 2 )) >= Rockercircler) {<br/> // obtain the angle between the joystick and the touch screen. <br/> double temprad = getrad (rockercirclex, rockercircley, event. getx (), event. gety (); <br/> // limits the length of inner circular motion <br/> getxy (rockercirclex, rockercircley, rockercircler, temprad ); <br/>} else {// if the center of the ball is smaller than the active area, move it with the user's touch point. <br/> smallrockercirclex = (INT) event. getx (); <br/> smallrockercircley = (INT) event. gety (); <br/>}< br/>} else if (event. getaction () = motio Nevent. action_up) {<br/> // when the button is released, the joystick must be restored to the initial position <br/> smallrockercirclex = 100; <br/> smallrockercircley = 100; <br/>}< br/> return true; <br/>}< br/>/** <br/> * @ Param r <br/> * rotating point of the circular motion <br/> * @ Param centerx <br/> * rotation point x <br/> * @ Param centery <br/> * rotation point Y <br/> * @ Param rad <br/> * rotating radians <br/> */<br/> Public void getxy (float centerx, float centery, float R, double rad) {<br/> // obtains the X sit of the circular motion. <Br/> smallrockercirclex = (float) (R * Math. cos (RAD) + centerx; <br/> // obtain the Y coordinate of the circular motion <br/> smallrockercircley = (float) (R * Math. sin (RAD) + centery; <br/>}< br/> Public void draw () {<br/> try {<br/> canvas = SFH. lockcanvas (); <br/> canvas. drawcolor (color. white); <br/> // set the transparency <br/> paint. setcolor (0x70000000); <br/> // draw the joystick background <br/> canvas. drawcircle (rockercirclex, rockercircley, rockercircler, paint); <br /> Paint. setcolor (0x70ff0000); <br/> // draw the joystick <br/> canvas. drawcircle (smallrockercirclex, smallrockercircley, <br/> smallrockercircler, paint); <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/> Public void run () {<br/> // todo auto-generated method stub <br/> while (FLAG) {<br/> draw (); <br/> try {<br/> thread. sleep (50); <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/> log. V ("himi", "surfacedestroyed"); <br/>}< br/>}
If you want to beautify the joystick, ask your artist to give two circular charts. If you are waiting for something, add a joystick to your game ~ Wahaha
Well, in fact, this is just to introduce your ideas. In the specific book, I have encapsulated this into a joystick class. This is more oop. As for how to encapsulate it, you can design it as needed. Today's blog may not be very clear, because I am very confused --.
From writing a book to now, I have to go to bed at 3-4 o'clock every day. Alas, but I'm glad that if there are no special circumstances, the books will be handed in at the end of June. Let's look forward to it; I will continue to work hard for the last two months;
Project: http://www.himigame.com/android-game/384.html
By the way, all previously uploaded project resources have been adjusted to 0 points, and all are set to download for free for your convenience;