[C++]クリックしたらボールが発生して自由落下
[C++]クリックしたらボールが発生して自由落下
C++言語でDxlibを用いて、クリックした場所にボールが発生して自由落下するプログラムを作りたいと考えています。
どなたか参考になるプログラムなど教えていただけないでしょうか?
初投稿ですが、よろしくお願いします。
どなたか参考になるプログラムなど教えていただけないでしょうか?
初投稿ですが、よろしくお願いします。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: [C++]クリックしたらボールが発生して自由落下
自分で作りたいということであるのなら、コードを貰う前にご自身で出来るだけ頑張らないと身につきません。
> クリックしたらボールが発生して自由落下
というモノであるなら。
1.クリックの処理が分かり、座標も取得できる。
2.ボールを任意の座標に表示できる
3.ボールを自由落下させる事が出来る
と3つの要件をクリアするだけです。
この内出来ない事はどれでしょうか?
> クリックしたらボールが発生して自由落下
というモノであるなら。
1.クリックの処理が分かり、座標も取得できる。
2.ボールを任意の座標に表示できる
3.ボールを自由落下させる事が出来る
と3つの要件をクリアするだけです。
この内出来ない事はどれでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: [C++]クリックしたらボールが発生して自由落下
この中でわからないのは、
1.クリックの処理が分かり、座標も取得できる。
です。
現状、クリックすると、ボールが出現するのですが、クリックを離すとボールが消えてしまいます。
また、画面上をクリック連打すると連打に応じて大量にボールが出現する処理というものがわかりません。
何か良い方法はないでしょうか?
1.クリックの処理が分かり、座標も取得できる。
です。
現状、クリックすると、ボールが出現するのですが、クリックを離すとボールが消えてしまいます。
また、画面上をクリック連打すると連打に応じて大量にボールが出現する処理というものがわかりません。
何か良い方法はないでしょうか?
- Hiragi(GKUTH)
- 記事: 167
- 登録日時: 14年前
- 住所: 大阪府
- 連絡を取る:
Re: [C++]クリックしたらボールが発生して自由落下
クリックされると、フラグが立って、フラグが立ったボールを処理する...
などといった方法が簡単だと思いますが。
取りあえず現状のソースコードを張ってみてください。
などといった方法が簡単だと思いますが。
取りあえず現状のソースコードを張ってみてください。
だいがくせい!
Re: [C++]クリックしたらボールが発生して自由落下
クリックされた時、そこの位置を初期位置としたボールのデータを線形リスト(std::list)に入れ、
各フレームでリスト内のデータを順に処理(速度と位置の計算、および描画)を行うのがいいと思います。
各フレームでリスト内のデータを順に処理(速度と位置の計算、および描画)を行うのがいいと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: [C++]クリックしたらボールが発生して自由落下
返信ありがとうございます。
現状のソースコードは以下のようになっています。
#include "DxLib.h"
#define g 9.8
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
int mx,my;//マウス座標
int Handle,Handle2; // 画像格納用ハンドル
Handle = LoadGraph( "ball.png" ); // ball画像のロード
Handle2= LoadGraph( "ground.png" );//地面画像のロード
double F,a;//力と加速度
//初期値
double y=0;//y座標
double v=0;//速度
double m=1.0;//質量
double r=25.0;//半径
double k=0.5;//ばね定数
double c=2.5;//粘性係数
double dt=0.1;//時間変化
// while( 裏画面を表画面に反映, メッセージ処理, 画面クリア )
while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0&&CheckHitKey(KEY_INPUT_ESCAPE) == 0 ){
//マウスの入力状態取得
GetMousePoint(&mx,&my);
if( ( GetMouseInput() & MOUSE_INPUT_LEFT ) != 0 ){//マウスをクリックしたら
F=m*g;//自由落下
//バウンド処理
if(y>450){
F=-m*g;
if(y>r){
F+=k*(r-y)-c*v;
}
}
a=F/m;//加速度
v+=a*dt;//加速度から速度
y+=v*dt;//速度から座標
DrawGraph( mx,y, Handle, TRUE ); //ball画像の描画
DrawGraph( 0, 470, Handle2, TRUE ); //地面画像の描画
}
}
DxLib_End(); // DXライブラリ終了処理
return 0;
}
このソースコードでは、クリックしたら1つのボールが自由落下して地面でバウンドして減衰していきます。
問題点は、
1.クリックを離すと、ボールが消える。
2.ボールを複数個に対応させたい。
この2点を考えています。
現状考えているのは、ballのクラスまたは構造体を作り、そこからクリックのカウントに応じて新しく配列からボールを呼び出そうと思っています。
何か、良いアイデアがあればご教示いただければ幸いです。
現状のソースコードは以下のようになっています。
#include "DxLib.h"
#define g 9.8
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
int mx,my;//マウス座標
int Handle,Handle2; // 画像格納用ハンドル
Handle = LoadGraph( "ball.png" ); // ball画像のロード
Handle2= LoadGraph( "ground.png" );//地面画像のロード
double F,a;//力と加速度
//初期値
double y=0;//y座標
double v=0;//速度
double m=1.0;//質量
double r=25.0;//半径
double k=0.5;//ばね定数
double c=2.5;//粘性係数
double dt=0.1;//時間変化
// while( 裏画面を表画面に反映, メッセージ処理, 画面クリア )
while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0&&CheckHitKey(KEY_INPUT_ESCAPE) == 0 ){
//マウスの入力状態取得
GetMousePoint(&mx,&my);
if( ( GetMouseInput() & MOUSE_INPUT_LEFT ) != 0 ){//マウスをクリックしたら
F=m*g;//自由落下
//バウンド処理
if(y>450){
F=-m*g;
if(y>r){
F+=k*(r-y)-c*v;
}
}
a=F/m;//加速度
v+=a*dt;//加速度から速度
y+=v*dt;//速度から座標
DrawGraph( mx,y, Handle, TRUE ); //ball画像の描画
DrawGraph( 0, 470, Handle2, TRUE ); //地面画像の描画
}
}
DxLib_End(); // DXライブラリ終了処理
return 0;
}
このソースコードでは、クリックしたら1つのボールが自由落下して地面でバウンドして減衰していきます。
問題点は、
1.クリックを離すと、ボールが消える。
2.ボールを複数個に対応させたい。
この2点を考えています。
現状考えているのは、ballのクラスまたは構造体を作り、そこからクリックのカウントに応じて新しく配列からボールを呼び出そうと思っています。
何か、良いアイデアがあればご教示いただければ幸いです。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: [C++]クリックしたらボールが発生して自由落下
コードタグをご利用くださいね。
使うとこんなふうに表示されます。
ついでにインデントを整理すると更に見やすいです。
さて、現状の問題はですがインデントを直した版をみてもらうと分かりやすいですがマウスクリックしたらのif文に落下処理が内包されてますよね?
内包しているということはif文が真の間しか実行されてないと言うことです。
つまり、マウスをクリックしていないと落下しないし表示もされないようにご自身で書いてしまっているわけですね。
これを思った通りしたいとしたら、マウスをクリックしたことを何かの変数に覚えておいて、その変数がクリック後の値に成っていたら表示するというふうにすれば良いんじゃないでしょうか。
>現状考えているのは、ballのクラスまたは構造体を作り、そこからクリックのカウントに応じて新しく配列からボールを呼び出そうと思っています。
>何か、良いアイデアがあればご教示いただければ幸いです。
これについては、みけCAT さんがすでに提案してくれていますね。
使うとこんなふうに表示されます。
#include "DxLib.h"
#define g 9.8
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
int mx,my;//マウス座標
int Handle,Handle2; // 画像格納用ハンドル
Handle = LoadGraph( "ball.png" ); // ball画像のロード
Handle2= LoadGraph( "ground.png" );//地面画像のロード
double F,a;//力と加速度
//初期値
double y=0;//y座標
double v=0;//速度
double m=1.0;//質量
double r=25.0;//半径
double k=0.5;//ばね定数
double c=2.5;//粘性係数
double dt=0.1;//時間変化
// while( 裏画面を表画面に反映, メッセージ処理, 画面クリア )
while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0&&CheckHitKey(KEY_INPUT_ESCAPE) == 0 ){
//マウスの入力状態取得
GetMousePoint(&mx,&my);
if( ( GetMouseInput() & MOUSE_INPUT_LEFT ) != 0 ){//マウスをクリックしたら
F=m*g;//自由落下
//バウンド処理
if(y>450){
F=-m*g;
if(y>r){
F+=k*(r-y)-c*v;
}
}
a=F/m;//加速度
v+=a*dt;//加速度から速度
y+=v*dt;//速度から座標
DrawGraph( mx,y, Handle, TRUE ); //ball画像の描画
DrawGraph( 0, 470, Handle2, TRUE ); //地面画像の描画
}
}
DxLib_End(); // DXライブラリ終了処理
return 0;
}
#include "DxLib.h"
#define g 9.8
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) {
ChangeWindowMode( TRUE ), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
int mx, my; //マウス座標
int Handle, Handle2; // 画像格納用ハンドル
Handle = LoadGraph( "ball.png" ); // ball画像のロード
Handle2 = LoadGraph( "ground.png" ); //地面画像のロード
double F, a; //力と加速度
//初期値
double y = 0; //y座標
double v = 0; //速度
double m = 1.0; //質量
double r = 25.0; //半径
double k = 0.5; //ばね定数
double c = 2.5; //粘性係数
double dt = 0.1; //時間変化
// while( 裏画面を表画面に反映, メッセージ処理, 画面クリア )
while( ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) {
//マウスの入力状態取得
GetMousePoint( &mx, &my );
if( ( GetMouseInput() & MOUSE_INPUT_LEFT ) != 0 ) { //マウスをクリックしたら
F = m * g; //自由落下
//バウンド処理
if( y > 450 ) {
F = -m * g;
if( y > r ) {
F += k * ( r - y ) - c * v;
}
}
a = F / m; //加速度
v += a * dt; //加速度から速度
y += v * dt; //速度から座標
DrawGraph( mx, y, Handle, TRUE ); //ball画像の描画
DrawGraph( 0, 470, Handle2, TRUE ); //地面画像の描画
}
}
DxLib_End(); // DXライブラリ終了処理
return 0;
}
内包しているということはif文が真の間しか実行されてないと言うことです。
つまり、マウスをクリックしていないと落下しないし表示もされないようにご自身で書いてしまっているわけですね。
これを思った通りしたいとしたら、マウスをクリックしたことを何かの変数に覚えておいて、その変数がクリック後の値に成っていたら表示するというふうにすれば良いんじゃないでしょうか。
>現状考えているのは、ballのクラスまたは構造体を作り、そこからクリックのカウントに応じて新しく配列からボールを呼び出そうと思っています。
>何か、良いアイデアがあればご教示いただければ幸いです。
これについては、みけCAT さんがすでに提案してくれていますね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: [C++]クリックしたらボールが発生して自由落下
softyaさんのアドバイスを元に、ソースコードを以下のように変えてみたら、クリックしたあともボールは描画されるようになりました。
ありがとうございます。
次は、みけCATさんのアドバイスを参考にボールを複数個呼び出せるように改良していきたいと思います。
ありがとうございます。
#include "DxLib.h"
#define g 9.8
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) {
ChangeWindowMode( TRUE ), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
int mx, my; //マウス座標
int Handle, Handle2; // 画像格納用ハンドル
Handle = LoadGraph( "ball.png" ); // ball画像のロード
Handle2 = LoadGraph( "ground.png" ); //地面画像のロード
double F, a; //力と加速度
//初期値
int count=0;
double y = 0; //y座標
double v = 0; //速度
double m = 1.0; //質量
double r = 25.0; //半径
double k = 0.5; //ばね定数
double c = 2.5; //粘性係数
double dt = 0.1; //時間変化
// while( 裏画面を表画面に反映, メッセージ処理, 画面クリア )
while( ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) {
//マウスの入力状態取得
GetMousePoint( &mx, &my );
if( ( GetMouseInput() & MOUSE_INPUT_LEFT ) != 0 ) { //マウスをクリックしたら
count=1;
}
if(count==1){
F = m * g; //自由落下
//バウンド処理
if( y > 450 ) {
F = -m * g;
if( y > r ) {
F += k * ( r - y ) - c * v;
}
}
a = F / m; //加速度
v += a * dt; //加速度から速度
y += v * dt; //速度から座標
DrawGraph( mx, y, Handle, TRUE ); //ball画像の描画
DrawGraph( 0, 470, Handle2, TRUE ); //地面画像の描画
}
}
DxLib_End(); // DXライブラリ終了処理
return 0;
}
Re: [C++]クリックしたらボールが発生して自由落下
現在、ballの構造体を作り、そこに座標などの情報を格納しました。
そして、配列を作り、ball[10]の中から、42行目のfor文で、
クリックしたら一つ目のボール:ball[0]を呼び出して、
次にクリックすると、二つ目のボール:ball[1]が呼び出されるように
クリックするたびにボールを最大10個発生させたいのですが、
現状、ボールが一個しか発生しなくて困ってます。
修正すべき部分を教えていただければ幸いです。
コードは以下のようになっています。
よろしくお願いします。
そして、配列を作り、ball[10]の中から、42行目のfor文で、
クリックしたら一つ目のボール:ball[0]を呼び出して、
次にクリックすると、二つ目のボール:ball[1]が呼び出されるように
クリックするたびにボールを最大10個発生させたいのですが、
現状、ボールが一個しか発生しなくて困ってます。
修正すべき部分を教えていただければ幸いです。
コードは以下のようになっています。
#include "DxLib.h"
#define g 9.8
const int MAXN=10;
int ball[MAXN];
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) {
ChangeWindowMode( TRUE ), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
int mx,my; //マウス座標
int Handle, Handle2; // 画像格納用ハンドル
Handle = LoadGraph( "ball.png" ); // ball画像のロード
Handle2 = LoadGraph( "ground.png" ); //地面画像のロード
double F, a; //力と加速度
//マウスの入力状態取得
GetMousePoint( &mx, &my );
//初期値
int count=0;
struct Ball{
double x ; //x座標
double y ; //y座標
double v ; //速度
double m ; //質量
double r ; //半径
double k ; //ばね定数
double c ; //粘性係数
double dt; //時間変化
}ball[MAXN];
for(int i=0;i<10;i++){
ball[i].x=mx;
ball[i].y=my;
ball[i].v=0;
ball[i].m=1.0;
ball[i].r=25.0;
ball[i].k=0.5;
ball[i].c=2.5;
ball[i].dt=0.1;
}
// while( 裏画面を表画面に反映, メッセージ処理, 画面クリア )
while( ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) {
for(int i=0;i<10;i++){
if( ( GetMouseInput() & MOUSE_INPUT_LEFT ) != 0 ) { //マウスをクリックしたら
count=1;
}
if(count==1){
F = ball[i].m * g; //自由落下
//バウンド処理
if( ball[i].y > 450 ) {
F = -ball[i].m * g;
if( ball[i].y > ball[i].r ) {
F += ball[i].k * ( ball[i].r -ball[i]. y ) - ball[i].c *ball[i]. v;
}
}
a = F / ball[i].m; //加速度
ball[i].v += a * ball[i].dt; //加速度から速度
ball[i].y += ball[i].v * ball[i].dt; //速度から座標
DrawGraph( ball[i].x, ball[i].y, Handle, TRUE ); //ball画像の描画
}
DrawGraph( 0, 470, Handle2, TRUE ); //地面画像の描画
}
}
DxLib_End(); // DXライブラリ終了処理
return 0;
}
Re: [C++]クリックしたらボールが発生して自由落下
まず落ち着いて どういう手順で何をすればいいのか を整理できてからコーディングした方が良いように見受けます.
いろいろと混乱していませんか?
(例えば,countという変数は何なのか(何を表しているのか)具体的に説明できますか?)
とりあえず,各フレームにおいてやること:「最初にAをして,次にBをして…」という手順を書きだす等してみてはいかがでしょう.
で,各々の要素AやBは具体的にはどうやって実現していくのか,
例えば処理Aというのは細かく見ると,「処理aをして,次に変数bの状態を判定して bがxxxだったら処理c,そうでなければ処理d を行うのだ」
という風により具体的に分解……→最終的に全ての箇所がコードで書ける単位にまで.
(その過程で 「処理aというのが必要だと思うが,どうやって実現すればいいのかわからん」
とかいうことがあれば,それを質問するとか.)
[hr]
[追記]
上記だけでは何なので,気になる点をいくつか書いておきます.
・「マウスをクリックしたら」という判定は各フレームで1回だけやればよいのでは?
・クリック時に「さっき[2]番目の玉を発生させたから今回は[3]番目だな」みたいなことを決めるための処理が存在していない
・玉の運動処理や描画処理は,現在存在する玉についてのみ行えば良いと思うが,玉が存在しているのか?という判定処理が見当たらない.
いろいろと混乱していませんか?
(例えば,countという変数は何なのか(何を表しているのか)具体的に説明できますか?)
とりあえず,各フレームにおいてやること:「最初にAをして,次にBをして…」という手順を書きだす等してみてはいかがでしょう.
で,各々の要素AやBは具体的にはどうやって実現していくのか,
例えば処理Aというのは細かく見ると,「処理aをして,次に変数bの状態を判定して bがxxxだったら処理c,そうでなければ処理d を行うのだ」
という風により具体的に分解……→最終的に全ての箇所がコードで書ける単位にまで.
(その過程で 「処理aというのが必要だと思うが,どうやって実現すればいいのかわからん」
とかいうことがあれば,それを質問するとか.)
[hr]
[追記]
上記だけでは何なので,気になる点をいくつか書いておきます.
・「マウスをクリックしたら」という判定は各フレームで1回だけやればよいのでは?
・クリック時に「さっき[2]番目の玉を発生させたから今回は[3]番目だな」みたいなことを決めるための処理が存在していない
・玉の運動処理や描画処理は,現在存在する玉についてのみ行えば良いと思うが,玉が存在しているのか?という判定処理が見当たらない.
Re: [C++]クリックしたらボールが発生して自由落下
皆さんのアドバイスとこちらのサイト
http://takabosoft.com/19991219151646.html
を参考にコードを修正しましたが、思うとおりにいきません。
現在クリックすると、ボールがつながって表示されてしまいます。
どこが原因で、どのように修正すべきか教えていただければ幸いです。
http://takabosoft.com/19991219151646.html
を参考にコードを修正しましたが、思うとおりにいきません。
現在クリックすると、ボールがつながって表示されてしまいます。
どこが原因で、どのように修正すべきか教えていただければ幸いです。
#include <windows.h>
#include "DxLib.h"
#define g 9.8
#define BMAX 10
int mx,my; //マウス座標
int click =0;
//初期値
float F, a; //力と加速度
struct Ball{
BOOL enable; //使用:1 未使用:0
float x ; //x座標
float y ; //y座標
float v ; //速度
float m ; //質量
float r ; //半径
float k ; //ばね定数
float c ; //粘性係数
float dt; //時間変化
}ball[BMAX];
void InitGame(){
int Handle2 = LoadGraph( "ground.png" ); //地面画像の
DrawGraph( 0, 470, Handle2, TRUE ); //地面画像の描画
//弾データ初期化
for(int i=0;i<BMAX;i++)
ball[i].enable=0;
}
void Createball(float x,float y){
int i;
int no=-1; //作成する弾のデータ番号
//構造体の中で、空いている(未使用)データを探す
for(i=0;i<BMAX;i++)
if(ball[i].enable==0){
no=i;
break;
}
//空いているデータが見つからなかったら作成せずに戻る
if(no==-1)
return;
//データ詰める
ball[no].x=x;
ball[no].y=y;
ball[no].enable=1; //使用中にする
}
void Shoot(){
//ボール発射判定
if( ( GetMouseInput() & MOUSE_INPUT_LEFT ) != 0 )//マウスをクリックしたら
click=1;
if(click==1)
Createball(mx,my);
}
void MoveBall(){
int i;
for(i=0;i<BMAX;i++){
if(ball[i].enable==0) //未使用データだったら次の処理へ
continue;
//移動
F = ball[i].m * g; //自由落下
//バウンド処理
if( ball[i].y > 450 ) {
F = -ball[i].m * g;
if( ball[i].y > ball[i].r ) {
F += ball[i].k * ( ball[i].r -ball[i]. y ) - ball[i].c *ball[i]. v;
}
}
a = F / ball[i].m; //加速度
ball[i].v += a * ball[i].dt; //加速度から速度
ball[i].y += ball[i].v * ball[i].dt; //速度から座標
}
}
void Show(){
int i;
int Handle = LoadGraph( "ball.png" ); // ball画像のロード
//ボール表示
for(i=0;i<BMAX;i++)
if(ball[i].enable==1)
DrawGraph( ball[i].x, ball[i].y, Handle, TRUE ); //ball画像の描画
}
//----------[ メインループ ]--------------------------------------------------------------------
void GameLoop(void){
for(int i=0;i<BMAX;i++){
Shoot(); //弾発射判定
MoveBall(); //弾移動
Show(); //画像表示
}
}
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) {
ChangeWindowMode( TRUE ), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
//マウスの入力状態取得
GetMousePoint( &mx, &my );
//初期値
int i;
for(i=0;i<BMAX;i++){
ball[i].x=mx;
ball[i].y=my;
ball[i].v=0;
ball[i].m=1.0;
ball[i].r=25.0;
ball[i].k=0.5;
ball[i].c=2.5;
ball[i].dt=0.1;
}
// while( 裏画面を表画面に反映, メッセージ処理, 画面クリア )
while( ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) {
InitGame();
GameLoop();
}
DxLib_End(); // DXライブラリ終了処理
return 0;
}
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: [C++]クリックしたらボールが発生して自由落下
こちらと
http://takabosoft.com/19991219151646.html
このサイトのゲームプログラミングの館のある章の
http://dixq.net/g/02_09.html
は、ある程度似たことしているのですがお気づきですか?
その部分が全く反映されていないので起きている問題です。
【補足】 よく考えたら、慣れていない人には似ても似つかない処理に見えるかもしれないので、ゲームプログラミングの館の方を参考にして下さい。
それとLoadGraph( "ball.png" )を毎フレームやるとメモリリークで落ちますよ。
正確に言うとDXライブラリの画像ハンドルを使い過ぎでDXライブラリが異常終了します。
http://takabosoft.com/19991219151646.html
このサイトのゲームプログラミングの館のある章の
http://dixq.net/g/02_09.html
は、ある程度似たことしているのですがお気づきですか?
その部分が全く反映されていないので起きている問題です。
【補足】 よく考えたら、慣れていない人には似ても似つかない処理に見えるかもしれないので、ゲームプログラミングの館の方を参考にして下さい。
それとLoadGraph( "ball.png" )を毎フレームやるとメモリリークで落ちますよ。
正確に言うとDXライブラリの画像ハンドルを使い過ぎでDXライブラリが異常終了します。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
- Hiragi(GKUTH)
- 記事: 167
- 登録日時: 14年前
- 住所: 大阪府
- 連絡を取る:
Re: [C++]クリックしたらボールが発生して自由落下
このままだとクリックしている間はずっとボールが放出され続けてしまいます、クリックされた瞬間だけ、ボールを追加する必要があります。
加えてマウスの座標はメインループ外で取得しているので、プログラム起動時の位置しか取得できないのでは?(間違っていたらすいません。)
特にsoftyaさんも仰っていますが、毎フレーム ロード->描画を繰り返すのは良くないと思います。Show関数も同じように画像のロード部分はメインループ外でするべきです。
加えてマウスの座標はメインループ外で取得しているので、プログラム起動時の位置しか取得できないのでは?(間違っていたらすいません。)
特にsoftyaさんも仰っていますが、毎フレーム ロード->描画を繰り返すのは良くないと思います。Show関数も同じように画像のロード部分はメインループ外でするべきです。
だいがくせい!
Re: [C++]クリックしたらボールが発生して自由落下
丁寧なご回答ありがとうございます。
言われた点を意識して、ソースコードを修正してみました。
以下が現在のコードです。
現在、このソースコードで実行すると、一回クリックしたら、ボールが1個発生し、2回目クリックするともう一つのボールが発生するのですが、3回目クリックすると、2回目のボールが消えて新しいボールに更新されてしまいます。2個目以降もボールが画面上に残り続け、ボールがどんどん画面上に発生するためには、どの部分を直せば良いでしょうか?
よろしければ教えていただけると嬉しいです。
言われた点を意識して、ソースコードを修正してみました。
以下が現在のコードです。
#include <windows.h>
#include "DxLib.h"
#include<math.h>
#define g 9.8
#define BMAX 10
//----------[ ボール構造体 ]----------------------------------------
struct Ball{
BOOL enable; //使用:1 未使用:0
float x ; //x座標
float y ; //y座標
float v ; //速度
float m ; //質量
float r ; //半径
float k ; //ばね定数
float c ; //粘性係数
float dt; //時間変化
}ball[BMAX];
//----------[ ゲーム初期化 ]----------------------------------------
void InitGame(){
int Handle2 = LoadGraph( "ground.png" ); //地面画像の
DrawGraph( 0, 420, Handle2, TRUE ); //地面画像の描画
//弾データ初期化
for(int i=0;i<BMAX;i++)
ball[i].enable=0;
}
//----------[ ボール作成 ]----------------------------------------------
void Createball(float x,float y){
int i;
int no=-1; //作成する弾のデータ番号
//構造体の中で、空いている(未使用)データを探す
for(i=0;i<BMAX;i++)
if(ball[i].enable==0){
no=i;
break;
}
//空いているデータが見つからなかったら作成せずに戻る
if(no==-1)
return;
//データ詰める
ball[no].x=x;
ball[no].y=y;
ball[no].enable=1; //使用中にする
}
//----------[ メイン関数 ]----------------------------------------------
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) {
ChangeWindowMode( TRUE ), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
int mx,my; //マウス座標
int Handle;// 画像格納用ハンドル
Handle = LoadGraph( "ball.png" ); // ball画像のロード
float F, a; //力と加速度
//初期値
int clickcount=0;//クリック初期化
int beforeMouseInput = 0;//1フレーム前のマウスの状態
//マウスの初期化
GetMousePoint( &mx, &my );
for(int i=0;i<BMAX;i++){
ball[i].x=mx;
ball[i].y=my;
ball[i].v=0;
ball[i].m=1.0;
ball[i].r=25.0;
ball[i].k=1.0;
ball[i].c=3.5;
ball[i].dt=0.1;
}
// while( 裏画面を表画面に反映, メッセージ処理, 画面クリア )
while( ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) {
//マウスの入力状態更新
GetMousePoint( &mx, &my );
InitGame();
for(int i=0;i<BMAX;i++){
//クリックした瞬間
if( (beforeMouseInput & MOUSE_INPUT_LEFT ) != MOUSE_INPUT_LEFT
&& (GetMouseInput() & MOUSE_INPUT_LEFT)== MOUSE_INPUT_LEFT){
clickcount=1;
Createball(mx,my);
}
beforeMouseInput = GetMouseInput();
if(ball[i].enable==0&&clickcount==1){
F = ball[i].m * g; //自由落下
//バウンド処理
if( ball[i].y > 380 ) {
F = -ball[i].m * g;
if( abs(ball[i].y-380) < ball[i].r ) {
F += ball[i].k * ( ball[i].r -ball[i]. y ) - ball[i].c *ball[i]. v;
}
}
a = F / ball[i].m; //加速度
ball[i].v += a * ball[i].dt; //加速度から速度
ball[i].y += ball[i].v * ball[i].dt; //速度から座標
DrawGraph( ball[i].x, ball[i].y, Handle, TRUE ); //ball画像の描画
}
}
}
DxLib_End(); // DXライブラリ終了処理
return 0;
}
現在、このソースコードで実行すると、一回クリックしたら、ボールが1個発生し、2回目クリックするともう一つのボールが発生するのですが、3回目クリックすると、2回目のボールが消えて新しいボールに更新されてしまいます。2個目以降もボールが画面上に残り続け、ボールがどんどん画面上に発生するためには、どの部分を直せば良いでしょうか?
よろしければ教えていただけると嬉しいです。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: [C++]クリックしたらボールが発生して自由落下
ここの部分に違和感を感じます.
> if(ball.enable==0&&clickcount==1){
問題をねじ伏せるために、このコードを書いていませんか?
そもそもの別の間違いが無ければ、こうはならないはずです。
あとクリックの処理を for(int i=0;i<BMAX;i++){のループに入れる理由はないはずです。
> if(ball.enable==0&&clickcount==1){
問題をねじ伏せるために、このコードを書いていませんか?
そもそもの別の間違いが無ければ、こうはならないはずです。
あとクリックの処理を for(int i=0;i<BMAX;i++){のループに入れる理由はないはずです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: [C++]クリックしたらボールが発生して自由落下
よく直ったつもりで、直っていないことがありますので最終コードを投稿することをオススメします。たらお さんが書きました:皆さんのアドバイスを参考にしたら、完成できました。
ありがとうございます。
あと、他の人に参考になるように投稿して頂くと掲示板としても助かります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: [C++]クリックしたらボールが発生して自由落下
/----------[インクルードファイル ]----------------------------------------
#include "DxLib.h"
//----------[マクロ定義部 ]----------------------------------------
#define g 9.8//重力加速度
#define BMAX 100 //ボールの最大出現数を100個に
#define X_MAX 640//画面の最大横幅
//----------[ グローバル変数 ]----------------------------------------
int Handle,Handle2,Handle3,Handle4,Handle5;//画像格納用ハンドル
int clickcount;//クリック格納変数
int beforeMouseInput;//1フレーム前のマウスの状態
int mx,my; //マウス座標
double F, a; //力と加速度
//----------[ ボール構造体 ]----------------------------------------
struct Ball{
int flag;//1:使用 0:消去
double x ; //x座標
double y ; //y座標
double v ; //速度
double m ; //質量
double r ; //半径
double k ; //ばね定数
double c ; //粘性係数
double dt; //時間変化
}ball[BMAX];
//----------[ 音声・画像ファイルロード ]----------------------------------------
void File_load(){
Handle= LoadGraph( "tumball.png" ); // ball画像のロード
Handle2 = LoadGraph( "tumball3.png" ); //ball2画像のロード
Handle3 = LoadGraph( "ground4.jpg" ); //地面画像のロード
Handle4=LoadGraph( "background5.jpg" ); //背景画像のロード
Handle5= LoadSoundMem( "se1.mp3" );//効果音のロード
}
//----------[ 初期値 ]----------------------------------------
void Ini_Game(){
clickcount=0;//クリック初期化
beforeMouseInput = 0;//1フレーム前のマウスの状態
}
//----------[ 背景描画 ]----------------------------------------
void BackGround(){
DrawGraph( 0, 0, Handle4, TRUE ); //背景画像の描画
}
//----------[ 地面描画 ]----------------------------------------
void DrawGround(){
DrawGraph( 0, 420, Handle3, TRUE ); //地面画像の描画
for(int i=0;i<BMAX;i++){
//ボールが当たったら地面振動
if(ball[i].flag==1&& ball[i].y+ball[i].r > 395)
DrawGraph( 10, 420, Handle3, TRUE ); //x軸に10ピクセルずらして地面画像の描画
}
}
//----------[ ボール作成 ]----------------------------------------------
void Createball(double x,double y){
//構造体の中で、空いている(未使用)データを探す
for(int i=clickcount;i<BMAX;i++){
//データ詰める
ball[i].x=x;
ball[i].y=y;
ball[i].v=0;
ball[i].m=1.0;
ball[i].r=25.0;
ball[i].k=0.5;
ball[i].c=2.5;
ball[i].dt=0.1;
ball[i].flag=1;//使用にする
}
}
//----------[ ボール発射判定 ]----------------------------------------------
void Shot_Hantei(){
//クリックした瞬間
if( (beforeMouseInput & MOUSE_INPUT_LEFT ) != MOUSE_INPUT_LEFT
&& (GetMouseInput() & MOUSE_INPUT_LEFT)== MOUSE_INPUT_LEFT){
clickcount+=1;//クリックカウント増やす
Createball(mx,my);//マウスの座標にボール作成
PlaySoundMem(Handle5,DX_PLAYTYPE_NORMAL);//ボール出現音再生
}
beforeMouseInput = GetMouseInput();
}
//----------[ ボール移動 ]----------------------------------------------
void Moveball(){
for(int i=0;i<BMAX;i++){
if(ball[i].flag==1&&clickcount>=1){//ボールが使用中なら
F = ball[i].m * g; //自由落下
//バウンド処理
if( ball[i].y+ball[i].r > 395 ) {//地面に当たったら
F = -ball[i].m * g;//バウンドさせる。
//沈み込み量に応じてバウンド減衰
if( ball[i].y-370 < ball[i].r ) {
F += ball[i].k * ( ball[i].r -ball[i]. y) - ball[i].c *ball[i]. v;
}
}
a = F / ball[i].m; //加速度
ball[i].v += a * ball[i].dt; //加速度から速度
ball[i].y += ball[i].v * ball[i].dt; //速度から座標
ball[i].x +=2; //x座標方向への移動
//画面外に出たらボール消去
if(ball[i].x<0 || X_MAX<ball[i].x)
ball[i].flag=0;//消去する
}
}
}
//----------[ ボール描画 ]----------------------------------------------
void Drawball(){
for(int i=0;i<BMAX;i++){
if(ball[i].flag==1&&clickcount>=1){//ボールが使用中なら
DrawGraph( ball[i].x, ball[i].y, Handle, TRUE); //ball1画像の描画
if( ball[i].y+ball[i].r > 395 )//地面に当たったらボール変形
DrawGraph( ball[i].x, ball[i].y, Handle2, TRUE ); //ball2画像の描画
}
}
}
//----------[ メイン関数 ]----------------------------------------------
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) {
ChangeWindowMode( TRUE ), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
File_load();//画像ロード
Ini_Game();//初期値
//----------[ メインループ ]----------------------------------------------
// while( 裏画面を表画面に反映, メッセージ処理, 画面クリア,ESCAPEで終了 )
while( ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) {
GetMousePoint( &mx, &my );//マウスの入力状態更新
BackGround();//背景描画
DrawGround();//地面描画
Shot_Hantei();//ボール発射判定
Moveball();//ボール移動
Drawball();//ボール描画
}
DxLib_End(); // DXライブラリ終了処理
return 0;
}
最終コードです。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: [C++]クリックしたらボールが発生して自由落下
ありがとうございます。
一点気になる点が。ボールと地面でバウンド時にバウンド前の描画も同時に行われてますが意図通りなのでしょうか?
つまり、2つの状態(バウンド前と後)の画像が重ね書きされています。画像がないので正しいかどうかは、こちらでは判断不能でした。
一点気になる点が。ボールと地面でバウンド時にバウンド前の描画も同時に行われてますが意図通りなのでしょうか?
つまり、2つの状態(バウンド前と後)の画像が重ね書きされています。画像がないので正しいかどうかは、こちらでは判断不能でした。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。