Source/Bit.m
author Jens Alfke <jens@mooseyard.com>
Wed Mar 12 15:51:32 2008 -0700 (2008-03-12)
changeset 6 af9b2b929b03
parent 0 e9f7ba4718e1
child 7 428a194e3e59
permissions -rw-r--r--
Fixed: An exception in the Go game if you mouse down on the board but then drag to the captured-pieces area and release the mouse.
jens@0
     1
/*  This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
jens@0
     2
    http://developer.apple.com/samplecode/GeekGameBoard/
jens@0
     3
    Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
jens@0
     4
jens@0
     5
    Redistribution and use in source and binary forms, with or without modification, are permitted
jens@0
     6
    provided that the following conditions are met:
jens@0
     7
jens@0
     8
    * Redistributions of source code must retain the above copyright notice, this list of conditions
jens@0
     9
      and the following disclaimer.
jens@0
    10
    * Redistributions in binary form must reproduce the above copyright notice, this list of
jens@0
    11
      conditions and the following disclaimer in the documentation and/or other materials provided
jens@0
    12
      with the distribution.
jens@0
    13
jens@0
    14
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
jens@0
    15
    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
jens@0
    16
    FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
jens@0
    17
    BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
jens@0
    18
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
jens@0
    19
    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
jens@0
    20
    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
jens@0
    21
    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
jens@0
    22
*/
jens@0
    23
#import "Bit.h"
jens@0
    24
#import "Game.h"
jens@0
    25
#import "QuartzUtils.h"
jens@0
    26
jens@0
    27
jens@0
    28
@implementation Bit
jens@0
    29
jens@0
    30
jens@0
    31
- (id) copyWithZone: (NSZone*)zone
jens@0
    32
{
jens@1
    33
    Bit *clone = [super copyWithZone: zone];
jens@1
    34
    clone->_owner = _owner;
jens@1
    35
    return clone;
jens@0
    36
}
jens@0
    37
jens@0
    38
@synthesize owner=_owner;
jens@0
    39
jens@0
    40
- (BOOL) isFriendly         {return _owner.friendly;}
jens@0
    41
- (BOOL) isUnfriendly       {return _owner.unfriendly;}
jens@0
    42
jens@0
    43
jens@0
    44
- (CGFloat) scale
jens@0
    45
{
jens@0
    46
    NSNumber *scale = [self valueForKeyPath: @"transform.scale"];
jens@0
    47
    return scale.floatValue;
jens@0
    48
}
jens@0
    49
jens@0
    50
- (void) setScale: (CGFloat)scale
jens@0
    51
{
jens@0
    52
    [self setValue: [NSNumber numberWithFloat: scale]
jens@0
    53
        forKeyPath: @"transform.scale"];
jens@0
    54
}
jens@0
    55
jens@0
    56
jens@0
    57
- (int) rotation
jens@0
    58
{
jens@0
    59
    NSNumber *rot = [self valueForKeyPath: @"transform.rotation"];
jens@0
    60
    return round( rot.doubleValue * 180.0 / M_PI );
jens@0
    61
}
jens@0
    62
jens@0
    63
- (void) setRotation: (int)rotation
jens@0
    64
{
jens@0
    65
    [self setValue: [NSNumber numberWithDouble: rotation*M_PI/180.0]
jens@0
    66
        forKeyPath: @"transform.rotation"];
jens@0
    67
}
jens@0
    68
jens@0
    69
jens@0
    70
- (BOOL) pickedUp
jens@0
    71
{
jens@0
    72
    return self.zPosition >= kPickedUpZ;
jens@0
    73
}
jens@0
    74
jens@0
    75
- (void) setPickedUp: (BOOL)up
jens@0
    76
{
jens@0
    77
    if( up != self.pickedUp ) {
jens@0
    78
        CGFloat shadow, offset, radius, opacity, z, scale;
jens@0
    79
        if( up ) {
jens@0
    80
            shadow = 0.8;
jens@0
    81
            offset = 2;
jens@0
    82
            radius = 8;
jens@0
    83
            opacity = 0.9;
jens@0
    84
            scale = 1.2;
jens@0
    85
            z = kPickedUpZ;
jens@0
    86
            _restingZ = self.zPosition;
jens@0
    87
        } else {
jens@0
    88
            shadow = offset = radius = 0.0;
jens@0
    89
            opacity = 1.0;
jens@0
    90
            scale = 1.0/1.2;
jens@0
    91
            z = _restingZ;
jens@0
    92
        }
jens@0
    93
        
jens@0
    94
        self.zPosition = z;
jens@1
    95
#if !TARGET_OS_ASPEN
jens@0
    96
        self.shadowOpacity = shadow;
jens@0
    97
        self.shadowOffset = CGSizeMake(offset,-offset);
jens@0
    98
        self.shadowRadius = radius;
jens@1
    99
#endif
jens@0
   100
        self.opacity = opacity;
jens@0
   101
        self.scale *= scale;
jens@0
   102
    }
jens@0
   103
}
jens@0
   104
jens@0
   105
jens@0
   106
- (BOOL)containsPoint:(CGPoint)p
jens@0
   107
{
jens@0
   108
    // Make picked-up pieces invisible to hit-testing.
jens@0
   109
    // Otherwise, while dragging a Bit, hit-testing the cursor position would always return
jens@0
   110
    // that Bit, since it's directly under the cursor...
jens@0
   111
    if( self.pickedUp )
jens@0
   112
        return NO;
jens@0
   113
    else
jens@0
   114
        return [super containsPoint: p];
jens@0
   115
}
jens@0
   116
jens@0
   117
jens@0
   118
-(id<BitHolder>) holder
jens@0
   119
{
jens@0
   120
    // Look for my nearest ancestor that's a BitHolder:
jens@0
   121
    for( CALayer *layer=self.superlayer; layer; layer=layer.superlayer ) {
jens@0
   122
        if( [layer conformsToProtocol: @protocol(BitHolder)] )
jens@0
   123
            return (id<BitHolder>)layer;
jens@0
   124
        else if( [layer isKindOfClass: [Bit class]] )
jens@0
   125
            return nil;
jens@0
   126
    }
jens@0
   127
    return nil;
jens@0
   128
}
jens@0
   129
jens@0
   130
jens@0
   131
- (void) destroy
jens@0
   132
{
jens@0
   133
    // "Pop" the Bit by expanding it 5x as it fades away:
jens@0
   134
    self.scale = 5;
jens@0
   135
    self.opacity = 0.0;
jens@0
   136
    // Removing the view from its superlayer right now would cancel the animations.
jens@0
   137
    // Instead, defer the removal until sometime shortly after the animations finish:
jens@0
   138
    [self performSelector: @selector(removeFromSuperlayer) withObject: nil afterDelay: 1.0];
jens@0
   139
}
jens@0
   140
jens@0
   141
jens@0
   142
@end