First build that actually works. SDL_main errors before but didn't figure out the cause.

master
Zed A. Shaw 6 days ago
commit 6b181382bd
  1. 29
      .gitignore
  2. 1
      .vimrc_proj
  3. 26
      Makefile
  4. BIN
      charset.png
  5. 34
      main.cpp
  6. 27
      meson.build
  7. 2005
      quickcg.cpp
  8. 334
      quickcg.h
  9. 242
      raycaster_flat.cpp
  10. 7
      scripts/coverage_reset.ps1
  11. 11
      scripts/coverage_reset.sh
  12. 7
      scripts/reset_build.ps1
  13. 11
      scripts/reset_build.sh
  14. 36
      sdlprog.cpp
  15. 9
      tests/base.cpp
  16. 11
      wraps/catch2.wrap
  17. 13
      wraps/fmt.wrap
  18. 11
      wraps/freetype2.wrap
  19. 13
      wraps/libpng.wrap
  20. 11
      wraps/nlohmann_json.wrap
  21. 15
      wraps/sdl2.wrap

29
.gitignore vendored

@ -0,0 +1,29 @@
# ---> Vim
# Swap
[._]*.s[a-v][a-z]
!*.svg # comment out if you don't need vector files
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]
# Session
Session.vim
Sessionx.vim
# Temporary
.netrwhist
*~
# Auto-generated tag files
tags
# Persistent undo
[._]*.un~
subprojects
builddir
ttassets
backup
*.exe
*.dll
*.world
coverage

@ -0,0 +1 @@
set makeprg=meson\ compile\ -C\ .

@ -0,0 +1,26 @@
all: build test
reset:
powershell -executionpolicy bypass .\scripts\reset_build.ps1
%.cpp : %.rl
ragel -o $@ $<
build:
meson compile -j 10 -C builddir
test: build
./builddir/runtests
run: build test
powershell "cp ./builddir/lodecaster.exe ."
./lodecaster
clean:
meson compile --clean -C builddir
debug_test: build
gdb --nx -x .gdbinit --ex run --args builddir/runtests.exe
cover:
gcovr --html coverage/index.html --gcov-ignore-errors=no_working_dir_found --exclude "scratchpad.*" --exclude "subprojects.*" --html-nested coverage/

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

@ -0,0 +1,34 @@
/*
Copyright (c) 2004, Lode Vandevenne
All rights reserved.
*/
#include <cmath>
#include <string>
#include <vector>
#include <iostream>
#include "quickcg.h"
using namespace QuickCG;
using namespace std;
//place the example code below here:
int main(int argc, char *argv[])
{
screen(256, 256, 0, "Small Test Script");
for (int x = 0; x < w; x++)
for (int y = 0; y < h; y++)
{
pset(x, y, ColorRGBA(x, y, 128, 255));
}
print("Hello, world!", 8, 8);
std::string test;
test.resize(20);
redraw();
sleep();
return 0;
}

@ -0,0 +1,27 @@
project('lodecaster', 'cpp',
default_options: ['cpp_std=c++20'])
catch2 = dependency('catch2-with-main')
fmt = dependency('fmt')
json = dependency('nlohmann_json')
sdl2 = dependency('sdl2')
sdl2_main = dependency('sdl2main')
dependencies = [
sdl2, sdl2_main,
fmt, json
]
executable('runtests', [
'quickcg.cpp',
'main.cpp',
],
win_subsystem: 'windows',
dependencies: dependencies)
executable('lodecaster', [
'quickcg.cpp',
'raycaster_flat.cpp',
],
win_subsystem: 'windows',
dependencies: dependencies)

File diff suppressed because it is too large Load Diff

@ -0,0 +1,334 @@
/*
QuickCG SDL2 20190709
Copyright (c) 2004-2007, Lode Vandevenne
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
QuickCG is an SDL 2.0 codebase that wraps some of the SDL 2.0 functionality.
It's used by Lode's Computer Graphics Tutorial to work with simple function calls
to demonstrate graphical programs. It may or may not be of industrial strength
for games, though I've actually used it for some.
QuickCG can handle some things that standard C++ does not but that are useful, such as:
-drawing graphics
-a bitmap font
-simplified saving and loading of files
-reading keyboard and mouse input
-playing sound
-color models
-loading images
Contact info:
My email address is (puzzle the account and domain together with an @ symbol):
Domain: gmail dot com.
Account: lode dot vandevenne.
*/
#ifndef _quickcg_h_included
#define _quickcg_h_included
#include <SDL.h>
#include <string>
#include <sstream>
#include <iomanip>
#include <vector>
#include <algorithm> //std::min and std::max
namespace QuickCG
{
////////////////////////////////////////////////////////////////////////////////
//useful templates//////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//don't know why, but the standard C++ abs sometimes gives cryptic errors? if so use this :D
template<typename T>
const T template_abs(const T &a)
{
return (a < 0) ? -a : a;
}
//usage: std::string str = valtostr(25454.91654654f);
template<typename T>
std::string valtostr(const T& val)
{
std::ostringstream sstream;
sstream << val;
return sstream.str();
}
//usage: double val = strtoval<double>("465498.654");
template<typename T>
T strtoval(const std::string& s)
{
std::istringstream sstream(s);
T val;
sstream >> val;
return val;
}
//length is decimal precision of the floating point number
template<typename T>
std::string valtostr(const T& val, int length, bool fixed = true)
{
std::ostringstream sstream;
if(fixed) sstream << std::fixed;
sstream << std::setprecision(length) << val;
return sstream.str();
}
////////////////////////////////////////////////////////////////////////////////
//COLOR STRUCTS/////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
struct ColorRGBA8bit;
//a color with 4 components: r, g, b and a
struct ColorRGBA
{
int r;
int g;
int b;
int a;
ColorRGBA(Uint8 r, Uint8 g, Uint8 b, Uint8 a);
ColorRGBA(const ColorRGBA8bit& color);
ColorRGBA();
};
ColorRGBA operator+(const ColorRGBA& color, const ColorRGBA& color2);
ColorRGBA operator-(const ColorRGBA& color, const ColorRGBA& color2);
ColorRGBA operator*(const ColorRGBA& color, int a);
ColorRGBA operator*(int a, const ColorRGBA& color);
ColorRGBA operator/(const ColorRGBA& color, int a);
ColorRGBA overlay(const ColorRGBA& color, const ColorRGBA& color2);
bool operator==(const ColorRGBA& color, const ColorRGBA& color2);
bool operator!=(const ColorRGBA& color, const ColorRGBA& color2);
static const ColorRGBA RGB_Black ( 0, 0, 0, 255);
static const ColorRGBA RGB_Red (255, 0, 0, 255);
static const ColorRGBA RGB_Green ( 0, 255, 0, 255);
static const ColorRGBA RGB_Blue ( 0, 0, 255, 255);
static const ColorRGBA RGB_Cyan ( 0, 255, 255, 255);
static const ColorRGBA RGB_Magenta (255, 0, 255, 255);
static const ColorRGBA RGB_Yellow (255, 255, 0, 255);
static const ColorRGBA RGB_White (255, 255, 255, 255);
static const ColorRGBA RGB_Gray (128, 128, 128, 255);
static const ColorRGBA RGB_Grey (192, 192, 192, 255);
static const ColorRGBA RGB_Maroon (128, 0, 0, 255);
static const ColorRGBA RGB_Darkgreen( 0, 128, 0, 255);
static const ColorRGBA RGB_Navy ( 0, 0, 128, 255);
static const ColorRGBA RGB_Teal ( 0, 128, 128, 255);
static const ColorRGBA RGB_Purple (128, 0, 128, 255);
static const ColorRGBA RGB_Olive (128, 128, 0, 255);
//a color with 4 components: r, g, b and a
struct ColorRGBA8bit
{
Uint8 r;
Uint8 g;
Uint8 b;
Uint8 a;
ColorRGBA8bit(Uint8 r, Uint8 g, Uint8 b, Uint8 a);
ColorRGBA8bit(const ColorRGBA& color);
ColorRGBA8bit();
};
//a color with 3 components: h, s and l
struct ColorHSL
{
int h;
int s;
int l;
int a;
ColorHSL(Uint8 h, Uint8 s, Uint8 l, Uint8 a);
ColorHSL();
};
//a color with 3 components: h, s and v
struct ColorHSV
{
int h;
int s;
int v;
int a;
ColorHSV(Uint8 h, Uint8 s, Uint8 v, Uint8 a);
ColorHSV();
};
////////////////////////////////////////////////////////////////////////////////
//GLOBAL VARIABLES//////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
extern int w;
extern int h;
////////////////////////////////////////////////////////////////////////////////
//KEYBOARD FUNCTIONS////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
bool keyDown(int key); //this checks if the key is held down, returns true all the time until the key is up
bool keyPressed(int key); //this checks if the key is *just* pressed, returns true only once until the key is up again
////////////////////////////////////////////////////////////////////////////////
//BASIC SCREEN FUNCTIONS////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void screen(int width = 640, int height = 400, bool fullscreen = 0, const std::string& text = " ");
void lock();
void unlock();
void redraw();
void cls(const ColorRGBA& color = RGB_Black);
void pset(int x, int y, const ColorRGBA& color);
ColorRGBA pget(int x, int y);
void drawBuffer(Uint32* buffer);
bool onScreen(int x, int y);
////////////////////////////////////////////////////////////////////////////////
//NON GRAPHICAL FUNCTIONS///////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void sleep();
void sleep(double seconds);
void waitFrame(double oldTime, double frameDuration); //in seconds
bool done(bool quit_if_esc = true, bool delay = true);
void end();
void readKeys();
void getMouseState(int& mouseX, int& mouseY);
void getMouseState(int& mouseX, int& mouseY, bool& LMB, bool& RMB);
unsigned long getTicks(); //ticks in milliseconds
inline double getTime() { return getTicks() / 1000.0; } //time in seconds
////////////////////////////////////////////////////////////////////////////////
//2D SHAPES/////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
bool horLine(int y, int x1, int x2, const ColorRGBA& color);
bool verLine(int x, int y1, int y2, const ColorRGBA& color);
bool drawLine(int x1, int y1, int x2, int y2, const ColorRGBA& color);
bool drawCircle(int xc, int yc, int radius, const ColorRGBA& color);
bool drawDisk(int xc, int yc, int radius, const ColorRGBA& color);
bool drawRect(int x1, int y1, int x2, int y2, const ColorRGBA& color);
bool clipLine(int x1,int y1,int x2, int y2, int & x3, int & y3, int & x4, int & y4);
////////////////////////////////////////////////////////////////////////////////
//COLOR CONVERSIONS/////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
ColorHSL RGBtoHSL(const ColorRGBA& ColorRGBA);
ColorRGBA HSLtoRGB(const ColorHSL& colorHSL);
ColorHSV RGBtoHSV(const ColorRGBA& ColorRGBA);
ColorRGBA HSVtoRGB(const ColorHSV& colorHSV);
Uint32 RGBtoINT(const ColorRGBA& ColorRGBA);
ColorRGBA INTtoRGB(Uint32 colorINT);
////////////////////////////////////////////////////////////////////////////////
//FILE FUNCTIONS////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void loadFile(std::vector<unsigned char>& buffer, const std::string& filename);
void saveFile(const std::vector<unsigned char>& buffer, const std::string& filename);
////////////////////////////////////////////////////////////////////////////////
//IMAGE FUNCTIONS///////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
int loadImage(std::vector<ColorRGBA>& out, unsigned long& w, unsigned long& h, const std::string& filename);
int loadImage(std::vector<Uint32>& out, unsigned long& w, unsigned long& h, const std::string& filename);
int decodePNG(std::vector<unsigned char>& out_image, unsigned long& image_width, unsigned long& image_height, const unsigned char* in_png, size_t in_size, bool convert_to_rgba32 = true);
int decodePNG(std::vector<unsigned char>& out_image_32bit, unsigned long& image_width, unsigned long& image_height, const std::vector<unsigned char>& in_png);
////////////////////////////////////////////////////////////////////////////////
//TEXT FUNCTIONS////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
extern bool font[256][8][8];
void drawLetter(unsigned char n, int x, int y, const ColorRGBA& color = RGB_White, bool bg = 0, const ColorRGBA& color2 = RGB_Black);
int printString(const std::string& text, int x = 0, int y = 0, const ColorRGBA& color = RGB_White, bool bg = 0, const ColorRGBA& color2 = RGB_Black, int forceLength = 0);
//print something (string, int, float, ...)
template<typename T>
int print(const T& val, int x = 0, int y = 0, const ColorRGBA& color = RGB_White, bool bg = 0, const ColorRGBA& color2 = RGB_Black, int forceLength = 0)
{
std::string text = valtostr(val);
return printString(text, x, y, color, bg, color2, forceLength);
}
//print some floating point number, this one allows printing floating point numbers with limited length
template<typename T>
int fprint(const T& val, int length, int x = 0, int y = 0, const ColorRGBA& color = RGB_White, bool bg = 0, const ColorRGBA& color2 = RGB_Black, int forceLength = 0)
{
std::string text = valtostr(val, length, true);
return printString(text, x, y, color, bg, color2, forceLength);
}
////////////////////////////////////////////////////////////////////////////////
//TEXT INPUT FUNCTIONS//////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Uint8 getInputCharacter();
void getInputString(std::string& text, const std::string& message = "", bool clear = false, int x = 0, int y = 0, const ColorRGBA& color = RGB_White, bool bg = 0, const ColorRGBA& color2 = RGB_Black);
template<typename T>
T getInput(const std::string& message = "", bool clear = false, int x = 0, int y = 0, const ColorRGBA& color = RGB_White, bool bg = 0, const ColorRGBA& color2 = RGB_Black)
{
std::string text;
getInputString(text, message, clear, x, y, color, bg, color2);
return strtoval<T>(text);
}
////////////////////////////////////////////////////////////////////////////////
//SOUNDCARD FUNCTIONS///////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
int audioOpen(int samplerate, int framesize); //always 16-bit mono sound for now; returns 0 if no error happened
void audioClose();
int audioReOpen(); //closes and opens again with same parameters
/*
push samples to the soundcard, making sure not to cause shortage or overflow
pos and end are the range in the samples vector that you want to push to the audio card
*/
void audioPushSamples(const std::vector<double>& samples, size_t pos, size_t end);
size_t audioSamplesShortage(); //returns value > 0 if the soundcard is consuming more samples than you're producing
size_t audioSamplesOverflow(); //returns value > 0 if you're producing more samples than the soundard is consuming - so take it easy a bit
void audioSetBufferSamplesRange(size_t min_samples, size_t max_samples); //set shortage and overflow values. E.g. 4096 and 8192.
/*
This plays the sound starting at this time, until it's done
The difference with audioPushSamples is:
audioPlay allows playing multiple sounds at the same time: it doesn't push at the end,
but elementwise-adds or pushes back samples if needed.
The duration depends on samplerate, make sure the samples in the vector have the correct samplerate.
*/
void audioPlay(const std::vector<double>& samples);
void audioSetMode(int mode); //0: silent, 1: full (no volume calculations ==> faster), 2: volume-controlled (= default value)
void audioSetVolume(double volume); //multiplier used if mode is 2 (volume-controlled). Default value is 1.0.
} //end of namespace QuickCG
#endif

@ -0,0 +1,242 @@
/*
Copyright (c) 2004-2021, Lode Vandevenne
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cmath>
#include <string>
#include <vector>
#include <iostream>
#include "quickcg.h"
using namespace QuickCG;
/*
g++ *.cpp -lSDL -O3 -W -Wall -ansi -pedantic
g++ *.cpp -lSDL
*/
//place the example code below here:
#define screenWidth 640
#define screenHeight 480
#define mapWidth 24
#define mapHeight 24
int worldMap[mapWidth][mapHeight]=
{
{1,1,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1},
{1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1},
{1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,2,2,0,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,4,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,4,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,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,1,1}
};
int main(int /*argc*/, char */*argv*/[])
{
double posX = 22, posY = 12; //x and y start position
double dirX = -1, dirY = 0; //initial direction vector
double planeX = 0, planeY = 0.66; //the 2d raycaster version of camera plane
double time = 0; //time of current frame
double oldTime = 0; //time of previous frame
screen(screenWidth, screenHeight, 0, "Raycaster");
while(!done())
{
for(int x = 0; x < w; x++)
{
//calculate ray position and direction
double cameraX = 2 * x / (double)w - 1; //x-coordinate in camera space
double rayDirX = dirX + planeX * cameraX;
double rayDirY = dirY + planeY * cameraX;
//which box of the map we're in
int mapX = int(posX);
int mapY = int(posY);
//length of ray from current position to next x or y-side
double sideDistX;
double sideDistY;
//length of ray from one x or y-side to next x or y-side
//these are derived as:
//deltaDistX = sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
//deltaDistY = sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
//which can be simplified to abs(|rayDir| / rayDirX) and abs(|rayDir| / rayDirY)
//where |rayDir| is the length of the vector (rayDirX, rayDirY). Its length,
//unlike (dirX, dirY) is not 1, however this does not matter, only the
//ratio between deltaDistX and deltaDistY matters, due to the way the DDA
//stepping further below works. So the values can be computed as below.
// Division through zero is prevented, even though technically that's not
// needed in C++ with IEEE 754 floating point values.
double deltaDistX = (rayDirX == 0) ? 1e30 : std::abs(1 / rayDirX);
double deltaDistY = (rayDirY == 0) ? 1e30 : std::abs(1 / rayDirY);
double perpWallDist;
//what direction to step in x or y-direction (either +1 or -1)
int stepX;
int stepY;
int hit = 0; //was there a wall hit?
int side; //was a NS or a EW wall hit?
//calculate step and initial sideDist
if(rayDirX < 0)
{
stepX = -1;
sideDistX = (posX - mapX) * deltaDistX;
}
else
{
stepX = 1;
sideDistX = (mapX + 1.0 - posX) * deltaDistX;
}
if(rayDirY < 0)
{
stepY = -1;
sideDistY = (posY - mapY) * deltaDistY;
}
else
{
stepY = 1;
sideDistY = (mapY + 1.0 - posY) * deltaDistY;
}
//perform DDA
while(hit == 0)
{
//jump to next map square, either in x-direction, or in y-direction
if(sideDistX < sideDistY)
{
sideDistX += deltaDistX;
mapX += stepX;
side = 0;
}
else
{
sideDistY += deltaDistY;
mapY += stepY;
side = 1;
}
//Check if ray has hit a wall
if(worldMap[mapX][mapY] > 0) hit = 1;
}
//Calculate distance projected on camera direction. This is the shortest distance from the point where the wall is
//hit to the camera plane. Euclidean to center camera point would give fisheye effect!
//This can be computed as (mapX - posX + (1 - stepX) / 2) / rayDirX for side == 0, or same formula with Y
//for size == 1, but can be simplified to the code below thanks to how sideDist and deltaDist are computed:
//because they were left scaled to |rayDir|. sideDist is the entire length of the ray above after the multiple
//steps, but we subtract deltaDist once because one step more into the wall was taken above.
if(side == 0) perpWallDist = (sideDistX - deltaDistX);
else perpWallDist = (sideDistY - deltaDistY);
//Calculate height of line to draw on screen
int lineHeight = (int)(h / perpWallDist);
//calculate lowest and highest pixel to fill in current stripe
int drawStart = -lineHeight / 2 + h / 2;
if(drawStart < 0) drawStart = 0;
int drawEnd = lineHeight / 2 + h / 2;
if(drawEnd >= h) drawEnd = h - 1;
//choose wall color
ColorRGB color;
switch(worldMap[mapX][mapY])
{
case 1: color = RGB_Red; break; //red
case 2: color = RGB_Green; break; //green
case 3: color = RGB_Blue; break; //blue
case 4: color = RGB_White; break; //white
default: color = RGB_Yellow; break; //yellow
}
//give x and y sides different brightness
if(side == 1) {color = color / 2;}
//draw the pixels of the stripe as a vertical line
verLine(x, drawStart, drawEnd, color);
}
//timing for input and FPS counter
oldTime = time;
time = getTicks();
double frameTime = (time - oldTime) / 1000.0; //frameTime is the time this frame has taken, in seconds
print(1.0 / frameTime); //FPS counter
redraw();
cls();
//speed modifiers
double moveSpeed = frameTime * 5.0; //the constant value is in squares/second
double rotSpeed = frameTime * 3.0; //the constant value is in radians/second
readKeys();
//move forward if no wall in front of you
if(keyDown(SDLK_UP))
{
if(worldMap[int(posX + dirX * moveSpeed)][int(posY)] == false) posX += dirX * moveSpeed;
if(worldMap[int(posX)][int(posY + dirY * moveSpeed)] == false) posY += dirY * moveSpeed;
}
//move backwards if no wall behind you
if(keyDown(SDLK_DOWN))
{
if(worldMap[int(posX - dirX * moveSpeed)][int(posY)] == false) posX -= dirX * moveSpeed;
if(worldMap[int(posX)][int(posY - dirY * moveSpeed)] == false) posY -= dirY * moveSpeed;
}
//rotate to the right
if(keyDown(SDLK_RIGHT))
{
//both camera direction and camera plane must be rotated
double oldDirX = dirX;
dirX = dirX * cos(-rotSpeed) - dirY * sin(-rotSpeed);
dirY = oldDirX * sin(-rotSpeed) + dirY * cos(-rotSpeed);
double oldPlaneX = planeX;
planeX = planeX * cos(-rotSpeed) - planeY * sin(-rotSpeed);
planeY = oldPlaneX * sin(-rotSpeed) + planeY * cos(-rotSpeed);
}
//rotate to the left
if(keyDown(SDLK_LEFT))
{
//both camera direction and camera plane must be rotated
double oldDirX = dirX;
dirX = dirX * cos(rotSpeed) - dirY * sin(rotSpeed);
dirY = oldDirX * sin(rotSpeed) + dirY * cos(rotSpeed);
double oldPlaneX = planeX;
planeX = planeX * cos(rotSpeed) - planeY * sin(rotSpeed);
planeY = oldPlaneX * sin(rotSpeed) + planeY * cos(rotSpeed);
}
}
}

@ -0,0 +1,7 @@
mv .\subprojects\packagecache .
rm -recurse -force .\subprojects\,.\builddir\
mkdir subprojects
mv .\packagecache .\subprojects\
mkdir builddir
cp wraps\*.wrap subprojects\
meson setup --default-library=static --prefer-static -Db_coverage=true builddir

@ -0,0 +1,11 @@
#!/usr/bin/env bash
set -e
mv -f ./subprojects/packagecache .
rm -rf subprojects builddir
mkdir subprojects
mv packagecache ./subprojects/
mkdir builddir
cp wraps/*.wrap subprojects/
# on OSX you can't do this with static
meson setup -Db_coverage=true builddir

@ -0,0 +1,7 @@
mv .\subprojects\packagecache .
rm -recurse -force .\subprojects\,.\builddir\
mkdir subprojects
mv .\packagecache .\subprojects\
mkdir builddir
cp wraps\*.wrap subprojects\
meson setup --default-library=static --prefer-static builddir

@ -0,0 +1,11 @@
#!/usr/bin/env bash
set -e
mv -f ./subprojects/packagecache .
rm -rf subprojects builddir
mkdir subprojects
mv packagecache ./subprojects/
mkdir builddir
cp wraps/*.wrap subprojects/
# on OSX you can't do this with static
meson setup builddir

@ -0,0 +1,36 @@
#include "SDL.h"
int main(int argc, char *argv[])
{
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Surface *surface;
SDL_Event event;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError());
return 3;
}
if (SDL_CreateWindowAndRenderer(320, 240, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window and renderer: %s", SDL_GetError());
return 3;
}
while (1) {
SDL_PollEvent(&event);
if (event.type == SDL_QUIT) {
break;
}
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x00);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}

@ -0,0 +1,9 @@
#include <catch2/catch_test_macros.hpp>
#include <fmt/core.h>
#include <string>
using namespace fmt;
TEST_CASE("base test", "[base]") {
REQUIRE(1 == 1);
}

@ -0,0 +1,11 @@
[wrap-file]
directory = Catch2-3.7.1
source_url = https://github.com/catchorg/Catch2/archive/v3.7.1.tar.gz
source_filename = Catch2-3.7.1.tar.gz
source_hash = c991b247a1a0d7bb9c39aa35faf0fe9e19764213f28ffba3109388e62ee0269c
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/catch2_3.7.1-1/Catch2-3.7.1.tar.gz
wrapdb_version = 3.7.1-1
[provide]
catch2 = catch2_dep
catch2-with-main = catch2_with_main_dep

@ -0,0 +1,13 @@
[wrap-file]
directory = fmt-11.0.2
source_url = https://github.com/fmtlib/fmt/archive/11.0.2.tar.gz
source_filename = fmt-11.0.2.tar.gz
source_hash = 6cb1e6d37bdcb756dbbe59be438790db409cdb4868c66e888d5df9f13f7c027f
patch_filename = fmt_11.0.2-1_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/fmt_11.0.2-1/get_patch
patch_hash = 90c9e3b8e8f29713d40ca949f6f93ad115d78d7fb921064112bc6179e6427c5e
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/fmt_11.0.2-1/fmt-11.0.2.tar.gz
wrapdb_version = 11.0.2-1
[provide]
fmt = fmt_dep

@ -0,0 +1,11 @@
[wrap-file]
directory = freetype-2.13.3
source_url = https://download.savannah.gnu.org/releases/freetype/freetype-2.13.3.tar.xz
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/freetype2_2.13.3-1/freetype-2.13.3.tar.xz
source_filename = freetype-2.13.3.tar.xz
source_hash = 0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289
wrapdb_version = 2.13.3-1
[provide]
freetype2 = freetype_dep
freetype = freetype_dep

@ -0,0 +1,13 @@
[wrap-file]
directory = libpng-1.6.44
source_url = https://github.com/glennrp/libpng/archive/v1.6.44.tar.gz
source_filename = libpng-1.6.44.tar.gz
source_hash = 0ef5b633d0c65f780c4fced27ff832998e71478c13b45dfb6e94f23a82f64f7c
patch_filename = libpng_1.6.44-1_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/libpng_1.6.44-1/get_patch
patch_hash = 394b07614c45fbd1beac8b660386216a490fe12f841a1a445799b676c9c892fb
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/libpng_1.6.44-1/libpng-1.6.44.tar.gz
wrapdb_version = 1.6.44-1
[provide]
libpng = libpng_dep

@ -0,0 +1,11 @@
[wrap-file]
directory = nlohmann_json-3.11.3
lead_directory_missing = true
source_url = https://github.com/nlohmann/json/releases/download/v3.11.3/include.zip
source_filename = nlohmann_json-3.11.3.zip
source_hash = a22461d13119ac5c78f205d3df1db13403e58ce1bb1794edc9313677313f4a9d
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/nlohmann_json_3.11.3-1/nlohmann_json-3.11.3.zip
wrapdb_version = 3.11.3-1
[provide]
nlohmann_json = nlohmann_json_dep

@ -0,0 +1,15 @@
[wrap-file]
directory = SDL2-2.30.6
source_url = https://github.com/libsdl-org/SDL/releases/download/release-2.30.6/SDL2-2.30.6.tar.gz
source_filename = SDL2-2.30.6.tar.gz
source_hash = c6ef64ca18a19d13df6eb22df9aff19fb0db65610a74cc81dae33a82235cacd4
patch_filename = sdl2_2.30.6-2_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/sdl2_2.30.6-2/get_patch
patch_hash = aa9f6a4947b07510c2ea84fb457e965bebe5a5deeb9f5059fbcf10dfe6b76d1f
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/sdl2_2.30.6-2/SDL2-2.30.6.tar.gz
wrapdb_version = 2.30.6-2
[provide]
sdl2 = sdl2_dep
sdl2main = sdl2main_dep
sdl2_test = sdl2_test_dep
Loading…
Cancel
Save