Browse Source

Begin work on procgen and map exploration tool

master
Josh Gordon 3 years ago
parent
commit
0e5d13682d
  1. BIN
      app/action/Cave.png
  2. 55
      app/action/Character.cpp
  3. 38
      app/action/Character.h
  4. 15
      app/action/Level.h
  5. 7
      app/action/Makefile
  6. 61
      app/action/Texture.cpp
  7. 30
      app/action/Texture.h
  8. BIN
      app/action/action
  9. 104
      app/action/main.cpp
  10. BIN
      app/action/sp.png
  11. 23
      app/dungeon.py
  12. BIN
      app/procgen/Cave.png
  13. 0
      app/procgen/__init__.py
  14. 63
      app/procgen/cave.py
  15. BIN
      app/voronoi.png

BIN
app/action/Cave.png

After

Width: 1920  |  Height: 1080  |  Size: 114 KiB

55
app/action/Character.cpp

@ -0,0 +1,55 @@
#include "Character.h"
void Character::handleEvent(SDL_Event& e) {
if(e.type == SDL_KEYDOWN && e.key.repeat == 0) {
switch(e.key.keysym.sym) {
case SDLK_UP: vy_ -= CHAR_SPEED; break;
case SDLK_DOWN: vy_ += CHAR_SPEED; break;
case SDLK_LEFT: vx_ -= CHAR_SPEED; break;
case SDLK_RIGHT: vx_ += CHAR_SPEED; break;
}
} else if(e.type == SDL_KEYUP && e.key.repeat == 0) {
switch(e.key.keysym.sym) {
case SDLK_UP: vy_ += CHAR_SPEED; break;
case SDLK_DOWN: vy_ -= CHAR_SPEED; break;
case SDLK_LEFT: vx_ += CHAR_SPEED; break;
case SDLK_RIGHT: vx_ -= CHAR_SPEED; break;
}
}
}
//update function
void Character::move() {
x_ += vx_;
if((x_ < 0) || (x_ + sprite_.getWidth() > L_W))
x_ -= vx_;
y_ += vy_;
if((y_ < 0) || (y_ + sprite_.getHeight() > L_H))
y_ -= vy_;
//camera time
camera_.x = (x_ + sprite_.getWidth()/2) - S_W/2;
camera_.y = (y_ + sprite_.getHeight()/2) - S_H/2;
if(camera_.x < 0)
camera_.x = 0;
if(camera_.y < 0)
camera_.y = 0;
if(camera_.x > L_W - camera_.w)
camera_.x = L_W - camera_.w;
if(camera_.y > L_H - camera_.h)
camera_.y = L_H - camera_.h;
//handle fog of war here
}
void Character::render() {
sprite_.render(x_ - camera_.x, y_ - camera_.y);
}
SDL_Rect* Character::getCamera() {
return &camera_;
}

38
app/action/Character.h

@ -0,0 +1,38 @@
#pragma once
#include <string>
#include "Texture.h"
extern const int S_W; //screen dimensions
extern const int S_H;
extern const int L_W; //level dimensions
extern const int L_H;
class Character {
private:
int x_,y_,vx_,vy_; //position and velocity. We dont need no second derivatives.
Texture sprite_;
SDL_Rect camera_;
public:
static const int CHAR_SPEED = 1;
Character(std::string filepath, int x, int y): x_(x), y_(y), vx_(0), vy_(0), camera_({0,0,S_W,S_H}) {
sprite_.loadFromFile(filepath);
};
~Character() {
sprite_.free();
};
void handleEvent(SDL_Event& e);
void move();
void render();
SDL_Rect* getCamera();
};

15
app/action/Level.h

@ -0,0 +1,15 @@
#pragma once
#include "Texture.h"
//very unfinished, do not use
class Level {
private:
Texture texture_;
//list of players?
//list of monsters?
SDL_Rect camera;
public:
};

7
app/action/Makefile

@ -0,0 +1,7 @@
CC = clang++
FLAGS = -lSDL2 -lSDL2_image -lSDL2_gfx
EXEC = action
SRC = main.cpp Texture.cpp Character.cpp
all: main.cpp Texture.cpp Character.cpp
$(CC) $(FLAGS) -o $(EXEC) $(SRC)

61
app/action/Texture.cpp

@ -0,0 +1,61 @@
#include "Texture.h"
Texture::Texture() {
texture_ = NULL;
w_ = -1;
h_ = -1;
}
Texture::~Texture() {
free();
}
bool Texture::loadFromFile(std::string path) {
free();
SDL_Texture* newTexture = NULL;
SDL_Surface* loadedSurface = IMG_Load(path.c_str());
SDL_SetColorKey(loadedSurface,SDL_TRUE, SDL_MapRGB(loadedSurface->format,0xFF,0x00,0xFF));
newTexture = SDL_CreateTextureFromSurface(renderer, loadedSurface);
w_ = loadedSurface->w;
h_ = loadedSurface->h;
texture_ = newTexture;
return true;
}
void Texture::free() {
if(texture_ != NULL) {
SDL_DestroyTexture(texture_);
w_ = -1;
h_ = -1;
}
}
void Texture::setColor(Uint8 red, Uint8 green, Uint8 blue) {
SDL_SetTextureColorMod(texture_,red,green,blue);
}
void Texture::render(int x, int y, SDL_Rect* clip) {
SDL_Rect renderQuad = {x,y,w_,h_};
if(clip != NULL) {
renderQuad.w = clip->w;
renderQuad.h = clip->h;
}
SDL_RenderCopy(renderer, texture_,clip,&renderQuad);
}
int Texture::getWidth() {
return w_;
}
int Texture::getHeight() {
return h_;
}

30
app/action/Texture.h

@ -0,0 +1,30 @@
#pragma once
#include <string>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
extern SDL_Renderer* renderer;
class Texture {
private:
SDL_Texture* texture_;
int w_,h_;
public:
Texture();
~Texture();
bool loadFromFile(std::string path);
void free();
void setColor(Uint8 red, Uint8 green, Uint8 blue);
void render(int x, int y, SDL_Rect* clip = NULL);
int getWidth();
int getHeight();
};

BIN
app/action/action

104
app/action/main.cpp

@ -0,0 +1,104 @@
#include <stdio.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL2_gfxPrimitives.h>
#include <SDL2/SDL_image.h>
#include "Texture.h"
#include "Character.h"
//screen width, height
const int S_W = 640;
const int S_H = 480;
const int L_W = 1920;
const int L_H = 1080;
void init();
void close();
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
int main(int argc, char** argv) {
init();
Texture map;
map.loadFromFile("Cave.png");
Character ch("sp.png",0,0);
SDL_Event e;
bool done = false;
while(!done) {
while(SDL_PollEvent(&e) != 0) {
if(e.type == SDL_QUIT) {
done = true;
break;
}
if(e.type == SDL_KEYDOWN) {
if(e.key.keysym.sym == SDLK_q) {
done = true;
break;
}
}
ch.handleEvent(e);
}
ch.move();
SDL_RenderClear(renderer);
map.render(0,0,ch.getCamera());
ch.render();
SDL_RenderPresent(renderer);
}
close();
return 0;
}
#define CHECK(call) while(0) { \
if(call < 0) { \
printf("Error on %s, SDL_Error is: %s\n",#call,SDL_GetError()); \
exit(1);\
}\
}
#define CHECKNULL(call) while(0) { \
if(call == NULL) { \
printf("Error constructing %s, SDL_Error is: %s\n",#call,SDL_GetError()); \
exit(1);\
} \
}
void init() {
CHECK(SDL_Init(SDL_INIT_VIDEO));
CHECK(IMG_Init(IMG_INIT_PNG));
window = SDL_CreateWindow("A large but ultimately finite amount of bees",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,S_W,S_H,SDL_WINDOW_SHOWN);
CHECKNULL(window);
renderer = SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
CHECKNULL(renderer);
SDL_SetRenderDrawColor(renderer,0xFF,0xFF,0xFF,0xFF); //white with 255 alpha
}
void close() {
SDL_DestroyRenderer(renderer);
renderer = NULL;
SDL_DestroyWindow(window);
window = NULL;
IMG_Quit();
SDL_Quit();
}

BIN
app/action/sp.png

After

Width: 235  |  Height: 259  |  Size: 14 KiB

23
app/dungeon.py

@ -357,13 +357,34 @@ def genCaveDungeonB64(pSizeX,pSizeY):
cv2.imwrite("generated_dungeon.png",im)
#size x, size y, cell count
def voronoiForest(sx,sy,cc):
cellPoints = []
for i in range(cc):
rx = randint(0,sx-1)
ry = randint(0,sy-1)
cellPoints.append((rx,ry,randomColor()))
im = np.zeros((sx,sy,3))
for x in range(sx):
for y in range(sy):
dists = [(np.cbrt((x-cx)**3 + (y-cy)**3),clr/255) for (cx,cy,clr) in cellPoints]
_,clr = min(dists,key=lambda t: t[0])
im[x,y,:] = clr
return np.kron(im,np.ones((8,8,1)))
#s = genGridDungeonB64(10,10,8,24)
#print(s)
if len(sys.argv) > 1:
if "cave" in sys.argv:
genCaveDungeonB64(64,64)
#genCaveDungeonB64(64,64)
im = voronoiForest(128,128,64)
cv2.imshow("voronoi",im)
cv2.waitKey(0)
cv2.imwrite("voronoi.png",im*255)
sys.exit(0)
g = Grid(GRID_SIZE,GRID_SIZE)

BIN
app/procgen/Cave.png

After

Width: 1920  |  Height: 1080  |  Size: 114 KiB

0
app/procgen/__init__.py

63
app/procgen/cave.py

@ -0,0 +1,63 @@
import numpy as np
import cv2
from random import randint, choice, shuffle
CAVE_W = 1080//4
CAVE_H = 1920//4
DIG_SPEED = 400
MINER_SPAWN = 10
STOP_LOOP = CAVE_W * CAVE_H
OPEN = np.array([255,255,255])
CLOSE = np.array([0,0,0])
def caveIsFinished(cave):
return np.sum(cave)/255 > CAVE_W*CAVE_H/4
def randomMiner(cave):
x = randint(0,CAVE_W-1)
y = randint(0,CAVE_H-1)
return [(x,y)]
def genCave():
cave = np.zeros((CAVE_W,CAVE_H,3))
miners = [(CAVE_W//2,CAVE_H//2)] #maybe do random?
progress = 0
while progress < CAVE_W*CAVE_H//4:
print("Dug {} spaces".format(progress))
for i in range(DIG_SPEED):
newMiners = []
if len(miners) == 0:
miners = randomMiner(cave)
x,y = miners.pop(0)
neighbors = []
for i in [-1,0,1]:
for j in [-1,0,1]:
dx = x+i
dy = y+j
if (i == 0 and j == 0) or dx < 0 or dx >= CAVE_W or dy < 0 or dy >= CAVE_H:
pass
elif np.array_equal(cave[dx,dy,:],CLOSE):
neighbors.append((dx,dy))
#print("Neighbors: " + str(neighbors))
if len(neighbors) > 0:
shuffle(neighbors)
nx,ny = neighbors.pop(0)
newMiners.append((nx,ny))
cave[nx,ny,:] = OPEN
progress += 1
if randint(1,100) < MINER_SPAWN and len(neighbors) > 0:
newMiners.append(neighbors.pop(0))
miners = newMiners
#clean up with morph
kernel = np.ones((3,3),np.uint8)
upscale = np.kron(cave,np.ones((4,4,1)))
dilation = cv2.dilate(upscale,kernel,iterations=2)
return dilation
def driver():
c = genCave()
cv2.imwrite("Cave.png",c)
driver()

BIN
app/voronoi.png

After

Width: 1024  |  Height: 1024  |  Size: 15 KiB

Loading…
Cancel
Save