私はいまWindowsAPIでスクリーンセーバーを作っています。
デザインは東方の「波と粒の境界」(以下、波粒)という弾幕を表示するようにしています。
スクリーンセーバーで波粒を表示させる所まではできたのですが、画面のちらつきが激しいです。
画面のちらつきを無くしたいのですが、DXライブラリの
ClearDrawScreen() ;
ScreenFlip() ;
などの関数は私が調べた限り見つけることができなかったです。
ちょっとした興味でWindowsAPIをつついてみたので知識はほとんどない状態です。;;
ちらつきを無くす方法がありましたら、教えてください。
どうぞよろしくお願いします。
環境は
VC++2005
windowsXP
です。
以下ソースです。
#include <windows.h> #include <scrnsave.h> #include <math.h> #include <time.h> //スクリーンセーバを作るためのライブラリ #pragma comment(lib,"ScrnSave.lib") #pragma comment(lib,"Comctl32.lib") //タイマーのID #define ID_TIMER 32767 #define PI 3.1415926535897932384626433832795 #define RAD 57.295779513082320876798154814105 //弾の最大数 #define MAX 65536 int i,j; int wx,wy; int count = 0; //弾幕の制御変数 とりあえずグローバルで float angle = 0; float plus_angle = 1; bool angle_flag = false; //Ball::Draw() で //RoundRect(hdc , x , y , x+size , y+size , size , size); //と書いてもhdcがありません とエラーがでるのでポインタを使ってみた HDC *p_hdc; //弾幕のクラス class Ball{ public: float x,y,vx,vy; int size; bool used; Ball(); void Add(float X, float Y, float SP, float ANGLE); void Draw(); void Action(); }; //コンストラクタ Ball::Ball(){ x = 0; y = 0; vx = 0; vy = 0; size = 20; used = false; } // 弾幕を発射する X Y 速度 角度 void Ball::Add(float X, float Y, float SP, float ANGLE){ x = X; y = Y; vx = cos(ANGLE/RAD)*SP; vy = sin(ANGLE/RAD)*SP; used = true; } // 弾幕の描写 void Ball::Draw(){ RoundRect(*p_hdc , x , y , x+size , y+size , size , size); } // 弾幕の制御 void Ball::Action(){ x += vx; y += vy; //画面外にでたら消す if(x < -size || x > wx)used = false; if(y < -size || y > wy)used = false; } Ball ball[MAX]; //for文とif文を弾幕を発射するたびに書くのではめんどくさいので関数に void Add(float X, float Y, float SP, float ANGLE){ for(i=0;i<MAX;i++){ if(ball.used == false){ ball.Add(X,Y,SP,ANGLE); break; } } } LRESULT WINAPI ScreenSaverProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { srand((unsigned)time(NULL)); RECT rc; HDC hdc; p_hdc = &hdc; HBRUSH hBrush,hOldBrush; switch(msg) { case WM_CREATE: GetClientRect(hWnd,&rc); wx = rc.right-rc.left; wy = rc.bottom-rc.top; SetTimer(hWnd,ID_TIMER,16,NULL); break; case WM_TIMER: //画面の初期化 画面の全範囲を黒で塗りつぶす hdc = GetDC(hWnd); hBrush= CreateSolidBrush(RGB(0,0,0)); hOldBrush= (HBRUSH)SelectObject(hdc,hBrush); Rectangle(hdc,0,0,wx,wy); SelectObject(hdc,hOldBrush); DeleteObject(hBrush); ReleaseDC(hWnd,hdc); hdc = GetDC(hWnd); hBrush= CreateSolidBrush(RGB(200,0,200)); hOldBrush= (HBRUSH)SelectObject(hdc,hBrush); for(i=0;i<MAX;i++){ if(ball.used == true){ ball.Draw(); ball.Action(); } } SelectObject(hdc,hOldBrush); DeleteObject(hBrush); ReleaseDC(hWnd,hdc); if(count++ % 2 == 0){ for(j=0;j<6;j++) Add(wx/2,wy/4,8,angle+j*60); } angle += plus_angle; if(angle_flag == false)plus_angle += 0.1; if(angle_flag == true)plus_angle -= 0.1; if(plus_angle > 350)angle_flag = true; if(plus_angle < 10)angle_flag = false; InvalidateRect( hWnd, NULL, FALSE ); break; case WM_DESTROY: KillTimer(hWnd,ID_TIMER); PostQuitMessage(0); return 0; default: break; } return DefScreenSaverProc(hWnd, msg, wParam, lParam); } BOOL WINAPI ScreenSaverConfigureDialog(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { return TRUE; } BOOL WINAPI RegisterDialogClasses(HANDLE hInst) { return TRUE; }
タイトルを無題にしてしまったのですぐ修正しました