Compare commits
No commits in common. "a0b65364325bd33fc54bfb1ae3c7cfd77318ed19" and "b47052aa4d3a48fdb5c17abe423c2fe9da60db69" have entirely different histories.
a0b6536432
...
b47052aa4d
3 changed files with 35 additions and 56 deletions
61
World.cpp
61
World.cpp
|
@ -6,9 +6,8 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
|
||||||
World::World(int w, int h, sf::Color groundColor, sf::Color ceilingColor, std::vector<BlockType> worldMap) :
|
World::World(int w, int h, sf::Color groundColor, sf::Color ceilingColor, std::vector<BlockType> worldMap) : w(w), h(h),
|
||||||
player(0,0,0), w(w), h(h), map(std::move(worldMap)),
|
groundColor(groundColor), ceilingColor(ceilingColor), map(std::move(worldMap)), player(0,0,0)
|
||||||
groundColor(groundColor), ceilingColor(ceilingColor)
|
|
||||||
{
|
{
|
||||||
map.resize(w*h,BlockType::WALL);
|
map.resize(w*h,BlockType::WALL);
|
||||||
}
|
}
|
||||||
|
@ -23,14 +22,9 @@ int World::getH() const
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockType World::getBlock(int x, int y) const
|
|
||||||
{
|
|
||||||
return map[x + w*y];
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockType World::getBlock(float x, float y) const
|
BlockType World::getBlock(float x, float y) const
|
||||||
{
|
{
|
||||||
return map[static_cast<int>(x) + w*static_cast<int>(y)];
|
return(map.at(static_cast<int>(x)+w* static_cast<int>(y)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::setBlock(BlockType block, int x, int y, int width, int height)
|
void World::setBlock(BlockType block, int x, int y, int width, int height)
|
||||||
|
@ -89,6 +83,16 @@ std::ostream& operator<<(std::ostream& ostream, World const& world)
|
||||||
return(ostream);
|
return(ostream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::fillColumn(sf::RenderWindow& window, int column, float scale, sf::Color wallColor) const
|
||||||
|
{
|
||||||
|
float columnHeight = window.getSize().y*scale;
|
||||||
|
sf::RectangleShape pixelColumn(sf::Vector2f(1,columnHeight));
|
||||||
|
pixelColumn.setPosition(column,(window.getSize().y-columnHeight)/2.0);
|
||||||
|
pixelColumn.setFillColor(wallColor);
|
||||||
|
|
||||||
|
window.draw(pixelColumn);
|
||||||
|
}
|
||||||
|
|
||||||
float World::castRay(float originX, float originY, float orientation) const
|
float World::castRay(float originX, float originY, float orientation) const
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -165,8 +169,7 @@ float World::castRay(float originX, float originY, float orientation) const
|
||||||
float hCheckX = originX + hOffsetX;
|
float hCheckX = originX + hOffsetX;
|
||||||
float hCheckY = hOffsetY;
|
float hCheckY = hOffsetY;
|
||||||
/* Bounds + sanity check. */
|
/* Bounds + sanity check. */
|
||||||
while (hCheckX >= 0 && hCheckX <= static_cast<float>(w) &&
|
while (hCheckX >= 0 && hCheckX <= w && hCheckY >= 0 && hCheckY <= h && i < h) {
|
||||||
hCheckY >= 0 && hCheckY <= static_cast<float>(h) && i < h) {
|
|
||||||
if (getBlock(floorf(hCheckX), floorf(hCheckY) + hRound) == BlockType::WALL) {
|
if (getBlock(floorf(hCheckX), floorf(hCheckY) + hRound) == BlockType::WALL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -181,8 +184,7 @@ float World::castRay(float originX, float originY, float orientation) const
|
||||||
float vCheckY = originY + vOffsetY;
|
float vCheckY = originY + vOffsetY;
|
||||||
|
|
||||||
/* Bounds + sanity check. */
|
/* Bounds + sanity check. */
|
||||||
while (vCheckX >= 0 && vCheckX < static_cast<float>(w) &&
|
while (vCheckX >= 0 && vCheckX < w && vCheckY >= 0 && vCheckY < h && i < w) {
|
||||||
vCheckY >= 0 && vCheckY < static_cast<float>(h) && i < w) {
|
|
||||||
if (getBlock(floorf(vCheckX) + vRound, floorf(vCheckY)) == BlockType::WALL) {
|
if (getBlock(floorf(vCheckX) + vRound, floorf(vCheckY)) == BlockType::WALL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -200,36 +202,24 @@ float World::castRay(float originX, float originY, float orientation) const
|
||||||
(originY - hCheckY)*(originY - hCheckY));
|
(originY - hCheckY)*(originY - hCheckY));
|
||||||
float vDist = sqrtf((originX - vCheckX)*(originX - vCheckX) +
|
float vDist = sqrtf((originX - vCheckX)*(originX - vCheckX) +
|
||||||
(originY - vCheckY)*(originY - vCheckY));
|
(originY - vCheckY)*(originY - vCheckY));
|
||||||
|
float finalDist = hDist > vDist ? vDist : hDist;
|
||||||
|
|
||||||
return hDist > vDist ? vDist : hDist;
|
/* 2 Is wall height in meters. */
|
||||||
}
|
return player.focalLength*2/finalDist;
|
||||||
|
|
||||||
void World::fillColumn(sf::RenderWindow& window, unsigned int column,
|
|
||||||
float scale, sf::Color wallColor) const
|
|
||||||
{
|
|
||||||
float columnHeight = static_cast<float>(window.getSize().y)*scale;
|
|
||||||
sf::RectangleShape pixelColumn(sf::Vector2f(1,columnHeight));
|
|
||||||
pixelColumn.setPosition(static_cast<float>(column),
|
|
||||||
(static_cast<float>(window.getSize().y)-columnHeight)/2.0f);
|
|
||||||
pixelColumn.setFillColor(wallColor);
|
|
||||||
|
|
||||||
window.draw(pixelColumn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::render(sf::RenderWindow& window) const
|
void World::render(sf::RenderWindow& window) const
|
||||||
{
|
{
|
||||||
float windowX = static_cast<float>(window.getSize().x);
|
|
||||||
float windowY = static_cast<float>(window.getSize().y);
|
|
||||||
/*
|
/*
|
||||||
* Draw ground and sky planes through half of the screen, as the walls
|
* Draw ground and sky planes through half of the screen, as the walls
|
||||||
* will get drawn over them.
|
* will get drawn over them.
|
||||||
* This doesn't work if we support textures/levels.
|
* This doesn't work if we support textures/levels.
|
||||||
*/
|
*/
|
||||||
sf::RectangleShape ground = sf::RectangleShape(sf::Vector2f(windowX,windowY/2.0f));
|
sf::RectangleShape ground = sf::RectangleShape(sf::Vector2f(window.getSize().x,window.getSize().y/2.0));
|
||||||
ground.setFillColor(groundColor);
|
ground.setFillColor(groundColor);
|
||||||
ground.setPosition(0,windowY/2.0f);
|
ground.setPosition(0,window.getSize().y/2.0);
|
||||||
|
|
||||||
sf::RectangleShape ceiling = sf::RectangleShape(sf::Vector2f(windowX,windowY/2.0f));
|
sf::RectangleShape ceiling = sf::RectangleShape(sf::Vector2f(window.getSize().x,window.getSize().y/2.0));
|
||||||
ceiling.setFillColor(ceilingColor);
|
ceiling.setFillColor(ceilingColor);
|
||||||
|
|
||||||
window.draw(ground);
|
window.draw(ground);
|
||||||
|
@ -239,17 +229,16 @@ void World::render(sf::RenderWindow& window) const
|
||||||
* Throw rays and draw walls over the ceiling and ground.
|
* Throw rays and draw walls over the ceiling and ground.
|
||||||
* Only throws in the plane, which doesn't work for levels/3D.
|
* Only throws in the plane, which doesn't work for levels/3D.
|
||||||
*/
|
*/
|
||||||
for(unsigned int i = 0 ; i < window.getSize().x ; i++)
|
for(int i = 0;i<window.getSize().x;i++)
|
||||||
{
|
{
|
||||||
float deltaAngle = (player.fov/windowX) * (static_cast<float>(i)-windowX/2.0f);
|
float deltaAngle = (player.fov/window.getSize().x) * (i-window.getSize().x/2.0);
|
||||||
float rayAngle = player.orientation + deltaAngle;
|
float rayAngle = player.orientation + deltaAngle;
|
||||||
if (rayAngle < 0) {
|
if (rayAngle < 0) {
|
||||||
rayAngle += 360;
|
rayAngle += 360;
|
||||||
} else if (rayAngle > 360) {
|
} else if (rayAngle > 360) {
|
||||||
rayAngle -= 360;
|
rayAngle -= 360;
|
||||||
}
|
}
|
||||||
float obstacleScale = player.focalLength*2/(castRay(player.x, player.y, rayAngle)*player.sensorSize);
|
float obstacleScale = castRay(player.x, player.y, rayAngle)/player.sensorSize;
|
||||||
/* 2 Is wall height in meters. */
|
|
||||||
fillColumn(window, i, obstacleScale);
|
fillColumn(window, i, obstacleScale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,7 +247,7 @@ void World::step(const float& stepTime) {
|
||||||
player.move(player.currentMoveSpeedX*stepTime,
|
player.move(player.currentMoveSpeedX*stepTime,
|
||||||
player.currentMoveSpeedY*stepTime);
|
player.currentMoveSpeedY*stepTime);
|
||||||
/* Undo last move if the player would end up in a wall. */
|
/* Undo last move if the player would end up in a wall. */
|
||||||
if (getBlock(player.x, player.y) != BlockType::AIR) {
|
if (getBlock((int)player.x, (int)player.y) != BlockType::AIR) {
|
||||||
player.move(-player.currentMoveSpeedX*stepTime,
|
player.move(-player.currentMoveSpeedX*stepTime,
|
||||||
-player.currentMoveSpeedY*stepTime);
|
-player.currentMoveSpeedY*stepTime);
|
||||||
}
|
}
|
||||||
|
|
11
World.h
11
World.h
|
@ -30,9 +30,8 @@ public:
|
||||||
int getW() const;
|
int getW() const;
|
||||||
int getH() const;
|
int getH() const;
|
||||||
|
|
||||||
inline BlockType getBlock(int x, int y) const;
|
inline BlockType getBlock(float x, float y) const;
|
||||||
inline BlockType getBlock(float x, float y) const;
|
void setBlock(BlockType block, int x, int y, int width = 1, int height = 1);
|
||||||
void setBlock(BlockType block, int x, int y, int width = 1, int height = 1);
|
|
||||||
|
|
||||||
void render(sf::RenderWindow&) const;
|
void render(sf::RenderWindow&) const;
|
||||||
|
|
||||||
|
@ -51,14 +50,14 @@ private:
|
||||||
sf::Color groundColor;
|
sf::Color groundColor;
|
||||||
sf::Color ceilingColor;
|
sf::Color ceilingColor;
|
||||||
|
|
||||||
void fillColumn(sf::RenderWindow&, unsigned int column, float scale,
|
void fillColumn(sf::RenderWindow&, int column, float scale,
|
||||||
sf::Color wallColor = sf::Color(84,56,34)) const;
|
sf::Color wallColor = sf::Color(84,56,34)) const;
|
||||||
/**
|
/**
|
||||||
* Cast a ray from a given position and its distance to the origin.
|
* Cast a ray from a given position and return the on-screen scale.
|
||||||
* @param originX Ray X origin, strictly positive
|
* @param originX Ray X origin, strictly positive
|
||||||
* @param originY Ray Y origin, strictly positive
|
* @param originY Ray Y origin, strictly positive
|
||||||
* @param orientation Angle to cast to, in degrees between 0 and 360
|
* @param orientation Angle to cast to, in degrees between 0 and 360
|
||||||
* @return Distance of the hit to the origin.
|
* @return Scale on the screen of the hit wall.
|
||||||
*/
|
*/
|
||||||
float castRay(float originX, float originY, float orientation) const;
|
float castRay(float originX, float originY, float orientation) const;
|
||||||
};
|
};
|
||||||
|
|
19
main.cpp
19
main.cpp
|
@ -14,7 +14,8 @@ int main()
|
||||||
std::cout << world << std::endl;
|
std::cout << world << std::endl;
|
||||||
|
|
||||||
sf::RenderWindow window(sf::VideoMode(800,600),"Da raycasting");
|
sf::RenderWindow window(sf::VideoMode(800,600),"Da raycasting");
|
||||||
sf::RenderWindow window(sf::VideoMode(1000,1000),"Da raycasting");
|
world.render(window);
|
||||||
|
window.display();
|
||||||
|
|
||||||
sf::Event event{};
|
sf::Event event{};
|
||||||
sf::Clock frameTime;
|
sf::Clock frameTime;
|
||||||
|
@ -22,19 +23,9 @@ int main()
|
||||||
{
|
{
|
||||||
while (window.pollEvent(event))
|
while (window.pollEvent(event))
|
||||||
{
|
{
|
||||||
if (event.type == sf::Event::Closed) {
|
if (event.type == sf::Event::Closed)
|
||||||
window.close();
|
window.close();
|
||||||
continue;
|
else if (event.type == sf::Event::KeyPressed) {
|
||||||
}
|
|
||||||
if (event.type == sf::Event::Resized) {
|
|
||||||
// Keep the view area fit to the window.
|
|
||||||
sf::FloatRect newView(0, 0,
|
|
||||||
static_cast<float>(event.size.width),
|
|
||||||
static_cast<float>(event.size.height));
|
|
||||||
window.setView(sf::View(newView));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (event.type == sf::Event::KeyPressed) {
|
|
||||||
switch (event.key.code) {
|
switch (event.key.code) {
|
||||||
case sf::Keyboard::Key::Escape:
|
case sf::Keyboard::Key::Escape:
|
||||||
window.close();
|
window.close();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue