How to disable multitouch in Android in cocos2d-x 3.2 - cocos2d-x

I am setting handlers for single touch in this way
auto touchListener = EventListenerTouchOneByOne::create();
touchListener->setSwallowTouches(true);
touchListener->onTouchBegan = CC_CALLBACK_2(MyClass::onTouchBegan, this);
touchListener->onTouchMoved = CC_CALLBACK_2(MyClass::onTouchMoved, this);
touchListener->onTouchEnded = CC_CALLBACK_2(MyClass::onTouchEnded, this);
auto dispatcher = Director::getInstance()->getEventDispatcher();
dispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
For iOS it works properly, but for Android if I touch the screen with two fingers in the same time it will call onTouchBegan twice.
How can I disable multitouch from cocos2d-x (3.2) code for Android?

I found a workaround, since cocos2d-x doesn't have an official solution for this. (using Cocos2d-x 3.2)
Since each touch has it's own ID, we just need to filter first touch ID from others.
I have achieved this in the following way:
Created layer's instance variable:
int _currentTouchID;
Initialised it with -1 in layer's init() method:
_currentTouchID = -1;
In the beginign of all touch handlers I did next:
bool MyClass::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *event)
{
if (_currentTouchID < 0) {
_currentTouchID = touch->getID();
}
else {
return false;
}
//Your code here
return true;
}
void MyClass::onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *event)
{
if (_currentTouchID != touch->getID()) {
return;
}
//Your code here
}
void MyClass::onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *event)
{
if (_currentTouchID == touch->getID()) {
_currentTouchID = -1;
}
else {
return;
}
//Your code here
}
That's it. Please provide your solution if you have found a better one.
BTW: Commenting the switch case MotionEvent.ACTION_POINTER_DOWN: in Cocos2dxGLSurfaceView.java file,
as it was offered on cocos2d-x forum, didn't work for me.

Related

how to do a button click in Xamarin Forms Android custom info window

In my Xamarin Forms Android project I am showing a Map using CustomMapRenderer. I am popping up a Info Window in Map screen and this info window has button name called "Call". I need to do a "OnCLick" button click operation for this button. I have googled it, but unfortunately I didn't come across any solutions. at last I have started to work on converting the Android Native code -Java into Xamarin Forms Android - c#, for this conversion I have been using this answers Google Maps Android API v2 - Interactive InfoWindow (like in original android google maps) . This converted code shows A field initializer cannot reference the non static field, method or property OnInfoWindowElemTouchListener.onClickConfirmed(view, marker) this Error inside Java.Lang.Runnable please help me to resolve the problem.
OnInfoWindowElemTouchListener.cs
using System.Threading.Tasks;
using Android.App;
using Android.Content;
using Android.Gms.Maps.Model;
using Android.Graphics.Drawables;
using Android.OS;
using Android.Views;
using Android.Views.Accessibility;
using Java.Lang;
namespace Hotel.Droid
{
public abstract class OnInfoWindowElemTouchListener : Java.Lang.Object
, View.IOnTouchListener
{
private View view;
private Drawable bgDrawableNormal;
private Drawable bgDrawablePressed;
private Handler handler = new Handler();
private Marker marker;
private static bool endPressStatus = false;
private bool pressed = false;
public OnInfoWindowElemTouchListener(View view, Drawable bgDrawableNormal, Drawable bgDrawablePressed)
{
this.view = this.view;
this.bgDrawableNormal = this.bgDrawableNormal;
this.bgDrawablePressed = this.bgDrawablePressed;
}
public OnInfoWindowElemTouchListener()
{
}
public void setMarker(Marker marker)
{
this.marker = this.marker;
}
public bool OnTouch(View vv, MotionEvent e)
{
if (0 <= e.GetX() && e.GetX() <= vv.Width && 0 <= e.GetY() && e.GetY() <= vv.Height)
{
switch (e.ActionMasked)
{
case MotionEventActions.Down:
startPress();
break;
// We need to delay releasing of the view a little so it shows the
// pressed state on the screen
case MotionEventActions.Up:
//handler.PostDelayed(ConfirmClickRunnable, 150);
Task.Factory.StartNew(() => onClickConfirmed(view, marker));
Task.Delay(150);
break;
case MotionEventActions.Cancel:
endPress();
break;
default:
break;
}
}
else {
// If the touch goes outside of the view's area
// (like when moving finger out of the pressed button)
// just release the press
endPress();
}
return false;
}
private void startPress()
{
if (!pressed)
{
pressed = true;
//handler.RemoveCallbacks(ConfirmClickRunnable);
view.SetBackgroundDrawable(bgDrawablePressed);
if ((marker != null))
{
marker.ShowInfoWindow();
}
}
}
public bool endPress()
{
if (pressed)
{
this.pressed = false;
handler.RemoveCallbacks(ConfirmClickRunnable);
view.SetBackgroundDrawable(bgDrawableNormal);
if ((marker != null))
{
marker.ShowInfoWindow();
}
endPressStatus = true;
return true;
}
else {
endPressStatus = false;
return false;
}
}
private Runnable ConfirmClickRunnable = new Java.Lang.Runnable(() =>
{
if (endPressStatus)
{
onClickConfirmed(view, marker);
}
});
/*private class RunnableAnonymousInnerClassHelper : Java.Lang.Object, Java.Lang.IRunnable
{
private readonly Context outerInstance;
public RunnableAnonymousInnerClassHelper(Context outerInstance)
{
this.outerInstance = outerInstance;
}
public void Run()
{
if (endPressStatus)
{
onClickConfirmed();
}
}
}*/
protected abstract void onClickConfirmed(View v, Marker marker);
}
}
Updated
I have implemented the Task.Factory.StartNew instead of Android Runnableand now I am stucking on the below lines. I am struggling on converting this below Java codes into C#since it is written by Anonymous class concept.
Java
this.infoButtonListener = new OnInfoWindowElemTouchListener(infoButton,
getResources().getDrawable(R.drawable.btn_default_normal_holo_light),
getResources().getDrawable(R.drawable.btn_default_pressed_holo_light))
{
#Override
protected void onClickConfirmed(View v, Marker marker) {
// Here we can perform some action triggered after clicking the button
Toast.makeText(MainActivity.this, marker.getTitle() + "'s button clicked!", Toast.LENGTH_SHORT).show();
}
};
this.infoButton.setOnTouchListener(infoButtonListener);
infoButton in code is Call button
C# - Please help me to resolve the problem by converting/using(How to use) the above java code
The solution is too complicated for this window. Please see chat room for step by step solution.
https://chat.stackoverflow.com/rooms/128847/discussion-between-jamal-and-yuri-s

Cocos2d-x 3.0rc not detecting touches

In the new cocos2d-x 3.0rc I wanted to detect touch in a Layer. I have over ridden functions in my class as mentioned below.
virtual bool onTouchBegan(CCTouch* touch, CCEvent* event);
virtual void onTouchMoved(CCTouch* touch, CCEvent* event);
virtual void onTouchEnded(CCTouch* touch, CCEvent* event);
but touches are not getting detected. Any idea y is this happening?
To enable touches I used the below code. works perfectly in cocos2d-x 3.0 RC1
void class_name::onEnter()
{
Layer::onEnter();
// Register Touch Event
auto dispatcher = Director::getInstance()->getEventDispatcher();
auto listener = EventListenerTouchOneByOne::create();
listener->onTouchBegan = CC_CALLBACK_2(class_name::onTouchBegan, this);
listener->onTouchMoved = CC_CALLBACK_2(class_name::onTouchMoved, this);
listener->onTouchEnded = CC_CALLBACK_2(class_name::onTouchEnded, this);
dispatcher->addEventListenerWithSceneGraphPriority(listener, this);
}
Detect Touch in Cocos2d-x 3.0
write code in (HelloWorld.h)
{
cocos2d::EventListenerTouchAllAtOnce *Listner;
void onTouchesBegan(const std::vector<cocos2d::Touch *> &touches, cocos2d::Event *event);
void onTouchesMoved(const std::vector<cocos2d::Touch *> &touches, cocos2d::Event *event);
void onTouchesEnded(const std::vector<cocos2d::Touch *> &touches, cocos2d::Event *event);
}
write code in init Method(HelloWorld.cpp)
{
Listner = EventListenerTouchAllAtOnce::create();
Listner->onTouchesBegan = CC_CALLBACK_2(HelloWorld::onTouchesBegan, this);
Listner->onTouchesMoved = CC_CALLBACK_2(HelloWorld::onTouchesMoved, this);
Listner->onTouchesEnded = CC_CALLBACK_2(HelloWorld::onTouchesEnded, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(Listner, this);
}
enable touch on init() Or onEnter()
this->setTouchEnabled(true);
CCDirector::sharedDirector() -> getTouchDispatcher() -> addTargetedDelegate( this, 0, true );

Using ccTouchBegan and ccTouchesEnded at the same time in Cocos2dx

Can I use ccTouchBegan and ccTouchesEnded at the same time?
When I'm trying to add actions in ccTouchBegan, I recognize that ccTouchesEnded isn't called. Can anyone explain for me how to use touch events?
Some of my code
bool GameplayScene::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent){
CCActionInterval* actionBy = CCRotateBy::create(1, 180);
weapon->runAction(CCSequence::create(actionBy, NULL, NULL));
location = pTouch->getLocation();
shootBullet();
this->schedule(schedule_selector(GameplayScene::shootBullet), 1.0);
return true;
}
void GameplayScene::ccTouchesEnded(cocos2d::CCSet* touches, cocos2d::CCEvent* event){
this->unschedule(schedule_selector(GameplayScene::shootBullet));
}
void GameplayScene::registerWithTouchDispatcher(void) {
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, INT_MIN + 1, true);
}
First you are using ccTouchBegan and ccTouchesEnded, you could use ccTouchesBegan.
To use ccTouchesBegan and ccTouchesEnded, you need to set:
layer->setTouchEnabled(true);
where layer is the main layer of your Gameplay scene.

How to make html5 full screen in Libgdx?

Does anyone know how to set the canvas full screen in HTML5 LibGDX?
I only find width and height property in GwtApplicationConfiguration.
I'm using a Stage so I had to use an InputMultiplexer to send input to both my Stage and the InputAdapter that handles fullscreen GWT requests.
InputAdapter webGlfullscreen = new InputAdapter() {
#Override
public boolean keyUp (int keycode) {
if (keycode == Keys.ENTER && Gdx.app.getType() == ApplicationType.WebGL) {
if (!Gdx.graphics.isFullscreen()) Gdx.graphics.setDisplayMode(Gdx.graphics.getDisplayModes()[0]);
}
return true;
}
};
Gdx.input.setInputProcessor(new InputMultiplexer(webGlfullscreen, stage));

CCScrollView with CCControlButton. How to control the touch area?

I have CCScrollView with container with CCControlButtons, when the buttons scroll out of the visible CCScrollView area, They are also can be touched too. How can I control the area ?
Inspired by Tomasz's answer, I created an alternative solution, also inheriting from CCControlButton:
bool ScrollableButton::isTouchInside(CCTouch *touch) {
return !dragging && CCControlButton::isTouchInside(touch);
}
bool ScrollableButton::ccTouchBegan(CCTouch *touch, CCEvent *event) {
dragging = false;
return CCControlButton::ccTouchBegan(touch, event);
}
void ScrollableButton::ccTouchMoved(CCTouch *touch, CCEvent *event) {
if (!dragging && ccpDistance(touch->getLocation(), touch->getStartLocation()) > 25) {
dragging = true;
}
CCControlButton::ccTouchMoved(touch, event);
}
void ScrollableButton::ccTouchEnded(CCTouch *touch, CCEvent *event) {
CCControlButton::ccTouchEnded(touch, event);
dragging = false;
}
void ScrollableButton::ccTouchCancelled(CCTouch *touch, CCEvent *event) {
CCControlButton::ccTouchCancelled(touch, event);
dragging = false;
}
The secret sauce is the override of the isTouchInside function, which will return false even if the touch is inside, but was moved. This way, the button will also release its "zoomed" state as soon as you start scrolling.
It also adds a small tolerance factor, so if the touch moves just a little, it's still considered a "click". This factor is hardcoded at 25 in the example above.
My problems:
There is a scrollView with many buttons (items). Above it there are 2 function buttons (return, start).
When I scroll down item buttons overlie function buttons. When I swallow all touches above my scrollview I will lose my function buttons. So I have to find another solution.
When I start draging scroll view a item button is pressed. When I ended the button action will be execute. This is very annoying.
But there is the solution. I have created new CCControlButton. It checks whether was clicked outside scrollview or was dragged. The button is used for items buttons.
bool ControlButtonForScrolling::checkIfTouchIsInsideScrollView(CCTouch *pTouch)
{
CCPoint touchLocation = pTouch->getLocation(); // Get the touch position
touchLocation = _scrollView->getParent()->convertToNodeSpace(touchLocation);
CCRect bBox=_scrollView->boundingBox();
bool result = bBox.containsPoint(touchLocation);
return result;
}
bool ControlButtonForScrolling::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
bool isInside = this->checkIfTouchIsInsideScrollView(pTouch);
if (isInside) {
return CCControlButton::ccTouchBegan(pTouch, pEvent);
}
else
{
return false;
}
}
void ControlButtonForScrolling::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent)
{
CCControlButton::ccTouchMoved(pTouch, pEvent);
_scrollWasDragged = true; // information about dragging is stored to prevent sending action
}
void ControlButtonForScrolling::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
// this method is a copy of CCControlButton::ccTouchEnded except lines with _scrollWasDragged
m_eState = CCControlStateNormal;
m_isPushed = false;
setHighlighted(false);
if (!_scrollWasDragged)
{
if (isTouchInside(pTouch))
{
sendActionsForControlEvents(CCControlEventTouchUpInside);
}
else
{
sendActionsForControlEvents(CCControlEventTouchUpOutside);
}
}
_scrollWasDragged = false;
}