Oolite 1.91.0.7646-241128-10e222e
Loading...
Searching...
No Matches
OOTrumble.m
Go to the documentation of this file.
1/*
2
3OOTrumble.m
4
5Oolite
6Copyright (C) 2004-2013 Giles C Williams and contributors
7
8This program is free software; you can redistribute it and/or
9modify it under the terms of the GNU General Public License
10as published by the Free Software Foundation; either version 2
11of the License, or (at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program; if not, write to the Free Software
20Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21MA 02110-1301, USA.
22
23*/
24
25#import "OOTrumble.h"
26#import "Universe.h"
27#import "PlayerEntity.h"
28#import "OOTexture.h"
29#import "ResourceManager.h"
30#import "OOSound.h"
31#import "OOStringParsing.h"
32#import "OOMaths.h"
33#import "MyOpenGLView.h"
34
35
36static void InitTrumbleSounds(void);
37static void PlayTrumbleIdle(void);
38static void PlayTrumbleSqueal(void);
39
40
41@implementation OOTrumble
42
43- (id) init
44{
45 self = [super init];
46
47 int i;
48 for (i = 0; i < 4; i++)
49 {
50 colorPoint1[i] = 1.0;
51 colorPoint2[i] = 1.0;
52 }
53
54 return self;
55}
56
57- (id) initForPlayer:(PlayerEntity*) p1
58{
59 self = [super init];
60
61 [self setupForPlayer: p1 digram: @"a1"];
62
63 return self;
64}
65
66- (id) initForPlayer:(PlayerEntity*) p1 digram:(NSString*) digramString
67{
68 self = [super init];
69
70 [self setupForPlayer: p1 digram: digramString];
71
72 return self;
73}
74
75- (void) setupForPlayer:(PlayerEntity*) p1 digram:(NSString*) digramString
76{
77 // set digram
78 //
79 digram[0] = [digramString characterAtIndex:0];
80 digram[1] = [digramString characterAtIndex:1];
81
82 // set player
83 //
84 player = p1;
85
86 // set color points
87 int r0 = (int)digram[0];
88 int r1 = (int)digram[1];
89 int pointscheme[6] = { 1, 1, 0, 0, 1, 1};
90 int ps = r0 >> 2; // first digram determines pattern of points
91 pointscheme[0] = (ps >> 3) & 1;
92 pointscheme[1] = (ps >> 2) & 1;
93 pointscheme[2] = (ps >> 1) & 1;
94 pointscheme[3] = ps & 1;
95 pointscheme[4] = (ps >> 2) & 1;
96 pointscheme[5] = (ps >> 3) & 1;
97
98 GLfloat c1[4] = { 1.0, 1.0, 1.0, 1.0};
99 GLfloat c2[4] = { 1.0, 0.0, 0.0, 1.0};
100
101 // I am missing something. Please clarify the intent of the following statement.
102 // The next statement shift the result of adding two masked values
103 // max_size = 0.90 + 0.50 * (((r0 & 0x38) + (r1 & 0x38)) >> 3) / 63.0; // inheritable
104 // The next statement adds masked(r0) to shifted(masked(r1)
105 // max_size = 0.90 + 0.50 * ((r0 & 0x38) + ((r1 & 0x38) >> 3)) / 63.0; // inheritable
106 // Sorry, but I cannot determine what you intended to do here.
107 //
108 // GILES: It's the second one, we're just determining a pseudo random max_size from the first digram
109 max_size = 0.90 + 0.50 * ((r0 & 0x38) + ((r1 & 0x38) >> 3)) / 63.0; // inheritable
110
111 // seed the random number generator
112 //
113 ranrot_srand(r0 + r1 * 256);
114
115 // set random colors
116 int col1 = r0 & 7;
117 int col2 = r1 & 7;
118 while (((col1 == 7)||(col1 == 0)) && ((col2 == 7)||(col2 == 0))) // monochrome not allowed
119 {
120 if (col1 == col2)
121 col1 = ranrot_rand() & 7;
122 else
123 col2 = ranrot_rand() & 7;
124 }
125 c1[0] = (GLfloat)(col1 & 1);
126 c1[1] = (GLfloat)((col1 >> 1) & 1);
127 c1[2] = (GLfloat)((col1 >> 2) & 1);
128 c2[0] = (GLfloat)(col2 & 1);
129 c2[1] = (GLfloat)((col2 >> 1) & 1);
130 c2[2] = (GLfloat)((col2 >> 2) & 1);
131 if (col1 == 0)
132 {
133 c1[0] = 0.5 + 0.1 * c2[1]; c1[1] = 0.5 + 0.1 * c2[2]; c1[2] = 0.5;
134 }
135 if (col1 == 7)
136 {
137 c1[0] = 1.0 - 0.1 * c2[1]; c1[1] = 1.0 - 0.1 * c2[2]; c1[2] = 0.9;
138 }
139 if (col2 == 0)
140 {
141 c2[0] = 0.5 + 0.1 * c1[2]; c2[1] = 0.5 + 0.1 * c1[0]; c2[2] = 0.5;
142 }
143 if (col2 == 7)
144 {
145 c2[0] = 1.0 - 0.1 * c1[2]; c2[1] = 1.0 - 0.1 * c1[0]; c2[2] = 0.9;
146 }
147
148 // position and motion
149 //
150 position.x = (ranrot_rand() & 15)* 28 - 210;
151 position.y = (ranrot_rand() & 15)* 28 - 210;
152 //
153 [self randomizeMotionX];
154 [self randomizeMotionY];
155
156 // rotation
157 //
160
161 //
162 int i;
163 for (i = 0; i < 4; i++)
164 {
165 colorPoint1[i] = c1[i];
166 colorPoint2[i] = c2[i];
167 }
168 //
169 for (i = 0; i < 6; i++)
170 {
172 if (pointscheme[i] == 0)
174 if (pointscheme[i] == 1)
176 }
177 //
178 for (i = 0; i < 4; i++)
179 {
180 colorEyes[i] = 0.2 * (2.0 * pointColor[3][i] + 2.0 * pointColor[1][i] + 1.0); // eyes - paler than average
181 colorBase[i] = 0.5 * (pointColor[2][i] + pointColor[3][i]); // mouth
182 }
183 //
184 size = 0.5 * (1.0 + randf());
185 [self calcGrowthRate];
186 hunger = 0.0;
187 discomfort = 0.0;
188 //
189 eye_position = NSMakePoint( 0.0, 0.075 * (randf() - randf()));
191 //
192 mouth_position = NSMakePoint( 0.0, 0.035 * (randf() - randf()));
194 //
197 animationTime = 0.0;
198 animationDuration = 1.5 + randf() * 3.0; // time until next animation
199 //
200 texture = [OOTexture textureWithName:@"trumblekit.png"
201 inFolder:@"Textures"
202 options:kOOTextureDefaultOptions | kOOTextureNoShrink
203 anisotropy:0.0f
204 lodBias:kOOTextureDefaultLODBias];
205 [texture retain];
206
208
209 readyToSpawn = NO;
210}
211
212- (void) dealloc
213{
214 [texture release];
215
216 [super dealloc];
217}
218
219- (void) spawnFrom:(OOTrumble*) parentTrumble
220{
221 if (parentTrumble)
222 {
223 // mutate..
224 unichar mutation1 = ranrot_rand() & ranrot_rand() & ranrot_rand() & 0xff; // each bit has a 1/8 chance of being set
225 unichar mutation2 = ranrot_rand() & ranrot_rand() & ranrot_rand() & 0xff; // each bit has a 1/8 chance of being set
226 unichar* parentdigram = [parentTrumble digram];
227 unichar newdigram[2];
228 newdigram[0] = parentdigram[0] ^ mutation1;
229 newdigram[1] = parentdigram[1] ^ mutation2;
230 //
231 [self setupForPlayer: player digram: [NSString stringWithCharacters:newdigram length:2]];
232 //
233 size = [parentTrumble size] * 0.4;
234 if (size < 0.5)
235 size = 0.5; // minimum size
236 position = [parentTrumble position];
237 rotation = [parentTrumble rotation];
238 movement = [parentTrumble movement];
239 movement.y += 8.0; // emerge!
240 }
241 else
242 {
243 size = 0.5; // minimum size
244 position.x = (ranrot_rand() & 15)* 28 - 210;
245 position.y = (ranrot_rand() & 15)* 28 - 210;
246 [self randomizeMotionX];
247 [self randomizeMotionY];
250 }
251 hunger = 0.25;
252 [self calcGrowthRate];
253 discomfort = 0.0;
254 [self actionSleep];
255}
256
257- (void) calcGrowthRate
258{
259 float rsize = size / max_size;
260 growth_rate = TRUMBLE_GROWTH_RATE * (1.0 - rsize);
261}
262
263
264- (unichar *) digram
265{
266 return digram;
267}
268
269- (NSPoint) position
270{
271 return position;
272}
273
274- (NSPoint) movement
275{
276 return movement;
277}
278
279- (GLfloat) rotation
280{
281 return rotation;
282}
283
284- (GLfloat) size
285{
286 return size;
287}
288
289- (GLfloat) hunger
290{
291 return hunger;
292}
293
294- (GLfloat) discomfort
295{
296 return discomfort;
297}
298
299
300
301// AI methods here
302- (void) actionIdle
303{
305 animationDuration = 1.5 + 3.0 * randf(); // time until next animation
306}
307
308- (void) actionBlink
309{
311 animationDuration = 0.5 + 0.5 * randf(); // time until next animation
312}
313
314- (void) actionSnarl
315{
317 animationDuration = 4.0 + 1.0 * randf(); // time until next animation
318}
319
320- (void) actionProot
321{
323 animationDuration = 1.5 + 0.5 * randf(); // time until next animation
324}
325
326- (void) actionShudder
327{
329 animationDuration = 2.25 + randf() * 1.5; // time until next animation
330}
331
332- (void) actionStoned
333{
335 animationDuration = 1.5 + randf() * 3.0; // time until next animation
336}
337
338- (void) actionPop
339{
341 animationDuration = 1.5 + randf() * 3.0; // time until next animation
342}
343
344- (void) actionSleep
345{
347 animationDuration = 12.0 + 12.0 * randf(); // time until next animation
348}
349
350- (void) actionSpawn
351{
353 animationDuration = 9.0 + 3.0 * randf(); // time until next animation
354}
355
356
357- (void) randomizeMotionX
358{
359 movement.x = 36 * (randf() - 0.5);
360 movement.x += (movement.x > 0)? 2.0: -2.0;
362}
363
364- (void) randomizeMotionY
365{
366 movement.y = 36 * (randf() - 0.5);
367 movement.y += (movement.y > 0)? 2.0: -2.0;
369}
370
371- (void) drawTrumble:(double) z
372{
373 /*
374 draws a trumble body as a fan of triangles...
375 2-------3-------4
376 | \ | / |
377 | \ | / |
378 | \ | / |
379 1-------0-------5
380
381 */
382 GLfloat wd = 96 * size;
383 GLfloat ht = 96 * size;
384 OOGL(glShadeModel(GL_SMOOTH));
385 OOGL(glEnable(GL_TEXTURE_2D));
386
388
389 OOGLTranslateModelView(make_vector(position.x, position.y, z));
390 OOGLMultModelView(OOMatrixForRotationZ(rotation));
391
392 [texture apply];
393
394 //
395 // Body..
396 //
397 OOGLBEGIN(GL_TRIANGLE_FAN);
398 glColor4fv(pointColor[3]);
399 glTexCoord2f( 0.25, 0.5);
400 glVertex2f( 0.0, -0.5 * ht);
401
402 glColor4fv(pointColor[0]);
403 glTexCoord2f( 0.0, 0.5);
404 glVertex2f( -0.5 * wd, -0.5 * ht);
405
406 glColor4fv(pointColor[1]);
407 glTexCoord2f( 0.0, 0.0);
408 glVertex2f( -0.5 * wd, 0.5 * ht);
409
410 glColor4fv(pointColor[2]);
411 glTexCoord2f( 0.25, 0.0);
412 glVertex2f( 0.0, 0.5 * ht);
413
414 glColor4fv(pointColor[4]);
415 glTexCoord2f( 0.5, 0.0);
416 glVertex2f( 0.5 * wd, 0.5 * ht);
417
418 glColor4fv(pointColor[5]);
419 glTexCoord2f( 0.5, 0.5);
420 glVertex2f( 0.5 * wd, -0.5 * ht);
421 OOGLEND();
422
423 //
424 // Eyes
425 //
426 GLfloat eyeTextureOffset = 0.0;
427 switch(eyeFrame)
428 {
429 case TRUMBLE_EYES_NONE :
430 case TRUMBLE_EYES_OPEN :
431 eyeTextureOffset = 0.0; break;
432 case TRUMBLE_EYES_SHUT :
433 eyeTextureOffset = 0.25; break;
434 case TRUMBLE_EYES_WIDE :
435 eyeTextureOffset = 0.5; break;
436 }
437
438 OOGLTranslateModelView(make_vector(eye_position.x * wd, eye_position.y * ht, 0.0));
439
440 OOGL(glColor4fv(colorEyes));
441 OOGLBEGIN(GL_QUADS);
442 glTexCoord2f( 0.5, eyeTextureOffset);
443 glVertex2f( -0.5 * wd, 0.20 * ht);
444
445 glTexCoord2f( 1.0, eyeTextureOffset);
446 glVertex2f( 0.5 * wd, 0.20 * ht);
447
448 glTexCoord2f( 1.0, eyeTextureOffset + 0.25);
449 glVertex2f( 0.5 * wd, -0.30 * ht);
450
451 glTexCoord2f( 0.5, eyeTextureOffset + 0.25);
452 glVertex2f( -0.5 * wd, -0.30 * ht);
453 OOGLEND();
454
455 //
456 // Mouth
457 //
458 GLfloat mouthTextureOffset = 0.0;
459 switch(mouthFrame)
460 {
461 case TRUMBLE_MOUTH_POUT :
462 mouthTextureOffset = 0.500; break;
463 case TRUMBLE_MOUTH_NONE :
465 mouthTextureOffset = 0.625; break;
467 mouthTextureOffset = 0.750; break;
469 mouthTextureOffset = 0.875; break;
470 }
471
472 OOGLTranslateModelView(make_vector(mouth_position.x * wd, mouth_position.y * ht, 0.0));
473
474 OOGL(glColor4fv(colorBase));
475 OOGLBEGIN(GL_QUADS);
476 glTexCoord2f( 0.0, mouthTextureOffset);
477 glVertex2f( -0.25 * wd, -0.10 * ht);
478
479 glTexCoord2f( 0.25, mouthTextureOffset);
480 glVertex2f( 0.25 * wd, -0.10 * ht);
481
482 glTexCoord2f( 0.25, mouthTextureOffset + 0.125);
483 glVertex2f( 0.25 * wd, -0.35 * ht);
484
485 glTexCoord2f( 0.0, mouthTextureOffset + 0.125);
486 glVertex2f( -0.25 * wd, -0.35 * ht);
487 OOGLEND();
488
489 // finally..
491 OOGL(glDisable(GL_TEXTURE_2D));
492}
493
494- (void) updateTrumble:(double) delta_t
495{
496 // player movement
497 NSPoint p_mov = NSMakePoint(TRUMBLE_MAX_ROTATIONAL_VELOCITY * [player dialPitch], TRUMBLE_MAX_ROTATIONAL_VELOCITY * [player dialRoll]);
498 switch ([UNIVERSE viewDirection])
499 {
500 GLfloat t;
501 case VIEW_AFT:
502 p_mov.x = -p_mov.x;
503 p_mov.y = -p_mov.y;
504 break;
505 case VIEW_STARBOARD:
506 t = p_mov.x;
507 p_mov.x = -p_mov.y;
508 p_mov.y = t;
509 break;
510 case VIEW_PORT:
511 t = p_mov.x;
512 p_mov.x = p_mov.y;
513 p_mov.y = -t;
514 break;
515
516 default:
517 break;
518 }
519 p_mov.x *= -4.0;
520
521 // movement
522 //
523 GLfloat wd = 0.5 * 96 * size;
524 GLfloat ht = 0.5 * 96 * size;
525 //
526 GLfloat bumpx = 320 * 1.5 - wd;
527 GLfloat bumpy = 240 * 1.5 - ht;
528 //
529 position.x += delta_t * movement.x;
530 if ((position.x < -bumpx)||(position.x > bumpx))
531 {
532 position.x = (position.x < -bumpx)? -bumpx : bumpx;
533 [self randomizeMotionX];
534 }
535 position.y += delta_t * (movement.y + p_mov.x);
536 if ((position.y < -bumpy)||(position.y > bumpy))
537 {
538 position.y = (position.y < -bumpy)? -bumpy : bumpy;
539 [self randomizeMotionY];
540 }
541
542 // rotation
543 //
544 rotation += delta_t * (rotational_velocity + p_mov.y);
546 {
548 {
551 }
553 {
556 }
557 }
558 // growth
559 //
560 size += delta_t * growth_rate;
561 hunger += delta_t * (growth_rate + TRUMBLE_GROWTH_RATE);
562 if (size > max_size) // fully_grown.. stop growing
563 {
564 size = max_size;
565 growth_rate = 0.0;
566 }
567 [self calcGrowthRate];
568 if (hunger > 0.75)
569 growth_rate = 0.0;
570 if (hunger > 1.0)
571 hunger = 1.0; // clamp
572
573 // feelings
574 //
575 GLfloat temp = [player hullHeatLevel];
576 discomfort += delta_t * hunger * 0.02 * (1.0 - hunger);
577 if (temp > 0.33)
578 discomfort += delta_t * (temp - 0.33) * (temp - 0.33) * 0.05;
579 if (discomfort > 1.0)
580 discomfort = 1.0; // clamp
581
582 // feeding & reproducing
583 //
584 // am I really hungry?
585 if (hunger > 0.50)
586 {
587 // consult menu...
588 ShipEntity *selectedCargopod = nil;
589 float mostYummy = 0.0;
590 NSMutableArray *cargopods = [player cargo]; // the cargo pods
591 NSUInteger i, n_pods = [cargopods count];
592 for (i = 0 ; i < n_pods; i++)
593 {
594 ShipEntity *cargopod = [cargopods objectAtIndex:i];
595 OOCommodityType cargo_type = [cargopod commodityType];
596 float yumminess = (1.0 + randf()) * [[UNIVERSE commodityMarket] trumbleOpinionForGood:cargo_type];
597 if (yumminess > mostYummy)
598 {
599 selectedCargopod = cargopod;
600 mostYummy = yumminess;
601 }
602 }
603 if (selectedCargopod)
604 {
605 // feed
606 float trumbleAppetiteAccumulator = [player trumbleAppetiteAccumulator];
607
608 trumbleAppetiteAccumulator += hunger;
609 hunger = 0.0;
610 discomfort -= mostYummy * 0.5;
611 if (discomfort < 0.0)
612 discomfort = 0.0;
613 if (trumbleAppetiteAccumulator > 10.0)
614 {
615 // eaten all of this cargo!
616 NSString* ms = [NSString stringWithFormat:DESC(@"trumbles-eat-@"),
617 [UNIVERSE displayNameForCommodity:[selectedCargopod commodityType]]];
618
619 [UNIVERSE addMessage: ms forCount: 4.5];
620 [cargopods removeObject:selectedCargopod];
621 trumbleAppetiteAccumulator -= 10.0;
622
623 // consider breeding - must be full grown and happy
624 if ((size > 0.95)&&(discomfort < 0.25))
625 {
626 readyToSpawn = YES;
627 }
628
629 [player setTrumbleAppetiteAccumulator:trumbleAppetiteAccumulator];
630 }
631 }
632 }
633
634 // animations
635 //
636 switch (animation)
637 {
638 case TRUMBLE_ANIM_SNARL :
639 [self updateSnarl: delta_t]; break;
641 [self updateShudder: delta_t]; break;
643 [self updateStoned: delta_t]; break;
644 case TRUMBLE_ANIM_DIE :
645 [self updatePop: delta_t]; break;
646 case TRUMBLE_ANIM_BLINK :
647 [self updateBlink: delta_t]; break;
648 case TRUMBLE_ANIM_PROOT :
649 [self updateProot: delta_t]; break;
650 case TRUMBLE_ANIM_SLEEP :
651 [self updateSleep: delta_t]; break;
652 case TRUMBLE_ANIM_SPAWN :
653 [self updateSpawn: delta_t]; break;
654 case TRUMBLE_ANIM_IDLE :
655 default:
656 [self updateIdle: delta_t]; break;
657 }
658
659
660}
661
662- (void) updateIdle:(double) delta_t
663{
664 animationTime += delta_t;
666 {
667 // blink or proot or idle and/or change direction
668 [self actionIdle];
669 if (randf() < 0.25)
670 [self actionBlink];
671 if (randf() < 0.10)
672 [self randomizeMotionX];
673 if (randf() < 0.10)
674 [self randomizeMotionY];
675 if (randf() < 0.05)
676 [self actionProot];
677 if (randf() < 0.01)
678 [self actionSleep];
679 if (randf() < 0.01)
680 [self actionSnarl];
681 //
682 if (readyToSpawn)
683 {
684 [self actionSpawn];
685 readyToSpawn = NO;
686 }
687 //
688 if (discomfort > 0.5 + randf())
689 {
690 [self actionShudder];
691 }
692 //
693 if (discomfort > 0.96)
694 {
695 [self actionPop];
696 }
697 //
699 animationTime = 0.0;
700 }
701}
702
703- (void) updateBlink:(double) delta_t
704{
706 animationTime += delta_t;
708 {
709 // blink or proot or idle
710 [self actionIdle];
711 if (randf() < 0.05)
712 [self actionBlink];
713 if (randf() < 0.1)
714 [self actionProot];
716 animationTime = 0.0;
718 }
719}
720
721- (void) updateSnarl:(double) delta_t
722{
723 int pc = 100 * animationTime / animationDuration;
724 if (pc < 25)
725 {
728 }
729 if ((pc >=25)&&(pc < 90))
730 {
731 double vibr = (pc & 1)? -1.0 : 1.0;
732 if (digram[1] & 4)
733 position.x += size * vibr * 0.5;
734 else
735 position.y += size * vibr * 0.5;
737 if (pc & 2)
739 else
741 }
742 if ((pc >=90)&&(pc < 100))
743 {
746 }
747 animationTime += delta_t;
749 {
750 // blink or idle
751 [self actionIdle];
752 if (randf() < 0.1)
753 [self actionBlink];
755 animationTime = 0.0;
758 }
759}
760
761- (void) updateProot:(double) delta_t
762{
763 if (!animationTime)
764 {
765 animationStage = 0;
766 }
767 int pc = 100 * animationTime / animationDuration;
768 if (pc < 10)
769 {
772 }
773 if (pc >=10)
774 {
775 double vibr = (pc & 2)? -1.0 : 1.0;
776 position.x += size * vibr * 0.25;
779 if (!animationStage)
780 {
781 animationStage = 1;
783 }
784 }
785 animationTime += delta_t;
787 {
788 // blink or idle
789 [self actionIdle];
790 if (randf() < 0.1)
791 [self actionBlink];
793 animationTime = 0.0;
796 }
797}
798
799- (void) updateShudder:(double) delta_t
800{
801 if (!animationTime)
802 {
806 }
807 int pc = 100 * animationTime / animationDuration;
808 if (pc < 10)
809 {
812 }
813 if (pc >= 10)
814 {
815 double vibr = (pc & 2)? -0.25 : 0.25;
816 position.x += size * vibr;
819 }
820 animationTime += delta_t;
822 {
823 // feel better
824 discomfort *= 0.9;
825 // blink or idle
826 [self actionIdle];
827 if (randf() < 0.1)
828 [self actionBlink];
830 animationTime = 0.0;
833 }
834}
835
836- (void) updateStoned:(double) delta_t
837{
838}
839
840- (void) updatePop:(double) delta_t
841{
842 if (!animationTime)
843 {
846 movement.y = (ranrot_rand() & 7);
847 if (randf() < 0.5)
848 rotational_velocity = 63 + (ranrot_rand() & 127);
849 else
850 rotational_velocity = -63 - (ranrot_rand() & 127);
851 // squeal here!
853 }
854 float pc = animationTime / animationDuration;
855
856 // fading alpha
857 colorPoint1[1] *= (1.0 - delta_t);
858 colorPoint2[1] *= (1.0 - delta_t);
859 colorPoint1[2] *= (1.0 - delta_t);
860 colorPoint2[2] *= (1.0 - delta_t);
861 colorPoint1[3] = (1.0 - pc);
862 colorPoint2[3] = (1.0 - pc);
863 colorBase[3] = (1.0 - pc);
864
865 // falling
866 movement.y -= delta_t * 98.0;
867 rotational_velocity *= (1.0 + delta_t);
868
869 // shrinking
870 size -= delta_t * (1.0 - pc) * size;
871
872 animationTime += delta_t;
874 {
875 // kaputnik!
876 [player removeTrumble:self];
877 }
878}
879
880- (void) updateSleep:(double) delta_t
881{
882 if (!animationTime)
883 {
886 }
888 int pc = 512 * animationTime / animationDuration;
889 if (pc & 16)
890 {
891 double vibr = (pc & 2)? -0.0025 : 0.0025;
892 eye_position.y += size * vibr;
893 mouth_position.y += size * vibr * -0.5;
894 }
895 else
896 {
899 }
900 animationTime += delta_t;
902 {
903 // idle or proot
906 [self actionIdle];
907 if (randf() < 0.25)
908 [self actionProot];
910 animationTime = 0.0;
912 }
913}
914
915- (void) updateSpawn:(double) delta_t
916{
917 movement.x *= (1.0 - delta_t);
918 movement.y *= (1.0 - delta_t);
919 rotation *= (1.0 - delta_t);
920 rotational_velocity *= (1.0 - delta_t);
923 int pc = 256 * animationTime / animationDuration;
924 double vibr = (pc & 2)? -0.002 * pc : 0.002 * pc;
925 position.x += size * vibr;
926 animationTime += delta_t;
928 {
929 // proot
932 [self actionProot];
934 animationTime = 0.0;
937 [self randomizeMotionX];
938 [player addTrumble:self];
939 }
940}
941
942- (NSDictionary*) dictionary
943{
944 return [NSDictionary dictionaryWithObjectsAndKeys:
945 [NSString stringWithCharacters:digram length:2], @"digram",
946 [NSNumber numberWithFloat:hunger], @"hunger",
947 [NSNumber numberWithFloat:discomfort], @"discomfort",
948 [NSNumber numberWithFloat:size], @"size",
949 [NSNumber numberWithFloat:growth_rate], @"growth_rate",
950 [NSNumber numberWithFloat:rotation], @"rotation",
951 [NSNumber numberWithFloat:rotational_velocity], @"rotational_velocity",
952 StringFromPoint(position), @"position",
953 StringFromPoint(movement), @"movement",
954 nil];
955}
956
957- (void) setFromDictionary:(NSDictionary*) dict
958{
959 NSString* digramString = (NSString*)[dict objectForKey:@"digram"];
960 [self setupForPlayer: player digram: digramString];
961 hunger = [[dict objectForKey: @"hunger"] floatValue];
962 discomfort = [[dict objectForKey: @"discomfort"] floatValue];
963 size = [[dict objectForKey: @"size"] floatValue];
964 growth_rate = [[dict objectForKey: @"growth_rate"] floatValue];
965 rotation = [[dict objectForKey: @"rotation"] floatValue];
966 rotational_velocity = [[dict objectForKey: @"rotational_velocity"] floatValue];
967 position = PointFromString([dict objectForKey: @"position"]);
968 movement = PointFromString([dict objectForKey: @"movement"]);
969}
970
971@end
972
973
977
978static void InitTrumbleSounds(void)
979{
981 {
982 sTrumbleSoundSource = [[OOSoundSource alloc] init];
983 sTrumbleIdleSound = [[OOSound alloc] initWithCustomSoundKey:@"[trumble-idle]"];
984 sTrumbleSqealSound = [[OOSound alloc] initWithCustomSoundKey:@"[trumble-squeal]"];
985 }
986}
987
988
989static void PlayTrumbleIdle(void)
990{
991 // Only play idle sound if no trumble is making noise.
992 if (![sTrumbleSoundSource isPlaying])
993 {
994 // trumble sound from random direction - where's it gone now?
995 [sTrumbleSoundSource setPosition:OORandomUnitVector()];
996 [sTrumbleSoundSource playSound:sTrumbleIdleSound];
997 }
998}
999
1000
1001static void PlayTrumbleSqueal(void)
1002{
1003 // Play squeal sound if no trumble is currently squealing, but trumping idle sound.
1004 if (![sTrumbleSoundSource isPlaying] || [sTrumbleSoundSource sound] == sTrumbleIdleSound)
1005 {
1006 // trumble sound from random direction - where's it gone now?
1007 [sTrumbleSoundSource setPosition:OORandomUnitVector()];
1008 [sTrumbleSoundSource playSound:sTrumbleSqealSound];
1009 }
1010}
void OOGLPushModelView(void)
void OOGLTranslateModelView(Vector vector)
void OOGLMultModelView(OOMatrix matrix)
OOMatrix OOGLPopModelView(void)
#define OOGLBEGIN
Definition OOOpenGL.h:253
#define OOGL(statement)
Definition OOOpenGL.h:251
#define OOGLEND
Definition OOOpenGL.h:254
return nil
float y
float x
NSPoint PointFromString(NSString *xyString)
#define TRUMBLE_MAX_ROTATION
Definition OOTrumble.h:33
@ TRUMBLE_MOUTH_NONE
Definition OOTrumble.h:62
@ TRUMBLE_MOUTH_GROWL
Definition OOTrumble.h:64
@ TRUMBLE_MOUTH_NORMAL
Definition OOTrumble.h:66
@ TRUMBLE_MOUTH_POUT
Definition OOTrumble.h:63
@ TRUMBLE_MOUTH_SNARL
Definition OOTrumble.h:65
#define TRUMBLE_GROWTH_RATE
Definition OOTrumble.h:36
@ TRUMBLE_ANIM_SLEEP
Definition OOTrumble.h:48
@ TRUMBLE_ANIM_IDLE
Definition OOTrumble.h:41
@ TRUMBLE_ANIM_SHUDDER
Definition OOTrumble.h:45
@ TRUMBLE_ANIM_PROOT
Definition OOTrumble.h:44
@ TRUMBLE_ANIM_STONED
Definition OOTrumble.h:46
@ TRUMBLE_ANIM_SNARL
Definition OOTrumble.h:43
@ TRUMBLE_ANIM_DIE
Definition OOTrumble.h:49
@ TRUMBLE_ANIM_BLINK
Definition OOTrumble.h:42
@ TRUMBLE_ANIM_SPAWN
Definition OOTrumble.h:47
#define TRUMBLE_MAX_ROTATIONAL_VELOCITY
Definition OOTrumble.h:34
@ TRUMBLE_EYES_OPEN
Definition OOTrumble.h:55
@ TRUMBLE_EYES_NONE
Definition OOTrumble.h:54
@ TRUMBLE_EYES_WIDE
Definition OOTrumble.h:57
@ TRUMBLE_EYES_SHUT
Definition OOTrumble.h:56
static OOSound * sTrumbleIdleSound
Definition OOTrumble.m:975
static void PlayTrumbleSqueal(void)
Definition OOTrumble.m:1001
static OOSoundSource * sTrumbleSoundSource
Definition OOTrumble.m:974
static OOSound * sTrumbleSqealSound
Definition OOTrumble.m:976
static void InitTrumbleSounds(void)
Definition OOTrumble.m:978
static void PlayTrumbleIdle(void)
Definition OOTrumble.m:989
NSString * OOCommodityType
Definition OOTypes.h:106
#define UNIVERSE
Definition Universe.h:840
void playSound:(OOSound *inSound)
void setPosition:(Vector inPosition)
id textureWithName:inFolder:options:anisotropy:lodBias:(NSString *name,[inFolder] NSString *directory,[options] OOTextureFlags options,[anisotropy] GLfloat anisotropy,[lodBias] GLfloat lodBias)
Definition OOTexture.m:134
void actionStoned()
Definition OOTrumble.m:332
void actionIdle()
Definition OOTrumble.m:302
void randomizeMotionX()
Definition OOTrumble.m:357
NSDictionary * dictionary()
Definition OOTrumble.m:942
NSPoint mouth_position
Definition OOTrumble.h:97
void actionSnarl()
Definition OOTrumble.m:314
enum trumble_animation animation
Definition OOTrumble.h:102
GLfloat discomfort
Definition OOTrumble.h:84
NSPoint position
Definition OOTrumble.h:93
GLfloat rotation
Definition OOTrumble.h:90
void actionSleep()
Definition OOTrumble.m:344
GLfloat colorBase[4]
Definition OOTrumble.h:77
GLfloat size
Definition OOTrumble.h:86
GLfloat colorPoint1[4]
Definition OOTrumble.h:78
void randomizeMotionY()
Definition OOTrumble.m:364
enum trumble_eyes eyeFrame
Definition OOTrumble.h:108
int animationStage
Definition OOTrumble.h:105
NSPoint movement
Definition OOTrumble.h:94
void actionProot()
Definition OOTrumble.m:320
GLfloat colorEyes[4]
Definition OOTrumble.h:80
GLfloat colorPoint2[4]
Definition OOTrumble.h:79
OOTexture * texture
Definition OOTrumble.h:110
GLfloat rotational_velocity
Definition OOTrumble.h:91
BOOL readyToSpawn
Definition OOTrumble.h:114
GLfloat saved_float2
Definition OOTrumble.h:112
GLfloat max_size
Definition OOTrumble.h:87
void actionBlink()
Definition OOTrumble.m:308
enum trumble_mouth mouthFrame
Definition OOTrumble.h:107
void actionSpawn()
Definition OOTrumble.m:350
GLfloat * pointColor[6]
Definition OOTrumble.h:81
GLfloat growth_rate
Definition OOTrumble.h:88
void calcGrowthRate()
Definition OOTrumble.m:257
double animationDuration
Definition OOTrumble.h:100
GLfloat saved_float1
Definition OOTrumble.h:112
PlayerEntity * player
Definition OOTrumble.h:73
GLfloat hunger
Definition OOTrumble.h:83
unichar digram[2]
Definition OOTrumble.h:75
enum trumble_animation nextAnimation
Definition OOTrumble.h:103
void actionShudder()
Definition OOTrumble.m:326
double animationTime
Definition OOTrumble.h:99
void dealloc()
Definition OOTrumble.m:212
void actionPop()
Definition OOTrumble.m:338
NSPoint eye_position
Definition OOTrumble.h:96
OOCommodityType commodityType()
voidpf void uLong size
Definition ioapi.h:134
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
float randf(void)
void ranrot_srand(uint32_t seed)
#define ranrot_rand()