Saya telah menghabiskan banyak waktu untuk membaca tutorial dan melihat setiap pertanyaan yang terkait dengan multiTouch dari sini dan Stackoverflow. Tapi saya tidak tahu bagaimana melakukan ini dengan benar. Saya menggunakan loop untuk mendapatkan pointerId
, saya tidak melihat banyak orang melakukan ini tetapi satu-satunya cara saya berhasil membuatnya agak berfungsi.
Saya memiliki dua joystick di layar saya, satu untuk bergerak dan satu untuk mengendalikan rotasi sprite saya dan sudut yang dia tembak, seperti di Monster Shooter. Keduanya bekerja dengan baik.
Masalah saya adalah ketika saya Memindahkan sprite saya pada saat yang sama dengan pemotretan Im, touchingPoint
gerakan saya untuk saya diatur ke touchingPoint
pemotretan saya, karena x
dan y
lebih tinggi pada touchingPoint
pemotretan saya ( moving-stick
di sisi kiri layar, shooting-stick
di sisi kanan) , sprite saya mempercepat, ini menciptakan perubahan kecepatan yang tidak diinginkan untuk sprite saya.
beginilah cara saya menyelesaikannya dengan bantuan Anda! ini untuk siapa saja yang mungkin mengalami masalah serupa:
public void update(MotionEvent event) {
if (event == null && lastEvent == null) {
return;
} else if (event == null && lastEvent != null) {
event = lastEvent;
} else {
lastEvent = event;
}
int action = event.getAction();
int actionCode = action & MotionEvent.ACTION_MASK;
int pid = action >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
int x = (int) event.getX(pid);
int y = (int) event.getY(pid);
int index = event.getActionIndex();
int id = event.getPointerId(index);
String actionString = null;
switch (actionCode)
{
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
actionString = "DOWN";
try{
if(x > 0 && x < steeringxMesh + (joystick.get_joystickBg().getWidth() * 2)
&& y > yMesh - (joystick.get_joystickBg().getHeight()) && y < panel.getHeight()){
movingPoint.x = x;
movingPoint.y = y;
dragging = true;
draggingId = id;
}
else if(x > shootingxMesh - (joystick.get_joystickBg().getWidth()) && x < panel.getWidth()
&& y > yMesh - (joystick.get_joystickBg().getHeight()) && y < panel.getHeight()){
shootingPoint.x = x;
shootingPoint.y = y;
shooting=true;
shootingId=id;
}
}catch(Exception e){
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_OUTSIDE:
if(id == draggingId)
dragging = false;
if(id == shootingId)
shooting = false;
actionString = "UP";
break;
case MotionEvent.ACTION_MOVE:
for(index=0; index<event.getPointerCount(); index++) {
id=event.getPointerId(index);
int xx = (int) event.getX(index); //pro naming of variable
int yy = (int) event.getY(index);
if(dragging && id == draggingId) {
if(xx > 0 && xx < (steeringxMesh + joystick.get_joystickBg().getWidth() * 2)
&& yy > yMesh - (joystick.get_joystickBg().getHeight()) && yy < panel.getHeight()) {
movingPoint.x = xx;
movingPoint.y = yy;
}
else
dragging = false;
}
if(shooting && id == shootingId){
if(xx > shootingxMesh - (joystick.get_joystickBg().getWidth()) && xx < panel.getWidth()
&& yy > yMesh - (joystick.get_joystickBg().getHeight()) && yy < panel.getHeight()) {
shootingPoint.x = xx;
shootingPoint.y = yy;
}
else
shooting = false;
}
}
actionString = "MOVE";
break;
}
Log.d(TAG, "actionsString: " + actionString + ", pid: " + pid + ", x: " + x + ", y: " + y);
Tidak akan memposting kode sebanyak ini jika saya tidak benar-benar kehilangan apa yang saya lakukan salah. Saya benar-benar tidak bisa mendapatkan pemahaman yang baik tentang cara kerja multiTouching.
pada dasarnya movingPoint
perubahan untuk jari pertama dan kedua saya. Saya mengikatnya ke sebuah kotak, tetapi selama saya memegang satu jari di dalam kotak ini, itu mengubah nilainya berdasarkan di mana jari kedua saya menyentuh. Itu bergerak ke arah yang benar dan tidak ada yang memberikan kesalahan, masalahnya adalah perubahan kecepatan, hampir seperti menambahkan dua touchingPoints.
sumber
Anda hampir melakukannya dengan benar, tetapi Anda harus menggunakan id penunjuk untuk meminta X / Y alih-alih
i
Dari dokumentasi MotionEvent:
event.getX/Y
memerlukan id pointer, bukani
, karena tidak ada jaminan mereka akan berada dalam urutan yang sama.Selain itu, ada masalah lain yang halus namun penting. Perhatikan bagaimana rangkaian fungsi getAction () tidak mengambil parameter. Agak aneh, kan? Mendapatkan X / Y membutuhkan id pointer, tetapi bukankah tindakan dilakukan? Itu mengisyaratkan beberapa hal penting:
Jadi itu berarti Anda mendapatkan satu panggilan ke penangan sentuh Anda per tindakan pointer (turun / bergerak / naik). Jadi dua jari bergerak = 2 panggilan. Efek samping buruk dari kode Anda adalah bahwa ia menerapkan aksi dari satu peristiwa ke semua petunjuk ...
Jadi, alih-alih mengulangi jejak, cukup dapatkan tindakan pid / x / y / hanya untuk acara saat ini (untuk gerakan simultan, Anda akan mendapatkan panggilan lain ke handler Anda sedikit kemudian, seperti yang saya katakan)
Ini kode saya untuk menangani acara:
}
Untuk kembali ke kode Anda, Anda harus dapat menyederhanakannya dengan cara berikut. Loopnya hilang, jika tidak, jika Anda memiliki kendala lain yang tidak Anda sebutkan, Anda selalu dapat menambahkannya kembali. Ini bekerja dengan melacak id penunjuk mana yang digunakan untuk kontrol mana (bergerak / menembak) ketika BAWAH dipicu dan mengatur ulang mereka di ATAS. Karena Anda tidak menggunakan gerakan, Anda dapat membatasi sakelar () ke BAWAH, ATAS, MOVE dan LUAR.
sumber
sendTouchToGameEngine(pid, actionCode, (int)event.getX(pid), (int)event.getY(pid));
dilakukan baris ini dan kapan Anda menyebutnya?int pid = action >> MotionEvent.ACTION_POINTER_ID_SHIFT;
gerhana memberitahu saya untuk menambahkan supressWarning, apakah itu normal? Maaf untuk semua pertanyaan setelah jawaban terperinci seperti itu. MotionEvent sangat baru bagi saya, dan tidak dapat memahami logika karena beberapa alasanpid
, dan loop masih ada, tidak akan berfungsi tanpanya, karena saya harus mendapatkannyai
.Ada sedikit keanehan yang terjadi dengan kode ini. Saya tidak menggunakan Android, jadi mungkin saya berpikir ini adalah sesuatu yang bukan. Namun saya perhatikan Anda mendapatkan posisi itu dua kali, dengan dua cara berbeda:
Pertama Anda mendapatkannya seperti ini di awal
pointerCount
loop Anda :Kemudian, di dalam statement switch Anda, Anda mendapatkannya seperti ini:
Perhatikan bahwa Anda beralih dari menggunakan
i
ke menggunakanid
.Saya berasumsi itu seharusnya menjadi metode yang pertama. Saya sarankan mengganti semua instance
(int) event.getX(id)
dan menggunakan nilai yangx
Anda atur di awal. Demikian juga bertukar(int) event.getY(id)
key
.Cobalah menukar bagian-bagian ini:
Kemudian di dalam sakelar Anda gunakan ini:
sumber
x
dany
, tetapi Anda masih mendapatkan posisiid
nanti.x=event.getX(i)
), makax
harus menyimpan 2 nilai setiap kalipointerCount
lebih dari 1, benar? Dan itu terasa tidak enak.event
benar-benar daftar acara. Anda mengakses berbagai acara dengan menelusuri daftar seperti yang Anda lakukan. Jadi untuk mengaksesx
posisi untuk acara kedua yang Anda gunakanevent.getX(1)
(karena kita mulai dari 0). Ada beberapax
s, Anda menggunakan parameter untuk memberi tahu yang mana yang Anda inginkan. Anda mengulang semua peristiwa denganfor
loop Anda , jadi gunakan nomor itu sebagai peristiwa saat ini yang Anda minati. Lihat saran perubahan kode saya.Saya pernah mengalami masalah serupa pada Huawei U8150. Multitouch dua jari pada perangkat itu benar-benar buruk, menggunakan aplikasi tes multitouch (mungkin itu adalah "Phone Tester" tapi saya tidak yakin) Saya bisa melihat bahwa menyentuh dengan jari kedua memindahkan tempat sentuhan pertama dari banyak piksel . Jika itu masalah Anda daripada yang terkait dengan perangkat keras dan saya pikir Anda tidak bisa berbuat banyak untuk itu :(
Maaf untuk bahasa Inggris saya yang buruk
sumber
Saya percaya masalah Anda adalah bahwa Anda mengasumsikan bahwa, di antara pembaruan, urutan penunjuk diatur tetap sama. Kemungkinan besar itu tidak akan terjadi.
Bayangkan sebuah situasi di mana Anda menyentuh dengan jari A. Akan ada pointerCount () dari 1, dan A akan menjadi satu-satunya elemen yang bisa Anda tanyakan. Jika Anda menambahkan jari kedua, pointerCount () akan menjadi 2, A akan berada di indeks 0, B akan berada di indeks 1. Jika Anda menaikkan jari A, pointerCount () akan menjadi 1 lagi, dan B akan berada di indeks 0 . Jika Anda menyentuh dengan jari A lagi, A akan berada di indeks 1 dan B akan berada di indeks 0 .
Inilah sebabnya mengapa ID penunjuk disediakan, sehingga Anda dapat melacak setiap sentuhan di antara pembaruan. Jadi, jika sentuhan pertama jari B diberikan ID 12, ia akan selalu memiliki ID itu, bahkan ketika jari A dihapus dan ditambahkan kembali.
Jadi, jika kode Anda mengidentifikasi sentuhan di dekat joystick pemotretan Anda, ia harus memeriksa untuk melihat apakah sudah ada sentuhan 'pemotretan' yang sedang berlangsung. Jika tidak, maka ID dari sentuhan pemotretan harus diingat dalam beberapa variabel anggota yang tetap ada untuk pembaruan berikutnya. Di pembaruan berikutnya, jika Anda memiliki sentuhan 'pemotretan' sedang berlangsung, beralih melalui pointer dan cari pointer dengan ID yang tepat, dan itu pointer yang perlu Anda gunakan untuk melacak pembaruan, dan semua yang lain dapat diabaikan. Sama untuk sentuhan gerakan. Saat sentuhan dilepaskan, Anda menghapus ID yang terkait dengan joystick itu sehingga sentuhan baru dapat mengendalikannya.
Sekalipun sentuhan yang dimulai di dekat satu joystick jauh dari posisi sentuh semula, dengan ID-nya Anda masih dapat mengidentifikasi joystick apa yang dikontrolnya. Dan sebagai efek samping yang bagus, jari tersesat kedua di dekat joystick tertentu tidak akan memiliki efek apa pun, karena joystick akan terikat pada jari pertama yang memicu itu sampai dilepaskan.
sumber