dev.nlited.com

>>

Item.cpp

<<<< prev
next >>>>

2016-01-27 00:52:20 chip Page 1547 📢 PUBLIC


Item.cpp: /*************************************************************************/ /** Item.cpp: Manage individual items. **/ /** (C)2013 nlited systems inc, Chip Doran **/ /*************************************************************************/ #include #include #include "Util.h" #include "MyD2D.h" #include "Sprite.h" #include "Globals.h" using namespace D2D1; class Item { //Base class for all items. public: static Item *Ptr(HITEM hItem); static int Create(HITEM *phItem, UINT TypeID, HITEM hSrc); virtual int Destroy(void); struct ItemLink_s *GetLink(void); virtual int Update(HITEMS hItems, UINT Tick); virtual int Collision(HITEMS hItems); virtual int Explode(HITEMS hItems, HITEM hKiller); virtual int Draw(HIMAGE hImg); //Data //Link is used by ItemList.cpp to manage the linked list of items. struct ItemLink_s Link; //Must be at the top of the struct! UINT PlayerID; //Owner PlayerID struct Sprite_s Sprite; //Sprite information protected: Item(UINT ItemID); ~Item(void); int Create2(HITEM hSrc); void UpdateRebound(const RECT &rArena); void UpdateWrap(const RECT &rArena); //Data private: //Data bool DoRebound; //Do items rebound or wraparound? }; class Rocket:Item { friend class Item; //Visibility into Item protected members. public: static int Create(HITEM *phItem, HITEM hSrc); int Update(HITEMS hItems, UINT Tick); //Data private: Rocket(void); void UpdateRotation(UINT CtrlState); //Data bool DoRotationalMomentum; //Simple or momentum rotation? UINT NextFire; //When rocket can fire another bullet }; class Bullet:Item { friend class Item; public: static int Create(HITEM *phItem, HITEM hSrc); int Update(HITEMS hItems, UINT Tick); int Collision(HITEMS hItems); //Data private: Bullet(void); int Create2(HITEM hSrc); //Data UINT TimeOut; //When bullet expires }; class Rock:Item { friend class Item; public: static int Create(HITEM *phItem, HITEM hSrc); int Explode(HITEMS hItems, HITEM hSrc); //Data private: Rock(void); //Data }; static __inline FLOAT RandF(void) { return((FLOAT)rand()/RAND_MAX); } static __inline UINT RandI(UINT Limit) { return((UINT)(RandF()*Limit)); } #define THRUST_ANGLE (90.0f) static __inline FLOAT DegToRad(FLOAT Deg) { return((3.14159f*2.0f)*((Deg-THRUST_ANGLE)/360.0f)); } UINT ExplodeShrinkage= 75; UINT ExplodeFragment= 40; static bool IsCollision(D2D_POINT_2F &Pt, D2D_POINT_2F &Obj, UINT Size) { double Dist; Dist= fmax(fabs(Obj.x-Pt.x),fabs(Obj.y-Pt.y)); if((UINT)Dist <= Size/2) { return(1); } return(0); } /*************************************************************************/ /** Public interface **/ /*************************************************************************/ int ItemCreate(HITEM *phItem, UINT ItemID, HITEM hSrc) { if(IsBadPtr(phItem,sizeof(*phItem),BADPTR_WRITE)) return(ERR_BADPTR); switch(ItemID) { case ITEM_ROCKET: return(Rocket::Create(phItem,hSrc)); case ITEM_BULLET: return(Bullet::Create(phItem,hSrc)); case ITEM_ROCK: return(Rock::Create(phItem,hSrc)); } return(Warn(ERR_BADTYPE,__FUNCTION__": Invalid ItemID[%d]",ItemID)); } int ItemDestroy(HITEM hItem) { Item *pItem= Item::Ptr(hItem); if(!pItem) return(Warn(ERR_BADHANDLE,__FUNCTION__": Bad hItem[%X]",hItem)); return(pItem->Destroy()); } struct ItemLink_s *ItemGetLink(HITEM hItem) { Item *pItem= Item::Ptr(hItem); if(!pItem) return(0); return(pItem->GetLink()); } int ItemUpdate(HITEM hItem, HITEMS hList, UINT Tick) { Item *pItem= Item::Ptr(hItem); if(!pItem) return(Warn(ERR_BADHANDLE,__FUNCTION__": Bad hItem[%X]",hItem)); return(pItem->Update(hList,Tick)); } int ItemCollision(HITEM hItem, HITEMS hList) { Item *pItem= Item::Ptr(hItem); if(!pItem) return(Warn(ERR_BADHANDLE,__FUNCTION__": Bad hItem[%X]",hItem)); return(pItem->Collision(hList)); } int ItemDraw(HITEM hItem, HIMAGE hImg) { Item *pItem= Item::Ptr(hItem); if(!pItem) return(Warn(ERR_BADHANDLE,__FUNCTION__": Bad hItem[%X]",hItem)); return(pItem->Draw(hImg)); } /*************************************************************************/ /** Public internals **/ /*************************************************************************/ /** Base Item **/ /*************************************************************************/ Item *Item::Ptr(HITEM hItem) { Item *pItem= (Item*)hItem; if(!hItem || IsBadPtr(pItem,sizeof(*pItem),BADPTR_RW) || pItem->Link.Signature!=SIGNATURE_ITEM) pItem= 0; return(pItem); } int Item::Destroy(void) { int Err= ERR_OK; delete this; return(Err); } struct ItemLink_s *Item::GetLink(void) { return(&Link); } int Item::Update(HITEMS hItems, UINT Tick) { int Err= ERR_OK; RECT rArena; ItemsGetArena(hItems,&rArena); Sprite.PosPrev= Sprite.Pos; Sprite.RotationPrev= Sprite.Rotation; Sprite.FrameIDPrev= Sprite.FrameID; Sprite.Pos.x+= Sprite.PosVel.x; Sprite.Pos.y+= Sprite.PosVel.y; if(DoRebound) UpdateRebound(rArena); else UpdateWrap(rArena); Sprite.Rotation+= Sprite.RotationVel; Sprite.FrameID= RandI(2); return(Err); } int Item::Collision(HITEMS hItems) { int Err= ERR_OK; return(Err); } int Item::Explode(HITEMS hItems, HITEM hKiller) { int Err= ERR_OK; return(Err); } int Item::Draw(HIMAGE hImg) { int Err= ERR_OK; ImgAddSprite(hImg,&Sprite); return(Err); } /*************************************************************************/ /** Private internals **/ /*************************************************************************/ Item::Item(UINT ItemID) { memset(this,0,sizeof(*this)); Link.Signature= SIGNATURE_ITEM; Link.hItem= (HITEM)this; Link.ItemID= ItemID; DoRebound= 0; Sprite.SpriteID= SPRITE_BOX; Sprite.BitmapID= 0; Sprite.Color= ColorF(RandF(),RandF(),RandF(),RandF()); Sprite.Pos= Sprite.PosPrev= Point2F(0,0); Sprite.PosVel.x= RandF(); Sprite.PosVel.y= RandF(); Sprite.Rotation= Sprite.RotationPrev= 0.0f; Sprite.RotationVel= RandF()*2.0f-1.0f; Sprite.Size= (UINT)(RandF()*100); Sprite.FrameID= Sprite.FrameIDPrev= 0; } Item::~Item(void) { Link.Signature|= SIGNATURE_INVALID; } int Item::Create2(HITEM hSrc) { int Err= ERR_OK; Item *pSrc= Ptr(hSrc); if(pSrc) { PlayerID= pSrc->PlayerID; Sprite.Pos= pSrc->Sprite.Pos; Sprite.PosVel= pSrc->Sprite.PosVel; Sprite.Rotation= pSrc->Sprite.Rotation; Sprite.RotationVel= pSrc->Sprite.RotationVel; } return(Err); } void Item::UpdateRebound(const RECT &rArena) { if(Sprite.Pos.x <= rArena.left) { Sprite.PosVel.x= (FLOAT)fabs(Sprite.PosVel.x); Sprite.Pos.x= rArena.left+Sprite.PosVel.x; } else if(Sprite.Pos.x >= rArena.right) { Sprite.PosVel.x= -(FLOAT)fabs(Sprite.PosVel.x); Sprite.Pos.x= rArena.right+Sprite.PosVel.x; } if(Sprite.Pos.y <= rArena.top) { Sprite.PosVel.y= (FLOAT)fabs(Sprite.PosVel.y); Sprite.Pos.y= rArena.top+Sprite.PosVel.y; } else if(Sprite.Pos.y >= rArena.bottom) { Sprite.PosVel.y= -(FLOAT)fabs(Sprite.PosVel.y); Sprite.Pos.y= rArena.bottom+Sprite.PosVel.y; } } void Item::UpdateWrap(const RECT &rArena) { if(Sprite.Pos.x < rArena.left) Sprite.Pos.x= (FLOAT)(rArena.right-1); else if(Sprite.Pos.x >= rArena.right) Sprite.Pos.x= (FLOAT)rArena.left; if(Sprite.Pos.y < rArena.top) Sprite.Pos.y= (FLOAT)(rArena.bottom-1); else if(Sprite.Pos.y >= rArena.bottom) Sprite.Pos.y= (FLOAT)rArena.top; } /*************************************************************************/ /** Rocket **/ /*************************************************************************/ int Rocket::Create(HITEM *phItem, HITEM hSrc) { int Err= ERR_OK; Rocket *pRocket= new Rocket; if(!pRocket) { Err= Error(ERR_NOMEM,__FUNCTION__": Unable to alloc %d.",sizeof(*pRocket)); } else if(IsErr(Err= pRocket->Create2(hSrc))) { delete pRocket; } else { *phItem= pRocket->Link.hItem; } return(Err); } int Rocket::Update(HITEMS hItems, UINT Tick) { int Err= ERR_OK; UINT CtrlState= 0; struct Sprite_s *pS= &Sprite; FLOAT ThrustDir= DegToRad(pS->Rotation); HITEM hBullet; ItemsGetControl(hItems,PlayerID,&CtrlState); UpdateRotation(CtrlState); if(CtrlState & CTRL_THRUST) { pS->PosVel.x+= (FLOAT)cos(ThrustDir)*0.1f; pS->PosVel.y+= (FLOAT)sin(ThrustDir)*0.1f; } if(CtrlState & CTRL_FIRE) { if(Tick > NextFire) { //Create a new Bullet item and add to the ItemList. if(IsErr(Err= ItemCreate(&hBullet,ITEM_BULLET,(HITEM)this))) { Err= Warn(Err,__FUNCTION__": Unable to create new bullet."); } else if(IsErr(Err= ItemsAdd(hItems,hBullet))) { Err= Warn(Err,__FUNCTION__": Unable to add new bullet."); ItemDestroy(hBullet); } NextFire= Tick+100; } } Item::Update(hItems,Tick); pS->FrameID= (CtrlState & CTRL_THRUST) ? 1:0; return(Err); } void Rocket::UpdateRotation(UINT CtrlState) { struct Sprite_s *pS= &Sprite; if(DoRotationalMomentum) { if(CtrlState & CTRL_LEFT) pS->RotationVel-= 0.2f; else if(CtrlState & CTRL_RIGHT) pS->RotationVel+= 0.2f; } else { if(CtrlState & CTRL_LEFT) pS->RotationVel= -4.0f; else if(CtrlState & CTRL_RIGHT) pS->RotationVel= +4.0f; else pS->RotationVel= 0; } } Rocket::Rocket(void):Item(ITEM_ROCKET) { Sprite.SpriteID= SPRITE_BITMAP; Sprite.BitmapID= BITMAP_ROCKET_PNG; Sprite.Size= 100; Sprite.Color.a= 1.0f; DoRotationalMomentum= 0; NextFire= 0; } /*************************************************************************/ /** Bullet **/ /*************************************************************************/ int Bullet::Create(HITEM *phItem, HITEM hSrc) { int Err= ERR_OK; Bullet *pBullet= new Bullet; if(!pBullet) { Err= Error(ERR_NOMEM,__FUNCTION__": Unable to alloc %d.",sizeof(*pBullet)); } else if(IsErr(Err= pBullet->Create2(hSrc))) { delete pBullet; } else { *phItem= (HITEM)pBullet; } return(Err); } int Bullet::Update(HITEMS hItems, UINT Tick) { int Err= ERR_OK; if(Tick>=TimeOut) { Err= ItemsRemove(hItems,Link.hItem); delete this; } else { Err= Item::Update(hItems,Tick); } return(Err); } int Bullet::Collision(HITEMS hItems) { int Err2,Err= ERR_OK; HITEM hList,hNext; Item *pItem; bool DoDelete= 0; if(IsErr(Err= ItemsGetNext(hItems,0,&hList))) { Err= Error(Err,__FUNCTION__": Unable to retrieve item list."); } else { //Loop through all the items in ItemList while(!IsErr(Err) && hList) { Err2= ItemsGetNext(hItems,hList,&hNext); if(!(pItem= Ptr(hList))) { Err= Error(ERR_BADHANDLE,__FUNCTION__": Invalid hItem [%X]",hList); } else if(pItem->Link.ItemID==ITEM_ROCK) { if(IsCollision(Sprite.Pos,pItem->Sprite.Pos,pItem->Sprite.Size)) { //If collision between a bullet and a rock, //Explode the rock and expire the bullet. pItem->Explode(hItems,Link.hItem); ItemsRemove(hItems,Link.hItem); DoDelete= 1; break; } } if(IsErr(Err2)) { Err= Error(Err2,__FUNCTION__": Unable to retrieve next item. [%X]",hList); } else { hList= hNext; } } } if(DoDelete) delete this; return(Err); } Bullet::Bullet(void):Item(ITEM_BULLET) { TimeOut= GetTickCount()+5000; Sprite.Size= 4; Sprite.Color= ColorF(0.25f,1.00f,1.00f,1.00f); } int Bullet::Create2(HITEM hSrc) { int Err= ERR_OK; FLOAT GunDir; if(!IsErr(Err= Item::Create2(hSrc))) { GunDir= DegToRad(Sprite.Rotation); Sprite.PosVel.x+= (FLOAT)cos(GunDir)*10.0f; Sprite.PosVel.y+= (FLOAT)sin(GunDir)*10.0f; } return(Err); } /*************************************************************************/ /** Rock **/ /*************************************************************************/ int Rock::Create(HITEM *phItem, HITEM hSrc) { int Err= ERR_OK; Rock *pRock= new Rock; if(!pRock) { Err= Error(ERR_NOMEM,__FUNCTION__": Unable to alloc %d.",sizeof(*pRock)); } else if(IsErr(Err= pRock->Create2(hSrc))) { delete pRock; } else { *phItem= (HITEM)pRock; } return(Err); } int Rock::Explode(HITEMS hItems, HITEM hKiller) { int Err= ERR_OK; UINT ExplodeSz= Sprite.Size; HITEM hNew; Item *pNew; if(Sprite.Size < 10) { GameEvent(ghGame,EVENT_ROCK_DESTROYED); ItemsRemove(hItems,Link.hItem); delete this; } else { Sprite.Size= (Sprite.Size*ExplodeShrinkage)/100; while(ExplodeSz>ExplodeFragment) { if(IsErr(Err= Create(&hNew,Link.hItem))) break; if(pNew= Ptr(hNew)) { pNew->Sprite.Size= Sprite.Size; pNew->Sprite.PosVel.x+= RandF()-0.5f; pNew->Sprite.PosVel.y+= RandF()-0.5f; } if(IsErr(Err= ItemsAdd(hItems,hNew))) ItemDestroy(hNew); ExplodeSz-= ExplodeFragment; } } return(Err); } Rock::Rock(void):Item(ITEM_ROCK) { }


WebV7 (C)2018 nlited | Rendered by tikope in 34.534ms | 3.144.108.200