Better mapconv

This commit is contained in:
mibi88 2023-05-28 16:33:03 +02:00
parent ed274c34da
commit f57183357a
8 changed files with 343 additions and 98 deletions

View File

@ -14,16 +14,44 @@ typedef struct {
int tw, th; /* Tile width and height */
int px, py; /* Contains the position of the player on the screen, after
drawing the map */
int pw, ph; /* Player height and width. */
int sx, sy; /* Where the map started to be drawn. */
int padx, pady; /* Where the map was drawn on the screen. */
int sw, sh; /* The size of the part that was drawn on screen. */
} MMap;
/* Prototypes */
/* void dmap(int sx, int sy, MMap *map);
/* void vmap(int padx, int pady, int w, int h, int sx, int sy, MMap *map);
Draws a map contained in a MMap struct.
dmap draw the map from sx, sy.
dmap draw the map from sx, sy, at padx, pady on the screen with width w and
height h on screen.
The map should be the first thing to be drawn, because the map is not perfectly
drawn at (padx, pady), and vplayer and vitem use some variables that are updated
when calling vmap.
*/
void vmap(int sx, int sy, MMap *map);
void vmap(int padx, int pady, int w, int h, int sx, int sy, MMap *map);
/* void vplayer(MMap *map, unsigned char **player_sprites, int anim_frame);
Draws the player on map map, from the sprite coder image in the image table at
anim frame.
*/
void vplayer(MMap *map, unsigned char **player_sprites, int anim_frame);
/* void vitem(MMap *map, int x, int y, int w, int h, unsigned char **item,
int anim_frame);
Draws an item at the position (x, y) on the map on the screen.
item is the sprite coder sprite table that contains the diffrent frames of the
animation of this item.
anim_frame is the frame of the animation of item that should be drawn.
*/
void vitem(MMap *map, int x, int y, int w, int h, unsigned char **item,
int anim_frame);
#endif

View File

@ -2,7 +2,7 @@
#include "../../../include/microfx/ext/img.h"
#include "../../../include/microfx/microfx.h"
void vmap(int sx, int sy, MMap *map) {
void vmap(int padx, int pady, int w, int h, int sx, int sy, MMap *map) {
/* Dessine la map à l'écran. */
/* x et y contiendront la position à laquelle je suis dans la boucle. */
int x, y;
@ -12,53 +12,76 @@ void vmap(int sx, int sy, MMap *map) {
/* mx contient le nombre de pixels qui seront cachés sur x, pareil pour
y. */
int mx = sx-tx*map->tw, my = sy-ty*map->th;
/* dw et dh contiennent le nombre de tuiles à dessiner sur x et y. */
int dw = w/map->tw+1, dh = h/map->th+1;
/* mw et mh contiennent la largeur et la hauteur de la map. */
int mw = map->w*map->tw, mh = map->h*map->th;
/* tile contient la tuile à dessiner */
unsigned char tile;
/* J'ajuste sx. */
if(sx-SWIDTH/2<0){
if(sx<w/2){
/* Si je ne peux pas centrer le joueur car je suis trop proche du bord
gauche de la map. */
map->px = sx;
sx = 0;
}else if(sx+SWIDTH/2>map->w*map->tw){
}else if(sx+w/2>mw){
/* Si je ne peux pas centrer le joueur car je suis trop proche du bord
droit de la map. */
map->px = sx-(map->w*map->tw-SWIDTH/2);
sx = map->w*map->tw-SWIDTH/2;
map->px = sx-(mw-w/2);
sx = mw-w/2;
}else{
/* Sinon je peux centrer le joueur. */
sx = sx-SWIDTH/2;
map->px = SWIDTH/2;
sx = sx-w/2;
map->px = w/2;
}
/* J'ajuste sy. */
if(sy-SHEIGHT/2<0){
if(sy<h/2){
/* Si je ne peux pas centrer le joueur car je suis trop proche du haut
de la map. */
map->py = sy;
sy = 0;
}else if(sy+SHEIGHT/2>map->h*map->th){
}else if(sy+h/2>mh){
/* Si je ne peux pas centrer le joueur car je suis trop proche du bas de
la map. */
map->py = sy-(map->h*map->th-SHEIGHT/2);
sy = map->h*map->th-SHEIGHT/2;
map->py = sy-(mh-h/2);
sy = mh-h/2;
}else{
/* Sinon je peux centrer le joueur. */
sy = sy-SHEIGHT/2;
map->py = SHEIGHT/2;
sy = sy-h/2;
map->py = h/2;
}
tx = sx/map->tw;
ty = sy/map->th;
for(y=0;y<map->h;y++){
for(x=0;x<map->w;x++){
for(y=0;y<dh;y++){
for(x=0;x<dw;x++){
/* Je récupère la tuile dans map et je la dessine si tx+x est plus
petit que la largeur de la map. */
if(tx+x < map->w){
if(tx+x>=0 && tx+x < map->w && ty+y>=0 && ty+y < map->h){
tile = map->map[(ty+y)*map->w+tx+x];
if(tile > 0){
simage(x*map->tw-mx, y*map->th-my, map->tw, map->th,
map->tileset[(int)tile-1], SNORMAL);
simage(x*map->tw-mx+padx, y*map->th-my+pady, map->tw,
map->th, map->tileset[(int)tile-1], SNORMAL);
}
}
}
}
map->sx = sx;
map->sy = sy;
map->sw = w;
map->sh = h;
map->padx = padx;
map->pady = pady;
}
void vplayer(MMap *map, unsigned char **player_sprites, int anim_frame) {
simage(map->px, map->py, map->pw, map->ph, player_sprites[anim_frame],
SNORMAL);
}
void vitem(MMap *map, int x, int y, int w, int h, unsigned char **item,
int anim_frame) {
int dx = x-map->sx, dy = y-map->sy;
if(dx+w>=0 && dx<map->sw && dy+h>=0 && dy<map->sh) {
simage(dx, dy, w, h, item[anim_frame], SNORMAL);
}
}

Binary file not shown.

View File

@ -1,15 +1,18 @@
NAME = mapconv
SRC = src/main.c
SRC = src/main.c \
src/parse.c
OBJ = $(SRC:src/%=build/%.o)
BUILD = build
CFLAGS = -Wall -Wextra -Wpedantic
all: $(OBJ)
$(CC) $(OBJ) -o $(NAME)
$(OBJ): $(SRC) | $(BUILD)/
$(CC) -c $< -o $@ -Os -Iinc -std=c89
$(BUILD)/%.o: src/% | $(BUILD)/
$(CC) -c $< -o $@ -Os -Iinc -std=c89 $(CFLAGS)
.PRECIOUS: %/

View File

@ -5,18 +5,6 @@ const char help[] = "mapconv - Microfx map creator\n\n"
"This little tool makes it easier to create maps for the Microfx gametools ext."
"\n"
"Use :\n"
" mapconv map.txt conf.txt map.h\n"
"map.txt should contain a map made out of ASCII characters. Each line in the\n"
"map.txt file should represent one line in the map.\n"
"conf.txt should contain the map width, on the next line the height and then,\n"
"after, the number of the tile followed by a space and her ASCII character like"
"\n"
"this :\n"
" 1 #\n"
"The last argument is the header file that will be generated. You'll just need"
"\n"
"to modify it to add some informations into the MMap struct before using it in"
"\n"
"your game.";
" mapconv conf.txt\n";
#endif

31
tools/mapconv/inc/parse.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef PARSE_H
#define PARSE_H
#define TOKEN_SZ 64
typedef enum {
T_GROUP,
T_NAME,
T_CHAR,
T_STRING,
T_INT
} Token;
typedef struct {
Token token;
char content[TOKEN_SZ];
} Tokendata;
typedef enum {
FALSE,
TRUE
} bool;
int parse(char *content, Tokendata **data);
int search_token(Token token, char *content, Tokendata *tokens, int token_d_sz);
int get_value_from_name(Token value_type, char *value, Tokendata *tokens,
int token_d_sz);
int get_value_from_name_noerror(Token value_type, char *value,
Tokendata *tokens, int token_d_sz);
#endif

View File

@ -2,65 +2,27 @@
#include <stdio.h>
#include <string.h>
#include <help.h>
#include <ctype.h>
void grabint(char *data, int size, int *start, char stop, int *out) {
int i;
*out=0;
for(i=0;*start<size-1;i++){
if(data[*start] == stop) break;
(*out) += data[*start] - 48;
if(data[(*start)+1] != stop) (*out) *= 10;
(*start)++;
}
(*start)++;
}
#include <parse.h>
int main(int argc, char **argv) {
FILE *fp;
FILE *fp_map;
size_t size;
char tile[256];
int i, n, oldn, a, len;
int w, h;
if(argc < 4){
char tiles[256];
int i, a, len, out;
int w, h, pw, ph, tw, th, padx, pady, dw, dh;
bool found;
Tokendata *tokens = NULL;
char buffer[TOKEN_SZ], c;
char *data = NULL;
int amount;
if(argc < 2){
puts(help);
return 1;
}
char *data = NULL;
fp = fopen(argv[2], "rb");
if(fp == NULL){
printf("[mapconv] Can't open \"%s\"\n", argv[2]);
return 2;
}
fseek(fp, 0L, SEEK_END);
size = ftell(fp);
rewind(fp);
data = malloc(sizeof(unsigned char) * size);
if(data == NULL){
puts("[mapconv] More memory needed !");
return 3;
}
if(!fread(data, 1, sizeof(unsigned char) * size, fp)){
fclose(fp);
return;
}
fclose(fp);
/* Get the width and the height */
n=0;
grabint(data, size, &n, '\n', &w);
grabint(data, size, &n, '\n', &h);
oldn = n;
len = 0;
for(i=0;i<256 && n<size-1;i++){
if(data[n] == '\n') break;
grabint(data, size, &n, ' ', (int *)&tile[i]);
i++;
tile[i] = data[n];
n+=2;
len++;
}
free(data);
/* Make the map */
/* Loading config */
fp = fopen(argv[1], "rb");
if(fp == NULL){
printf("[mapconv] Can't open \"%s\"\n", argv[1]);
@ -71,31 +33,121 @@ int main(int argc, char **argv) {
rewind(fp);
data = malloc(sizeof(unsigned char) * size);
if(data == NULL){
puts("[mapconv] More memory needed !");
puts("[mapconv] More memory needed!");
return 3;
}
if(!fread(data, 1, sizeof(unsigned char) * size, fp)){
fclose(fp);
return;
return 4;
}
fclose(fp);
fp_map = fopen(argv[3], "w");
fputs("#ifndef MAP_H\n#define MAP_H\n\n#include \"TILESET.h\"\n"
"#include <microfx/ext/gametools.h>\n\n"
"const unsigned char _map[] = {", fp_map);
for(i=0;i<size;i++){
puts("[status] Parsing config ...");
out = parse(data, &tokens);
if(out < 0){
puts("[mapconv] Error when parsing config!");
return -1;
}
puts("[status] Parsing config successful!");
/* TODO the following lines are really dirty */
/* Get the width and the height */
i=get_value_from_name(T_INT, "width", tokens, out);
w = atoi(tokens[i].content);
i=get_value_from_name(T_INT, "height", tokens, out);
h=atoi(tokens[i].content);
len=0;
puts("[status] Getting tile numbers.");
for(i=0;i<256;i++){
sprintf(buffer, "t%d", i);
a = get_value_from_name_noerror(T_CHAR, buffer, tokens, out);
if(a<0) break;
tiles[i] = tokens[a].content[0];
len++;
}
free(data);
/* Make the map */
puts("[status] Reading map.");
i=get_value_from_name(T_STRING, "input", tokens, out);
fp = fopen(tokens[i].content, "rb");
if(fp == NULL){
printf("[mapconv] Can't open \"%s\"\n", tokens[i].content);
return 2;
}
fseek(fp, 0L, SEEK_END);
size = ftell(fp);
rewind(fp);
data = malloc(sizeof(unsigned char) * size);
if(data == NULL){
puts("[mapconv] More memory needed!");
return 3;
}
if(!fread(data, 1, sizeof(unsigned char) * size, fp)){
fclose(fp);
return 4;
}
fclose(fp);
i=get_value_from_name(T_STRING, "output", tokens, out);
fp_map = fopen(tokens[i].content, "w");
if(fp == NULL){
printf("[mapconv] Can't open \"%s\"\n", tokens[i].content);
return 2;
}
a=get_value_from_name(T_STRING, "mapname", tokens, out);
for(i=0;i<(int)strlen(tokens[a].content);i++){
c = tokens[a].content[i];
if((c >= 0x30 && c <= 0x39) || (c >= 0x41 && c <= 0x5A) ||
(c >= 0x61 && c <= 0x7A)){
buffer[i] = toupper(c);
}else{
buffer[i] = '_';
}
}
puts("[status] Generating header.");
i=get_value_from_name(T_STRING, "tileset_header", tokens, out);
fprintf(fp_map, "#ifndef %s_H\n#define %s_H\n\n#include <%s>\n"
"#include <microfx/ext/gametools.h>\n\nconst unsigned char _%s[] = {",
buffer, buffer, tokens[i].content, tokens[a].content);
amount = 0;
for(i=0;i<(int)size;i++){
if(data[i] != '\n'){
found = FALSE;
for(a=0;a<len;a++){
if(tile[a*2+1] == data[i]) fprintf(fp_map, "%d, ", tile[a*2]);
if(tiles[a] == data[i]){
fprintf(fp_map, "%d, ", a);
found = TRUE;
amount++;
}
}
if(!found){
printf("[mapconv] Tile number of '%c' not found\n", data[i]);
return 5;
}
}
}
if(amount!=w*h){
printf("[warning] %d tiles written instead of %d*%d=%d\n", amount, w, h,
w*h);
}
fseek(fp_map, -2L, SEEK_CUR);
fputs("};", fp_map);
fprintf(fp_map, "\n\nMMap map = {(unsigned char *)_map, (unsigned char **)"
"TILESET_HERE, %d, %d, TILEWIDTH_HERE, TILEHEIGHT_HERE, 0, 0};\n\n#endif\n",
w, h);
i=get_value_from_name(T_STRING, "tileset_name", tokens, out);
tw=get_value_from_name(T_INT, "tilewidth", tokens, out);
th=get_value_from_name(T_INT, "tileheight", tokens, out);
pw=get_value_from_name(T_INT, "playerwidth", tokens, out);
ph=get_value_from_name(T_INT, "playerheight", tokens, out);
padx=get_value_from_name(T_INT, "drawingzone_x", tokens, out);
pady=get_value_from_name(T_INT, "drawingzone_y", tokens, out);
dw=get_value_from_name(T_INT, "drawingzone_w", tokens, out);
dh=get_value_from_name(T_INT, "drawingzone_h", tokens, out);
fprintf(fp_map, "\n\nMMap %s = {(unsigned char *)_%s, (unsigned char **)"
"%s, %d, %d, %s, %s, 0, 0, %s, %s, 0, 0, %s, %s, %s, %s};\n\n#endif\n",
tokens[a].content, tokens[a].content, tokens[i].content, w, h,
tokens[tw].content, tokens[th].content, tokens[pw].content,
tokens[ph].content, tokens[padx].content, tokens[pady].content,
tokens[dw].content, tokens[dh].content);
/* TODO end */
fclose(fp_map);
free(data);
puts("[status] Generating done! You can now use the generated header "
"file.");
return 0;
}

120
tools/mapconv/src/parse.c Normal file
View File

@ -0,0 +1,120 @@
#include <parse.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int parse(char *content, Tokendata **data) {
int i, current_token_pos = 0;
bool token_started = FALSE;
char c;
char current_token[TOKEN_SZ];
Token current_token_type;
int token_num = 0;
for(i=0;i<(int)strlen(content);i++){
c = content[i];
if(!token_started && c != ' '){
token_started = TRUE;
switch(c){
case '\'':
current_token_type = T_CHAR;
break;
case '"':
current_token_type = T_STRING;
break;
case '-':
current_token_type = T_GROUP;
break;
default:
current_token_type = T_NAME;
}
if(c >= 0x30 && c <= 0x39){
current_token_type = T_INT;
}
}
if(token_started){
if(c != ' ' || (current_token_type == T_STRING ||
current_token_type == T_CHAR)){
/* TODO : the following condition should be changed, to allow
'"', '\'' and '-' in chars, strings, names, groups ... */
if(current_token_pos < TOKEN_SZ && (c != '"' && c != '\'' &&
c != '=' && c != '-' && c != '\n')){
current_token[current_token_pos] = c;
current_token_pos++;
}else if(current_token_pos >= TOKEN_SZ){
puts("[config] Too big token !");
return -2;
}
}
if(((c == '=' && current_token_type == T_NAME) ||
c == '\n') && strlen(current_token) > 0){
(*data) = realloc((*data), (token_num+1)*sizeof(Tokendata));
if(!(*data)){
puts("[config] More memory needed !");
return -1;
}
(*data)[token_num].token = current_token_type;
strcpy((*data)[token_num].content, current_token);
memset(current_token, '\0', TOKEN_SZ);
current_token_pos = 0;
token_started = FALSE;
token_num++;
}
}
}
if(current_token_pos > 0){
(*data) = realloc((*data), (token_num+1)*sizeof(Tokendata));
if(!(*data)){
puts("[config] More memory needed !");
return -1;
}
(*data)[token_num].token = current_token_type;
strcpy((*data)[token_num].content, current_token);
}
return token_num;
}
int search_token(Token token, char *content, Tokendata *tokens,
int token_d_sz) {
int i;
for(i=0;i<token_d_sz;i++){
if(tokens[i].token == token && !strcmp(tokens[i].content, content)){
return i;
}
}
return -1;
}
int get_value_from_name(Token value_type, char *value, Tokendata *tokens,
int token_d_sz) {
int i;
i=search_token(T_NAME, value, tokens, token_d_sz);
if(i<0){
printf("[config] Can't get \"%s\" value !\n", value);
exit(-2);
}
if(i+1 >= token_d_sz){
printf("[config] Can't get \"%s\" value, value not existing ! !\n",
value);
exit(-2);
}
if(tokens[i+1].token != value_type){
printf("[config] Bad type for \"%s\" value !\n", value);
exit(-2);
}
return i+1;
}
int get_value_from_name_noerror(Token value_type, char *value,
Tokendata *tokens, int token_d_sz) {
int i;
i=search_token(T_NAME, value, tokens, token_d_sz);
if(i<0 || i+1 >= token_d_sz){
return -1;
}
if(tokens[i+1].token != value_type){
return -1;
}
return i+1;
}