351 lines
8.4 KiB
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);
|
|
}
|
|
|