Source/Bit.m
author Jens Alfke <jens@mooseyard.com>
Sat Jul 05 17:46:43 2008 -0700 (2008-07-05)
changeset 11 436cbdf56810
parent 10 6c78cc6bd7a6
child 12 4e567e11f45f
permissions -rw-r--r--
* Improved drag-and-drop (supports CandyBar)
* Fixed DiscPiece
* Inheritable layer styles
etc.
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@10
    25
#import "Player.h"
jens@0
    26
#import "QuartzUtils.h"
jens@0
    27
jens@0
    28
jens@9
    29
#ifdef TARGET_OS_IPHONE
jens@9
    30
#define kPickedUpScale   2.0      // more magnification, so piece shows up underneath fingertip
jens@9
    31
#define kPickedUpOpacity 0.6
jens@9
    32
#else
jens@9
    33
#define kPickedUpScale   1.2
jens@9
    34
#define kPickedUpOpacity 0.9
jens@9
    35
#endif
jens@9
    36
jens@9
    37
jens@0
    38
@implementation Bit
jens@0
    39
jens@0
    40
jens@0
    41
- (id) copyWithZone: (NSZone*)zone
jens@0
    42
{
jens@1
    43
    Bit *clone = [super copyWithZone: zone];
jens@1
    44
    clone->_owner = _owner;
jens@1
    45
    return clone;
jens@0
    46
}
jens@0
    47
jens@7
    48
- (void) dealloc
jens@7
    49
{
jens@7
    50
    [super dealloc];
jens@7
    51
}
jens@7
    52
jens@7
    53
jens@0
    54
@synthesize owner=_owner;
jens@0
    55
jens@0
    56
- (BOOL) isFriendly         {return _owner.friendly;}
jens@0
    57
- (BOOL) isUnfriendly       {return _owner.unfriendly;}
jens@0
    58
jens@7
    59
/*
jens@7
    60
- (NSString*) identifier
jens@7
    61
{
jens@7
    62
    if( _identifier )
jens@7
    63
        return _identifier;
jens@7
    64
    // Defaults to just identifying the owner:
jens@7
    65
    return [NSString stringWithFormat: @"p%i", _owner.index+1];
jens@7
    66
}
jens@7
    67
*/
jens@0
    68
jens@0
    69
- (CGFloat) scale
jens@0
    70
{
jens@0
    71
    NSNumber *scale = [self valueForKeyPath: @"transform.scale"];
jens@0
    72
    return scale.floatValue;
jens@0
    73
}
jens@0
    74
jens@0
    75
- (void) setScale: (CGFloat)scale
jens@0
    76
{
jens@0
    77
    [self setValue: [NSNumber numberWithFloat: scale]
jens@0
    78
        forKeyPath: @"transform.scale"];
jens@0
    79
}
jens@0
    80
jens@0
    81
jens@0
    82
- (int) rotation
jens@0
    83
{
jens@0
    84
    NSNumber *rot = [self valueForKeyPath: @"transform.rotation"];
jens@0
    85
    return round( rot.doubleValue * 180.0 / M_PI );
jens@0
    86
}
jens@0
    87
jens@0
    88
- (void) setRotation: (int)rotation
jens@0
    89
{
jens@0
    90
    [self setValue: [NSNumber numberWithDouble: rotation*M_PI/180.0]
jens@0
    91
        forKeyPath: @"transform.rotation"];
jens@0
    92
}
jens@0
    93
jens@0
    94
jens@0
    95
- (BOOL) pickedUp
jens@0
    96
{
jens@9
    97
    return _pickedUp;
jens@0
    98
}
jens@0
    99
jens@0
   100
- (void) setPickedUp: (BOOL)up
jens@0
   101
{
jens@9
   102
    if( up != _pickedUp ) {
jens@11
   103
        CGFloat shadow, radius, opacity, z, scale;
jens@11
   104
        CGSize offset;
jens@0
   105
        if( up ) {
jens@0
   106
            shadow = 0.8;
jens@11
   107
            offset = CGSizeMake(2,2);
jens@0
   108
            radius = 8;
jens@9
   109
            opacity = kPickedUpOpacity;
jens@9
   110
            scale = kPickedUpScale;
jens@0
   111
            z = kPickedUpZ;
jens@0
   112
            _restingZ = self.zPosition;
jens@11
   113
            _restingShadowOpacity = self.shadowOpacity;
jens@11
   114
            _restingShadowOffset  = self.shadowOffset;
jens@11
   115
            _restingShadowRadius  = self.shadowRadius;
jens@0
   116
        } else {
jens@11
   117
            shadow = _restingShadowOpacity;
jens@11
   118
            offset = _restingShadowOffset;
jens@11
   119
            radius = _restingShadowRadius;
jens@11
   120
            opacity = 1;
jens@9
   121
            scale = 1.0/kPickedUpScale;
jens@0
   122
            z = _restingZ;
jens@0
   123
        }
jens@9
   124
jens@9
   125
        //self.zPosition = z;
jens@8
   126
#if !TARGET_OS_IPHONE
jens@0
   127
        self.shadowOpacity = shadow;
jens@11
   128
        self.shadowOffset = offset;
jens@0
   129
        self.shadowRadius = radius;
jens@1
   130
#endif
jens@0
   131
        self.opacity = opacity;
jens@0
   132
        self.scale *= scale;
jens@9
   133
        _pickedUp = up;
jens@0
   134
    }
jens@0
   135
}
jens@0
   136
jens@0
   137
jens@0
   138
- (BOOL)containsPoint:(CGPoint)p
jens@0
   139
{
jens@0
   140
    // Make picked-up pieces invisible to hit-testing.
jens@0
   141
    // Otherwise, while dragging a Bit, hit-testing the cursor position would always return
jens@0
   142
    // that Bit, since it's directly under the cursor...
jens@0
   143
    if( self.pickedUp )
jens@0
   144
        return NO;
jens@0
   145
    else
jens@0
   146
        return [super containsPoint: p];
jens@0
   147
}
jens@0
   148
jens@0
   149
jens@0
   150
-(id<BitHolder>) holder
jens@0
   151
{
jens@0
   152
    // Look for my nearest ancestor that's a BitHolder:
jens@0
   153
    for( CALayer *layer=self.superlayer; layer; layer=layer.superlayer ) {
jens@0
   154
        if( [layer conformsToProtocol: @protocol(BitHolder)] )
jens@0
   155
            return (id<BitHolder>)layer;
jens@0
   156
        else if( [layer isKindOfClass: [Bit class]] )
jens@0
   157
            return nil;
jens@0
   158
    }
jens@0
   159
    return nil;
jens@0
   160
}
jens@0
   161
jens@0
   162
jens@0
   163
- (void) destroy
jens@0
   164
{
jens@0
   165
    // "Pop" the Bit by expanding it 5x as it fades away:
jens@0
   166
    self.scale = 5;
jens@0
   167
    self.opacity = 0.0;
jens@0
   168
    // Removing the view from its superlayer right now would cancel the animations.
jens@0
   169
    // Instead, defer the removal until sometime shortly after the animations finish:
jens@0
   170
    [self performSelector: @selector(removeFromSuperlayer) withObject: nil afterDelay: 1.0];
jens@0
   171
}
jens@0
   172
jens@0
   173
jens@0
   174
@end