我想做一个中级游戏,名字叫“机器时代”。这是这个游戏的第一个有编码的角色——镰刀手。镰刀手的图片是用Flash画的(要经photoshop处理图片的透明多余部分)。画工不算精,不过还看得过眼。

 

                                                  

镰刀要实现的效果:
  按ADWS键能上下左右移动。按Up键会快速旋转(顺时针),按Left键会逆时针慢旋,按Right键会顺时针慢旋。如果同时按下Up键和Right键会比只按Up键更快。按Up键Left键Right键都会自动返回0度。而按Down键能停止Left键和Right键的自动返回。不旋转时镰刀手会微微扩展收缩。

游戏设计:
  按Left键和Right键和Down键配合是为了调整镰刀角度,镰刀具有防御能力。如果只按Left键,侧镰刀处于无防状态,同时镰到手能达到储气效果。当储气到达一定量时,就可以使用Up键,快速旋转的镰刀集攻防能力一身,不过是受到气的限制的。如果同时按下Up键和Right键会比只按Up键攻击能力更大,气也耗得更快(气的代码没写)。

具体实现:
  1、移动效果。
  这个并不难,newState.IsKeyDown()就能轻松实现。但是还要消除同时按左上左下右上右下键时带来的增速效果。所以给每个键分配一个监视变量,如果键按下了变量值会变为1,键没按下变量值为0;这样只要根据变量值就能做出适合的速度赋值。如:           
if (newState.IsKeyDown(Keys.S))
   {
     sbool = 1;
      if ((abool == 0 && dbool == 1) || (abool == 1 && dbool == 0))
          sspeed = 2.828f;
      else sspeed = 4;
      if (strongpos.Y < 506 - sspeed )
      {
          strongpos.Y += sspeed ;
      }
      else
      {
          strongpos.Y = 506;
      }
   }
上面的代码还包含边界限制(窗口还是800*600)的作用。

  2、呼吸效果。(微微扩展收缩)
  这个是为了增强游戏的活泼性。为了实现这个效果,要在Draw函数下要加入size参数,如下:
spriteBatch.Draw(liandaostd ,liandpos  ,null , Color.White,finalrot ,Vector2 .Zero ,size,SpriteEffects.None ,0f);
然后再增加了一个state函数来专职负责这个效果。具体代码如下:
        private void state()
        {
            stop++;
            if (stop > 10)
            {
                num++;
                size = (float)(basesize + 0.0005 * num * t);
                sizepos.X = (float)(0.0005 * 45)*t;
                sizepos.Y = (float)(0.0005 * 49)*t;
                if (num == 50)
                {
                    if (t == -1)
                    {
                        stop = 0;
                    }
                    t *= -1;
                    num = 0;
                    basesize = size;
                }
            }
        }
设计basesize是用来呼应num,当然还可以设计成size += 0.005*t;  num++;
sizepos是为了防止机器“呼吸”时导的重心移动。stop是为了增加活泼性还有作为旋转时停掉这个效果的开关。效果不难实现,就是一有旋转时就把stop设置为0;
  
  3、旋转效果。
  旋转本身不难实现,在draw函数中再加入finalrot(旋转参数)就行了。但是旋转时却是以精灵的坐标点(左上角)为旋转点的,而不是以重心为旋点。我记得2D教程里有对付这种问题的方法和函数,当时以为改变旋转点不难,就自己写代码了。结果发现不容易。(我几何学得不好)。具体代码如下:
            y = Math.Sqrt(liandaowidth * liandaowidth + liandaohight * liandaohight)
                * Math.Sin(Math.Asin(liandaohight / Math.Sqrt(liandaowidth * liandaowidth + liandaohight * liandaohight)) + finalrot);
            x = Math.Sqrt(liandaowidth * liandaowidth + liandaohight * liandaohight)
                * Math.Cos(Math.Asin(liandaohight / Math.Sqrt(liandaowidth * liandaowidth + liandaohight * liandaohight)) + finalrot);
            liandpos.X = strongpos.X + liandaowidth - (float)x - sizepos.X;
            liandpos.Y = strongpos.Y + liandaohight - (float)y - sizepos.Y;
其中liandaowidth和liandaohight是精灵的宽和长的一半,我认为最好还是用图片文件的值去计算,如何用精灵函数去访问的话似乎不精确,会导致重心的微动。上面的代码只要套入几何图形里就不难理解了。具体思路是:因为只是旋转的话重心会围绕坐标点旋转,要使重心不动,就要坐标点围着重心旋转,用这种相对效果抵消就能实现重心的不动。x、y是记录因为旋转而导致的精灵坐标的改变。而这里的strongpos是上下左右移动时才改变的。各种不同的动作造成的变动我认为最好用不用的参数去储存,然后叠加在一起,这样能防止各种变动相互影响和减少误差。

  4、自动返0效果。
  也就是按Up键Left键Right键时如果控键停止了精灵的当前角度并不为0的时候会自动渐变为0;对于每个键,如果其累加的角度的绝对值超过6.2832(360度,xna里是用弧度计算的)就会自动减去或加上6.2832,使其绝对值减少。对于Up键,由于其速度很快,所以直接用以下代码就轻松解决。
  if (liandaorot != 0 && liandaorot < 6.2832)
        liandaorot += (float)boun / 10;
    else
        liandaorot = 0;
其中boun是用来判断之前按下的是Up键还是Left键或者Right键。如果是Up键的话则用Up键的速度返回0;同样,如果是Left键Right键的话就用它们的速度返回0;因为Left键Right键的速度比较慢,所以还要选择合适的路径去返回0;代码如下:
   if (liandaorot < 3.1416 && liandaorot > 0)
   {
      liandaorot -= (float)boun / 10;
      if (liandaorot < 0)
         liandaorot = 0;
   }
   else if ((liandaorot <= -3.1416 && liandaorot >= -6.2832))
   {
      liandaorot -= (float)boun / 10;
      if (liandaorot <= -6.2832)
          liandaorot = 0;
   }
   else if (liandaorot > 3.1416 && liandaorot <= 6.2832)
   {
       liandaorot += ((float)boun / 10);
       if (liandaorot >= 6.2832)
          liandaorot = 0;
   }
   else if ((liandaorot >= -3.1416 && liandaorot < 0))
   {
       liandaorot += ((float)boun / 10);
       if (liandaorot > 0)
       liandaorot = 0;
   }
最后就只差Down键的效果了。Down键是实现精灵在其它角度状态下也能保持静止(做为防御招数)。实现的代码也不复杂,代码如下:
   if (boun == 1 && newState.IsKeyDown(Keys.Down))
      returnbool = 0;
boun是确定返回状态是不是按下Left键和Right键后的。returnbool刚是自动返0函数的开关。
  
  整个程序还没有整理好和化成类,代码写得还是很乱。因为我比较注重实现效果而少注重程序可观性。/Files/sysudm/镰刀手.rar

posted on 2009-03-29 15:14  中大信息中心数媒部  阅读(523)  评论(2)    收藏  举报