Source/Bit.m
author Jens Alfke <jens@mooseyard.com>
Fri Jul 18 13:26:59 2008 -0700 (2008-07-18)
changeset 20 7c9ecb09a612
parent 13 db7bb080c3d5
child 22 4cb50131788f
permissions -rw-r--r--
Checkers and Hexchequer now detect victory when the other player can't move.
     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 
    83 - (int) rotation
    84 {
    85     NSNumber *rot = [self valueForKeyPath: @"transform.rotation"];
    86     return round( rot.doubleValue * 180.0 / M_PI );
    87 }
    88 
    89 - (void) setRotation: (int)rotation
    90 {
    91     [self setValue: [NSNumber numberWithDouble: rotation*M_PI/180.0]
    92         forKeyPath: @"transform.rotation"];
    93 }
    94 
    95 
    96 - (BOOL) pickedUp
    97 {
    98     return _pickedUp;
    99 }
   100 
   101 - (void) setPickedUp: (BOOL)up
   102 {
   103     if( up != _pickedUp ) {
   104         CGFloat shadow, radius, opacity, z, scale;
   105         CGSize offset;
   106         if( up ) {
   107             shadow = 0.8;
   108             offset = CGSizeMake(2,2);
   109             radius = 8;
   110             opacity = kPickedUpOpacity;
   111             scale = kPickedUpScale;
   112             z = kPickedUpZ;
   113             _restingZ = self.zPosition;
   114 #if !TARGET_OS_IPHONE
   115             _restingShadowOpacity = self.shadowOpacity;
   116             _restingShadowOffset  = self.shadowOffset;
   117             _restingShadowRadius  = self.shadowRadius;
   118 #endif
   119         } else {
   120 #if !TARGET_OS_IPHONE
   121             shadow = _restingShadowOpacity;
   122             offset = _restingShadowOffset;
   123             radius = _restingShadowRadius;
   124 #endif
   125             opacity = 1;
   126             scale = 1.0/kPickedUpScale;
   127             z = _restingZ;
   128         }
   129 
   130 #if !TARGET_OS_IPHONE
   131         self.zPosition = z;
   132         self.shadowOpacity = shadow;
   133         self.shadowOffset = offset;
   134         self.shadowRadius = radius;
   135 #endif
   136         self.opacity = opacity;
   137         self.scale *= scale;
   138         _pickedUp = up;
   139     }
   140 }
   141 
   142 
   143 - (BOOL)containsPoint:(CGPoint)p
   144 {
   145     // Make picked-up pieces invisible to hit-testing.
   146     // Otherwise, while dragging a Bit, hit-testing the cursor position would always return
   147     // that Bit, since it's directly under the cursor...
   148     if( self.pickedUp )
   149         return NO;
   150     else
   151         return [super containsPoint: p];
   152 }
   153 
   154 
   155 -(id<BitHolder>) holder
   156 {
   157     // Look for my nearest ancestor that's a BitHolder:
   158     for( CALayer *layer=self.superlayer; layer; layer=layer.superlayer ) {
   159         if( [layer conformsToProtocol: @protocol(BitHolder)] )
   160             return (id<BitHolder>)layer;
   161         else if( [layer isKindOfClass: [Bit class]] )
   162             return nil;
   163     }
   164     return nil;
   165 }
   166 
   167 
   168 - (void) destroy
   169 {
   170     // "Pop" the Bit by expanding it 5x as it fades away:
   171     self.scale = 5;
   172     self.opacity = 0.0;
   173     // Removing the view from its superlayer right now would cancel the animations.
   174     // Instead, defer the removal until sometime shortly after the animations finish:
   175     [self performSelector: @selector(removeFromSuperlayer) withObject: nil afterDelay: 1.0];
   176 }
   177 
   178 
   179 @end