-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
319 lines (273 loc) · 10.8 KB
/
main.cpp
File metadata and controls
319 lines (273 loc) · 10.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
#include <iostream>
#include <fstream>
#include "game.h"
#include "field.h"
#include "testfield.h"
// #include "T01.h"
// #include "T02.h"
// #include "T03.h"
// #include "T04.h"
// #include "T05.h"
// #include "T06.h"
// #include "T07.h"
// #include "T08.h"
// #include "T09.h"
// #include "T10.h"
// #include "T11.h"
// #include "T12.h"
// #include "T13.h"
// #include "T14.h"
// #include "T15.h"
// #include "T16.h"
// #include "T17.h"
// #include "T18.h"
// #include "T19.h"
// #include "T20.h"
// #include "T21.h"
// #include "T22.h"
// #include "T23.h"
// #include "T24.h"
// #include "T25.h"
// #include "T26.h"
// #include "T27.h"
// #include "T28.h"
// #include "T29.h"
// #include "T30.h"
#include "T31.h"
// #include "T32.h"
// #include "T33.h"
// #include "T34.h"
// #include "T35.h"
// #include "T36.h"
// #include "T37.h"
// #include "T38.h"
// #include "T39.h"
// #include "T40.h"
io::path texturepath="enigma3d.app/Contents/Resources/";
class MyEventReceiver : public IEventReceiver
{
public:
core::position2di Position;
virtual bool OnEvent(const SEvent& event)
{
if (event.EventType == irr::EET_KEY_INPUT_EVENT)
KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
if (event.EventType == irr::EET_MOUSE_INPUT_EVENT)
{
switch(event.MouseInput.Event)
{
case EMIE_MOUSE_MOVED:
Position.X = event.MouseInput.X;
Position.Y = event.MouseInput.Y;
break;
default:
break;
}
}
return false;
}
virtual bool IsKeyDown(EKEY_CODE keyCode) const
{
return KeyIsDown[keyCode];
}
MyEventReceiver()
{
for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
KeyIsDown[i] = false;
}
private:
bool KeyIsDown[KEY_KEY_CODES_COUNT];
};
// This function is called by the main routine when reading the
// level field to create the respective types of stones:
Field* makefield(int fieldtype, ISceneManager* smgr, IVideoDriver* driver, int i, int j, Field::playground pg){
switch(fieldtype){
case tWall:
return new Wall(smgr,driver,i,j,pg);
break;
case tTestWall:
return new TestWall(smgr,driver,i,j,pg);
break;
case tFloor:
return new Floor(smgr,driver,i,j,pg);
break;
case tLightFloor:
return new LightFloor(smgr,driver,i,j,pg);
break;
case tT31: return new T31(smgr,driver,i,j,pg); break;
/*case tT01: return new T01(smgr,driver,i,j,pg); break;
case tT02: return new T02(smgr,driver,i,j,pg); break;
case tT03: return new T03(smgr,driver,i,j,pg); break;
case tT04: return new T04(smgr,driver,i,j,pg); break;
case tT05: return new T05(smgr,driver,i,j,pg); break;
case tT06: return new T06(smgr,driver,i,j,pg); break;
case tT07: return new T07(smgr,driver,i,j,pg); break;
case tT08: return new T08(smgr,driver,i,j,pg); break;
case tT09: return new T09(smgr,driver,i,j,pg); break;
case tT10: return new T10(smgr,driver,i,j,pg); break;
case tT11: return new T11(smgr,driver,i,j,pg); break;
case tT12: return new T12(smgr,driver,i,j,pg); break;
case tT13: return new T13(smgr,driver,i,j,pg); break;
case tT14: return new T14(smgr,driver,i,j,pg); break;
case tT15: return new T15(smgr,driver,i,j,pg); break;
case tT16: return new T16(smgr,driver,i,j,pg); break;
case tT17: return new T17(smgr,driver,i,j,pg); break;
case tT18: return new T18(smgr,driver,i,j,pg); break;
case tT19: return new T19(smgr,driver,i,j,pg); break;
case tT20: return new T20(smgr,driver,i,j,pg); break;
case tT21: return new T21(smgr,driver,i,j,pg); break;
case tT22: return new T22(smgr,driver,i,j,pg); break;
case tT23: return new T23(smgr,driver,i,j,pg); break;
case tT24: return new T24(smgr,driver,i,j,pg); break;
case tT25: return new T25(smgr,driver,i,j,pg); break;
case tT26: return new T26(smgr,driver,i,j,pg); break;
case tT27: return new T27(smgr,driver,i,j,pg); break;
case tT28: return new T28(smgr,driver,i,j,pg); break;
case tT29: return new T29(smgr,driver,i,j,pg); break;
case tT30: return new T30(smgr,driver,i,j,pg); break;
case tT32: return new T32(smgr,driver,i,j,pg); break;
case tT33: return new T33(smgr,driver,i,j,pg); break;
case tT34: return new T34(smgr,driver,i,j,pg); break;
case tT35: return new T35(smgr,driver,i,j,pg); break;
case tT36: return new T36(smgr,driver,i,j,pg); break;
case tT37: return new T37(smgr,driver,i,j,pg); break;
case tT38: return new T38(smgr,driver,i,j,pg); break;
case tT39: return new T39(smgr,driver,i,j,pg); break;
case tT40: return new T40(smgr,driver,i,j,pg); break;*/
default:
cerr << "Undefined field type in level file: " << fieldtype << endl;
error("");
}
}
int main()
{
// Initialization of Device, Video Driver and Scene Manager
video::E_DRIVER_TYPE driverType=video::EDT_OPENGL;
MyEventReceiver receiver;
IrrlichtDevice* device = createDevice(driverType,
core::dimension2d<u32>(960, 720), 16, false, false, false, &receiver);
if (device == 0) return 1;
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
// Building the scene.
// open level file
ifstream infile;
infile.open("enigma3d.app/Contents/Resources/field.lvl");
if (infile.fail()) error("Could not open level file\n");
// checking the file starts with "Enigma-3D"
string line;
infile >> line;
if (line!="Enigma-3D") error("Illegal Level file: "+line+"\n");
Field* playground[dimx][dimy];
// now reading from level file one number for each field
// and creating a wall or floor of the appropriate sub-class
for(int j=0; j<dimy; j++){
for(int i=0; i<dimx; i++){
// determine filed type
int fieldtype;
infile >> fieldtype;
playground[i][j]=makefield(fieldtype,smgr,driver,i,j,playground);
}
}
// the level file may contain additional requests for introducing
// some fields to each other:
while ((infile >> line), line!="end"){
// must have the form "introduce x1 y1 to x1 y2"
if (line!="introduce") error("Level File: mistake in introduce lines");
int x1,x2,y1,y2;
infile >> x1 >> y1 >> line >> x2 >> y2;
if ( (x1 < 0) || x1>=dimx
|| (x2 < 0) || x2>=dimx
|| (y1 < 0) || y1>=dimy
|| (y2 < 0) || y2>=dimy
|| line !="to" )
error("Level File: mistake in introduce lines");
// call the introduceTo method of field x1 y1:
playground[x1][y1]->introduceTo(*(playground[x2][y2]));
}
infile.close();
Sphere *sphere=new Sphere(smgr,driver);
scene::ICameraSceneNode* camera=smgr->addCameraSceneNode(NULL,core::vector3df(offsety+50.f,100.f,offsetx),
core::vector3df(offsety,0.f,offsetx));
// to change the camera position use:
// camera->setPosition(core::vector3df(...));
// see docmentation of ICameraSceneNode for more (like setting target, rotation, aspect)
// hide the mouse cursor
device->getCursorControl()->setVisible(false);
// for time measurement: get an initial time reference
u32 then = device->getTimer()->getTime();
// for mouse-move measurement: get an initial mouse position
core::position2di RefPosition=receiver.Position;
// compute the field number where the sphere is and notify that field
int fieldx=getFieldx(sphere->getPosition());
int fieldy=getFieldy(sphere->getPosition());
playground[fieldx][fieldy]->sphereEnter(*sphere);
while(device->run())
{
if(receiver.IsKeyDown(irr::KEY_KEY_Q)) exit(0); // quit game on key Q
// Adapt speed by the difference in mouse position
core::position2di mousemove;
mousemove.X=(receiver.Position.X-RefPosition.X);
mousemove.Y=(receiver.Position.Y-RefPosition.Y);
// eliminating too rapid movements of the mouse
if (fabs(mousemove.X)>10) mousemove.X=0;
if (fabs(mousemove.Y)>10) mousemove.Y=0;
// remember current mouse position
RefPosition=receiver.Position;
// Measure the time that has passed since last round
const u32 now = device->getTimer()->getTime();
const f32 frameDeltaTime = (f32)(now - then) / 1000.f;
then = now;
/* The field that the sphere is currently on is now in control
to decide how the sphere moves within the time
frameDeltaTime. This will typically NOT include collision
detection with surrounding walls---that will be done
later. */
playground[fieldx][fieldy]->handleSphere(*sphere,mousemove,frameDeltaTime);
// tell also all other fields that time has passed:
for(int j=0; j<dimy; j++)
for(int i=0; i<dimx; i++)
if (!(i==fieldx && j==fieldy))
playground[i][j]->timeProgress(frameDeltaTime);
/* Now we turn to collision detection:
- compute what field the sphere is on now
- compute overlap with adjacent fields
- notify all fields where overlap is non-zero
*/
core::vector3df spherePosition = sphere->getPosition();
int new_fieldx=getFieldx(spherePosition);
int new_fieldy=getFieldy(spherePosition);
f32 xoE=getOverlapx(spherePosition,new_fieldx+1);
f32 xoW=getOverlapx(spherePosition,new_fieldx-1);
f32 yoN=getOverlapy(spherePosition,new_fieldy+1);
f32 yoS=getOverlapy(spherePosition,new_fieldy-1);
// E = east, W = west...
if (xoE) playground[new_fieldx+1][new_fieldy]->sphereOverlap(*sphere,xoE,0.f);
if (xoW) playground[new_fieldx-1][new_fieldy]->sphereOverlap(*sphere,xoW,0.f);
if (yoN) playground[new_fieldx][new_fieldy+1]->sphereOverlap(*sphere,0.f,yoN);
if (yoS) playground[new_fieldx][new_fieldy-1]->sphereOverlap(*sphere,0.f,yoS);
/*
if (spherePosition==sphere->getPosition()){
// if there was no collision with E,W,N, or S, check for overlaps with diagonal fields
if (xoE && yoN) playground[new_fieldx+1][new_fieldy+1]->sphereOverlap(*sphere,xoE/4,yoN/4);
if (xoE && yoS) playground[new_fieldx+1][new_fieldy-1]->sphereOverlap(*sphere,xoE/4,yoS/4);
if (xoW && yoN) playground[new_fieldx-1][new_fieldy+1]->sphereOverlap(*sphere,xoW/4,yoN/4);
if (xoW && yoS) playground[new_fieldx-1][new_fieldy-1]->sphereOverlap(*sphere,xoW/4,yoS/4);
}
*/
// If all the movements and collisions have changed the field the sphere is on, notify both
// the field it leaves and the field it enters:
if (new_fieldx!=fieldx || new_fieldy!=fieldy){
playground[fieldx][fieldy]->sphereExit(*sphere);
fieldx=new_fieldx;
fieldy=new_fieldy;
playground[fieldx][fieldy]->sphereEnter(*sphere);
}
// Draw the picture anew and go to a next round
driver->beginScene(true, true, video::SColor(255,113,113,133));
smgr->drawAll();
driver->endScene();
}
device->drop();
return 0;
}