Implement basic shading and colors.

CameraRay struct now stores information about tile intersection.
This commit is contained in:
Sheldon Lee 2023-05-01 00:10:01 +01:00
parent 67c41106ff
commit 22cd090f92
7 changed files with 82 additions and 16 deletions

View File

@ -2,7 +2,6 @@
#include <stdio.h> #include <stdio.h>
#include "maths.h" #include "maths.h"
#include "level.h"
#define ROTATION_SPEED PI #define ROTATION_SPEED PI
#define TRANSLATIONAL_SPEED 1.f #define TRANSLATIONAL_SPEED 1.f
@ -59,7 +58,7 @@ static void castRays(Camera* camera)
float rayDirection = camera->direction - camera->fov/2.f + rayDirectionStep/2.f; float rayDirection = camera->direction - camera->fov/2.f + rayDirectionStep/2.f;
for (unsigned int i = 0; i < camera->resolution; i++) { for (unsigned int i = 0; i < camera->resolution; i++) {
camera->rays[i].direction = rayDirection; camera->rays[i].direction = rayDirection;
camera->rays[i].distance = level_rayCastDistance(camera->pos, rayDirection); camera->rays[i].distance = level_rayCast(camera->pos, rayDirection, &camera->rays[i].tileData);
rayDirection += rayDirectionStep; rayDirection += rayDirectionStep;
} }

View File

@ -2,11 +2,13 @@
#define CAMERA_H #define CAMERA_H
#include <SFML/Graphics.hpp> #include <SFML/Graphics.hpp>
#include "level.h"
typedef struct typedef struct
{ {
float direction; float direction;
float distance; float distance;
TileData tileData;
} CameraRay; } CameraRay;
typedef struct typedef struct

View File

@ -39,9 +39,34 @@ void firstperson_update(sf::RenderTarget* renderTarget, Camera* camera)
distanceScale = (distanceScale > 1.f)? 1.f : distanceScale; distanceScale = (distanceScale > 1.f)? 1.f : distanceScale;
float brightness = 255.f*(1.f-distanceScale); float brightness = 255.f*(1.f-distanceScale);
switch (camera->rays[i].tileData.side) {
case NORTH:
break;
case EAST:
case WEST:
brightness *= 0.9;
break;
case SOUTH:
brightness *= 0.8;
break;
}
sf::Color color(brightness, brightness, brightness);
switch (camera->rays[i].tileData.value) {
case 2:
color *= sf::Color::Red;
break;
case 3:
color *= sf::Color::Green;
break;
case 4:
color *= sf::Color::Blue;
break;
};
sf::RectangleShape rectangle(sf::Vector2f(columnWidth, columnHeight)); sf::RectangleShape rectangle(sf::Vector2f(columnWidth, columnHeight));
rectangle.setPosition(sf::Vector2f(i*columnWidth, centeredHeight)); rectangle.setPosition(sf::Vector2f(i*columnWidth, centeredHeight));
rectangle.setFillColor(sf::Color(brightness, brightness, brightness)); rectangle.setFillColor(color);
renderTexture.draw(rectangle); renderTexture.draw(rectangle);
} }

View File

@ -5,17 +5,17 @@
#define WIDTH 10 #define WIDTH 10
#define HEIGHT 10 #define HEIGHT 10
static float castRay(sf::Vector2f point, float direction); static float castRay(sf::Vector2f point, float direction, TileData* tileData);
static void getGridIndex(sf::Vector2f point, int* x, int* y); static void getGridIndex(sf::Vector2f point, int* x, int* y);
static unsigned int level[WIDTH * HEIGHT] = { static unsigned int level[WIDTH * HEIGHT] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1,
1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 2, 0, 1,
1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1,
1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 3, 0, 1,
1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1,
1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 4, 0, 1,
1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@ -36,9 +36,10 @@ void level_end()
return; return;
} }
float level_rayCastDistance(sf::Vector2f point, float direction) float level_rayCast(sf::Vector2f point, float direction, TileData* tileData)
{ {
return castRay(point, direction); if (!tileData) return -1.f;
return castRay(point, direction, tileData);
} }
void level_getDimensions(unsigned int* width, unsigned int* height) void level_getDimensions(unsigned int* width, unsigned int* height)
@ -55,7 +56,7 @@ unsigned int level_getGridValue(unsigned int x, unsigned int y)
return level[y * HEIGHT + x]; return level[y * HEIGHT + x];
} }
static float castRay(sf::Vector2f point, float direction) static float castRay(sf::Vector2f point, float direction, TileData* tileData)
{ {
int indexX, indexY; int indexX, indexY;
getGridIndex(point, &indexX, &indexY); getGridIndex(point, &indexX, &indexY);
@ -125,7 +126,12 @@ static float castRay(sf::Vector2f point, float direction)
if (!(inLevel0 || inLevel1)) break; if (!(inLevel0 || inLevel1)) break;
if (horizontalRayDist < verticalRayDist) { if (horizontalRayDist < verticalRayDist) {
if (level[indexY0 * WIDTH + indexX0]) return horizontalRayDist; unsigned int gridValue = level[indexY0 * WIDTH + indexX0];
if (gridValue) {
tileData->value = gridValue;
tileData->side = goingDown? NORTH : SOUTH;
return horizontalRayDist;
}
horizontalProjectedX += horizontalStepX; horizontalProjectedX += horizontalStepX;
horizontalProjectedY += horizontalStepY; horizontalProjectedY += horizontalStepY;
@ -133,7 +139,12 @@ static float castRay(sf::Vector2f point, float direction)
horizontalRayDist += std::abs(horizontalStepY/horizontalDistCoeff); horizontalRayDist += std::abs(horizontalStepY/horizontalDistCoeff);
} }
else { else {
if (level[indexY1 * WIDTH + indexX1]) return verticalRayDist; unsigned int gridValue = level[indexY1 * WIDTH + indexX1];
if (gridValue) {
tileData->value = gridValue;
tileData->side = goingRight? WEST : EAST;
return verticalRayDist;
}
verticalProjectedX += verticalStepX; verticalProjectedX += verticalStepX;
verticalProjectedY += verticalStepY; verticalProjectedY += verticalStepY;

16
level.h
View File

@ -3,9 +3,23 @@
#include <SFML/Graphics.hpp> #include <SFML/Graphics.hpp>
enum level_tileSide
{
NORTH,
EAST,
SOUTH,
WEST
};
typedef struct
{
unsigned int value;
level_tileSide side;
} TileData;
int level_init(); int level_init();
void level_end(); void level_end();
float level_rayCastDistance(sf::Vector2f point, float direction); float level_rayCast(sf::Vector2f point, float direction, TileData* tileData);
void level_getDimensions(unsigned int* width, unsigned int* height); void level_getDimensions(unsigned int* width, unsigned int* height);
unsigned int level_getGridValue(unsigned int x, unsigned int y); unsigned int level_getGridValue(unsigned int x, unsigned int y);

View File

@ -97,10 +97,25 @@ static void drawGrid(sf::RenderTarget* renderTarget, unsigned int tileSize)
{ {
for (unsigned int x = 0; x < gridWidth; x++) { for (unsigned int x = 0; x < gridWidth; x++) {
for (unsigned int y = 0; y < gridHeight; y++) { for (unsigned int y = 0; y < gridHeight; y++) {
if (!level_getGridValue(x, y)) continue; unsigned int value = level_getGridValue(x, y);
if (!value) continue;
sf::Color color(255, 255, 255);
switch (value) {
case 2:
color = sf::Color::Red;
break;
case 3:
color = sf::Color::Green;
break;
case 4:
color = sf::Color::Blue;
break;
};
sf::RectangleShape rectangle(sf::Vector2f(tileSize, tileSize)); sf::RectangleShape rectangle(sf::Vector2f(tileSize, tileSize));
rectangle.setPosition((float)x * tileSize, (float)y * tileSize); rectangle.setPosition((float)x * tileSize, (float)y * tileSize);
rectangle.setFillColor(color);
renderTarget->draw(rectangle); renderTarget->draw(rectangle);
} }
} }

View File

@ -7,7 +7,7 @@
#include "minimap.h" #include "minimap.h"
#include "firstperson.h" #include "firstperson.h"
#define MINIMAP_SIZE 720 #define MINIMAP_SIZE 480
#define VIEW_SIZE MINIMAP_SIZE*2 #define VIEW_SIZE MINIMAP_SIZE*2
static int handleKeyCode(sf::Keyboard::Key key); static int handleKeyCode(sf::Keyboard::Key key);
@ -21,7 +21,7 @@ static sf::Clock timer;
int view_init() int view_init()
{ {
printf("view_init()\n"); printf("view_init()\n");
if (!camera_init(&camera, sf::Vector2f(10.f/2.f, 10.f/2.f), 0.f, 128, 0.5f*PI)) return 0; if (!camera_init(&camera, sf::Vector2f(10.f/2.f, 10.f/2.f), 0.f, 2<<7, 0.5f*PI)) return 0;
if (!minimap_init(MINIMAP_SIZE)) return 0; if (!minimap_init(MINIMAP_SIZE)) return 0;
if (!firstperson_init(VIEW_SIZE, MINIMAP_SIZE)) return 0; if (!firstperson_init(VIEW_SIZE, MINIMAP_SIZE)) return 0;