Line data Source code
1 0 : /* 2 : 3 : OORingEffectEntity.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 "OORingEffectEntity.h" 27 : #import "Universe.h" 28 : #import "OOMacroOpenGL.h" 29 : 30 : 31 0 : #define kRingDuration (2.0f) // seconds 32 0 : #define kRingAttack (0.4f) // fade-up time 33 : 34 : // Dimensions and growth rates per second in terms of base size. 35 0 : #define kInnerRingInitialSizeFactor (0.5f) 36 0 : #define kOuterRingInitialSizeFactor (1.25f * kInnerRingInitialSizeFactor) 37 0 : #define kInnerRingGrowthRateFactor (1.1f * kInnerRingInitialSizeFactor) 38 0 : #define kOuterRingGrowthRateFactor (1.25f * kInnerRingInitialSizeFactor) 39 : 40 : // These factors produce a ring that shrinks to nothing, then expands to the size of a "normal" ring. 41 0 : #define kShrinkingRingInnerGrowthFactor (-2.5) 42 0 : #define kShrinkingRingOuterGrowthFactor (-2.0) 43 : 44 : 45 0 : enum 46 : { 47 : kCircleSegments = 65 48 : }; 49 0 : static struct { float x, y; } sCircleVerts[kCircleSegments]; // holds vector coordinates for a unit circle 50 : 51 : 52 : @implementation OORingEffectEntity 53 : 54 0 : + (void)initialize 55 : { 56 : unsigned i; 57 : for (i = 0; i < kCircleSegments; i++) 58 : { 59 : sCircleVerts[i].x = sinf(i * 2 * M_PI / (kCircleSegments - 1)); 60 : sCircleVerts[i].y = cosf(i * 2 * M_PI / (kCircleSegments - 1)); 61 : } 62 : } 63 : 64 : 65 0 : - (id) initRingFromEntity:(Entity *)sourceEntity 66 : { 67 : if (sourceEntity == nil) 68 : { 69 : [self release]; 70 : return nil; 71 : } 72 : 73 : if ((self = [super init])) 74 : { 75 : GLfloat baseSize = [sourceEntity collisionRadius]; 76 : _innerRadius = baseSize * kInnerRingInitialSizeFactor; 77 : _outerRadius = baseSize * kOuterRingInitialSizeFactor; 78 : _innerGrowthRate = baseSize * kInnerRingGrowthRateFactor; 79 : _outerGrowthRate = baseSize * kOuterRingGrowthRateFactor; 80 : 81 : [self setPosition:[sourceEntity position]]; 82 : [self setOrientation:[sourceEntity orientation]]; 83 : [self setVelocity:[sourceEntity velocity]]; 84 : 85 : [self setStatus:STATUS_EFFECT]; 86 : [self setScanClass:CLASS_NO_DRAW]; 87 : 88 : [self setOwner:sourceEntity]; 89 : } 90 : 91 : return self; 92 : } 93 : 94 : 95 : + (instancetype) ringFromEntity:(Entity *)sourceEntity 96 : { 97 : return [[[self alloc] initRingFromEntity:sourceEntity] autorelease]; 98 : } 99 : 100 : 101 : + (instancetype) shrinkingRingFromEntity:(Entity *)sourceEntity 102 : { 103 : OORingEffectEntity *result = [self ringFromEntity:sourceEntity]; 104 : if (result != nil) 105 : { 106 : result->_innerGrowthRate *= kShrinkingRingInnerGrowthFactor; 107 : result->_outerGrowthRate *= kShrinkingRingOuterGrowthFactor; 108 : } 109 : return result; 110 : } 111 : 112 : 113 0 : - (NSString *) descriptionComponents 114 : { 115 : return [NSString stringWithFormat:@"%f seconds passed of %f", _timePassed, kRingDuration]; 116 : } 117 : 118 : 119 0 : - (void) update:(OOTimeDelta) delta_t 120 : { 121 : [super update:delta_t]; 122 : _timePassed += delta_t; 123 : 124 : _innerRadius += delta_t * _innerGrowthRate; 125 : _outerRadius += delta_t * _outerGrowthRate; 126 : 127 : if (_timePassed > kRingDuration) 128 : { 129 : [UNIVERSE removeEntity:self]; 130 : } 131 : } 132 : 133 : 134 0 : - (void) drawImmediate:(bool)immediate translucent:(bool)translucent 135 : { 136 : if (!translucent || [UNIVERSE breakPatternHide]) return; 137 : 138 : OO_ENTER_OPENGL(); 139 : OOSetOpenGLState(OPENGL_STATE_ADDITIVE_BLENDING); 140 : 141 : GLfloat alpha = OOClamp_0_1_f((kRingDuration - _timePassed) / kRingAttack); 142 : 143 : GLfloat ex_em_hi[4] = {0.6, 0.8, 1.0, alpha}; // pale blue 144 : GLfloat ex_em_lo[4] = {0.2, 0.0, 1.0, 0.0}; // purplish-blue-black 145 : 146 : OOGLBEGIN(GL_TRIANGLE_STRIP); 147 : for (unsigned i = 0; i < kCircleSegments; i++) 148 : { 149 : glColor4fv(ex_em_lo); 150 : glVertex3f(_innerRadius * sCircleVerts[i].x, _innerRadius * sCircleVerts[i].y, 0.0f); 151 : glColor4fv(ex_em_hi); 152 : glVertex3f(_outerRadius * sCircleVerts[i].x, _outerRadius * sCircleVerts[i].y, 0.0f); 153 : } 154 : OOGLEND(); 155 : 156 : OOVerifyOpenGLState(); 157 : OOCheckOpenGLErrors(@"OOQuiriumCascadeEntity after drawing %@", self); 158 : } 159 : 160 : 161 0 : - (BOOL) isEffect 162 : { 163 : return YES; 164 : } 165 : 166 : 167 0 : - (BOOL) canCollide 168 : { 169 : return NO; 170 : } 171 : 172 : @end