Files
openmine/main.c

351 lines
8.4 KiB
C

/***************************************************************************
main.c - Buscaminas 3D
-------------------
begin : dom oct 6 20:22:13 ART 2002
copyright : (C) 2002 by Feuerfrei
email : feuerfrei@interlap.com.ar
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#else
#define PACKAGE_VERSION "0.2b"
#define PACKAGE_NAME "openmine"
#endif
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <SDL/SDL.h>
#include "structs.h"
#include "gamedefs.h"
#include "game.h"
#include "gameinput.h"
#include "video.h"
#include "conf.h"
#include "main.h"
#ifndef WIN32
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#endif
char *progname;
int
main (int argc, char **argv)
{
struct game g;
struct config c;
struct display disp;
g.display = &disp;
g.config = &c;
progname = argv[0];
g.status=NEWGAME;
if (getOptions (&c, argc, argv) < 0)
return EXIT_FAILURE;
SDL_Init (SDL_INIT_VIDEO);
SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
SDL_SetVideoMode (SCREEN_W, SCREEN_H, 0, c.flags);
SDL_WM_SetCaption ("Openmine", NULL);
strcat (c.theme, "/");
if (init (&g) < 0)
return EXIT_FAILURE;
do
{
if (g.status==NEWGAME)
nuevojuego (&g);
jugar(&g);
}
while (g.status!=QUIT);
SDL_Quit ();
return 0;
}
void
jugar (struct game *g)
{
display (g);
ingame_input(g);
}
int
ProcessClick (struct game *g, int xPos, int yPos, int flag)
{
int x, y, z, i, done = 0;
GLuint *ptr, *cercano, minZ, selectBuff[BUFFER_LENGTH];
GLint hits, viewport[4];
glSelectBuffer (BUFFER_LENGTH, selectBuff);
glGetIntegerv (GL_VIEWPORT, viewport);
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glRenderMode (GL_SELECT);
glLoadIdentity ();
gluPickMatrix (xPos, yPos, 1, 1, viewport);
gluPerspective (45.0f, (float) SCREEN_W / SCREEN_H, 0.1f, 100.0f);
display (g);
hits = glRenderMode (GL_RENDER);
ptr = selectBuff;
minZ = 0xffffffff;
for (i = 0; i < hits; i++)
{
ptr++;
if (*ptr < minZ)
{
minZ = *ptr;
cercano = ptr + 2;
}
ptr += 3;
}
if (hits != 0)
{
z = (*cercano) % (g->config->side[2]);
*cercano /= (g->config->side[2]);
y = (*cercano) % (g->config->side[1]);
*cercano /= (g->config->side[1]);
x = (*cercano) % (g->config->side[0]);
if (!flag)
descubrir (g, x, y, z);
else if (g->campoV[x][y][z] == NUEVO)
g->campoV[x][y][z] = BOMBA;
else if (g->campoV[x][y][z] == BOMBA)
g->campoV[x][y][z] = MARCA;
else if (g->campoV[x][y][z] == MARCA)
g->campoV[x][y][z] = NUEVO;
}
glMatrixMode (GL_PROJECTION);
glPopMatrix ();
glMatrixMode (GL_MODELVIEW);
return done;
}
int
init (struct game *g)
{
int x, y, i;
g->campo = (char ***) calloc (g->config->side[0], sizeof (char **));
for (x = 0; x < g->config->side[0]; x++)
{
g->campo[x] = (char **) calloc (g->config->side[1], sizeof (char *));
for (y = 0; y < g->config->side[1]; y++)
g->campo[x][y] = (char *) calloc (g->config->side[2], sizeof (char));
}
g->campoV = (char ***) calloc (g->config->side[0], sizeof (char **));
for (x = 0; x < g->config->side[0]; x++)
{
g->campoV[x] = (char **) calloc (g->config->side[1], sizeof (char *));
for (y = 0; y < g->config->side[1]; y++)
g->campoV[x][y] = (char *) calloc (g->config->side[2], sizeof (char));
}
SDL_ShowCursor (SDL_ENABLE);
glViewport (0, 0, SCREEN_W, SCREEN_H);
glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
if (LoadGLTextures (g, g->config->theme) < 0)
{
SDL_Quit ();
return -1;
}
glEnable (GL_TEXTURE_2D);
glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
glClearDepth (1.0);
glEnable (GL_DEPTH_TEST);
glShadeModel (GL_SMOOTH);
glLoadIdentity ();
glGenLists (THEME_N);
for (i = 0; i < THEME_N; i++)
{
glNewList (i + 1, GL_COMPILE);
drawcube (g, i, g->config->cube);
glEndList ();
}
glMatrixMode (GL_PROJECTION);
gluPerspective (45.0f, (float) SCREEN_W / SCREEN_H, 0.1f, 1000.0f);
return 0;
}
void
display (struct game *g)
{
int x, y, z;
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode (GL_MODELVIEW);
glEnable (GL_CULL_FACE);
glInitNames ();
glPushName (0);
glLoadIdentity ();
glTranslatef (g->display->side, 0, g->display->zoom - 25.0);
glRotatef (g->display->up, 1.0f, 0.0f, 0.0f);
glRotatef (g->display->tilt_y, 0.0f, 1.0f, 0.0f);
for (x = 1; x < g->config->side[0] - 1; x++)
for (y = 1; y < g->config->side[1] - 1; y++)
for (z = 1; z < g->config->side[2] - 1; z++)
{
if (g->campoV[x][y][z] != 0)
{
glPushMatrix ();
glTranslatef (x - (g->config->side[0] - 1) / 2.0f,
y - (g->config->side[1] - 1) / 2.0f,
z - (g->config->side[2] - 1) / 2.0f);
glLoadName (x * g->config->side[1] * g->config->side[2] +
y * g->config->side[2] + z);
glCallList (g->campoV[x][y][z] !=
NUEVO ? g->campoV[x][y][z] + 1 : 1);
glPopMatrix ();
}
}
if(g->status==WON)
{
drawString(-13.0, 9.0, -25.0, 0.01, "You Win!");
drawString(-13.0, -10.0, -25.0, 0.01, "Press n to start a new game");
}
else if(g->status==LOST)
{
drawString(-13.0, 9.0, -25.0, 0.01, "You Lose!");
drawString(-13.0, -10.0, -25.0, 0.01, "Press n to start a new game");
}
SDL_GL_SwapBuffers ();
}
int
LoadGLTextures (struct game *g, const char *tema)
{
FILE *fp;
SDL_Surface *img;
char *dir, *s;
unsigned i, n;
int fail = 0;
glGenTextures (THEME_N, g->config->texture);
dir = malloc (strlen (THEME_IMAGE) + strlen (tema) + THEME_LEN + 2 + 1);
sprintf (dir, "%s/%s", THEME_IMAGE, tema);
s = dir + strlen (dir);
strcpy (s, THEME_RC);
fp = fopen (dir, "r");
if (fp == NULL)
{
fprintf (stderr, "%s: unable to open `%s'\n"
"%s: %s \n", progname, dir, progname, strerror (errno));
return -1;
}
for (i = 0; !fail && i < THEME_N && fgets (s, THEME_LEN, fp); i++)
{
n = strlen (s);
if (n == THEME_LEN - 1 && s[n - 1] != '\0')
{ /* TODO: line overflown */
}
else
{
s[n - 1] = '\0';
if (n - 2 == '\r')
s[n - 2] = '\0';
}
img = LoadBMP (dir);
if (!img)
fail = 1;
else
{
glBindTexture (GL_TEXTURE_2D, g->config->texture[i]);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TEXTURAS);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TEXTURAS);
glTexImage2D (GL_TEXTURE_2D, 0, 3, img->w, img->h, 0,
GL_RGB, GL_UNSIGNED_BYTE, img->pixels);
}
}
/* TODO: free resources when LoadBMP fail */
free (dir);
return -fail;
}
SDL_Surface *
LoadBMP (const char *filename)
{
Uint8 *rowhi, *rowlo;
Uint8 *tmpbuf, tmpch;
SDL_Surface *image;
int i, j;
image = SDL_LoadBMP (filename);
if (image == NULL)
{
fprintf (stderr, "Unable to load %s: %s\n", filename, SDL_GetError ());
return (NULL);
}
tmpbuf = (Uint8 *) malloc (image->pitch);
if (tmpbuf == NULL)
{
fprintf (stderr, "Out of memory\n");
return (NULL);
}
rowhi = (Uint8 *) image->pixels;
rowlo = rowhi + (image->h * image->pitch) - image->pitch;
for (i = 0; i < image->h / 2; ++i)
{
for (j = 0; j < image->w; ++j)
{
tmpch = rowhi[j * 3];
rowhi[j * 3] = rowhi[j * 3 + 2];
rowhi[j * 3 + 2] = tmpch;
tmpch = rowlo[j * 3];
rowlo[j * 3] = rowlo[j * 3 + 2];
rowlo[j * 3 + 2] = tmpch;
}
memcpy (tmpbuf, rowhi, image->pitch);
memcpy (rowhi, rowlo, image->pitch);
memcpy (rowlo, tmpbuf, image->pitch);
rowhi += image->pitch;
rowlo -= image->pitch;
}
free (tmpbuf);
return (image);
}