001 #ifndef SKELETAL
002 #define SKELETAL
003 #include "_2d.HC";
004 class CBone:CQue {
005   U64 ident;
006   C2DObject *obj;
007 //Bone takes rotation from rot
008 #define BONE_M_NORMAL 0
009 //Bone points to point_x,point_y motherfucker(point_rot_off is added to rot) 
010 #define BONE_M_POINT_TO 1
011   I64 mode;
012 #define BONE_F_FLIP 1
013   I64 flags;
014   F64 x,y,z,length;
015   F64 point_x,point_y,point_rot_off;
016   F64 rot;
017   CQue child_bones;
018 };
019 CBone *BoneNew(C2DObject *obj,CTask *mem_task=NULL) {
020   CBone *b=CAlloc(sizeof CBone,mem_task);
021   b->ident='Bone';
022   b->obj=obj;
023   QueInit(&b->child_bones);
024   return b;
025 }
026 U0 BoneSetFlip(CBone *bone,Bool on=TRUE) {
027   if(!on) {bone->obj->flipped=TRUE;bone->flags|=BONE_F_FLIP;}
028   else {bone->flags&=~BONE_F_FLIP;bone->obj->flipped=FALSE;}
029   CBone *head=&bone->child_bones,*cur;
030   for(cur=head->next;cur!=head;cur=cur->next)
031     BoneSetFlip(cur,on);
032 }
033 F64 FlipAngle(F64 a) {
034   return (pi-a)+pi;
035 }
036 U0 BoneUpdate(CBone *bone,CBone *parent=NULL) {
037   CBone *head,*cur;
038   F64 dist,ang,flip=1;
039   if(parent&&parent->flags&BONE_F_FLIP)
040     flip=-1;
041   if(!parent) {
042     bone->obj->x=bone->x;
043     bone->obj->y=bone->y;
044     bone->obj->rot=bone->rot;
045     bone->obj->flipped=!!(bone->flags&BONE_F_FLIP);
046   } else {
047     switch(bone->mode) {
048       start:
049         bone->obj->x=parent->obj->x;
050         bone->obj->y=parent->obj->y;
051         dist=Sqrt(Sqr(bone->x)+Sqr(bone->y));
052         ang=Arg(flip*bone->x,bone->y);
053         bone->obj->x+=dist*Cos(parent->obj->rot+ang);
054         bone->obj->y+=dist*Sin(parent->obj->rot+ang);
055         case BONE_M_NORMAL:
056           if(!(bone->flags&BONE_F_FLIP))
057             bone->obj->rot=bone->rot+parent->obj->rot;
058           else
059             bone->obj->rot=FlipAngle(bone->rot)+parent->obj->rot;
060           break;
061         case BONE_M_POINT_TO:
062           if(!(bone->flags&BONE_F_FLIP))
063             bone->obj->rot=Arg(bone->point_x-bone->obj->x,bone->point_y-bone->obj->y)+bone->point_rot_off;
064           else 
065             bone->obj->rot=FlipAngle(Arg(-(bone->point_x-bone->obj->x),bone->point_y-bone->obj->y)+bone->point_rot_off);
066           break;
067       end:;
068     }
069   }
070   head=&bone->child_bones;
071   for(cur=head->next;cur!=head;cur=cur->next) {
072     BoneUpdate(cur,bone);
073   }
074 }
075 #if __CMD_LINE__
076 C2DWorld *w=C2DWorldNew(BLACK);
077 CDC *rect1=DCNew(200,50);
078 CDC *rect2=DCNew(100,50);
079 DCFill(rect1,YELLOW);
080 DCFill(rect2,CYAN);
081 CDC *sq=DCNew(50,50);
082 DCFill(sq,RED);
083 C2DObject *arm=C2DObjectNewFromDC(rect1);
084 C2DObject *arm2=C2DObjectNewFromDC(rect2);
085 C2DObject *hand=C2DObjectNewFromDC(sq);
086 C2DObjectMoveCenter(arm,0,25);
087 C2DObjectMoveCenter(arm2,0,25);
088 C2DObjectMoveCenter(hand,0,0);
089 CBone *arm_bone=BoneNew(arm);
090 CBone *arm_bone2=BoneNew(arm2);
091 arm_bone->x=0,arm_bone->y=0;
092 arm_bone2->x=200,arm_bone2->y=25;
093 CBone *hand_bone=BoneNew(hand);
094 hand_bone->x=100;
095 hand_bone->y=0;
096 QueIns(arm_bone2,&arm_bone->child_bones);
097 QueIns(hand_bone,&arm_bone2->child_bones);
098 AddObjectToWorld(arm,w);
099 AddObjectToWorld(arm2,w);
100 AddObjectToWorld(hand,w);
101 //Recursive
102 
103 U0 DrawIt(CTask *t,CDC *dc) {
104   DrawWorld(Fs,w);
105   GrBlot(dc,0,0,w->scrn);
106 }
107 FlushMsgs;
108 WinMax;
109 U0 Foo() {
110   Fs->draw_it=&DrawIt;
111   while(!ScanKey) {
112     arm_bone->x=GR_WIDTH/2;
113     arm_bone->y=GR_HEIGHT/2;
114     arm_bone->rot=tS;
115     arm_bone2->rot=tS*3;
116     arm_bone2->mode=BONE_M_POINT_TO;
117     arm_bone->point_x=0;
118     arm_bone->point_y=0;
119     BoneUpdate(arm_bone);
120     BoneSetFlip(arm_bone,Blink(.5));
121     Refresh;
122   }
123   Exit;
124 };
125 Foo;
126 #endif
127 #endif