1 #include "SDL.h"
2 #include <stdlib.h>
3 #include "../engine/kyra.h"
4
5 #include "tutorial1.h"
6
7 using namespace grinliz;
8
9 #define SDL_TIMER_EVENT ( SDL_USEREVENT + 0 )
10 const int TIMER_INTERVAL = 80;
11
12 const int SCREENX = 640;
13 const int SCREENY = 480;
14
15 // A structure to store the spell effect.
16 struct SpellEffect
17 {
18 KrSprite* particle;
19 int xSpeed;
20 int ySpeed;
21 };
22
TimerCallback(Uint32 interval)23 Uint32 TimerCallback(Uint32 interval)
24 {
25 SDL_Event event;
26 event.type = SDL_TIMER_EVENT;
27
28 SDL_PeepEvents( &event, 1, SDL_ADDEVENT, 0 );
29 return TIMER_INTERVAL;
30 }
31
32
main(int argc,char * argv[])33 int main( int argc, char *argv[] )
34 {
35 // code_d A linked list for our spell effects.
36 GlCircleList< SpellEffect > spells;
37 // code_d A random number generator.
38 Random random;
39
40 SDL_Surface* screen;
41
42 const SDL_version* sdlVersion = SDL_Linked_Version();
43 if ( sdlVersion->minor < 2 )
44 {
45 printf( "SDL version must be at least 1.2.0" );
46 exit( 254 );
47 }
48
49 /* Initialize the SDL library */
50 if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_NOPARACHUTE) < 0 ) {
51 printf( "Couldn't initialize SDL: %s\n",SDL_GetError());
52 exit(255);
53 }
54
55 /* Create a display for the image */
56 screen = SDL_SetVideoMode( SCREENX, SCREENY, 0, SDL_SWSURFACE );
57 if ( screen == NULL ) {
58 exit(3);
59 }
60
61 KrEngine* engine = new KrEngine( screen );
62 engine->Draw();
63
64 // Load the dat file.
65 // The dat file was carefully created in the sprite
66 // editor. Loading allows us access to the
67 // MAGE, PARTICLE, and CARPET.
68 if ( !engine->Vault()->LoadDatFile( "tutorial1.dat" ) )
69 {
70 printf( "Error loading the tutorial dat file\n" );
71 exit( 255 );
72 }
73
74 // Get the CARPET resource
75 KrSpriteResource* carpetRes = engine->Vault()->GetSpriteResource( TUT1_CARPET );
76 GLASSERT( carpetRes );
77
78 // Create the carpet sprite and add it to the tree
79 KrSprite* carpet = new KrSprite( carpetRes );
80 carpet->SetPos( SCREENX, SCREENY / 2 );
81 engine->Tree()->AddNode( 0, carpet );
82 // Get the MAGE resource, create the mage.
83 KrSpriteResource* mageRes = engine->Vault()->GetSpriteResource( TUT1_MAGE );
84 GLASSERT( mageRes );
85 KrSprite* mage = new KrSprite( mageRes );
86
87 // Add the Mage as a child of the carpet.
88 engine->Tree()->AddNode( carpet, mage );
89 // code_d Get the Particle resource
90 KrSpriteResource* particleRes = engine->Vault()->GetSpriteResource( TUT1_PARTICLE );
91 GLASSERT( particleRes );
92 SDL_Event event;
93 bool done = false;
94
95 // Start timing!
96 SDL_SetTimer( TIMER_INTERVAL, TimerCallback );
97
98 while( !done && SDL_WaitEvent(&event) )
99 {
100 if ( event.type == SDL_QUIT )
101 break;
102
103 switch(event.type)
104 {
105 case SDL_KEYDOWN:
106 {
107 done = true;
108 }
109 break;
110
111 case SDL_TIMER_EVENT:
112 {
113 // code_d Walk the list and move the particles
114 GlCircleListIterator< SpellEffect > it( spells );
115 for( it.Begin(); !it.Done(); it.Next() )
116 {
117 KrSprite* particle = it.Current().particle;
118
119 // Check for something off the stage
120 if ( particle->X() < 0
121 || particle->X() > SCREENX
122 || particle->Y() < 0
123 || particle->Y() > SCREENY )
124 {
125 // code_d Remove the sprite from the Tree
126 engine->Tree()->DeleteNode( particle );
127
128 // Back up the iterator, remove the next.
129 it.Remove();
130 it.Prev();
131 continue;
132 }
133
134 // This particle stays on the stage. So
135 // move it based on speed.
136 particle->SetPos( particle->X() + it.Current().xSpeed,
137 particle->Y() + it.Current().ySpeed );
138
139 // Fade out the alpha channel, so that the
140 // particles dim.
141 KrColorTransform color = particle->CTransform();
142
143 const int FADE = 2;
144 if ( color.Alpha() > FADE )
145 {
146 color.SetAlpha( color.Alpha() - FADE );
147 particle->SetColor( color );
148 }
149
150 }
151
152 // Perhaps create particles
153 if ( random.Rand( 4 ) == 0 )
154 {
155 int x, y;
156 SpellEffect spellEffect;
157
158 // We're creating a particle: Right hand or left?
159 // The offsets are measured in pixels, and
160 // measured in the source tga file.
161 if ( random.Rand( 2 ) )
162 {
163 x = carpet->X() - 32;
164 y = carpet->Y() - 28;
165 }
166 else
167 {
168 x = carpet->X() - 32;
169 y = carpet->Y() + 28;
170 }
171
172 // code_d Create the particle
173 spellEffect.particle = new KrSprite( particleRes );
174 spellEffect.particle->SetPos( x, y );
175
176 spellEffect.xSpeed = -8 + random.Rand( 3 );
177 spellEffect.ySpeed = -2 + random.Rand( 4 );
178
179 engine->Tree()->AddNode( 0, spellEffect.particle );
180
181 // code_d Transform the color
182 KrColorTransform colorXForm;
183
184 // This takes the 3 color components, and scales
185 // them back by a random percentage. This essentially
186 // turns the white ball into a random color in
187 // RGB space.
188 colorXForm.SetRed( random.Rand( 256 ), 0 );
189 colorXForm.SetGreen( random.Rand( 256 ), 0 );
190 colorXForm.SetBlue( random.Rand( 256 ), 0 );
191
192 spellEffect.particle->SetColor( colorXForm );
193
194 spells.PushBack( spellEffect );
195 }
196 // Move the carpet.
197 carpet->DoStep();
198 if ( carpet->X() < 0 )
199 {
200 carpet->SetPos( SCREENX, carpet->Y() );
201 }
202 engine->Draw();
203 }
204 break;
205
206 default:
207 break;
208 }
209
210 }
211
212 delete engine;
213
214 SDL_Quit();
215 return 0;
216 }
217