[Add] Rudimentary screenshots.
This commit is contained in:
parent
7dbe3d2598
commit
70c9585302
2
.gitignore
vendored
2
.gitignore
vendored
@ -28,5 +28,5 @@
|
||||
*bin/data
|
||||
*pack
|
||||
*core
|
||||
|
||||
*screenshot.png
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
<Start>
|
||||
<name>Dark Tides</name>
|
||||
<player>
|
||||
<ship>Lancer</ship>
|
||||
<credits>
|
||||
|
70
src/main.c
70
src/main.c
@ -21,8 +21,12 @@
|
||||
#include "pack.h"
|
||||
#include "weapon.h"
|
||||
#include "faction.h"
|
||||
#include "xml.h"
|
||||
#include "pilot.h"
|
||||
|
||||
#define XML_START_ID "Start"
|
||||
#define START_DATA "../dat/start.xml"
|
||||
|
||||
#define CONF_FILE "conf"
|
||||
#define MINIMUM_FPS 0.5
|
||||
|
||||
@ -34,8 +38,10 @@ static int quit = 0; // Primary loop.
|
||||
static unsigned int time = 0; // Calculate FPS and movement.
|
||||
|
||||
// Just some default crap.
|
||||
#define DATA_DEF "data"
|
||||
#define DATA_DEF "data" // Default data pack file.
|
||||
#define DATA_NAME_LEN 25 // Max length of data name.
|
||||
char* data = NULL;
|
||||
char dataname[DATA_NAME_LEN];
|
||||
static int show_fps = 1; // Default - True.
|
||||
static int max_fps = 0;
|
||||
|
||||
@ -43,6 +49,8 @@ static int max_fps = 0;
|
||||
|
||||
static void print_usage(char** argv);
|
||||
static void display_fps(const double dt);
|
||||
static void window_caption(void);
|
||||
static void data_name(void);
|
||||
// Update.
|
||||
static void update_all(void);
|
||||
|
||||
@ -188,13 +196,26 @@ int main(int argc, char** argv) {
|
||||
namjoystick = strdup(optarg);
|
||||
break;
|
||||
case 'v':
|
||||
LOG("Lephisto: version %d.%d.%d\n", VMAJOR, VMINOR, VREV);
|
||||
LOG(APPNAME": version %d.%d.%d", VMAJOR, VMINOR, VREV);
|
||||
case 'h':
|
||||
print_usage(argv);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the data file is valid.
|
||||
if(pack_check(data)) {
|
||||
ERR("Data file '%s'not found", data);
|
||||
WARN("You should specify which data file to use with '-d'");
|
||||
WARN("See -h or --help for more information.");
|
||||
SDL_Quit();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
data_name(); // Loads the data's name and friends.
|
||||
LOG(" %s", dataname);
|
||||
DEBUG();
|
||||
|
||||
// Random numbers.
|
||||
rng_init();
|
||||
|
||||
@ -214,11 +235,10 @@ int main(int argc, char** argv) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Window.
|
||||
SDL_WM_SetCaption(APPNAME, NULL);
|
||||
window_caption();
|
||||
|
||||
// Input.
|
||||
if(indjoystick >= 0 || namjoystick != NULL) {
|
||||
if((indjoystick >= 0) || (namjoystick != NULL)) {
|
||||
if(joystick_init())
|
||||
WARN("Error initializing joystick input");
|
||||
if(namjoystick != NULL) {
|
||||
@ -307,7 +327,7 @@ int main(int argc, char** argv) {
|
||||
// ========================================================
|
||||
static double fps_dt = 1.;
|
||||
static void update_all(void) {
|
||||
// dt in us.
|
||||
// dt in ms/1000.
|
||||
double dt = (double)(SDL_GetTicks() - time) / 1000.;
|
||||
time = SDL_GetTicks();
|
||||
|
||||
@ -319,7 +339,7 @@ static void update_all(void) {
|
||||
return;
|
||||
}
|
||||
// If FPS is limited.
|
||||
else if(max_fps != 0 && dt < 1./max_fps) {
|
||||
else if((max_fps != 0) && (dt < 1./max_fps)) {
|
||||
double delay = 1./max_fps - dt;
|
||||
SDL_Delay(delay);
|
||||
fps_dt += delay; // Make sure it displays the propper FPS.
|
||||
@ -351,6 +371,7 @@ static void display_fps(const double dt) {
|
||||
fps_dt += dt;
|
||||
fps_cur += 1.;
|
||||
if(fps_dt > 1.) {
|
||||
// Recalculate every second.
|
||||
fps = fps_cur / fps_dt;
|
||||
fps_dt = fps_cur = 0.;
|
||||
}
|
||||
@ -360,3 +381,38 @@ static void display_fps(const double dt) {
|
||||
gl_print(NULL, &pos, NULL, "%3.2f", fps);
|
||||
}
|
||||
|
||||
static void data_name(void) {
|
||||
uint32_t bufsize;
|
||||
char* buf = pack_readfile(DATA, START_DATA, &bufsize);
|
||||
|
||||
xmlNodePtr node;
|
||||
xmlDocPtr doc = xmlParseMemory(buf, bufsize);
|
||||
|
||||
node = doc->xmlChildrenNode;
|
||||
if(!xml_isNode(node, XML_START_ID)) {
|
||||
ERR("Maformed '"START_DATA"' file: missing root element '"XML_START_ID"'");
|
||||
return;
|
||||
}
|
||||
|
||||
node = node->xmlChildrenNode; // First node.
|
||||
if(node == NULL) {
|
||||
ERR("Malformed '"START_DATA"' file: does not contain elements");
|
||||
return;
|
||||
}
|
||||
do {
|
||||
if(xml_isNode(node, "name"))
|
||||
strncpy(dataname, xml_get(node), DATA_NAME_LEN);
|
||||
} while((node = node->next));
|
||||
|
||||
xmlFreeDoc(doc);
|
||||
free(buf);
|
||||
xmlCleanupParser();
|
||||
}
|
||||
|
||||
static void window_caption(void) {
|
||||
char tmp[DATA_NAME_LEN+10];
|
||||
|
||||
snprintf(tmp, DATA_NAME_LEN+10, APPNAME" - %s", dataname);
|
||||
SDL_WM_SetCaption(tmp, NULL);
|
||||
}
|
||||
|
||||
|
56
src/opengl.c
56
src/opengl.c
@ -1,5 +1,6 @@
|
||||
#include <SDL.h>
|
||||
#include <SDL_image.h>
|
||||
#include <png.h>
|
||||
#include <ft2build.h>
|
||||
#include <freetype/freetype.h>
|
||||
#include <freetype/ftglyph.h>
|
||||
@ -43,6 +44,8 @@ static int pot(int n);
|
||||
static GLuint gl_loadSurface(SDL_Surface* surface, int* rw, int* rh);
|
||||
// Gl font.
|
||||
static void gl_fontMakeDList(FT_Face face, char ch, GLuint list_base, GLuint* tex_base, int* width_base);
|
||||
// PNG.
|
||||
int write_png(const char* file_name, png_bytep* rows, int w, int h, int colortype, int bitdepth);
|
||||
|
||||
// ================
|
||||
// MISC!
|
||||
@ -133,6 +136,19 @@ static uint8_t* SDL_MapTrans(SDL_Surface* s) {
|
||||
return t;
|
||||
}
|
||||
|
||||
// Take a screenshot.
|
||||
void gl_screenshot(const char* filename) {
|
||||
SDL_Surface* screen = SDL_GetVideoSurface();
|
||||
unsigned rowbytes = screen->w * 4;
|
||||
unsigned char screenbuf[screen->h][rowbytes], *rows[screen->h];
|
||||
int i;
|
||||
|
||||
glReadPixels(0, 0, screen->w, screen->h, GL_RGBA, GL_UNSIGNED_BYTE, screenbuf);
|
||||
|
||||
for(i = 0; i < screen->h; i++) rows[i] = screenbuf[screen->h - i - 1];
|
||||
write_png(filename, rows, screen->w, screen->h, PNG_COLOR_TYPE_RGBA, 8);
|
||||
}
|
||||
|
||||
// ================
|
||||
// TEXTURE!
|
||||
// ================
|
||||
@ -708,3 +724,43 @@ void gl_exit(void) {
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
// Saves a png.
|
||||
int write_png(const char* file_name, png_bytep* rows, int w, int h, int colortype, int bitdepth) {
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
FILE* fp = NULL;
|
||||
char* doing = "Open for writing";
|
||||
|
||||
if(!(fp = fopen(file_name, "wb"))) goto fail;
|
||||
|
||||
doing = "Create png write struct";
|
||||
if(!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) goto fail;
|
||||
|
||||
doing = "Create png info struct";
|
||||
if(!(info_ptr = png_create_info_struct(png_ptr))) goto fail;
|
||||
if(setjmp(png_jmpbuf(png_ptr))) goto fail;
|
||||
|
||||
doing = "Init IO";
|
||||
png_init_io(png_ptr, fp);
|
||||
png_set_IHDR(png_ptr, info_ptr, w, h, bitdepth, colortype, PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
||||
|
||||
doing = "Write info";
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
|
||||
doing = "Write image";
|
||||
png_write_image(png_ptr, rows);
|
||||
|
||||
doing = "Write end";
|
||||
png_write_end(png_ptr, NULL);
|
||||
|
||||
doing = "Closing file";
|
||||
if(0 != fclose(fp)) goto fail;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
WARN("write_png: Could not %s", doing);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -83,4 +83,5 @@ void gl_exit(void);
|
||||
// Misc.
|
||||
int gl_isTrans(const gl_texture* t, const int x, const int y);
|
||||
void gl_getSpriteFromDir(int* x, int* y, const gl_texture* t, const double dir);
|
||||
void gl_screenshot(const char* filename);
|
||||
|
||||
|
61
src/player.c
61
src/player.c
@ -20,7 +20,7 @@
|
||||
|
||||
#define START_DATA "../dat/start.xml"
|
||||
|
||||
#define POW2(x) ((x)*(x))
|
||||
#define pow2(x) ((x)*(x))
|
||||
|
||||
#define GFX_GUI_FRAME "../gfx/gui/frame.png"
|
||||
#define GFX_GUI_TARG_PILOT "../gfx/gui/pilot.png"
|
||||
@ -38,8 +38,9 @@ typedef struct {
|
||||
} Keybind;
|
||||
static Keybind** player_input; // Contains the players keybindings.
|
||||
// Name of each keybinding.
|
||||
const char* keybindNames[] = { "accel", "left", "right", "primary", "target",
|
||||
"target_nearest", "mapzoomin", "mapzoomout", "end" }; // Need to terminate in "end".
|
||||
const char* keybindNames[] = { "accel", "left", "right", // Movement.
|
||||
"primary", "target", "target_nearest", "board", // Combat.
|
||||
"mapzoomin", "mapzoomout", "screenshot", "end" }; // Misc.
|
||||
|
||||
// Player stuff.
|
||||
Pilot* player = NULL; // extern in pilot.h
|
||||
@ -138,6 +139,9 @@ static int gui_parse(const xmlNodePtr parent, const char* name);
|
||||
static void gui_renderPilot(const Pilot* p);
|
||||
static void gui_renderBar(const glColor* c, const Vec2* p, const Rect* r, const double w);
|
||||
|
||||
static void player_board(void);
|
||||
static void player_screenshot(void);
|
||||
|
||||
// Create a new player.
|
||||
void player_new(void) {
|
||||
Ship* ship;
|
||||
@ -529,28 +533,28 @@ static void rect_parse(const xmlNodePtr parent, double* x, double* y, double* w,
|
||||
do {
|
||||
if(xml_isNode(cur, "x")) {
|
||||
if(x != NULL) {
|
||||
*x = (double)atoi((char*)cur->children->content);
|
||||
*x = xml_getFloat(cur);
|
||||
param |= (1<<0);
|
||||
} else
|
||||
WARN("Extra parameter 'x' found for GUI node '%s'", parent->name);
|
||||
}
|
||||
else if(xml_isNode(cur, "y")) {
|
||||
if(y != NULL) {
|
||||
*y = (double)atoi((char*)cur->children->content);
|
||||
*y = xml_getFloat(cur);
|
||||
param |= (1<<1);
|
||||
} else
|
||||
WARN("Extra parameter 'y' found for GUI node '%s'", parent->name);
|
||||
}
|
||||
else if(xml_isNode(cur, "w")) {
|
||||
if(w != NULL) {
|
||||
*w = (double)atoi((char*)cur->children->content);
|
||||
*w = xml_getFloat(cur);
|
||||
param |= (1<<2);
|
||||
} else
|
||||
WARN("Extra parameter 'w' found for GUI node '%s'", parent->name);
|
||||
}
|
||||
else if(xml_isNode(cur, "h")) {
|
||||
if(h != NULL) {
|
||||
*h = (double)atoi((char*)cur->children->content);
|
||||
*h = xml_getFloat(cur);
|
||||
param |= (1<<3);
|
||||
} else
|
||||
WARN("Extra parameter 'h' found for GUI node '%s'", parent->name);
|
||||
@ -736,6 +740,40 @@ void player_think(Pilot* player) {
|
||||
vect_pset(&player->solid->force, player->ship->thrust * player_acc, player->solid->dir);
|
||||
}
|
||||
|
||||
void player_board(void) {
|
||||
Pilot* p;
|
||||
|
||||
if(player_target == PLAYER_ID) {
|
||||
player_message("You need a target to board first!");
|
||||
return;
|
||||
}
|
||||
p = pilot_get(player_target);
|
||||
|
||||
if(!pilot_isFlag(p, PILOT_DISABLED)) {
|
||||
player_message("You cannot board a ship that isn't disabled!");
|
||||
return;
|
||||
}
|
||||
if(vect_dist(&player->solid->pos, &p->solid->pos) > p->ship->gfx_space->sw * PILOT_SIZE_APROX) {
|
||||
player_message("You are too far away to board your target");
|
||||
return;
|
||||
}
|
||||
if((pow2(VX(player->solid->vel)-VX(p->solid->vel)) +
|
||||
pow2(VY(player->solid->vel)-VY(p->solid->vel))) > (double)pow2(MAX_HYPERSPACE_VEL)) {
|
||||
|
||||
player_message("You are going too fact to board the ship");
|
||||
return;
|
||||
}
|
||||
player_message("Ship boarding isn't implemented yet! HAHA");
|
||||
}
|
||||
|
||||
// Take a screenshot.
|
||||
static void player_screenshot(void) {
|
||||
char filename[20];
|
||||
// TODO not overwirte old screenshots.
|
||||
strncpy(filename, "screenshot.png", 20);
|
||||
gl_screenshot(filename);
|
||||
}
|
||||
|
||||
// ================
|
||||
// INPUT!
|
||||
// ================
|
||||
@ -748,8 +786,10 @@ void input_setDefault(void) {
|
||||
input_setKeybind("primary", KEYBIND_KEYBOARD, SDLK_SPACE, 0);
|
||||
input_setKeybind("target", KEYBIND_KEYBOARD, SDLK_TAB, 0);
|
||||
input_setKeybind("target_nearest", KEYBIND_KEYBOARD, SDLK_r, 0);
|
||||
input_setKeybind("board", KEYBIND_KEYBOARD, SDLK_b, 0);
|
||||
input_setKeybind("mapzoomin", KEYBIND_KEYBOARD, SDLK_UP, 0);
|
||||
input_setKeybind("mapzoomout", KEYBIND_KEYBOARD, SDLK_DOWN, 0);
|
||||
input_setKeybind("screenshot", KEYBIND_KEYBOARD, SDLK_F12, 0);
|
||||
}
|
||||
|
||||
// Initialization/exit functions (does not assign keys).
|
||||
@ -820,6 +860,10 @@ static void input_key(int keynum, double value, int abs) {
|
||||
else if(strcmp(player_input[keynum]->name, "target_nearest")==0) {
|
||||
if(value == KEY_PRESS) player_target = pilot_getHostile();
|
||||
}
|
||||
// Board those ships.
|
||||
else if(strcmp(player_input[keynum]->name, "board")==0) {
|
||||
if(value == KEY_PRESS) player_board();
|
||||
}
|
||||
// Zoom in.
|
||||
else if(strcmp(player_input[keynum]->name, "mapzoomin")==0) {
|
||||
if(value == KEY_PRESS && gui.radar.res < RADAR_RES_MAX)
|
||||
@ -830,6 +874,9 @@ static void input_key(int keynum, double value, int abs) {
|
||||
if(value == KEY_PRESS && gui.radar.res > RADAR_RES_MIN)
|
||||
gui.radar.res -= RADAR_RES_INTERVAL;
|
||||
}
|
||||
else if(strcmp(player_input[keynum]->name, "screenshot")==0) {
|
||||
if(value == KEY_PRESS) player_screenshot();
|
||||
}
|
||||
|
||||
//Make sure values are sane.
|
||||
player_acc = ABS(player_acc);
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "pilot.h"
|
||||
|
||||
#define MIN_HYPERSPACE_DIST 1500
|
||||
#define MAX_HYPERSPACE_VEL 3
|
||||
#define MAX_HYPERSPACE_VEL 10
|
||||
|
||||
// Planet types. I didn't take them from Star Trek, I promise.
|
||||
typedef enum {
|
||||
|
Loading…
Reference in New Issue
Block a user