0
点赞
收藏
分享

微信扫一扫

第一人称射击游戏 C++控制台版(未完成)

一点读书 2022-07-12 阅读 79


视频:​​https://www.bilibili.com/video/BV14z4y1r7wX?p=2&t=188​​

一、在控制台中显示画面

使用cout方式显示时刷新速度较慢,不能满足游戏需求。 游戏的显示借助windows函数。

#include<iostream>
using namespace std;

#include<Windows.h>

//定义屏幕宽度、高度
int nScreenWidth = 120;
int nScreenHeight = 40;

int main()
{
// Create Screen Buffer 创建屏幕缓冲区
wchar_t *screen = new wchar_t[nScreenWidth*nScreenHeight];
HANDLE hConsole = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
SetConsoleActiveScreenBuffer(hConsole);
DWORD dwBytesWritten = 0;

//游戏循环
while (1)
{
// Display Frame 显示
screen[nScreenWidth * nScreenHeight - 1] = '\0';
WriteConsoleOutputCharacter(hConsole, screen, nScreenWidth * nScreenHeight, { 0,0 }, &dwBytesWritten);

}

}

二、

地图

//地图
int nMapWidth = 16; // World Dimensions
int nMapHeight = 16;
//玩家位置X、Y、角度
float fPlayerX = 0.0f; // Player Start Position
float fPlayerY = 0.0f;
float fPlayerA = 0.0f; // Player Start Rotation


// 创建地图 Create Map of world space # = wall block, . = space
wstring map;
map += L"################";
map += L"#..............#";
map += L"#..............#";
map += L"#..............#";
map += L"#..............#";
map += L"#..............#";
map += L"#..............#";
map += L"#..............#";
map += L"#..............#";
map += L"#..............#";
map += L"#..............#";
map += L"#..............#";
map += L"#..............#";
map += L"#..............#";
map += L"#..............#";
map += L"################";

地图与实际的对应

 

第一人称射击游戏 C++控制台版(未完成)_#include

  

(玩家视角有限)           

第一人称射击游戏 C++控制台版(未完成)_sed_02

(玩家视线)

通过视线与墙面的碰撞检测,生成玩家看到的画面。

for (int x = 0; x < nScreenWidth; x++)
{
// For each column, calculate the projected ray angle into world space
float fRayAngle = (fPlayerA - fFOV / 2.0f) + ((float)x / (float)nScreenWidth) * fFOV;//从左半边到右半边
float fDistanceToWall = 0.0f; //
bool bHitWall = false;

float fEyeX = sinf(fRayAngle); //视线方向对应的单位分量 Unit vector for ray in player space
float fEyeY = cosf(fRayAngle);

//增量方式 判断视线撞墙
while (!bHitWall && fDistanceToWall<fDepth)
{
fDistanceToWall += 0.1f;
int nTestX = (int)(fPlayerX + fEyeX * fDistanceToWall);
int nTestY = (int)(fPlayerY + fEyeY * fDistanceToWall);

// 检查视线达到边界 Test if ray is out of bounds
if (nTestX < 0 || nTestX >= nMapWidth || nTestY < 0 || nTestY >= nMapHeight)
{
bHitWall = true; // Just set distance to maximum depth
fDistanceToWall = fDepth;
}
else
{
//检查视线是否遇到墙体
if (map[nTestY*nMapWidth + nTestX] == '#')
{
bHitWall = true;
}
}
}
//计算到天花板和地板的距离
int nCeiling = (float)(nScreenHeight / 2.0) - nScreenHeight/((float)fDistanceToWall);
int nFloor = nScreenHeight - nCeiling;



for (int y = 0; y < nScreenHeight; y++)
{
// Each Row
if (y < nCeiling) //天花板
screen[y*nScreenWidth + x] = ' ';
else if (y > nCeiling && y <= nFloor)
screen[y*nScreenWidth + x] = '#';
else // 地板 Floor
{

screen[y*nScreenWidth + x] = ' ';
}
}
}

     三、左右移动,其中用tp2-tp1来获得一帧花费的时间,使得运动看起来更流畅。

#include<chrono>          //时间相关  
auto tp1 = chrono::system_clock::now();
auto tp2 = chrono::system_clock::now();

//游戏循环
while (1)
{
//计算时间
tp2 = chrono::system_clock::now();
chrono::duration<float>elapsedTime = tp2 - tp1;
tp1 = tp2;
float fElapsedTime = elapsedTime.count(); //一帧的时间

// Handle CCW Rotation
if (GetAsyncKeyState((unsigned short)'A') & 0x8000)
fPlayerA -= (0.1f)*fElapsedTime;

if (GetAsyncKeyState((unsigned short)'D') & 0x8000)
fPlayerA += (0.1f)*fElapsedTime;

                 

做到这里(视频的19:06),当我继续往下做的时候发现图像显示的很奇怪,方块都串行显示,看起来像乱码。

但是参考之前的俄罗斯方块中的控制台设置方法,改变控制台之后还是没有改变。

没有找到解决方法,但猜测是和控制台相关的问题(使用作者代码运行也是乱码​​https://github.com/OneLoneCoder/videos/blob/master/OneLoneCoder_CommandLineFPS.cpp​​)。

 

 

举报

相关推荐

0 条评论