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