ConsoleGameEngine

Форк
0
/
Raycaster.cpp 
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

10
using namespace std;
11

12
class FirstPersonShooter : public ConsoleGameEngine
13
{
14
public:
15
	FirstPersonShooter()
16
	{
17
		sAppName = L"FPS in Command Prompt";
18
	}
19

20
	int nMapWidth = 24;
21
	int nMapHeight = 20;
22
	wstring sMap;
23

24
	float fPlayerX = 22.0f;
25
	float fPlayerY = 12.0f;
26
	
27
	float fPlayerDirX = -1.0f;
28
	float fPlayerDirY = 0.0f;
29

30
	float fPlaneX = 0.0f;
31
	float fPlaneY = 0.66f;
32

33
	float fSpeed = 5.0f;
34
	float fRotation = 3.0f;
35

36
	float fDepth = 16.0f;
37

38
protected:
39
	bool OnUserCreate() override
40
	{
41
		sMap += L"#################....###";
42
		sMap += L"#......................#";
43
		sMap += L"#..#####...............#";
44
		sMap += L"#.........#............#";
45
		sMap += L"..........#............#";
46
		sMap += L"...##.....#......####..#";
47
		sMap += L"..........#............#";
48
		sMap += L"..........#.....#......#";
49
		sMap += L".......................#";
50
		sMap += L"....###................#";
51
		sMap += L"#...#........####......#";
52
		sMap += L"#...#...#....####.......";
53
		sMap += L"#...#...................";
54
		sMap += L"#...#.........###.......";
55
		sMap += L"#.......................";
56
		sMap += L"#.....######...........#";
57
		sMap += L"#..........##..........#";
58
		sMap += L"#................###...#";
59
		sMap += L"#......................#";
60
		sMap += L"###...##################";
61

62
		return true;
63
	}
64

65
	bool OnUserUpdate(float fDeltaTime) override
66
	{
67
		if (GetKey(VK_UP).bHeld)
68
		{
69
			float fNewPosX = fPlayerX + fPlayerDirX * fSpeed * fDeltaTime;
70
			float fNewPosY = fPlayerY + fPlayerDirY * fSpeed * fDeltaTime;
71

72
			if ((int)fNewPosX < nMapWidth && (int)fNewPosX >= 0)
73
			{
74
				if (sMap[(int)fPlayerY * nMapWidth + (int)fNewPosX] != '#')
75
					fPlayerX = fNewPosX;
76
			}
77

78
			if ((int)fNewPosY < nMapHeight && (int)fNewPosY >= 0)
79
			{
80
				if (sMap[(int)fNewPosY * nMapWidth + (int)fPlayerX] != '#')
81
					fPlayerY = fNewPosY;
82
			}
83
		}
84

85
		if (GetKey(VK_DOWN).bHeld)
86
		{
87
			float fNewPosX = fPlayerX - fPlayerDirX * fSpeed * fDeltaTime;
88
			float fNewPosY = fPlayerY - fPlayerDirY * fSpeed * fDeltaTime;
89

90
			if ((int)fNewPosX < nMapWidth && (int)fNewPosX >= 0)
91
			{
92
				if (sMap[(int)fPlayerY * nMapWidth + (int)fNewPosX] != '#')
93
					fPlayerX = fNewPosX;
94
			}
95

96
			if ((int)fNewPosY < nMapHeight && (int)fNewPosY >= 0)
97
			{
98
				if (sMap[(int)fNewPosY * nMapWidth + (int)fPlayerX] != '#')
99
					fPlayerY = fNewPosY;
100
			}
101
		}
102

103
		if (GetKey(VK_RIGHT).bHeld)
104
		{
105
			float fOldDirX = fPlayerDirX;
106
			float fOldPlaneX = fPlaneX;
107

108
			fPlayerDirX = fPlayerDirX * cos(-fRotation * fDeltaTime) - fPlayerDirY * sin(-fRotation * fDeltaTime);
109
			fPlayerDirY = fOldDirX * sin(-fRotation * fDeltaTime) + fPlayerDirY * cos(-fRotation * fDeltaTime);
110

111
			fPlaneX = fPlaneX * cos(-fRotation * fDeltaTime) - fPlaneY * sin(-fRotation * fDeltaTime);
112
			fPlaneY = fOldPlaneX * sin(-fRotation * fDeltaTime) + fPlaneY * cos(-fRotation * fDeltaTime);
113
		}
114

115
		if (GetKey(VK_LEFT).bHeld)
116
		{
117
			float fOldDirX = fPlayerDirX;
118
			float fOldPlaneX = fPlaneX;
119

120
			fPlayerDirX = fPlayerDirX * cos(fRotation * fDeltaTime) - fPlayerDirY * sin(fRotation * fDeltaTime);
121
			fPlayerDirY = fOldDirX * sin(fRotation * fDeltaTime) + fPlayerDirY * cos(fRotation * fDeltaTime);
122

123
			fPlaneX = fPlaneX * cos(fRotation * fDeltaTime) - fPlaneY * sin(fRotation * fDeltaTime);
124
			fPlaneY = fOldPlaneX * sin(fRotation * fDeltaTime) + fPlaneY * cos(fRotation * fDeltaTime);
125
		}
126

127
		list<pair<pair<int, int>, float>> listStripes;
128

129
		for (int x = 0; x < ScreenWidth(); x++)
130
		{
131
			float fCamera = 2.0f * (float)x / (float)ScreenWidth() - 1.0f;
132

133
			float fRayX = fPlayerDirX + fPlaneX * fCamera;
134
			float fRayY = fPlayerDirY + fPlaneY * fCamera;
135

136
			float fCellDistX = (fRayX == 0.0f) ? INFINITY : abs(1.0f / fRayX);
137
			float fCellDistY = (fRayY == 0.0f) ? INFINITY : abs(1.0f / fRayY);
138

139
			int nMapX = (float)fPlayerX;
140
			int nMapY = (float)fPlayerY;
141

142
			float fDistToNextX, fDistToNextY;
143
			int nStepX, nStepY;
144

145
			if (fRayX < 0.0f)
146
			{
147
				nStepX = -1;
148
				fDistToNextX = (fPlayerX - (float)nMapX) * fCellDistX;
149
			}
150
			else
151
			{
152
				nStepX = 1;
153
				fDistToNextX = ((float)nMapX - fPlayerX + 1.0f) * fCellDistX;
154
			}
155

156
			if (fRayY < 0.0f)
157
			{
158
				nStepY = -1;
159
				fDistToNextY = (fPlayerY - (float)nMapY) * fCellDistY;
160
			}
161
			else
162
			{
163
				nStepY = 1;
164
				fDistToNextY = ((float)nMapY - fPlayerY + 1.0f) * fCellDistY;
165
			}
166

167
			float fDistToWall = 0.0f;
168

169
			int nSide;
170
			bool bHitWall = false;
171

172
			while (!bHitWall)
173
			{
174
				if (fDistToNextX < fDistToNextY)
175
				{
176
					fDistToNextX += fCellDistX;
177
					nMapX += nStepX;
178
					nSide = 0;
179
				}
180
				else
181
				{
182
					fDistToNextY += fCellDistY;
183
					nMapY += nStepY;
184
					nSide = 1;
185
				}
186

187
				if (nMapX < 0 || nMapY < 0 || nMapX >= nMapWidth || nMapY >= nMapHeight)
188
				{
189
					fDistToWall = fDepth;
190
					bHitWall = true;
191
				}
192
				else
193
				{
194
					if (sMap[nMapY * nMapWidth + nMapX] == L'#')
195
						bHitWall = true;
196
				}
197
			}
198

199
			if (fDistToWall != fDepth)
200
			{
201
				if (nSide == 0)
202
					fDistToWall = fDistToNextX - fCellDistX;
203
				else
204
					fDistToWall = fDistToNextY - fCellDistY;
205
			}
206

207
			float fStripeHeight = (float)ScreenHeight() / fDistToWall;
208

209
			int nCeiling = (int)max(-fStripeHeight * 0.5f + (float)ScreenHeight() * 0.5f, 0.0f);
210
			int nFloor = (int)min(fStripeHeight * 0.5f + (float)ScreenHeight() * 0.5f, (float)ScreenHeight() - 1.0f);
211

212
			listStripes.push_back({ { nCeiling, nFloor }, fDistToWall });
213
		}
214

215
		Clear(PIXEL_SOLID, FG_BLACK);
216

217
		int x = 0;
218
		for (const auto& s : listStripes)
219
		{
220
			int nCeiling = s.first.first;
221
			int nFloor = s.first.second;
222

223
			for (int y = 0; y <= nFloor; y++)
224
			{
225
				if (y <= nCeiling)
226
				{
227
					// Ceiling
228
					Draw(x, y, PIXEL_SOLID, FG_BLACK);
229

230
					// Floor
231
					Draw(x, ScreenHeight() - y, PIXEL_SOLID, FG_GREY);
232
				}
233
				else if (s.second < fDepth)
234
				{
235
					short nPixel;
236

237
					if (s.second / fDepth <= 0.25f) nPixel = PIXEL_SOLID;
238
					else if (s.second / fDepth <= 0.5f) nPixel = PIXEL_THREEQUARTERS;
239
					else if (s.second / fDepth <= 0.75f) nPixel = PIXEL_HALF;
240
					else if (s.second / fDepth <= 1.0f) nPixel = PIXEL_QUARTER;
241

242
					// Wall
243
					Draw(x, y, nPixel, FG_WHITE);
244
				}
245
				else
246
				{
247
					// Void
248
					Draw(x, y, PIXEL_SOLID, FG_BLACK);
249
				}
250
			}
251

252
			x++;
253
		}
254

255
		return true;
256
	}
257

258
};
259

260
int main()
261
{
262
	FirstPersonShooter demo;
263
	if (demo.ConstructConsole(256, 240, 4, 4) == rcode::OK)
264
		demo.Run();
265
	return 0;
266
}
267

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.