關于C語言的模擬物理模型

聲明:本文全部代碼效果基于C語言easyx圖形界面庫。

引言

關于很多游戲和模型的開發,都需要模擬真實的物理模型

比如:基本矢量運動模型(位移,速度,加速度),重力模型,碰撞模型,萬有引力模型。

本文我會一一介紹這幾種模型的開發。

既然是模擬顯示物理模型,那么引入的現實物理公式也是必要的。

本文所需要引用的公式有:其中TIKME_STEP是每幀變化的量,來彌補時間效果和逐幀效果的差

最后的總物理模型的話,可以選擇性給出每個球的狀態情況,比如每個方向的初速度,初加速度,以及是否受重力和球之間的萬有引力,對偏心碰撞,邊框碰撞。

代碼

位移公式 : ▲x = v * t??

程序內使用:x += vx? y+= vy (逐幀使用)
void move()//移動
{for (int i = 0; i <= 20; i++) {if (a[i].live) {a[i].x += a[i].vx * TIME_STEP;a[i].y += a[i].vy * TIME_STEP;}}
}

速度公式 :▲v = a * t?

程序內使用? vx += ax? vy += ay?(逐幀使用)
void speed()//速度變化
{for (int i = 0; i <= 20; i++) {if (a[i].live) {a[i].vx += a[i].ax * TIME_STEP;a[i].vy += a[i].ay * TIME_STEP;}}
}

加速度公式:a = F / m

程序內使用 (Fx+Fx1+Fx2...) / m = ax??(Fy+Fy1+Fy2...) / m = ay
void Fa()//受力
{for (int i = 0; i <= 20; i++) {if (a[i].live) {a[i].ax = (a[i].Fx + a[i].Fwx) / a[i].m;a[i].ay = (a[i].Fy + a[i].GN + a[i].Fwy) / a[i].m;}}
}

重力公式: G = mg

程序內使用 G = m*g? (g預定義數值) 然后G 是Fy的組成元素a[i].GN = a[i].m * g;

碰撞前后的動量守恒和能量守恒

m1*v1 + m2*v2 = m1*v3+m2*v4;

0.5*m1*v1*v1 + 0.5*m2*v2*v2 = 0.5*m1*v3*v3 + 0.5*m2*v3*v4;

然后再考慮是否對心碰撞分析左右偏移向量

// 檢測并處理小球碰撞
void collisionDetection()
{for (int i = 0; i < 20; i++) {if (a[i].live) {for (int j = i + 1; j <= 20; j++) {if (a[j].live) {double dx = a[i].x - a[j].x;double dy = a[i].y - a[j].y;double distance = sqrt(dx * dx + dy * dy);if (distance < 100) { // 兩個小球半徑之和為100double m1 = a[i].m;double m2 = a[j].m;double v1ix = a[i].vx;double v1iy = a[i].vy;double v2ix = a[j].vx;double v2iy = a[j].vy;// 計算碰撞法線方向的單位向量double n_x = dx / distance;double n_y = dy / distance;// 計算相對速度在法線方向和切線方向的分量double v1n = v1ix * n_x + v1iy * n_y;double v2n = v2ix * n_x + v2iy * n_y;double v1t = v1iy * n_x - v1ix * n_y;double v2t = v2iy * n_x - v2ix * n_y;// 應用動量守恒和恢復系數計算碰撞后的法向速度double v1nf = ((m1 - m2) * v1n + 2 * m2 * v2n + RESTITUTION_COEFFICIENT * m2 * (v2n - v1n)) / (m1 + m2);double v2nf = ((m2 - m1) * v2n + 2 * m1 * v1n + RESTITUTION_COEFFICIENT * m1 * (v1n - v2n)) / (m1 + m2);// 切線方向速度不變(假設無摩擦力)double v1tf = v1t;double v2tf = v2t;// 將法向和切向速度轉換回笛卡爾坐標系a[i].vx = v1nf * n_x - v1tf * n_y;a[i].vy = v1nf * n_y + v1tf * n_x;a[j].vx = v2nf * n_x - v2tf * n_y;a[j].vy = v2nf * n_y + v2tf * n_x;}}}}}
}

邊框碰撞模型

void peng()//碰撞影響一定放到位置更新之后
{for (int i = 0; i <= 20; i++) {if (a[i].live) {if (a[i].y - 50 < 0) {a[i].y = 50;  // 精確調整位置到邊界a[i].vy = -a[i].vy;  // 確保速度反向}if (a[i].x - 50 < 0) {a[i].x = 50;a[i].vx = -a[i].vx;}if (a[i].y + 50 > high) {a[i].y = high - 50;a[i].vy = -a[i].vy;}if (a[i].x + 50 > width) {a[i].x = width - 50;a[i].vx = -a[i].vx;}}}
}

檢測遇到邊界后,改變水平或者垂直方向的速度方向相反,保持速度大小不變,

實現碰撞墻壁效果。

萬有引力模型

F萬 =??G*m1*m2/(x*x)


void F_allocation()
{double sin_w = (a[0].y - a[1].y) / sqrt((a[0].y - a[1].y) * (a[0].y - a[1].y) + (a[0].x - a[1].x) * (a[0].x - a[1].x));double cos_w = (a[0].x - a[1].x) / sqrt((a[0].y - a[1].y) * (a[0].y - a[1].y) + (a[0].x - a[1].x) * (a[0].x - a[1].x));double Fw = Gk * a[0].m * a[1].m / ((a[0].y - a[1].y) * (a[0].y - a[1].y) + (a[0].x - a[1].x) * (a[0].x - a[1].x));a[0].Fwx = -Fw * cos_w;a[0].Fwy = -Fw * sin_w;a[1].Fwx = -a[0].Fwx;a[1].Fwy = -a[0].Fwy;
}

關于運行前的準備

預編譯和結構體

#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <time.h>
#include <stdbool.h>
#include <math.h>#define g 98
#define width 1700
#define high 1000
#define TIME_STEP 0.05  // 固定時間步長
#define Gk 677770
#define RESTITUTION_COEFFICIENT 0.8 // 恢復系數,0 <= e <= 1,0為完全非彈性,1為完全彈性typedef struct stu {double x;double y;double ax;double ay;double vx;double vy;double Fx;double Fy;double Fwx;double Fwy;double m;double GN;bool live;
} G;

代碼是集成的,每個作用都在,如果要研究其中某種模型,只需要調用該模型函數即可。

比如研究萬有引力模型,需要將重力模型關掉,然后控制不要碰撞,這里數值我測出來了一個效果就是,用假設初速度完全滿足萬有引力提供向心力從而做圓周運動的模型,

我們需要將兩個球的質量全設置為10,然后鎖定右側球,兩球高度一致,賦予左球vy = 130便可以滿足萬有引力完全提供向心力的天體勻速圓周模型。

展示總函數

#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <time.h>
#include <stdbool.h>
#include <math.h>#define g 98
#define width 1700
#define high 1000
#define TIME_STEP 0.05  // 固定時間步長
#define Gk 677770
#define RESTITUTION_COEFFICIENT 0.8 // 恢復系數,0 <= e <= 1,0為完全非彈性,1為完全彈性typedef struct stu {double x;double y;double ax;double ay;double vx;double vy;double Fx;double Fy;double Fwx;double Fwy;double m;double GN;bool live;
} G;G a[21];void Fa()//受力
{for (int i = 0; i <= 20; i++) {if (a[i].live) {a[i].ax = (a[i].Fx + a[i].Fwx) / a[i].m;a[i].ay = (a[i].Fy + a[i].GN + a[i].Fwy) / a[i].m;}}
}void speed()//速度變化
{for (int i = 0; i <= 20; i++) {if (a[i].live) {a[i].vx += a[i].ax * TIME_STEP;a[i].vy += a[i].ay * TIME_STEP;}}
}void move()//移動
{for (int i = 0; i <= 20; i++) {if (a[i].live) {a[i].x += a[i].vx * TIME_STEP;a[i].y += a[i].vy * TIME_STEP;}}
}void draw()
{for (int i = 0; i <= 20; i++) {if (a[i].live) {solidcircle((int)a[i].x, (int)a[i].y, 50);}}
}void peng()//碰撞影響一定放到位置更新之后
{for (int i = 0; i <= 20; i++) {if (a[i].live) {if (a[i].y - 50 < 0) {a[i].y = 50;  // 精確調整位置到邊界a[i].vy = -a[i].vy;  // 確保速度反向}if (a[i].x - 50 < 0) {a[i].x = 50;a[i].vx = -a[i].vx;}if (a[i].y + 50 > high) {a[i].y = high - 50;a[i].vy = -a[i].vy;}if (a[i].x + 50 > width) {a[i].x = width - 50;a[i].vx = -a[i].vx;}}}
}void init()
{for (int i = 0; i <= 20; i++) {a[i].x = 0;a[i].y = 0;a[i].ax = 0;a[i].ay = 0;a[i].vx = 0;a[i].vy = 0;a[i].Fx = 0;a[i].Fy = 0;a[i].Fwx = 0;a[i].Fwy = 0;a[i].m = 10;a[i].live = false;a[i].GN = a[i].m * g;}
}void F_allocation()
{double sin_w = (a[0].y - a[1].y) / sqrt((a[0].y - a[1].y) * (a[0].y - a[1].y) + (a[0].x - a[1].x) * (a[0].x - a[1].x));double cos_w = (a[0].x - a[1].x) / sqrt((a[0].y - a[1].y) * (a[0].y - a[1].y) + (a[0].x - a[1].x) * (a[0].x - a[1].x));double Fw = Gk * a[0].m * a[1].m / ((a[0].y - a[1].y) * (a[0].y - a[1].y) + (a[0].x - a[1].x) * (a[0].x - a[1].x));a[0].Fwx = -Fw * cos_w;a[0].Fwy = -Fw * sin_w;//a[1].Fwx = -a[0].Fwx;//a[1].Fwy = -a[0].Fwy;
}// 檢測并處理小球碰撞
void collisionDetection()
{for (int i = 0; i < 20; i++) {if (a[i].live) {for (int j = i + 1; j <= 20; j++) {if (a[j].live) {double dx = a[i].x - a[j].x;double dy = a[i].y - a[j].y;double distance = sqrt(dx * dx + dy * dy);if (distance < 100) { // 兩個小球半徑之和為100double m1 = a[i].m;double m2 = a[j].m;double v1ix = a[i].vx;double v1iy = a[i].vy;double v2ix = a[j].vx;double v2iy = a[j].vy;// 計算碰撞法線方向的單位向量double n_x = dx / distance;double n_y = dy / distance;// 計算相對速度在法線方向和切線方向的分量double v1n = v1ix * n_x + v1iy * n_y;double v2n = v2ix * n_x + v2iy * n_y;double v1t = v1iy * n_x - v1ix * n_y;double v2t = v2iy * n_x - v2ix * n_y;// 應用動量守恒和恢復系數計算碰撞后的法向速度double v1nf = ((m1 - m2) * v1n + 2 * m2 * v2n + RESTITUTION_COEFFICIENT * m2 * (v2n - v1n)) / (m1 + m2);double v2nf = ((m2 - m1) * v2n + 2 * m1 * v1n + RESTITUTION_COEFFICIENT * m1 * (v1n - v2n)) / (m1 + m2);// 切線方向速度不變(假設無摩擦力)double v1tf = v1t;double v2tf = v2t;// 將法向和切向速度轉換回笛卡爾坐標系a[i].vx = v1nf * n_x - v1tf * n_y;a[i].vy = v1nf * n_y + v1tf * n_x;a[j].vx = v2nf * n_x - v2tf * n_y;a[j].vy = v2nf * n_y + v2tf * n_x;}}}}}
}int main()
{init();a[0].live = true;a[0].x = 200;a[0].y = 500;/*a[0].vx = 50;a[0].vy = 20;*/a[1].m = 10;a[1].live = true;a[1].x = 600;a[1].y = 500;/*a[1].vx = 30;a[1].vy = 20;*/// 初始化圖形窗口,大小為 width x highinitgraph(width, high);// 設置填充顏色為綠色setfillcolor(GREEN);BeginBatchDraw();while (!_kbhit()) {cleardevice(); // 清除繪圖// F_allocation();Fa();speed();move();peng();collisionDetection(); // 檢測并處理碰撞draw();FlushBatchDraw();Sleep(8);}EndBatchDraw();// 關閉圖形窗口closegraph();return 0;
}

本文展現的是集成的物理模型框架,感興趣的可以嘗試調試實現各種效果。

我自己測試的是

1,萬有引力完全提供向心力的勻速圓周運動

2,對偏心碰撞的守恒

3,以及編寫初期的重力測試,和碰撞測試,加速度測試。

至于運行效果,這博客也不好發視頻,大家可以嘗試敲一下代碼運行試試。

當物理模型自己結合物理公式和編程寫出來展現在眼前的物理運動時,是真的相信課本里說的天體運動,也是切身感受到了,還有碰撞問題,感覺可以寫個桌球小游戲,不過這些交給大家發揮了,本文到此,感謝觀看。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/79351.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/79351.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/79351.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++編譯與鏈接:從源碼到可執行文件的魔法之旅(Visual Studio實踐)

文章目錄 **C++編譯與鏈接:從源碼到可執行文件的魔法之旅(Visual Studio實踐)****一、C++編譯器的工作流程****二、Visual Studio環境配置實戰****三、示例項目:Hello World全流程解析****四、高級技巧與工具鏈****五、總結與參考資料**C++編譯與鏈接:從源碼到可執行文件的…

現代C++的范式演進與工程實踐深度解析(本文序號不知道怎么整的,有點問題)

引言:C++的復興時代 在經歷了"已死語言"的質疑后,現代C++正迎來前所未有的復興。據2024年TIOBE指數顯示,C++以8.33%的占比穩居第三,較2020年上升2.1個百分點。這種復興并非偶然——隨著C++20標準的全面落地和C++23特性的逐步實現,這門已有40年歷史的語言正在系…

通過gird布局實現div的響應式分布排列

目標&#xff1a;實現對于固定寬度的div盒子在頁面中自適應排布&#xff0c;并且最后一行的div盒子可以與前面的盒子對齊。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" con…

WSL2-Ubuntu22.04安裝URSim5.21.3

WSL2-Ubuntu22.04安裝URSim5.21.3 準備安裝啟動 準備 名稱版本WSL2Ubuntu22.04URSim5.21.3VcXsrvNaN WSL2安裝與可視化請見這篇:WSL2-Ubuntu22.04-配置。 安裝 我們是wsl2-ubuntu22.04&#xff0c;所以安裝Linux版本的URSim&#xff0c;下載之前需要注冊一下&#xff0c;即…

產品研發項目管理6大痛點

在產品研發項目管理實踐中&#xff0c;企業普遍面臨六大系統性挑戰&#x1f937;?♀?&#xff0c;直接影響研發效能與戰略目標達成&#x1f514;&#xff0c;具體表現為&#xff1a; ① 產品需求管理不完善&#xff1a;需求與市場脫節&#xff0c;需求不明確、需求變更頻繁…

計算機網絡基礎概論

計算機網絡基礎概論 目錄 一、網絡基本概念 1.1. 網絡 1.2 互聯網 1.3 ip地址 1.3.1 作用 1.3.2 分類 1.4 MAC地址 1.4.1 MAC地址與 IP 地址的關系 1.5 網絡協議 二、網絡分層模型 2.1 物理層 2.2 數據鏈路層 2.3 網絡層 2.4 傳輸層 2.5 會話層 2.6 表示層 2.7…

Windows下導入文件中的環境變量

在Windows批處理腳本&#xff08;.bat&#xff09;中&#xff0c;通過文件獲取并設置環境變量通常涉及逐行讀取文件內容并動態賦值給變量。以下是具體實現方法及示例&#xff1a; 一、從文件讀取變量并設置到環境變量 假設有一個配置文件&#xff08;如env_config.txt&#xf…

WebSocket 實現數據實時推送原理

WebSocket 實現數據實時推送的核心機制在于其全雙工通信能力和持久的連接特性。以下是其工作原理的詳細步驟&#xff1a; 1. 握手階段&#xff08;HTTP 升級協議&#xff09; 客戶端發起請求&#xff1a;通過發送一個帶有特殊頭部的 HTTP 請求&#xff0c;請求協議升級。 GET …

Linux操作系統學習之---進程狀態

目錄 明確進程的概念: Linux下的進程狀態: 虛擬終端的概念: 見一見現象: 用途之一 : 結合指令來監控進程的狀態: 和進程強相關的系統調用函數接口: getpid()和getppid(): fork(): fork函數創建子進程的分流邏輯: 進程之間具有獨立性: 進程中存在的寫時拷貝: 見一見進程狀態…

何小鵬在得意的笑

"小鵬汽車率先邁出了造車新勢力出海一大步" 作者 | 魏強 編輯 | 盧旭成 4月15日&#xff0c;小鵬汽車在香港舉行小鵬全球熱愛之夜和2025首款全球旗艦小鵬X9上市發布會。 當小鵬汽車創始人何小鵬把香車X9交付給香港首批車主的時候&#xff0c;臉上露出經典的笑臉。…

@Autowird 注解與存在多個相同類型對象的解方案

現有一個 Student 類&#xff0c;里面有兩個屬性&#xff0c;分別為 name 和 id&#xff1b;有一個 StuService 類&#xff0c;里面有兩個方法&#xff0c;返回值均為類型為 Student 的對象&#xff1b;還有一個 StuController 類&#xff0c;里面有一個 Student 類型的屬性&am…

黑馬商城項目(三)微服務

一、單體架構 測試高并發軟件 二、微服務 三、SpringCloud 四、微服務拆分 黑馬商城模塊&#xff1a; 服務拆分原則&#xff1a; 拆分服務&#xff1a; 獨立project&#xff1a; maven聚合&#xff1a; 拆分案例&#xff1a; 遠程調用&#xff1a; package com.hmall.cart.…

PyTorch:學習 CIFAR-10 分類

&#x1f50d; 開始你的圖像分類之旅&#xff1a;一步一步學習 CIFAR-10 分類 圖像分類是計算機視覺中最基礎的任務之一&#xff0c;如果你是初學者&#xff0c;那么以 CIFAR-10 為訓練場是一個不錯的選擇。本文一步一步帶你從零開始&#xff0c;學習如何用深度學習模型實現圖…

3.學習筆記--Spring-AOP總結(p39)-Spring事務簡介(P40)-Spring事務角色(P41)-Spring事務屬性(P42)

1.AOP總結&#xff1a;面向切面編程&#xff0c;在不驚動原始基礎上為方法進行功能增強。 2.AOP核心概念&#xff1a; &#xff08;1&#xff09;代理&#xff1a;SpringAOP的核心是采用代理模式 &#xff08;2&#xff09;連接點&#xff1a;在SpringAOP中&#xff0c;理解為任…

數據庫-day06

一、實驗名稱和性質 分類查詢 驗證 綜合 設計 二、實驗目的 1&#xff0e;掌握數據查詢的Group by &#xff1b; 2&#xff0e; 掌握聚集函數的使用方法。 三、實驗的軟硬件環境要求 硬件環境要求&#xff1a; PC機(單機) 使用的軟件名稱、版本號以及模塊&#xff1a; …

看門狗定時器(WDT)超時

一、問題 Arduino 程序使用<Ticker.h>包時&#xff0c;使用不當情況下&#xff0c;會導致“看門狗WDT超時” 1.1問題控制臺報錯 在串口監視器顯示 --------------- CUT HERE FOR EXCEPTION DECODER ---------------Soft WDT resetException (4): epc10x402077cb epc2…

AI在多Agent協同領域的核心概念、技術方法、應用場景及挑戰 的詳細解析

以下是 AI在多Agent協同領域的核心概念、技術方法、應用場景及挑戰 的詳細解析&#xff1a; 1. 多Agent協同的定義與核心目標 多Agent系統&#xff08;MAS, Multi-Agent System&#xff09;&#xff1a; 由多個獨立或協作的智能體&#xff08;Agent&#xff09;組成&#xff…

Wireshark TS | 異常 ACK 數據包處理

問題背景 來自于學習群里群友討論的一個數據包跟蹤文件&#xff0c;在其中涉及到兩處數據包異常現象&#xff0c;而產生這些現象的實際原因是數據包亂序。由于這兩處數據包異常&#xff0c;都有點特別&#xff0c;本篇也就其中一個異常現象單獨展開說明。 問題信息 數據包跟…

【React】項目的搭建

create-react-app 搭建vite 搭建相關下載 在Vue中搭建項目的步驟&#xff1a;1.首先安裝腳手架的環境&#xff0c;2.通過腳手架的指令創建項目 在React中有兩種方式去搭建項目&#xff1a;1.和Vue一樣&#xff0c;先安裝腳手架然后通過腳手架指令搭建&#xff1b;2.npx create-…

深入淺出 NVIDIA CUDA 架構與并行計算技術

&#x1f407;明明跟你說過&#xff1a;個人主頁 &#x1f3c5;個人專欄&#xff1a;《深度探秘&#xff1a;AI界的007》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目錄 一、引言 1、CUDA為何重要&#xff1a;并行計算的時代 2、NVIDIA在…