物体的阻尼运动

#include <Windows.h>
#include <iostream>

 

const int X=200,Y=50;    //程序窗口左上角相对于屏幕的坐标 
const int WIDTH=640,HEIGHT=480;  // //程序窗口的宽与高

DWORD tPre,tNow;    //tPre记录上一次绘图的时间,tNow记录此次准备绘图的时间
int x=0,y=0,vx=3,vy=0,gy=1;  //x、y表示物体的初始位置

HDC hdc,mdc,bufdc;
HBITMAP bg,dra;
RECT rect;

 

void MyPaint(HDC);
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

 

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
 const std::string szTitle="阻尼运动";

 WNDCLASS winclass={CS_HREDRAW|CS_VREDRAW,WndProc,0,0,hInstance,LoadIcon(NULL,IDI_APPLICATION),
  LoadCursor(NULL,IDC_ARROW),(HBRUSH)GetStockObject(WHITE_BRUSH),NULL,szTitle.c_str()};

 if(!RegisterClass(&winclass))
  return false;

 HWND hWnd=CreateWindow(szTitle.c_str(),szTitle.c_str(),WS_OVERLAPPEDWINDOW,X,Y,WIDTH,HEIGHT,
  NULL,NULL,winclass.hInstance,NULL);

 if(0==hWnd)
  return 0;

 ShowWindow(hWnd,SW_SHOWDEFAULT);
 UpdateWindow(hWnd);

 MSG msg;
 ZeroMemory(&msg,sizeof(MSG));

 while(msg.message!=WM_QUIT)
 {
  if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  {
   TranslateMessage(&msg);
   DispatchMessage(&msg);
  }
  else
  {
   tNow=GetTickCount(); 
   while(tNow-tPre>=30)
    MyPaint(hdc);
  }
 }
 return msg.wParam;
}

 

LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
 HBITMAP bmp;

 switch(message)
 {
 case WM_CREATE:
  {
   hdc=GetDC(hWnd);
   mdc=CreateCompatibleDC(hdc);
   bufdc=CreateCompatibleDC(hdc);
   bmp=CreateCompatibleBitmap(hdc,WIDTH,HEIGHT);
   SelectObject(mdc,bmp);

   //加载物体位图
   bg=(HBITMAP)LoadImage(NULL,"bg.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
   dra=(HBITMAP)LoadImage(NULL,"dra.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);

   GetClientRect(hWnd,&rect);  //取得内部窗口区域大小
  }
  break;

 

 case WM_KEYDOWN:
  {
   if(wParam==VK_ESCAPE)
    DestroyWindow(hWnd);
  }
  break;

 case WM_DESTROY:
  {
   DeleteDC(bufdc);
   DeleteDC(mdc);
   DeleteObject(bg);
   DeleteObject(dra);
   ReleaseDC(hWnd,hdc);
   PostQuitMessage(0);
  }
  break;

 

 default:
  return DefWindowProc(hWnd,message,wParam,lParam);
 }
 return 0;
}

 

void MyPaint(HDC hdc)
{
 //贴背景图
 SelectObject(bufdc,bg);
 BitBlt(mdc,0,0,WIDTH,HEIGHT,bufdc,0,0,SRCCOPY);

 //贴物体图
 SelectObject(bufdc,dra);
 BitBlt(mdc,x,y,50,50,bufdc,50,0,SRCAND);
 BitBlt(mdc,x,y,50,50,bufdc,0,0,SRCPAINT);
 BitBlt(hdc,0,0,WIDTH,HEIGHT,mdc,0,0,SRCCOPY);

 
 x+=vx;  //计算x轴方向物体坐标
 vy+=gy;  //计算y轴方向速度分量
 y+=vy;  //计算y轴方向贴图坐标

 

 if(y>=rect.bottom-50)
 {
  y=rect.bottom-50;
  vx-=1;
  if(vx<0)
   vx=0;

  vy-=4;
  if(vy<0)
   vy=0;
  vy=-vy;
 }

 tPre=GetTickCount();
}

### 实现 Unity 中通过鼠标控制物体旋转并添加阻尼效果 在 Unity 中,可以通过 `Input.GetAxis` 方法获取鼠标的输入,并将其应用于物体的旋转。为了实现平滑的效果,可以引入阻尼机制来减缓旋转速度。 以下是具体的实现方法: #### 鼠标控制物体旋转的核心逻辑 当检测到鼠标移动时,可以根据鼠标的水平 (`Mouse X`) 和垂直 (`Mouse Y`) 输入调整物体的方向。这种操作通常用于第一人称视角或者第三人称视角中的角色头部转动[^1]。 ```csharp public class MouseRotationWithDamping : MonoBehaviour { public float sensitivity = 2.0f; // 控制鼠标灵敏度 public float dampingTime = 0.3f; // 设置阻尼时间 private Vector3 targetRotation; private Vector3 currentVelocity; void Start() { targetRotation = transform.eulerAngles; // 初始化目标角度 } void Update() { // 获取鼠标输入 float mouseX = Input.GetAxis("Mouse X") * sensitivity; float mouseY = Input.GetAxis("Mouse Y") * sensitivity; // 更新目标方向 targetRotation.x -= mouseY; targetRotation.y += mouseX; // 使用Lerp函数应用阻尼效果 transform.eulerAngles = Vector3.SmoothDamp( transform.eulerAngles, targetRotation, ref currentVelocity, dampingTime); } } ``` 上述代码实现了基于鼠标的旋转功能,并加入了阻尼效果以使运动更加自然流畅。其中 `Vector3.SmoothDamp` 是关键部分,它允许我们指定当前值、目标值以及过渡的时间参数。 #### ScriptableObject 的扩展用途 虽然此案例未直接涉及 `ScriptableObject`,但在更复杂的项目中,可以利用 `ScriptableObject` 来存储配置数据(如敏感度和阻尼系数)。这有助于将这些数值从硬编码转移到外部文件管理,从而提高灵活性。 例如,创建一个新的 `ScriptableObject` 类型如下所示: ```csharp [CreateAssetMenu(fileName = "RotationSettings", menuName = "Settings/Rotation")] public class RotationSettingsSO : ScriptableObject { public float sensitivity = 2.0f; public float dampingTime = 0.3f; } ``` 随后,在脚本中加载该设置对象即可完成动态绑定。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值