📄 main.c
字号:
#include <windows.h>
#include <windef.h>
#include <commctrl.h>
#include <commdlg.h>
#include <wingdi.h>
#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#include <stdio.h>
#include <math.h>
#include "resource.h"
#include "cannon.h"
#define MYSIDEVIEW 2000
const char* str[] =
{
"幻\0", "炎\0", "28\0", "舰\0","队\0"
};
LRESULT CALLBACK DemoDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK DefaultWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
HINSTANCE hinst;
HWND hMainWindow;
HDC hBufferDC;
HBITMAP hBufferBitmap;
void InitializeVariables(void);
void DrawLine(HDC hdc, int h1, int v1, int h2, int v2, int thk, COLORREF clr);
void DrawRectangle(HDC hdc, RECT *r, int thk, COLORREF clr);
void DrawCircle(HDC hdc, int cx, int cy, int r, COLORREF clr);
void DrawString(HDC hdc, int x, int y, LPCSTR lpszString, int size, int ptsz);
int DoSimulation(void);
BOOL UpdateParticleState(TParticle *p, int dtime);
void CreateParticleExplosion(int x, int y, int force, int life, float gravity, float angle);
BOOL DrawParticleExplosion(HDC hdc);
int tb_Rnd(int min, int max);
int tb_Round(double x);
int APIENTRY WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
DLGPROC dlgprc;
int retval = 0;
dlgprc = (DLGPROC)MakeProcInstance(DemoDlgProc, hInstance);
retval = DialogBox(hInstance, MAKEINTRESOURCE(IDD_DEMODIALOG), NULL, dlgprc);
if (-1 == retval)
{
MessageBox(NULL, "Error", "Can`t create dialog box.", MB_OK);
return FALSE;
}
FreeProcInstance((FARPROC)dlgprc);
return (FALSE);
}
LRESULT CALLBACK DemoDlgProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
static HWND hTopView;
static HWND hSideView;
WNDCLASSEX wclass;
char str[16];
BOOL status;
RECT r;
HDC hdc;
switch (message)
{
case WM_INITDIALOG:
// 这里初始化对话框
{
// 设置一个子窗口类以便我们能创建两个
// 窗口来画两个轨道视图
wclass.cbSize = sizeof(wclass);
wclass.style = CS_HREDRAW | CS_VREDRAW;
wclass.lpfnWndProc = DefaultWndProc;
wclass.cbClsExtra = 0;
wclass.cbWndExtra = 0;
wclass.hInstance = hinst; // ?????
wclass.hIcon = NULL;
wclass.hCursor = NULL;
wclass.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(0, 0, 0));
wclass.lpszMenuName = NULL;
wclass.lpszClassName = "ViewClass";
wclass.hIconSm = NULL;
RegisterClassEx(&wclass);
// 为边视图创建一个子窗口
hSideView = CreateWindowEx(
0L,
"ViewClass",
NULL,
WS_CHILD | WS_VISIBLE | WS_BORDER,
200,
10 + 10,
400,
400,
hDlg,
NULL,
hinst,
NULL
);
// 以我们的ID MYSIDEVIEW来标记窗口,这样我们
// 能够在画窗口时将它与顶视图窗口区分开。
SetWindowLong(hSideView, GWL_USERDATA, MYSIDEVIEW);
ShowWindow(hSideView, SW_SHOW);
// 现在以变量中的默认值来初始化对话框中的所有编辑控件
// 设置所有变量的默认值
InitializeVariables();
// 现在将每个变量值转换为字符串并
// 设置适当的edit控件
sprintf(str, "%d", xc);
SetDlgItemText(hDlg, IDC_X, str);
sprintf(str, "%d", yc);
SetDlgItemText(hDlg, IDC_Y, str);
sprintf(str, "%d", V0);
SetDlgItemText(hDlg, IDC_V0, str);
sprintf(str, "%d", Duration);
SetDlgItemText(hDlg, IDC_DURATION, str);
sprintf(str, "%f", Gravity);
SetDlgItemText(hDlg, IDC_GRAVITY, str);
sprintf(str, "%f", Angle);
SetDlgItemText(hDlg, IDC_ANGLE, str);
// 创建一个作图缓冲区
hdc = GetDC(hSideView);
hBufferDC = CreateCompatibleDC(hdc);
hBufferBitmap = CreateCompatibleBitmap(hdc, 400, 400);
ReleaseDC(hSideView, hdc);
// hBufferBitmap = CreateBitmap(500, 200, 1, 24, NULL);
SelectObject(hBufferDC, hBufferBitmap);
/***********************/
bShowTrack = FALSE;
CheckDlgButton(hDlg, IDC_CHECK_TRACK, BST_UNCHECKED);
/***********************/
} // End of case WM_INITDIALOG
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDC_RANDOM:
case IDC_FIRE:
// 以编辑控件显示的值更新变量
if (IDC_FIRE == LOWORD(wParam))
{
GetDlgItemText(hDlg, IDC_X, str, 15);
xc = atoi(str);
GetDlgItemText(hDlg, IDC_Y, str, 15);
yc = atoi(str);
GetDlgItemText(hDlg, IDC_V0, str, 15);
V0 = atoi(str);
GetDlgItemText(hDlg, IDC_DURATION, str, 15);
Duration = atoi(str);
GetDlgItemText(hDlg, IDC_GRAVITY, str, 15);
Gravity = atoi(str);
GetDlgItemText(hDlg, IDC_ANGLE, str, 15);
Angle = atoi(str);
} // End of if (IDC_FIRE == LOWORD(wParam))
else
{
xc = tb_Rnd(100, 300);
yc = tb_Rnd(100, 300);
V0 = tb_Rnd(10, 100);
Duration = tb_Rnd(2000, 6000);
Gravity = tb_Rnd(0, 100);
Angle = 999;
sprintf(str, "%d", xc);
SetDlgItemText(hDlg, IDC_X, str);
sprintf(str, "%d", yc);
SetDlgItemText(hDlg, IDC_Y, str);
sprintf(str, "%d", V0);
SetDlgItemText(hDlg, IDC_V0, str);
sprintf(str, "%d", Duration);
SetDlgItemText(hDlg, IDC_DURATION, str);
sprintf(str, "%f", Gravity);
SetDlgItemText(hDlg, IDC_GRAVITY, str);
sprintf(str, "%f", Angle);
SetDlgItemText(hDlg, IDC_ANGLE, str);
} // End of else (IDC_FIRE == LOWORD(wParam))
CreateParticleExplosion(xc, yc, V0, Duration, Gravity, Angle);
r.left = 0;
r.right = 400;
r.top = 0;
r.bottom = 400;
// 初始化时间和状态变量
status = TRUE;
// 开始单步模拟
// 直到目标被击中,炮弹击中了地面或sim。时间到。
while (status)
{
// 背景涂黑
if (!bShowTrack)
{
DrawRectangle(hBufferDC, &r, 1, RGB(0, 0, 0));
}
// 绘制粒子爆炸
status = DrawParticleExplosion(hBufferDC);
hdc = GetDC(hSideView);
if (!BitBlt(
hdc,
0,
0,
r.right,
r.bottom,
hBufferDC,
0,
0,
SRCCOPY
)
)
{
MessageBox(NULL, "BitBlt failed", "Error", MB_OK);
status = FALSE;
}
ReleaseDC(hSideView, hdc);
} // End of while (status)
break;
case ID_CLOSE:
{
// 清除子窗口并关闭对话框
DeleteObject(hBufferBitmap);
DeleteDC(hBufferDC);
DestroyWindow(hSideView);
EndDialog(hDlg, 1);
} // End of case ID_CLOSE
break;
case IDCANCEL:
{
// 清除子窗口并关闭对话框
DeleteObject(hBufferBitmap);
DeleteDC(hBufferDC);
DestroyWindow(hSideView);
EndDialog(hDlg, 0);
} // End of case IDCANCEL
break;
/***********************/
case IDC_CHECK_TRACK:
/*
bShowTrack = !bShowTrack;
CheckDlgButton(
hDlg,
IDC_CHECK_TRACK,
bShowTrack ? BST_CHECKED : BST_UNCHECKED);
*/
bShowTrack = IsDlgButtonChecked(hDlg, IDC_CHECK_TRACK);
CheckDlgButton(
hDlg,
IDC_CHECK_TRACK,
bShowTrack ? BST_CHECKED : BST_UNCHECKED);
break;
/***********************/
} // End of switch (LOWORD(wParam))
} // End of case WM_COMMAND
break;
default:
return (FALSE);
} // End of switch (message)
return (TRUE);
}
//------------------------------------------------------
// 子窗口的默认处理函数
//------------------------------------------------------
LRESULT CALLBACK DefaultWndProc(
HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
switch (message)
{
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
void InitializeVariables(void)
{
xc = 200;
yc = 100;
V0 = 75;
Duration = 4000;
Gravity = 30.0f;
Angle = 999;
}
void DrawRectangle(
HDC hdc,
RECT *r,
int thk,
COLORREF clr
)
{
HBRUSH CurrentBrush;
HBRUSH OldBrush;
HPEN CurrentPen;
HPEN OldPen;
COLORREF FColor = clr;
COLORREF BColor = clr;
if (NULL == hdc || NULL == r)
{
return;
}
CurrentBrush = CreateSolidBrush(BColor);
OldBrush = (HBRUSH)SelectObject(hdc, CurrentBrush);
CurrentPen = CreatePen(PS_SOLID, thk, FColor);
OldPen = (HPEN)SelectObject(hdc, CurrentPen);
Rectangle(hdc, r->left, r->top, r->right, r->bottom);
SelectObject(hdc, OldBrush);
SelectObject(hdc, OldPen);
DeleteObject(CurrentBrush);
DeleteObject(CurrentPen);
}
void DrawCircle(
HDC hdc,
int cx,
int cy,
int r,
COLORREF clr
)
{
HBRUSH CurrentBrush;
HBRUSH OldBrush;
HPEN CurrentPen;
HPEN OldPen;
COLORREF FColor = clr;
COLORREF BColor = clr;
static int num;
if (NULL == hdc)
{
return;
}
CurrentBrush = CreateSolidBrush(BColor);
OldBrush = (HBRUSH)SelectObject(hdc, CurrentBrush);
CurrentPen = CreatePen(PS_SOLID, 1, FColor);
OldPen = (HPEN)SelectObject(hdc, CurrentPen);
/*
Ellipse(hdc, cx - r, cy - r, cx + r, cy + r);
*/
/***********************/
/*呵呵~~这样做的话由于有粒子死亡,所以后面的字会乱*/
SetBkColor(hdc, RGB(0,0,0));
SetTextColor(hdc, clr);
TextOut(hdc, cx, cy, str[(num % 5)], strlen(str[(num % 5)]));
num ++;
/***********************/
SelectObject(hdc, OldBrush);
SelectObject(hdc, OldPen);
DeleteObject(CurrentBrush);
DeleteObject(CurrentPen);
}
int tb_Rnd(int min, int max)
{
int number;
number = (((abs(rand()) % (max - min + 1)) + min));
if (number > max)
{
number = max;
}
if (number < min)
{
number = min;
}
return number;
}
/////////////////////////////////////////////
// 浮点数的取整(四舍五入)
/////////////////////////////////////////////
int tb_Round(double x)
{
int result;
double remainder;
result = (int)(x);
if (0 == result)
return 0;
remainder = fmod(x, (double)result); // 取余数
if (0.5 <= remainder)
result ++;
return result;
}
void CreateParticleExplosion(
int x,
int y,
int Vinit,
int life,
float gravity,
float angle
)
{
int i;
int m; // 偏向型
float f; // 存活时间百分比
Explosion.Active = TRUE;
Explosion.x = x;
Explosion.y = y;
Explosion.V0 = Vinit;
for (i = 0; i < _MAXPARTICLES; i ++)
{
Explosion.p[i].x = 0;
Explosion.p[i].y = 0;
Explosion.p[i].vi = tb_Rnd(Vinit/2, Vinit);
if (999 > angle)
{
if (0 == tb_Rnd(0, 1))
m = -1;
else
m = 1;
Explosion.p[i].angle = -angle + m * tb_Rnd(0,10);
} // End of if (999 > angle)
else
{
Explosion.p[i].angle = tb_Rnd(0, 360);
}
f = (float)tb_Rnd(80, 100) / 100.0f;
Explosion.p[i].life = tb_Round(life * f);
Explosion.p[i].r = 255;
Explosion.p[i].g = 255;
Explosion.p[i].b = 255;
Explosion.p[i].time = 0;
Explosion.p[i].Active = TRUE;
Explosion.p[i].gravity = gravity;
Explosion.p[i].vx = Explosion.p[i].vi * cos(Explosion.p[i].angle * PI / 180.0f);
Explosion.p[i].vy = Explosion.p[i].vi * sin(Explosion.p[i].angle * PI / 180.0f);
} // End of for (i = 0; i < _MAXPARTICLES; i ++)
}
BOOL DrawParticleExplosion(HDC hdc)
{
int i;
BOOL finished = TRUE;
float r; // 生命经过的百分比
COLORREF clr;
if (Explosion.Active)
{
for (i = 0; i < _MAXPARTICLES; i ++)
{
if (Explosion.p[i].Active)
{
finished = FALSE;
r = ((float)(Explosion.p[i].life - Explosion.p[i].time) / (float)(Explosion.p[i].life));
// 计算粒子的颜色
clr = RGB(tb_Round(r * Explosion.p[i].r), tb_Round(r * Explosion.p[i].g), tb_Round(r * Explosion.p[i].b));
DrawCircle(
hdc,
Explosion.x + tb_Round(Explosion.p[i].x),
Explosion.y + tb_Round(Explosion.p[i].y),
2, // 半径
clr
);
Explosion.p[i].Active = UpdateParticleState(&(Explosion.p[i]), 10);
} // End of if (Explosion.p[i].Active)
} // End of for (i = 0; i < _MAXPARTICLES; i ++)
} // End of if (Explosion.Active)
if (finished)
// 如果所有粒子都死亡
{
Explosion.Active = FALSE;
}
return !finished;
}
//********************************
//更新粒子属性,如运动时间,位置等
//********************************
BOOL UpdateParticleState(TParticle* p, int dtime)
{
BOOL retval;
float t;
p->time += dtime;
if ((p->time) >= (p->life))
{
retval = FALSE;
}
else
{
retval = TRUE;
t = (float)(p->time) / 1000.0f;
p->x = p->vx * t;
p->y = p->vy * t + (p->gravity * t * t) / 2.0f;
}
return retval;
}
/*还应改确定窗口大小,粒子出了窗口就死亡*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -