src/character/member.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002  *  Wormux is a convivial mass murder game.
00003  *  Copyright (C) 2001-2004 Lawrence Azzoug.
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
00018  ******************************************************************************
00019  *****************************************************************************/
00020 
00021 #include <map>
00022 #include <iostream>
00023 #include "member.h"
00024 #include "../game/game_loop.h"
00025 #include "../team/teams_list.h"
00026 #include "../tool/math_tools.h"
00027 #include "../tool/xml_document.h"
00028 #include "../tool/string_tools.h"
00029 
00030 Member::Member(xmlpp::Element *xml, Profile* res)
00031 {
00032   parent = NULL;
00033   if(xml == NULL) return;
00034   name="";
00035   XmlReader::ReadStringAttr( xml, "name", name);
00036   assert(name!="");
00037 
00038   // Load the sprite
00039   spr = resource_manager.LoadSprite( res, name);
00040 //  spr->EnableRotationCache(64);
00041 //  spr->EnableFlippingCache();
00042 //  spr->cache.EnableLastFrameCache();
00043 
00044   // Get the various option
00045   type="";
00046   XmlReader::ReadStringAttr( xml, "type", type);
00047   assert(type!="");
00048 
00049   xmlpp::Element *el = XmlReader::GetMarker(xml, "anchor");
00050   if(el != 0)
00051   {
00052     int dx,dy;
00053     dx = dy = 0;
00054     XmlReader::ReadIntAttr(el, "dx", dx);
00055     XmlReader::ReadIntAttr(el, "dy", dy);
00056     anchor = Point2f((float)dx,(float)dy);
00057     spr->SetRotation_HotSpot(Point2i(dx,dy));
00058   }
00059 
00060   go_through_ground = false;
00061   XmlReader::ReadBoolAttr(xml, "go_through_ground", go_through_ground);
00062 
00063   xmlpp::Node::NodeList nodes = xml -> get_children("attached");
00064   xmlpp::Node::NodeList::iterator
00065     it=nodes.begin(),
00066     end=nodes.end();
00067 
00068   for (; it != end; ++it)
00069   {
00070     xmlpp::Element *elem = dynamic_cast<xmlpp::Element*> (*it);
00071     assert (elem != NULL);
00072     std::string att_type;
00073     if (!XmlReader::ReadStringAttr(elem, "member_type", att_type))
00074     {
00075       std::cerr << "Malformed attached member definition" << std::endl;
00076       continue;
00077     }
00078 
00079     int dx,dy;
00080     dx = dy = 0;
00081     XmlReader::ReadIntAttr(elem, "dx", dx);
00082     XmlReader::ReadIntAttr(elem, "dy", dy);
00083     Point2f d((float)dx, (float)dy);
00084 
00085     std::string frame_str;
00086     XmlReader::ReadStringAttr(elem, "frame", frame_str);
00087     if (frame_str == "*")
00088     {
00089       v_attached rot_spot;
00090       rot_spot.assign (spr->GetFrameCount(), d);
00091       attached_members[att_type] = rot_spot;
00092     }
00093     else
00094     {
00095       int frame;
00096       if (!str2int (frame_str, frame) || frame < 0 || frame >= (int)spr->GetFrameCount())
00097       {
00098         std::cerr << "Malformed attached member definition (wrong frame number)" << std::endl;
00099         continue;
00100       }
00101       if(attached_members.find(att_type) == attached_members.end())
00102       {
00103         v_attached rot_spot;
00104         rot_spot.resize(spr->GetFrameCount(), Point2f(0.0,0.0));
00105         attached_members[att_type] = rot_spot;
00106       }
00107       (attached_members.find(att_type)->second)[frame] = d;
00108     }
00109   }
00110   ResetMovement();
00111 }
00112 
00113 Member::Member(Member* m)
00114 {
00115   parent = NULL;
00116   name = m->name;
00117   spr = new Sprite(*m->spr);
00118   type = m->type;
00119   anchor = m->anchor;
00120   Point2i rot = Point2i((int)anchor.x, (int)anchor.y);
00121   spr->SetRotation_HotSpot(rot);
00122   go_through_ground = m->go_through_ground;
00123 
00124   for(std::map<std::string, v_attached>::iterator it = m->attached_members.begin();
00125       it != m->attached_members.end();
00126       ++it)
00127   {
00128     attached_members[it->first] = it->second;
00129   }
00130   ResetMovement();
00131 }
00132 
00133 Member::~Member()
00134 {
00135   delete spr;
00136   attached_members.clear();
00137 }
00138 
00139 void Member::RotateSprite()
00140 {
00141   spr->SetRotation_rad(angle_rad);
00142   spr->Scale(scale.x, scale.y);
00143   spr->RefreshSurface();
00144 }
00145 
00146 void Member::Draw(const Point2i & _pos, int flip_center, int direction)
00147 {
00148   assert(name != "weapon" && type!="weapon");
00149 
00150   Point2i posi((int)pos.x, (int)pos.y);
00151   posi += _pos;
00152 
00153   if(direction == 1)
00154   {
00155     spr->SetRotation_rad(angle_rad);
00156     spr->Scale(scale.x,scale.y);
00157   }
00158   else
00159   {
00160     spr->Scale(-scale.x,scale.y);
00161     spr->SetRotation_rad(-angle_rad);
00162     posi.x = 2 * flip_center - posi.x - spr->GetWidth();
00163   }
00164 
00165   if(parent == NULL && type != "body")
00166   {
00167     std::cerr << "Error : Member " << name << " have no parent member!" << std::endl;
00168     return;
00169   }
00170 
00171   spr->SetAlpha(alpha);
00172   spr->Update();
00173   spr->Draw(posi);
00174 }
00175 
00176 void Member::ResetMovement()
00177 {
00178   pos.x = 0;
00179   pos.y = 0;
00180   angle_rad = 0;
00181   alpha = 1.0;
00182   scale.x = 1.0;
00183   scale.y = 1.0;
00184 }
00185 
00186 void Member::ApplySqueleton(Member* parent_member)
00187 {
00188   // Place the member to shape the squeleton
00189   if(parent_member == NULL)
00190   {
00191     std::cerr << "Member " << name << " have no parent member!" << std::endl;
00192     return;
00193   }
00194   parent = parent_member;
00195 
00196   assert(parent->name != "weapon" && parent->type != "weapon");
00197 
00198   // Set the position
00199   pos = parent->pos;
00200   pos = pos - anchor;
00201 
00202   if(parent->attached_members.find(type) != parent->attached_members.end())
00203     pos = pos + parent->attached_members.find(type)->second[parent->spr->GetCurrentFrame()];
00204 }
00205 
00206 void Member::ApplyMovement(member_mvt &mvt, std::vector<junction>& squel_lst)
00207 {
00208   // Apply the movment to the member,
00209   // And apply the movement accordingly to the child members
00210 
00211   uint frame;
00212   if(spr!=NULL) // spr == NULL when Member is the weapon
00213     frame = spr->GetCurrentFrame();
00214   else
00215     frame = 0;
00216 
00217   // We first apply to the child (makes calcules simpler in this order):
00218   for(std::map<std::string, v_attached>::iterator child = attached_members.begin();
00219       child != attached_members.end();
00220       child++ )
00221   {
00222     // Find this member in the squeleton:
00223     for(std::vector<junction>::iterator member = squel_lst.begin();
00224         member != squel_lst.end();
00225         member++)
00226     {
00227       if(member->member->type == child->first)
00228       {
00229         // Calculate the movement to apply to the child
00230         member_mvt child_mvt;
00231         child_mvt.SetAngle(mvt.GetAngle());
00232         child_mvt.pos = mvt.pos;
00233         float radius = anchor.Distance(child->second[frame]);
00234 
00235         if(radius != 0.0)
00236         {
00237           float angle_init;
00238 
00239           if(child->second[frame].x > anchor.x)
00240           {
00241             if(child->second[frame].y > anchor.y)
00242               angle_init = acos( (child->second[frame].x - anchor.x) / radius );
00243             else
00244               angle_init = -acos( (child->second[frame].x - anchor.x) / radius );
00245           }
00246           else
00247           {
00248             if(child->second[frame].y > anchor.y)
00249               angle_init = acos( (child->second[frame].x - anchor.x) / radius );
00250             else
00251               angle_init = M_PI + acos( -(child->second[frame].x - anchor.x) / radius );
00252           }
00253 
00254           child_mvt.pos.x += radius * (cos(angle_init + angle_rad + mvt.GetAngle()) - cos(angle_init + angle_rad));
00255           child_mvt.pos.y += radius * (sin(angle_init + angle_rad + mvt.GetAngle()) - sin(angle_init + angle_rad));
00256         }
00257         // Apply recursively to childrens:
00258         member->member->ApplyMovement(child_mvt, squel_lst);
00259       }
00260     }
00261   }
00262 
00263   // Apply the movement to the current member
00264   SetAngle(angle_rad + mvt.GetAngle());
00265   pos += mvt.pos;
00266   alpha *= mvt.alpha;
00267   scale = scale * mvt.scale;
00268 }
00269 
00270 const Point2i Member::GetPos()
00271 {
00272   Point2i posi((int)pos.x, (int)pos.y);
00273   return posi;
00274 }
00275 
00276 WeaponMember::WeaponMember() : Member(NULL, NULL)
00277 {
00278   name = "weapon";
00279   type = "weapon";
00280   spr = NULL;
00281   anchor = Point2f(0.0,0.0);
00282 }
00283 
00284 WeaponMember::~WeaponMember()
00285 {
00286 }
00287 
00288 void WeaponMember::Draw(const Point2i & _pos, int flip_center, int direction)
00289 {
00290   // Would be cool to display the weapon from here...
00291 }

Generated on Mon Jan 1 13:10:55 2007 for Wormux by  doxygen 1.4.7