Greetings.
I try to make kid control application. The keyboard logger is a part of this application.
I use CGEventTapCreate to watch the keyboard. This works good, but sometimes I get duplicating key down events. They do not have [NSEvent isARepeat] set, just duplicates. For example I can type "qwerty" but application gets key down events for these characters: "qqwweerrttyy". Maybe somebody experienced smth like it? I get this problem on 10.5&10.6 (both are Intel).
I post here keyboard logger install & handler methods:
- (BOOL)installKeyboardLogger
{
CGEventMask keyboardMask = CGEventMaskBit(kCGEventKeyDown);
CGEventMask mouseMask = CGEventMaskBit(kCGEventMouseMoved) | CGEventMaskBit(kCGEventLeftMouseDown) |
CGEventMaskBit(kCGEventRightMouseDown);
CGEventMask mask = keyboardMask + mouseMask;// + mouseMask;//CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(kCGEventMouseMoved);
// Try to create keyboard-only hook. It will fail if Assistive Devices are not set.
mMachPortRef = CGEventTapCreate(
kCGAnnotatedSessionEventTap,
kCGTailAppendEventTap, // kCGHeadInsertEventTap
kCGEventTapOptionListenOnly,
keyboardMask,
(CGEventTapCallBack)eventTapFunction,
self );
if (!mMachPortRef)
[mLogFile logNeedAssistiveDevice: #"Can't install keyboard hook."];
else
CFRelease(mMachPortRef);
mMachPortRef = CGEventTapCreate(
kCGAnnotatedSessionEventTap,
kCGTailAppendEventTap, // kCGHeadInsertEventTap
kCGEventTapOptionListenOnly,
mask,
(CGEventTapCallBack)eventTapFunction,
self );
if (!mMachPortRef)
{
[mLogFile logNeedAssistiveDevice: #"Can't install keyboard&mouse hook."];
return NO;
}
mKeyboardEventSrc = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, mMachPortRef, 0);
if ( !mKeyboardEventSrc )
return NO;
CFRunLoopRef runLoop = CFRunLoopGetCurrent();
if ( !runLoop )
return NO;
CFRunLoopAddSource(runLoop, mKeyboardEventSrc, kCFRunLoopDefaultMode);
return YES;
}
CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon)
{
if (type != NX_KEYDOWN && type != NX_OMOUSEDOWN && type != NX_OMOUSEUP && type != NX_OMOUSEDRAGGED &&
type != NX_LMOUSEUP && type != NX_LMOUSEDOWN && type != NX_RMOUSEUP && type != NX_RMOUSEDOWN &&
type != NX_MOUSEMOVED && type != NX_LMOUSEDRAGGED && type != NX_RMOUSEDRAGGED)
return event;
NSEvent* sysEvent = [NSEvent eventWithCGEvent:event];
if (type == NX_KEYDOWN && [sysEvent type] == NSKeyDown)
{
if (![sysEvent isARepeat])
[(ControlPanelController*)refcon handleCapturedCharacters: [sysEvent characters]];
}
else
[(ControlPanelController*)refcon handleMouse];
return event;
}
Related
i am trying to implement a drag and drop behaviour for an object, i need to register when the touch is being pressed and after moving it a bit it should start dragging.
unfortunately i am using a custom framework that is implemented in C# and it's something like XNA.
How would you do it on XNA?
(it's for an android tablet) .
Obviously this example should be refactored to use input services and better handling for the touch up/down concepts, but the core of the answer remains the same:
// I don't remember the exact property names, but you probably understand what I mean
public override void Update(GameTime time)
{
var currentState = TouchPanel.GetState();
var gestures = currentState.TouchGestures;
var oldGests = this.oldState.TouchGestures;
if (oldGests.Count == 0 && gestures.Count == 1 && gestures[0].State == Pressed)
{
// Went from Released to Pressed
this.touchPressed = true;
}
else
{
// Not the frame it went to Pressed
this.touchPressed = false;
}
if (oldGests.Count == 1 && gestures.Count == 1 && oldGests[0].State == Pressed && gestures[0].State == Pressed)
{
// Touch is down, and has for more than 1 frame (aka. the user is dragging)
this.touchDown = true;
}
else
{
this.touchDown = false;
}
if (oldGests.Count == 1 && oldGests[0].State == Pressed && gestures.Count == 0)
{
// Went from Released to Pressed
this.touchReleased = true;
}
else
{
// Not the frame it went to Pressed
this.touchReleased = false;
}
this.oldState = currentState;
}
You might have to fiddle with the 'ifs' a bit, since I don't actually remember if Gestures goes down to 0 the first frame after you release your finger, or if it still shows 1 Gesture called 'Released'. Test it, and you shall have your answer!
Now you can use 'this.touchDown' elsewhere in your code to determine if your object should move or not.
I am trying to implement a removeLast function for a linked list in objective-c. My add function property works well because I can see the node I created, but when I try to remove a node it does not work. I have tried looking up general solutions for this, but have not come up with anything. Is there something special with objective-c that I should take a look at?
-(void) removeLast{
Node *newNode = [[Node alloc]init];
Node *tail = [[Node alloc]init];
if (self.head == NULL){
NSLog(#"No items to remove");
}
else{
newNode = self.head;
tail= self.head;
while (tail != NULL) {
tail = tail.next;
if (tail != NULL){
newNode = tail;
}
}
newNode.next = NULL;
}
}
I believe you've overcomplicated the algorithm. You don't need to keep a reference to the previous link if you always look one step ahead:
- (void) removeLast {
if (self.head == NULL) {
NSLog(#"Empty list");
} else if (self.head.next == NULL) {
self.head = NULL;
} else {
Node* current = self.head;
while (current.next.next != NULL)
current = current.next;
current.next = NULL;
}
}
This iterates through until it reaches the next-to-last node when current.next.next will be null. Then it makes that the last node.
I am getting a NPE (null-pointer exception) when placing any other item than the ones I have defined, or when drinking from a milk-bucket. I have tried adding isCanceled() == false to my EventHandler, but it breaks my RIGHT_CLICK_AIR action. Sorry, it sounds kind of complicated, any more info can be provided, thanks in advance!
#EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerInteract(PlayerInteractEvent event) {
Player p = event.getPlayer();
Location location = p.getLocation();
ItemStack item = event.getItem();
if(event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK && event.hasItem() != false || event.isCancelled() == true) {
I'd think it's because of this line:
ItemStack item = event.getItem();
When the player is not holding an item, it returns null. Try a null check to see if there is an item in their hand.
if (event.getItem() != null)){
//do stuff
}
else{
//don't do it
}
I'm trying to write a chess game and find that I cannot find solutions to find a stalemate situation. I'm trying to google, but can't find anything. Is there a well-known algorithm or something?
Your move generator will be one of two different designs;
either it checks for legality while generating the moves
or you generate all possible moves and remove those that are illegal afterwards.
The former is better as it doesn't need post-processing.
A stalemate condition is simply one where there are no legal moves and the moving-side's king is not in check. A checkmate condition is one where there are no legal moves but the moving-side's king is in check.
In other words if you've figured out how to detect check and checkmate, you've already got everything necessary to detect stalemate.
Here is an Open-source code with all the rules for the classic Chess game:
https://github.com/cjortegon/basic-chess
You can run the project right after cloning the project (Android, iOS, Desktop and Web), or you can use the main logic, which is here: https://github.com/cjortegon/basic-chess/tree/master/libgdx/core/src/com/mountainreacher/chess/model
I based my solution on a 3-moments algorithm, first moment is when the player selects a piece from the board, then when the destination of this piece has been chosen and finally when the piece reaches that position (considering that it is an animated game, if not, you can merge step 2 and 3).
The following code has been implemented in Java. From the properties of the model class:
boolean turn;
GenericPiece selected, conquest;
ClassicBoard board;
List<int[]> possibleMovements;
int checkType;
The first method will handle moments 1, 2 and the special 'conquest' moment (applied to pawn piece only):
public boolean onCellClick(int row, int column) {
if (row == -1 && conquest != null) {
checkType = 0;
conquest.changeFigure(column);
return true;
} else if (selected != null) {
if (possibleMovements != null) {
for (int[] move : possibleMovements) {
if (move[0] == row && move[1] == column) {
// Move the PieceActor to the desired position
if (selected.moveTo(row, column)) {
turn = !turn;
}
break;
}
}
}
selected = null;
possibleMovements = null;
return true;
} else {
selected = board.getSelected(turn ? Piece.WHITE_TEAM : Piece.BLACK_TEAM, row, column);
if (selected != null) {
possibleMovements = new ArrayList<>();
possibleMovements.addAll(((GenericPiece) selected).getMoves(board, false));
// Checking the movements
board.checkPossibleMovements(selected, possibleMovements);
if (possibleMovements.size() == 0) {
possibleMovements = null;
selected = null;
return false;
} else {
return true;
}
}
}
return false;
}
And the following method will handle the 3rd moment (when animation finishes):
public void movedPiece(Piece piece) {
Gdx.app.log(TAG, "movedPiece(" + piece.getType() + ")");
// Killing the enemy
Piece killed = board.getSelectedNotInTeam(piece.getTeam(),
piece.getRow(), piece.getColumn());
if (killed != null) {
killed.setAvailable(false);
}
// Checking hacks
GenericPiece[] threat = board.kingIsInDanger();
if (threat != null) {
checkType = board.hasAvailableMoves(threat[0].getTeam()) ? CHECK : CHECK_MATE;
} else {
checkType = NO_CHECK;
}
// Checking castling
if (piece.getFigure() == Piece.ROOK && ((GenericPiece) piece).getMovesCount() == 1) {
Piece king = board.getSelected(piece.getTeam(),
piece.getRow(), piece.getColumn() + 1);
if (king != null && king.getFigure() == Piece.KING && ((GenericPiece) king).getMovesCount() == 0) {
// Left Rook
if (board.getSelected(piece.getRow(), piece.getColumn() - 1) == null) {
king.moveTo(piece.getRow(), piece.getColumn() - 1);
}
} else {
king = board.getSelected(piece.getTeam(),
piece.getRow(), piece.getColumn() - 1);
if (king != null && king.getFigure() == Piece.KING && ((GenericPiece) king).getMovesCount() == 0) {
// Right Rook
if (board.getSelected(piece.getRow(), piece.getColumn() + 1) == null) {
king.moveTo(piece.getRow(), piece.getColumn() + 1);
}
}
}
}
// Conquest
else if (piece.getFigure() == Piece.PAWN && (piece.getRow() == 0 || piece.getRow() == board.getRows() - 1)) {
conquest = (GenericPiece) piece;
checkType = CONQUEST;
}
}
That code covers all the rules from the classic chess, including: regular piece movements, castling, check, check-mate and conquests of pawns.
I currently working on a Cocos2D Mac Game in Objective-C.
I've got the movement working but i have one more question ..
I use this code to move my player, it is a fly so it needs free movement in all directions.
Keyboard event:
- (void)ccKeyDown:(NSEvent*)keyDownEvent
{
// Get pressed key (code)
NSString * character = [keyDownEvent characters];
unichar keyCode = [character characterAtIndex: 0];
// Player movement
if (keyCode == 119) {
playerMoveUp = TRUE;
} else if (keyCode == 115) {
playerMoveDown = TRUE;
}
if (keyCode == 100) {
playerMoveLeft = TRUE;
} else if (keyCode == 97) {
playerMoveRight = TRUE;
}
}
- (void)ccKeyUp:(NSEvent*)keyUpEvent
{
// Get pressed key (code)
NSString * character = [keyUpEvent characters];
unichar keyCode = [character characterAtIndex: 0];
// Player movement
if (keyCode == 119) {
playerMoveUp = FALSE;
} else if (keyCode == 115) {
playerMoveDown = FALSE;
}
if (keyCode == 100) {
playerMoveLeft = FALSE;
} else if (keyCode == 97) {
playerMoveRight = FALSE;
}
}
Gametime loop:
-(void) tick: (ccTime) dt
{
// Get player current position
NSInteger playerPositionX = player.position.x;
NSInteger playerPositionY = player.position.y;
// Player movement
if (playerMoveUp == TRUE) {
player.position = ccp(playerPositionX, playerPositionY + 1);
}
if (playerMoveDown == TRUE) {
player.position = ccp(playerPositionX, playerPositionY - 1);
}
if (playerMoveLeft == TRUE) {
player.position = ccp(playerPositionX + 1, playerPositionY);
}
if (playerMoveRight == TRUE) {
player.position = ccp(playerPositionX - 1, playerPositionY);
}
}
My problem is when my player is moving left it's not possible to add the up key the same time, so the player will be moving left and up. What is the best way to achieve this?
There is a simple-simple trick: declare an array of bool like bool arrows[4], where each element is an arrow button state and true == pressed. Now you set an array element to true in keyDown event and to false in keyUp. The last thing you need - a timer to check this array and move objects.
Actually, the timer a better solution than regular event handling because you can control "keys processing speed".