commit
6b181382bd
@ -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/
|
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…
Reference in new issue