私はいま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;
}タイトルを無題にしてしまったのですぐ修正しました