#include<windows.h>
#include<math.h>
int*P,y[1<<18],a=256,c,r,m[8],n,S=a/2,u,v;BITMAPINFO T={40,a,a,1,32};HWND g;
float s,X,Y=-.57,Z,t,l,d;int WINAPI WinMain(HINSTANCE I,HINSTANCE,LPSTR,int)
{WNDCLASS w={67,DefWindowProc,0,0,I,0,0,0,0,"0"};RegisterClass(&w);HDC h=GetDC(
g=CreateWindow("0","○",513<<19,0,0,a,a,0,0,I,0));while(GetMessage((MSG*)m,g,0,0)!=-1)
{if(m[1]==15){s+=.1;Z=Y*cos(s);X=Y*sin(s);P=y;for(v=S;v>-S;v--){for(u=-S;u0?t=sqrt(d),l=sqrt(u*u+v*v+t*t),n=(X*u/l+Y*v/l+Z*t/l)*255,n=n<0?0:n:
n=64;*P++=n;}}SetDIBitsToDevice(h,0,0,a,a,0,0,0,a,y,&T,0);}else DispatchMessage((MSG*)m);
InvalidateRect(g,0,0);}return 0;}
↑のコードをコンパイルして実行すると、以下の様な「グルグル回転する球」が表示されます。
キタ Y⌒Y⌒Y⌒Y⌒(。A。)!!!
(※ 実際にプログラムを実行すると、高速で球が回転している様子が表示されます。)
Win32APIのコードの為、GUIがステキでいい感じ^^;)
それでは、プログラムの解説に移ります。
冒頭のコードに、適当なインデント・スペースを入れて読みやすくした物が以下のコードです。↓↓
#include<windows.h>
#include<math.h>
int *P, y[1<<18], a=256, c, r, m[8], n, S = a/2, u, v;
BITMAPINFO T = {40,a,a,1,32};
HWND g;
float s, X, Y =- .57, Z, t, l, d;
int WINAPI WinMain(HINSTANCE I, HINSTANCE, LPSTR, int)
{
WNDCLASS w = {67, DefWindowProc, 0,0,I,0,0,0,0,"0"};
RegisterClass(&w);
HDC h = GetDC(
g = CreateWindow("0", "○", 513<<19, 0, 0, a, a, 0, 0, I, 0)
);
while(GetMessage((MSG*)m,g,0,0) != -1) {
if (m[1] == 15) {
s += .1;
Z = Y * cos(s);
X = Y * sin(s);
P = y;
for (v = S; v>-S; v--) {
for (u =- S; u 0 ?
t = sqrt(d),
l = sqrt(u*u+v*v+t*t),
n = (X*u/l+Y*v/l+Z*t/l)*255,
n = n < 0 ? 0 : n
:
n = 64;
*P++ = n;
}
}
SetDIBitsToDevice(h,0,0,a,a,0,0,0,a,y,&T,0);
}
else
DispatchMessage((MSG*)m);
InvalidateRect(g,0,0);
}
return 0;
}
まだまだ読みにくい部分がある為、変数名を変更し、一部のコードを修正します。
そして、定義済の名称(#defineされているもの)がある値は、定義済の名称に変更します。
また、VC++2005のデフォルトのコンパイルオプションで表示される、C4305, C4244の警告(double型からfloat型, int型からfloat型への変換警告)も、あわせて対処します。
それが以下のコードです。↓↓
1 : #include<windows.h>
2 : #include<math.h>
3 :
4 : int c, r, n, u, v;
5 : float s, X, Z, t, l, d;
6 : int *lpnBits, nBits[1<<18];
7 :
8 : const float Y = -0.57f;
9 : int nWndSize = 256;
10 : int nHalfSize = nWndSize/2;
11 :
12 : BITMAPINFO bitmapInfo = {sizeof(BITMAPINFOHEADER), nWndSize, nWndSize, 1, 32};
13 : HWND hWnd;
14 : MSG msg;
15 :
16 : int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int)
17 : {
18 : WNDCLASS wndclass = {
19 : CS_CLASSDC | CS_VREDRAW | CS_HREDRAW,
20 : DefWindowProc,
21 : 0, 0, hInst, NULL, NULL, NULL, NULL,
22 : "MyClass"
23 : };
24 : RegisterClass(&wndclass);
25 :
26 : hWnd = CreateWindow(
27 : "MyClass", "○",
28 : WS_VISIBLE | WS_SYSMENU,
29 : 0, 0, nWndSize, nWndSize,
30 : NULL, NULL, hInst, NULL
31 : );
32 : HDC hdc = GetDC(hWnd);
33 :
34 : while (GetMessage(&msg, hWnd, 0, 0) != -1) {
35 : if (msg.message == WM_PAINT) {
36 : s += .1f;
37 : Z = Y * cos(s);
38 : X = Y * sin(s);
39 : lpnBits = nBits;
40 :
41 : for (v = nHalfSize; v > -nHalfSize; v--) {
42 : for (u =- nHalfSize; u < nHalfSize; u++) {
43 : d = float(9999 - u*u - v*v);
44 : d > 0 ?
45 : t = sqrt(d),
46 : l = sqrt(u*u+v*v+t*t),
47 : n = int( (X*u/l+Y*v/l+Z*t/l) * 255),
48 : n = n < 0 ? 0 : n
49 : :
50 : n = 64;
51 :
52 : *lpnBits++ = n;
53 : }
54 : }
55 :
56 : SetDIBitsToDevice(hdc, 0, 0, nWndSize, nWndSize, 0, 0,
57 : 0, nWndSize, nBits, &bitmapInfo, 0);
58 : }
59 : else
60 : DispatchMessage(&msg);
61 :
62 : InvalidateRect(hWnd, NULL, FALSE);
63 : Sleep(10);
64 : }
65 :
66 : return 0;
67 : }
【変数名の変更点】
y</td> | ⇒ | nBits |
P | ⇒ | lpnBits |
a | ⇒ | nWndSize |
S | ⇒ | nHalfSize |
g | ⇒ | hWnd |
T | ⇒ | bitmapInfo |
I | ⇒ | hInst |
w | ⇒ | wndclass |
h | ⇒ | hdc |
"0" | ⇒ | "MyClass" |
【変数の型変更点】
【定義済み名称への変更点】
12行目 40 | ⇒ | sizeof(BITMAPINFOHEADER) |
19行目 67 | ⇒ | CS_CLASSDC | CS_VREDRAW | CS_HREDRAW |
28行目 513<<19 | ⇒ | WS_VISIBLE | WS_SYSMENU |
35行目 15 | ⇒ | WM_PAIN |
随所 | ⇒ | FALSE または NULL |
砂嵐プログラミング その4 のコードを理解していれば、わりと難なく読めるコードだと思います^^;)
ちょっとだけ補足しておくと、
WM_PAINTメッセージの処理部分では、
nBitsにビットマップデータを保持するものとし、
lpnBitsにnBitsのアドレスを割り当て(←39行目)、
ループ内で 「 *lpnBits++ = n 」 (←52行目。ちなみに、nには計算結果が入る)をすることにより、
nBitsのビットマップデータが1つ1つ計算して埋められていきます。
そして最後に、SetDIBitsToDevice()でビットマップデータをウィンドウに描画(←56,57行目)して、球の表示処理終了!!
というわけです^^;)
さらに、WM_PAINTメッセージ処理で、球の描画を行う度に、変数sが「s += .1f」 (←36行目) されており、
その変数sをsin(), cos()に入れて変数Z, 変数Xの値を取得している(←37,38行目)事から、
変数Z, 変数Xへ周期的に同じ値が代入される事になり、
結果として、グルグル回転している球が表示されるというワケです^^;)
いやぁ~、なかなかイキなコードだw