ページ 1 / 1
花火の始点が5つ連なってしまって上手くばらけさせて綺麗な花火が作れません。C言語のMsTimer型です。
Posted: 2011年1月06日(木) 20:40
by wasabi
コード:
/**
* 最終課題 : 打ち上げ花火
* 注意: 描画領域の大きさは,Width, Height である。
* πの値はPAIで定義されている。(ラジアン値=PAI/360.0×度)
*/
#include <stdio.h> // 基本関数など(標準)
#include <string.h> // 文字操作用(標準)
#include <math.h> // 数学関数用(標準)
#include "WinBase4.h" // C言語グラフィックス教材専用
/* 花火構造体の型宣言 */
typedef struct _HANABI {
double xpos; // 花火の位置(X座標)
double ypos; // 花火の位置(Y座標)
double radius; // 花火の半径
COLORREF color; // 花火の色
} HANABI;
/* プロトタイプの宣言 */
void drawHanabi( HDC gDC, HANABI hanabi );
/* 広域変数の定義 */
//HANABI blueHanabi; // 花火変数を宣言する
HANABI abcHanabi[5]; // 花火変数を宣言する
char Str1[] = " 打ち上げ花火";
/**
* 機能 : 初期設定用(プログラムの実行で最初に1回呼ばれる)
* HWND hWind : ウィンドウのハンドル
* 戻り値 : なし
*/
void MsInit( HWND hWind )
{
MsWinReal( FALSE ); // gDCを仮想画面にする
// 花火に初期値を設定する
abcHanabi[0].xpos = 300; // 位置
abcHanabi[0].ypos = 150; // 位置
abcHanabi[0].radius = 100; // 半径
abcHanabi[0].color = RGB( 0, 0, 255);
// 花火に初期値を設定する
abcHanabi[1].xpos = 400; // 位置
abcHanabi[1].ypos = 200; // 位置
abcHanabi[1].radius = 100; // 半径
abcHanabi[1].color = RGB( 0,255 , 0);
// 花火に初期値を設定する
abcHanabi[2].xpos = 300; // 位置
abcHanabi[2].ypos = 300; // 位置
abcHanabi[2].radius = 100; // 半径
abcHanabi[2].color = RGB( 255,0 , 0);
// 花火に初期値を設定する
abcHanabi[3].xpos = 450; // 位置
abcHanabi[3].ypos = 150; // 位置
abcHanabi[3].radius = 100; // 半径
abcHanabi[3].color = RGB( 255,0 ,255);
// 花火に初期値を設定する
abcHanabi[4].xpos = 250; // 位置
abcHanabi[4].ypos = 350; // 位置
abcHanabi[4].radius = 100; // 半径
abcHanabi[4].color = RGB( 0,255 ,255 );
}
/**
* 機能: 1/100秒(10ms)ごとに実行される
* HWND hWind : ウィンドウのハンドル
* 戻り値 : なし
*/
void MsTimer( HWND hWind, UINT TimerID )
{
static int count = 0;
double dd, x0, y0;
int i;
//
MsClear( 0 ); // 仮想画面をクリアーする
/*
abcHanabi[i].xpos += abcHanabi[i].delta*cos(abcHanabi[i].dir);
if((Width-abcHanabi[i].radius)<abcHanabi[i].xpos) abcHanabi[i].dir = PAI - abcHanabi[i].dir;
if((0.0+abcHanabi[i].radius)>abcHanabi[i].xpos) abcHanabi[i].dir = PAI - abcHanabi[i].dir;
abcHanabi[i].ypos += abcHanabi[i].delta*sin(abcHanabi[i].dir);
if((Height-abcHanabi[i].radius)<abcHanabi[i].ypos) abcHanabi[i].dir = 0.0 - abcHanabi[i].dir;
if((0.0+abcHanabi[i].radius)>abcHanabi[i].ypos) abcHanabi[i].dir = 0.0 - abcHanabi[i].dir;
*/
for(i=0;i<5;i++)
{
// 新しい位置を計算する
// 花火を表示する
drawHanabi( gDC, abcHanabi[i] );
}
//
TextOut( gDC, 20, 10, Str1, (int)strlen(Str1) ); // 見出しを表示
MsShow(); // 実画面への表示
count++;
}
// WM_DESTROY(X)で起動される
void MsClose( HWND hWind )
{
// プログラムの後処理を記述する
}
/**
* 関数名: drawHanabi
* 機能 : 花火を(xpos,ypos)座標に描く
*/
void drawHanabi( HDC gDC, HANABI hanabi )
{
double x1, y1, x0, y0; // 左上隅と右下隅
double rr;
int i;
double nHdo;
for(i=0;i<=5;i++){
// === 描画のための準備 ===
HPEN hPen0 , hPen ; // ペンのハンドル
HBRUSH hBrush0 , hBrush ; // ブラシのハンドル
COLORREF Color ; // 色指定コード
//ans = 0;
//ans = 20 + MsRandom(200);
//nLeng = ans;
Color = hanabi.color; // 色を取り出す
hBrush = CreateSolidBrush( Color ); // ブラシを作成する。
hBrush0 = SelectObject( gDC , hBrush ); // ブラシをDCに持たせる
hPen = CreatePen( PS_SOLID , 0 , Color ); // ペンを作成する
hPen0 = SelectObject( gDC , hPen ); // ペンをDCに持たせる
//-------------------------------------------------------------------------------------------
nHdo=0;
rr = hanabi.radius; //花火の半径
// === 花火を描く ===
x0=300;
y0=150;
x0 = abcHanabi[i].xpos;
y0 = abcHanabi[i].ypos;
while( nHdo<360 )
{
x1 = hanabi.xpos+rr*cos(nHdo*(PAI/180.0));
y1 = hanabi.ypos+rr*sin(nHdo*(PAI/180.0));
MoveToEx(gDC,(int)(x0+0.5),(int)(y0+0.5),NULL);
LineTo(gDC,(int)(x1+0.5),(int)(y1+0.5));
nHdo += 10;
}
//----------------------------------------------------------------------------------------------------
SelectObject( gDC , hPen0 ) ; // 元のペンを持たせる
DeleteObject( hPen ); // ペンを消去する
SelectObject( gDC , hBrush0 ) ; // 元のブラシを持たせる
DeleteObject( hBrush ); // ブラシを消去する
}
// === 描画関係の後処理 ===
}
学校の課題で花火の製作をすることにしたのですが、始点が上手く定まらずそれぞれの花火のペン色がほかのすべての
花火の始点に連らなって移ってしまう処理がされてしまいます。
それぞれの花火の5つの始点をうまくばらけさせるにはどうすればいいのでしょうか。
またゆくゆくはランダムに座標を指定して花火を作りたいと思っています。
ご指摘の方よろしくおねがいします。
Re: 花火の始点が5つ連なってしまって上手くばらけさせて綺麗な花火が作れません。C言語のMsTimer型です。
Posted: 2011年1月06日(木) 23:43
by kimuchi
wasabiさんの書かれた花火の各点の移動処理はコメントアウト部分でしょうか?
とりあえず今疑問に思った事を書きます。
144~147行目で、x0,y0の代入が連続している、
また此処だけhanabiではなくabcHanabiが使われているのはなぜでしょうか?
Re: 花火の始点が5つ連なってしまって上手くばらけさせて綺麗な花火が作れません。C言語のMsTimer型です。
Posted: 2011年1月07日(金) 01:05
by wasabi
kimuch様ご指摘ありがとうございます。
ご指摘された通り直したところ上手く処理することができました。
ありがとうございます。
動きは10個ほど花火をランダムで座標にあげたあとに一回画面をクリアし、もう一度花火を打ち上げるの繰り返しをしようと考えています。
コメント部分は無視してください。
コード:
/**
* 最終課題 : 打ち上げ花火
* 注意: 描画領域の大きさは,Width, Height である。
* πの値はPAIで定義されている。(ラジアン値=PAI/360.0×度)
*/
#include <stdio.h> // 基本関数など(標準)
#include <string.h> // 文字操作用(標準)
#include <math.h> // 数学関数用(標準)
#include "WinBase4.h" // C言語グラフィックス教材専用
/* 花火構造体の型宣言 */
typedef struct _HANABI {
double xpos; // 花火の位置(X座標)
double ypos; // 花火の位置(Y座標)
double radius; // 花火の半径
COLORREF color; // 花火の色
} HANABI;
/* プロトタイプの宣言 */
void drawHanabi( HDC gDC, HANABI hanabi );
/* 広域変数の定義 */
//HANABI blueHanabi; // 花火変数を宣言する
HANABI abcHanabi[5]; // 花火変数を宣言する
char Str1[] = " 打ち上げ花火";
/**
* 機能 : 初期設定用(プログラムの実行で最初に1回呼ばれる)
* HWND hWind : ウィンドウのハンドル
* 戻り値 : なし
*/
void MsInit( HWND hWind )
{
MsWinReal( FALSE ); // gDCを仮想画面にする
// 花火に初期値を設定する
abcHanabi[0].xpos = 300; // 位置
abcHanabi[0].ypos = 150; // 位置
abcHanabi[0].radius = 100; // 半径
abcHanabi[0].color = RGB( 0, 0, 255);
// 花火に初期値を設定する
abcHanabi[1].xpos = 400; // 位置
abcHanabi[1].ypos = 200; // 位置
abcHanabi[1].radius = 100; // 半径
abcHanabi[1].color = RGB( 0,255 , 0);
// 花火に初期値を設定する
abcHanabi[2].xpos = 300; // 位置
abcHanabi[2].ypos = 300; // 位置
abcHanabi[2].radius = 100; // 半径
abcHanabi[2].color = RGB( 255,0 , 0);
// 花火に初期値を設定する
abcHanabi[3].xpos = 450; // 位置
abcHanabi[3].ypos = 150; // 位置
abcHanabi[3].radius = 100; // 半径
abcHanabi[3].color = RGB( 255,0 ,255);
// 花火に初期値を設定する
abcHanabi[4].xpos = 250; // 位置
abcHanabi[4].ypos = 350; // 位置
abcHanabi[4].radius = 100; // 半径
abcHanabi[4].color = RGB( 0,255 ,255 );
}
/**
* 機能: 1/100秒(10ms)ごとに実行される
* HWND hWind : ウィンドウのハンドル
* 戻り値 : なし
*/
void MsTimer( HWND hWind, UINT TimerID )
{
static int count = 0;
double dd, x0, y0;
int i;
//
MsClear( 0 ); // 仮想画面をクリアーする
for(i=0;i<5;i++)
{
// 花火を表示する
drawHanabi( gDC, abcHanabi[i] );
}
//
TextOut( gDC, 20, 10, Str1, (int)strlen(Str1) ); // 見出しを表示
MsShow(); // 実画面への表示
count++;
}
// WM_DESTROY(X)で起動される
void MsClose( HWND hWind )
{
// プログラムの後処理を記述する
}
/**
* 関数名: drawHanabi
* 機能 : 花火を(xpos,ypos)座標に描く
*/
void drawHanabi( HDC gDC, HANABI hanabi )
{
double x1, y1, x0, y0; // 左上隅と右下隅
double rr;
int i;
double nHdo;
for(i=0;i<=5;i++){
// === 描画のための準備 ===
HPEN hPen0 , hPen ; // ペンのハンドル
HBRUSH hBrush0 , hBrush ; // ブラシのハンドル
COLORREF Color ; // 色指定コード
//ans = 0;
//ans = 20 + MsRandom(200);
//nLeng = ans;
Color = hanabi.color; // 色を取り出す
hBrush = CreateSolidBrush( Color ); // ブラシを作成する。
hBrush0 = SelectObject( gDC , hBrush ); // ブラシをDCに持たせる
hPen = CreatePen( PS_SOLID , 0 , Color ); // ペンを作成する
hPen0 = SelectObject( gDC , hPen ); // ペンをDCに持たせる
//-------------------------------------------------------------------------------------------
nHdo=0;
rr = hanabi.radius; //花火の半径
// === 花火を描く ===
x0 = hanabi.xpos;
y0 = hanabi.ypos;
while( nHdo<360 )
{
x1 = hanabi.xpos+rr*cos(nHdo*(PAI/180.0));
y1 = hanabi.ypos+rr*sin(nHdo*(PAI/180.0));
MoveToEx(gDC,(int)(x0+0.5),(int)(y0+0.5),NULL);
LineTo(gDC,(int)(x1+0.5),(int)(y1+0.5));
nHdo += 10;
}
//----------------------------------------------------------------------------------------------------
SelectObject( gDC , hPen0 ) ; // 元のペンを持たせる
DeleteObject( hPen ); // ペンを消去する
SelectObject( gDC , hBrush0 ) ; // 元のブラシを持たせる
DeleteObject( hBrush ); // ブラシを消去する
}
// === 描画関係の後処理 ===
}
Re: 花火の始点が5つ連なってしまって上手くばらけさせて綺麗な花火が作れません。C言語のMsTimer型です。
Posted: 2011年1月07日(金) 01:13
by bitter_fox
直接の回答と関係ないですが、質問文のコードに質問者さんのお名前と思われるものが表示されてしまってますが、大丈夫でしょうか??
char str[]のところです。
Re: 花火の始点が5つ連なってしまって上手くばらけさせて綺麗な花火が作れません。C言語のMsTimer型です。
Posted: 2011年1月07日(金) 01:32
by wasabi.1
名前・・・。
投稿した後は名前の部分だけ消せないですよね?
消せるのであれば消していただくとありがたいです・・・。
Re: 花火の始点が5つ連なってしまって上手くばらけさせて綺麗な花火が作れません。C言語のMsTimer型です。
Posted: 2011年1月07日(金) 02:00
by kimuchi
ランダムな座標というのはxposやyposをランダムにしたいということでしょうか?
MsInit関数が何度でも呼べるのであれば、この中でランダムな値を設定し、
あとはcountを管理されているようなので、以下のような感じでどうでしょう?
コード:
void MsInit( HWND hWind )
{
MsWinReal( FALSE ); // gDCを仮想画面にする
// 花火に初期値を設定する
abcHanabi[0].xpos = ランダムで有効な値; // 位置
abcHanabi[0].ypos = ランダムで有効な値; // 位置
以下略
void MsTimer( HWND hWind, UINT TimerID )
{
static int count = 0;
double dd, x0, y0;
int i;
//
if(count%1000==999) //10秒ごとにリセット
{
MsClear( 0 ); // 仮想画面をクリアーする
MsInit( hWind ); //花火の情報をリセットする
}
以下略
MsInit関数が二回以上使えなくても代わりは立てられると思います。
当方プログラムの仕様をあまりよく知らないので、でたらめかもしれませんがお許し下さい。
Re: 花火の始点が5つ連なってしまって上手くばらけさせて綺麗な花火が作れません。C言語のMsTimer型です。
Posted: 2011年1月08日(土) 15:10
by wasabi
解決しました。
ありがとうございました。