// gameairhockey.h
// Sample header file code of how you might implement this.  (I've tested this
// and it CAN be done this way.)
//////////////////////////////////////////////////////////////////////

#ifndef GAMEAIRHOCKEY_H
#define GAMEAIRHOCKEY_H

#include "game.h"
#include "critterwall.h"

/* cCritterHockeyRobot will be the computer-operater opponent for the airhockey game. Most 
of its behavior will be produced by adding a cForceObjectSeek(_ppuck), but in the
update we'll add another condition: that it move towards its own goal if the puck is between
it and its goal. */
class cCritterHockeyRobot : public cCritter
{
DECLARE_SERIAL(cCritterHockeyRobot);
public:
	cCritterHockeyRobot(cGame *pownergame = NULL); 
	virtual void update(CPopView *pactiveview, Real dt); /* Assume we've assigned
		a cForceObjectAcclerateTowards in the cGameAirhockey constructor.
		What you might do here is call cCritter::update, and then if in
		fact the _ppuck is to your write, then set _acceleration to zero and
		don't move towards the _ppuck, thus undoing the force.  This is
		to avoid hitting the puck into your own goal. */
};

class cCritterHockeyPuck : public cCritter
{
DECLARE_SERIAL(cCritterHockeyPuck);
public:
	cCritterHockeyPuck(cGame *pownergame = NULL);
};

class cCritterHockeyPlayer : public cCritter
{
DECLARE_SERIAL(cCritterHockeyPlayer);
public:
	cCritterHockeyPlayer(cGame *pownergame = NULL);
	virtual void reset(); //Overlaod to move him to the middle of his play area.	
};

/* cCritterHockeyGoal will inherit from cCritterWall so as to bounce things off in a reasonable way.
We will specify that one side of it is "open".  In the overload of collide, we call 
cCritterWall::collide, but also do something special if the colliding critter is the puck.
If its the puck we move the puck to the center with a reset call, and we also add score
to the player who is shooting for this goal.  We use the _targetcritter field of 
cCritterHockeyGoal to keep track of the identity of the team who is shooting for this goal. */ 
class cCritterHockeyGoal : public cCritterWall
{
DECLARE_SERIAL(cCritterHockeyGoal);
private:
	int _openside;
public:
	cCritterHockeyGoal(cGame *pownergame = NULL):cCritterWall(pownergame){};
	cCritterHockeyGoal(const cVector &enda, const cVector &endb,
		Real thickness = cCritterWall::THICKNESS, cGame *pownergame = NULL):
		cCritterWall(enda, endb, thickness, pownergame){} 
			/* Call with enda as the middle
			of the bottom edge and endb as the middle of the top edge.  Feed
			in reasonable cVector(...,...) values and a thickness. */
	void setOpenside(int openside){_openside = openside;} /* Assume we put
		_pmygoal on the left and _probotgoal on the right.  For _pmygoal,
		the openside should be BOX2_DOWN, and for _probotboal it should be
		BOX2_UP.  This is because the enda to endb line is thought of as the
		"x axis" for a cCritterWall. */
	virtual BOOL collide(cCritter *pcritter); /* Call cCritterWall::collide
		and then have some code like this:
		cGameAirhockey *phgame = (cGameAirhockey*)(pgame());
		if (collided && outcode(pcritter->position()) == _openside &&
			pcritter == phgame->_ppuck)
			//move puck to center and set its velocity to zero,
			//use addScore to increase the score of the _ptarget critter.
		 */
	virtual void draw(cGraphics *pgraphics, int drawflags=0);
 	virtual void Serialize(CArchive& ar); //Have to save _openside
};

/*cGameAirhockey tracks the player, the opponent, the puck and the two goals.  These
get initizialized in the constructor.  We overlaod the seedCritters method to move all the
things into the starting position.  (We will by default use a cListenerCursor for the
player, so note that the player will be initialized to wherever the cursor is.) The
statusMessage states the score of the game and of the _phockeyrobot. */
class cGameAirhockey : public cGame
{
DECLARE_SERIAL(cGameAirhockey) /* Don't forget to have a matching IMPLEMENT_SERIAL
	in the *.cpp file. */
public:
	static int cGameAirhockey::WINSCORE; //Game ends when someone gets this score.
protected:
	cCritterHockeyPuck *_ppuck;
	cCritterHockeyRobot *_phockeyrobot; /* Give it a 
		cForceObjectSeek(_ppuck, ...). */
	cCritterHockeyGoal *_pmygoal, *_probotgoal; /* Use cCritter::setTarget with,
		respectively _phockeyrobot and _pplayer and have them award points
		to _ptarget. */
/* I want my helper classes to be able to access the _ppuck, _prorobotgoal
and so on that are inside my cGameAirhockey, so I make them friends.  By
the way, to get access to a properly cast pointer to the game, I do this
inside my cCritterHockeyRobot and cCritterHockeyGoal methods:
cGameAirhockey *phgame = (cGameAirhockey*)(pgame()); */
public:
	cGameAirhockey(); /* Initialize a cCritter* newplayer and call
		setPlayer(newPlayer).  Then initialize _ppuck, _phockeyrobot, 
		_pmygoal, _probotgoal and do a cGame::add on each of these as soon
		as you create them. */
	cCritterHockeyRobot* phockeyrobot(){return _phockeyrobot;}
	cCritterHockeyPuck* ppuck(){return _ppuck;}
	cCritterHockeyGoal* probotgoal(){return _probotgoal;}
	cCritterHockeyGoal* pmygoal(){return _pmygoal;}
	virtual void reset(); //Overlaod to reset the robot's score to 0.
	virtual void seedCritters(); /* We use this only to position the critters, they all
		actually get created in the constructor */
	virtual void initializeView(CPopView *pview);
	virtual void initializeViewpoint(cCritterViewer *pviewer); /* In 3D, we'll use
		a viewpoint from behind the player's goal. */
	virtual CString gameOverMessage(); /* overload to say who won the game. */
	virtual CString statusMessage(); /* Give a string like "Player score: 1.
		Robot score: 2.  Updates per second: 99." */
	virtual	void adjustGameParameters(); //End game when somebody gets 7 points.
	virtual void drawBackground(cGraphics *pgraphics, int drawflags); 
		/* Overload to call cGame::drawBackgroudn and
			draw a	midfield vertical line.*/
 	virtual void Serialize(CArchive& ar); /* This is a bit of work, as I have to match
	_ppuck , _phockeyrobot , _pmygoal , _probotgoal to the pointers in the cBiota array. */
};


#endif //GAMEAIRHOCKEY_H