/*****************************************************************************
 * Asteroids.cpp
 * Author: 	Edmund S. Lord III - e.lord@lwtelecom.com
 * Date: 	Approximately Summer/Fall 2000 (revision attempt: Feb 2006)
 * 
 * Description:
 * 		Entry point for an Asteroids game for MS-Windows or Dos with
 * 		DPMI. Heavy use of BIOS calls for input/output and absolute
 * 		pointers to VGA Framebuffer makes this a portability 
 * 		challenge. Most of the game Logic is fairly separate from 
 * 		mechanism however, and it should be at least straightforward
 * 		to convert to SDL or graphics/game library of your choice.
 * 		As is the Binaries almost run under wine, but as this was 
 * 		originally compiled under DJGPP I imagine it would need some
 * 		work just to compile under standard GNU tools.
 *
 * 		One source of dismay is that this was my first major C++
 * 		Program, and unfamiliar with linkers and compilers I simply
 * 		included the function definitions in with my header files.
 * 		This makes for a bit of spaghetti dependency which will need
 * 		to be untangled a bit before any serious porting can begin.
 *
 * 		I really feel that simply documenting the mechanics and
 * 		interfaces of these modules will produce clean code that
 * 		"Falls out" of the header files. My first goal is to produce
 * 		a linux-compatible SDL port that is 100% compatible with the
 * 		original game. Then I will begin updating the design and
 * 		mechanics of the game to reflect some design choices I feel
 * 		are more appropriate. A final goal is to try porting this
 * 		game to other systems such as Dreamcast or GBA or possibly
 * 		PSP with bootloader.
 *
 * 		It is my assertation that although some of my methods were
 * 		unorthodox and not the most effective design, the game itself
 * 		has a solid foundation and can be extended and brought into
 * 		the 21st century with relative ease. Indeed, many of the
 * 		projects I've worked on since writing this game have
 * 		incorporated large blocks of code from the various libraries
 * 		I created for it.
 *
 * 		WHY DO THIS?
 *
 * 		1. I want to play this game again. It was fun.
 * 		2. I don't want to lose anything I've created in the past.
 * 		   I'm working on creating a website that catalogs all of
 * 		   my previously created software that I've done for
 * 		   personal projects. It is my intention to use this as a
 * 		   foundation to make bigger and better things in the future.
 * 		3. Programming is fun.
 * 		4. I'm a nerd.
 * 		5. I want other people to play this game.
 * 		6. This will make me more attractive to the opposite sex.
 *
 * 		
 *
 ****************************************************************************/


#include <iostream>
#include <stdlib.h>
//#include <dos.h>		// old dos memory functions/used for vga
#include <string.h>
#include <math.h>
#include "SDL.h"
//#include <conio.h>		// old dos keyboard/screen interface
#include "vector.h"		// 2D Vector stuff used for screen coordinates
#include "draw.h"		// 2D Raster Graphics Library used for drawing
#include "blit.h"
#include "bullet.h"
#include "ship.h"		// Spaceship player class
#include "text.h"		// 2D Simple raster text output classes
#include "linklist.h"		// Used for enemy memory management
//#include "mouse.h"		// Mouse driver interface
#include "settings.h"
#include "game.h"		// Main game control

using namespace std;

bool titlescreen(byte_t *buffer,Settings *sets);
SDL_Surface* sdl_initialize();
void closing();

byte_t* double_buffer=NULL;
SDL_Surface *screen=NULL;


int main(int argc, char** argv){
	// THIS IS THE SURFACE WE DRAW TO

	// Get mouse support or BUST
	//if (!mouseon()){		
	//	cerr<<"ERROR: no mouse driver found\n";
	//	return 1;
	//}
	
	// Allocate back buffer as array of bytes size of screen or BUST 
	screen=sdl_initialize();
	atexit(closing);
	double_buffer = new byte_t[XMAX*YMAX];	
	if(double_buffer == NULL){
		cerr<<"ERROR: not enough memory for screen buffer\n";
		return 1;
	}
	memset(double_buffer,0,XMAX*YMAX);	// Clear screen to black
	Settings sets;	
	while (titlescreen(double_buffer,&sets)){ // Display title/wait for input
		game(double_buffer,screen,&sets);	// Play entire game in here
	}					// Go back to title/wait
	
	return 0;				// All's well that ends well!
}

void closing(){
	if(double_buffer!=NULL) delete[] double_buffer;
	SDL_Quit();
}

SDL_Surface* sdl_initialize(){
	if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER)==-1){
		cerr<<"Could not initialize SDL subsystem\n";
		return NULL;
	}
	SDL_ShowCursor(SDL_DISABLE);
	return SDL_SetVideoMode(XMAX,YMAX,8,SDL_FULLSCREEN);
}

/*****************************************************************************
 * bool titlescreen (byte_t *buffer);
 * Description:
 * 	Displays a brief message and waits for input
 * Arguments:
 * 	buffer - pointer to an array of bytes the size of the screen
 * Returns:
 * 	false 	if the letter 'Q' is typed on the keyboard
 * 	true 	if any other character is typed
 * Effects:
 * 	This function is used to generate a screen of introductory message.
 * 	The buffer as input above is written to so as to build this screen,
 * 	and is blitted to the actual screen as defined by the drawing library.
 * Requires:
 * 	#include "text.h"
 * 	#include "draw.h"
 * 	The hardware screen must be initialized.
 ****************************************************************************/
bool titlescreen(byte_t *buffer,Settings *sets){
	SDL_Event event;
	do{
		Text 	asteroids("ASTEROIDS",Vector(XMAX/2-40,YMAX/2-75)), 
			version("V 0.99",Vector(XMAX/2-25,YMAX/2-55)),
			beta("BETA",Vector(XMAX/2+10,YMAX/2-55)),
			author("BY: ED LORD",Vector(XMAX/2-25,YMAX/2-45)),
			pressanykey("PRESS SPACE KEY TO PLAY",Vector(XMAX/2-110,YMAX/2-10)),
			qtoquit("Q TO QUIT",Vector(XMAX/2-20, YMAX/2+30)),
			mouse("M MOUSELOOK",Vector(XMAX/2-50, YMAX/2+50)),
			on("ON",Vector(XMAX/2+25, YMAX/2+50)),
			off("OFF",Vector(XMAX/2+25, YMAX/2+50)),
			gunbonus("G GUN UPGRADES",Vector(XMAX/2-50, YMAX/2+60)),
			lifebonus("L EXTRA LIFE",Vector(XMAX/2-50, YMAX/2+70));
		asteroids.drawx2(SDL_MapRGB(screen->format,255,0,0),buffer);
		version.draw(SDL_MapRGB(screen->format,0,0,255),buffer);
		beta.draw(SDL_MapRGB(screen->format,255,128,25),buffer);
		author.draw(SDL_MapRGB(screen->format,0,255,0),buffer);
		pressanykey.drawx2(SDL_MapRGB(screen->format,255,255,0),buffer);
		qtoquit.draw(SDL_MapRGB(screen->format,255,128,128),buffer);
		mouse.draw(SDL_MapRGB(screen->format,0,128,255),buffer);
		gunbonus.draw(SDL_MapRGB(screen->format,0,128,255),buffer);
		lifebonus.draw(SDL_MapRGB(screen->format,0,128,255),buffer);
		longout(sets->gunbonus,Vector(XMAX/2+25,YMAX/2+60),SDL_MapRGB(screen->format,0,255,0),buffer);
		longout(sets->lifebonus,Vector(XMAX/2+25,YMAX/2+70),SDL_MapRGB(screen->format,0,255,0),buffer);
		
		if(sets->mouselook){
			on.draw(SDL_MapRGB(screen->format,0,255,0),buffer);
		} else {
			off.draw(SDL_MapRGB(screen->format,255,0,0),buffer);
		}
		Vector center((screen->w)/2,(screen->h/2));
		int radius=(screen->h)/2;
		for(int j=0; j<screen->h; j++){
			for(int i=0; i<screen->w; i++){
				Vector point(i,j);
				double val=radius-(mag(point-center)+40);
				if(fabs(val)<=40){
					val=cos(val*3.141592/80);
					pixel(i,j,SDL_MapRGB(screen->format,0,int(255*val),0),buffer);
				}
			}
		}
		blit0(buffer,screen);
		//wait
		while((SDL_PollEvent(&event)!=1)||(event.type!=SDL_KEYDOWN));
		memset(buffer,0,XMAX*YMAX);
		if(event.key.keysym.sym==SDLK_m){
			sets->mouselook=!sets->mouselook;
		}
	} while (event.key.keysym.sym!=SDLK_q && event.key.keysym.sym!=SDLK_ESCAPE && event.key.keysym.sym!=SDLK_SPACE);
	return (event.key.keysym.sym!=SDLK_q && event.key.keysym.sym!=SDLK_ESCAPE);
}

/*
 * 
#define ONEUP 5000
#define GREEN 49
#define BLUE 32
#define RED 39
#define WHITE 1
#define BLACK 0
#define YELLOW 44

Vector f(double t);
Vector g(double t);
Vector h(double t);
void game(byte_t *double_buffer);

 */
