Add files via upload
|
@ -0,0 +1,25 @@
|
|||
cmake_minimum_required(VERSION 3.0)
|
||||
project(dragonblocks)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin)
|
||||
add_executable(dragonblocks
|
||||
src/game.cpp
|
||||
src/graphics.cpp
|
||||
src/inventory.cpp
|
||||
src/main.cpp
|
||||
src/map.cpp
|
||||
src/mapgen.cpp
|
||||
src/mods.cpp
|
||||
src/node.cpp
|
||||
src/texture.cpp
|
||||
src/threads.cpp
|
||||
src/util.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(dragonblocks
|
||||
GL
|
||||
freeglut
|
||||
lua5.3
|
||||
pthread
|
||||
png16
|
||||
m
|
||||
)
|
|
@ -0,0 +1,82 @@
|
|||
DRAGONBLOCKS BEDROCK EDITION
|
||||
Written in C++
|
||||
An Open Source Project by Elias Fleckenstein
|
||||
|
||||
1. General
|
||||
1.1. What this is about
|
||||
Dragonblocks originaly was a Browsergame I made that should be some kind of 2D Minetest (Minetest (www.minetest.net) is a game similar to
|
||||
Minecraft, except Minetest is free & open source and is meant to be modded). The JavaScript Edition is hosted at www.dragonblocks.tk and
|
||||
further developed then this C++ Version, through the C++ Version has advantages like map saving and lot larger map. I decided to call the
|
||||
C++ Version "Bedrock Edition" as a joke for the Minecraft C++ Version is Called Bedrock or Pocket Edition.
|
||||
1.2. Version
|
||||
This is the Dragonblocks Bedrock Edition 3.0.
|
||||
1.4. Bugs
|
||||
Please Report Bugs to eliasfleckenstein@web.de.
|
||||
1.5. License
|
||||
Copyright 2020 Elias Fleckenstein <eliasfleckenstein@web.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02110-1301, USA.
|
||||
|
||||
2. Starting the Game
|
||||
2.1. Platform Compability
|
||||
This Game was developed on linux, therefore following instructions are only for linux users, basically because I have no idea how to
|
||||
port the game to other platforms. Feel free to add building instructions for other systems over github.
|
||||
2.3. Download
|
||||
You can download the game using git:
|
||||
$ git clone https://
|
||||
2.2. Dependencies:
|
||||
You need Freeglut, OpenGl, Cmake, Liblua and Libpng.
|
||||
If you are on Debian/Ubuntu You can install them over apt:
|
||||
$ sudo apt install liblua5.3-dev freeglut3-dev libgl1-mesa-dev cmake libpng-dev
|
||||
2.3. Building
|
||||
to Build dragonblocks run:
|
||||
$ cd dragonblocks
|
||||
$ cmake .
|
||||
$ make
|
||||
2.4. Exectute
|
||||
2.4.1. Run-In-Place
|
||||
Invoke dragonblocks by typing:
|
||||
$ cd dragonblocks
|
||||
$ bin/dragonblocks --worldname <your_worldname>
|
||||
To see a list of worlds do:
|
||||
$ bin/dragonblocks --worldlist
|
||||
You can select a world from this list or create a new one.
|
||||
For more info run:
|
||||
$ bin/dragonblocks --help
|
||||
2.4.2. Installation
|
||||
You can install dragonblocks by doing:
|
||||
$ sudo ./install.sh
|
||||
It will copy the dragonblocks directory to /usr/share/dragonblocks and place a script in
|
||||
/usr/bin/dragonblocks that starts dragonblocks.
|
||||
|
||||
3. Developing
|
||||
3.1. The Lua Modding API
|
||||
If you want to add a lua file to the game, place it in the game folder and add a dofile() in game/init.lua
|
||||
Note: The lua api currently consists of only two functions. If you want to add something I'm open to ideas or code.
|
||||
dragonblocks.register_node(obj)
|
||||
Register a new node
|
||||
obj has to contain:
|
||||
name: string - the itemstring. It should follow the convention "modulename:nodename"
|
||||
texture: string - the texture path. Textures should be placed in the textures folder and have to be 16 x 16 px.
|
||||
obj can contain:
|
||||
stable: boolean - Nodes like water or air are unstable. [default = true]
|
||||
hidden: boolean - The Node will be hidden in the invenotry. [default = false]
|
||||
translucent: boolean - Whether the node's texture should be transparent. [default = false]
|
||||
dragonblocks.log(text)
|
||||
Log something.
|
||||
3.2. The C++ API
|
||||
The C++ API is probably to big to explain here, but if you do C++ you should understand it. In case you have questions, feel free to
|
||||
ask them on github. You can also contribute code if you want.
|
|
@ -0,0 +1,5 @@
|
|||
local cpp_last_node = 0
|
||||
function cpp_get_next_node()
|
||||
cpp_last_node = cpp_last_node + 1
|
||||
return core.nodes[cpp_last_node]
|
||||
end
|
|
@ -0,0 +1,3 @@
|
|||
dragonblocks.log = function(text)
|
||||
print("[LUA] "..text)
|
||||
end
|
|
@ -0,0 +1,15 @@
|
|||
core = {}
|
||||
dragonblocks = {}
|
||||
dragonblocks.settings = {}
|
||||
|
||||
dofile("builtin/register.lua")
|
||||
dofile("builtin/functions.lua")
|
||||
dofile("builtin/cpp.lua")
|
||||
|
||||
--local popenfile = io.popen("ls game")
|
||||
--for filename in popenfile:lines() do
|
||||
-- dofile("game/"..filename.."/init.lua")
|
||||
--end
|
||||
--popenfile:close()
|
||||
|
||||
dofile("game/init.lua")
|
|
@ -0,0 +1,20 @@
|
|||
core.nodes = {}
|
||||
dragonblocks.register_node = function(obj)
|
||||
if obj and obj.name and obj.texture then
|
||||
core.nodes[#core.nodes+1] = {}
|
||||
core.nodes[#core.nodes].name = obj.name
|
||||
core.nodes[#core.nodes].texture = obj.texture
|
||||
core.nodes[#core.nodes].stable = false
|
||||
if obj.stable == nil or obj.stable == true then
|
||||
core.nodes[#core.nodes].stable = true
|
||||
end
|
||||
core.nodes[#core.nodes].hidden = false
|
||||
if obj.hidden then
|
||||
core.nodes[#core.nodes].hidden = true
|
||||
end
|
||||
core.nodes[#core.nodes].translucent = false
|
||||
if obj.translucent then
|
||||
core.nodes[#core.nodes].translucent = true
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,7 @@
|
|||
dragonblocks.log(" ____ _ _ _ ")
|
||||
dragonblocks.log("| _ \\ _ __ __ _ __ _ ___ _ __ | |__ | | ___ ___| | _____ ")
|
||||
dragonblocks.log("| | | | '__/ _` |/ _` |/ _ \\| '_ \\| '_ \\| |/ _ \\ / __| |/ / __| ")
|
||||
dragonblocks.log("| |_| | | | (_| | (_| | (_) | | | | |_) | | (_) | (__| <\\__ \\ ")
|
||||
dragonblocks.log("|____/|_| \\__,_|\\__, |\\___/|_| |_|_.__/|_|\\___/ \\___|_|\\_\\___/ ")
|
||||
dragonblocks.log(" |___/ ")
|
||||
dofile("game/nodes.lua")
|
|
@ -0,0 +1,50 @@
|
|||
dragonblocks.register_node({
|
||||
name = "dragonblocks:air",
|
||||
texture = "textures/air.png",
|
||||
stable = false,
|
||||
hidden = true,
|
||||
translucent = true,
|
||||
})
|
||||
dragonblocks.register_node({
|
||||
name = "dragonblocks:stone",
|
||||
texture = "textures/stone.png"
|
||||
})
|
||||
dragonblocks.register_node({
|
||||
name = "dragonblocks:dirt",
|
||||
texture = "textures/dirt.png"
|
||||
})
|
||||
dragonblocks.register_node({
|
||||
name = "dragonblocks:grass",
|
||||
texture = "textures/grass.png"
|
||||
})
|
||||
dragonblocks.register_node({
|
||||
name = "dragonblocks:wood",
|
||||
texture = "textures/wood.png"
|
||||
})
|
||||
dragonblocks.register_node({
|
||||
name = "dragonblocks:water",
|
||||
texture = "textures/water.png",
|
||||
stable = false,
|
||||
translucent = true,
|
||||
})
|
||||
dragonblocks.register_node({
|
||||
name = "dragonblocks:leaves",
|
||||
texture = "textures/leaves.png",
|
||||
translucent = true,
|
||||
})
|
||||
dragonblocks.register_node({
|
||||
name = "dragonblocks:bedrock",
|
||||
texture = "textures/bedrock.png"
|
||||
})
|
||||
dragonblocks.register_node({
|
||||
name = "dragonblocks:mese",
|
||||
texture = "textures/mese.png"
|
||||
})
|
||||
dragonblocks.register_node({
|
||||
name = "dragonblocks:sand",
|
||||
texture = "textures/sand.png"
|
||||
})
|
||||
dragonblocks.register_node({
|
||||
name = "dragonblocks:cobble",
|
||||
texture = "textures/cobble.png"
|
||||
})
|
|
@ -0,0 +1,7 @@
|
|||
#! /bin/bash
|
||||
cp . /usr/share/dragonblocks -R
|
||||
echo "
|
||||
cd /usr/share/dragonblocks
|
||||
bin/dragonblocks \$*
|
||||
" > /usr/bin/dragonblocks
|
||||
chmod +x /usr/bin/dragonblocks
|
|
@ -0,0 +1,84 @@
|
|||
#include <string>
|
||||
#include <iostream>
|
||||
#include <cstdio>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "mods.h"
|
||||
#include "game.h"
|
||||
using namespace std;
|
||||
|
||||
void Game::log(string text, int level){
|
||||
string prefix;
|
||||
int color;
|
||||
switch(level){
|
||||
case WARNING:
|
||||
color = ORANGE;
|
||||
prefix = "WARNING";
|
||||
break;
|
||||
case ERROR:
|
||||
color = RED;
|
||||
prefix = "ERROR";
|
||||
break;
|
||||
case INFO:
|
||||
color = LIGHTBLUE;
|
||||
prefix = "INFO";
|
||||
break;
|
||||
case LOG:
|
||||
color = BLUE;
|
||||
prefix = "LOG";
|
||||
break;
|
||||
case EASTEREGG:
|
||||
color = VIOLET;
|
||||
prefix = "EASTEREGG";
|
||||
default: break;
|
||||
}
|
||||
cout << "\e[3" << color << "m" << "[" << prefix << "] \e[0m" << text << endl;
|
||||
if(logfile_fd)
|
||||
fprintf(logfile_fd, "[%s] %s\n", prefix.c_str(), text.c_str());
|
||||
}
|
||||
void Game::log(string text){
|
||||
log(text, LOG);
|
||||
}
|
||||
void Game::help(){
|
||||
cout << "Usage: " << argv[0] << "[OPTIONS]" << endl;
|
||||
cout << "Options:" << endl;
|
||||
cout << "\t" << "-h" << "\t" << "--help" << "\t\t\t" << "Display this help and exit." << endl;
|
||||
cout << "\t" << "-v" << "\t" << "--version" << "\t\t" << "Display version info." << endl;
|
||||
cout << "\t" << "-p" << "\t" << "--worldpath [PATH]" << "\t" << "Set world path." << endl;
|
||||
cout << "\t" << "-w" << "\t" << "--worldname [PATH]" << "\t" << "Select world by name (Worlds are placed in ~/.dragonblocks/worlds/)." << endl;
|
||||
cout << "\t" << "-r" << "\t" << "--worldlist" << "\t\t" << "Show a list of your worlds." << endl;
|
||||
cout << "\t" << "-s" << "\t" << "--seed [NUMBER]" << "\t\t" << "Set seed." << endl;
|
||||
cout << "\t" << "-l" << "\t" << "--logfile [PATH]" << "\t" << "Set logfile." << endl;
|
||||
}
|
||||
void Game::version(){
|
||||
cout << "DRAGONBLOCKS BEDROCK EDITION" << endl;
|
||||
cout << "Written in C++" << endl;
|
||||
cout << "An Open Source Project by Elias Fleckenstein" << endl;
|
||||
cout << "Dragonblocks " << VERSION << endl;
|
||||
}
|
||||
void Game::worldlist(){
|
||||
log("Your worlds:");
|
||||
DIR *folder;
|
||||
struct dirent *entry;
|
||||
int files = 0;
|
||||
|
||||
folder = opendir(((string)getenv("HOME")+"/.dragonblocks/worlds/").c_str());
|
||||
if(!folder){
|
||||
Game::log("Cant Open World Directory", ERROR);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
while(entry = readdir(folder))
|
||||
{
|
||||
files++;
|
||||
if(files > 2)
|
||||
cout << "\t" << entry->d_name;
|
||||
}
|
||||
if(files <= 2)
|
||||
cout << "\tYou have no Worlds yet.";
|
||||
cout << endl;
|
||||
closedir(folder);
|
||||
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef _GAME_H_
|
||||
#define _GAME_H_
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#include "map.h"
|
||||
#include "inventory.h"
|
||||
|
||||
#define WARNING 1
|
||||
#define ERROR 2
|
||||
#define INFO -1
|
||||
#define EASTEREGG 17
|
||||
#define LOG 0
|
||||
|
||||
#define VERSION "3.0"
|
||||
|
||||
#define BLACK 0
|
||||
#define RED 1
|
||||
#define GREEN 2
|
||||
#define ORANGE 3
|
||||
#define BLUE 4
|
||||
#define VIOLET 5
|
||||
#define LIGHTBLUE 6
|
||||
#define GREY 7
|
||||
|
||||
class Game{
|
||||
public:
|
||||
static int *argc;
|
||||
static char **argv;
|
||||
static int seed;
|
||||
static std::string mapfile;
|
||||
static std::string logfile;
|
||||
static FILE *logfile_fd;
|
||||
static Map *map;
|
||||
static void log(std::string);
|
||||
static void log(std::string, int);
|
||||
static void help();
|
||||
static void version();
|
||||
static void worldlist();
|
||||
static Inventory *inventory;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,130 @@
|
|||
#include <GL/freeglut.h>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "graphics.h"
|
||||
#include "util.h"
|
||||
#include "game.h"
|
||||
#include "mapgen.h"
|
||||
|
||||
position Graphics::pointed;
|
||||
position Graphics::pos = {MAPWIDTH/2 - DISPLAYWIDTH/2, MAPHEIGHT/2 - DISPLAYHEIGHT/2};
|
||||
|
||||
using namespace std;
|
||||
void Graphics::display(){
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
//sky
|
||||
drawRectangle(0, 0, DISPLAYWIDTH*BLOCKWIDTH, DISPLAYHEIGHT*BLOCKWIDTH, "#87CEEB");
|
||||
//map
|
||||
for(int x = 0; x < DISPLAYWIDTH; x++){
|
||||
for(int y = 0; y < DISPLAYHEIGHT; y++){
|
||||
Game::map -> getNode(x+pos.x, y+pos.y) -> texture -> draw(x*BLOCKWIDTH, y*BLOCKWIDTH, BLOCKWIDTH, BLOCKWIDTH);
|
||||
}
|
||||
}
|
||||
//pointed block
|
||||
if(pointed.x < DISPLAYWIDTH){
|
||||
drawRectangle(pointed.x * BLOCKWIDTH, pointed.y * BLOCKWIDTH, BLOCKWIDTH, 1, COLOR_BLACK);
|
||||
drawRectangle(pointed.x * BLOCKWIDTH + BLOCKWIDTH - 1, pointed.y * BLOCKWIDTH, 1, BLOCKWIDTH, COLOR_BLACK);
|
||||
drawRectangle(pointed.x * BLOCKWIDTH, pointed.y * BLOCKWIDTH + BLOCKWIDTH - 1, BLOCKWIDTH, 1, COLOR_BLACK);
|
||||
drawRectangle(pointed.x * BLOCKWIDTH, pointed.y * BLOCKWIDTH, 1, BLOCKWIDTH, COLOR_BLACK);
|
||||
}
|
||||
//inventory
|
||||
|
||||
drawRectangle(DISPLAYWIDTH*BLOCKWIDTH, 0, INVWIDTH, DISPLAYHEIGHT*BLOCKWIDTH, "#B4B4B4");
|
||||
drawRectangle(DISPLAYWIDTH*BLOCKWIDTH, Game::inventory->selected * INVWIDTH, INVWIDTH, INVWIDTH, "#636363");
|
||||
for(int i = 0; i < Game::inventory->count; i++)
|
||||
Game::inventory -> getSlot(i) -> texture -> draw(BLOCKWIDTH*DISPLAYWIDTH + (INVWIDTH-INVBLOCKWIDTH)/2, i * INVWIDTH + (INVWIDTH-INVBLOCKWIDTH)/2, INVBLOCKWIDTH, INVBLOCKWIDTH);
|
||||
//infotext
|
||||
writeText(5, 5, (string)"Dragonblocks "+VERSION, GLUT_BITMAP_9_BY_15, COLOR_WHITE);
|
||||
string infotext = "pos: ("+to_string(pos.x)+", "+to_string(pos.y)+"), seed: "+to_string(Game::seed);
|
||||
if(pointed.x < DISPLAYWIDTH)
|
||||
infotext += ", pointed: "+ Game::map->getNode(pointed.x+pos.x, pointed.y+pos.y)->name + "("+to_string(pointed.x+pos.x)+", "+to_string(pointed.y+pos.y)+")";
|
||||
writeText(5, 20, infotext, GLUT_BITMAP_9_BY_15, COLOR_WHITE);
|
||||
//writeText(5, 35, "world: "+Game::mapfile, GLUT_BITMAP_9_BY_15, COLOR_WHITE);
|
||||
glFlush();
|
||||
}
|
||||
void Graphics::reshape(int width, int height){
|
||||
glViewport(0, 0, width, height); /* Establish viewing area to cover entire window. */
|
||||
glMatrixMode(GL_PROJECTION); /* Start modifying the projection matrix. */
|
||||
glLoadIdentity(); /* Reset project matrix. */
|
||||
glOrtho(0, width, 0, height, -1, 1); /* Map abstract coords directly to window coords. */
|
||||
glScalef(1, -1, 1); /* Invert Y axis so increasing Y goes down. */
|
||||
glTranslatef(0, -height, 0); /* Shift origin up to upper-pos.x corner. */
|
||||
}
|
||||
void Graphics::init(){
|
||||
glutInit(Game::argc, Game::argv);
|
||||
glutCreateWindow("Dragonblocks");
|
||||
glutReshapeWindow(DISPLAYWIDTH*BLOCKWIDTH+INVWIDTH, DISPLAYHEIGHT*BLOCKWIDTH);
|
||||
glutDisplayFunc(display);
|
||||
glutReshapeFunc(reshape);
|
||||
glutKeyboardFunc(keyboard);
|
||||
glutSpecialFunc(special);
|
||||
glutMouseFunc(mouse);
|
||||
glutPassiveMotionFunc(motion);
|
||||
glutMotionFunc(motion);
|
||||
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
|
||||
glutMainLoop();
|
||||
}
|
||||
void Graphics::keyboard(unsigned char key, int x, int y){
|
||||
}
|
||||
void Graphics::special(int key, int x, int y){
|
||||
switch(key){
|
||||
case GLUT_KEY_LEFT:
|
||||
if(pos.x > 0)
|
||||
pos.x--;
|
||||
break;
|
||||
case GLUT_KEY_UP:
|
||||
if(pos.y > 0)
|
||||
pos.y--;
|
||||
break;
|
||||
case GLUT_KEY_RIGHT:
|
||||
if(pos.x < MAPWIDTH-DISPLAYWIDTH)
|
||||
pos.x++;
|
||||
break;
|
||||
case GLUT_KEY_DOWN:
|
||||
if(pos.y < MAPHEIGHT-DISPLAYHEIGHT)
|
||||
pos.y++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
void Graphics::mouse(int key, int action, int x, int y){
|
||||
if(action == 0){
|
||||
if(x < BLOCKWIDTH*DISPLAYWIDTH){
|
||||
switch(key){
|
||||
case 0:
|
||||
if(Game::map -> getNode(pointed.x+pos.x, pointed.y+pos.y)->stable)
|
||||
Game::map -> setNode(pointed.x+pos.x, pointed.y+pos.y, MAPGEN_AIR);
|
||||
break;
|
||||
case 2:
|
||||
if(! Game::map -> getNode(pointed.x+pos.x, pointed.y+pos.y)->stable)
|
||||
Game::map -> setNode(pointed.x+pos.x, pointed.y+pos.y, Game::inventory->getSelectedSlot());
|
||||
break;
|
||||
}
|
||||
}
|
||||
else{
|
||||
Game::inventory->select(y/INVWIDTH);
|
||||
}
|
||||
}
|
||||
}
|
||||
void Graphics::motion(int x, int y){
|
||||
pointed.x = x / BLOCKWIDTH;
|
||||
pointed.y = y / BLOCKWIDTH;
|
||||
}
|
||||
void Graphics::writeText(int x, int y, string text, void *font, color c){
|
||||
glColor3f(c.red, c.green, c.blue);
|
||||
glRasterPos2i(x, y+10);
|
||||
char *s = strdup(text.c_str());
|
||||
--s;
|
||||
while(*++s)
|
||||
glutBitmapCharacter(font, *s);
|
||||
}
|
||||
void Graphics::drawRectangle(int x, int y, int width, int height, color c){
|
||||
glColor3f(c.red, c.green, c.blue);
|
||||
glBegin(GL_POLYGON);
|
||||
glVertex2i(x, y);
|
||||
glVertex2i(x+width, y);
|
||||
glVertex2i(x+width, y+height);
|
||||
glVertex2i(x, y+height);
|
||||
glEnd();
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
#ifndef _GRAPHICS_H_
|
||||
#define _GRAPHICS_H_
|
||||
|
||||
#include <string>
|
||||
#include "texture.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
#define BLOCKWIDTH 32
|
||||
#define DISPLAYWIDTH 25
|
||||
#define DISPLAYHEIGHT 25
|
||||
#define INVBLOCKWIDTH 64
|
||||
#define INVWIDTH 80
|
||||
|
||||
#define COLOR_WHITE {1,1,1}
|
||||
#define COLOR_BLACK {0,0,0}
|
||||
|
||||
|
||||
class Graphics{
|
||||
public:
|
||||
static void init();
|
||||
|
||||
static position pointed;
|
||||
static position pos;
|
||||
|
||||
//handlers
|
||||
static void display();
|
||||
static void keyboard(unsigned char, int, int);
|
||||
static void mouse(int, int, int, int);
|
||||
static void special(int, int, int);
|
||||
static void reshape(int, int);
|
||||
static void motion(int, int);
|
||||
|
||||
//functions
|
||||
static void drawRectangle(int, int, int, int, color);
|
||||
static void writeText(int, int, std::string, void*, color);
|
||||
};
|
||||
#endif
|
|
@ -0,0 +1,24 @@
|
|||
#include "node.h"
|
||||
#include "inventory.h"
|
||||
Inventory::Inventory(){
|
||||
count = 0;
|
||||
selected = 0;
|
||||
for(int i = 0; i < Node::count; i++){
|
||||
if(! Node::getNodeById(i) -> hidden){
|
||||
list[count] = Node::getNodeById(i);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
Node *Inventory::getSlot(int nr){
|
||||
if(nr >= 0 && nr < count)
|
||||
return list[nr];
|
||||
return list[0];
|
||||
}
|
||||
void Inventory::select(int nr){
|
||||
if(nr >= 0 && nr < count)
|
||||
selected = nr;
|
||||
}
|
||||
Node *Inventory::getSelectedSlot(){
|
||||
return list[selected];
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef _INVENTORY_H_
|
||||
#define _INVENTORY_H_
|
||||
|
||||
#include "node.h"
|
||||
|
||||
class Inventory{
|
||||
public:
|
||||
int count;
|
||||
int selected;
|
||||
Node *list[MAXNODES];
|
||||
Node *getSlot(int);
|
||||
void select(int);
|
||||
Node *getSelectedSlot();
|
||||
Inventory();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,113 @@
|
|||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <getopt.h>
|
||||
#include <iostream>
|
||||
#include <cstdio>
|
||||
#include <unistd.h>
|
||||
#include "graphics.h"
|
||||
#include "map.h"
|
||||
#include "game.h"
|
||||
#include "node.h"
|
||||
#include "mapgen.h"
|
||||
#include "mods.h"
|
||||
#include "threads.h"
|
||||
#include "inventory.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
Map *Game::map;
|
||||
string Game::mapfile;
|
||||
string Game::logfile;
|
||||
int Game::seed;
|
||||
char **Game::argv;
|
||||
int *Game::argc;
|
||||
FILE *Game::logfile_fd;
|
||||
Inventory *Game::inventory;
|
||||
|
||||
int main(int argc, char **argv){
|
||||
if((string)argv[0] != "bin/dragonblocks"){
|
||||
string command = "cd ..; bin/dragonblocks -w world ";
|
||||
while(*++argv)
|
||||
command += *argv;
|
||||
exit(system(command.c_str()));
|
||||
}
|
||||
create_dir_if_not_exists((string)getenv("HOME")+"/.dragonblocks");
|
||||
create_dir_if_not_exists((string)getenv("HOME")+"/.dragonblocks/worlds");
|
||||
Game::argc = &argc;
|
||||
Game::argv = argv;
|
||||
Game::seed = time(0);
|
||||
Game::logfile = (string)getenv("HOME")+"/.dragonblocks/dragonblocks.log";
|
||||
const char *short_options = "hrvs:l:w:p:";
|
||||
const struct option long_options[] = {
|
||||
{"help", 0, NULL, 'h'},
|
||||
{"version", 0, NULL, 'v'},
|
||||
{"worldname", 1, NULL, 'w'},
|
||||
{"worldpath", 1, NULL, 'p'},
|
||||
{"worldlist", 0, NULL, 'r'},
|
||||
{"seed", 1, NULL, 's'},
|
||||
{"logfile", 1, NULL, 'l'},
|
||||
{NULL, 0, NULL, 0},
|
||||
};
|
||||
int next_option;
|
||||
while((next_option = getopt_long(argc, argv, short_options, long_options, NULL)) != -1){
|
||||
switch(next_option){
|
||||
case 'h':
|
||||
Game::help();
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'v':
|
||||
Game::version();
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'p':
|
||||
Game::mapfile = optarg;
|
||||
break;
|
||||
case 'w':
|
||||
Game::mapfile = (string)getenv("HOME")+"/.dragonblocks/worlds/"+optarg;
|
||||
break;
|
||||
case 's':
|
||||
Game::seed = atoi(optarg);
|
||||
break;
|
||||
case 'l':
|
||||
Game::logfile = optarg;
|
||||
break;
|
||||
case 'r':
|
||||
Game::worldlist();
|
||||
exit(0);
|
||||
break;
|
||||
case '?':
|
||||
Game::log("Invalid Usage", ERROR);
|
||||
Game::help();
|
||||
exit(EXIT_FAILURE);
|
||||
break;
|
||||
};
|
||||
}
|
||||
if(Game::logfile_fd = fopen(Game::logfile.c_str(), "a"))
|
||||
fprintf(Game::logfile_fd, "\n--------------------------------------------------\n");
|
||||
else
|
||||
Game::log((string)"Failed to open log file " + Game::logfile, WARNING);
|
||||
Game::log((string)"Welcome to Dragonblocks "+VERSION);
|
||||
srand(Game::seed);
|
||||
new Node("unknown_node", "textures/unknown_node.png", true, true, false);
|
||||
Mods::init();
|
||||
Game::inventory = new Inventory();
|
||||
Game::map = new Map();
|
||||
if(Game::mapfile == ""){
|
||||
Game::log("No World Specified", ERROR);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if(fopen(Game::mapfile.c_str(), "r"))
|
||||
Game::map->load();
|
||||
else
|
||||
Mapgen();
|
||||
Threads::startMapBackupThread();
|
||||
Threads::startGraphicUpdateThread();
|
||||
Threads::addSignalHandlers();
|
||||
Graphics::init();
|
||||
Game::log("Closed Window, Exiting.");
|
||||
Game::map -> save();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
#include <string>
|
||||
#include <stdlib.h>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include "map.h"
|
||||
#include "node.h"
|
||||
#include "game.h"
|
||||
using namespace std;
|
||||
Node *Map::getNode(int x, int y){
|
||||
if(x < MAPWIDTH && y < MAPHEIGHT && x > -1 && y > -1)
|
||||
return content[x][y];
|
||||
return NULL;
|
||||
}
|
||||
void Map::setNode(int x, int y, Node *n){
|
||||
if(x < MAPWIDTH && y < MAPHEIGHT && x > -1 && y > -1)
|
||||
content[x][y] = n;
|
||||
}
|
||||
void Map::setNode(int x, int y, string n){
|
||||
setNode(x, y, Node::getNodeByName(n));
|
||||
}
|
||||
void Map::load(){
|
||||
Game::log("Loading Map from " + Game::mapfile);
|
||||
FILE *mapfile = fopen(Game::mapfile.c_str(), "r");
|
||||
if(mapfile){
|
||||
for(int x = 0; x < MAPWIDTH; x++)
|
||||
for(int y = 0; y < MAPHEIGHT; y++){
|
||||
char buffer[512] = {0};
|
||||
fscanf(mapfile, "%s", buffer);
|
||||
setNode(x, y, buffer);
|
||||
}
|
||||
fclose(mapfile);
|
||||
Game::log("Loaded Map");
|
||||
}
|
||||
else{
|
||||
Game::log("Could not Load Map.", ERROR);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
void Map::save(){
|
||||
Game::log("Saving Map to " + Game::mapfile);
|
||||
FILE *mapfile = fopen(Game::mapfile.c_str(), "w");
|
||||
if(mapfile){
|
||||
for(int x = 0; x < MAPWIDTH; x++){
|
||||
for(int y = 0; y < MAPHEIGHT; y++)
|
||||
fprintf(mapfile,"%s ", getNode(x,y)->name.c_str());
|
||||
fprintf(mapfile, "\n");
|
||||
}
|
||||
fclose(mapfile);
|
||||
Game::log("Saved Map");
|
||||
}
|
||||
else
|
||||
Game::log("Could not Save Map.", ERROR);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef _MAP_H_
|
||||
#define _MAP_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "node.h"
|
||||
|
||||
#define MAPWIDTH 500
|
||||
#define MAPHEIGHT 100
|
||||
|
||||
class Map{
|
||||
public:
|
||||
Node *getNode(int, int);
|
||||
void setNode(int, int, Node *);
|
||||
void setNode(int, int, std::string);
|
||||
void load();
|
||||
void save();
|
||||
private:
|
||||
Node *content[MAPWIDTH][MAPHEIGHT];
|
||||
};
|
||||
#endif
|
|
@ -0,0 +1,121 @@
|
|||
#include <string>
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "mapgen.h"
|
||||
#include "map.h"
|
||||
#include "node.h"
|
||||
#include "util.h"
|
||||
#include "game.h"
|
||||
|
||||
using namespace std;
|
||||
void Mapgen(){
|
||||
Game::log("Generating Map");
|
||||
//Air
|
||||
for(int x = 0; x < MAPWIDTH; x++){
|
||||
for(int y = 0; y < MAPHEIGHT; y++){
|
||||
Game::map->setNode(x,y,MAPGEN_AIR);
|
||||
}
|
||||
}
|
||||
//Seed 13 Easteregg
|
||||
if(Game::seed == 13){
|
||||
for(int x = 0; x < MAPWIDTH; x++){
|
||||
for(int y = 0; y < MAPHEIGHT; y++){
|
||||
Game::map->setNode(x,y,MAPGEN_BEDROCK);
|
||||
}
|
||||
}
|
||||
Game::log("LOL Seed 13", EASTEREGG);
|
||||
return;
|
||||
}
|
||||
//Bottom
|
||||
int bottom[MAPWIDTH];
|
||||
bottom[0] = random(MAPHEIGHT/2 - MAPHEIGHT/10, MAPHEIGHT/2);
|
||||
for(int x = 1; x < MAPWIDTH; x++){
|
||||
bottom[x] = bottom[x-1] + random(-1,1);
|
||||
}
|
||||
//Smooth
|
||||
for(int x = 1; x < MAPWIDTH-1; x++){
|
||||
if(bottom[x] > bottom[x+1] && bottom[x] > bottom[x-1]) bottom[x]--;
|
||||
else if(bottom[x] < bottom[x+1] && bottom[x] < bottom[x-1])bottom[x]++;
|
||||
}
|
||||
//Dirt with Grass
|
||||
for(int x = 0; x < MAPWIDTH; x++){
|
||||
Game::map->setNode(x,bottom[x],MAPGEN_GRASS);
|
||||
}
|
||||
//Dirt
|
||||
for(int x = 0; x < MAPWIDTH; x++){
|
||||
for(int y = bottom[x]+1; y < bottom[x]+5; y++){
|
||||
Game::map->setNode(x,y,MAPGEN_DIRT);
|
||||
}
|
||||
}
|
||||
//Stone
|
||||
for(int x = 0; x < MAPWIDTH; x++){
|
||||
for(int y = bottom[x]+5; y < MAPHEIGHT; y++){
|
||||
Game::map->setNode(x,y,MAPGEN_STONE);
|
||||
}
|
||||
}
|
||||
//Mese
|
||||
for(int x = 0; x < MAPWIDTH; x++){
|
||||
for(int y = bottom[x]+10; y < MAPHEIGHT; y++){
|
||||
if((rand() % 100) == 0) Game::map->setNode(x,y,MAPGEN_MESE);
|
||||
}
|
||||
}
|
||||
//Bedrock
|
||||
for(int x = 0; x < MAPWIDTH; x++){
|
||||
Game::map->setNode(x,MAPHEIGHT-1,MAPGEN_BEDROCK);
|
||||
if(random(0,1) == 0){
|
||||
Game::map->setNode(x,MAPHEIGHT-2,MAPGEN_BEDROCK);
|
||||
if(random(0,2) == 0){
|
||||
Game::map->setNode(x,MAPHEIGHT-3,MAPGEN_BEDROCK);
|
||||
}
|
||||
}
|
||||
}
|
||||
//Water
|
||||
int flatcount = 0;
|
||||
for(int x = 1; x < MAPWIDTH; x++){
|
||||
if(bottom[x] == bottom[x-1]) flatcount++;
|
||||
else if(flatcount > 7){
|
||||
int leftborder = rand() % 2;
|
||||
int rightborder = rand() % 2;
|
||||
for(int mx = x-flatcount-3; mx < x+2; mx++){
|
||||
for(int y = bottom[mx];y < bottom[mx]+5;y++){
|
||||
if(Game::map->getNode(mx,y) == MAPGEN_STONE) break;
|
||||
if(Game::map->getNode(mx,y) == MAPGEN_DIRT || Game::map->getNode(mx,y) == MAPGEN_GRASS) Game::map->setNode(mx,y,MAPGEN_SAND);
|
||||
}
|
||||
}
|
||||
for(int mx = x-flatcount+leftborder;mx < x-1-rightborder;mx++) Game::map->setNode(mx,bottom[x-1],MAPGEN_WATER);
|
||||
for(int mx = x-flatcount+1+leftborder;mx < x-2-rightborder;mx++) Game::map->setNode(mx,bottom[x-1]+1,MAPGEN_WATER);
|
||||
for(int mx = x-flatcount+2+leftborder; mx < x-3-rightborder;mx++) Game::map->setNode(mx,bottom[x-1]+2,MAPGEN_WATER);
|
||||
flatcount = 0;
|
||||
}
|
||||
else flatcount = 0;
|
||||
}
|
||||
//Tree
|
||||
int treecount = rand() % MAPWIDTH/10;
|
||||
int treepos[treecount];
|
||||
for(int i = 0; i < treecount; i++){
|
||||
while(true){
|
||||
bool cont = true;
|
||||
treepos[i] = rand() % MAPWIDTH;
|
||||
for(int j = 0; j < i; j++){
|
||||
if(abs(treepos[j]-treepos[i]) < 3) cont = false;
|
||||
}
|
||||
if(!(Game::map->getNode(treepos[i],bottom[treepos[i]]) == MAPGEN_GRASS)) cont = false;
|
||||
if(cont) break;
|
||||
}
|
||||
int x = treepos[i];
|
||||
int y = bottom[x] - 1;
|
||||
Game::map->setNode(x,y,MAPGEN_WOOD);
|
||||
Game::map->setNode(x,y-1,MAPGEN_WOOD);
|
||||
Game::map->setNode(x,y-2,MAPGEN_LEAVES);
|
||||
Game::map->setNode(x,y-3,MAPGEN_LEAVES);
|
||||
Game::map->setNode(x,y-4,MAPGEN_LEAVES);
|
||||
Game::map->setNode(x-1,y-2,MAPGEN_LEAVES);
|
||||
Game::map->setNode(x-1,y-3,MAPGEN_LEAVES);
|
||||
Game::map->setNode(x-1,y-4,MAPGEN_LEAVES);
|
||||
Game::map->setNode(x+1,y-2,MAPGEN_LEAVES);
|
||||
Game::map->setNode(x+1,y-3,MAPGEN_LEAVES);
|
||||
Game::map->setNode(x+1,y-4,MAPGEN_LEAVES);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef _MAPGEN_H_
|
||||
#define _MAPGEN_H_
|
||||
|
||||
#include "map.h"
|
||||
|
||||
#define MAPGEN_AIR Node::getNodeByName("dragonblocks:air")
|
||||
#define MAPGEN_GRASS Node::getNodeByName("dragonblocks:grass")
|
||||
#define MAPGEN_DIRT Node::getNodeByName("dragonblocks:dirt")
|
||||
#define MAPGEN_STONE Node::getNodeByName("dragonblocks:stone")
|
||||
#define MAPGEN_BEDROCK Node::getNodeByName("dragonblocks:bedrock")
|
||||
#define MAPGEN_MESE Node::getNodeByName("dragonblocks:mese")
|
||||
#define MAPGEN_LEAVES Node::getNodeByName("dragonblocks:leaves")
|
||||
#define MAPGEN_WOOD Node::getNodeByName("dragonblocks:wood")
|
||||
#define MAPGEN_WATER Node::getNodeByName("dragonblocks:water")
|
||||
#define MAPGEN_SAND Node::getNodeByName("dragonblocks:sand")
|
||||
|
||||
void Mapgen();
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,87 @@
|
|||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <cerrno>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include "node.h"
|
||||
#include "mods.h"
|
||||
#include "game.h"
|
||||
#include "util.h"
|
||||
#include "graphics.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
lua_State *Mods::lua_vm;
|
||||
|
||||
void Mods::init(){
|
||||
Game::log("Initializing Mods");
|
||||
lua_vm = luaL_newstate();
|
||||
luaL_openlibs(lua_vm);
|
||||
if(! check_lua(luaL_dofile(lua_vm, "builtin/init.lua"))){
|
||||
Game::log("Failed to load Builtin", ERROR);
|
||||
exit(EXIT_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
for(;;){
|
||||
lua_getglobal(lua_vm, "cpp_get_next_node");
|
||||
if(!lua_isfunction(lua_vm, -1)){
|
||||
Game::log("Lua is sick. What's Wrong with her?", EASTEREGG);
|
||||
Game::log("No, seriously, something is wrong with the lua builtin (it is missing the function cpp_get_next_node)", ERROR);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
lua_pcall(lua_vm, 0, 1, 0);
|
||||
if(! lua_istable(lua_vm, -1))
|
||||
break;
|
||||
|
||||
lua_pushstring(lua_vm, "name");
|
||||
lua_gettable(lua_vm, -2);
|
||||
if(!lua_isstring(lua_vm,-1))
|
||||
continue;
|
||||
string name = lua_tostring(lua_vm,-1);
|
||||
lua_pop(lua_vm, 1);
|
||||
|
||||
lua_pushstring(lua_vm, "texture");
|
||||
lua_gettable(lua_vm, -2);
|
||||
if(!lua_isstring(lua_vm,-1))
|
||||
continue;
|
||||
string texture = lua_tostring(lua_vm,-1);
|
||||
lua_pop(lua_vm, 1);
|
||||
|
||||
lua_pushstring(lua_vm, "hidden");
|
||||
lua_gettable(lua_vm, -2);
|
||||
if(!lua_isboolean(lua_vm,-1))
|
||||
continue;
|
||||
bool hidden = lua_toboolean(lua_vm,-1);
|
||||
lua_pop(lua_vm, 1);
|
||||
|
||||
lua_pushstring(lua_vm, "stable");
|
||||
lua_gettable(lua_vm, -2);
|
||||
if(!lua_isboolean(lua_vm,-1))
|
||||
continue;
|
||||
bool stable = lua_toboolean(lua_vm,-1);
|
||||
lua_pop(lua_vm, 1);
|
||||
|
||||
lua_pushstring(lua_vm, "translucent");
|
||||
lua_gettable(lua_vm, -2);
|
||||
if(!lua_isboolean(lua_vm,-1))
|
||||
continue;
|
||||
bool translucent = lua_toboolean(lua_vm,-1);
|
||||
lua_pop(lua_vm, 1);
|
||||
|
||||
new Node(name, texture, hidden, stable, translucent);
|
||||
Game::log("Registered Node " + name, INFO);
|
||||
}
|
||||
}
|
||||
bool Mods::check_lua(int code){
|
||||
if(code == LUA_OK)
|
||||
return true;
|
||||
else{
|
||||
error(lua_tostring(lua_vm, -1));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
void Mods::error(string text){
|
||||
Game::log("\e[34mlua: \e[0m" + text, ERROR);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef _MODS_H_
|
||||
#define _MODS_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
extern "C"{
|
||||
#include <lua5.3/lua.h>
|
||||
#include <lua5.3/lauxlib.h>
|
||||
#include <lua5.3/lualib.h>
|
||||
}
|
||||
|
||||
class Mods{
|
||||
public:
|
||||
static lua_State *lua_vm;
|
||||
static bool check_lua(int);
|
||||
static void init();
|
||||
static void error(std::string);
|
||||
};
|
||||
#endif
|
|
@ -0,0 +1,44 @@
|
|||
#include <string>
|
||||
#include <stdlib.h>
|
||||
#include <iostream>
|
||||
#include "node.h"
|
||||
#include "game.h"
|
||||
#include "texture.h"
|
||||
using namespace std;
|
||||
|
||||
int Node::count = 0;
|
||||
Node *Node::list[MAXNODES];
|
||||
|
||||
Node::Node(string n, string t, bool h, bool s, bool tr){
|
||||
if (Node::count >= MAXNODES)
|
||||
Game::log("Too many registered Nodes", ERROR);
|
||||
else{
|
||||
name = n;
|
||||
id = Node::count;
|
||||
hidden = h;
|
||||
stable = s;
|
||||
Node::list[id] = this;
|
||||
texture = new Texture(t,tr);
|
||||
Node::count++;
|
||||
}
|
||||
}
|
||||
Node *Node::getNodeById(int id){
|
||||
if(id < count && id > -1)
|
||||
return list[id];
|
||||
return list[0];
|
||||
}
|
||||
Node *Node::getNodeByName(string name){
|
||||
for(int i = 0; i < count; i++){
|
||||
if(list[i]->name == name ){
|
||||
return list[i];
|
||||
}
|
||||
}
|
||||
Game::log("Node "+name+" not found", WARNING);
|
||||
return list[0];
|
||||
}
|
||||
bool Node::operator==(Node *node){
|
||||
return id == node->id;
|
||||
}
|
||||
bool Node::operator==(string n){
|
||||
return name == n;
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef _NODE_H_
|
||||
#define _NODE_H_
|
||||
#include <string>
|
||||
#include "texture.h"
|
||||
#define MAXNODES 1024
|
||||
|
||||
|
||||
class Node{
|
||||
public:
|
||||
int id;
|
||||
std::string name;
|
||||
static Node *getNodeById(int);
|
||||
static Node *getNodeByName(std::string);
|
||||
static Node *list[MAXNODES];
|
||||
static int count;
|
||||
bool operator==(Node *);
|
||||
bool operator==(std::string);
|
||||
Texture *texture;
|
||||
bool hidden;
|
||||
bool stable;
|
||||
bool translucent;
|
||||
Node(std::string, std::string, bool, bool, bool);
|
||||
};
|
||||
#endif
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
#include <GL/freeglut.h>
|
||||
#include <png.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
|
||||
#include "game.h"
|
||||
#include "graphics.h"
|
||||
#include "texture.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
Texture::Texture(string filename, bool t){
|
||||
translucent = t;
|
||||
dummyimage = false;
|
||||
FILE *file = fopen(filename.c_str(), "rb");
|
||||
if(!file){
|
||||
Game::log("Failed to Load Image " + filename + ": File not found. Using a dummy Image.", WARNING);
|
||||
dummyimage = true;
|
||||
return;
|
||||
}
|
||||
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
assert(png);
|
||||
png_infop info = png_create_info_struct(png);
|
||||
assert(info);
|
||||
png_init_io(png, file);
|
||||
png_read_info(png, info);
|
||||
width = png_get_image_width(png, info);
|
||||
height = png_get_image_height(png, info);
|
||||
color_type = png_get_color_type(png, info);
|
||||
bit_depth = png_get_bit_depth(png, info);
|
||||
if(bit_depth == 16)
|
||||
png_set_strip_16(png);
|
||||
if(color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_palette_to_rgb(png);
|
||||
#ifndef _WIN32
|
||||
if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||
png_set_expand_gray_1_2_4_to_8(png);
|
||||
#endif
|
||||
if(png_get_valid(png, info, PNG_INFO_tRNS))
|
||||
png_set_tRNS_to_alpha(png);
|
||||
if(color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
|
||||
if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
png_set_gray_to_rgb(png);
|
||||
png_read_update_info(png, info);
|
||||
row_pointers = (png_bytep*)malloc(sizeof(png_bytep) *height);
|
||||
for(int y = 0; y < height; y++) {
|
||||
row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png,info));
|
||||
}
|
||||
png_read_image(png, row_pointers);
|
||||
fclose(file);
|
||||
png_destroy_read_struct(&png, &info, NULL);
|
||||
}
|
||||
void Texture::draw(int displayX, int displayY, int displayWidth, int displayHeight){
|
||||
if(dummyimage){
|
||||
Graphics::drawRectangle(displayX, displayY, displayWidth, displayHeight, {0, 0, 0});
|
||||
return;
|
||||
}
|
||||
int scaleX = (float)displayWidth/width;
|
||||
int scaleY = (float)displayHeight/height;
|
||||
for(int y = 0; y < height; y++) {
|
||||
png_bytep row = row_pointers[y];
|
||||
for(int x = 0; x < width; x++) {
|
||||
png_bytep px = &(row[x * 4]);
|
||||
if(!translucent || px[0] || px[1] || px[2])
|
||||
Graphics::drawRectangle(x*scaleX + displayX, y*scaleY + displayY, scaleX, scaleY, {(float)px[0]/255, (float)px[1]/255, (float)px[2]/255});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef _TEXTURE_H_
|
||||
#define _TEXTURE_H_
|
||||
|
||||
#include <png.h>
|
||||
#include <string>
|
||||
|
||||
class Texture{
|
||||
public:
|
||||
int width;
|
||||
int height;
|
||||
void draw(int, int, int, int);
|
||||
Texture(std::string, bool);
|
||||
private:
|
||||
png_byte color_type;
|
||||
png_byte bit_depth;
|
||||
png_bytep *row_pointers;
|
||||
bool dummyimage;
|
||||
bool translucent;
|
||||
};
|
||||
#endif
|
|
@ -0,0 +1,57 @@
|
|||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <GL/glut.h>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include "threads.h"
|
||||
#include "graphics.h"
|
||||
#include "game.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
void Threads::startMapBackupThread(){
|
||||
Game::log("Starting Map Backup Thread");
|
||||
pthread_t thread_id;
|
||||
pthread_create(&thread_id, NULL, &mapBackupThread, NULL);
|
||||
}
|
||||
void *Threads::mapBackupThread(void *unused){
|
||||
while(true){
|
||||
sleep(MAP_BACKUP_INTERVAL);
|
||||
Game::map -> save();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void Threads::startGraphicUpdateThread(){
|
||||
Game::log("Starting Graphic Update Thread");
|
||||
pthread_t thread_id;
|
||||
pthread_create(&thread_id, NULL, &graphicUpdateThread, NULL);
|
||||
}
|
||||
void *Threads::graphicUpdateThread(void *unused){
|
||||
while(true){
|
||||
usleep(1);
|
||||
if(glutGetWindow())
|
||||
glutPostRedisplay();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void Threads::addSignalHandlers(){
|
||||
#ifndef _WIN32
|
||||
struct sigaction sa_sigterm;
|
||||
sa_sigterm.sa_handler = &signal_handler;
|
||||
sigaction(SIGTERM, &sa_sigterm, NULL);
|
||||
|
||||
struct sigaction sa_sigint;
|
||||
sa_sigint.sa_handler = &signal_handler;
|
||||
sigaction(SIGINT, &sa_sigint, NULL);
|
||||
#endif
|
||||
}
|
||||
void Threads::signal_handler(int signal_number){
|
||||
#ifndef _WIN32
|
||||
Game::log((string)"Got "+sys_siglist[signal_number]+" Signal, Exiting.");
|
||||
Game::map -> save();
|
||||
exit(0);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef _THREADS_H_
|
||||
#define _THREADS_H_
|
||||
|
||||
#define MAP_BACKUP_INTERVAL 15
|
||||
|
||||
class Threads{
|
||||
public:
|
||||
static void startMapBackupThread();
|
||||
static void addSignalHandlers();
|
||||
static void startGraphicUpdateThread();
|
||||
private:
|
||||
static void *mapBackupThread(void *);
|
||||
static void *graphicUpdateThread(void *);
|
||||
static void signal_handler(int);
|
||||
};
|
||||
#endif
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#include <stdlib.h>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
#include "util.h"
|
||||
#include "game.h"
|
||||
|
||||
using namespace std;
|
||||
int random(int min, int max){
|
||||
return min + rand() % (max - min + 1);
|
||||
}
|
||||
color::color(const char *htmlcolor){
|
||||
unsigned int r, g, b;
|
||||
sscanf(htmlcolor, "#%2x%2x%2x", &r, &g, &b);
|
||||
red = (float) r / 255;
|
||||
green = (float) g / 255;
|
||||
blue = (float) b / 255;
|
||||
}
|
||||
color::color(float r, float g, float b){
|
||||
red = r;
|
||||
green = g;
|
||||
blue = b;
|
||||
}
|
||||
void create_dir_if_not_exists(string d){
|
||||
const char *dir = d.c_str();
|
||||
struct stat dir_exists_st = {0};
|
||||
if(stat(dir, &dir_exists_st) == -1){
|
||||
Game::log((string)dir + " doesn't exist, creating", INFO);
|
||||
#ifdef _WIN32
|
||||
mkdir(dir);
|
||||
#else
|
||||
mkdir(dir, 0700);
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef _UTIL_H_
|
||||
#define _UTIL_H_
|
||||
#include <string>
|
||||
class color{
|
||||
public:
|
||||
float red;
|
||||
float green;
|
||||
float blue;
|
||||
color(const char *);
|
||||
color(float, float, float);
|
||||
};
|
||||
class position{
|
||||
public:
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
int random(int, int);
|
||||
void create_dir_if_not_exists(std::string d);
|
||||
#endif
|
After Width: | Height: | Size: 133 B |
After Width: | Height: | Size: 327 B |
After Width: | Height: | Size: 268 B |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 829 B |
After Width: | Height: | Size: 773 B |
After Width: | Height: | Size: 188 B |
After Width: | Height: | Size: 253 B |
After Width: | Height: | Size: 233 B |
After Width: | Height: | Size: 193 B |
After Width: | Height: | Size: 257 B |
After Width: | Height: | Size: 309 B |