WindowsAPIでちらつきをなくす方法

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
スー

WindowsAPIでちらつきをなくす方法

#1

投稿記事 by スー » 16年前

皆様こんばんわ。

私はいま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;
}


タイトルを無題にしてしまったのですぐ修正しました

バグ

Re:WindowsAPIでちらつきをなくす方法

#2

投稿記事 by バグ » 16年前

ダブルバッファで調べてみるといいですよ(^-^)

スー

Re:WindowsAPIでちらつきをなくす方法

#3

投稿記事 by スー » 16年前

バグさんレスありがとうございます。

無事画面のちらつきを無くすことができました。
ありがとうございます。

ダブルバッファで調べるとたくさんできてきました。
私の調べ不足でした><;
今後はもう入念に調べてから質問をするようにしたいです。

バグ

Re:WindowsAPIでちらつきをなくす方法

#4

投稿記事 by バグ » 16年前

いえ、私も同じ質問をここでしたことがありましたので…(笑)

閉鎖

“C言語何でも質問掲示板” へ戻る