Skip to content

Instantly share code, notes, and snippets.

@EdwardDowling
Last active November 10, 2022 16:08
Show Gist options
  • Save EdwardDowling/01a872cca79e1404bbc2 to your computer and use it in GitHub Desktop.
Save EdwardDowling/01a872cca79e1404bbc2 to your computer and use it in GitHub Desktop.
Maze generation and raycasting.
#include <stdio.h>
#include <ncurses.h>
#include <stdlib.h>
#include <time.h>
#define WIDTH 63
#define HEIGHT 31
typedef struct position{
int x;
int y;
}position;
char room[HEIGHT][WIDTH];
int c;
int keys;
position dir;
position p;
int random(int min,int max){
unsigned int temp = rand()%(max-min)+min;
return temp;
}
void divide(int x,int y,int height,int width, char room[HEIGHT][WIDTH],char side){
int rx ;
int ry;
if(width > 5 && height > 5){
rx = 2*(random(x+2,x+width-2)/2);
ry = 2*(random(y+2,y+height-2)/2);
}else{
rx = x+2;
ry = y+2;
}
for(int j = 0;j<height;j++){
room[j+y][rx] = side;
}
for(int i = 0;i<width;i++){
room[ry][i+x] = side;
}
int gap = rand()%4;
if(gap != 0){
if(rx - x > 5){
room[ry][2*((1+random(x+1,rx-1))/2)-1] = 0;
}else{room[ry][x+1] = 0;}
}
if(gap != 1){
if(x + width - rx > 5){
room[ry][2*((1+random(rx+1,x+width-1))/2)-1] = 0;
}else{room[ry][rx+1] = 0;}
}
if(gap != 2){
if(ry-y> 5){
room[2*((1+random(y+1,ry-1)/2))-1][rx] = 0;
}else{room[y+1][rx] = 0;}
}
if(gap != 3){
if(y + height - ry > 5){
room[2*((1+random(ry+1,y+height-1))/2)-1][rx] = 0;
}else{room[ry+1][rx] = 0;}
}
if(ry-y>3 && rx-x>3)divide(x,y,ry-y,rx-x,room,'#');
if(ry-y>3 && width-(rx-x)>3)divide(rx,y,ry-y,width-(rx-x),room,'#');
if(height-(ry-y)>3 && rx-x>3)divide(x,ry,height-(ry-y),rx-x,room,'#');
if(height-(ry-y)>3 && width-(rx-x)>3)divide(rx,ry,height-(ry-y),width-(rx-x),room,'#');
}
void maze(int height, int width ,char room[height][width]){
for(int i = 0;i<height;i++){
room[i][0] = '#';
room[i][width - 1] = '#';
}
for(int j = 0;j<width;j++){
room[0][j] = '#';
room[height - 1][j] = '#';
}
divide(0,0,height,width,room,'#');
}
int main(){
initscr();
srand(time(NULL));
//fill array
for(int i = 0;i<HEIGHT;i++){
for(int j = 0;j < WIDTH;j++){
room[i][j] = 0 ;
}
}
maze(HEIGHT,WIDTH,room);
p.x = 01;
p.y = 01;
dir.x = 0;
dir.y = 0;
WINDOW *win;
win = newwin(HEIGHT,WIDTH,0,0);
raw();
keypad(stdscr,TRUE);
curs_set(0);
//get input
while(1){
c = getch();
werase(win);
wrefresh(win);
switch(c){
case KEY_UP:
dir.y--;
break;
case KEY_RIGHT:
dir.x++;
break;
case KEY_LEFT:
dir.x--;
break;
case KEY_DOWN:
dir.y++;
break;
}
switch(room[p.y + dir.y][p.x + dir.x]){
case 0:
p.y += dir.y;
p.x += dir.x;
break;
}
dir.y = 0;
dir.x = 0;
if(p.x >= WIDTH - 1)p.x--;
if(p.x < 1)p.x++;
if(p.y >= HEIGHT -1)p.y--;
if(p.y < 1)p.y++;
wmove(win,p.y,p.x);
wprintw(win,"X");
//draw level
for(int j = 0; j< WIDTH;j++){
for(int i = 0;i < HEIGHT; i++){
if(room[i][j]!=0){
wmove(win,i,j);
wprintw(win,&room[i][j]);
}
}
}
wrefresh(win);
if((c)== ' '){
break;
}
}
endwin();
return 0;
}
#include "raylib.h"
#include "testHeader.h"
#include <math.h>
int main()
{
// Initialization
//--------------------------------------------------------------------------------------
screenWidth = W_WIDTH;
screenHeight = W_HEIGHT;
InitWindow(screenWidth, screenHeight, "Test Game");
initGame();
double planeX = 0, planeY = 0.66; //the 2d raycaster version of camera plane
HideCursor();
SetTargetFPS(60);
// Main game loop
while (!WindowShouldClose())
{
updateGame();
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
for(int x = 0; x < W_WIDTH; x++){
//converts screen coodinates to camera plane
double cameraX = ((2 * x) / (double)W_WIDTH) - 1;
//ray direction for this vertical slice
double rayDirX = player.dirX + planeX * cameraX;
double rayDirY = player.dirY + planeY * cameraX;
//map coordinates
player.mapX = (int)player.x;
player.mapY = (int)player.y;
//length of ray from current position to next x or y-side
double sideDistX;
double sideDistY;
//distance travelled when traversing an x or y value
//deltaDistX^2 = (rayDirX * 1/rayDirX)^2 + (rayDirY * 1/rayDirx)^2
double deltaDistX = sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX));
//deltaDisty^2 = (rayDirY * 1/rayDirY)^2 + (rayDirX * 1/rayDirY)^2
double deltaDistY = sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY));
double perpWallDist;
//direction travelled
int stepX;
int stepY;
int hit = 0;
int side;
//direction and initial distance to next x or y value
if (rayDirX < 0)
{
stepX = -1;
sideDistX = (player.x - player.mapX) * deltaDistX;
}
else
{
stepX = 1;
sideDistX = (player.mapX + 1.0 - player.x) * deltaDistX;
}
if (rayDirY < 0)
{
stepY = -1;
sideDistY = (player.y - player.mapY) * deltaDistY;
}
else
{
stepY = 1;
sideDistY = (player.mapY + 1.0 - player.y) * deltaDistY;
}
//check each coordinate for wall
while (hit == 0)
{
//move to next possible wall location
if (sideDistX < sideDistY)
{
sideDistX += deltaDistX;
player.mapX += stepX;
side = 0;
}
else
{
sideDistY += deltaDistY;
player.mapY += stepY;
side = 1;
}
//Check if map coordinate is occupied
if (room[player.mapX][player.mapY]) hit = 1;
}
//Calculate distance to camera plane.
if (side == 0) perpWallDist = (player.mapX - player.x + (1 - stepX) / 2) / rayDirX;
else perpWallDist = (player.mapY - player.y + (1 - stepY) / 2) / rayDirY;
//Calculate height of line to draw on screen
int lineHeight = (int)(W_HEIGHT / perpWallDist);
//calculate start and end of line
int drawStart = (-lineHeight + W_HEIGHT) / 2;
if(drawStart < 0)drawStart = 0;
int drawEnd = (lineHeight + W_HEIGHT) / 2;
if(drawEnd >= W_HEIGHT)drawEnd = W_HEIGHT - 1;
//darken side
Color wallColor;
switch(side)
{
case 0: wallColor = LIGHTGRAY; break;
case 1: wallColor = DARKGRAY; break;
default: wallColor = BLUE; break;
}
//draw the line
DrawLine(x, drawStart,x, drawEnd, wallColor);
}
//draw overlay
DrawText(FormatText("Test game FPS %f",GetFPS()), 10, 10, 20, MAROON);
drawGameMap();
drawReticle(20);
EndDrawing();
//input----------------------------------------------------------------------------------
if(IsKeyDown(KEY_W)){
if(room[(int)(player.x + player.dirX * 5*GetFrameTime())][(int)(player.y)] == false)
player.x += player.dirX * 5*GetFrameTime();
if(room[(int)(player.x)][(int)(player.y + player.dirY * 5*GetFrameTime())] == false)
player.y += player.dirY * 5*GetFrameTime();
}
//move backwards if no wall behind you
if (IsKeyDown(KEY_S))
{
if(room[(int)(player.x - player.dirX * 5*GetFrameTime())][(int)(player.y)] == false)
player.x -= player.dirX * 5*GetFrameTime();
if(room[(int)(player.x)][(int)(player.y - player.dirY * 5*GetFrameTime())] == false)
player.y -= player.dirY * 5*GetFrameTime();
}
//store old values
double oldDirX = player.dirX;
double oldDirY = player.dirY;
double oldPlaneX = planeX;
double oldPlaneY = planeY;
//rotate plane and dir to the left
if(IsKeyDown(KEY_LEFT) && !IsKeyDown(KEY_RIGHT)){
player.dirX = oldDirX * cos(5*GetFrameTime()) - oldDirY * sin(5*GetFrameTime());
player.dirY = oldDirX * sin(5*GetFrameTime()) + oldDirY * cos(5*GetFrameTime());
planeX = oldPlaneX * cos(5*GetFrameTime()) - oldPlaneY * sin(5*GetFrameTime());
planeY = oldPlaneX * sin(5*GetFrameTime()) + oldPlaneY * cos(5*GetFrameTime());
}
//rotate plane and dir to the right
if(IsKeyDown(KEY_RIGHT) && !IsKeyDown(KEY_LEFT)){
player.dirX = oldDirX * cos(-5*GetFrameTime()) - oldDirY * sin(-5*GetFrameTime());
player.dirY = oldDirX * sin(-5*GetFrameTime()) + oldDirY * cos(-5*GetFrameTime());
planeX = oldPlaneX * cos(-5*GetFrameTime()) - oldPlaneY * sin(-5*GetFrameTime());
planeY = oldPlaneX * sin(-5*GetFrameTime()) + oldPlaneY * cos(-5*GetFrameTime());
}
}
CloseWindow();
return 0;
}
void initGame(){
//initialization
//Player starting values----------------------------------------------------------------
player.x =1;
player.y = 1;
player.dirX = -1;
player.dirY = 0;
//obstacles-----------------------------------------------------------------------------
for(int i = 0;i<MAX_BLOCKS;i++){
blocks[i].rectangle.x = 0;
blocks[i].rectangle.y = 0;
blocks[i].rectangle.width = 0;
blocks[i].rectangle.height = 0;
blocks[i].color = DARKGRAY;
}
for(int i = 0;i < HEIGHT;i++){
for(int j = 0; j <WIDTH;j++){
room[i][j] = 0;
}
}
//maze generation---------------------------------------------------------------------------
maze(HEIGHT,WIDTH,room);
//asigning blocks to maze
int blockIndex = 0;
for(int i = 0;i < HEIGHT;i++){
for(int j = 0; j < WIDTH;j++){
if(room[i][j]){
blocks[blockIndex].rectangle.x = j*TILE_WIDTH;
blocks[blockIndex].rectangle.y = i*TILE_HEIGHT;
blocks[blockIndex].rectangle.width = TILE_WIDTH;
blocks[blockIndex].rectangle.height = TILE_HEIGHT;
blocks[blockIndex].color = BLACK;
blockIndex++;
}
}
}
}
void updateGame(){
}
void drawGameMap(){
//draw blocks
for(int i = 0;i < MAX_BLOCKS;i++){
DrawRectangle(blocks[i].rectangle.x + MAP_OFFSET_X ,blocks[i].rectangle.y + MAP_OFFSET_Y,
blocks[i].rectangle.width,blocks[i].rectangle.height,
Fade(blocks[i].color,0.5f));
}
//draw player
DrawRectangle((int)player.y*TILE_HEIGHT + MAP_OFFSET_X,(int)player.x*TILE_WIDTH + MAP_OFFSET_Y,TILE_WIDTH,TILE_HEIGHT,MAROON);
}
//-----------------------------------------------------------------------------------------------
//maze stuff
void divide(int x,int y,int height,int width,char room[HEIGHT][WIDTH]){
int rx;
int ry;
if(width > 5 && height > 5){
rx = 2*(GetRandomValue(x+2,x+width-2)/2);
ry = 2*(GetRandomValue(y+2,y+height-2)/2);
}else{
rx = x+2;
ry = y+2;
}
for(int j = 0; j<height; j++){
room[j+y][rx] = 1;
}
for(int i = 0;i<width;i++){
room[ry][i+x] = 1;
}
int gap = GetRandomValue(0,4);
if(gap != 0){
if(rx - x > 5){
room[ry][2*((1+GetRandomValue(x+1,rx-1))/2)-1] = 0;
}else{room[ry][x+1] = 0;}
}
if(gap != 1){
if(x + width - rx > 5){
room[ry][2*((1+GetRandomValue(rx+1,x+width-1))/2)-1] = 0;
}else{room[ry][rx+1] = 0;}
}
if(gap != 2){
if(ry-y> 5){
room[2*((1+GetRandomValue(y+1,ry-1)/2))-1][rx] = 0;
}else{room[y+1][rx] = 0;}
}
if(gap != 3){
if(y + height - ry > 5){
room[2*((1+GetRandomValue(ry+1,y+height-1))/2)-1][rx] = 0;
}else{room[ry+1][rx] = 0;}
}
if(ry-y>3 && rx-x>3)divide(x,y,ry-y,rx-x,room);
if(ry-y>3 && width-(rx-x)>3)divide(rx,y,ry-y,width-(rx-x),room);
if(height-(ry-y)>3 && rx-x>3)divide(x,ry,height-(ry-y),rx-x,room);
if(height-(ry-y)>3 && width-(rx-x)>3)divide(rx,ry,height-(ry-y),width-(rx-x),room);
}
void maze(int height, int width ,char room[height][width]){
for(int i = 0;i<height;i++){
room[i][0] = 1;
room[i][width - 1] = 1;
}
for(int j = 0;j<width;j++){
room[0][j] = 1;
room[height - 1][j] = 1;
}
divide(0,0,height,width,room);
}
void drawReticle(int size){
DrawLine(W_WIDTH/2,W_HEIGHT/2-size/2,W_WIDTH/2,W_HEIGHT/2+size/2,MAROON);
DrawLine(W_WIDTH/2-size/2,W_HEIGHT/2,W_WIDTH/2 + size/2,W_HEIGHT/2,MAROON);
}
#define MAX_BLOCKS 100000
#define HEIGHT 35
#define WIDTH 55
#define TILE_WIDTH 5
#define TILE_HEIGHT 5
#define W_WIDTH 800
#define W_HEIGHT 480
#define MAP_OFFSET_X 500
#define MAP_OFFSET_Y 20
typedef struct Player{
int mapX, mapY;
double x,y, dirX,dirY;
}Player;
typedef struct Circle {
int radius;
Vector2 centre;
} Circle;
typedef struct Block {
Rectangle rectangle;
Color color;
}Block;
int screenWidth, screenHeight;
Player player;
Block blocks[MAX_BLOCKS];
char room[HEIGHT][WIDTH];
static void updateGame(void);
static void initGame(void);
static void drawGameMap(void);
static void divide(int x,int y,int height,int width,char room[HEIGHT][WIDTH]);
static void maze(int height, int width ,char room[height][width]);
static void drawReticle(int size);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment