Source/Bit.m
author snej@snej.local
Sun Jan 11 00:02:27 2009 -0800 (2009-01-11)
changeset 26 e7a464fb6d39
parent 16 28392c9a969f
permissions -rw-r--r--
Added ball graphics to Xcode project, which fixes the Go game. Fixed Tic-Tac-Toe. Fixed an exception in the demo app when changing games.
     1 /*  This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
     2     http://developer.apple.com/samplecode/GeekGameBoard/
     3     Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
     4 
     5     Redistribution and use in source and binary forms, with or without modification, are permitted
     6     provided that the following conditions are met:
     7 
     8     * Redistributions of source code must retain the above copyright notice, this list of conditions
     9       and the following disclaimer.
    10     * Redistributions in binary form must reproduce the above copyright notice, this list of
    11       conditions and the following disclaimer in the documentation and/or other materials provided
    12       with the distribution.
    13 
    14     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
    15     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
    16     FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
    17     BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    18     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
    19     PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
    20     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
    21     THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    22 */
    23 #import "Bit.h"
    24 #import "Game.h"
    25 #import "Player.h"
    26 #import "QuartzUtils.h"
    27 
    28 
    29 #ifdef TARGET_OS_IPHONE
    30 #define kPickedUpScale   2.0      // more magnification, so piece shows up underneath fingertip
    31 #define kPickedUpOpacity 0.6
    32 #else
    33 #define kPickedUpScale   1.2
    34 #define kPickedUpOpacity 0.9
    35 #endif
    36 
    37 
    38 @implementation Bit
    39 
    40 
    41 - (id) copyWithZone: (NSZone*)zone
    42 {
    43     Bit *clone = [super copyWithZone: zone];
    44     clone->_owner = _owner;
    45     clone->_tag   = _tag;
    46     return clone;
    47 }
    48 
    49 - (void) dealloc
    50 {
    51     [super dealloc];
    52 }
    53 
    54 
    55 @synthesize owner=_owner, tag=_tag;
    56 
    57 - (BOOL) isFriendly         {return _owner.friendly;}
    58 - (BOOL) isUnfriendly       {return _owner.unfriendly;}
    59 
    60 /*
    61 - (NSString*) identifier
    62 {
    63     if( _identifier )
    64         return _identifier;
    65     // Defaults to just identifying the owner:
    66     return [NSString stringWithFormat: @"p%i", _owner.index+1];
    67 }
    68 */
    69 
    70 - (CGFloat) scale
    71 {
    72     NSNumber *scale = [self valueForKeyPath: @"transform.scale"];
    73     return scale.floatValue;
    74 }
    75 
    76 - (void) setScale: (CGFloat)scale
    77 {
    78     [self setValue: [NSNumber numberWithFloat: scale]
    79         forKeyPath: @"transform.scale"];
    80 }
    81 
    82 - (void) scaleBy: (CGFloat)scale
    83 {
    84     self.transform = CATransform3DConcat(self.transform,
    85                                          CATransform3DMakeScale(scale, scale, scale));
    86 }
    87 
    88 
    89 - (int) rotation
    90 {
    91     NSNumber *rot = [self valueForKeyPath: @"transform.rotation"];
    92     return round( rot.doubleValue * 180.0 / M_PI );
    93 }
    94 
    95 - (void) setRotation: (int)rotation
    96 {
    97     [self setValue: [NSNumber numberWithDouble: rotation*M_PI/180.0]
    98         forKeyPath: @"transform.rotation"];
    99 }
   100 
   101 
   102 - (BOOL) pickedUp
   103 {
   104     return _pickedUp;
   105 }
   106 
   107 - (void) setPickedUp: (BOOL)up
   108 {
   109     if( up != _pickedUp ) {
   110         CGFloat shadow, radius, opacity, z;
   111         CGSize offset;
   112         CATransform3D transform;
   113         
   114         if( up ) {
   115             shadow = 0.8;
   116             offset = CGSizeMake(2,2);
   117             radius = 8;
   118             opacity = kPickedUpOpacity;
   119             z = kPickedUpZ;
   120             _restingZ = self.zPosition;
   121             _restingTransform = self.transform;
   122             transform = CATransform3DScale(_restingTransform, kPickedUpScale, kPickedUpScale, kPickedUpScale);
   123 #if !TARGET_OS_IPHONE
   124             _restingShadowOpacity = self.shadowOpacity;
   125             _restingShadowOffset  = self.shadowOffset;
   126             _restingShadowRadius  = self.shadowRadius;
   127 #endif
   128         } else {
   129 #if !TARGET_OS_IPHONE
   130             shadow = _restingShadowOpacity;
   131             offset = _restingShadowOffset;
   132             radius = _restingShadowRadius;
   133 #endif
   134             opacity = 1;
   135             transform = _restingTransform;
   136             z = _restingZ;
   137         }
   138 
   139 #if !TARGET_OS_IPHONE
   140         self.zPosition = z;
   141         self.shadowOpacity = shadow;
   142         self.shadowOffset = offset;
   143         self.shadowRadius = radius;
   144 #endif
   145         self.opacity = opacity;
   146         self.transform = transform;
   147         _pickedUp = up;
   148     }
   149 }
   150 
   151 
   152 - (BOOL)containsPoint:(CGPoint)p
   153 {
   154     // Make picked-up pieces invisible to hit-testing.
   155     // Otherwise, while dragging a Bit, hit-testing the cursor position would always return
   156     // that Bit, since it's directly under the cursor...
   157     if( self.pickedUp )
   158         return NO;
   159     else
   160         return [super containsPoint: p];
   161 }
   162 
   163 
   164 -(id<BitHolder>) holder
   165 {
   166     // Look for my nearest ancestor that's a BitHolder:
   167     for( CALayer *layer=self.superlayer; layer; layer=layer.superlayer ) {
   168         if( [layer conformsToProtocol: @protocol(BitHolder)] )
   169             return (id<BitHolder>)layer;
   170         else if( [layer isKindOfClass: [Bit class]] )
   171             return nil;
   172     }
   173     return nil;
   174 }
   175 
   176 
   177 - (void) destroy
   178 {
   179     // "Pop" the Bit by expanding it 5x as it fades away:
   180     self.scale = 5;
   181     self.opacity = 0.0;
   182     // Removing the view from its superlayer right now would cancel the animations.
   183     // Instead, defer the removal until sometime shortly after the animations finish:
   184     [self performSelector: @selector(removeFromSuperlayer) withObject: nil afterDelay: 1.0];
   185 }
   186 
   187 
   188 @end