[Android game development 24] 360 ° smooth game joystick (touch screen navigation)

Source: Internet
Author: User
Tags acos gety

 

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 360-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:

 

/***

* Obtain the radians between two points.

*/

Public double getRad (float px1, float py1, float px2, float py2 ){

// Obtain the distance between two points X.

Float x = px2-px1;

// Obtain the distance between two Y points.

Float y = py1-py2;

// Calculate the oblique edge Length

Float xie = (float) Math. sqrt (Math. pow (x, 2) + Math. pow (y, 2 ));

// Obtain the cosine of this angle (through the theorem in the trigonometric function: adjacent edge/Oblique Edge = angle cosine value)

Float cosAngle = x/xie;

// Obtain the radians of the angle using the arccosine theorem.

Float rad = (float) Math. acos (cosAngle );

// Note: When the position Y coordinate of the touch screen is <Y coordinate of the joystick, we need to take the inverse value-0 ~ -180

If (py2 <py1 ){

Rad =-rad;

}

Return rad;

}

 

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:

 

/**

*

* @ Param R

* Rotating point of the circular motion

* @ Param centerX

* Rotation point X

* @ Param centerY

* Rotation point Y

* @ Param rad

* Rotating radians

*/

Public void getXY (float centerX, float centerY, float R, double rad ){

// Obtain the X coordinate of the circular motion

SmallRockerCircleX = (float) (R * Math. cos (rad) + centerX;

// Obtain the Y coordinate of the circular motion

SmallRockerCircleY = (float) (R * Math. sin (rad) + centerY;

}

 

 

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;

Import android. content. Context;

Import android. graphics. Canvas;

Import android. graphics. Color;

Import android. graphics. Paint;

Import android. util. Log;

Import android. view. MotionEvent;

Import android. view. SurfaceHolder;

Import android. view. SurfaceView;

Import android. view. SurfaceHolder. Callback;

Public class MySurfaceView extends SurfaceView implements Callback, Runnable {

Private Thread th;

Private SurfaceHolder sfh;

Private Canvas canvas;

Private Paint paint;

Private boolean flag;

// Fixed the X, Y coordinates and radius of the circle on the rocker background

Private int rockercirclex= 100;

Private int rockercircle = 100;

Private int RockerCircleR = 50;

// The X and Y coordinates of the joystick and the radius of the joystick

Private float SmallRockerCircleX = 100;

Private float SmallRockerCircleY = 100;

Private float SmallRockerCircleR = 20;

Public MySurfaceView (Context context ){

Super (context );

Log. v ("Himi", "MySurfaceView ");

This. setKeepScreenOn (true );

Sfh = this. getHolder ();

Sfh. addCallback (this );

Paint = new Paint ();

Paint. setAntiAlias (true );

SetFocusable (true );

SetFocusableInTouchMode (true );

}

Public void surfaceCreated (SurfaceHolder holder ){

Th = new Thread (this );

Flag = true;

Th. start ();

}

/***

* Obtain the radians between two points.

*/

Public double getRad (float px1, float py1, float px2, float py2 ){

// Obtain the distance between two points X.

Float x = px2-px1;

// Obtain the distance between two Y points.

Float y = py1-py2;

// Calculate the oblique edge Length

Float xie = (float) Math. sqrt (Math. pow (x, 2) + Math. pow (y, 2 ));

// Obtain the cosine of this angle (through the theorem in the trigonometric function: adjacent edge/Oblique Edge = angle cosine value)

Float cosAngle = x/xie;

// Obtain the radians of the angle using the arccosine theorem.

Float rad = (float) Math. acos (cosAngle );

// Note: When the position Y coordinate of the touch screen is <Y coordinate of the joystick, we need to take the inverse value-0 ~ -180

If (py2 <py1 ){

Rad =-rad;

}

Return rad;

}

@ Override

Public boolean onTouchEvent (MotionEvent event ){

If (event. getAction () = MotionEvent. ACTION_DOWN |

Event. getAction () = MotionEvent. ACTION_MOVE ){

// When the touch screen area is out of the scope of activity

If (Math. sqrt (Math. pow (RockerCircleX-(int) event. getX (), 2)

+ Math. pow (RockerCircleY-(int) event. getY (), 2)> = RockerCircleR ){

// Obtain the angle between the joystick and the touch screen.

Double tempRad = getRad (RockerCircleX, RockerCircleY, event. getX (), event. getY ());

// Ensure the length limit of inner Small circular motion

GetXY (RockerCircleX, RockerCircleY, RockerCircleR, tempRad );

} Else {// if the center of the ball is smaller than the active area, move it with the user's touch point.

SmallRockerCircleX = (int) event. getX ();

SmallRockerCircleY = (int) event. getY ();

}

} Else if (event. getAction () = MotionEvent. ACTION_UP ){

// When the button is released, the joystick must be restored to its initial position.

Smallrockercirclex= 100;

SmallRockerCircleY = 100;

}

Return true;

}

/**

*

* @ Param R

* Rotating point of the circular motion

* @ Param centerX

* Rotation point X

* @ Param centerY

* Rotation point Y

* @ Param rad

* Rotating radians

*/

Public void getXY (float centerX, float centerY, float R, double rad ){

// Obtain the X coordinate of the circular motion

SmallRockerCircleX = (float) (R * Math. cos (rad) + centerX;

// Obtain the Y coordinate of the circular motion

SmallRockerCircleY = (float) (R * Math. sin (rad) + centerY;

}

Public void draw (){

Try {

Canvas = sfh. lockCanvas ();

Canvas. drawColor (Color. WHITE );

// Set transparency

Paint. setColor (0x70000000 );

// Draw the joystick background

Canvas. drawCircle (RockerCircleX, RockerCircleY, RockerCircleR, paint );

Paint. setColor (0x70ff0000 );

// Draw the joystick

Canvas. drawCircle (SmallRockerCircleX, SmallRockerCircleY,

SmallRockerCircleR, paint );

} Catch (Exception e ){

// TODO: handle exception

} Finally {

Try {

If (canvas! = Null)

Sfh. unlockCanvasAndPost (canvas );

} Catch (Exception e2 ){

}

}

}

Public void run (){

// TODO Auto-generated method stub

While (flag ){

Draw ();

Try {

Thread. sleep (50 );

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

Log. v ("Himi", "surfaceDestroyed ");

}

}

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.bkjia.com/uploadfile/2011/1115/20111115053515741.rar

 

 

Himi original, reprinted must indicate the source!

Address: http://blog.csdn.net/xiaominghimi/archive/2011/05/16/6423983.aspx

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.