racing_game/blocks.cpp

548 lines
12 KiB
C++
Raw Normal View History

2019-05-25 14:24:49 +10:00
#include <GL/glut.h>
#include <vector>
#include <math.h>
#include "PerlinNoise.hpp"
#include "mainloop.h"
#include "archive.h"
#include "textures.h"
#include "blocks.h"
int blocks_tex;
int blocks_size;
int blocks_img_size[2];
double fluid_motion = 0;
double fluid_frequency = 0.99*8;
double fluid_octaves = 1;
std::vector<BlockSettings> block_settings;
const siv::PerlinNoise perlin;
BlockSettings blockGetSettings(int id) {
return block_settings[id];
}
int load_image(const char* dir)
{
int w, h;
loadArchiveImageGL(dir, 'N', w, h);
}
void blocks_tick(int *args)
{
// Make this happen again
mainloopRegAction(blocks_tick, 10, 0);
// Increase the fluid time for perlin noise
fluid_motion += 1e-2;
}
void setup_block_settings()
{
BlockSettings b;
// Set all the textures numbers
int GRASS_TOP = 0;
int GRASS_SIDE = 1;
int ASPHELT_TOP = 2;
int ASPHELT_SIDE = 3;
int DIRT = 4;
int GRAVEL = 5;
int STONE = 6;
int BARRIER = 7;
int PLANT_GRASS = 8;
int WATER = 9;
int SAND = 10;
// Create the queue of textures to load
std::vector<const char*> load_images;
load_images.push_back("textures/blocks/grass_top.rimg");
load_images.push_back("textures/blocks/grass_side.rimg");
load_images.push_back("textures/blocks/asphelt_top.rimg");
load_images.push_back("textures/blocks/asphelt_side.rimg");
load_images.push_back("textures/blocks/dirt.rimg");
load_images.push_back("textures/blocks/gravel.rimg");
load_images.push_back("textures/blocks/stone.rimg");
load_images.push_back("textures/blocks/barrier.rimg");
load_images.push_back("textures/plants/grass.rimg");
load_images.push_back("textures/fluids/water.rimg");
load_images.push_back("textures/blocks/sand.rimg");
// Setup the big image
int big_image_size;
char* big_image;
// Loop over the queue
for(int i=0;i<load_images.size();i++)
{
// Get the image position
ArchivePos pos = archiveGetPos(archive, load_images[i]);
// Get the image
char* tex = new char[pos.size];
archiveRead(archive, pos, tex);
// Is this the first iteration
if(i==0)
{
// Set the big image to the texture
big_image = tex;
big_image_size = pos.size;
}
else
{
// Combine the images
int new_image_size;
char* new_image = combineImages(big_image, big_image_size, tex, pos.size, new_image_size);
// Free the old texture data
free(tex);
free(big_image);
// Set the new image as the big image
big_image = new_image;
big_image_size = new_image_size;
}
}
// Load the combined blocks texture
blocks_tex = loadImageDataGL(big_image, big_image_size, 'N',
blocks_img_size[0], blocks_img_size[1]);
// Set the size of the textures to the width of the image
blocks_size = blocks_img_size[0];
// Air
b.transparent = true;
block_settings.push_back(b);
// Stone
b.tex.t = STONE;
b.tex.b = STONE;
b.tex.n = STONE;
b.tex.e = STONE;
b.tex.s = STONE;
b.tex.w = STONE;
b.transparent = false;
block_settings.push_back(b);
// Grass
b.tex.t = GRASS_TOP;
b.tex.b = DIRT;
b.tex.n = GRASS_SIDE;
b.tex.e = GRASS_SIDE;
b.tex.s = GRASS_SIDE;
b.tex.w = GRASS_SIDE;
b.transparent = false;
block_settings.push_back(b);
// Dirt
b.tex.t = DIRT;
b.tex.b = DIRT;
b.tex.n = DIRT;
b.tex.e = DIRT;
b.tex.s = DIRT;
b.tex.w = DIRT;
b.transparent = false;
block_settings.push_back(b);
// Gravel
b.tex.t = GRAVEL;
b.tex.b = GRAVEL;
b.tex.n = GRAVEL;
b.tex.e = GRAVEL;
b.tex.s = GRAVEL;
b.tex.w = GRAVEL;
b.transparent = false;
block_settings.push_back(b);
// Asphelt
b.tex.t = ASPHELT_TOP;
b.tex.b = DIRT;
b.tex.n = ASPHELT_SIDE;
b.tex.e = ASPHELT_SIDE;
b.tex.s = ASPHELT_SIDE;
b.tex.w = ASPHELT_SIDE;
b.transparent = false;
block_settings.push_back(b);
// Barrier
b.tex.t = BARRIER;
b.tex.b = BARRIER;
b.tex.n = BARRIER;
b.tex.e = BARRIER;
b.tex.s = BARRIER;
b.tex.w = BARRIER;
b.transparent = true;
block_settings.push_back(b);
// Grass Plant
b.tex.t = PLANT_GRASS;
b.tex.b = PLANT_GRASS;
b.transparent = true;
block_settings.push_back(b);
// Water
b.tex.t = WATER;
b.tex.b = WATER;
b.tex.n = WATER;
b.tex.e = WATER;
b.tex.s = WATER;
b.tex.w = WATER;
b.transparent = true;
block_settings.push_back(b);
// Sand
b.tex.t = SAND;
b.tex.b = SAND;
b.tex.n = SAND;
b.tex.e = SAND;
b.tex.s = SAND;
b.tex.w = SAND;
b.transparent = false;
block_settings.push_back(b);
}
Block make_block(uint8_t id, uint8_t type, uint8_t direction)
{
// Set the values
Block b;
b.id = id;
b.type = type;
b.direction = direction;
// Return the block
return b;
}
void blocks_init()
{
// Set the size of the block textures
blocks_size = blocks_img_size[0]/3;
// Initialise the default blocks
setup_block_settings();
// Register some actions
mainloopRegAction(blocks_tick, 10, 0);
}
void tex_coord_block(double x, double y)
{
// Load the position of a texture on a list of textures
glTexCoord2d(x, y*blocks_size/((double)blocks_img_size[1]));
}
void bind_block_texture()
{
// Bind the texture
glBindTexture(GL_TEXTURE_2D, blocks_tex);
}
void unbind_block_texture()
{
// Unbind the texture
glBindTexture(GL_TEXTURE_2D, 0);
}
void render_block_face_here(Block block)
{
// Get the texture settings
BlockTextures bt = block_settings[block.id].tex;
unbind_block_texture();
// Render the face
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
/*tex_coord_block(0, bt.n+0); */glVertex2d(-1,-1);
/*tex_coord_block(1, bt.n+0); */glVertex2d( 1,-1);
/*tex_coord_block(1, bt.n+1); */glVertex2d( 1, 1);
/*tex_coord_block(0, bt.n+1); */glVertex2d(-1, 1);
}
double get_fluid_motion(int x, int z)
{
// Return the blocks perlin noise
return perlin.octaveNoise0_1(
x / fluid_frequency,
z / fluid_frequency,
fluid_motion,
fluid_octaves
)*2;
}
void render_block(Block block, int x, int y, int z, BlockFaceMap fm)
{
// Save the current matrix
glPushMatrix();
// Shift the block face map
for(int i=0;i<block.direction;i++)
{
// Save some of the values of the faces to show
bool n = fm.n;
bool e = fm.e;
bool s = fm.s;
bool w = fm.w;
// Load them moved slightly
fm.n = w;
fm.e = n;
fm.s = e;
fm.w = s;
}
// Set the blocks position
// North
if(block.direction==DIRECTION_N) {
glTranslatef(x,y,z);
}
// East
if(block.direction==DIRECTION_E) {
glTranslatef(x,y,z+1);
}
// South
if(block.direction==DIRECTION_S) {
glTranslatef(x+1,y,z+1);
}
// West
if(block.direction==DIRECTION_W) {
glTranslatef(x+1,y,z);
}
// Rotate the block
glRotatef(block.direction*90,0,1,0);
BlockTextures bt = block_settings[block.id].tex;
// Is this a plant type
if(block.type == BTYPE_PLANT)
{
// Start drawing
glBegin(GL_QUADS);
// Draw in an X shape
tex_coord_block(0, bt.t+1); glVertex3i(1,0,1);
tex_coord_block(0, bt.t+0); glVertex3i(1,1,1);
tex_coord_block(1, bt.t+0); glVertex3i(0,1,0);
tex_coord_block(1, bt.t+1); glVertex3i(0,0,0);
tex_coord_block(0, bt.b+1); glVertex3i(1,0,0);
tex_coord_block(0, bt.b+0); glVertex3i(1,1,0);
tex_coord_block(1, bt.b+0); glVertex3i(0,1,1);
tex_coord_block(1, bt.b+1); glVertex3i(0,0,1);
// Stop drawing
glEnd();
// Pop the old matrix
glPopMatrix();
// Return
return;
}
// Start drawing
glBegin(GL_QUADS);
// Block type
if(block.type == BTYPE_BLOCK)
{
// Top
if(fm.t)
{
tex_coord_block(0, bt.t+0); glVertex3i(0,1,0);
tex_coord_block(1, bt.t+0); glVertex3i(1,1,0);
tex_coord_block(1, bt.t+1); glVertex3i(1,1,1);
tex_coord_block(0, bt.t+1); glVertex3i(0,1,1);
}
// Sides
if(fm.s)
{
tex_coord_block(0, bt.s+0); glVertex3i(1,1,1);
tex_coord_block(1, bt.s+0); glVertex3i(0,1,1);
tex_coord_block(1, bt.s+1); glVertex3i(0,0,1);
tex_coord_block(0, bt.s+1); glVertex3i(1,0,1);
}
if(fm.w)
{
tex_coord_block(1, bt.w+0); glVertex3i(0,1,1);
tex_coord_block(1, bt.w+1); glVertex3i(0,0,1);
tex_coord_block(0, bt.w+1); glVertex3i(0,0,0);
tex_coord_block(0, bt.w+0); glVertex3i(0,1,0);
}
if(fm.e)
{
tex_coord_block(1, bt.e+0); glVertex3i(1,1,1);
tex_coord_block(1, bt.e+1); glVertex3i(1,0,1);
tex_coord_block(0, bt.e+1); glVertex3i(1,0,0);
tex_coord_block(0, bt.e+0); glVertex3i(1,1,0);
}
}
// Ramp type
if(block.type == BTYPE_RAMP)
{
// Top
if(fm.t)
{
tex_coord_block(0, bt.t+0); glVertex3i(0,1,0);
tex_coord_block(1, bt.t+0); glVertex3i(1,1,0);
tex_coord_block(1, bt.t+1); glVertex3i(1,0,1);
tex_coord_block(0, bt.t+1); glVertex3i(0,0,1);
}
}
// Bottom
if(fm.b)
{
tex_coord_block(0, bt.b+0); glVertex3i(0,0,0);
tex_coord_block(1, bt.b+0); glVertex3i(1,0,0);
tex_coord_block(1, bt.b+1); glVertex3i(1,0,1);
tex_coord_block(0, bt.b+1); glVertex3i(0,0,1);
}
// Back
if(fm.n && (block.type == BTYPE_RAMP || block.type == BTYPE_BLOCK))
{
tex_coord_block(0, bt.n+0); glVertex3i(1,1,0);
tex_coord_block(1, bt.n+0); glVertex3i(0,1,0);
tex_coord_block(1, bt.n+1); glVertex3i(0,0,0);
tex_coord_block(0, bt.n+1); glVertex3i(1,0,0);
}
// Fluids
if(block.type == BTYPE_FLUID)
{
// Height varible
double h;
// Frequency
double f = fluid_frequency;
// Octaves
double o = fluid_octaves;
// Is there free space above
if(fm.t)
{
// Calculate the height of the fluid
h = perlin.octaveNoise0_1(x / f, z / f, fluid_motion, o);
}
else
{
// Set the height to maximum
h = 1;
}
// Top
if(fm.t)
{
/*for(int bx=-1;bx<2;bx++)
{
for(int bz=-1;bz<2;bz++)
{
tex_coord_block(0, bt.t+0); glVertex3d(bx+0,1*h,bz+0);
tex_coord_block(1, bt.t+0); glVertex3d(bx+1,1*h,bz+0);
tex_coord_block(1, bt.t+1); glVertex3d(bx+1,1*h,bz+1);
tex_coord_block(0, bt.t+1); glVertex3d(bx+0,1*h,bz+1);
}
}*/
tex_coord_block(0, bt.t+0); glVertex3f(0,1*h,0);
tex_coord_block(1, bt.t+0); glVertex3f(1,1*h,0);
tex_coord_block(1, bt.t+1); glVertex3f(1,1*h,1);
tex_coord_block(0, bt.t+1); glVertex3f(0,1*h,1);
}
// Sides
// N
if(fm.t || fm.n)
{
double nh;
if(fm.w) nh = 0;
else nh = perlin.octaveNoise0_1(x / f, (z-1) / f, fluid_motion, o);
tex_coord_block(0, bt.s+0+nh); glVertex3f(1,1*h,0);
tex_coord_block(1, bt.s+0+nh); glVertex3f(0,1*h,0);
tex_coord_block(1, bt.s+1*h); glVertex3f(0,0+nh,0);
tex_coord_block(0, bt.s+1*h); glVertex3f(1,0+nh,0);
}
// S
if(fm.s)
{
double nh = 0;
tex_coord_block(0, bt.s+0+nh); glVertex3f(1,1*h,1);
tex_coord_block(1, bt.s+0+nh); glVertex3f(0,1*h,1);
tex_coord_block(1, bt.s+1*h); glVertex3f(0,0+nh,1);
tex_coord_block(0, bt.s+1*h); glVertex3f(1,0+nh,1);
}
// W
if(fm.t || fm.w)
{
double nh;
if(fm.w) nh = 0;
else nh = perlin.octaveNoise0_1((x-1) / f, z / f, fluid_motion, o);
tex_coord_block(1, bt.w+0+nh); glVertex3f(0,1*h,1);
tex_coord_block(1, bt.w+1*h); glVertex3f(0,0+nh,1);
tex_coord_block(0, bt.w+1*h); glVertex3f(0,0+nh,0);
tex_coord_block(0, bt.w+0+nh); glVertex3f(0,1*h,0);
}
// E
if(fm.e)
{
double nh = 0;
tex_coord_block(1, bt.e+0+nh); glVertex3f(1,1*h,1);
tex_coord_block(1, bt.e+1*h); glVertex3f(1,0+nh,1);
tex_coord_block(0, bt.e+1*h); glVertex3f(1,0+nh,0);
tex_coord_block(0, bt.e+0+nh); glVertex3f(1,1*h,0);
}
}
// Stop drawing
glEnd();
// Ramp type
if(block.type==BTYPE_RAMP)
{
// Start drawing triangles
glBegin(GL_TRIANGLES);
// Sides
if(fm.w)
{
tex_coord_block(1, bt.e+1); glVertex3i(0,0,1);
tex_coord_block(0, bt.e+1); glVertex3i(0,0,0);
tex_coord_block(0, bt.e+0); glVertex3i(0,1,0);
}
if(fm.e)
{
tex_coord_block(1, bt.e+1); glVertex3i(1,0,1);
tex_coord_block(0, bt.e+1); glVertex3i(1,0,0);
tex_coord_block(0, bt.e+0); glVertex3i(1,1,0);
}
// Stop drawing
glEnd();
}
// Pop the old matrix
glPopMatrix();
}