社区讨论
物理引擎展示
灌水区参与者 5已保存回复 13
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 13 条
- 当前快照
- 1 份
- 快照标识符
- @m2et101u
- 此快照首次捕获于
- 2024/10/18 22:07 去年
- 此快照最后确认于
- 2025/11/04 23:52 4 个月前
CPP
#include<iostream>
#include<time.h>
#include<windows.h>
#include<math.h>
#include<algorithm>
#include<list>
#include<map>
#include<unordered_map>
#include<cstring>
#include<typeinfo>
BITMAPINFO bmpinfo;
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
union Object {
#define _UNION_CONVER(type) type _##type;\
type& operator=(const type &right) {_##type = right;};\
operator type(){return _##type;}
using _string = std::string;
_UNION_CONVER(int);
_UNION_CONVER(short);
_UNION_CONVER(_string);
_UNION_CONVER(long);
_UNION_CONVER(float);
_UNION_CONVER(double);
_UNION_CONVER(bool);
Object operator=(const Object &a) {
#define _UNION_PUT(type) _##type = a._##type
_UNION_PUT(int);
_UNION_PUT(short);
_UNION_PUT(_string);
_UNION_PUT(long);
_UNION_PUT(float);
_UNION_PUT(double);
_UNION_PUT(bool);
return a;
}
size_t operator()(const Object &a) {
return a._int;
}
~Object(){};
Object(){};
Object(const Object &a) {
*this = a;
}
bool operator==(const Object &a)
{
#define _UNION_COMPARE(a, type) (typeid(a) == typeid(type) && this -> _##type == a._##type)
if(typeid(a) == typeid(this)) {
return _UNION_COMPARE(a, int) ||
_UNION_COMPARE(a, short) ||
_UNION_COMPARE(a, _string) ||
_UNION_COMPARE(a, long) ||
_UNION_COMPARE(a, float) ||
_UNION_COMPARE(a, double) ||
_UNION_COMPARE(a, bool);
} else {
return false;
}
}
#undef _UNION_CONVER
};
class Vector2 {
public:
double x;
double y;
Vector2(): x(0), y(0) {}
Vector2(double a, double b): x(a), y(b) {}
Vector2 operator+(Vector2 a) {
return Vector2(x + a.x, y + a.y);
}
Vector2 operator-(Vector2 a) {
return Vector2(x - a.x, y - a.y);
}
Vector2 operator*(double a) {
return Vector2(x * a, y * a);
}
double Module() {
return sqrt(x * x + y * y);
}
Vector2 Normalize() {
return *this * (1 / (*this).Module());
}
Vector2 operator+=(Vector2 a) {
x += a.x, y += a.y;
return Vector2(x, y);
}
Vector2 operator-=(Vector2 a) {
x -= a.x, y -= a.y;
return Vector2(x, y);
}
Vector2 operator*=(double a) {
x *= a, y *= a;
return Vector2(x, y);
}
bool operator==(Vector2 a) {
return x == a.x && y == a.y;
}
bool operator!=(Vector2 a) {
return x != a.x || y != a.y;
}
std::string ToString() {
return '(' + std::to_string(x) + ',' + std::to_string(y) + ')';
}
};
double Cross(Vector2 a, Vector2 b) {
return a.x * b.y - a.y * b.x;
}
double Dot(Vector2 a, Vector2 b) {
return a.x * b.x + a.y * b.y;
}
typedef Vector2 Vector;
enum class EntityType{
PLAYER,
CAMERA
};
bool Equal(double a, double b) {
if(fabs(a - b) <= 1e-6) {
return true;
}
return false;
}
class Entity{
public:
Vector position = Vector(0, 0);
Vector velocity = Vector(0, 0);
bool Invisible = false;
double Health;
std::string custom_name;
EntityType type;
std::unordered_map<std::string, Object> tag;
};
typedef __time64_t Time;
double tickTime = 0;
Time GetTime() {
FILETIME t;
GetSystemTimeAsFileTime(&t);
return (Time)t.dwHighDateTime << 32 | t.dwLowDateTime;
}
template<typename T1> class DyadicArray {
public:
int width;
T1 a[100000000];
bool set(int x, int y, int value) {
if(x + y * width >= 100000000) return false;
if(x >= width) return false;
if(x < 0 || y < 0) return false;
a[x + y * width] = value;
return true;
}
bool Clear() {
memset(a, 0, sizeof(a));
return true;
}
T1 get(int x, int y) {
return a[x + y * width];
}
};
typedef DyadicArray<COLORREF> ColorMap;
bool Segment(ColorMap &a, Vector start, Vector end, COLORREF color) {
bool result = false;
double k = (start.y - end.y) / (start.x - end.x);
if(fabs(k) <= 1) {
if(start.x > end.x) std::swap(start, end);
for(int x = start.x; x <= end.x && start.x != end.x; ++x) {
result |= a.set(x, (int)(k * (x - start.x) + start.y), color);
}
} else {
if(start.y > end.y) std::swap(start, end);
k = (start.x - end.x) / (start.y - end.y);
for(int y = start.y; y <= end.y && start.y != end.y; ++y) {
result |= a.set((int)(k * (y - start.y) + start.x), y, color);
}
}
return result;
}
ColorMap cmap;
std::list<Entity> entity;
std::list<std::pair<Vector, Vector> > wall;
typedef std::list<Entity>::iterator ExistentEntity;
bool Remove(std::list<Entity> &a, ExistentEntity entity) {
if(entity == a.end()) {
return false;
}
a.erase(entity);
return true;
}
ExistentEntity Spawn(std::list<Entity> &a, EntityType entity_type, Vector position, std::unordered_map<std::string, Object> tag = std::unordered_map<std::string, Object>{}) {
Entity temp_entity;
temp_entity.position = position;
temp_entity.velocity = Vector(0, 0);
temp_entity.type = entity_type;
for(std::unordered_map<std::string, Object>::iterator i = tag.begin(); i != tag.end(); ++i) {
temp_entity.tag.insert(*i);
}
a.push_back(temp_entity);
return prev(a.end());
}
ExistentEntity player, camera;
std::unordered_map<DWORD, bool> keyDown;
bool PaintScreen(HWND hwnd) {
cmap.Clear();
RECT rect;
GetWindowRect(hwnd, &rect);
COORD size;
size.X = rect.right - rect.left;
size.Y = rect.bottom - rect.top;
cmap.width = size.X;
bmpinfo.bmiHeader.biWidth = size.X;
bmpinfo.bmiHeader.biHeight = size.Y;
HDC hdc = GetDC(hwnd);
HDC hdcmem = CreateCompatibleDC(hdc);
HBITMAP hbmpmem = CreateCompatibleBitmap(hdc, size.X, size.Y);
for(std::list<Entity>::iterator temp_entity = entity.begin(); temp_entity != entity.end(); ++temp_entity) {
switch(temp_entity -> type) {
case(EntityType::PLAYER): {
Vector position = (*temp_entity).position, temp_array[4] = {Vector(1, 1), Vector(1, -1), Vector(-1, -1), Vector(-1, 1)};
for(int j = 0; j < 4; ++j) {
Segment(cmap, (position - (*camera).position + temp_array[j] * 16) + Vector(size.X / 2, size.Y / 2), (position - (*camera).position + temp_array[(j + 1) % 4] * 16) + Vector(size.X / 2, size.Y / 2), 0xFFFFFF);
}
break;
}
default: {
break;
}
}
}
for(std::list<std::pair<Vector, Vector> >::iterator temp_wall = wall.begin(); temp_wall != wall.end(); ++temp_wall) {
Segment(cmap, (temp_wall -> first - (*camera).position) + Vector(size.X / 2, size.Y / 2), (temp_wall -> second - (*camera).position) + Vector(size.X / 2, size.Y / 2), 0xFFFFFF);
}
SelectObject(hdcmem, hbmpmem);
SetDIBits(hdcmem, hbmpmem, 0, size.X, cmap.a, &bmpinfo, DIB_RGB_COLORS);
BitBlt(hdc, 0, 0, size.X, size.Y, hdcmem, 0, 0, SRCCOPY);
return true;
}
Time lastCalculate = GetTime();
bool Calculate() {
Time thisCalculate = GetTime();
Time subTime = 2 / tickTime;
while(thisCalculate - lastCalculate > subTime) {
if(keyDown['W'] && player -> tag["on_ground"]._bool) {
player -> velocity.y += 2 * subTime * tickTime;
}
if(keyDown['S']) {
player -> velocity.y -= 0.2 * subTime * tickTime;
}
if(keyDown['A']) {
player -> velocity.x -= 0.1 * subTime * tickTime;
}
if(keyDown['D']) {
player -> velocity.x += 0.1 * subTime * tickTime;
}
player -> velocity.y -= 0.1 * subTime * tickTime;
player -> position += player -> velocity * subTime * tickTime;
camera -> velocity = (player -> position - camera -> position) * 0.05;
camera -> position += camera -> velocity * subTime * tickTime;
// player -> velocity *= exp(log(0.99) * subTime * tickTime);
player -> tag["on_ground"] = false;
for(std::list<std::pair<Vector, Vector> >::iterator temp_wall = wall.begin(); temp_wall != wall.end(); ++temp_wall) {
Vector a = temp_wall -> first, b = temp_wall -> second, ab = b - a;
Vector temp_array[5] = {Vector(0, 0), Vector(1, 1), Vector(1, -1), Vector(-1, -1), Vector(-1, 1)};
Vector majorVector = Vector(0, 0);
Vector maxVector = Vector(0, 0);
for(int i = 0; i < 5; ++i) {
Vector p = player -> position + temp_array[i] * 16;
Vector ap = p - a;
Vector ph = ab * ((Dot(ap, ab)) / (Dot(ab, ab))) - ap;
if(i == 0) {
majorVector = ph;
} else {
if(Dot(ph, majorVector) <= 0) {
if(maxVector.Module() < ph.Module()) {
maxVector = ph;
}
}
}
}
player -> position += maxVector * 1;
if(maxVector != Vector(0, 0)) {
player -> tag["on_ground"] = Dot(maxVector, Vector(0, 1)) > 0 && !(Equal(Dot(maxVector, Vector(0, 1)), 0));
Vector temp_vector = ab * (Dot(player -> velocity, ab) / Dot(ab, ab));
player -> velocity = temp_vector + (player -> velocity - temp_vector) * (-(player -> tag["elasticity"]._double));
}
}
lastCalculate += subTime;
}
return true;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
switch(Message) {
case WM_KEYDOWN: {
keyDown[wParam] = true;
break;
}
case WM_KEYUP: {
keyDown[wParam] = false;
break;
}
case WM_MOUSEMOVE: {
break;
}
case WM_DESTROY: {
PostQuitMessage(0);
exit(0);
break;
}
default: {
return DefWindowProc(hwnd, Message, wParam, lParam);
}
}
return 0;
}
bool CreateWall(Vector a, Vector b) {
wall.push_back(std::make_pair(a, b));
return true;
}
void Initialize() {
tickTime = 1e-5;
#define sin(x) sin((x) * 3.1415926 / 180)
#define cos(x) cos((x) * 3.1415926 / 180)
for(int i = 0; i < 90; ++i) {
CreateWall(Vector(cos(i) * 100 + 100, sin(i) * 100 + 100), Vector(cos(i + 1) * 100 + 100, sin(i + 1) * 100 + 100));
}
CreateWall(Vector(100, 200), Vector(-100, 200));
for(int i = 90; i < 180; ++i) {
CreateWall(Vector(cos(i) * 100 - 100, sin(i) * 100 + 100), Vector(cos(i + 1) * 100 - 100, sin(i + 1) * 100 + 100));
}
CreateWall(Vector(200, 100), Vector(200, -100));
for(int i = 180; i < 270; ++i) {
CreateWall(Vector(cos(i) * 100 - 100, sin(i) * 100 - 100), Vector(cos(i + 1) * 100 - 100, sin(i + 1) * 100 - 100));
}
CreateWall(Vector(100, -200), Vector(-100, -200));
for(int i = 270 ;i < 360; ++i) {
CreateWall(Vector(cos(i) * 100 + 100, sin(i) * 100 - 100), Vector(cos(i + 1) * 100 + 100, sin(i + 1) * 100 - 100));
}
CreateWall(Vector(-200, 100), Vector(-200, -100));
player = Spawn(entity, EntityType::PLAYER, Vector(0, 0));
player -> tag["elasticity"] = double(1);
camera = Spawn(entity, EntityType::CAMERA, Vector(0, 0));
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
ShowWindow(GetConsoleWindow(), HIDE_WINDOW);
bmpinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpinfo.bmiHeader.biWidth = 100;
bmpinfo.bmiHeader.biHeight = 100;
bmpinfo.bmiHeader.biPlanes = 1;
bmpinfo.bmiHeader.biBitCount = 32;
bmpinfo.bmiHeader.biCompression = BI_RGB;
bmpinfo.bmiHeader.biSizeImage = 0;
bmpinfo.bmiHeader.biXPelsPerMeter = 3000;
bmpinfo.bmiHeader.biYPelsPerMeter = 3000;
bmpinfo.bmiHeader.biClrUsed = 0;
bmpinfo.bmiHeader.biClrImportant = 0;
WNDCLASSEX wc;
HWND hwnd;
MSG msg;
memset(&wc,0,sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = WndProc; /* insert window procedure function here */
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszClassName = "WindowClass";
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); /* use "A" as icon name when you want to use the project icon */
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); /* as above */
if(!RegisterClassEx(&wc)) {
MessageBox(NULL, "Window Registration Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
return 0;
}
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,"WindowClass","Caption",WS_VISIBLE|WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,640,480,NULL,NULL,hInstance,NULL);
if(hwnd == NULL) {
MessageBox(NULL, "Window Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
return 0;
}
Initialize();
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != -1) {
TranslateMessage(&msg);
DispatchMessage(&msg);
Calculate();
PaintScreen(hwnd);
Sleep(1);
}
return msg.wParam;
}
RT,花了点时间弄了个小玩意(
运行得在编译选项加上-lgdi32
函数Initialize()内可以修改玩家弹性(默认为1)(为了做机械能守恒弄的)
回复
共 13 条回复,欢迎继续交流。
正在加载回复...