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";
}