ratcatcher/edit.c

579 lines
12 KiB
C
Raw Normal View History

2008-09-16 12:40:09 +10:00
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <math.h>
#include <SDL.h>
#include <SDL_keysym.h>
#include <SDL_rotozoom.h>
#include <SDL_ttf.h>
#include <SDL_framerate.h>
#include "defs.h"
#include "shared.h"
#include "edit.h"
2008-09-16 12:40:09 +10:00
/* these hold the currently selected sprite/tile types */
2008-09-16 12:40:09 +10:00
tiletype_t *seltile = NULL;
int selsprite = -1;
int modified = B_FALSE; // has the current level been modified since last save?
2008-09-16 12:40:09 +10:00
int curworld = 1;
int curlevelnum;
int main (int argc, char **argv) {
Uint8 *keys;
char filename[BUFLEN];
int i;
int mb,mx,my;
curlevelnum = 1;
/* handle arguments */
if (argc >= 2) {
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-fs")) {
printf("Fullscreen mode enabled.\n");
vidargs |= SDL_FULLSCREEN;
} else if (!strcmp(argv[i], "-l")) {
if (++i >= argc) {
printf("Missing level number.\n");
usage();
exit(1);
}
curlevelnum = atoi(argv[i]);
printf("Skipping to level %d.\n",curlevelnum);
} else {
usage();
exit(1);
}
}
}
/* initialise */
initglobals();
2008-09-16 12:40:09 +10:00
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE)==-1) {
printf("SDL_Init: %s\n", SDL_GetError());
exit(1);
}
atexit(cleanup);
#ifdef OPENGL
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
screen = SDL_SetVideoMode(EDITORW,EDITORH,16,SDL_OPENGLBLIT|vidargs);
#else
screen = SDL_SetVideoMode(EDITORW,EDITORH,16,SDL_SWSURFACE|SDL_DOUBLEBUF|vidargs);
#endif
if (loadimagesets()) {
return 1;
}
fakeblock.id = T_LAND;
strcpy(fakeblock.name,"Fake");
for (i = 0; i < TILEW; i++) {
fakeblock.lowness[i] = 0;
}
fakeblock.solid = S_SOLID;
fakeblock.img[0] = IMG_Load("land.bmp");
fakeblock.numframes = 1;
2008-09-16 12:40:09 +10:00
fakeblock.next = NULL;
fakeblock.prev = NULL;
/* load fonts */
TTF_Init();
sprintf(filename, "verdana.ttf");
for (i = 1; i < MAXLETTERHEIGHT; i++) {
font[i] = TTF_OpenFont(filename,i);
if (!font[i]) {
printf("Error opening font: %s\n", TTF_GetError());
return 1;
}
}
if (loadlevel(curworld,curlevelnum)) {
return 1;
}
modified = B_FALSE;
2008-09-16 12:40:09 +10:00
seltile = tiletype;
draweditorlevel();
2008-09-16 12:40:09 +10:00
drawpalette();
drawsprites();
flip();
timer = 0;
//player->invuln = INVULNTIME;
//player->score = 0;
2008-09-16 12:40:09 +10:00
while (1) {
/* check for mouse actions */
mb = SDL_GetMouseState(&mx,&my);
if (mb & SDL_BUTTON(1)) { // lmb
if ((mx >= PALX) && (my < SPALY)) { // over tile palette
tiletype_t *tt;
int x = PALX,y = PALY;
seltile = NULL;
/* get tile number */
for (tt = tiletype; tt != NULL; tt = tt->next) {
// is mouse over this one?
if ((mx >= x) && (my >= y) && (mx <= x+TILEW-1) && (my <= y+TILEH-1)) {
seltile = tt;
selsprite = -1;
break;
} else {
// check next one
x += TILEW;
if (x >= EDITORW) {
x = PALX;
y += TILEH;
}
}
}
// redraw palette with new selection
drawpalette();
} else if ((mx >= PALX) && (my > SPALY)) { // over sprite palette
int p;
int x = SPALX, y = SPALY;
int maxh = 0;
/* get sprite id */
selsprite = -1;
for (p = 0; p < MAXPTYPES; p++) {
SDL_Surface *firstimg;
int w,h;
/* select images */
firstimg = imageset[p].img[F_WALK1];
w = firstimg->w;
h = firstimg->h;
if (h > maxh) maxh = h;
// is mouse over it?
if ((mx >= x) && (my >= y) && (mx <= x+w-1) && (my <= y+h-1)) {
selsprite = p;
seltile = NULL;
break;
} else {
// check next one
x += w;
if (x >= EDITORW-TILEW) {
2008-09-16 12:40:09 +10:00
x = SPALX;
y += maxh;
maxh = 0;
}
}
}
// redraw palette with new selection
drawpalette();
} else if (mx < PALX) { // over map
int x,y;
if (seltile != NULL) {
/* place selected tile at mouse pos */
x = (mx / TILEW);
y = (my / TILEH);
curlevel->map[y*LEVELW+x] = seltile->uniqid;
curlevel->tileframe[y*LEVELW+x] = 0;
2008-09-16 12:40:09 +10:00
// redraw tile and sprites
drawtile(screen,x,y);
drawsprites();
modified = B_TRUE;
2008-09-16 12:40:09 +10:00
} else if (selsprite >= 0) {
int placed = B_FALSE;
x = (mx / TILEW);
y = (my / TILEH);
/* checks */
if (toggletimer == 0) {
// can only have one player start pos
if (selsprite == P_PLAYER) {
/* does a player start pos already exist? */
sprite_t *s;
for (s = sprite ; s ; s = s->next) {
if (s->id == P_PLAYER) {
// if so, just move it
s->x = x*TILEW+(TILEW/2);
s->y = y*TILEH+TILEH;
placed = B_TRUE;
modified = B_TRUE;
// get rid of old sprite
draweditorlevel();
}
}
} else { // is there a monster already there?
sprite_t *s;
for (s = sprite ; s ; s = s->next) {
if (s->id == selsprite) {
if ((s->x == x*TILEW+(TILEW/2)) && (s->y == y*TILEH+TILEH)) {
/* don't place it */
placed = B_TRUE;
}
}
2008-09-16 12:40:09 +10:00
}
}
}
2008-09-16 12:40:09 +10:00
if (!placed) {
/* place selected sprite at mouse position
(locked to a til) */
if (selsprite == P_HELP) {
addsprite(selsprite, x*TILEW+(TILEW/2),y*TILEH+TILEH,"FILL ME IN", B_TRUE);
} else {
addsprite(selsprite, x*TILEW+(TILEW/2),y*TILEH+TILEH,"something", B_TRUE);
}
toggletimer = 30;
modified = B_TRUE;
drawsprites();
2008-09-16 12:40:09 +10:00
}
}
}
}
/* check for keys */
SDL_PumpEvents();
keys = SDL_GetKeyState(NULL);
if (keys[SDLK_x]) { // delete monster
int donesomething = B_FALSE;
sprite_t *s, *nextone;
for (s = sprite ; s ; s = nextone) {
nextone = s->next;
/* if mouse is over this sprite */
if ( (mx >= s->x - (s->img->w/2)) &&
(mx <= s->x + (s->img->w/2)) &&
(my >= s->y - s->img->h) &&
(my <= s->y )) {
// kill it
killsprite(s);
donesomething = B_TRUE;
}
}
if (donesomething) {
draweditorlevel();
drawsprites();
modified = B_TRUE;
}
2008-09-16 12:40:09 +10:00
}
if (keys[SDLK_c]) {
if (toggletimer == 0) {
int offset,x,y;
/* clear all sprites */
while (sprite) {
killsprite(sprite);
}
/* clear level */
for (x = 0; x < LEVELW; x++) {
for (y = 0; y < LEVELH; y++) {
offset = y*LEVELW+x;
if ((x == 0) || (x == LEVELW-1)) {
curlevel->map[offset] = T_FULL;
} else if (y == LEVELH-1) {
curlevel->map[offset] = T_LAND;
} else {
curlevel->map[offset] = T_BLANK;
}
drawtile(screen,x,y);
}
}
}
}
/* next level */
if (keys[SDLK_RIGHT]) {
if (toggletimer == 0) {
printf("Skipping to next level.\n");
curlevelnum++;
loadlevel(curworld,curlevelnum);
draweditorlevel();
drawsprites();
toggletimer = 30;
}
}
/* prev level */
if (keys[SDLK_LEFT]) {
if (toggletimer == 0) {
if (curlevelnum > 1) {
printf("Skipping to previous level.\n");
curlevelnum--;
loadlevel(curworld,curlevelnum);
draweditorlevel();
drawsprites();
toggletimer = 30;
}
}
}
2008-09-16 12:40:09 +10:00
if (keys[SDLK_RETURN]) {
if (toggletimer == 0) {
SDL_WM_ToggleFullScreen(screen);
toggletimer = 50;
}
}
if (keys[SDLK_ESCAPE]) {
return 1;
}
/* SAVE LEVEL */
if (keys[SDLK_s]) {
if (modified) {
savelevel(curworld,curlevelnum);
modified = B_FALSE;
}
}
2008-09-16 12:40:09 +10:00
flip();
if (++timer == 100) timer = 0;
if (toggletimer > 0) toggletimer--;
}
return 0;
}
void cleanup(void) {
int i;
for (i = 1; i < MAXLETTERHEIGHT; i++) {
TTF_CloseFont(font[i]);
2008-09-16 12:40:09 +10:00
}
TTF_Quit();
SDL_Quit();
2008-09-16 12:40:09 +10:00
}
void draweditorlevel(void) {
int x,y;
2008-09-16 12:40:09 +10:00
if (temps) {
SDL_FreeSurface(temps);
temps = NULL;
2008-09-16 12:40:09 +10:00
}
temps = SDL_CreateRGBSurface(SDL_SWSURFACE,
640, 480,
screen->format->BitsPerPixel, screen->format->Rmask,
screen->format->Gmask,screen->format->Bmask,
screen->format->Amask);
2008-09-16 12:40:09 +10:00
for (x = 0; x < LEVELW; x++) {
for (y = 0; y < LEVELH; y++) {
drawtile(screen,x,y);
2008-09-16 12:40:09 +10:00
}
}
SDL_UpdateRect(screen, 0, 0, EDITORW, EDITORH);
2008-09-16 12:40:09 +10:00
}
void drawsprites(void) {
sprite_t *s;
for (s = sprite; s != NULL; s = s->next) {
drawsprite(s);
2008-09-16 12:40:09 +10:00
}
}
/*
char tiletochar(int id) {
switch (id) {
case T_BLANK: return '0';
case T_LAND: return '~';
case T_SLOPEUP: return '/';
case T_SLOPEDOWN: return '\\';
case T_FULL: return '*';
case T_SKY: return '0';
case T_LADDER: return '=';
case T_LADDERTOP: return '-';
case T_RIGHT: return '>';
case T_LEFT: return '<';
case T_SPIKES: return '^';
case T_TELEPORT: return ';';
case T_TELEPORT2: return ':';
case T_TELEPORTDEST: return '.';
case T_WATER: return '}';
case T_WATERTOP: return '{';
case T_WATERSPIKES: return '|';
}
return '0';
}
*/
void usage(void) {
printf("usage: edit [-fs] [-l xx]\n");
printf(" -fs Start in full-screen mode.\n");
printf(" -l xx Edit level xx.\n");
printf("\n");
2008-09-16 12:40:09 +10:00
}
void drawpalette(void) {
2008-09-16 12:40:09 +10:00
tiletype_t *tt;
SDL_Rect area;
tiletype_t *bg = gettile(curlevel->bgtileid);
int p;
int maxheight;
2008-09-16 12:40:09 +10:00
/* draw all tiles */
area.x = PALX;
area.y = PALY;
area.w = TILEW;
area.h = TILEH;
for (tt = tiletype; tt != NULL; tt = tt->next) {
/* draw background */
SDL_BlitSurface(bg->img[0], NULL, screen, &area);
/* draw tile */
SDL_BlitSurface(tt->img[0], NULL, screen, &area);
/* draw selector box */
if (seltile == tt) {
drawbox16(screen,area.x,area.y,area.x+area.w-1,area.y+area.h-1,&red,NULL);
drawbox16(screen,area.x+1,area.y+1,area.x+area.w-2,area.y+area.h-2,&red,NULL);
2008-09-16 12:40:09 +10:00
}
/* move on to next position */
area.x += TILEW;
if (area.x >= EDITORW) {
area.x = PALX;
area.y += TILEH;
2008-09-16 12:40:09 +10:00
}
2008-09-16 12:40:09 +10:00
}
SDL_UpdateRect(screen, PALX,PALY,PALW,PALH);
2008-09-16 12:40:09 +10:00
/* draw all sprites */
maxheight = 0;
2008-09-16 12:40:09 +10:00
area.x = SPALX;
area.y = SPALY;
for (p = 0; p < MAXPTYPES; p++) {
SDL_Surface *firstimg;
2008-09-16 12:40:09 +10:00
/* select images */
firstimg = imageset[p].img[F_WALK1];
area.w = firstimg->w;
area.h = firstimg->h;
if (area.h > maxheight) maxheight = area.h;
2008-09-16 12:40:09 +10:00
/* clear bg */
drawbox16(screen,area.x,area.y,area.x+area.w,area.y+area.h,&black,&black);
/* draw sprite */
SDL_BlitSurface(firstimg, NULL, screen, &area);
/* draw selector box */
if (selsprite == p) {
drawbox16(screen,area.x,area.y, area.x+area.w-1,area.y+area.h-1,&red,NULL);
drawbox16(screen,area.x+1,area.y+1, area.x+area.w-2,area.y+area.h-2,&red,NULL);
2008-09-16 12:40:09 +10:00
}
/* move to next position */
area.x += area.w;
if (area.x >= EDITORW-TILEW) {
area.x = SPALX;
area.y += maxheight;
maxheight = 0;
2008-09-16 12:40:09 +10:00
}
}
SDL_UpdateRect(screen, SPALX,SPALY,SPALW,SPALH);
}
2008-09-16 12:40:09 +10:00
int savelevel(int wnum, int lnum) {
FILE *f;
int x,y;
char filename[BUFLEN];
2008-09-16 12:40:09 +10:00
sprite_t *s;
2008-09-16 12:40:09 +10:00
sprintf(filename, "world%d/level%d.dat",wnum,lnum);
f = fopen(filename,"wt");
if (!f) {
printf("can't open level file\n");
return B_TRUE;
}
2008-09-16 12:40:09 +10:00
fprintf(f, "tileset %s\n",level->tileset);
fprintf(f, "bg %d\n",level->bgtileid);
fprintf(f, "hurryup %d\n",level->hurryuptime);
2008-09-16 12:40:09 +10:00
/* no mappings */
fprintf(f, "endmaps\n");
2008-09-16 12:40:09 +10:00
/* help text */
fprintf(f, "help\n");
for (s = sprite; s ; s = s->next) {
if (s->id == P_HELP) {
fprintf(f,"%s\n",s->name);
2008-09-16 12:40:09 +10:00
}
}
fprintf(f, "endhelp\n");
2008-09-16 12:40:09 +10:00
/* monster defs */
fprintf(f, "monsters\n");
for (s = sprite; s ; s = s->next) {
int mx,my;
char mid;
mid = monstertochar(s->id);
mx = (s->x - (TILEW/2)) / TILEW;
my = (s->y - TILEH/2) / TILEH;
fprintf(f,"%c %d %d\n",mid,mx,my);
2008-09-16 12:40:09 +10:00
}
fprintf(f, "endmonsters\n");
2008-09-16 12:40:09 +10:00
/* level data */
for (y = 0; y < LEVELH; y++) {
for (x = 0; x < LEVELW; x++) {
fprintf(f, "%d,",level->map[y*LEVELW+x]);
2008-09-16 12:40:09 +10:00
}
fprintf(f, "\n");
}
2008-09-16 12:40:09 +10:00
fclose(f);
2008-09-16 12:40:09 +10:00
printf("Level saved to '%s'\n",filename);
2008-09-16 12:40:09 +10:00
return 0;
}
2008-09-16 12:40:09 +10:00