Android Multitouch Issues - java

This is a fairly simple question I am sure, but I can't seem to figure out a way around this little thing. First, here is my code:
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
Log.w("Platformer", "primary down");
break;
case MotionEvent.ACTION_UP:
Log.w("Platformer", "primary up");
break;
case MotionEvent.ACTION_POINTER_1_DOWN:
Log.w("Platformer", "secondary down");
break;
case MotionEvent.ACTION_POINTER_1_UP:
Log.w("Platformer", "secondary up");
break;
}
All I wanted it to do was when I pressed down, it would show me in the log whether the primary or secondary pointer was down, and when I release, do the same thing. The problem is, it always works on the down, but on up, whatever the 1st finger that comes up is, regardless of if it was the primary or secondary pointer originally, it returns that the secondary pointer was removed. Any idea around this? I am guessing it is something simple, but I don't know where to look truthfully. Thanks in advance.
WWaldo

ACTION_UP means that the gesture is over, that is, all pointers are up.
ACTION_POINTER_UP means that a non-primary pointer is up, you'll have to check the event to figure out which, i.e.:
int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
MotionEvent.ACTION_POINTER_INDEX_SHIFT;
int pointerId = event.getPointerId(pointerIndex)
ACTION_POINTER_1_UP and ACTION_POINTER_2_UP are deprecated now.
You should note that this is extremely buggy on Android versions less than Gingerbread. I find that if I lift the first of two touches and place it back down, the pointers swap index and ID. Very frustrating.

Use getPointerId to get which pointer is being selected.
Edit
To answer the question in the comment, try:
for (int i = 0; i < ev.getPointerCount(); i++) {
switch (ev.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
Log.d(TAG,"down "+ ev.getPointerId(i));
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG,"move "+ ev.getPointerId(i));
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
Log.d(TAG,"up "+ ev.getPointerId(i));
break;
}
}

Related

Changing Recycler View item based on its data

So I have a POJO with a question, and in my recycler I wanna show a question itself with answers and correct answer should have the background color.
When I try to add background color, items get colored based on some serious magic.
First few items do not get any color, and closer to the bottom of the recycler here is what happens.
enter image description here
The further the better, when I scroll from the bottom to the top, items at the top get the color as well.
public void bind(Question question) {
int correctAnswerNumber = question.getCorrectAnswer();
switch (correctAnswerNumber) {
case 1:
answer1.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
case 2:
answer2.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
case 3:
answer3.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
case 4:
answer4.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
}
}
The context here is passed from the activity, and I have to ideas what to do.
I tried to remove the logic to the constructor, change the context, address items through holder, didn't change much.
You have a classic case of "stale state from a recycled view item".
Your Problem
You only set the background for a correct answer. When that item view is recycled and used for an incorrect answer, you are not updating it and it keeps the old background that was set on it.
The Solution
Always explicitly set the full state of a recycler item view. In this case, set the background for whatever it should be when it's not a correct answer.
public void bind(Question question) {
int correctAnswerNumber = question.getCorrectAnswer();
// Reset all backgrounds to default before setting the current correct one
answer1.setBackground(getDefaultBackgroundBorder());
answer2.setBackground(getDefaultBackgroundBorder());
answer3.setBackground(getDefaultBackgroundBorder());
answer4.setBackground(getDefaultBackgroundBorder());
switch (correctAnswerNumber) {
case 1:
answer1.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
case 2:
answer2.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
case 3:
answer3.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
case 4:
answer4.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
}
}

Button needs to be clicked twice. Any ideas why?

Basically what I'm trying to do is setting the color of the buttons. The "ganzjahrbutton" includes the other buttons. Therefore I wanna change the color of all the buttons (besides the ganzjahrbutton) to the grey color (162,162,162) if it's clicked.
If any of the other buttons is clicked, they should turn green and the ganzjahrbutton should become grey again. It kinda works, but the buttons need to be pressed twice.
Does anybody have an idea why?
switch (v.getId()){
case R.id.ganzjahrbutton:
ganzjahrbtnstate = !ganzjahrbtnstate;
if (ganzjahrbtnstate==true){
ganzjahrbutton.setBackgroundColor(Color.rgb(30,168,1));
fruhlungbutton.setBackgroundColor(Color.rgb(162,162,162));
sommerbutton.setBackgroundColor(Color.rgb(162,162,162));
herbstbutton.setBackgroundColor(Color.rgb(162,162,162));
winterbutton.setBackgroundColor(Color.rgb(162,162,162));
}
else {ganzjahrbutton.setBackgroundColor(Color.rgb(162,162,162));}
break;
case R.id.fruhlingbutton:
fruhlingbtnstate = !fruhlingbtnstate;
if (fruhlingbtnstate==true){fruhlungbutton.setBackgroundColor(Color.rgb(30,168,1));
ganzjahrbutton.setBackgroundColor(Color.rgb(162,162,162)); }
else {fruhlungbutton.setBackgroundColor(Color.rgb(162,162,162));}
break;
case R.id.sommerbutton:
sommerbtnstate = !sommerbtnstate;
if (sommerbtnstate==true){sommerbutton.setBackgroundColor(Color.rgb(30,168,1));
ganzjahrbutton.setBackgroundColor(Color.rgb(162,162,162)); }
else {sommerbutton.setBackgroundColor(Color.rgb(162,162,162));}
break;
case R.id.herbstbutton:
herbstbtnstate = !herbstbtnstate;
if (herbstbtnstate==true){herbstbutton.setBackgroundColor(Color.rgb(30,168,1));
ganzjahrbutton.setBackgroundColor(Color.rgb(162,162,162)); }
else {herbstbutton.setBackgroundColor(Color.rgb(162,162,161));}
break;
case R.id.winterbutton:
winterbtnstate = !winterbtnstate;
if (winterbtnstate==true){winterbutton.setBackgroundColor(Color.rgb(30,168,1));
ganzjahrbutton.setBackgroundColor(Color.rgb(162,162,162)); }
else {winterbutton.setBackgroundColor(Color.rgb(162,162,162));}
break;
Move the lines where you change the boolean states to the end of cases just before break statements
case R.id.ganzjahrbutton:
****FROM HERE*****ganzjahrbtnstate = !ganzjahrbtnstate;****
if (ganzjahrbtnstate==true){
ganzjahrbutton.setBackgroundColor(Color.rgb(30,168,1));
fruhlungbutton.setBackgroundColor(Color.rgb(162,162,162));
sommerbutton.setBackgroundColor(Color.rgb(162,162,162));
herbstbutton.setBackgroundColor(Color.rgb(162,162,162));
winterbutton.setBackgroundColor(Color.rgb(162,162,162));
}
else {ganzjahrbutton.setBackgroundColor(Color.rgb(162,162,162));}
TO HERE*****ganzjahrbtnstate = !ganzjahrbtnstate;****
break;

Best way to create options in RPG

I am following a tutorial I found on youtube on creating a basic RPG with a GUI. The tutorial is very helpful in giving directions on how to handle panels and frames, but the way they handle user decisions seems very impractical. They have a switch case that uses the player's location, and then another switch case within that then handles the actions depending on what button the user enters. Im not saying that it doesn't get the job done, but it leads me to have a LONG switch case. I was wondering what would be the best approach to have a cleaner and more manageable code.
snippet of the code:
//depending on your position, you are given different action options
switch(position) {
//if you are in town, these are your options
case "townGate":
switch(yourOption) {
//talk to the guard
case "c1": talkGaurd(); break;
//attack the guard
case "c2": attackGuard(); break;
}
break;
//if you are talking to the guard, these are your options
case "talkingToGaurd":
switch(yourOption) {
//leave to the outside of the gate
case "c1": townGate(); break;
}
break;
//if you are attacking the guard, these are your options
case "attackingGuard":
switch(yourOption) {
//leave the the outside of the gate
case "c1": townGate(); break;
}
break;
}

Android - ACTION_UP not detected

I am unable to figure out why the ACTION_UP event is not being fired when I move my finger away from contact in the following code.
public boolean onTouch(View v, MotionEvent event) {
switch(event.getActionIndex()){
case MotionEvent.ACTION_UP:
Utils.log("Touch Up");
break;
case MotionEvent.ACTION_DOWN:
Utils.log("Touch Down");
break;
}
return true;
}
You should use getActionMasked().
getAction() returns single pointer events (and deprecated multiple pointer events...)
getActionMasked() returns single and multiple pointer events (use with getActionIndex() to determine which pointer),
getActionIndex() returns only the pointer index.
So getActionIndex() returns which finger performed a down / up action (0, 1, 2, etc.) While getAction() or getActionMasked() return the single pointer events you want (ACTION_DOWN, ACTION_UP, etc.)
Replace your code with mine.
public boolean onTouch(View v, MotionEvent event) {
//Here's the problem
switch(event.getAction()){
case MotionEvent.ACTION_UP:
Utils.log("Touch Up");
break;
case MotionEvent.ACTION_DOWN:
Utils.log("Touch Down");
break;
}
return true;
}
For others having a similar problem, one of the reasons why ACTION_UP is not fired could be overly sensitive ACTION_MOVE. In this case, ACTION_UP never gets fired because system interprets touch action as ACTION_MOVE and fires it instead.
A solution for that is to check when ACTION_MOVE happens if x and y offset is big enough to handle it as ACTION_MOVE, otherwise, you can threat it as ACTION_UP.
Here is SO example.

How should i program mouse/key input in an advanced java game?

I am a self taught programmer, so I do not know the proper ways to do things. I have made simple games like asteroids and snake, but in those games, you can easily modify the variables within the keyevent functions. Here is how I did it in my simple Asteroids game:
/*
* key listener events
*/
public void keyReleased(KeyEvent k){
int keyCode = k.getKeyCode();
switch(keyCode){
case KeyEvent.VK_LEFT:
turnLeft = false;
break;
case KeyEvent.VK_RIGHT:
turnRight = false;
break;
case KeyEvent.VK_UP:
accel = false;
break;
case KeyEvent.VK_1:
cls = true;
break;
case KeyEvent.VK_ENTER:
break;
case KeyEvent.VK_SPACE:
fire = false;
}
}
public void keyTyped(KeyEvent K){}
public void keyPressed(KeyEvent k){
int keyCode = k.getKeyCode();
switch(keyCode){
case KeyEvent.VK_LEFT:
turnLeft = true;
break;
case KeyEvent.VK_RIGHT:
turnRight = true;
break;
case KeyEvent.VK_UP:
accel = true;
break;
case KeyEvent.VK_1:
cls = false;
break;
case KeyEvent.VK_ENTER:
clearAllBullets();
break;
case KeyEvent.VK_SPACE:
fire = true;
}
}
If I were to make a more advanced game (with a main menu, options, main game, etc.) How should I do the key/mouse input?
Also, if I were to go into the single-player, should I put all of the gameplay code into one class? Is there a way to put the single player code into a separate class and somehow have the key input still modify the variables and such?
Thank you for your time!
P.S. Any links or source is extremely appreciated. :D
"Is there a way to put the single player code into a separate class and somehow have the key input still modify the variables and such?"
Yes, there is way to encapsulate all event-based behaviours- http://en.wikipedia.org/wiki/Mediator_pattern but, it can make yor code very complicated, so firstly try to implement your game in more "normal" way.
Anyway - you will need other classes, to present domain model of your game (Player, Gameboard, UserInterfaces etc...)

Categories

Resources