Source/Bit.m
author Jens Alfke <jens@mooseyard.com>
Wed Jul 09 17:07:45 2008 -0700 (2008-07-09)
changeset 15 73f8c889f053
parent 12 4e567e11f45f
child 16 28392c9a969f
permissions -rw-r--r--
More tweaks, including a "reversed" property for Grids to show the second player's perspective without turning the pieces upside-down.
     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             _restingShadowOpacity = self.shadowOpacity;
   115             _restingShadowOffset  = self.shadowOffset;
   116             _restingShadowRadius  = self.shadowRadius;
   117         } else {
   118             shadow = _restingShadowOpacity;
   119             offset = _restingShadowOffset;
   120             radius = _restingShadowRadius;
   121             opacity = 1;
   122             scale = 1.0/kPickedUpScale;
   123             z = _restingZ;
   124         }
   125 
   126 #if !TARGET_OS_IPHONE
   127         self.zPosition = z;
   128         self.shadowOpacity = shadow;
   129         self.shadowOffset = offset;
   130         self.shadowRadius = radius;
   131 #endif
   132         self.opacity = opacity;
   133         self.scale *= scale;
   134         _pickedUp = up;
   135     }
   136 }
   137 
   138 
   139 - (BOOL)containsPoint:(CGPoint)p
   140 {
   141     // Make picked-up pieces invisible to hit-testing.
   142     // Otherwise, while dragging a Bit, hit-testing the cursor position would always return
   143     // that Bit, since it's directly under the cursor...
   144     if( self.pickedUp )
   145         return NO;
   146     else
   147         return [super containsPoint: p];
   148 }
   149 
   150 
   151 -(id<BitHolder>) holder
   152 {
   153     // Look for my nearest ancestor that's a BitHolder:
   154     for( CALayer *layer=self.superlayer; layer; layer=layer.superlayer ) {
   155         if( [layer conformsToProtocol: @protocol(BitHolder)] )
   156             return (id<BitHolder>)layer;
   157         else if( [layer isKindOfClass: [Bit class]] )
   158             return nil;
   159     }
   160     return nil;
   161 }
   162 
   163 
   164 - (void) destroy
   165 {
   166     // "Pop" the Bit by expanding it 5x as it fades away:
   167     self.scale = 5;
   168     self.opacity = 0.0;
   169     // Removing the view from its superlayer right now would cancel the animations.
   170     // Instead, defer the removal until sometime shortly after the animations finish:
   171     [self performSelector: @selector(removeFromSuperlayer) withObject: nil afterDelay: 1.0];
   172 }
   173 
   174 
   175 @end