Processing Continuous Callbacks on key holding - callback

I want to implement the navigational system in my Processing project. If user (that navigates the object) wants to turn left, he hits the 'a' button. Here is my callback function on keyPressed:
void keyPressed() {
...
if(key == 'a') { ship.plainAngle -= 0.1; }
else if(key == 'd') { ship.plainAngle += 0.1; }
}
What I want to avoid is spamming the 'a' key in order to make 90 degrees turn left. I tried increasing the value that affects it directly (0.1) but it made it look laggy. I heard that there is a possibility in processing to make continuous callbacks while user keeps holding the key. As I found out using callback function keyPressed should work out but it doesn't work for me. The code in callback function executes only once. I don't know how to solve that problem.

Use a boolean variable to keep track of whether the a key (or any other key you care about) is currently held down. Set it to true in the mousePressed() function, and set it to false in the mouseReleased() function. Then in the draw() function, you can check that variable and do something if the key is currently being pressed.
Shameless self-promotion: I wrote a tutorial on keyboard input in Processing available here. Check out the section on handling multiple key presses for the approach I just outlined.

Related

Keyboard as game controller, handling multiple keys in Swift

I'm trying to make a spaceship move on the screen with the keyboard. I manage to deal with key events, but I noticed that when multiple keys are kept down at the same time, it won't behave correctly and only one will have priority. I'm using a switch statement because I thought the keyDown function was called once for every key, but even when I explicitly add a fallthrough in the cases, it's not better. Has anyone ever experienced anything like that and is there any better way to use the keyboard as a controller?
override func keyDown(with event: NSEvent) {
switch event.keyCode {
case 0x31:
if let playerShip = self.playerShip {
playerShip.run(SKAction.init(named: "Pulse")!, withKey: "fadeInOut")
}
case 123:
if let playerShip = self.playerShip {
playerShip.run(SKAction.applyAngularImpulse(0.001, duration: 0.1))
}
case 124:
if let playerShip = self.playerShip {
playerShip.run(SKAction.applyAngularImpulse(-0.001, duration: 0.1))
}
case 125:
if let playerShip = self.playerShip {
playerShip.run(SKAction.applyImpulse(CGVector.init(angle: playerShip.zRotation).opposite(), duration: 0.1))
}
case 126:
if let playerShip = self.playerShip {
playerShip.run(SKAction.applyImpulse(CGVector.init(angle: playerShip.zRotation), duration: 0.1))
}
default:
print("keyDown: \(event.characters!) keyCode: \(event.keyCode)")
}
}
My guess is that even if you get the code working exactly the way you describe it will be extremely difficult in practice for anyone playing your game to hit two keys at the exact same time. One key will almost always be hit slightly before the other. So, maybe you could implement it so that you capture one key event, and then look for a second one happening within a short time window after the first one (before the first one is released).
The keyDown method should be called by the OS X every time a key is pressed. If two keys are pressed, it's called twice, etc. Perhaps you're seeing this behavior because only the last key's action overrides the first key's action?
After testing a few things to make sure that my SKActions were not the cause of the problem, I remembered a few things from the days I was coding in Delphi with DelphiX and GLScene. I know it's PC, but it's related.
The thing is that the keyboard event cue will retrigger only the las key that was pressed. So applying force with the up arrow and keeping it pressed to accelerate will work until I press, for example, the left arrow to apply some torque. Then the left arrow key will get retriggered, but the next event to come from the up arrow, even if it's still pressed by now, will be when you actually release it. Therefore, the ship will start rotating but will stop accelerating because the keyDown event won't get retriggered for the up arrow.
This is why you need a way to keep track of key states, so you can check if multiple keys are pressed together at any given moment.
This is also why I'm gonna build my keyboard manager class.

QApplication::processEvents never returns

In my application I need to wait until external program (using QProcess) is finished. I want to keep the application responsible so blocking methods are unacceptable.
Also I need to disallow user input. I've tried to make QEventLoop and exec it with QEventLoop::ExcludeUserInputEvents flag, but as documentation says it only delays an event handling:
the events are not discarded; they will be delivered the next time processEvents() is called without the ExcludeUserInputEvents flag.
So I implemented simple event filter and install it on qApp (the idea is took from Qt Application: Simulating modal behaviour (enable/disable user input)). It works well, but sometimes QApplication::processEvents function never returns even if I specify the maximum timeout. Could anyone help me to understand for what reasons it periodically happens?
class UserInputEater : public QObject
{
public:
bool eventFilter(QObject *object, QEvent *event)
{
switch(event->type())
{
case QEvent::UpdateRequest:
case QEvent::UpdateLater:
case QEvent::Paint:
return QObject::eventFilter(object, event);
default:
return true;
}
}
};
-
UserInputEater eventEater;
qApp->installEventFilter(&eventEater);
QProcess prc;
prc.start("...");
while(!prc.waitForFinished(10))
{
if(qApp->hasPendingEvents())
{
// Sometimes it never returns from processEvents
qApp->processEvents(QEventLoop::AllEvents, 100);
}
}
qApp->removeEventFilter(&eventEater);
UPD: Seems like it depends of the timeout value for QProcess::waitForFinished.
I guess you are filtering some useful events (for example, QEvent::SockAct could be involved). Try to add some debug output and find out which event types you're actually filtering. Or it might be better to specify the black list of events you want to block instead of white list of events you want to allow. See this answer.
Also you shouldn't use return QObject::eventFilter(object, event);. You should use return false. All other event filters will be called automatically.
This solution however seems weird and unreasonable to me because you can just call setEnabled(false) for your top level widget to block user input, and then you can use QApplication::processEvents without any flags.

How can I pause execution within a method until the user sends a "Did End on Exit" (presses the "Next" button on the keyboard?

This is what I have:
while(wordList){ //wordlist is instance of NSArray containing NSStrings
word.text = [wordList objectAtIndex:x]; //word is instance of UILabel
//LOOKING TO PLACE WAIT CODE HERE TO WAIT FOR "DID END ON EXIT"
input = inputBox.text; //input is instance of UITextField
[self compare:input andb:word.text]; //compare is an instance method to compare the two strings
x++;
}
I'm a beginner, if any of you could help me, that would be fantastic.
Best...
SL
Is this what you are looking for?:
[yourTextField addTarget:self
action:#selector(yourMethod:)
forControlEvents:UIControlEventEditingDidEndOnExit];
Edit:
Why don't you just break the while loop and call a separate method when the user hits next? No need to pause and trigger some other method.
The approach you're asking about won't work. If your app were to pause execution in the middle of a method, what would cause it to unpause?
The user is not going to be entering text in the middle of your loop -- that would have to have already done that before the loop starts to execute. Trigger the method that contains the loop as #Imirak suggested, or from some other user interaction, for example a button press. That way you'll know that the user has already entered the text, and the code you've written should work as expected.
One note though: the code you've shown doesn't check the return value from your compare:andb: method. You haven't really provided enough information about what you expect the method to do to do to be sure whether that makes sense or not.
Also, your loop control logic is incorrect -- as written it's either going to be an infinite loop or it will never be entered, depending on whether wordList is nil. Consider using fast enumeration syntax instead of writing a while loop, for example:
for (UILabel *currLabel in wordList)
{
// It appears as though this may be the comparison you want to do
// but there's not enough context in your question to be sure.
//
if ([inputBox.text isEqualToString:currLabel.text])
{
// Do something here. Again, it's not clear what you're trying to do.
}
}

How to use the new BufferWithTimeOrCount in Rx that returns IObservable<IObservable<T>> instead of IObservable<IList<T>>

On Windows Phone 7 there is a new version of the BufferWithTimeOrCount extension method for IObservable that returns a "stream of streams" instead of the previous "stream of lists". I'm having difficulty trying to use either the new or old methods, so maybe I just don't understand how it works, but my goal is to create a stream that only fires when an existing stream matches a specified time based pattern during the previous 2 touch events. So far I have created streams for TouchUp and TouchDown (see related question) and In pseudo code I want something like:
//BufferLast2 should contain the last 1 or 2 touch events that occurred in the last 500ms. If no touches occurred this should return an empty set
var BufferLast2 = TouchDown.Merge(TouchUp).BufferWithTimeOrCount(TimeSpan.FromSeconds(0.5), 2);
//Use BufferLast2 to detect tap (TouchDown then TouchUp occuring in less than 0.5s)
var TouchTap = from touch2 in BufferLast2
where touch2.Count == 2 && touch2.First().Action == TouchAction.Down && touch2.Last().Action == TouchAction.Up
select touch2.First(); //returns initial TouchDown event
//Use BufferLast2 to detect Hold (TouchDown with no TouchUp occuring in 0.5s)
var TouchHold = from touch2 in BufferLast2
where touch2.Count == 1 && touch2.First().Action == TouchAction.Down
select touch2.First(); //returns initial TouchDown event
When using the "Stable" Microsoft.Phone.Reactive version of Rx that is built into the ROM calling IObservable<Class>.BufferWithTimeOrCount(...) returns a IObservable<IList<Class>>, which is pretty easy to work with using the standard list operators (as outlined above), but for some reason BufferLast2 was always returning two down events instead of the Down->Up sequence that I expected.
I figured it might be a bug in the code, so I tried adding a reference to the latest version of Rx and used the Observable Extensions from C:\Program Files (x86)\Microsoft Cloud Programmability\Reactive Extensions\v1.0.2838.0\WP7\System.Reactive.dll in which BufferWithTimeOrCount(...) returns a IObservable<IObservable<Class>>. This makes simple filters like Where x.Count == 2 or Where x.First().P == ... much harder to write. I haven't actually figured out how to do a simple filter like x.Count() == 2 on this return value without creating a completely separate subscription or Subject object, which seams way too complex. It's probably a simple error like my last question (all I needed was a Where clause :-P) but it is really driving me bonkers. Any help?
Changing the api makes the buffering look more Rx-y and fits with their Window operator implementation (wouldn't be surprised if using reflector you'd be able to see the Buffer operators using Window). I would think there's probably a variety of reasons that they've changed it. I'm not going to second guess them as they're a lot smarter than me!
So here's my stab at a solution. There may be a cleaner way to get what you're after but i'd probably implement my own extention method to buffer into a list. Maybe something like:
public static class BufferToList
{
public static IObservable<IEnumerable<TSource>> BufferToList<TSource>(this IObservable<TSource> source)
{
return Observable.CreateWithDisposable<IEnumerable<TSource>>(observer =>
{
var list = new List<TSource>();
return source.Subscribe(list.Add,
observer.OnError,
() =>
{
observer.OnNext(list);
observer.OnCompleted();
});
});
}
}
Then something like:
TouchDown.Merge(TouchUp)
.BufferWithTimeOrCount(TimeSpan.FromSeconds(0.5), 2)
.Select(bufferedValues => bufferedValues.BufferToList())
.Subscribe(OnBufferOpen)
private void OnBufferOpen(IObservable<IEnumerable<IEvent<IEventArgs>>> bufferedListAsync)
{
bufferedListAsync.Where(list => list.Count() == 2);
}
I suggest if you want a full explanation of why they've changed the api, go and ask the question over on the rx forums on msdn
The latest release of Rx, v1.0.2856.0, provides both buffers and windows. For the buffers, we restored the original signatures, based on IList. The corresponding window operators will return nested observable sequences.
The way the Buffer* operators are implemented is by composing the corresponding Window* operator with the new ToList extension method that takes an IObservable into an IObservable>. All the Buffer* operator does is invoke this new ToList operator in a SelectMany selector.

Signal fires twice from gtkmm popup list

It's been a while since I used GTK+, and the last time I did was in C, not using gtkmm and C++ as I am now. Anyway, I have what I think should be an easy problem to solve:
I have a pop-up menu consisting of a list of radio buttons, and when I click one of them I want some action to occur. The code goes like this:
Gtk::RadioMenuItem::Group group;
for ( size_t i = 1; i < LH_MAX; ++i )
{
Gtk::RadioMenuItem* pItem = new Gtk::RadioMenuItem( group, names[i], names[i] );
pItem->set_name( names[i] );
pItem->signal_activate().connect( sigc::mem_fun(*this, &MyClass::on_item_activated) );
pItem->show();
m_Menu.append( *Gtk::manage(pItem) );
}
The only problem I see is that MyClass::on_item_activated gets called twice when a previously-unselected radio button is chosen from the menu. It's called only once when the already-selected radio button is clicked.
I'm guessing that the first firing is to say "something is no longer activate," and the second is for the new radio button activation. Whether I'm right or wrong, the question is the same: how best can I have my handler only take action once per click? Either I need the handler to get called only once, or I need something to check from inside it to know if the callback is a "duplicate" or not.
You could use sigc::bind to supply the item as a argument to the callback function.
pItem->signal_activate().sigc::bind(sigc::mem_fun(*this,&MyClass::on_item_activated),pItem));
Then you can use item->get_active() in the callback to respond to activations only.
void MyClass::on_item_activated(Gtk::RadioMenuItem* item) {
if (item->get_active()) {
// Do some stuff
}
}
That's what I do too, connect to signal_toggled() and check if get_active() is true.
I don't know exactly what you're trying to accomplish (or what MyClass is and what base classes it inherits from), but connecting to signal_toggled() might be more useful than signal_activate()
/Agree with Johannes. Check if the item is activated when receiving the signal.