Line data Source code
1 0 : /* 2 : 3 : OOFlasherEntity.m 4 : 5 : 6 : Oolite 7 : Copyright (C) 2004-2013 Giles C Williams and contributors 8 : 9 : This program is free software; you can redistribute it and/or 10 : modify it under the terms of the GNU General Public License 11 : as published by the Free Software Foundation; either version 2 12 : of the License, or (at your option) any later version. 13 : 14 : This program is distributed in the hope that it will be useful, 15 : but WITHOUT ANY WARRANTY; without even the implied warranty of 16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 : GNU General Public License for more details. 18 : 19 : You should have received a copy of the GNU General Public License 20 : along with this program; if not, write to the Free Software 21 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 22 : MA 02110-1301, USA. 23 : 24 : */ 25 : 26 : #import "OOFlasherEntity.h" 27 : #import "Universe.h" 28 : #import "PlayerEntity.h" 29 : #import "OOColor.h" 30 : #import "OOCollectionExtractors.h" 31 : #import "NSDictionaryOOExtensions.h" 32 : 33 : 34 : @interface OOFlasherEntity (Internal) 35 : 36 0 : - (void) setUpColors:(NSArray *)colorSpecifiers; 37 0 : - (void) getCurrentColorComponents; 38 : 39 : @end 40 : 41 : 42 : @implementation OOFlasherEntity 43 : 44 : + (instancetype) flasherWithDictionary:(NSDictionary *)dictionary 45 : { 46 : return [[[OOFlasherEntity alloc] initWithDictionary:dictionary] autorelease]; 47 : } 48 : 49 : 50 : - (id) initWithDictionary:(NSDictionary *)dictionary 51 : { 52 : float size = [dictionary oo_floatForKey:@"size" defaultValue:1.0f]; 53 : 54 : if ((self = [super initWithDiameter:size])) 55 : { 56 : _frequency = [dictionary oo_floatForKey:@"frequency" defaultValue:1.0f] * 2.0f; 57 : _phase = [dictionary oo_floatForKey:@"phase" defaultValue:0.0f]; 58 : _brightfraction = [dictionary oo_floatForKey:@"bright_fraction" defaultValue:0.5f]; 59 : 60 : [self setUpColors:[dictionary oo_arrayForKey:@"colors"]]; 61 : [self getCurrentColorComponents]; 62 : 63 : [self setActive:[dictionary oo_boolForKey:@"initially_on" defaultValue:YES]]; 64 : } 65 : return self; 66 : } 67 : 68 : 69 0 : - (void) dealloc 70 : { 71 : [_colors release]; 72 : 73 : [super dealloc]; 74 : } 75 : 76 : 77 0 : - (void) setUpColors:(NSArray *)colorSpecifiers 78 : { 79 : NSMutableArray *colors = [NSMutableArray arrayWithCapacity:[colorSpecifiers count]]; 80 : id specifier = nil; 81 : NSEnumerator *specEnum = [colorSpecifiers objectEnumerator]; 82 : while ((specifier = [specEnum nextObject])) 83 : { 84 : [colors addObject:[OOColor colorWithDescription:specifier saturationFactor:0.75f]]; 85 : } 86 : 87 : _colors = [colors copy]; 88 : } 89 : 90 : 91 0 : - (void) getCurrentColorComponents 92 : { 93 : [self setColor:[_colors objectAtIndex:_activeColor] alpha:_colorComponents[3]]; 94 : } 95 : 96 : 97 : - (BOOL) isActive 98 : { 99 : return _active; 100 : } 101 : 102 : 103 : - (void) setActive:(BOOL)active 104 : { 105 : _active = !!active; 106 : } 107 : 108 : 109 : - (OOColor *) color 110 : { 111 : return [OOColor colorWithRed:_colorComponents[0] 112 : green:_colorComponents[1] 113 : blue:_colorComponents[2] 114 : alpha:_colorComponents[3]]; 115 : } 116 : 117 : 118 : - (float) frequency 119 : { 120 : return _frequency; 121 : } 122 : 123 : 124 : - (void) setFrequency:(float)frequency 125 : { 126 : _frequency = frequency; 127 : } 128 : 129 : 130 : - (float) phase 131 : { 132 : return _phase; 133 : } 134 : 135 : 136 : - (void) setPhase:(float)phase 137 : { 138 : _phase = phase; 139 : } 140 : 141 : 142 : - (float) fraction 143 : { 144 : return _brightfraction; 145 : } 146 : 147 : 148 : - (void) setFraction:(float)fraction 149 : { 150 : _brightfraction = fraction; 151 : } 152 : 153 : 154 0 : - (void) update:(OOTimeDelta) delta_t 155 : { 156 : [super update:delta_t]; 157 : 158 : _time += delta_t; 159 : 160 : if (_frequency != 0) 161 : { 162 : float wave = sinf(_frequency * M_PI * (_time + _phase)); 163 : NSUInteger count = [_colors count]; 164 : if (count > 1 && wave < 0) 165 : { 166 : if (!_justSwitched && wave > _wave) // don't test for wave >= _wave - could give wrong results with very low frequencies 167 : { 168 : _justSwitched = YES; 169 : ++_activeColor; 170 : _activeColor %= count; //_activeColor = ++_activeColor % count; is potentially undefined operation 171 : [self setColor:[_colors objectAtIndex:_activeColor]]; 172 : } 173 : } 174 : else if (_justSwitched) 175 : { 176 : _justSwitched = NO; 177 : } 178 : 179 : float threshold = cosf(_brightfraction * M_PI); 180 : 181 : float brightness = _brightfraction; 182 : if (wave > threshold) 183 : { 184 : brightness = _brightfraction + (((1-_brightfraction)/(1-threshold))*(wave-threshold)); 185 : } 186 : else if (wave < threshold) 187 : { 188 : brightness = _brightfraction + ((_brightfraction/(threshold+1))*(wave-threshold)); 189 : } 190 : 191 : _colorComponents[3] = brightness; 192 : 193 : _wave = wave; 194 : } 195 : else 196 : { 197 : _colorComponents[3] = 1.0; 198 : } 199 : } 200 : 201 : 202 0 : - (void) drawImmediate:(bool)immediate translucent:(bool)translucent 203 : { 204 : if (_active) 205 : { 206 : [super drawImmediate:immediate translucent:translucent]; 207 : } 208 : } 209 : 210 : 211 0 : - (void) drawSubEntityImmediate:(bool)immediate translucent:(bool)translucent 212 : { 213 : if (_active) 214 : { 215 : [super drawSubEntityImmediate:immediate translucent:translucent]; 216 : } 217 : } 218 : 219 : 220 0 : - (BOOL) isFlasher 221 : { 222 : return YES; 223 : } 224 : 225 : 226 0 : - (double)findCollisionRadius 227 : { 228 : return [self diameter] / 2.0; 229 : } 230 : 231 : 232 0 : - (void) rescaleBy:(GLfloat)factor 233 : { 234 : [self setDiameter:[self diameter] * factor]; 235 : } 236 : 237 : 238 0 : - (void) rescaleBy:(GLfloat)factor writeToCache:(BOOL)writeToCache 239 : { 240 : /* Do nothing; this is only needed because of OOEntityWithDrawable 241 : implementation requirements */ 242 : } 243 : 244 : @end 245 : 246 : 247 : @implementation Entity (OOFlasherEntityExtensions) 248 : 249 : - (BOOL) isFlasher 250 : { 251 : return NO; 252 : } 253 : 254 : @end