联机版乒乓球游戏

13号,锅坏了,茶壶里煮水饺,肚里有货倒不出.....

这是个超简单的联机版乒乓球游戏,做了分屏渲染,以便可以放在vr眼镜中观看,由于没有vr眼镜所以没有检验效果正确性。单帧绘制左眼内容,双帧时绘制右眼内容,两帧之间没有禁止时间步进,可能有微小的不同。

设置摄像机的代码:


void Camera::SplitLookAt()
{
	if (G_Engine->IsSplitScreenX()==false)
		return;

	vec3 eyePos = m_eyePos;
	vec3 tarPos = m_eyePos+m_headDir;

	int   SplitFrame = G_Timer->GetCurrentFrame()%2 + 1;
	float HalfEyeDis = G_Engine->GetSplitEyeDis()/2;            //双目间距/2
	float ang = atan(HalfEyeDis/G_Engine->GetSplitEyeDepth());  //根据焦距计算双目偏转
	if (IsCurCtrler<CameraCtrlerTarget>())
	{
		ang = atan(HalfEyeDis/((CameraCtrlerTarget*)GetCurCtrler())->m_distToTar);
	}

	mat4 rot;
	if (SplitFrame==1)
	{
		eyePos += m_leftDir* HalfEyeDis;  //左眼
		rot.FromAxisAngle(m_upDir,-ang);
	}
	else if (SplitFrame==2)
	{
		eyePos -= m_leftDir* HalfEyeDis;  //右眼
		rot.FromAxisAngle(m_upDir,ang);
	}

	tarPos = eyePos + rot*m_headDir;

	G_RendDriver->LookAt(eyePos.x,eyePos.y,eyePos.z,	
		tarPos.x,tarPos.y,tarPos.z,
		m_upDir.x,m_upDir.y,m_upDir.z);

}

由于没有vr输入设备,鼠标或键盘只方便在两个维度上进行输入,无法模拟三维输入,加上不用vr眼镜无法感知球的深度,所以这个乒乓球游戏做了二维的限定,球只能在平面上移动,这样球拍才好接。也有些乒乓球游戏在桌面上标记了球的投影点来帮助判断球的高度。

加了部分打砖块的元素,球碰到砖块可能被反弹或得到相应奖励。砖块被打爆后上面的砖块自动下落。

 

 球类:

//========================================================
//  @Date:     2016.05
//  @File:     SourceDemoClient/PingPong/PingPongBall.h
//  @Brief:     PingPongBall
//  @Author:     LouLei
//  @Email:  twopointfive@163.com
//  @Copyright (Crapell) - All Rights Reserved
//========================================================

#ifndef  __PingPongBall__H__
#define  __PingPongBall__H__

#include "Math/MathLib.h"

namespace RendSys
{
	class MovieClip;
}
using namespace RendSys;
class SoundChannel;

//同步移动 航位推测法

//碰撞检测结果全放到host上,其它玩家只是把paddle移动发送到host上,防止不同步和外挂
enum HitType
{
	HitNull   = 0,
	HitPaddle,
	HitBrick,
	HitDesk,
	HitOut,
};
//球
class PingPongBall 
{
public:
	PingPongBall();
	~PingPongBall();
	void  Reset();
	void  Render();
	vec3  GetPos();
	void  SetPos(const vec3& pos);
	void  SetSpeed(const vec3& speed);
	bool  Update(float time);

	//预测球的位置 最长预测2秒 最多计算两次反弹 (deviation对于球的位置和速度引入误差)
	bool  Predict(const vec3& paddleHomePos,vec3& resPos,vec3& resSpeed,float deviation);

	void  PlayHitSound(HitType hitType);

	//private:
	int   ID;
	float m_mass;
	float m_radius;

	float m_maxSpeed;
	vec3  m_pos;
	vec3  m_homePos;
	vec3  m_speed;
	vec3  m_headDir;

	quat  m_rot;

	MovieClip*     m_movieBall;
	MovieClip*     m_movieTail;
	MovieClip*     m_movieExploid;
	float          m_exploidTime;
	SoundChannel*  m_sound;
};

enum BrickType
{
	Brick  , //砖
	Bonus  , //奖
	Penalty, //罚
};

//砖
class PingPongBrick 
{
public:
	MovieClip* m_movie;
	vec3 m_pos;
	vec3 m_homePos;

	int  ID;
	//bool m_visible;
};

#endif

//========================================================
//  @Date:     2016.05
//  @File:     SourceDemoClient/PingPong/PingPongBall.cpp
//  @Brief:     PingPongBall
//  @Author:     LouLei
//  @Email:  twopointfive@163.com
//  @Copyright (Crapell) - All Rights Reserved
//========================================================

#include "General/Pch.h"
#include "PingPong/PingPongBall.h"
#include "PingPong/MiniGamePingPong.h"
#include "PingPong/PingPongPlayer.h"
#include "Render/MC_MovieClip.h"
#include "Render/RendDriver.h"
#include "Sound/ChannelSound.h"
#include "Packet/PacketMiniGame.h"
#include "General/Timer.h"
#include "General/Pce.h"

PingPongBall::PingPongBall() 
:m_movieBall(NULL)
,m_movieTail(NULL)
,m_movieExploid(NULL)
{
	m_sound = new SoundChannel;
	Reset();
}
PingPongBall::~PingPongBall() 
{
	SafeDelete(m_sound);
}
void PingPongBall::Reset() 
{
	m_mass = 0.01f;
	m_radius = 8;
	m_maxSpeed = 100;
	m_speed = vec3(0,0,-m_maxSpeed);
	m_pos = m_homePos;
	m_headDir = vec3(0,0,-1);
	m_exploidTime = 0;
}

vec3 PingPongBall::GetPos()
{
	return m_pos;
}

void PingPongBall::SetPos(const vec3& pos)
{
	m_pos = pos;
}

void PingPongBall::Render()
{
	mat4 mat;
	G_RendDriver->PushMatrix();
	G_RendDriver->Translatef(m_pos.x, m_pos.y, m_pos.z);

	m_rot.ToMatrix(mat);
	G_RendDriver->MultMatrix(mat);

	m_movieBall->Advance();
	m_movieBall->RendClip();

	G_RendDriver->PopMatrix();

	if (m_movieTail)
	{
		m_movieTail->RendClip();
	}
	if (m_movieExploid)
	{
		m_movieExploid->RendClip();
	}
	
	G_RendDriver->DisableRendState(RS_TEXTURE_2D);
	G_RendDriver->DisableRendState(RS_LIGHTING);
	G_RendDriver->Color3f(1, 0, 0);	
	G_RendDriver->SetLineWidth(1);
	G_RendDriver->RendBegin(RS_LINES);
	{
		float time = G_Timer->GetStepTimeLimited();
		vec3  end  = m_pos + m_speed * time * 1000;
		G_RendDriver->Vertex3fv(m_pos);
		G_RendDriver->Vertex3fv(end);
	}
	G_RendDriver->RendEnd();
	G_RendDriver->EnableRendState(RS_LIGHTING);
}

bool PingPongBall::Update(float time) 
{
	if (G_PingPongGame->IsHost()
		&&m_speed.Length() > 0.001f) 
	{
		vec3 mov = m_speed * time * 1.1f;//稍微加长 防止穿透
		//
		RayMovieCollideRes res;
		res.vStart   = m_pos;
		res.vEnd     = m_pos + mov;
		res.justBond = false;
		res.face     = 1;
		int hitType  = HitNull;

		//hit paddle
		PingPongPlayer* thePlayer;
		if(hitType == 0)
		{
			for(int i = 0; i < G_PingPongGame->GetAllPlayerNum(); i++)
			{
				thePlayer = dynamic_cast<PingPongPlayer*>(G_PingPongGame->GetPlayerFromIndex(i));
				if(    thePlayer 
					&& thePlayer->m_moviePaddleCollide 
					&& thePlayer->m_moviePaddleCollide->IntersectTray(res))
				{
					hitType = HitPaddle;
					res.vEnd = res.resPos;
				}
			}
		}


		int brickID = 0;
		//hit brick
		if(hitType == 0)
		{
			for(int i = 0; i < G_PingPongGame->m_brickNum; i++)
			{
				PingPongBrick* theBrick = &G_PingPongGame->m_bricks[i];
				if(theBrick->m_movie 
					&& theBrick->m_movie->IsVisible()
					&& theBrick->m_movie->IntersectTray(res))
				{
					//todo 砖块按高度排序  砖块下面无支撑则下落砖块
					hitType = HitBrick;
					brickID = theBrick->ID;
					res.vEnd = res.resPos;
					theBrick->m_movie->SetVisible(false);
					m_exploidTime = 0.5f;
				}
			}
		}

		//hit desk
		if(hitType == 0)
		{
			if (G_PingPongGame->m_movieCollidePingpong->IntersectTray(res))
			{
				hitType = HitDesk;
				res.vEnd = res.resPos;
			}
		}

		//
		if (hitType==HitPaddle)
		{
			if (m_speed.Dot(res.resNorml)>0)
			{
				//背面碰撞导致穿透
				int a = 0;
			}
			//不是反弹 直接沿法线击出
			m_speed = res.resNorml*m_maxSpeed;

			运动继承
			//vec3 mov = vec3(100,0,0)*thePlayer->m_movDir;
			//m_speed += mov;
		}
		else if (hitType==HitBrick || hitType==HitDesk)
		{
			m_speed = Reflect(m_headDir,res.resNorml)*m_maxSpeed;
		}

		if (abs(m_pos.x-G_PingPongGame->GetStartPos().x)>200)
		{
			hitType = HitOut;
			Reset();
		}
		if (abs(m_pos.z-G_PingPongGame->GetStartPos().z)>200)
		{
			hitType = HitOut;
			Reset();
		}
		if (hitType!=HitNull)
		{
			PlayHitSound((HitType)hitType);
			C2SPacketMiniGameCmd packet;
			packet.WriteHeader();
			packet.WriteValue(CMD_BallMove);
			packet.WriteValue(ID);
			packet.WriteValue(hitType);
			packet.WriteValue(brickID);
			packet.WriteValue(m_pos);
			packet.WriteValue(m_speed);
			G_MiniGame->SendPacketToOther(&packet);
		}
	} 

	//重新计算
	vec3  mov = m_speed * time;
	m_pos += mov;
	float speedLen = m_speed.Length();
	//
	if (m_speed.LengthSq()>0.001f)
	{
		m_headDir = m_speed;
		m_headDir.Normalize();
		vec3 rightDir(m_headDir.z,0.0f,- m_headDir.x);

		//
		float rotAngleRad = speedLen * time/ m_radius;
		//if (m_rotAngleRad > TWOPI)
		//	m_rotAngleRad =  m_rotAngleRad - TWOPI;

		quat omegaQ;
		omegaQ.FromAxisAngle(rightDir, rotAngleRad); 
		m_rot = omegaQ *m_rot;  
		m_rot.Normalize();
	}

	if (m_movieTail)
	{
		Frame frame;
		frame.SetPos(m_pos);
		m_movieTail->SetProgramFrame(&frame);
		m_movieTail->Advance();
	}

	if (m_movieExploid)
	{
		Frame frame;
		if (m_exploidTime >0)
		{
			m_exploidTime -= G_Timer->GetStepTimeLimited();
			frame.SetPos(m_pos);
		}
		else
		{
			frame.SetPos(vec3(0,-100,0));
		}
		m_movieExploid->SetProgramFrame(&frame);
		m_movieExploid->Advance();
	}
	
	return false;
}
//预测球的位置 最长预测2秒 最多计算两次反弹 (deviation对于球的位置和速度引入误差)
bool PingPongBall::Predict(const vec3& paddleHomePos,vec3& resPos,vec3& resSpeed,float deviation)
{
	//deviation 柏林误差 持续一段时间后才改变 防止震荡
	resPos   = m_pos;
	resSpeed = m_speed;

	//return true;	//不思考球的反弹

	//反弹
	if(deviation>0)
	{
		Srand(deviation*100);
		resPos.x += m_maxSpeed*RandRange(-1.0f,1.0f)*0.1f;
		resPos.z += m_maxSpeed*RandRange(-1.0f,1.0f)*0.1f;
		//
		mat4 rot;
		rot.FromRotateY(deviation); 
		resSpeed = rot*resSpeed;
		//resSpeed.x += m_maxSpeed*RandRange(-1.0f,1.0f)*0.1f;
		//resSpeed.z += m_maxSpeed*RandRange(-1.0f,1.0f)*0.1f;
	}

	bool ret = false;

	float time = 0.02f;
	vec3 mov;
	//
	RayMovieCollideRes res;
	res.justBond = false;

	int reflectNum = 0;
	for (int t=0;t<100;t++) //最长预测2秒
	{
		mov = resSpeed * time;
		res.vStart = resPos;
		res.vEnd = resPos + mov;

		int hitType = HitNull;

		//hit paddle line
		if(hitType == 0)
		{
			if(  abs(paddleHomePos.z-resPos.z) < m_radius*2)
			{
				ret = true;
				break;
			}
		}


		//hit brick
		if(hitType == 0 && reflectNum<2)
		{
			for(int i = 0; i < G_PingPongGame->m_brickNum; i++)
			{
				PingPongBrick* theBrick = &G_PingPongGame->m_bricks[i];
				if(theBrick->m_movie 
					&& theBrick->m_movie->IsVisible()
					&& theBrick->m_movie->IntersectTray(res))
				{
					//todo 砖块按高度排序  砖块下面无支撑则下落砖块
					hitType = HitBrick;
					res.vEnd = res.resPos;
				}
			}
		}

		//hit desk
		if(hitType == 0 /*&& reflectNum<2*/)
		{
			if (G_PingPongGame->m_movieCollidePingpong->IntersectTray(res))
			{
				hitType = HitDesk;
				res.vEnd = res.resPos;
			}
		}

		//
		if (hitType==HitBrick || hitType==HitDesk)
		{
			resSpeed.Normalize();
			resSpeed = Reflect(resSpeed,res.resNorml)*m_maxSpeed;
			//添加反弹误差
			reflectNum++;
		}

		resPos += resSpeed * time;
	}

	若桌面最多2次反弹,预测位置可能超出台面
	//if (resPos.x < )
	//{
	//}

	if (ret == false)
	{
		//回中线机动
		//resPos = paddleHomePos; //超时未到达
	}
	return ret;
}

void PingPongBall::PlayHitSound(HitType hitType)
{
	switch(hitType)
	{
	case HitNull:
		break;
	case HitPaddle:
		m_sound->PlaySound__("data/sound/event_shoot01.wav");
		break;
	case HitBrick:
		m_sound->PlaySound__("data/sound/event_glass.wav");
		break;
	case HitOut:
		m_sound->PlaySound__("data/sound/event_leveldown.wav");
		break;
	default:
		m_sound->PlaySound__("data/sound/ui_click.wav");
		break;
	}
}

玩家类:

//========================================================
//  @Date:     2016.05
//  @File:     SourceDemoClient/CarRacing/RacingCar.h
//  @Brief:     RacingCar
//  @Author:     LouLei
//  @Email:  twopointfive@163.com
//  @Copyright (Crapell) - All Rights Reserved
//========================================================
 

#ifndef  __PingPongPlayer__H__
#define  __PingPongPlayer__H__

#include "Rpg/MiniGame.h"
#include "AI/Entity/LogicCharacter.h"

namespace RendSys
{
	class Frame;
}


//对战模式 player、paddle只能在x轴方向移动
class PingPongPlayer: public LogicCharacter,public MiniPlayer
{
public:
	PingPongPlayer();
	virtual ~PingPongPlayer();

	virtual bool Start();
	//virtual bool Restart();
	//virtual bool Stop();
	virtual void Update();

	virtual void Render();

	int   m_side;   //队
	int   m_movDir; //移动方向
	vec3  m_homePos;//中心位置
	MovieClip* m_moviePaddle;  //球拍
	MovieClip* m_moviePaddleCollide; //球拍碰撞体
};


class PingPongPlayerRobot: public PingPongPlayer
{
public:
	PingPongPlayerRobot();
	virtual ~PingPongPlayerRobot();

	//virtual bool Start();
	virtual bool Stop();
	virtual void Update();
	void SetWorkingWithAI(bool working);
	bool   m_workingWithAI;
	double m_thinkTime;
	float  m_deviation;  //误差,ai不能接太准
	float  m_hitOffset;  //击球角度

};


class PingPongPlayerRole: public PingPongPlayerRobot
{
public:
	PingPongPlayerRole();
	virtual ~PingPongPlayerRole();

	//virtual bool Start();
	virtual bool Stop();
	virtual void Update();
	virtual void Render();

};

#endif

//========================================================
//  @Date:     2016.05
//  @File:     SourceDemoClient/CarRacing/RacingCar.cpp
//  @Brief:     RacingCar
//  @Author:     LouLei
//  @Email:  twopointfive@163.com
//  @Copyright (Crapell) - All Rights Reserved
//========================================================
 
#include "General/Pch.h"
#include "General/Window.h"
#include "PingPong/PingPongPlayer.h"
#include "PingPong/PingPongBall.h"
#include "PingPong/MiniGamePingPong.h"
#include "General/Timer.h"
#include "Rpg/SyncGameInfo.h"
#include "Sound/SoundManager.h"
#include "Packet/PacketMiniGame.h"
#include "Render/RendDriver.h"
#include "Render/MC_MovieClip.h"
#include "Input/InputMgr.h"
#include "General/Pce.h"

PingPongPlayer::PingPongPlayer()
{
	m_movDir = 0;
}
PingPongPlayer::~PingPongPlayer()
{
}


bool PingPongPlayer::Start()
{
	MiniPlayer::Start();
	m_movDir = 0; 
	return true;
}

void PingPongPlayer::Update()
{
	MiniPlayer::Update();
			
	mat3 matRot;

	if (m_moviePaddleCollide)
	{
		Frame paddleFrame;
		paddleFrame.SetPos(m_pos-m_homePos);
		m_moviePaddle->SetProgramFrame(&paddleFrame);

		m_moviePaddleCollide->SetProgramFrame(&paddleFrame);
	}

	{
		vec3 mov = vec3(100,0,0)*m_movDir* G_Timer->GetStepTimeLimited();
		m_pos += mov;

		{
			GetRenderCharacter()->PlayAnim("standing_WalkRight01");
			if(m_movDir == 0)
			{
				GetRenderCharacter()->SetAnimSpeed(10);
			}
			else if ((GetPlayerInfo()->roomSlot==0 && m_movDir == -1)
				||(GetPlayerInfo()->roomSlot==1 && m_movDir == 1)
				)
			{
				GetRenderCharacter()->SetAnimSpeed(-30);
			}
			else
			{
				GetRenderCharacter()->SetAnimSpeed(30);
			}
		}

		//
		if (GetPlayerInfo()->roomSlot==0)
		{
			matRot.FromRotateY(_PI);
		}
		else
		{
			matRot.FromRotateY(0);
		}
		
		GetRenderCharacter()->SetPos(m_pos);
		GetRenderCharacter()->SetRot(matRot);
		GetRenderCharacter()->Update();
	}
}

void PingPongPlayer::Render()
{
	LogicCharacter::Render();
}

//==================^_^
PingPongPlayerRobot::PingPongPlayerRobot()
:m_thinkTime(0)
,m_deviation(0)
,m_hitOffset(0)
{
	m_workingWithAI = true;
}
PingPongPlayerRobot::~PingPongPlayerRobot()
{
}
void PingPongPlayerRobot::Update()
{
	PingPongPlayer::Update();

	int lasMovDir = m_movDir;

	//预测球的到达位置
	vec3 predictPos,predictSpeed;
	G_PingPongGame->m_balls[0].Predict(m_homePos,predictPos,predictSpeed,m_deviation);

	if (G_Timer->GetAccumTime() - m_thinkTime >= 0.5f)
	{
		m_thinkTime = G_Timer->GetAccumTime();
		Srand(m_thinkTime);//Predict will fix seed
		m_deviation = RandRange(0.1f,0.2f);
		//预测最佳击球方向 碰砖得分 让对手来不及接球的位置(体力消耗)
		m_hitOffset = RandRange(-8.0f,8.0f);
	}

	float ballX = predictPos.x + m_hitOffset;

	if (ballX > m_pos.x+2)
	{
		m_movDir = 1;
	}
	else if (ballX < m_pos.x-2)
	{
		m_movDir = -1;
	}
	else
	{
		m_movDir = 0;
	}

	if (m_movDir!=lasMovDir)
	{
		C2SPacketMiniGameCmd packet;
		packet.WriteHeader();
		packet.WriteValue(CMD_PaddleMove);
		packet.WriteValue(GetPlayerInfo()->roomSlot);
		packet.WriteValue(m_pos);
		packet.WriteValue(m_movDir);
		G_MiniGame->SendPacketToOther(&packet);
	}
}
void PingPongPlayerRobot::SetWorkingWithAI(bool working)
{
	m_workingWithAI = working;
	if (m_workingWithAI==false)
	{

	}
}

//==================^_^
PingPongPlayerRole::PingPongPlayerRole()
{
	m_workingWithAI = false;
}
PingPongPlayerRole::~PingPongPlayerRole()
{
}

void PingPongPlayerRole::Update()
{
	if(m_workingWithAI)
	{
		PingPongPlayerRobot::Update();
		return;
	}

	PingPongPlayer::Update();


	int lasMovDir = m_movDir;

	//播放死亡动画期间不能移动
	//if (m_state == Running)
	{
		m_movDir = 0;
		if(G_PingPongGame->IsKeyPressed(KeyLeft))
		{
			if (GetPlayerInfo()->roomSlot==0)
			{
				m_movDir = -1;
			}
			else
			{
				m_movDir = 1;
			}
		}
		if(G_PingPongGame->IsKeyPressed(KeyRight))
		{
			if (GetPlayerInfo()->roomSlot==0)
			{
				m_movDir = 1;
			}
			else
			{
				m_movDir = -1;
			}
		}
		if(G_PingPongGame->IsKeyPressed(KeyUp))
		{
		}
		if(G_PingPongGame->IsKeyPressed(KeyDown))
		{
		}
		if(G_Keyboard->IsKeyPressed(DIK_SPACE)||G_Joystick->GetValueOfAxisRZ()<0)
		{
		}

		if (m_movDir)
		{
			vec3 localPos = m_pos - m_homePos;
			if (  (localPos.x <= -150&& m_movDir < 0)
				||(localPos.x >= 150 && m_movDir > 0)
				)
			{
				m_movDir = 0;
			}
		}

	}

	if (m_movDir!=lasMovDir)
	{
		C2SPacketMiniGameCmd packet;
		packet.WriteHeader();
		packet.WriteValue(CMD_PaddleMove);
		packet.WriteValue(GetPlayerInfo()->roomSlot);
		packet.WriteValue(m_pos);
		packet.WriteValue(m_movDir);
		G_MiniGame->SendPacketToOther(&packet);
	}

	//UpdateListener();

	if (m_liveNum < 0)
	{
		G_PingPongGame->SetGameState(MS_End);
	}
}

void PingPongPlayerRole::Render()
{
	PingPongPlayer::Render();
}

 游戏类:

//========================================================
//  @Date:     2016.05
//  @File:     SourceDemoClient/PingPong/MiniGamePingPong.h
//  @Brief:     MiniGamePingPong
//  @Author:     LouLei
//  @Email:  twopointfive@163.com
//  @Copyright (Crapell) - All Rights Reserved
//========================================================
 
#ifndef  __MiniGamePingPong__H__
#define  __MiniGamePingPong__H__

#include "Math/MathLib.h"
#include "Render/Texture.h"
#include "Rpg/MiniGame.h"
#include "Gui/GuiControlMisc.h"


class PingPongBrick;
class PingPongBall;
class PingPongPlayer;
class PingPongPlayerRole;

// 抽 盖 旋 特技 双打  
// 	   paddle size ( pixel) 	ball speed (pixels per second)	   score modification
//Easy	    72 - 180	            240 - 400	                          -20%
//Medium	72 - 144	            270 - 430	                            0
//Hard	    52 - 108	            300 - 450	                          +30%
enum MiniPingPongCmd
{
	CMD_BallMove  ,   
	CMD_PaddleMove,
	CMD_GameOver  ,
	CMD_Restart   ,
};
const char* PingPongCmdToString(int enumeration);

class MiniGamePingPong:public MiniGame
{
public:
	MiniGamePingPong();
	virtual ~MiniGamePingPong();

	virtual bool KeepResource(bool once,int& circle,String& nextTip);
	virtual bool Start();
	virtual bool Stop();
	virtual bool Render();
	virtual void RenderUI();
	virtual bool Update();
	virtual bool Free();
	virtual bool IsEnd();

	//三种类型结构
	virtual MiniPlayer*  CreatePlayer();
	virtual MiniPlayer*  CreateRobot ();
	virtual MiniPlayer*  CreateRole  ();

	PingPongPlayer* GetTurnPlayer();	

	//处理游戏网络命令包
	virtual int  ProcessPacketCmd(PacketBase* packet);
	//virtual const char* CmdToString(const char* stream,int len);

#define MaxBall 2
	//乒乓球
	PingPongBall*   m_balls;
	int             m_ballNum;

#define MaxBrick 64
	//砖块
	PingPongBrick*  m_bricks;
	int             m_brickNum;

	//球桌
	MovieClip*  m_movieCollidePingpong;

	PingPongPlayerRole* m_myRolePlayer;

	vec2I Offset;//左上角		


};
extern MiniGamePingPong* G_PingPongGame;
#endif 

//========================================================
//  @Date:     2016.05
//  @File:     SourceDemoClient/PingPong/MiniGamePingPong.cpp
//  @Brief:     MiniGamePingPong
//  @Author:     LouLei
//  @Email:  twopointfive@163.com
//  @Copyright (Crapell) - All Rights Reserved
//========================================================
 
#include "General/Pch.h"
#include "General/Window.h"
#include "General/Timer.h"
#include "Gui/GuiMgr.h"
#include "Gui/RpgGuis.h"
#include "Input/InputMgr.h"
#include "PingPong/PingPongPlayer.h"
#include "PingPong/MiniGamePingPong.h"
#include "Render/RendDriver.h"
#include "Render/Shader.h"
#include "PingPong/MiPingPong_PlayGui.h"
#include "Rpg/SyncGameInfo.h"
#include "Packet/PacketMiniGame.h"
#include "Net/PacketList.h"
#include "Render/Camera.h"
#include "Render/MC_MovieClip.h"
#include "PingPongBall.h"
#include "Render/MC_Misc.h"
#include "Rpg/RpgGame.h"
#include "General/Pce.h"
#include "General/Engine.h"


MiniGamePingPong* G_PingPongGame;

MiniGamePingPong::MiniGamePingPong()
{
	G_PingPongGame = this;
	CmdEnumToString = PingPongCmdToString;
}

MiniGamePingPong::~MiniGamePingPong()
{
	G_PingPongGame = NULL;
}

bool MiniGamePingPong::Start()
{
	m_myRolePlayer = NULL;
	if(!MiniGame::Start())
		return false;

	G_Engine->SetSplitScreenX(true,10,100);//由于桌子被放大,人眼距也要放大

	m_gameState= MS_Gamming;

	char buf[512];
	if (m_movieScene == NULL)
	{
		LoadConfig loader(LoadConfig::GenDonotReShrinkBound,true,true);
		m_movieScene = new RendSys::MovieClip;
		if(m_movieScene->LoadFromFile("data/minigame/pingpong/scene.movie",&loader)==false)
			return false;

		Frame frame;
		frame.SetPos(m_startPos);
		m_movieScene->SetProgramFrame(&frame);
		m_movieScene->Advance();

		m_movieCollidePingpong = m_movieScene->GetMovieClip("ground_collide");
		if (m_movieCollidePingpong==NULL)
		{
			return false;
		}
	}

	//
	m_balls = new PingPongBall[MaxBall];
	m_ballNum = 1;
	for (int i = 0; i < MaxBall; i++)
	{
		m_balls[i].ID = i;
		MovieClip* movie = m_movieScene->GetMovieClip("ball");
		m_balls[i].m_movieBall = movie;
		if (movie==NULL)
		{
			return false;
		}
		m_balls[i].m_radius = 8;
		m_balls[i].m_homePos = movie->GetCollideSys().m_center;
		m_balls[i].m_pos = m_balls[i].m_homePos;
		m_balls[i].m_speed = vec3(0,0,-m_balls[i].m_maxSpeed);

		movie->SetInheritParentFrame(false);
		movie->SetFrustumSkipEnable(false, Recursive);
		((MC_Frame*)movie)->ZeroFrames();
		movie->Advance();

		movie = m_movieScene->GetMovieClip("balltail");
		m_balls[i].m_movieTail = movie;
		if (movie)
		{
			movie->SetInheritParentFrame(false);
			movie->SetFrustumSkipEnable(false, Recursive);
			if(dynamic_cast<MC_Particle*>(movie))
				dynamic_cast<MC_Particle*>(movie)->ZeroFrames();
			movie->Advance();
		}
		

		movie = m_movieScene->GetMovieClip("exploid");
		m_balls[i].m_movieExploid = movie;
		m_balls[i].m_exploidTime = 0;
		if (movie)
		{
			movie->SetInheritParentFrame(false);
			movie->SetFrustumSkipEnable(false, Recursive);
			if(dynamic_cast<MC_Particle*>(movie))
				dynamic_cast<MC_Particle*>(movie)->ZeroFrames();
			movie->Advance();
		}
		
	}

	//
	m_bricks = new PingPongBrick[MaxBrick];
	m_brickNum = 0;
	for (int i = 0; i < MaxBrick; i++)
	{
		if(m_brickNum>=MaxBrick)
			break;
		sprintf(buf,"Brick%02d",i+1);
		MovieClip* movie = m_movieScene->GetMovieClip(buf);
		if (movie)
		{
			//m_bricks[m_brickNum].m_visible = true;
			m_bricks[m_brickNum].ID = m_brickNum;
			m_bricks[m_brickNum].m_movie = movie;
			m_bricks[m_brickNum].m_homePos = movie->GetCollideSys().m_center;
			m_bricks[m_brickNum].m_pos = movie->GetCollideSys().m_center;
			//movie->SetInheritParentFrame(false);
			//movie->SetFrustumSkipEnable(false, Recursive);
			//((MC_Frame*)movie)->ZeroFrames();
			movie->Advance();
			m_brickNum++;
		}
	}


	//
	for(int i = 0; i < m_allPlayerNum; i++)
	{
		MyRoomPlayerInfo* playerInfo = G_SyncMyRoomInfo->GetPlayerFromIndex(i);
		if(playerInfo)
		{
		}
	
		PingPongPlayer* thePlayer = dynamic_cast<PingPongPlayer*>(m_miniPlayer[i]);
		PingPongPlayerRobot* theRobot = dynamic_cast<PingPongPlayerRobot*>(thePlayer);
		PingPongPlayerRole* theRole = dynamic_cast<PingPongPlayerRole*>(thePlayer);
		if (theRole)
		{
			theRole->SetWorkingWithAI(false);
		}
		else if (theRobot)
		{
			theRobot->SetWorkingWithAI(true);
		}

		Style* style = G_StyleMgr->GetStyle(thePlayer->GetPlayerInfo()->style);
		thePlayer->SetStyle(style);
		thePlayer->GetRenderCharacter()->SetScale(vec3(3.0f,3.0f,3.0f));
		thePlayer->GetRenderCharacter()->PlayAnim("stand");

		//player->m_side = (i==0?SideRed:SideBlack);
		sprintf(buf,"paddle0%d",i+1);
		thePlayer->m_moviePaddle = m_movieScene->GetMovieClip(buf);
		if (thePlayer->m_moviePaddle==NULL)
		{
			return false;
		}

		sprintf(buf,"paddleCollide0%d",i+1);
		thePlayer->m_moviePaddleCollide = m_movieScene->GetMovieClip(buf);
		if (thePlayer->m_moviePaddleCollide==NULL)
		{
			return false;
		}
		thePlayer->m_moviePaddleCollide->SetVisible(false);

		thePlayer->m_homePos = thePlayer->m_moviePaddleCollide->GetCollideSys().m_center;
		thePlayer->SetPos(thePlayer->m_homePos);
	}



	//
	for(int i = 0; i < m_allPlayerNum; i++)
	{
		m_miniPlayer[i]->Start();
	}


	//进入miniplaygui,(选人、选关卡都已在房间里进行完毕)。
	if(GetStyle()) G_GuiMgr->PushGui(GetStyle()->playGUI.c_str(),GL_DIALOG);

	//设置摄像机
	CameraCtrlerTarget* ctrler = new CameraCtrlerTarget;
	ctrler->SetDistToTar(300);
	ctrler->SetTarPos(m_startPos);
	G_Camera->PushCtrler(ctrler);	
	if (m_myRolePlayer->GetPlayerInfo()->roomSlot==0)
	{
		G_Camera->SetEuler(0,-45,0);
	}
	else
	{
		G_Camera->SetEuler(180,-45,0);
	}
	//片头摄像机
	PushIntroCamera();

	return true;
}

bool MiniGamePingPong::Stop()
{
	G_Engine->SetSplitScreenX(false);
	SafeDeleteArray(m_balls);
	SafeDeleteArray(m_bricks);
	G_Camera->PopCtrler();
	{
		if (m_myPlayer && m_myPlayer->m_liveNum>0)
		{
			G_GuiMgr->GetGui<Rpg_ResultDialog>()->ShowResult(true);
		}
		else
		{
			G_GuiMgr->GetGui<Rpg_ResultDialog>()->ShowResult(false);
		}
		G_GuiMgr->PushGui("Rpg_ResultDialog",GL_DIALOGBOTTOM); 
	}
	return MiniGame::Stop();
}

MiniPlayer* MiniGamePingPong::CreatePlayer()
{
	return new PingPongPlayer;
}

MiniPlayer* MiniGamePingPong::CreateRobot()
{
	return new PingPongPlayerRobot;
}

MiniPlayer* MiniGamePingPong::CreateRole()
{
	m_myRolePlayer = new PingPongPlayerRole;
	return m_myRolePlayer;
}

PingPongPlayer* MiniGamePingPong::GetTurnPlayer()
{
	return dynamic_cast<PingPongPlayer*>(m_miniPlayer[m_curSide]);
	//for(int i = 0; i < m_allPlayerNum; i++)
	//{
	//	PingPongPlayer* player = dynamic_cast<PingPongPlayer*>(m_miniPlayer[i]);
	//	if (player->m_side == m_curSide)
	//	{
	//		return player;
	//	}
	//}
	return NULL;
}


bool MiniGamePingPong::KeepResource(bool once,int& circle,String& nextTip)
{
	{
		G_SkeletonMgr->KeepAnim("data/modelcharacter/commonman/commonman_standing_WalkRight01.bone");
	}
	return true;
}




bool MiniGamePingPong::Render()
{
	G_RendDriver->EndUI();

	if (m_movieScene)
	{
		m_movieScene->RendClip();
	}

	//renderBalls
	for (int p = 0; p < m_ballNum; p++)
	{
		m_balls[p].Render();
	}

	//
	for(int i = 0; i < m_allPlayerNum; i++)
	{
		dynamic_cast<PingPongPlayer*>(m_miniPlayer[i])->Render();
	}

	G_RendDriver->BeginUI();
	G_RendDriver->Color4f(1,1,1,1);
	G_RendDriver->SetRenderStateEnable(RS_BLEND,true);
	G_RendDriver->BlendFunc(Blend_Filter);
	G_ShaderMgr->PushShader();

	G_RendDriver->EndUI();
	G_ShaderMgr->PopShader();
	return true;
}

void MiniGamePingPong::RenderUI()
{
	Render();
}
bool MiniGamePingPong::Update()
{
	m_turnTime += G_Timer->GetStepTimeLimited();
	if (m_movieScene)
	{
		m_movieScene->Advance();
	}

	for(int i = 0; i < m_allPlayerNum; i++)
	{
		dynamic_cast<PingPongPlayer*>(m_miniPlayer[i])->Update();
	}
	for (int i=0;i<m_ballNum;i++)
	{
		m_balls[i].Update(G_Timer->GetStepTimeLimited());
	}
	return true;
}

bool MiniGamePingPong::Free()
{
	MiniGame::Free();
	return true;
}

bool MiniGamePingPong::IsEnd()
{
	return m_gameState == MS_End;
}

int  MiniGamePingPong::ProcessPacketCmd(PacketBase* packet)
{
	int cmd;
	packet->ReadValue(cmd);
	switch(cmd)
	{
	case CMD_BallMove:
		{
			int ballID = 0;
			int hitType;
			int brickID;
			vec3 pos;
			vec3 speed;
			packet->ReadValue(ballID);
			packet->ReadValue(hitType);
			packet->ReadValue(brickID);
			packet->ReadValue(pos);
			packet->ReadValue(speed);
			m_balls[ballID].m_pos = pos;
			m_balls[ballID].m_speed = speed;
			m_balls[ballID].PlayHitSound((HitType)hitType);
			switch(hitType)
			{
			case HitBrick:
				m_bricks[brickID].m_movie->SetVisible(false);
				m_balls[ballID].m_exploidTime = 0.5f;
				break;
			default:
				break;
			}
		}
		break;	
	case CMD_PaddleMove:
		{
			int paddle = 0;
			vec3 pos;
			int  movDir;
			packet->ReadValue(paddle);
			packet->ReadValue(pos);
			packet->ReadValue(movDir);
			PingPongPlayer* thePlayer = (PingPongPlayer*)GetPlayerFromSlot(paddle);
			thePlayer->SetPos(pos);
			thePlayer->m_movDir = movDir;
		}
		break;
	case CMD_GameOver:
		{
			int turn = 0;
			packet->ReadValue(turn);
			m_winnerTurn = turn;
			m_turnTime = 0;
			m_gameStatus = Resulting;

			char sound[256];
			if (m_winnerTurn == m_lordTurn)
			{
				sprintf(sound,"data/sound/poker/play_lord_win");
			}
			else
			{
				sprintf(sound,"data/sound/poker/play_farmer_win");
			}
			if (m_winnerTurn%2) //
				strcat(sound,"_femail.wav");
			else
				strcat(sound,".wav");
			m_players[m_winnerTurn]->m_sound->PlaySound__(sound);

		}
		break;
	case CMD_Restart:
		Free();
		Start();
		break;
	}
	return 0;
}



const char* PingPongCmdToString(int enumeration)
{
	switch(enumeration)
	{
	case CMD_BallMove  :return "CMD_BallMove  ";		
	case CMD_PaddleMove:return "CMD_PaddleMove";		
	case CMD_GameOver  :return "CMD_GameOver  ";		
	case CMD_Restart   :return "CMD_Restart   ";			
	default             :return "CMD_unknow";
	}
	return "CMD_unknow";
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值