mirror of
https://github.com/ssloy/tinyraycaster.git
synced 2025-01-16 12:49:38 +01:00
Few bugfixes (e.g. FPS control); SDL knows to load .bmp files, so I remove the dependency to stb_image.h, because it is slow to compile
This commit is contained in:
parent
bb8b2f4ca1
commit
da425dbe9f
73
gui.cpp
73
gui.cpp
@ -9,6 +9,11 @@
|
||||
#include "tinyraycaster.h"
|
||||
|
||||
int main() {
|
||||
if (SDL_Init(SDL_INIT_VIDEO)) {
|
||||
std::cerr << "Failed to initialize SDL: " << SDL_GetError() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
FrameBuffer fb{1024, 512, std::vector<uint32_t>(1024*512, pack_color(255, 255, 255))};
|
||||
GameState gs{ Map(), // game map
|
||||
{3.456, 2.345, 1.523, M_PI/3., 0, 0}, // player
|
||||
@ -17,8 +22,8 @@ int main() {
|
||||
{5.323, 5.365, 1, 0},
|
||||
{14.32, 13.36, 3, 0},
|
||||
{4.123, 10.76, 1, 0} },
|
||||
Texture("../walltext.png"), // textures for the walls
|
||||
Texture("../monsters.png") }; // textures for the monsters
|
||||
Texture("../walltext.bmp", SDL_PIXELFORMAT_ABGR8888), // textures for the walls
|
||||
Texture("../monsters.bmp", SDL_PIXELFORMAT_ABGR8888)}; // textures for the monsters
|
||||
if (!gs.tex_walls.count || !gs.tex_monst.count) {
|
||||
std::cerr << "Failed to load textures" << std::endl;
|
||||
return -1;
|
||||
@ -27,44 +32,47 @@ int main() {
|
||||
SDL_Window *window = nullptr;
|
||||
SDL_Renderer *renderer = nullptr;
|
||||
|
||||
if (SDL_Init(SDL_INIT_VIDEO)) {
|
||||
std::cerr << "Couldn't initialize SDL: " << SDL_GetError() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (SDL_CreateWindowAndRenderer(fb.w, fb.h, SDL_WINDOW_SHOWN | SDL_WINDOW_INPUT_FOCUS, &window, &renderer)) {
|
||||
std::cerr << "Couldn't create window and renderer: " << SDL_GetError() << std::endl;
|
||||
std::cerr << "Failed to create window and renderer: " << SDL_GetError() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_Texture *framebuffer_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, fb.w, fb.h);
|
||||
|
||||
SDL_Event event;
|
||||
if (!framebuffer_texture) {
|
||||
std::cerr << "Failed to create framebuffer texture : " << SDL_GetError() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto t1 = std::chrono::high_resolution_clock::now();
|
||||
while (1) {
|
||||
auto t2 = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double, std::milli> fp_ms = t2 - t1;
|
||||
if (fp_ms.count()<20) { // sleep if less than 20 ms since last re-rendering
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(3));
|
||||
{ // sleep if less than 20 ms since last re-rendering; TODO: decouple rendering and event polling frequencies
|
||||
auto t2 = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double, std::milli> fp_ms = t2 - t1;
|
||||
if (fp_ms.count()<20) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(3));
|
||||
continue;
|
||||
}
|
||||
t1 = t2;
|
||||
}
|
||||
|
||||
if (SDL_PollEvent(&event)) { // update player's state (walking/turning)
|
||||
if (SDL_QUIT==event.type || (SDL_KEYDOWN==event.type && SDLK_ESCAPE==event.key.keysym.sym)) break;
|
||||
if (SDL_KEYUP==event.type) {
|
||||
if ('a'==event.key.keysym.sym || 'd'==event.key.keysym.sym) gs.player.turn = 0;
|
||||
if ('w'==event.key.keysym.sym || 's'==event.key.keysym.sym) gs.player.walk = 0;
|
||||
}
|
||||
if (SDL_KEYDOWN==event.type) {
|
||||
if ('a'==event.key.keysym.sym) gs.player.turn = -1;
|
||||
if ('d'==event.key.keysym.sym) gs.player.turn = 1;
|
||||
if ('w'==event.key.keysym.sym) gs.player.walk = 1;
|
||||
if ('s'==event.key.keysym.sym) gs.player.walk = -1;
|
||||
{ // poll events and update player's state (walk/turn flags); TODO: move this block to a more appropriate place
|
||||
SDL_Event event;
|
||||
if (SDL_PollEvent(&event)) {
|
||||
if (SDL_QUIT==event.type || (SDL_KEYDOWN==event.type && SDLK_ESCAPE==event.key.keysym.sym)) break;
|
||||
if (SDL_KEYUP==event.type) {
|
||||
if ('a'==event.key.keysym.sym || 'd'==event.key.keysym.sym) gs.player.turn = 0;
|
||||
if ('w'==event.key.keysym.sym || 's'==event.key.keysym.sym) gs.player.walk = 0;
|
||||
}
|
||||
if (SDL_KEYDOWN==event.type) {
|
||||
if ('a'==event.key.keysym.sym) gs.player.turn = -1;
|
||||
if ('d'==event.key.keysym.sym) gs.player.turn = 1;
|
||||
if ('w'==event.key.keysym.sym) gs.player.walk = 1;
|
||||
if ('s'==event.key.keysym.sym) gs.player.walk = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{ // update player's position
|
||||
{ // update player's position; TODO: move this block to a more appropriate place
|
||||
gs.player.a += float(gs.player.turn)*.05; // TODO measure elapsed time and modify the speed accordingly
|
||||
float nx = gs.player.x + gs.player.walk*cos(gs.player.a)*.05;
|
||||
float ny = gs.player.y + gs.player.walk*sin(gs.player.a)*.05;
|
||||
@ -79,18 +87,19 @@ int main() {
|
||||
std::sort(gs.monsters.begin(), gs.monsters.end()); // sort it from farthest to closest
|
||||
}
|
||||
|
||||
render(fb, gs);
|
||||
SDL_UpdateTexture(framebuffer_texture, NULL, reinterpret_cast<void *>(fb.img.data()), fb.w*4);
|
||||
render(fb, gs); // render the scene to the frambuffer
|
||||
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_RenderCopy(renderer, framebuffer_texture, NULL, NULL);
|
||||
SDL_RenderPresent(renderer);
|
||||
{ // copy the framebuffer contents to the screen
|
||||
SDL_UpdateTexture(framebuffer_texture, NULL, reinterpret_cast<void *>(fb.img.data()), fb.w*4);
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_RenderCopy(renderer, framebuffer_texture, NULL, NULL);
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_DestroyTexture(framebuffer_texture);
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
|
||||
SDL_Quit();
|
||||
|
||||
return 0;
|
||||
|
BIN
monsters.bmp
Normal file
BIN
monsters.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 64 KiB |
7462
stb_image.h
7462
stb_image.h
File diff suppressed because it is too large
Load Diff
32
textures.cpp
32
textures.cpp
@ -1,34 +1,42 @@
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
#include "SDL.h"
|
||||
|
||||
#include "utils.h"
|
||||
#include "textures.h"
|
||||
|
||||
Texture::Texture(const std::string filename) : img_w(0), img_h(0), count(0), size(0), img() {
|
||||
int nchannels = -1, w, h;
|
||||
unsigned char *pixmap = stbi_load(filename.c_str(), &w, &h, &nchannels, 0);
|
||||
if (!pixmap) {
|
||||
std::cerr << "Error: can not load the textures" << std::endl;
|
||||
Texture::Texture(const std::string filename, const uint32_t format) : img_w(0), img_h(0), count(0), size(0), img() {
|
||||
SDL_Surface *tmp = SDL_LoadBMP(filename.c_str());
|
||||
if (!tmp) {
|
||||
std::cerr << "Error in SDL_LoadBMP: " << SDL_GetError() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (4!=nchannels) {
|
||||
SDL_Surface *surface = SDL_ConvertSurfaceFormat(tmp, format, 0);
|
||||
SDL_FreeSurface(tmp);
|
||||
if (!surface) {
|
||||
std::cerr << "Error in SDL_ConvertSurfaceFormat: " << SDL_GetError() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
int w = surface->w;
|
||||
int h = surface->h;
|
||||
|
||||
if (w*4!=surface->pitch) {
|
||||
std::cerr << "Error: the texture must be a 32 bit image" << std::endl;
|
||||
stbi_image_free(pixmap);
|
||||
SDL_FreeSurface(surface);
|
||||
return;
|
||||
}
|
||||
|
||||
if (w!=h*int(w/h)) {
|
||||
std::cerr << "Error: the texture file must contain N square textures packed horizontally" << std::endl;
|
||||
stbi_image_free(pixmap);
|
||||
SDL_FreeSurface(surface);
|
||||
return;
|
||||
}
|
||||
count = w/h;
|
||||
size = w/count;
|
||||
img_w = w;
|
||||
img_h = h;
|
||||
uint8_t *pixmap = reinterpret_cast<uint8_t *>(surface->pixels);
|
||||
|
||||
img = std::vector<uint32_t>(w*h);
|
||||
for (int j=0; j<h; j++) {
|
||||
@ -40,7 +48,7 @@ Texture::Texture(const std::string filename) : img_w(0), img_h(0), count(0), siz
|
||||
img[i+j*w] = pack_color(r, g, b, a);
|
||||
}
|
||||
}
|
||||
stbi_image_free(pixmap);
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
|
||||
uint32_t Texture::get(const size_t i, const size_t j, const size_t idx) const {
|
||||
|
@ -9,7 +9,7 @@ struct Texture {
|
||||
size_t count, size; // number of textures and size in pixels
|
||||
std::vector<uint32_t> img; // textures storage container
|
||||
|
||||
Texture(const std::string filename);
|
||||
Texture(const std::string filename, const uint32_t format);
|
||||
uint32_t get(const size_t i, const size_t j, const size_t idx) const; // get the pixel (i,j) from the texture idx
|
||||
std::vector<uint32_t> get_scaled_column(const size_t texture_id, const size_t tex_coord, const size_t column_height) const; // retrieve one column (tex_coord) from the texture texture_id and scale it to the destination size
|
||||
};
|
||||
|
BIN
walltext.bmp
Normal file
BIN
walltext.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 96 KiB |
Loading…
x
Reference in New Issue
Block a user