控制台屏幕上跑动的字符-质点运动模拟的C++小程序

元旦整理了个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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值