12号,感谢水饺,20多度室内有点冷,穿上羽绒服减少能量消耗.....
这是个仿雷电的空战类游戏,写了个开头,还有很多没实现的。一开始由于找不到相关的3D模型资源所以做成了2D的。后来发现做成2D的竟然比做成3D还要啰嗦,就没有继续做下去,主要是引擎对3D支持比较多。
游戏中有几种子弹:制导导弹、闪电、火龙。采集相应的弹夹可以切换子弹。
没做联机功能,早期写的游戏,代码结构不太好,可能需要重构。
实体基类:
//========================================================
// @Date: 2016.05
// @File: SourceDemoClient/SpaceWar2D/ScreenEntity.h
// @Brief: ScreenEntity
// @Author: LouLei
// @Email: twopointfive@163.com
// @Copyright (Crapell) - All Rights Reserved
//========================================================
#ifndef __ScreenEntity__H__
#define __ScreenEntity__H__
#include "General/General.h"
#include "Math/MathLib.h"
#include "Render/Texture.h"
//#include "Rpg/RpgCommon.h"
#include "AI/Entity/BaseEntity.h"
#include "AI/Entity/MovingEntity.h"
class File;
//!attack kick dead run bakrun run45 run135???
enum SpaceAnimState
{
SA_Normal = 0,
SA_Exploide,
SA_Fire,
SA_Num,
};
//2d序列
class Serial2D
{
public:
Serial2D();
bool Load(File& file);
void Clear();
int maxX;
int maxY;
int opacityType;
//每帧的显示时间
float frameTime;
String fileName;
};
//2d序列播放者
class SerialAnimator
{
public:
SerialAnimator();
//cenPos drawRect中心
void Rend(const vec3& cenPos);
//面向速度 旋转支点在中心cenPos
void Rend(const vec3& cenPos,const vec3& dir);
重新规定区域
//void Rend(const RectF& rect);
旋转支点在rect中心
//void Rend(const RectF& rect,const vec3& speed);
// return is animEnd
bool Update();
void SetIndex(int index);
void PlayAnim(Serial2D* animStyle);
Serial2D* GetAnim();
//获得序列裁剪大小
void GetExtend(int& width,int& height);
void GetExtend(float& width,float& height);
float m_curTime;
//当前播放格子序号
int m_curIndex;
Serial2D* m_serial2D;
TexturePtr m_texture;
};
//!DeclareStyleEnum(eLogicCharacter2DStyle)
class Space2DEntityStyle:public MovingEntityStyle
{
public:
virtual bool Load(File& file);
void Clear();
Serial2D animStyles[SA_Num];
RectF collideBox;
float life;
int canDamage;
float atackness;
//对于每种敌机这些属性是不变的,这样才能给玩家明确的规则,否则虽然多了复杂性,但是缺少了个性
//面向速度
int faceSpeed;
//面向玩家
int faceRole;
//出生音乐
String sound;
TexturePtr keepAnim[SA_Num];
};
class SoundChannel3D;
//功能简单没必要在库里添加 logiccharacter2d
//? 同时billboard绘制3d面片, 缓冲区优化
//!同样具有跟踪 寻路 重力 物理 动作回调等各个功能
class Space2DEntity:public MovingEntity
{
public:
Space2DEntity();
~Space2DEntity();
virtual void Update();
virtual void Render();
virtual bool SetStyle(Style* style);
virtual Space2DEntityStyle* GetStyle();
bool IsAnimState(SpaceAnimState state);
bool Intersect(Space2DEntity *pOther);
bool OutOfClient();
bool OutOfSight();
//m_pos 在drawRect的中心
RectF m_drawRect;
//更精确的多边形碰撞, 暂不区分不同的动画状态 不同的帧
RectF m_collideBox;
float m_life;
float m_atack;
float m_liveTime;
SerialAnimator m_animator;
SoundChannel3D* m_sound;
};
//
class SpacePlane2DStyle:public Space2DEntityStyle
{
public:
virtual bool Load(File& file);
//void Clear();
//螺旋桨
//炮位
#define MaxPropeller 6
int propellerNum;
vec3 propellerPos[MaxPropeller];
Serial2D propellerAnimStyles[SA_Num];
TexturePtr propellerKeepAnim[SA_Num];
float fireIntervalRat;
//子弹类型
String bulletType;
//炮位
#define MaxGun 12
int gunNum;
//int gunFaceRole;
vec3 gunPos[MaxGun];
Serial2D gunAnimStyles[SA_Num];
TexturePtr gunKeepAnim[SA_Num];
};
struct Space2DBulletStyle;
class SpacePlane2D:public Space2DEntity
{
public:
SpacePlane2D();
virtual void Update();
virtual void Render();
virtual bool SetStyle(Style* style);
virtual SpacePlane2DStyle* GetStyle();
virtual void Fire();
void SetLastFireTime();
Space2DBulletStyle* m_bulletStyle;
SerialAnimator m_propellerAnimator;
SerialAnimator m_gunAnimator;
float m_lastFireTime;
mat4 m_mat;
};
DeclareEntityGroupEnum(PlayerBulletGroup,100);
DeclareEntityGroupEnum(EnemyBulletGroup,101);
DeclareEntityGroupEnum(ItemGroup,102);
DeclareEntityGroupEnum(EnemyGroup,103);
DeclareEntityGroupEnum(EnvironmentGroup,104);
#endif
//========================================================
// @Date: 2016.05
// @File: SourceDemoClient/SpaceWar2D/ScreenEntity.cpp
// @Brief: ScreenEntity
// @Author: LouLei
// @Email: twopointfive@163.com
// @Copyright (Crapell) - All Rights Reserved
//========================================================
#include "General/Pch.h"
#include "General/General.h"
#include "General/File.h"
#include "General/Timer.h"
#include "Render/MC_MovieClip.h"
#include "Render/RendDriver.h"
#include "SpaceWar2D/Space2DEntity.h"
#include "SpaceWar2D/Space2DRole.h"
#include "SpaceWar2D/Space2DItem.h"
#include "SpaceWar2D/SpaceBullet2D.h"
#include "SpaceWar2D/MiniGameSpace2DWar.h"
#include "Sound/ChannelSound.h"
#include "General/Pce.h"
Serial2D::Serial2D()
{
opacityType = 0;
}
bool Serial2D::Load(File& file)
{
maxX = file.ReadFloat();
maxY=file.ReadFloat();
frameTime =file.ReadFloat();
fileName=file.ReadString();
opacityType = file.ReadInt();
return true;
}
void Serial2D::Clear()
{
maxX = 0.0f;
maxY=0.0f;
frameTime=0.0f;
fileName="";
}
SerialAnimator::SerialAnimator()
{
m_curTime = 0;
//当前播放格子序号
m_curIndex = 0;
m_serial2D = NULL;
m_texture = NULL;
}
void SerialAnimator::PlayAnim(Serial2D* animStyle)
{
if (m_serial2D==animStyle)
{
return;
}
m_serial2D = animStyle;
m_curTime = 0;
G_TextureMgr->AddTexture(m_texture,animStyle->fileName.c_str());
}
Serial2D* SerialAnimator::GetAnim()
{
return m_serial2D;
}
void SerialAnimator::GetExtend(int& width,int& height)
{
width = m_texture->GetWidth()/m_serial2D->maxX;
height = m_texture->GetHeight()/m_serial2D->maxY;
}
void SerialAnimator::GetExtend(float& width,float& height)
{
width = m_texture->GetWidth()/m_serial2D->maxX;
height = m_texture->GetHeight()/m_serial2D->maxY;
}
//cenPos drawRect中心
void SerialAnimator::Rend(const vec3& cenPos)
{
int maxX = m_serial2D->maxX;
int maxY = m_serial2D->maxY;
float xt = (m_curIndex % maxX);
xt /= maxX;
float yt = (m_curIndex / maxX);
yt /= maxY;
RectF srcRect(xt,yt,1.0f/maxX,1.0f/maxY);
float tarW = m_texture->GetWidth()/maxX;
float tarH = m_texture->GetHeight()/maxY;
G_RendDriver->SetRenderStateEnable(RS_TEXTURE_2D,true);
G_RendDriver->SetRenderStateEnable(RS_BLEND,true);
G_RendDriver->BlendFunc((BlendingType)m_serial2D->opacityType);
G_RendDriver->Color4f(1,1,1,1);
m_texture->Bind();
拖尾
//for (float f=0.8f;f>=0;f-=0.1f)
//{
// //G_RendDriver->Color4f(1,1,1,(1.0f-f)*0.05);
// G_RendDriver->Color4f((1.0f-f)*0.05,(1.0f-f)*0.05,(1.0f-f)*0.05,(1.0f-f)*0.05);
// //m_playerAnim[animAction].Rend(pos - m_speed*f*30);
// //G_RendDriver->DrawTextureRect(SRect(pos.x,pos.y-f*70,cellW,cellH),srcRect);
// float scale = 1/sqrt(f);
// G_RendDriver->DrawTextureRect(RectF(pos.x - cellW*(scale-1)/2,pos.y-cellH*(scale-1),cellW*scale,cellH*scale),srcRect);
//}
G_RendDriver->Color4f(1,1,1,1);
G_RendDriver->DrawTextureRect(RectF(cenPos.x-tarW/2,cenPos.y-tarH/2,tarW,tarH),srcRect);
//G_RendDriver->RendTrigon()
}
//面向速度时 旋转支点在中心cenPos
void SerialAnimator::Rend(const vec3& cenPos,const vec3& dir)
{
if (dir.LengthSq()<0.001f)
{
return Rend(cenPos);
}
int maxX = m_serial2D->maxX;
int maxY = m_serial2D->maxY;
float xt = (m_curIndex % maxX);
xt /= maxX;
float yt = (m_curIndex / maxX);
yt /= maxY;
RectF srcRect(xt,yt,1.0f/maxX,1.0f/maxY);
float tarW = m_texture->GetWidth()/maxX;
float tarH = m_texture->GetHeight()/maxY;
G_RendDriver->Color4f(1,1,1,1);
G_RendDriver->SetRenderStateEnable(RS_BLEND,true);
G_RendDriver->BlendFunc((BlendingType)m_serial2D->opacityType);
m_texture->Bind();
拖尾
//for (float f=0.8f;f>=0;f-=0.1f)
//{
// //G_RendDriver->Color4f(1,1,1,(1.0f-f)*0.05);
// G_RendDriver->Color4f((1.0f-f)*0.05,(1.0f-f)*0.05,(1.0f-f)*0.05,(1.0f-f)*0.05);
// //m_playerAnim[animAction].Rend(pos - m_speed*f*30);
// //G_RendDriver->DrawTextureRect(SRect(pos.x,pos.y-f*70,cellW,cellH),srcRect);
// float scale = 1/sqrt(f);
// G_RendDriver->DrawTextureRect(RectF(pos.x - cellW*(scale-1)/2,pos.y-cellH*(scale-1),cellW*scale,cellH*scale),srcRect);
//}
float dirRad = atan2(dir.y,dir.x);
dirRad += HALFPI;
dirRad*=-1;
dirRad += _PI;
G_RendDriver->Color4f(1,1,1,1);
G_RendDriver->DrawTextureRect(RectF(cenPos.x-tarW/2,cenPos.y-tarH/2,tarW,tarH),srcRect,vec2(tarW*0.5f,tarH*0.5f),dirRad,ET_SCALE);
}
bool SerialAnimator::Update()
{
if (m_serial2D==NULL)
{
return false;
}
bool isEnd = false;
m_curTime += G_Timer->GetStepTime();
m_curIndex = m_curTime/m_serial2D->frameTime;
int maxIndex = m_serial2D->maxX*m_serial2D->maxY;
if(m_curIndex>=maxIndex)
{
isEnd = true;
m_curTime -= m_serial2D->frameTime*maxIndex;
m_curIndex %= maxIndex;
}
return isEnd;
}
void SerialAnimator::SetIndex(int index)
{
m_curIndex = index;
if (m_curIndex<0)
{
m_curIndex = 0;
}
int maxIndex = m_serial2D->maxX*m_serial2D->maxY;
m_curIndex %= maxIndex;
}
bool Space2DEntityStyle::Load(File& file)
{
Clear();
name = file.ReadString();
description = file.ReadString();
ID = file.ReadInt();
assert(ID);
animStyles[SA_Normal].Load(file);
animStyles[SA_Exploide].Load(file);
//collideBox = SRect(file.ReadFloat(),file.ReadFloat(),file.ReadFloat(),file.ReadFloat());
collideBox.x = file.ReadFloat();
collideBox.y = file.ReadFloat();
collideBox.width = file.ReadFloat();
collideBox.height = file.ReadFloat();
maxSpeed = file.ReadFloat();
life = file.ReadFloat();
canDamage = file.ReadInt();
atackness = file.ReadFloat();
faceSpeed = file.ReadInt();
faceRole = file.ReadInt();
sound = file.ReadString();
//keepAnim
for (int i=0;i<SA_Num;i++)
{
G_TextureMgr->AddTexture(keepAnim[i],animStyles[i].fileName.c_str());
}
//
int width, height;
width = keepAnim[SA_Normal]->GetWidth()/animStyles[SA_Normal].maxX;
height = keepAnim[SA_Normal]->GetHeight()/animStyles[SA_Normal].maxY;
//collideBox.x = width*0.1;
//collideBox.y = height*0.1;
//collideBox.width = width*0.8;
//collideBox.height = height*0.8;
collideBox.x = width*0.0;
collideBox.y = height*0.0;
collideBox.width = width*1.0;
collideBox.height = height*1.0;
return true;
}
void Space2DEntityStyle::Clear()
{
for (int i=0;i<SA_Num;i++)
{
animStyles[i].Clear();
}
//collideBox = SRect(0.0f,0.0f,0.0f,0.0f);
collideBox.x = 0.0f;
collideBox.y = 0.0f;
collideBox.width = 0.0f;
collideBox.height = 0.0f;
maxSpeed = 0.0f;
life = 0.0f;
canDamage = 0;
atackness = 0.0f;
faceSpeed = 0;
}
Space2DEntity::Space2DEntity()
{
m_drawRect = RectF(0,0,0,0);
m_collideBox = RectF(0,0,0,0);
m_life=1;
m_atack=1;
m_speed=vec3(0,0,0);
m_pos = vec3(0,0,0);
m_sound = new SoundChannel3D;
}
Space2DEntity::~Space2DEntity()
{
SafeDelete(m_sound);
}
void Space2DEntity::Update()
{
bool animEnd = m_animator.Update();
m_liveTime += G_Timer->GetStepTimeLimited();
Space2DEntityStyle* style = GetStyle();
if(m_life>0)
{
m_pos.x += m_speed.x * G_Timer->GetStepTimeLimited();
m_pos.y += m_speed.y * G_Timer->GetStepTimeLimited();
//head
if (style->faceRole)
{
m_heading = G_SpaceWarGame->m_myRolePlayer->GetPos() - m_pos;
m_heading.Normalize();
}
else if (style->faceSpeed)
{
m_heading = m_speed;
m_heading.Normalize();
}
else
{
m_heading = vec3(0,1,0);
m_heading.Normalize();
}
}
else
{
m_speed = vec3(0,0,0);
if(animEnd)
{
SetToBeRemoved(true);
}
}
}
bool Space2DEntity::SetStyle(Style* style_)
{
MovingEntity::SetStyle(style_);
Space2DEntityStyle* style = (Space2DEntityStyle*)style_;
m_speed.y = style->maxSpeed;
m_maxSpeed = style->maxSpeed;
m_life = style->life;
m_atack = style->atackness;
m_collideBox = style->collideBox;
m_liveTime = 0;
m_animator.PlayAnim(&style->animStyles[SA_Normal]);
if (!GetStyle()->sound.empty())
{
m_sound->PlaySound__(GetStyle()->sound.c_str());
}
return true;
}
Space2DEntityStyle* Space2DEntity::GetStyle()
{
return dynamic_cast<Space2DEntityStyle*>(m_entityStyle);
}
void Space2DEntity::Render()
{
Space2DEntityStyle* style = GetStyle();
m_animator.GetExtend(m_drawRect.width,m_drawRect.height);
m_drawRect.x = m_pos.x -m_drawRect.width / 2;
m_drawRect.y = m_pos.y -m_drawRect.height / 2;
G_RendDriver->Color4f(1,1,1,1);
//m_pos drawRect中心
m_animator.Rend(m_pos,m_heading);
//画血条
if (m_life>0 && style->canDamage)
{
G_RendDriver->BlendFunc(RS_SRC_ALPHA, RS_ONE_MINUS_SRC_ALPHA);
G_RendDriver->Color3f(1.0f, 0.0f, 0.0f);
//RectF tar(-5,0,10,1);
float bloodWidth = m_drawRect.width*0.5f;
float bloodX = m_drawRect.x + m_drawRect.width*0.25f;
float bloodY = m_drawRect.y + m_drawRect.height + 5;
G_RendDriver->DrawRect(RectF(bloodX,bloodY,bloodWidth,5));
G_RendDriver->Color3f(0.0f, 1.0f, 0.0f);
G_RendDriver->DrawRect(RectF(bloodX,bloodY,bloodWidth*m_life/style->life,5));
}
G_RendDriver->BlendFunc(RS_SRC_ALPHA, RS_ONE_MINUS_SRC_ALPHA);
}
bool Space2DEntity::IsAnimState(SpaceAnimState state)
{
return m_animator.GetAnim() == &GetStyle()->animStyles[state];
}
bool Space2DEntity::Intersect(Space2DEntity *pOther)
{
return m_drawRect.IntersectRect(pOther->m_drawRect);
}
bool Space2DEntity::OutOfClient()
{
float space = 30;
return (m_pos.x+m_drawRect.width*0.5f <-space)
|| (m_pos.y+m_drawRect.height*0.5f <-space )
|| (m_pos.x-m_drawRect.height*0.5f > G_SpaceWarGame->m_width+space)
|| (m_pos.y-m_drawRect.height*0.5f > G_SpaceWarGame->m_height+space);
}
bool Space2DEntity::OutOfSight()
{
//m_pos 在图片中心
return (m_pos.x+m_drawRect.width*0.5f <0 )
|| (m_pos.y+m_drawRect.height*0.5f <0 )
|| (m_pos.x-m_drawRect.height*0.5f >G_SpaceWarGame->m_width )
|| (m_pos.y-m_drawRect.height*0.5f >G_SpaceWarGame->m_height);
}
bool SpacePlane2DStyle::Load(File& file)
{
Space2DEntityStyle::Load(file);
bulletType = file.ReadString();
/
propellerNum = file.ReadInt();
for (int i=0;i<propellerNum;i++)
{
propellerPos[i].x = file.ReadFloat();
propellerPos[i].y = file.ReadFloat();
}
if (propellerNum>0)
{
//?只有一种类型的propeller
propellerAnimStyles[SA_Normal].Load(file);
}
//keepAnim
for (int i=0;i<SA_Num;i++)
{
G_TextureMgr->AddTexture(propellerKeepAnim[i],propellerAnimStyles[i].fileName.c_str());
}
///
gunNum = file.ReadInt();
for (int i=0;i<gunNum;i++)
{
gunPos[i].x = file.ReadFloat();
gunPos[i].y = file.ReadFloat();
}
if (gunNum>0)
{
//?只有一种类型的gun
gunAnimStyles[SA_Normal].Load(file);
gunAnimStyles[SA_Exploide].Load(file);
gunAnimStyles[SA_Fire].Load(file);
}
//keepAnim
for (int i=0;i<SA_Num;i++)
{
G_TextureMgr->AddTexture(gunKeepAnim[i],gunAnimStyles[i].fileName.c_str());
}
return true;
}
SpacePlane2D::SpacePlane2D()
{
}
void SpacePlane2D::Update()
{
Space2DEntity::Update();
SpacePlane2DStyle* style = GetStyle();
if(m_life>0)
{
bool animEnd = m_propellerAnimator.Update();
animEnd = m_gunAnimator.Update();
if (animEnd)
{
//开火动画不循环
if (m_gunAnimator.GetAnim() == &style->gunAnimStyles[SA_Fire])
{
m_gunAnimator.PlayAnim(&style->gunAnimStyles[SA_Normal]);
}
}
//非循环动画
m_animator.SetIndex((1-m_pos.x/G_SpaceWarGame->m_width)*13);
//ufo 类似循环动画使用螺旋浆绘制
}
}
void SpacePlane2D::Render()
{
Space2DEntity::Render();
SpacePlane2DStyle* style = GetStyle();
for (int i=0;i<style->gunNum;i++)
{
m_gunAnimator.Rend(m_pos+style->gunPos[i],m_heading);
}
for (int i=0;i<style->propellerNum;i++)
{
m_propellerAnimator.Rend(m_pos+style->propellerPos[i],m_heading);
}
}
bool SpacePlane2D::SetStyle(Style* style_)
{
Space2DEntity::SetStyle(style_);
SpacePlane2DStyle* style = (SpacePlane2DStyle*)style_;
m_bulletStyle = G_StyleMgr->GetStyle<Space2DBulletStyle>(style->bulletType.c_str());
if(style->propellerNum>0)
m_propellerAnimator.PlayAnim(&style->propellerAnimStyles[SA_Normal]);
if(style->gunNum>0)
m_gunAnimator.PlayAnim(&style->gunAnimStyles[SA_Normal]);
SetLastFireTime();
return true;
}
SpacePlane2DStyle* SpacePlane2D::GetStyle()
{
return dynamic_cast<SpacePlane2DStyle*>(m_entityStyle);
}
void SpacePlane2D::Fire()
{
}
void SpacePlane2D::SetLastFireTime()
{
if(m_bulletStyle)
m_lastFireTime = G_Timer->GetAccumTime() - RandRange(0.f,m_bulletStyle->fireInterval);
}
敌机:
//========================================================
// @Date: 2016.05
// @File: SourceDemoClient/SpaceWar2D/Monster2D.h
// @Brief: Monster2D
// @Author: LouLei
// @Email: twopointfive@163.com
// @Copyright (Crapell) - All Rights Reserved
//========================================================
#ifndef __Monster2D__H__
#define __Monster2D__H__
#include "Space2DEntity.h"
class Space2DBullet;
class SpaceWar2DGame;
//
struct Space2DEnermyStyle:public SpacePlane2DStyle
{
public:
enum AIType
{
MoveForward = 1,
MoveLRF,
MoveSin,
};
DeclareStyleEnum(Space2DEnermyStyle ,101001);
virtual bool Load(File& file);
void Clear();
//终极boss 可能有多种子弹
//掉落物品类型
String itemType;
//掉落物品几率
float itemChance;
AIType aiType;
};
class Space2DEnermy:public SpacePlane2D
{
friend class EnermySpawner;
public:
Space2DEnermy();
virtual void Update();
virtual void Render();
virtual Space2DEnermyStyle* GetStyle();
virtual bool SetStyle(Style* style);
virtual void Fire();
void UpdateCollision();
};
class Enermy_Ufo:public Space2DEnermy
{
public:
enum Direction
{
DIR_LEFT,
DIR_RIGHT,
DIR_FORWARD
};
Enermy_Ufo();
void Update();
//曲线运动的位置
float GetPathPosX(float y);
Direction m_direction;
vec3 m_onCarrierPos;
float m_sin1;
float m_sin2;
};
//struct SpaceCarrier2DStyle:public SpaceEnermy2DStyle
//{
//public:
// DeclareStyleEnum(SpaceCarrier2DStyle ,105001);
// virtual bool Load(File& file);
// void Clear();
// int planeNum;
//#define MaxPlane 12
// String planeName[MaxPlane];
// vec3 planePos[MaxPlane];
//
//};
//
母舰
//class Enermy_Carrier:public Enermy_Ufo
//{
//public:
// Enermy_Carrier();
//};
#endif
//========================================================
// @Date: 2016.05
// @File: SourceDemoClient/SpaceWar2D/Monster2D.cpp
// @Brief: Monster2D
// @Author: LouLei
// @Email: twopointfive@163.com
// @Copyright (Crapell) - All Rights Reserved
//========================================================
#include "General/Pch.h"
#include "General/Timer.h"
#include "SpaceWar2D/Space2DItem.h"
#include "SpaceWar2D/SpaceBullet2D.h"
#include "SpaceWar2D/Space2DEnermy.h"
#include "SpaceWar2D/Space2DRole.h"
#include "SpaceWar2D/MiniGameSpace2DWar.h"
#include "General/File.h"
#include "Sound/ChannelSound.h"
#include "General/Pce.h"
CheckStyleEnum(Space2DEnermyStyle)
bool Space2DEnermyStyle::Load(File& file)
{
Clear();
SpacePlane2DStyle::Load(file);
itemType = file.ReadString();
itemChance = file.ReadFloat();
aiType = (AIType)file.ReadInt();
//aiType = (AIType)3;
return true;
}
void Space2DEnermyStyle::Clear()
{
bulletType = "";
fireIntervalRat = 1;
//SpriteStyle::Clear();
}
///
Space2DEnermy::Space2DEnermy()
{
m_speed.x=0;
m_lastFireTime=0;
m_lastFireTime = 0;
// m_carrierShip = NULL;
}
bool Space2DEnermy::SetStyle(Style* style_)
{
SpacePlane2D::SetStyle(style_);
return true;
}
Space2DEnermyStyle* Space2DEnermy::GetStyle()
{
return dynamic_cast<Space2DEnermyStyle*>(m_entityStyle);
}
void Space2DEnermy::Render()
{
//SpacePlane2D::Render();
Space2DEntity::Render();
SpacePlane2DStyle* style = GetStyle();
float dirRad = atan2(m_heading.y,m_heading.x);
dirRad += HALFPI;
dirRad += _PI;
//朝向下时mat为单位矩阵
//dirRad*=-1;
m_mat.FromRotateZ(dirRad);
vec3 rolePos = G_SpaceWarGame->m_myRolePlayer->GetPos();
vec3 pos;
vec3 dir;
for (int i=0;i<style->gunNum;i++)
{
//旋转后位置会变
pos = m_pos+m_mat*style->gunPos[i];
dir = rolePos - pos;
m_gunAnimator.Rend(pos,dir);
}
if (m_life>0)
{
//爆炸了就不绘制ufo的螺旋桨
for (int i=0;i<style->propellerNum;i++)
{
pos = m_pos+m_mat*style->propellerPos[i];
m_propellerAnimator.Rend(pos,m_heading);
}
}
}
void Space2DEnermy::Update()
{
UpdateCollision();
SpacePlane2D::Update();
SpacePlane2DStyle* style = GetStyle();
//
if(m_life<=0)
{
if(IsAnimState(SA_Normal))
{
m_sound->PlaySound__("data/sound/event_exploid01.wav",false);
m_animator.PlayAnim(&style->animStyles[SA_Exploide]);
m_gunAnimator.PlayAnim(&style->gunAnimStyles[SA_Exploide]);
G_SpaceWarGame->m_myRolePlayer->m_killEnermy++;
G_SpaceWarGame->m_myRolePlayer->m_score += GetStyle()->life;
}
}
if (IsToBeRemoved())
{
if ((Rand()%100)/100.0f < GetStyle()->itemChance)
{
//掉落
Space2DItem *item = new Space2DItem();
item->SetPos(m_pos);
Space2DItemStyle* style = G_StyleMgr->GetStyle<Space2DItemStyle>(GetStyle()->itemType.c_str());
item->SetStyle(style);
G_EntityMgr->RegisterEntity(item,Enum_EntityGroup(ItemGroup));
}
}
if( OutOfClient() && m_pos.y >= G_SpaceWarGame->m_height )
{
SetToBeRemoved(true);
}
}
void Space2DEnermy::Fire()
{
if( m_bulletStyle==NULL
|| G_Timer->GetAccumTime() - m_lastFireTime < m_bulletStyle->fireInterval )
return;
Space2DEnermyStyle* style = GetStyle();
m_gunAnimator.PlayAnim(&style->gunAnimStyles[SA_Fire]);
//如果飞船面向玩家 需要调整子弹发射角度
float centerAngle = 270;
//如果炮台个数大于0
if (style->gunNum>0)
{
//在炮台处发射子弹
for (int gun=0;gun<style->gunNum;gun++)
{
int bulletNum = m_bulletStyle->bulletNum;
Space2DBullet *pNewBullet;
vec3 gunPos = m_pos+m_mat*style->gunPos[gun];
//所有gun 默认facerole
//if (gun->faceRole)
{
vec3 dir = G_SpaceWarGame->m_myRolePlayer->GetPos()-gunPos;
centerAngle = atan2(dir.y,dir.x)*RAD2DEG;
//centerAngle += 90;
centerAngle *= -1;
}
float gunW,gunH;
m_gunAnimator.GetExtend(gunW,gunH);
//沿着扇弧发射子弹
float startAng = 0;
float step = 0;
if (bulletNum > 1)
{
startAng = /*270*/centerAngle - m_bulletStyle->bulletFov/2.0f;
step = m_bulletStyle->bulletFov/(bulletNum-1);
}
else
{
startAng = /*270*/centerAngle;
step = 0;
}
vec3 bulletPos,bulletDir;
for(int i=0; i<bulletNum; i++)
{
//use matrix
float angle = (startAng+i*step)*DEG2RAD;
bulletDir.x = cos( angle);
bulletDir.y = -sin( angle );
//推前, 也可能是战舰上的炮位
bulletPos = gunPos +bulletDir*(gunH*0.5f);
pNewBullet=new Space2DBullet(style->bulletType,bulletDir);
pNewBullet->SetPos(bulletPos);
pNewBullet->SetParentSpeed(m_speed);
G_EntityMgr->RegisterEntity(pNewBullet,Enum_EntityGroup(EnemyBulletGroup));
}
}
}
else
{
//在飞船前面发射子弹
int bulletNum = m_bulletStyle->bulletNum;
Space2DBullet *pNewBullet;
if (style->faceRole || style->faceSpeed)//? face speed?
{
centerAngle = atan2(m_speed.y,m_speed.x)*RAD2DEG;
//centerAngle += 90;
centerAngle *= -1;
}
//沿着扇弧发射子弹
float startAng = /*270*/centerAngle - m_bulletStyle->bulletFov/2.0f;
float step = 0;
if (bulletNum > 1)
step = m_bulletStyle->bulletFov/(bulletNum-1);
vec3 bulletPos,bulletDir;
for(int i=0; i<bulletNum; i++)
{
//use matrix
float angle = (startAng+i*step)*DEG2RAD;
bulletDir.x = cos( angle);
bulletDir.y = -sin( angle );
//推前, 也可能是战舰上的炮位
bulletPos = m_pos +bulletDir*(m_drawRect.height*0.5f);
pNewBullet=new Space2DBullet(style->bulletType,bulletDir);
pNewBullet->SetPos(bulletPos);
pNewBullet->SetParentSpeed(m_speed);
G_EntityMgr->RegisterEntity(pNewBullet,Enum_EntityGroup(EnemyBulletGroup));
}
}
m_lastFireTime = G_Timer->GetAccumTime();
}
void Space2DEnermy::UpdateCollision()
{
Space2DRole* pPlayer = G_SpaceWarGame->m_myRolePlayer;
EntityGroupRef playerBullets(Enum_EntityGroup(PlayerBulletGroup));
Space2DBullet* pBullet = (Space2DBullet*)(playerBullets.GetFirst());
// 遍历玩家子弹
while(pBullet)
{
if(m_life <= 0)
return;
if(pBullet->m_life > 0)
{
if(Intersect(pBullet))
{
this->m_life -= pBullet->m_atack;
//子弹血量
pBullet->m_life -= this->m_atack;
}
}
pBullet = (Space2DBullet*)playerBullets.GetNext();
}
}
//void SpaceEnermy2D::SetCarrier(SpaceEnermy2D* carrier)
//{
// m_carrierShip = carrier;
//}
Enermy_Ufo::Enermy_Ufo()
{
m_direction=DIR_FORWARD;
}
void Enermy_Ufo::Update()
{
Space2DEnermy::Update();
if(m_life<=0) return;
Space2DEnermyStyle* style = GetStyle();
if(m_life>0 && m_pos.y>10)
{
Fire();
}
switch(GetStyle()->aiType)
{
case Space2DEnermyStyle::MoveLRF:
{
switch( m_direction )
{
case DIR_LEFT:
m_speed.x = -fabs(m_speed.y)*4;
if( m_pos.x<0 )
{
m_speed.x = 0;
m_direction = DIR_FORWARD;
}
break;
case DIR_RIGHT:
{
m_speed.x = fabs(m_speed.y)*4;
if( m_pos.x > G_SpaceWarGame->m_width )
{
m_speed.x = 0;
m_direction = DIR_FORWARD;
}
break;
}
default:
m_speed.x = 0;
break;
}
if( Rand() < 5000*G_Timer->GetStepTimeLimited() )
m_direction = ( Direction ) ( Rand() % 3 );
}
break;
case Space2DEnermyStyle::MoveSin:
{
//WANDER曲线 posx 是以posy为自变量的函数
if (m_pos.y>200)
{
//曲线接近水平的时候 不可移动太快 调整speedY
float tryY = m_pos.y + (m_maxSpeed-m_speed.y);
float tryX = GetPathPosX(tryY);
float trySpeedX = tryX - m_pos.x;
vec2 normSpeed(trySpeedX,GetStyle()->maxSpeed);
normSpeed.Normalize();
m_speed.y = GetStyle()->maxSpeed* normSpeed.y;
}
m_pos.x = GetPathPosX(m_pos.y);
}
//break;
}
//head
if (style->faceRole)
{
m_heading = G_SpaceWarGame->m_myRolePlayer->GetPos() - m_pos;
m_heading.Normalize();
}
else if (style->faceSpeed)
{
m_heading = m_speed;
m_heading.Normalize();
}
else
{
m_heading = vec3(0,1,0);
m_heading.Normalize();
}
}
float Enermy_Ufo::GetPathPosX(float y)
{
//WANDER曲线
float t1 = y/G_SpaceWarGame->m_height; //0~1
float t2 = t1*2;
float x = G_SpaceWarGame->m_width*0.5f
+G_SpaceWarGame->m_width*0.45f* ( sin(m_sin1 * t1) * cos(m_sin2 * t1))
+G_SpaceWarGame->m_width*0.45f*0.45f*( sin(m_sin1 * t2) * cos(m_sin2 * t2));
return x;
}
//CheckStyleEnum(SpaceCarrier2DStyle)
//bool SpaceCarrier2DStyle::Load(File& file)
//{
// Clear();
// SpaceEnermy2DStyle::Load(file);
// planeNum = file.ReadInt();
// for (int i=0;i<planeNum;i++)
// {
// planeName[i] = file.ReadString();
// planePos[i].x = file.ReadFloat();
// planePos[i].y = file.ReadFloat();
// }
// return true;
//}
//
//void SpaceCarrier2DStyle::Clear()
//{
// SpaceEnermy2DStyle::Clear();
//
//}
//Enermy_Carrier::Enermy_Carrier()
//{
//}
子弹
//========================================================
// @Date: 2016.05
// @File: SourceDemoClient/SpaceWar2D/Item2D.h
// @Brief: Item2D
// @Author: LouLei
// @Email: twopointfive@163.com
// @Copyright (Crapell) - All Rights Reserved
//========================================================
#ifndef __SpaceBullet2D__H__
#define __SpaceBullet2D__H__
#include "Space2DEntity.h"
class Space2DRole;
//
struct Space2DBulletStyle:public Space2DEntityStyle
{
public:
DeclareStyleEnum(Space2DBulletStyle ,102001);
virtual bool Load(File& file);
void Clear();
//间隔
float fireInterval;
//间隔差异率
float fireIntervalVariation;
//个数 角度
float bulletNum;
float bulletFov;
//是否瞄准?
//是否继承发射者速度
int addParentSpeed;
//是否制导
int bNavigate;
//制导发射的密集一些 变成雷电形??
};
// 定义子弹基类
class Space2DBullet:public Space2DEntity
{
public:
Space2DBullet(String bullettype, const vec3& dir);
virtual void Update();
virtual void Render();
virtual Space2DBulletStyle* GetStyle();
virtual bool SetStyle(Style* style);
void SetParentSpeed(vec3& parentSpeed);
Space2DEntity* m_navCharacter;
};
#endif
//========================================================
// @Date: 2016.05
// @File: SourceDemoClient/SpaceWar2D/Item2D.cpp
// @Brief: Item2D
// @Author: LouLei
// @Email: twopointfive@163.com
// @Copyright (Crapell) - All Rights Reserved
//========================================================
#include "General/Pch.h"
#include "Render/DeferredRender.h"
#include "SpaceWar2D/Space2DItem.h"
#include "SpaceWar2D/SpaceBullet2D.h"
#include "SpaceWar2D/Space2DRole.h"
#include "SpaceWar2D/Space2DEnermy.h"
#include "SpaceWar2D/MiniGameSpace2DWar.h"
#include "General/File.h"
#include "Sound/ChannelSound.h"
#include "General/Pce.h"
CheckStyleEnum(Space2DBulletStyle)
bool Space2DBulletStyle::Load(File& file)
{
Clear();
Space2DEntityStyle::Load(file);
fireInterval = file.ReadFloat();
fireIntervalVariation = 0.1f;
bulletNum = file.ReadFloat();
bulletFov = file.ReadFloat();
addParentSpeed = file.ReadInt();
bNavigate = file.ReadInt();
return true;
}
void Space2DBulletStyle::Clear()
{
name = "";
//SpriteStyle::Clear();
fireInterval = 0.0f;
bulletNum = 0.0f;
bulletFov = 0.0f;
faceSpeed = 0;
}
Space2DBullet::Space2DBullet(String type_, const vec3& dir)
:m_navCharacter(NULL)
{
Space2DBulletStyle* style = G_StyleMgr->GetStyle<Space2DBulletStyle>(type_.c_str());
SetStyle(style);
m_speed = dir * style->maxSpeed;
};
bool Space2DBullet::SetStyle(Style* style_)
{
Space2DEntity::SetStyle(style_);
Space2DBulletStyle* style = (Space2DBulletStyle*)style_;
//m_animator.PlayAnim(&style->animStyles[SA_Normal]);
return true;
}
Space2DBulletStyle* Space2DBullet::GetStyle()
{
return dynamic_cast<Space2DBulletStyle*>(m_entityStyle);
}
void Space2DBullet::SetParentSpeed(vec3& parentSpeed)
{
if (GetStyle()->addParentSpeed)
{
m_speed += parentSpeed;
}
}
void Space2DBullet::Update()
{
if(OutOfClient())
{
SetToBeRemoved(true);
}
Space2DEntity::Update();
//2~3 秒走完
//attack 每隔 0.5s 减至0.9
float step = 0.5f;
if(m_liveTime>step)
{
m_atack = GetStyle()->atackness*pow(0.9f,m_liveTime/step);
}
if(m_life<=0)
{
if(IsAnimState(SA_Normal))
{
m_animator.PlayAnim(&GetStyle()->animStyles[SA_Exploide]);
}
}
//制导
if (GetStyle()->bNavigate)
{
// 遍历敌机
Space2DEnermy* pEnermyTarget = NULL;
EntityGroupRef enermys(Enum_EntityGroup(EnemyGroup));
Space2DEnermy* pEnermy = (Space2DEnermy*)enermys.GetFirst();
//if (m_navCharacter->IsToBeRemoved())
//{
//}
float distSq = 9999999;
while(pEnermy)
{
if(pEnermy->m_life>0)
{
float lenSq = (pEnermy->GetPos()-GetPos()).LengthSq();
if (lenSq<distSq)
{
distSq = lenSq;
pEnermyTarget = pEnermy;
if (distSq < 10000)
{
break;
}
}
}
pEnermy = (Space2DEnermy*)enermys.GetNext();
}
if (pEnermyTarget)
{
m_navCharacter = pEnermyTarget;
vec3 navSpeed = pEnermyTarget->GetPos()-GetPos();
navSpeed.Normalize();
navSpeed *= GetStyle()->maxSpeed;
m_speed = Lerp(m_speed,navSpeed,0.1f);
}
}
}
void Space2DBullet::Render()
{
Space2DEntity::Render();
}
奖子
//========================================================
// @Date: 2016.05
// @File: SourceDemoClient/SpaceWar2D/Item2D.h
// @Brief: Item2D
// @Author: LouLei
// @Email: twopointfive@163.com
// @Copyright (Crapell) - All Rights Reserved
//========================================================
#ifndef __Item2D__H__
#define __Item2D__H__
#include "Space2DEntity.h"
class Space2DRole;
//奖子
enum ItemType
{
//弹夹
caisson_firedragon = 0, //火龙
caisson_lightning, //闪电
caisson_blitzball, //闪电球
caisson_frozen, //冻结枪
caisson_rocket, //导弹
//
IT_Gold, //金币
IT_Denender, //防护罩
IT_AddMySpeed, //加减速度
IT_AddEnemySpeed,//加减敌速
IT_ItemCollector,//奖子收集器
IT_Fog, //迷雾
ITEM_TYPE_COUNT
};
const char* ItemTypeToString(int gt);
struct Space2DItemStyle:public Space2DEntityStyle
{
public:
DeclareStyleEnum(Space2DItemStyle ,103001);
virtual bool Load(File& file);
String bulletType;
};
class Space2DItem:public Space2DEntity
{
public:
Space2DItem();
void Update();
virtual Space2DItemStyle* GetStyle();
virtual bool SetStyle(Style* style);
bool viewUnknow;//显示问号
};
//
struct SpaceEnvironment2DStyle:public Space2DEntityStyle
{
public:
DeclareStyleEnum(SpaceEnvironment2DStyle ,104001);
virtual bool Load(File& file);
};
//装饰物
class SpaceEnvironment2D:public Space2DEntity
{
public:
SpaceEnvironment2D();
void Update();
virtual SpaceEnvironment2DStyle* GetStyle();
virtual bool SetStyle(Style* style);
};
#endif
//========================================================
// @Date: 2016.05
// @File: SourceDemoClient/SpaceWar2D/Item2D.cpp
// @Brief: Item2D
// @Author: LouLei
// @Email: twopointfive@163.com
// @Copyright (Crapell) - All Rights Reserved
//========================================================
#include "General/Pch.h"
#include "Render/DeferredRender.h"
#include "SpaceWar2D/Space2DItem.h"
#include "SpaceWar2D/Space2DRole.h"
#include "SpaceWar2D/Space2DEnermy.h"
#include "SpaceWar2D/MiniGameSpace2DWar.h"
#include "General/File.h"
#include "Sound/ChannelSound.h"
#include "General/Pce.h"
const char* ItemTypeToString(int gt)
{
switch(gt)
{
case caisson_firedragon:
return "caisson_firedragon";
case caisson_lightning:
return "caisson_lightning";
case caisson_blitzball:
return "caisson_blitzball";
case ITEM_TYPE_COUNT:
return "ITEM_TYPE_COUNT";
default:
return "UNKNOWN GOAL TYPE!";
}
}
CheckStyleEnum(Space2DItemStyle)
bool Space2DItemStyle::Load(File& file)
{
Space2DEntityStyle::Load(file);
bulletType = file.ReadString();
return true;
}
Space2DItem::Space2DItem()
{
m_speed.x=0;
}
bool Space2DItem::SetStyle(Style* style_)
{
Space2DEntity::SetStyle(style_);
Space2DItemStyle* style = (Space2DItemStyle*)style_;
//m_animator.PlayAnim(&style->animStyles[SA_Normal]);
return true;
}
Space2DItemStyle* Space2DItem::GetStyle()
{
return dynamic_cast<Space2DItemStyle*>(m_entityStyle);
}
void Space2DItem::Update()
{
Space2DRole *pPlayer = G_SpaceWarGame->m_myRolePlayer;
Space2DItemStyle* style = GetStyle();
//if( this->Life <= 0 || pBullet->Life <= 0 ) return;
if(Intersect(pPlayer))
{
pPlayer->m_life += 1;
//this delete no sound
pPlayer->m_sound->PlaySound__("data/sound/ui_coin01.wav",false);
//if (style->bulletType == caisson_firedragon)
//{
// G_AfterEffectMgr->BeginAfterEffect(Effect_Twirl,Layer_Scene);
//}
//else if (m_objType == caisson_lightning)
//{
// G_AfterEffectMgr->BeginAfterEffect(Effect_RockPaint,Layer_Scene);
//}
//else if (m_objType == caisson_blitzball)
//{
// G_AfterEffectMgr->BeginAfterEffect(Effect_RockPaint,Layer_Scene);
//}
SetToBeRemoved(true);
//pPlayer->bulletCount["player_bullet_lightning"] += 1;
pPlayer->ChangeWeapon(style->bulletType.c_str());
}
Space2DEntity::Update();
if( OutOfClient() && m_pos.y>=G_SpaceWarGame->m_height )
{
SetToBeRemoved(true);
}
}
//==================^_^==================^_^==================^_^==================^_^
CheckStyleEnum(SpaceEnvironment2DStyle)
bool SpaceEnvironment2DStyle::Load(File& file)
{
Space2DEntityStyle::Load(file);
return true;
}
SpaceEnvironment2D::SpaceEnvironment2D()
{
m_speed.x=0;
}
bool SpaceEnvironment2D::SetStyle(Style* style_)
{
Space2DEntity::SetStyle(style_);
SpaceEnvironment2DStyle* style = (SpaceEnvironment2DStyle*)style_;
m_animator.PlayAnim(&style->animStyles[SA_Normal]);
return true;
}
SpaceEnvironment2DStyle* SpaceEnvironment2D::GetStyle()
{
return dynamic_cast<SpaceEnvironment2DStyle*>(m_entityStyle);
}
void SpaceEnvironment2D::Update()
{
Space2DRole *pPlayer = G_SpaceWarGame->m_myRolePlayer;
SpaceEnvironment2DStyle* style = GetStyle();
//if( this->Life <= 0 || pBullet->Life <= 0 ) return;
//if(Intersect(pPlayer))
//{
// pPlayer->m_life += 1;
// //if (style->bulletType == caisson_firedragon)
// //{
// // G_AfterEffectMgr->BeginAfterEffect(Effect_Twirl,Layer_Scene);
// //}
// //else if (m_objType == caisson_lightning)
// //{
// // G_AfterEffectMgr->BeginAfterEffect(Effect_RockPaint,Layer_Scene);
// //}
// //else if (m_objType == caisson_blitzball)
// //{
// // G_AfterEffectMgr->BeginAfterEffect(Effect_RockPaint,Layer_Scene);
// //}
// SetToBeRemoved(true);
// //pPlayer->bulletCount["player_bullet_lightning"] += 1;
// pPlayer->ChangeWeapon(style->bulletType.c_str());
//}
Space2DEntity::Update();
if( OutOfClient() && m_pos.y>=G_SpaceWarGame->m_height )
{
SetToBeRemoved(true);
}
}
完