ConsoleGameEngine
266 строк · 6.2 Кб
1#define CGE_IMPL
2#include "ConsoleGameEngine.hpp"
3
4#undef min
5#undef max
6
7#include <algorithm>
8#include <list>
9
10using namespace std;
11
12class FirstPersonShooter : public ConsoleGameEngine
13{
14public:
15FirstPersonShooter()
16{
17sAppName = L"FPS in Command Prompt";
18}
19
20int nMapWidth = 24;
21int nMapHeight = 20;
22wstring sMap;
23
24float fPlayerX = 22.0f;
25float fPlayerY = 12.0f;
26
27float fPlayerDirX = -1.0f;
28float fPlayerDirY = 0.0f;
29
30float fPlaneX = 0.0f;
31float fPlaneY = 0.66f;
32
33float fSpeed = 5.0f;
34float fRotation = 3.0f;
35
36float fDepth = 16.0f;
37
38protected:
39bool OnUserCreate() override
40{
41sMap += L"#################....###";
42sMap += L"#......................#";
43sMap += L"#..#####...............#";
44sMap += L"#.........#............#";
45sMap += L"..........#............#";
46sMap += L"...##.....#......####..#";
47sMap += L"..........#............#";
48sMap += L"..........#.....#......#";
49sMap += L".......................#";
50sMap += L"....###................#";
51sMap += L"#...#........####......#";
52sMap += L"#...#...#....####.......";
53sMap += L"#...#...................";
54sMap += L"#...#.........###.......";
55sMap += L"#.......................";
56sMap += L"#.....######...........#";
57sMap += L"#..........##..........#";
58sMap += L"#................###...#";
59sMap += L"#......................#";
60sMap += L"###...##################";
61
62return true;
63}
64
65bool OnUserUpdate(float fDeltaTime) override
66{
67if (GetKey(VK_UP).bHeld)
68{
69float fNewPosX = fPlayerX + fPlayerDirX * fSpeed * fDeltaTime;
70float fNewPosY = fPlayerY + fPlayerDirY * fSpeed * fDeltaTime;
71
72if ((int)fNewPosX < nMapWidth && (int)fNewPosX >= 0)
73{
74if (sMap[(int)fPlayerY * nMapWidth + (int)fNewPosX] != '#')
75fPlayerX = fNewPosX;
76}
77
78if ((int)fNewPosY < nMapHeight && (int)fNewPosY >= 0)
79{
80if (sMap[(int)fNewPosY * nMapWidth + (int)fPlayerX] != '#')
81fPlayerY = fNewPosY;
82}
83}
84
85if (GetKey(VK_DOWN).bHeld)
86{
87float fNewPosX = fPlayerX - fPlayerDirX * fSpeed * fDeltaTime;
88float fNewPosY = fPlayerY - fPlayerDirY * fSpeed * fDeltaTime;
89
90if ((int)fNewPosX < nMapWidth && (int)fNewPosX >= 0)
91{
92if (sMap[(int)fPlayerY * nMapWidth + (int)fNewPosX] != '#')
93fPlayerX = fNewPosX;
94}
95
96if ((int)fNewPosY < nMapHeight && (int)fNewPosY >= 0)
97{
98if (sMap[(int)fNewPosY * nMapWidth + (int)fPlayerX] != '#')
99fPlayerY = fNewPosY;
100}
101}
102
103if (GetKey(VK_RIGHT).bHeld)
104{
105float fOldDirX = fPlayerDirX;
106float fOldPlaneX = fPlaneX;
107
108fPlayerDirX = fPlayerDirX * cos(-fRotation * fDeltaTime) - fPlayerDirY * sin(-fRotation * fDeltaTime);
109fPlayerDirY = fOldDirX * sin(-fRotation * fDeltaTime) + fPlayerDirY * cos(-fRotation * fDeltaTime);
110
111fPlaneX = fPlaneX * cos(-fRotation * fDeltaTime) - fPlaneY * sin(-fRotation * fDeltaTime);
112fPlaneY = fOldPlaneX * sin(-fRotation * fDeltaTime) + fPlaneY * cos(-fRotation * fDeltaTime);
113}
114
115if (GetKey(VK_LEFT).bHeld)
116{
117float fOldDirX = fPlayerDirX;
118float fOldPlaneX = fPlaneX;
119
120fPlayerDirX = fPlayerDirX * cos(fRotation * fDeltaTime) - fPlayerDirY * sin(fRotation * fDeltaTime);
121fPlayerDirY = fOldDirX * sin(fRotation * fDeltaTime) + fPlayerDirY * cos(fRotation * fDeltaTime);
122
123fPlaneX = fPlaneX * cos(fRotation * fDeltaTime) - fPlaneY * sin(fRotation * fDeltaTime);
124fPlaneY = fOldPlaneX * sin(fRotation * fDeltaTime) + fPlaneY * cos(fRotation * fDeltaTime);
125}
126
127list<pair<pair<int, int>, float>> listStripes;
128
129for (int x = 0; x < ScreenWidth(); x++)
130{
131float fCamera = 2.0f * (float)x / (float)ScreenWidth() - 1.0f;
132
133float fRayX = fPlayerDirX + fPlaneX * fCamera;
134float fRayY = fPlayerDirY + fPlaneY * fCamera;
135
136float fCellDistX = (fRayX == 0.0f) ? INFINITY : abs(1.0f / fRayX);
137float fCellDistY = (fRayY == 0.0f) ? INFINITY : abs(1.0f / fRayY);
138
139int nMapX = (float)fPlayerX;
140int nMapY = (float)fPlayerY;
141
142float fDistToNextX, fDistToNextY;
143int nStepX, nStepY;
144
145if (fRayX < 0.0f)
146{
147nStepX = -1;
148fDistToNextX = (fPlayerX - (float)nMapX) * fCellDistX;
149}
150else
151{
152nStepX = 1;
153fDistToNextX = ((float)nMapX - fPlayerX + 1.0f) * fCellDistX;
154}
155
156if (fRayY < 0.0f)
157{
158nStepY = -1;
159fDistToNextY = (fPlayerY - (float)nMapY) * fCellDistY;
160}
161else
162{
163nStepY = 1;
164fDistToNextY = ((float)nMapY - fPlayerY + 1.0f) * fCellDistY;
165}
166
167float fDistToWall = 0.0f;
168
169int nSide;
170bool bHitWall = false;
171
172while (!bHitWall)
173{
174if (fDistToNextX < fDistToNextY)
175{
176fDistToNextX += fCellDistX;
177nMapX += nStepX;
178nSide = 0;
179}
180else
181{
182fDistToNextY += fCellDistY;
183nMapY += nStepY;
184nSide = 1;
185}
186
187if (nMapX < 0 || nMapY < 0 || nMapX >= nMapWidth || nMapY >= nMapHeight)
188{
189fDistToWall = fDepth;
190bHitWall = true;
191}
192else
193{
194if (sMap[nMapY * nMapWidth + nMapX] == L'#')
195bHitWall = true;
196}
197}
198
199if (fDistToWall != fDepth)
200{
201if (nSide == 0)
202fDistToWall = fDistToNextX - fCellDistX;
203else
204fDistToWall = fDistToNextY - fCellDistY;
205}
206
207float fStripeHeight = (float)ScreenHeight() / fDistToWall;
208
209int nCeiling = (int)max(-fStripeHeight * 0.5f + (float)ScreenHeight() * 0.5f, 0.0f);
210int nFloor = (int)min(fStripeHeight * 0.5f + (float)ScreenHeight() * 0.5f, (float)ScreenHeight() - 1.0f);
211
212listStripes.push_back({ { nCeiling, nFloor }, fDistToWall });
213}
214
215Clear(PIXEL_SOLID, FG_BLACK);
216
217int x = 0;
218for (const auto& s : listStripes)
219{
220int nCeiling = s.first.first;
221int nFloor = s.first.second;
222
223for (int y = 0; y <= nFloor; y++)
224{
225if (y <= nCeiling)
226{
227// Ceiling
228Draw(x, y, PIXEL_SOLID, FG_BLACK);
229
230// Floor
231Draw(x, ScreenHeight() - y, PIXEL_SOLID, FG_GREY);
232}
233else if (s.second < fDepth)
234{
235short nPixel;
236
237if (s.second / fDepth <= 0.25f) nPixel = PIXEL_SOLID;
238else if (s.second / fDepth <= 0.5f) nPixel = PIXEL_THREEQUARTERS;
239else if (s.second / fDepth <= 0.75f) nPixel = PIXEL_HALF;
240else if (s.second / fDepth <= 1.0f) nPixel = PIXEL_QUARTER;
241
242// Wall
243Draw(x, y, nPixel, FG_WHITE);
244}
245else
246{
247// Void
248Draw(x, y, PIXEL_SOLID, FG_BLACK);
249}
250}
251
252x++;
253}
254
255return true;
256}
257
258};
259
260int main()
261{
262FirstPersonShooter demo;
263if (demo.ConstructConsole(256, 240, 4, 4) == rcode::OK)
264demo.Run();
265return 0;
266}
267