元旦整理了个C++的控制台的程序,可以动画运动的符号,可视化直接用的printf,所以不用其它什么额外库,但是有用到C++11以上的语法和库,所以最好是VC2015~VC2022的编译,直接拷贝代码就行。是一个笑脸符号在屏幕上飘,点和屏幕中心的固定点有个弹性力作用,为了叫点不发散,点在运动时候受到阻尼会减速的,a d s w按健分别会朝左右下上推一下点。
main.cpp
#include<string>
#include<vector>
#include<stdio.h>
#include<conio.h>
#include<math.h>
#include<iostream>
#include<thread>
#include<mutex>
using namespace std;
mutex mu;
// 可视化采用字符阵列
// 点的位置
int _w=60;
int _h=30;
float chars=1.0;
void drawCharArray(int x, int y)
{
for (int i=0; i<_h;i++)
{
for (int j=0; j<_w;j++)
{
if (x==j && y == i)
printf("(^-^)");
else
printf(" ");
}
printf("\n");
}
}
bool exitflag = false;
int posx=1; //整数符号位置
int posy=1;
// 质点的位置r,速度v,力f
float posrx=10.f;
float posry=10.f;
float posvx=2.5f;
float posvy=0.f;
float posfx=0.f;
float posfy=0.f;
float posm=2.f; // 质量
float posdam=0.12f; // 阻尼系数
float posk=0.6f; // 弹性系数
float posminv=1.f/posm; // 质量倒数
float vmax=50.f; // 最大速度
float dv=4.f; // 速度增量
float knotx=_w*0.5; // 中心节点
float knoty=_h*0.5;
// 点到边上处理反弹
void posworld_side()
{
if (posx < 0)
{
posx=0;
posrx=posx;
posvx=-0.8*posvx;
}
else if (posx >= _w)
{
posx=_w-1;
posrx=posx;
posvx=-0.8*posvx;
}
if (posy >= _h)
{
posy=_h-1;
posry=posy;
posvy=-0.8*posvy;
}
else if (posy < 0)
{
posy=0;
posry=posy;
posvy=-0.8*posvy;
}
}
// 计算力
void compute_force(float& posfx1,
float& posfy1)
{
float pkx=knotx-posrx;
float pky=knoty-posry;
// 指向knot的弹性力
float pkl=sqrt(pkx*pkx+pky*pky)+0.01f;
float pkf=posk*pkl;
float fkx= pkf*(pkx/pkl);
float fky= pkf*(pky/pkl);
// 线性阻力
float fdax=-posvx*posdam;
float fday=-posvy*posdam;
posfx1=fkx+fdax;
posfy1=fky+fday;
}
// 仿真步,采用了verlet积分
void sim_step(float dt)
{
posrx = posrx+posvx*dt +
posfx*0.5*posminv*dt*dt;
posry = posry+posvy*dt+
posfy*0.5*posminv*dt*dt;
float posfx1=posfx;
float posfy1=posfy;
compute_force(posfx1,posfy1);
posvx += (posfx1+posfx)*0.5*posminv*dt;
posvy += (posfy1+posfy)*0.5*posminv*dt;
posfx=posfx1;
posfy=posfy1;
posx = int(posrx+0.5f);
posy = int(posry+0.5f);
posworld_side();
}
// a d s w 方向推,改变速度大小
void func_getch()
{
if (!kbhit())
return;
int c=getch();
rewind(stdin);
if (mu.try_lock())
{
if (c == 'q')
{
exitflag=true;
}
else if (c == 'a')
{
posvx-=dv;
if (posvx < -vmax)
posvx=-vmax;
}
else if (c == 'd')
{
posvx+=dv;
if (posvx > vmax)
posvx=vmax;
}
else if (c == 's')
{
posvy+=dv;
if (posvy > vmax)
posvy= vmax;
}
else if (c == 'w')
{
posvy-=dv;
if (posvy < -vmax)
posvy=-vmax;
}
mu.unlock();
}
}
// 可视化点
void func_drawchars()
{
int px=0;
int py=0;
if (mu.try_lock())
{
px=posx;
py=posy;
mu.unlock();
}
system("cls");
drawCharArray(px, py);
}
void thread_proc()
{
while (!exitflag)
{
// func_drawchars();
func_getch();
this_thread::sleep_for(
chrono::milliseconds (30));
}
}
int main()
{
thread thr(thread_proc);
thr.detach();
float dt = 0.08f; // 仿真步长假设固定
while(!exitflag)
{
sim_step(dt);
func_drawchars();
this_thread::sleep_for(chrono::milliseconds (10));
}
system("cls");
printf("over...");
return 0;
}