During this time, I studied Android custom controls and remembered that the implementation of the joystick in the game was quite interesting. So I wrote a set of familiar ones myself. There are also many features on surfaceview, so I will not repeat them here, anyway, drawing is quite easy to use. I never say goodbye to the era of using Java GUI to manually implement double buffering ......
Android content:
- Android floating search box development and Configuration
- Android client request server resource tutorial
- Android SQLite operation addition, deletion, modification, and subtraction tutorial
- How does Android save files?
- HTML and XML escape characters in Android
Import com. Game. Graphics. utils. mathutils;
Import Android. content. context;
Import Android. Graphics. Canvas;
Import Android. Graphics. color;
Import Android. Graphics. paint;
Import Android. Graphics. pixelformat;
Import Android. Graphics. Point;
Import Android. Graphics. porterduff. mode;
Import Android. util. attributeset;
Import Android. View. motionevent;
Import Android. View. surfaceholder;
Import Android. View. surfaceview;
Import Android. View. surfaceholder. Callback;
Public class rudder extends surfaceview implements runnable, callback {
Private surfaceholder mholder;
Private Boolean isstop = false;
Private thread mthread;
Private paint mpaint;
Private point mrockerposition; // joystick position
Private point mctrlpoint = new point (80, 80); // the starting position of the joystick.
Private int mrudderradius = 20; // joystick radius
Private int mwheelradius = 60; // radius of the Active range of the joystick
Private rudderlistener listener = NULL; // Event Callback Interface
Public static final int action_rudder = 1, action_attack = 2; // 1: joystick event 2: button event (not implemented)
Public rudder (context ){
Super (context );
}
Public rudder (context, attributeset ){
Super (context, );
This. setkeepscreenon (true );
Mholder = getholder ();
Mholder. addcallback (this );
Mthread = new thread (this );
Mpaint = new paint ();
Mpaint. setcolor (color. Green );
Mpaint. setantialias (true); // anti-aliasing
Mrockerposition = new point (mctrlpoint );
Setfocusable (true );
Setfocusableintouchmode (true );
Setzorderontop (true );
Mholder. setformat (pixelformat. Transparent); // sets the background transparency.
}
// Set the callback Interface
Public void setrudderlistener (rudderlistener rockerlistener ){
Listener = rockerlistener;
}
@ Override
Public void run (){
Canvas canvas = NULL;
While (! Isstop ){
Try {
Canvas = mholder. lockcanvas ();
Canvas. drawcolor (color. Transparent, mode. Clear); // clear the screen
Mpaint. setcolor (color. Cyan );
Canvas. drawcircle (mctrlpoint. X, mctrlpoint. Y, mwheelradius, mpaint); // draw range
Mpaint. setcolor (color. Red );
Canvas. drawcircle (mrockerposition. X, mrockerposition. Y, mrudderradius, mpaint); // draw the joystick
} Catch (exception e ){
E. printstacktrace ();
} Finally {
If (canvas! = NULL ){
Mholder. unlockcanvasandpost (canvas );
}
}
Try {
Thread. Sleep (30 );
} Catch (interruptedexception e ){
E. printstacktrace ();
}
}
}
@ Override
Public void surfacechanged (surfaceholder holder, int format, int width,
Int height ){
}
@ Override
Public void surfacecreated (surfaceholder holder ){
Mthread. Start ();
}
@ Override
Public void surfacedestroyed (surfaceholder holder ){
Isstop = true;
}
@ Override
Public Boolean ontouchevent (motionevent event ){
Int Len = mathutils. getlength (mctrlpoint. X, mctrlpoint. Y, event. getx (), event. Gety ());
If (event. getaction () = motionevent. action_down ){
// If the screen contact point is not within the rocker wave range, do not process it
If (LEN> mwheelradius ){
Return true;
}
}
If (event. getaction () = motionevent. action_move ){
If (LEN <= mwheelradius ){
// If the finger is in the active range of the joystick, the joystick is in the touch position of the finger
Mrockerposition. Set (INT) event. getx (), (INT) event. Gety ());
} Else {
// Set the joystick position so that it is at the edge of the Active range of the joystick in the direction of the finger touch
Mrockerposition = mathutils. getborderpoint (mctrlpoint,
New Point (INT) event. getx (), (INT) event. Gety (), mwheelradius );
}
If (listener! = NULL ){
Float radian = mathutils. getradian (mctrlpoint, new point (INT) event. getx (), (INT) event. Gety ()));
Listener. onsteeringwheelchanged (action_rudder, rudder. This. getanglecouvert (radian ));
}
}
// If the finger leaves the screen, the joystick returns the initial position
If (event. getaction () = motionevent. action_up ){
Mrockerposition = new point (mctrlpoint );
}
Return true;
}
// Obtain the joystick offset from 0 to °.
Private int getanglecouvert (float radian ){
Int TMP = (INT) math. Round (radian/Math. Pi * 180 );
If (TMP <0 ){
Return-TMP;
} Else {
Return 180 + (180-TMP );
}
}
// Callback Interface
Public interface rudderlistener {
Void onsteeringwheelchanged (INT action, int angle );
}
}
Import Android. Graphics. Point;
Public class mathutils {
// Obtain the linear distance between two points
Public static int getlength (float X1, float Y1, float X2, float Y2 ){
Return (INT) math. SQRT (math. Pow (x1-x2, 2) + math. Pow (y1-y2, 2 ));
}
/**
* Obtains the coordinates of a point on a line segment. The length is A. X-cutradius.
* @ Param A:
* @ Param B point B
* @ Param cutradius truncation distance
* @ Return truncation point
*/
Public static point getborderpoint (point a, point B, int cutradius ){
Float radian = getradian (A, B );
Return new point (. X + (INT) (cutradius * Math. cos (radian),. X + (INT) (cutradius * Math. sin (radian )));
}
// Obtain the angle radians of the horizontal line
Public static float getradian (point a, point B ){
Float Lena = B. x-a.x;
Float lenb = B. y-a.y;
Float lenc = (float) math. SQRT (Lena * Lena + lenb * lenb );
Float ang = (float) math. ACOs (Lena/lenc );
Ang = ang * (B. Y <A. Y? -1: 1 );
Return Ang;
}
}
<? XML version = "1.0" encoding = "UTF-8"?>
<Framelayout xmlns: Android = "http://schemas.android.com/apk/res/android"
Android: Orientation = "vertical"
Android: layout_width = "fill_parent"
Android: layout_height = "fill_parent">
<Imageview
Android: layout_width = "fill_parent"
Android: layout_height = "fill_parent"
Android: scaletype = "fitxy"
Android: src = "@ drawable/xx"/>
<Relativelayout
Android: Id = "@ + ID/ctrls"
Android: layout_width = "fill_parent"
Android: layout_height = "fill_parent">
<Com. Game. Demo. Views. Rudder
Android: Id = "@ + ID/Rudder"
Android: layout_width = "480dip"
Android: layout_height = "160dip"
Android: layout_alignparentbottom = "true"
Android: layout_centerhorizontal = "true"/>
</Relativelayout>
</Framelayout>
Setcontentview (R. layout. Main );
Rudder rudder = (rudder) findviewbyid (R. Id. Rudder );
Rudder. setrudderlistener (New rudderlistener (){
@ Override
Public void onsteeringwheelchanged (INT action, int angle ){
If (Action = rudder. action_rudder ){
// Todo: Event implementation
}
}
});