How to prevent users touch continuously in Cocos2dx - cocos2d-x

I need some ideas for these questions in Cocos2dx
How to prevent users touch continuously. For example, I shoot bullet continuously, I want there is a delay about 1 second even I press touch continuously. I mean touch continuously not touch and hold.
How to detect if the hold touch event?

1: When your bullet fires you could set a boolean (e.g. bulletPassing) to notify you that touches should be ignored (you use it in your ccTouchBegan method). Then you create an action that will notify you when one second passes. Let's say your class is called MyLayer and you have a function bulletDelayPassed that will set you boolean:
bool ArmourTest::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){
if( !bulletPassing ){
this->runAction( CCSequence::create( CCDelayTime::create(1),
CCCallFunc::create(this, callfunc_selector(MyLayer::bulletDelayPassed)), NULL) );
bulletPassing = true;
shootBullet();
}
isTouching = true;
...
}
void MyLayer::bulletDelayPassed(){
bulletPassing = false;
}
2: Best way to do this is to create a boolean to tell you that a touch is active (e.g. isTouching), you set it to true in your ccTouchBegan method and to false in your ccTouchEnded. If you need to measure how long the touch is held, you should schedule an update and update some time variable that you set to 0 in ccTouchBegan and you update it only when your touching boolean is true:
void MyLayer::update( float dt ){
if( isTouching ) touchDuration += dt;
}

Related

Allow a button press by true or false variable AS3

I have been making an advent calendar in which when you press the button the door opens. I have created a variable to control which date you can open them on called 'AllowOpen' if it is the right date. I have also created a function to go to a frame when clicked.
var AllowOpen: Boolean = false;
if (Day == 1) {
AllowOpen = true;
} else {
AllowOpen = false;
}
button1.addEventListener(MouseEvent.MOUSE_DOWN, click);
function click(event:MouseEvent):void
{
gotoAndStop(2)
}
I can't work out how I would tell the the program to only open the door if allow open is true. I have tried the 'if' statement but it doesn't seem to work. Thanks
OK, you could put the 'if' loop inside the function as already suggested thusly:
function click(e:Event):void{
if (AllowOpen) {
gotoAndStop(2);
}
}
BUT, spidey senses tingling. I would opt for adding an ENTER_FRAME listener so that as the day changes you automatically change boolean values for each day/door to open:
var my_boolean_var_i:boolean = false;
addEventListener(Event.ENTER_FRAME, checkDay);
function checkDay(e:Event):void{
if(Day == day_i){
my_boolean_var_i = true;
}
}
"i" would be another variable that you would declare to store an integer from 1 to 28 depending on the date and then a set of variables 'day + i'. Then you can have a listener/function for each door named sequentially with i to keep everything organized:
door_i.addEventListener(Event.MOUSE_CLICK, click_i);
function click_i(e:Event):void{
if(my_boolean_var_i == true){
gotoAndStop(2);
}
}
This is the way I would go about settling the task. It's a lot of repetitive code so there is bound to be some more elegant way to do this from a more advanced user. Also, if you want to animate the door look up GreenSock TweenLite. VERY useful and friendly for graphics and whatnot.

Any ways to detect Cocos2d-x: CCScrollView is scrolling or not?

I'm seeking a way to get the scrolling state of CCScrollView.
It seems not to be a rare requirement, but do I need to implement it?
Thanks:)
Edit: Following is my two 'brute force' ways, but they seems work.
The goal is to get the scroll condition of a CCScrollView s from a cocos2d::Layer l.
Way #1
In each iteration of update() function of l, get the content offset of s by
ScrollView::getContentOffset()
if it stays the same, we can assume that the ScrollView is not scrolling.
Way #2
Create class S which inherits CCScrollView and CCScrollViewDelegate, then in the override of the delegate's function
void scrollViewDidScroll(ScrollView* view)
(which seems to be called every time the ScrollView scrolls.) use a variable to save current time
/*uint64_t*/ lastScrollTime = mach_absolute_time();
then in the update() function of l, assume the ScrollView is not scrolling by a time threshold
curTime = mach_absolute_time();
if (GlobalUtils::machTimeToSecs(curTime - lastScrollTime) > 0.1)
Hope that works :)
So, in your's initScroll() method you should set:
scrollView = ScrollView::create();
// initialisation scrollview
scrollView->addEventListener(CC_CALLBACK_2(YourScene::testScroll, this));
this->addChild(scrollView);
and make bool variable isScrolled. Then in method testScroll() you need to check listener's event type and depending from it set the variable isScrolled:
void YourScene::testScroll(Ref* sender, ui::ScrollView::EventType type)
{
if (type == ui::ScrollView::EventType::SCROLLING)
isScrolling = true;
else
isScrolling = false;
}
You can see other values EventType here
One way without modifying the source code of CCScrollView is to check the flag of ScrollView::isDragging() and whether one of the scrolling selectors of ScrollView is scheduled.
bool isDeaccelerateScrolling = scrollView->getScheduler()->isScheduled(CC_SCHEDULE_SELECTOR(ScrollView::deaccelerateScrolling));
bool isPerformedAnimatedScroll = scrollView->getScheduler()->isScheduled(CC_SCHEDULE_SELECTOR(ScrollView::performedAnimatedScroll));
bool isScrolling = scrollView->isDragging() || isDeaccelerateScrolling || isPerformedAnimatedScroll;

What can I do to stop a character's movement upon hitting an object?

I want my controlled character to completely stop moving when he hits a specific object (and not regain control until he answers the question correctly.) But I can't seem to figure out how to make him stop and remove control from the user, removing the key functions that allow character movement only works for the first instance of this and afterwards only stops the character if he falls onto the object rather than touch it (basically keeps moving the character if he touches the object horizontally in every instance afterwards). The current code for the hitTest is below if it helps.
addEventListener(Event.ENTER_FRAME, information);
function information(e:Event)
{
if (player.hitTestObject(folder))
{
removeChild(folder);
myInfo.alpha=100;
myInfo.gotoAndStop("folder1");
myInfo.x=player.x;
myInfo.y=player.y-50;
stage.addEventListener(KeyboardEvent.KEY_DOWN,kU);
//stops player movement
myInfo.myA.addEventListener(MouseEvent.CLICK, answerA);
function answerA(event:MouseEvent)
{
trace("answer A");
myInfo.alpha=0;
stage.removeEventListener(KeyboardEvent.KEY_DOWN, kU);
}
the "kU" function is the function that checks whether a key is not being pressed and doesn't seem to work when i switch it with the "key down function" I have. the code for movement is below.
function loop(e:Event)
{
if (kLeft)
{
speedX=-15;
}
if (kRight)
{
speedX=15;
}
else
{
speedX*=0.5;
}
You can use a boolean value and set it to true when the object hits the specific object you want , then if the boolean value is true you disable the movement code , but when it becomes say false you can activate it again ...
So basically the movement code depends on the boolean value ...
Regards
Nullifying the "kLeft" variable and the "kRight" variable effectively stops the character upon the hitTest. The reason nothing else would work is because the Movement is in a seperate function than the hitTest (so i guess it would constantly detect movement and count that instead). Anyways, the code i used was
kLeft = null;
kRight = null;

My WP8 game isn't receiving Drag gestures when using MonoGame

I've got a WP8 project that is using the MonoGame framework. I have some code that should recognize Horizontal and Vertical drag events and perform an action but I never seem to get these events. I do get a FreeDrag gesture but the Deltas are always NaN.
I initialize the TouchPanel.EnabledGestures in the Initialize method of the game as follows:
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
TouchPanel.EnabledGestures = GestureType.HorizontalDrag | GestureType.FreeDrag;
}
I have a method that checks the gesture type as follows:
private void CheckUserGesture()
{
while (TouchPanel.IsGestureAvailable)
{
var gesture = TouchPanel.ReadGesture();
switch(gesture.GestureType)
{
case GestureType.DragComplete:
System.Diagnostics.Debug.WriteLine("Drag Complete");
break;
case GestureType.FreeDrag:
System.Diagnostics.Debug.WriteLine("Drag Complete");
break;
case GestureType.HorizontalDrag:
if (gesture.Delta.X < 0)
gameVm.MoveLeft(Math.Abs((int)gesture.Delta.X));
if (gesture.Delta.X > 0)
gameVm.MoveRight((int)gesture.Delta.X);
break;
case GestureType.VerticalDrag:
if (gesture.Delta.Y > 0)
gameVm.MoveDown(Math.Abs((int)gesture.Delta.Y));
break;
case GestureType.Tap:
System.Diagnostics.Debug.WriteLine("Rotating Shape Due To Tap Command");
gameVm.RotateClockwise();
break;
}
}
}
And this is called in the Update method:
protected override void Update(GameTime gameTime)
{
base.Update(gameTime);
// TODO: Add your update logic here
//CheckTouchGesture();
CheckUserGesture();
gameVm.UpdateGame((int)gameTime.ElapsedGameTime.TotalMilliseconds);
}
I've also tried using TouchState:
private void CheckTouchGesture()
{
var touchCol = TouchPanel.GetState();
foreach (var touch in touchCol)
{
// You're looking for when they finish a drag, so only check
// released touches.
if (touch.State != TouchLocationState.Released)
continue;
TouchLocation prevLoc;
// Sometimes TryGetPreviousLocation can fail. Bail out early if this happened
// or if the last state didn't move
if (!touch.TryGetPreviousLocation(out prevLoc) || prevLoc.State != TouchLocationState.Moved)
continue;
// get your delta
var delta = touch.Position - prevLoc.Position;
// Usually you don't want to do something if the user drags 1 pixel.
if (delta.LengthSquared() < DragTolerence)
continue;
if (delta.X < 0)
gameVm.MoveLeft(Math.Abs((int)delta.X));
else if (delta.X > 0)
gameVm.MoveRight((int)delta.X);
else if (delta.Y > 0)
gameVm.MoveDown((int)delta.Y);
}
}
But again the deltas are always NaN.
Is there something I'm missing that I might need to initialize?
I've tried various combinations of the EnabledGestures types but still can't get the dragging events to work. Flick doesn't work either.
Things like Tap are fine though.
Thanks
I think this is broken on the current release of MonoGame ( Version 3.0.1, Release date: Mar 3 2013 ).
Building the latest from the GitHub developer branch:
https://github.com/mono/MonoGame.git
(NOTE: I also built SharpDX too from here: https://github.com/sharpdx/SharpDX)
Seems to fix a lot of my problems
I'm not 100% convinced it is fully working though.
Using the touch.TryGetPreviousLocation() as shown in the code above always returns the same position as the current position so doing var delta = loc.Position - preLoc.Postion always results in 0.
At least I'm receiving the drag gestures now.

Emulating Mouse Event AS3

I have a project that involves polling a hardware switch each update and converting its states to a custom events:
ToggleSwitchEvent.BackWardButtonDown
ToggleSwitchEvent.BackWardButtonUp
ToggleSwitchEvent.Click
etc ....
The hardware switch acts similar to a two button mouse. So I would like to be able to "inject" the custom ToggleSwitchEvent events into the Display List and have it act just as a MouseEvent does, bubbling up from the InteractionObject that the click intersects with. This would allow me to addEventListener to the display list just as I do with MouseEvents.
The trouble, as far as I understand it, is that I would need a reference to the leaf nodes of the DisplayList to insert my ToggleSwitchEvent manually. I would like to say that the switch was clicked at a certain position on screen, and have the DisplayList figure out what InteractionObject the click intersects and dispatch my ToggleSwitchEvent instead of a MouseEvent.
Is there a method to emulate the MouseEvent in AS3 but using a custom event?
i do not quite understand ... do you want a custom event to bubble, or to fire MouseEvents on your own?
any event will bubble as expected, if its bubbles property is set to true ...
if you dispatch mouse events manually, they will also bubble, and even their stageX and stageY is calculated appropriately ...
so good luck then ... ;)
edit:
ok, well the display list will not really take care of this for you ... actually, you have two options ... start at the stage, and make your way through it, always keeping under the mouse ... or, start at the object under the mouse, get its path in the tree, and find the right InteractiveObject in its parent chain ... the latter can be done using DisplayObjectContainer::getObjectsUnderPoint ... here's the code ...
public static function dispatchEventUnderMouse(event:Event, stage:Stage, point:Point):Boolean {
//return if stage is disabled
if (!stage.mouseEnabled) return false;
//find the topmost object
var cur:DisplayObject = stage.getObjectsUnderPoint(point).pop();
if (cur == null) cur = stage;
//build the path
var path:Array = [];
while (cur != null) {
path.push(cur);
cur = cur.parent;
}
//traverse the path from the root to find the right InteractiveObject
while (path.length > 0) {
cur = path.pop();
if (cur is InteractiveObject) {
if (!(cur as InteractiveObject).mouseEnabled) {
cur = cur.parent;
break;
}
if (cur is DisplayObjectContainer) {
if (!(cur as DisplayObjectContainer).mouseChildren) break;
}
}
else {
cur = cur.parent;
break;
}
}
return cur.dispatchEvent(event);
}
you might actually want to inject the right coordinates into the event, but i guess you'll figure that out ... ;)

Categories