SpriteKit - Touch Handling

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • SpriteKit - Touch Handling

    Hallo zusammen,

    Ich probiere gerade bisschen mit Sprite kit rum.

    Und nun bin ich auf ein Problem gestoßen. Ich habe eine selbsterstellte Klasse für Thumbsticks.

    Hat auch alles gut geklappt bis ich 2 Sticks in meinem Spiel verwendete. Wenn ich beim zweiten "reintouche" bewegt sich auch der andere stick bzw. der spieler.
    Das selbe problem hatte ich bei Buttons auch, das habe ich dann natürlich so gelöst, dass ich in der touchbegan: methode abgefragt habe ob der Touch innerhalb des Buttons ist.

    Beim Thumbstick habe ich habe das Problem, dass es ja normal ist, das man beim Bewegen ausserhalb des sticks kommt. Und wenn ich nun in touchMoved: abfrage ob der Touch innerhalb ist, trifft das ja nicht mehr zu..


    Hier die touch methoden des Thumbsticks:

    Quellcode

    1. - (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    2. {
    3. isUsing = YES;
    4. }
    5. - (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
    6. {
    7. UITouch *touch = [touches anyObject];
    8. CGPoint touchPoint = [touch locationInNode:self];
    9. isUsing = YES;
    10. CGFloat distance = DistanceBetweenTwoPoints(CGPointZero, touchPoint);
    11. if((distance < self.size.height / 2 || isUsing))
    12. {
    13. movingPad.position = CGPointMake(Normalize(touchPoint).x * 30, Normalize(touchPoint).y * 30);
    14. self.direction = Normalize(touchPoint);
    15. }
    16. }
    17. - (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
    18. {
    19. isUsing = NO;
    20. movingPad.position = CGPointZero;
    21. self.direction = CGPointZero;
    22. }
    Alles anzeigen


    Und so rufe ich sie in der Scene auf:

    Quellcode

    1. [moveTHStick touchesMoved:touches withEvent:event];
    2. [shootTHStick touchesMoved:touches withEvent:event];


    Auf Stackoverflow wurde mir geraten(für die Butttons) den Nodes namen zu geben. Aber das klappt ja dann bei den Sticks auch nicht, da sie ja auch ausserhalb sein können.


    Wie es scheint habe ich das auch noch nicht ganz verstanden wie das mit den Touches funktioniert. Ich dachte eigentlich, dass die Scene eben diese touchevents auslöst, wenn irgendwo gedrückt wurde.
    Nun kann ich dass in jede Klasse übergeben und schauen ob der Touch innerhalb ist.
    Ich habe "früher" mit C# und XNA Spiele programmiert und dachte es ähnelt sich in der Hinsicht...

    Kann mir jemand helfen bzw. ein guten Link zukommen lassen?

    Danke!
    Every language has an optimization operator. In ObjC that operator is ‘//’.

    golbros.de
  • Wenn ich es richtig verstehe ist dein Hauptproblem die fehlende Abgrenzung der beiden Thumbsticks. Hierfür gibt es denke ich mehrere Wege das zu lösen.

    1. Du könntest feste Bereiche definieren und den Thumbsticks zuordnen. Sowas wie

    Quellcode

    1. if(touch.x < self.size.width/2){
    2. // linker stick gemeint
    3. }else{
    4. // rechter stick
    5. }


    2. Du könntest aber auch die Abstände der touches zu den sticks ermitteln. der stick mit dem geringeren Abstand ist dann wohl der anvisierte.
  • ioscampus schrieb:

    Wenn ich es richtig verstehe ist dein Hauptproblem die fehlende Abgrenzung der beiden Thumbsticks. Hierfür gibt es denke ich mehrere Wege das zu lösen.

    1. Du könntest feste Bereiche definieren und den Thumbsticks zuordnen. Sowas wie

    Quellcode

    1. if(touch.x < self.size.width/2){
    2. // linker stick gemeint
    3. }else{
    4. // rechter stick
    5. }


    2. Du könntest aber auch die Abstände der touches zu den sticks ermitteln. der stick mit dem geringeren Abstand ist dann wohl der anvisierte.


    Sowas in die Richtung denke ich auch. Aber was ich immernoch nicht verstehe:
    Der Rechte Stick ist für die Bewegung des Spielers. der Linke für das Schießen.
    Das bewegen mache ich in etwas so(Pseudocode):

    Quellcode

    1. player.position += moveStick.direction * 3.5;


    Bewege ich nun aber den linken Stick bewegst sich der rechte Stick und der Spieler bewegt sich auch. Dabei hat doch der Linke stick gar nichts mit dem rechten zu tun?
    Sind ja 2 verschiedene Objekte..
    Every language has an optimization operator. In ObjC that operator is ‘//’.

    golbros.de
  • Um das zu beurteilen sehe ich zu wenig Code.

    Vermutung:
    Du hast geschrieben, dass du beiden Sticks die Touches übergibst. Dann werden auch beide die Touches abarbeiten, was zu dem von dir beobachteten Verhalten führen könnte.

    Wo (in welcher Methode) findet denn "player.position += moveStick.direction * 3.5;" statt?
  • Hier der Ganze Code des Thumbsticks

    Quellcode

    1. @implementation ThumbStick
    2. {
    3. SKSpriteNode *movingPad;
    4. BOOL isUsing;
    5. }
    6. - (id) initWithTexture:(SKTexture *)texture color:(UIColor *)color size:(CGSize)size
    7. {
    8. self = [super initWithTexture:texture color:color size:size];
    9. if(self)
    10. {
    11. isUsing = NO;
    12. self.direction = CGPointZero;
    13. self.colorBlendFactor = 0.4;
    14. movingPad = [[SKSpriteNode alloc] initWithTexture:texture color:color size:CGSizeMake(size.width/3, size.height/3)];
    15. [self addChild:movingPad];
    16. return self;
    17. }
    18. return nil;
    19. }
    20. - (void) setPosition:(CGPoint)position
    21. {
    22. [super setPosition:position];
    23. movingPad.position = CGPointZero;
    24. NSLog(@"x: %f y: %f", self.position.x, self.position.y);
    25. NSLog(@"x: %f y: %f", movingPad.position.x, movingPad.position.y);
    26. }
    27. - (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    28. {
    29. isUsing = YES;
    30. }
    31. - (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
    32. {
    33. UITouch *touch = [touches anyObject];
    34. CGPoint touchPoint = [touch locationInNode:self];
    35. CGFloat distance = DistanceBetweenTwoPoints(CGPointZero, touchPoint);
    36. if((distance < self.size.height / 2 || isUsing))
    37. {
    38. isUsing = YES;
    39. movingPad.position = CGPointMake(Normalize(touchPoint).x * 30, Normalize(touchPoint).y * 30);
    40. self.direction = Normalize(touchPoint);
    41. }
    42. }
    43. - (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
    44. {
    45. if(isUsing)
    46. {
    47. isUsing = NO;
    48. movingPad.position = CGPointZero;
    49. self.direction = CGPointZero;
    50. }
    51. }
    52. CGFloat DistanceBetweenTwoPoints(CGPoint point1,CGPoint point2)
    53. {
    54. CGFloat dx = point2.x - point1.x;
    55. CGFloat dy = point2.y - point1.y;
    56. return sqrt(dx*dx + dy*dy );
    57. }
    58. CGPoint Normalize(CGPoint a) {
    59. float length = Length(a);
    60. return CGPointMake(a.x / length, a.y / length);
    61. }
    62. float Length(CGPoint a) {
    63. return sqrtf(a.x * a.x + a.y * a.y);
    64. }
    Alles anzeigen


    Ich habe eine Klasse Player, die eben nur das Schiff darstellt mit Lifepoints etc.
    Und dann eben eine PlayerManager Klasse die das Schiff und die Sticks etc. behinhalten.

    Die PlayerManager Klasse instanziiere ich in der Scene und bei den touchEvents rufe ich Sie ganz normal auf

    Quellcode

    1. [playerManager touchMoved:touches event:event]


    In der PlayerManager Klasse dann so:

    Quellcode

    1. - (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    2. {
    3. UITouch *touch = [touches anyObject];
    4. CGPoint touchLocation = [touch locationInNode:self];
    5. SKNode *node = [self nodeAtPoint:touchLocation];
    6. if([node.name isEqualToString:@"moveStick"])
    7. [moveTHStick touchesBegan:touches withEvent:event];
    8. if([node.name isEqualToString:@"shootStick"])
    9. [shootTHStick touchesBegan:touches withEvent:event];
    10. }
    11. - (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
    12. {
    13. //UITouch *touch = [touches anyObject];
    14. //CGPoint touchLocation = [touch locationInNode:self];
    15. //SKNode *node = [self nodeAtPoint:touchLocation];
    16. [moveTHStick touchesMoved:touches withEvent:event];
    17. [shootTHStick touchesMoved:touches withEvent:event];
    18. }
    19. - (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
    20. {
    21. UITouch *touch = [touches anyObject];
    22. CGPoint touchLocation = [touch locationInNode:self];
    23. SKNode *node = [self nodeAtPoint:touchLocation];
    24. [moveTHStick touchesEnded:touches withEvent:event];
    25. [shootTHStick touchesEnded:touches withEvent:event];
    26. }
    Alles anzeigen


    Ist bisschen unstrukturiert, da ich noch am Probieren bin..
    Every language has an optimization operator. In ObjC that operator is ‘//’.

    golbros.de
  • ioscampus schrieb:

    Warum benutzt du "if([node.name isEqualToString:@"moveStick"])" nur in touchesBegan und nicht in touchesMoved?


    Da ich dann das Problem hatte, das der Stick sich nur bewegt wenn der Touch auch drauf ist. Ich möchte aber das man das Schiff auch steuern kann, falls man ausserhalb des Sticks kommt..
    Every language has an optimization operator. In ObjC that operator is ‘//’.

    golbros.de