728x90
반응형
JMainActivity
package kr.appgrider.game
import android.graphics.PixelFormat
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import kr.appgrider.JoystickView
class JMainActivity : AppCompatActivity(), JoystickView.JoystickListener {
lateinit var testJoystick : JoystickView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//setContentView(R.layout.activity_jmain)
//var joystickView = JoystickView(this);
//setContentView(joystickView)
setContentView(R.layout.activity_jmain)
//var joystickView = JoystickView(this);
// initView()
}
// 뷰세팅
fun initView(){
testJoystick = findViewById(R.id.testJoystick)
testJoystick.setZOrderOnTop(true) // 최상단으로 올리고
testJoystick.holder.setFormat(PixelFormat.TRANSPARENT) // 배경투명하게
}
// 조이스틱 이동
override fun onJoystickMoved(xPercent: Float, yPercent: Float, source: Int) {
// xPercent 가 +이면 : 오른쪽
// xPercent 가 -이면 : 왼쪽
// yPercent 가 +이면 : 아래
// yPercent 가 -이면 : 위
// var direction : String ="방향 : ";
// if(yPercent > 0){
// direction = direction + "/ 아래 ";
// }else{
// direction = direction + "/ 위 ";
// }
// if(xPercent > 0){
// direction = direction + " 오른쪽 ";
// }else{
// direction = direction + " 왼쪽 ";
// }
// Log.d("Woongs","가로방향 : "+xPercent +" 세로방향 : "+yPercent);
// Log.d("Woongs","direction : "+direction);
}
}
xml
package kr.appgrider;
import static android.view.MotionEvent.ACTION_UP;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import androidx.annotation.NonNull;
public class JoystickView extends SurfaceView implements SurfaceHolder.Callback, View.OnTouchListener {
/*
https://www.instructables.com/A-Simple-Android-UI-Joystick/
* 1. SurfaceView 상속후 생성자 생성
* 2. SurfaceHolder.Callback implements 후 함수 implements
* 3. 생성자에 getHolder().addCallback(this); 이벤트 추가
* 4. jMain에 var joystickView = JoystickView(this); 인스턴스 생성후
* setContentView(R.layout.activity_jmain) 대신에 생성한 인스턴스를 넣는다.
* 5. 조이스틱 그리기 drawJoystick, setupDimensions 추가 surfaceCreated에 호출
* 6. View.OnTouchListener 구현
* 7. 조이스틱 제한하기 (피타고라스 정리) 읭? displacement , interface
* 8. jMain에 implements 및 값 표현
* 9. XML 에 JoystickView 추가
* */
float centerX;
float centerY;
float baseRadius;
float hatRadius;
private JoystickListener joystickCallback;
private final int ratio = 5;
public JoystickView(Context context) {
super(context);
getHolder().addCallback(this);
setOnTouchListener(this);
if(context instanceof JoystickListener){
joystickCallback = (JoystickListener) context;
setZOrderOnTop(true);
getHolder().setFormat(PixelFormat.TRANSPARENT);
}
}
public JoystickView(Context context, AttributeSet attrs) {
super(context, attrs);
getHolder().addCallback(this);
setOnTouchListener(this);
if(context instanceof JoystickListener){
joystickCallback = (JoystickListener) context;
setZOrderOnTop(true);
getHolder().setFormat(PixelFormat.TRANSPARENT);
}
}
public JoystickView(Context context, AttributeSet attrs, int style) {
super(context, attrs, style);
getHolder().addCallback(this);
setOnTouchListener(this);
if(context instanceof JoystickListener){
joystickCallback = (JoystickListener) context;
setZOrderOnTop(true);
getHolder().setFormat(PixelFormat.TRANSPARENT);
}
}
// 조이스틱 그리기
private void drawJoystick(float newX, float newY ){
if(getHolder().getSurface().isValid()){
// 해당 캔버스에 이제 그림그리기를 시작하기 위해 lock을 얻어왔다.
Canvas myCanvas = this.getHolder().lockCanvas();
Paint colors = new Paint();
myCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); // PorterDuff.Mode.CLEAR 빈 공백상태로 만들기
// 배경원
colors.setARGB(255,50,50,50);
myCanvas.drawCircle(centerX,centerY,baseRadius,colors);
// 조이스틱원
colors.setARGB(255,0,0,250);
myCanvas.drawCircle(newX,newY,hatRadius,colors);
getHolder().unlockCanvasAndPost(myCanvas);
}
}
private void setupDimensions(){
centerX = getWidth() / 2;
centerY = getHeight() / 2;
baseRadius = Math.min(getWidth(), getHeight()) / 3;
hatRadius = Math.min(getWidth(), getHeight()) / 5;
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if(view.equals(this)){ //지금의 SurfaceView에서만 오는 터치이벤트만 허용함
if(motionEvent.getAction() != ACTION_UP){ // 사용자가 스크린에서 손을 떼지 않았다는것을 확인
float displacement = (float) Math.sqrt(Math.pow(motionEvent.getX() - centerX, 2) + Math.pow(motionEvent.getY() - centerY, 2));
if(displacement < baseRadius){
drawJoystick(motionEvent.getX(),motionEvent.getY());
joystickCallback.onJoystickMoved((motionEvent.getX()-centerX) /baseRadius,(motionEvent.getY()-centerY)/baseRadius, getId());
}else{
float ratio = baseRadius/displacement;
float constrainX = centerX + (motionEvent.getX() - centerX) * ratio;
float constrainY = centerY + (motionEvent.getY() - centerY) * ratio;
drawJoystick(constrainX,constrainY);
joystickCallback.onJoystickMoved((constrainX-centerX) /baseRadius,(constrainY-centerY)/baseRadius, getId());
}
}else{ // 사용자가 손을떼면 조이스틱이 중앙위치로 재배치
drawJoystick(centerX,centerY);
joystickCallback.onJoystickMoved(0,0, getId());
}
}
// false를 반환하면 onTouch 메서드가 향후 터치를 수신하는 것을 방지하므로 true를 반환합니다.
return true;
}
@Override
public void surfaceCreated(@NonNull SurfaceHolder holder) {
setupDimensions();
drawJoystick(centerX,centerY);
}
@Override
public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
}
public interface JoystickListener
{
// 방향 백분률
// xPercent 가 +이면 : 오른쪽
// xPercent 가 -이면 : 왼쪽
// yPercent 가 +이면 : 아래
// yPercent 가 -이면 : 위
void onJoystickMoved(float xPercent, float yPercent, int source);
}
}
JoystickView
package kr.appgrider;
import static android.view.MotionEvent.ACTION_UP;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import androidx.annotation.NonNull;
public class JoystickView extends SurfaceView implements SurfaceHolder.Callback, View.OnTouchListener {
/*
https://www.instructables.com/A-Simple-Android-UI-Joystick/
* 1. SurfaceView 상속후 생성자 생성
* 2. SurfaceHolder.Callback implements 후 함수 implements
* 3. 생성자에 getHolder().addCallback(this); 이벤트 추가
* 4. jMain에 var joystickView = JoystickView(this); 인스턴스 생성후
* setContentView(R.layout.activity_jmain) 대신에 생성한 인스턴스를 넣는다.
* 5. 조이스틱 그리기 drawJoystick, setupDimensions 추가 surfaceCreated에 호출
* 6. View.OnTouchListener 구현
* 7. 조이스틱 제한하기 (피타고라스 정리) 읭? displacement , interface
* 8. jMain에 implements 및 값 표현
* 9. XML 에 JoystickView 추가
* */
float centerX;
float centerY;
float baseRadius;
float hatRadius;
private JoystickListener joystickCallback;
private final int ratio = 5;
public JoystickView(Context context) {
super(context);
getHolder().addCallback(this);
setOnTouchListener(this);
if(context instanceof JoystickListener){
joystickCallback = (JoystickListener) context;
setZOrderOnTop(true);
getHolder().setFormat(PixelFormat.TRANSPARENT);
}
}
public JoystickView(Context context, AttributeSet attrs) {
super(context, attrs);
getHolder().addCallback(this);
setOnTouchListener(this);
if(context instanceof JoystickListener){
joystickCallback = (JoystickListener) context;
setZOrderOnTop(true);
getHolder().setFormat(PixelFormat.TRANSPARENT);
}
}
public JoystickView(Context context, AttributeSet attrs, int style) {
super(context, attrs, style);
getHolder().addCallback(this);
setOnTouchListener(this);
if(context instanceof JoystickListener){
joystickCallback = (JoystickListener) context;
setZOrderOnTop(true);
getHolder().setFormat(PixelFormat.TRANSPARENT);
}
}
// 조이스틱 그리기
private void drawJoystick(float newX, float newY ){
if(getHolder().getSurface().isValid()){
// 해당 캔버스에 이제 그림그리기를 시작하기 위해 lock을 얻어왔다.
Canvas myCanvas = this.getHolder().lockCanvas();
Paint colors = new Paint();
myCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); // PorterDuff.Mode.CLEAR 빈 공백상태로 만들기
// 배경원
colors.setARGB(255,50,50,50);
myCanvas.drawCircle(centerX,centerY,baseRadius,colors);
// 조이스틱원
colors.setARGB(255,0,0,250);
myCanvas.drawCircle(newX,newY,hatRadius,colors);
getHolder().unlockCanvasAndPost(myCanvas);
}
}
private void setupDimensions(){
centerX = getWidth() / 2;
centerY = getHeight() / 2;
baseRadius = Math.min(getWidth(), getHeight()) / 3;
hatRadius = Math.min(getWidth(), getHeight()) / 5;
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if(view.equals(this)){ //지금의 SurfaceView에서만 오는 터치이벤트만 허용함
if(motionEvent.getAction() != ACTION_UP){ // 사용자가 스크린에서 손을 떼지 않았다는것을 확인
float displacement = (float) Math.sqrt(Math.pow(motionEvent.getX() - centerX, 2) + Math.pow(motionEvent.getY() - centerY, 2));
if(displacement < baseRadius){
drawJoystick(motionEvent.getX(),motionEvent.getY());
joystickCallback.onJoystickMoved((motionEvent.getX()-centerX) /baseRadius,(motionEvent.getY()-centerY)/baseRadius, getId());
}else{
float ratio = baseRadius/displacement;
float constrainX = centerX + (motionEvent.getX() - centerX) * ratio;
float constrainY = centerY + (motionEvent.getY() - centerY) * ratio;
drawJoystick(constrainX,constrainY);
joystickCallback.onJoystickMoved((constrainX-centerX) /baseRadius,(constrainY-centerY)/baseRadius, getId());
}
}else{ // 사용자가 손을떼면 조이스틱이 중앙위치로 재배치
drawJoystick(centerX,centerY);
joystickCallback.onJoystickMoved(0,0, getId());
}
}
// false를 반환하면 onTouch 메서드가 향후 터치를 수신하는 것을 방지하므로 true를 반환합니다.
return true;
}
@Override
public void surfaceCreated(@NonNull SurfaceHolder holder) {
setupDimensions();
drawJoystick(centerX,centerY);
}
@Override
public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
}
public interface JoystickListener
{
// 방향 백분률
// xPercent 가 +이면 : 오른쪽
// xPercent 가 -이면 : 왼쪽
// yPercent 가 +이면 : 아래
// yPercent 가 -이면 : 위
void onJoystickMoved(float xPercent, float yPercent, int source);
}
}
728x90
반응형
'Android' 카테고리의 다른 글
Android Gradle ?? - Android 빌드시스템 (0) | 2022.09.17 |
---|---|
Android UI 파편화 관련 (0) | 2022.09.01 |
(스크랩 ) android animation 종류 (0) | 2022.03.02 |
AAC : navigation (0) | 2022.02.21 |
android ISP 연동 관련 (0) | 2022.01.25 |