|
Name: フォントの表示 ..ぴよぴよ(269ポイント)
Date: 2010/09/02(木) 00:16
No:60846
|
|
Title: フォント
|
|
いつもこの掲示板にお世話になっております。
現在ゲームの作成を行っているのですがフォントについて調べてもわからない事があったので質問いたします。
フォントの種類を下記のように指定しました。
CreateFontToHandle( "HGPゴシックE" , 64 , 2 , DX_FONTTYPE_ANTIALIASING_EDGE);
今回自分は"HGPゴシックE"以外のフォントを使用したかったのでインターネットからダウンロードしたのですが
そのダウンロードしたフォントはプログラムで使用できるのでしょうか。
またできる場合はどのように使用すればいいのか教えてください。お願い致します。
269ポイント を手に入れた。
|
|
|
|
Name: フォントの表示 ..ぴよぴよ(431ポイント)
Date: 2010/09/02(木) 22:20
No:60875
|
|
Title: Re:フォント
|
|
返信していただき、ありがとうございます。
一番上のサイトで解決できました。DXライブラリを検索ワードに入れないでフォントについてばかり調べていたので検索に引っかからなかったみたいです。
本当にありがとうございました。
2倍のポイントを手に入れた! 162ポイント を手に入れた。
|
|
|
|
Name: Wize ..かけだし(2,103ポイント)
Date: 2010/09/02(木) 03:27
No:60850
|
|
Title: 当たり判定がうまく出ません
|
|
初めて質問させて頂きます。画面の左右からキャラを発射して、接触時に文字を表示させようとしています。
現段階では文字は表示されません。
どこがまずいのか、どなたか教えて頂けないでしょうか?
[1] 質問文
[1.1] 自分が今行いたい事は何か
動かしている二つのキャラが接触したかを判定させたい。二つのキャラはY軸においては同じです。
[1.2] どのように取り組んだか(プログラムコードがある場合記載)
プログラムコードは以下の通りです。大本はこのサイトのゲーム基本編26のコードを改編したものです。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
//対戦型風の表現
#include "DxLib.h"
struct shot{
int x1,y1,t_x1,t_y1;
int flag1,t_flag1;
};
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
ChangeWindowMode( TRUE ) ; // ウインドウモードに変更
if( DxLib_Init() == -1 ) return -1; //DXライブラリ初期化 エラーが起きたら終了
int image[16],i1,t1,counter=0; //counter=発射してからのカウントをする変数。
char Key[256];
struct shot tama[20]; //tamaを20個作る。
struct shot teki[20]; //tekiを20体作る。
for(i1=0;i1<20;i1++){ //初期化処理
tama[i1].x1=600; tama[i1].y1=480/4; //座標代入
tama[i1].flag1=0; //飛んでいない事を示すフラグ=0
}
for(t1=0;t1<20;t1++){ //初期化処理
teki[t1].t_x1=10; teki[t1].t_y1=480/4; //座標代入
teki[t1].t_flag1=0; //飛んでいない事を示すフラグ=0
}
SetDrawScreen( DX_SCREEN_BACK ) ;//描画先を裏画面に設定
LoadDivGraph( "char.png" , 16 , 4 , 4 , 32 , 32 , image ) ;//画像を分割してimage配列に保存
int beak = LoadGraph("haikei.png");
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
while(1){
ClearDrawScreen(); //裏画面のデータを全て削除
DrawGraph(0,0,beak,TRUE);
GetHitKeyStateAll( Key ) ; // すべてのキーの状態を得る
if( ProcessMessage() == -1 ) break ; //異常がおきたら終了
if(counter<5) //前にエンターを押してから5カウント未満なら
counter++; //カウントアップ
else if( Key[ KEY_INPUT_P ] == 1 ){//5カウント以上たっていたら
counter=0; //カウンターを戻す
for(i1=0;i1<20;i1++){
if(tama[i1].flag1==0){ //発射していない玉を探し、
tama[i1].flag1=1; //発射フラグを立てる
break;
} } }
else if( Key[ KEY_INPUT_Q ] == 1 ){//5カウント以上たっていたら
counter=0; //カウンターを戻す
for(t1=0;t1<20;t1++){
if(teki[t1].t_flag1==0){ //発射していない玉を探し、
teki[t1].t_flag1=1; //発射フラグを立てる
break;
} } }
for(i1=0;i1<10;i1++){
if(tama[i1].flag1==1){ //発射している玉なら
tama[i1].x1-=1; //座標を1減らす
DrawGraph( tama[i1].x1 , tama[i1].y1 , image[4] , TRUE );//玉を描画
if(tama[i1].x1 < -32){ //もし画面外まで来たら
tama[i1].x1=640; //初期値に戻し、
tama[i1].flag1=0; //発射フラグを戻す
} } }
for(t1=0;t1<10;t1++){
if(teki[t1].t_flag1==1){ //発射している玉なら
teki[t1].t_x1+=1; //座標を1増やす
DrawGraph( teki[t1].t_x1 , teki[t1].t_y1 , image[12] , TRUE );//敵を描画
if(teki[t1].t_x1 > 671){ //もし画面外まで来たら
teki[t1].t_x1=0; //初期値に戻し、
teki[t1].t_flag1=0; //発射フラグを戻す
} } }
/* こっちの括りが、私が書いた当たり判定文です。うまくいかず第二案へ */
// if( tama[i1].flag1 ==1 && teki[t1].flag1 ==1 )
// if( teki[t1].t_flag1 == 1 )
// if( tama[i1].flag1 == 1)
// if( teki[t1].t_x1 == tama[i1].x1 )
// printfDx("骨");
/* 他のサイトを参考に書いた第2案です */
if( ( tama[i1].x1 < teki[t1].t_x1 + 32 ) &&
( tama[i1].x1 + 32 > teki[t1].t_x1 ) ){
printfDx("魚");
}
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
[1.3] どのようなエラーやトラブルで困っているか(エラーメッセージが解る場合は記載)
キャラがぶつかっても当たり判定メッセージが出ない。
[1.4] 今何がわからないのか、知りたいのか
当たり判定をどう記述したらいいかわからない。
[2] 環境
[2.1] OS : XPです。
[2.2] コンパイラ名 : Microsoft Visual Studio 2008
[3] その他
・どの程度C言語を理解しているか
初心者です。このサイトで勉強してる程度。
・ライブラリを使っている場合は何を使っているか
DXライブラリを使用しています。 
2,103ポイント を手に入れた。
|
|
|
|
Name: めるぽん ..上級者(19,052ポイント)
Date: 2010/09/02(木) 21:54
No:60872
|
|
Title: Re:当たり判定がうまく出ません
|
|
tama や teki は 20個ずつあるので、tama[i1] と teki[t1] だけの当たり判定をしてもダメですね。
tama[0] と teki[0]
tama[0] と teki[1]
...
tama[0] と teki[19]
tama[1] と teki[0]
tama[1] と teki[1]
...
tama[1] と teki[19]
tama[2] と teki[0]
...
...
tama[19] と teki[19]
と、それぞれが当たっていないかをチェックします。当然まだ使われていないデータもあるので、flag1 や t_flag1 もチェックする必要がありそうです。
for (i1 = 0; i1 < 20; i1++)
{
if (tama[i1].flag1 == 0) continue;
for (t1 = 0; t1 < 20; t1++)
{
if (teki[t1].t_flag1 == 0) continue;
if( ( tama[i1].x1 < teki[t1].t_x1 + 32 ) &&
( tama[i1].x1 + 32 > teki[t1].t_x1 ) ){
printfDx("魚");
}
}
という感じではないでしょうか。
あと、これ以降は全部当たり判定とは関係無いことなんですが、
for(i1=0;i1<10;i1++){
...
for(t1=0;t1<10;t1++){
ここら辺、10 ではなくて 20 じゃないでしょうか。こういうのは定数でやっておいた方が分かりやすくなりますし、間違いも少なくなります。
const int TAMA_NUM = 20;
const int TEKI_NUM = 20;
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow )
{
...
struct shot tama[TAMA_NUM];
struct shot teki[TEKI_NUM];
for (i1 = 0; i1 < TAMA_NUM; i1++) {
...
}
}
あと、コードを見る限り、tama は x1,y1,flag1 しか使っていなくて、teki は t_x1,t_y1,t_flag1 しか使っていないみたいなので、
struct shot{
int x1,y1;
int flag1;
};
としておいた方が、tama が間違って t_x1 や t_flag1 を使ってしまったり、teki が y1 や flag1 を使うことが無くなるので、そうした方が良いと思います。
9ポイント を手に入れた。
|
|
|
|
|
Name: Wize
Date: 2010/09/15(水) 01:33
No:608501284481987
| 解決!
|
Title: Re:当たり判定がうまく出ません
|
|
返答がずいぶん遅くなってしまい、申し訳ないです。
おかげさまで問題は解決しました。
定数の助言もありがとうございます。
プログラミングが進んだ後で数を変更する際にも便利で助かってます。
ただ、最後の助言の個別にまとめるのがうまくいかずに棚上げになっていますが…まだ自分で試行錯誤してみます。
|
|
|
|
Name: のとと ..ぴよぴよ(87ポイント)
Date: 2010/09/01(水) 20:14
No:60821
|
|
Title: Cプログラムのシャットダウンシグナル
|
|
linuxで自作プログラムのデーモンを作成していて,シャットダウンの処理に困っています.
Cプログラムでファイルをオープンして追加書き込みの処理をしていたとします.
このとき,誤ってOSをシャットダウンしてしまった場合,
ファイルはオープンされたまシャットダウンしてしまうのでしょうか?
それともOSレベルでファイルをクローズしてくれてシャットダウンするものなのでしょうか?
宜しくお願いします.
87ポイント を手に入れた。
|
|
|
|
Name: のとと ..ぴよぴよ(55ポイント)
Date: 2010/09/02(木) 09:35
No:60855
|
|
Title: Re:Cプログラムのシャットダウンシグナル
|
|
ありがとうございます,
安全にクローズしたいのですが,シャットダウンのシグナルみたいなのを
C言語で監視できるものなのでしょうか?
> OSレベルでクローズしてくれます。
> 内容は保証できないと思いますが。
32ポイント を落としてしまった。
|
|
|
|
|
Name: アビゲイル ..ぴよぴよ(407ポイント)
Date: 2010/09/02(木) 19:13
No:60868
|
|
Title: Re:Cプログラムのシャットダウンシグナル
|
|
http://d.hatena.ne.jp/seiunsky/20090322/1237747356
↑こんな感じでシグナルごとの挙動を変更することができますが、
デーモンプロセスは、ソケットを扱うので、基本シグナルは無視するように設定します。
たしかこんな感じのものです。
signal(SIGPIPE, SIG_IGN);
signal(SIGTERM, SIG_IGN);
プロセスが終了するとクローズされるので、シャットダウンだったら正常に終了しますよ
HDDに保存されている方のファイルもそうそう壊れないでしょうし、
メモリからHDDに保存されなかった分が保証されないということではないかと思います。
、
251ポイント を手に入れた。
|
|
|
|
Name: 宗一郎 ..ぴよぴよ(263ポイント)
Date: 2010/09/02(木) 16:28
No:60863
|
|
Title: ”10.敵を表示させてみよう”での質問です。
|
|
はじめまして。今回初めて質問させていただきます本庄です。
皆さんこれからどうぞよろしくお願いしますm(..)M
早速の質問ですみませんが、
10.敵を表示させてみよう(以下URL)
http://dixq.net/rp/10.html
抜き出すとここの部分ですが、
//ゲームの初期化
void ini(){
stage_count=1;
memset(&ch,0,sizeof(ch_t));//自機データの初期化
ch.x=FIELD_MAX_X/2;
ch.y=FIELD_MAX_Y*3/4;
memset(enemy,0,sizeof(enemy_t)*ENEMY_MAX);//敵データの初期化
}
赤の部分は関数の呼び出しですよね?
この関数の宣言がどこにも見当たらないのですが、どのような処理をして自機と敵を初期化
しているのでしょうか?
よろしくお願いしますm(..)m
263ポイント を手に入れた。
|
|
|
|
Name: へろり ..プログラマー(34,705ポイント)
Date: 2010/09/02(木) 16:39
No:60865
|
|
Title: Re:”10.敵を表示させてみよう”での質問です。
|
|
memset()関数は標準関数です。
プロトタイプは string.h memory.h で次のように宣言されています。
void *memset(void *buf, int c, size_t size);
buf が指す領域を、c で、size バイト分埋めます。
戻り値は、buf の値です。
件のコードは、それぞれ &ch, enemy を、sizeof(ch_t), sizeof(enemy_t) * ENEMY_MAX分0でクリアしてるのですね。
164ポイント を手に入れた。
|
|
|
|
|
Name: 宗一郎 ..ぴよぴよ(342ポイント)
Date: 2010/09/02(木) 16:45
No:60866
| 解決!
|
Title: Re:”10.敵を表示させてみよう”での質問です。
|
|
標準関数にそういうものがあったんですね。
すみません、その辺はまだほとんど知りませんでした。
シエルさん、へろりさん
わかりやすい回答ありがとうございますm(. .)m
今後はそのあたりを含めて勉強していきたいと思います。
ありがとうございました^^
79ポイント を手に入れた。
|
|
|
|
Name: ナイ ..ぴよぴよ(202ポイント)
Date: 2010/09/01(水) 17:28
No:60803
|
|
Title: 関数ポインタのポインタについて
|
|
質問よろしいでしょうか?
C++にて関数ポインタのアドレスを更にアドレスにいれたいのですが(つまり関数のポインタのポインタです)
その場合に
void (* MOTO )(void);//すでに関数のアドレスが入っていると思ってください
void (** SAKI )(void);
SAKI = &MOTO;
とポインタの代入のようにするのか
void (* MOTO )(void);//すでに関数のアドレスが入っていると思ってください
void (* SAKI )(void);
(* SAKI ) = MOTO;
のように関数ポインタのようにやればいいのでしょうか?
わかりにくい書き方で申し訳ないですが、教えていただけないでしょうか?
201ポイント を手に入れた。
|
|
|
|
Name: アビゲイル ..ぴよぴよ(138ポイント)
Date: 2010/09/01(水) 17:44
No:60805
|
|
Title: Re:関数ポインタのポインタについて
|
|
int a;
int *b =&a;
int **c = &b:
int a;
int *b = &a;
int *c = b;
質問の内容は上記と同じですね。
関数のポインタのポインタという言葉の響きは前者ですが、実際どのように扱いたいのでしょうか?
その場合にもよりますが、可能なら後者がいいのではないでしょうか。
#質問の意図を汲んで文言を修正しました 
52ポイント を手に入れた。
|
|
|
|
|
Name: たかぎ [URL] ..ハッカー(222,248ポイント)
Date: 2010/09/01(水) 17:52
No:60807
|
|
Title: Re:関数ポインタのポインタについて
|
|
後者はあり得ません。
> void (* MOTO )(void);//すでに関数のアドレスが入っていると思ってください
> void (* SAKI )(void);
> (* SAKI ) = MOTO;
(* SAKI )は関数型ですので、代入できるはずがありませんね。
38ポイント を手に入れた。
|
|
|
|
|
Name: ナイ ..ぴよぴよ(239ポイント)
Date: 2010/09/01(水) 18:03
No:60811
|
|
Title: Re:関数ポインタのポインタについて
|
|
あぁすみません
(* SAKI ) = MOTO;
↓
SAKI = MOTO;です
37ポイント を手に入れた。
|
|
|
|
|
Name: gyz ..ぴよぴよ(862ポイント)
Date: 2010/09/01(水) 20:45
No:60823
|
|
Title: Re:関数ポインタのポインタについて
|
|
ポインタの指してる先を矢印で表現すると
前者は
SAKI → MOTO → 関数A
後者は
SAKI → 関数A
MOTO → 関数A
ってことですよね?
後者は「関数ポインタのポインタ」を保持してるわけではなく
MOTOと同じ関数ポインタをSAKIも持つようにしてるだけなので
「関数ポインタのポインタ」を使用する必要があるなら
前者が適当だと思います。
179ポイント を手に入れた。
|
|
|
|
|
Name: ナイ ..ぴよぴよ(302ポイント)
Date: 2010/09/02(木) 09:09
No:60854
| 解決!
|
Title: Re:関数ポインタのポインタについて
|
|
なるほど
よくわかりました。
お答えいただいてありがとうございます。
また何かありましたときには、よろしくお願いいたします。 
63ポイント を手に入れた。
|
|
|
|
Name: 鵺 ..ぴよぴよ(389ポイント)
Date: 2010/09/01(水) 16:49
No:60797
|
|
Title: 初心者な質問失礼します;
|
|
はじめまして鵺といいます。
ちょこっと関数を覚えてきたのでゲームを作ろうと思ったのですが
まだ勉強不足で1から作るのが困難で、作り方を調べていましたら
こちらのサイト様に行き着きました。
そこで、こちらで配布していらっしゃるSTGをお借りして、
色々いじってどんな結果になるか試して遊んでいたんですが
少し質問がありまして、書き込みさせて頂きました。
右のスコアボードなども消して、デバッグ実行した時に
画面全部を使ってキャラが移動できるようにしたいのですが
どういう関数を使うと良いでしょうか・・?
フルスクリーンではなくて、デバッグ実行したときに
本来スコアボードなどがある場所も消して横を広くしたいです。
過去レスも参考にしてみたのですがわからなくて・・・;
あと、DXライブラリを使った参考書を見てやってみたのですが
うまくいかないことがもう1つありまして、
龍神録さんの弾幕STGの自キャラにアニメーションが付いていて
凄いなあ!と思っているのですがイマイチやり方がわからない為
静止画で自分の作った自キャラをはっつけたいと思うのですが
関数は、int ghandle = LoadGraph("フォルダ名\\画像名.拡張子");
これではダメでしょうか・・・?
迷惑かけてすみませんが、良かったら教えて下さい・・!
389ポイント を手に入れた。
|
|
|
|
Name: softya [URL] ..ハッカー(211,026ポイント)
Date: 2010/09/01(水) 17:02
No:60799
|
|
Title: Re:初心者な質問失礼します;
|
|
たぶん、分からないのは「龍神録プログラミングの館」を最初の章から1章づつ理解されていないからだと思います。最初の部分から、じっくりと理解していけば後々すごくゲームプログラミング力が付きますよ。
動ける範囲に関しては、
7章の「ボードを表示してみよう」
http://dixq.net/rp/7.html
に
FIELD_MAX_X, 〜Yはそれぞれキャラクタが動ける領域の広さです。
と記述があります。
これと9章の「キャラクタの移動制御をしてみよう」と組み合わせて読めば理解できると思います。
>関数は、int ghandle = LoadGraph("フォルダ名\\画像名.拡張子");
>これではダメでしょうか・・・?
ここら辺は、「ゲームプログラミグの館」から理解されたほうが良いと思います。
〜ゲーム基本編〜
17. 画像を分割して読み込む
辺りから
19. キャラをキー入力によって移動させる。
が参考になるでしょう。
実際のところ「龍神録プログラミングの館」の前に「ゲームプログラミグの館」は一通り理解されることをお勧めします。
「龍神録プログラミングの館」や「ゲームプログラミグの館」の命令記述や変数の意味など細かいところについて分からないことがあれば、ここでまた質問してください。
87ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..ウィザード(1,267,588ポイント)
Date: 2010/09/01(水) 22:53
No:60842
|
|
Title: Re:初心者な質問失礼します;
|
|
softyaさんの仰る通りで、最初から館を読めばわかると思いますよ。
ボードの表示部分について付け加えますと、
最初はキャラしかいません。
実際ボードは7章からしか表示していませんから、それまでの章では表示していません。
重なりますが、ボードの表示は7章で書いているプログラムで表示していますから、
そのプログラムを実行しなければボードを表示しなくすることは出来ます。
144ポイント を手に入れた。
|
|
|
|
Name: ジュンヤ ..入門者(3,235ポイント)
Date: 2010/08/30(月) 01:45
No:60655
|
|
Title: 音ゲーの作り方
|
|
専門学校の卒業制作で、音ゲーを作ろうと思いまして、
太鼓の鉄人を参考にさせてもらってるのですが、
わからないところがあったので質問させてもらいます。
//弾の登録計算
void input_bullet(){
int k;
// stage.cntはフレームカウンター
double sc0=stage.cnt*16.6666666666, sc1=(stage.cnt+1)*16.6666666666;
// 弾を登録するタイミング(固定値)
double cnt=music.term*humen[stage.humen_cnt].cnt;
if(sc0<=cnt && cnt<sc1){
if((k=serch_bullet())!=-1){
enter_bullet(k,humen[stage.humen_cnt].knd-1,stage.spd);
}
stage.humen_cnt++;
}
}
この関数で、music.termという変数が使われていて、
ini関数で初期値が363.5625/8と代入されているのですが、これは一体何を意味するのでしょうか?
どの様に値を設定したらいいか、教えていただければ幸いです。
色々調べてみたのですが、アクションゲームやシューティングゲームの作り方の解説なら沢山あるのに、
音ゲーの作り方の参考になるサイトや書籍ってなかなかないんですね><
377ポイント を落としてしまった。
|
|
|
|
Name: Justy ..伝説なるハッカー(570,974ポイント)
Date: 2010/08/30(月) 02:53
No:60657
|
|
Title: Re:音ゲーの作り方
|
|
>どの様に値を設定したらいいか
多分ですけど。
0.txtのデータは1拍を更に8個に分解してデータが作られています。
その1個あたりのデータの時間が music.termであり 363.5625/8となるわけですが、
じゃあその363.5625がどこからきたかというと……。
この曲のテンポは推定 165bpmです。つまり1秒あたりだと 165/60で 2.75bpsで、
1拍辺りにミリ秒で換算すると 1000ミリ秒 / 2.75bpsで1拍 363.636363ミリ秒となります。
その1拍を8つに分解しているのですから 363.636363ミリ秒/8となるわけです。
ちょっと細かい数値が異なりますが、その辺りは曲のデータの正確な bpmが微妙にことなるのと、
実際に動かしてみた調整の結果によるものじゃないかと思います。
>音ゲーの作り方の参考になるサイトや書籍ってなかなかない
どうしてなんでしょうね……。
まぁ意外と必要無いからなのかもしれませんね。
普通にアクションゲームやシューティングゲームが作れるくらいのプログラミングスキルが
あるなら、音ゲーを作るのは難しくないですから。
175ポイント を手に入れた。
|
|
|
|
|
Name: めるぽん ..上級者(18,446ポイント)
Date: 2010/08/30(月) 03:19
No:60659
|
|
Title: Re:音ゲーの作り方
|
|
音ゲーの特殊なところは、音楽との同期や、キー入力の細かさでしょうね。ちょっとでもずれるとまともに遊べなくなります。
特にキー入力は、音ゲーの得意な人は60FPSよりももっと細かいレベルで入力できるので「フレーム毎にキーが押されているかどうかを判定する」という作り方だと、そういう人には簡単なゲームになってしまうでしょうね。そこは少し工夫が必要そうな気がします。
30ポイント を手に入れた。
|
|
|
|
|
Name: ISLe ..上級者(17,608ポイント)
Date: 2010/08/30(月) 05:49
No:60663
|
|
Title: Re:音ゲーの作り方
|
|
> 音ゲーの作り方の参考になるサイトや書籍ってなかなかないんですね><
特許に触れて訴えられる可能性が高いというのがあるかもしれません。
メジャーな音ゲーは意匠で固められているので。
48ポイント を落としてしまった。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..ウィザード(1,265,032ポイント)
Date: 2010/08/30(月) 07:55
No:60665
|
|
Title: Re:音ゲーの作り方
|
|
サンプルプログラミングの館に書いてあるものは、こんなのも作れますよという雰囲気を味わっていただきたくて公開しているものなので、
設計の仕方などについては参考にしないでください。
特に、あのような譜面の作り方では必ず行き詰まると思います。
もし本格的に作るならダンスマニアやBM98など有名なフリーの音ゲーのデータを参考にすべきかと思います。
(思いっきり特許を侵害しているフリーソフトの名前をここで上げるのは良くないかもしれませんが・・)
ISLeさんが仰るように音ゲーは特許に抵触する可能性が高いです。
例えばDDRやビートマニアのようなゲームシステムには特許があります。
ですから、それと同じようなゲームシステムのフリーゲームはいくつかありますが、あれらは特許を侵害しています。
後、音ゲーの作り方は需要が無いから無いのではないでしょうか?
世の中に公開されているフリーのオリジナル音ゲーがいくつあるかと思うと・・。
音ゲーはなんちゃってであれば割と簡単に出来ると思いますが、
音楽と正確に同期する処理が意外に難しいです。
また、譜面生成ツールを作らなければならないので、ゲームを2つ作るくらいの手間が必要だと思います。
まず思うように作ってみて、行き詰まりそうになったら質問するという感じで制作を続けてみてはいかがでしょう?
私も音ゲーなんて作ったことなかったですし、何も参考にした本やサイトはありませんでしたが、
以前試行錯誤で作りました。
まぁだから酷い仕様な部分があるのですが^^;
489ポイント を落としてしまった。
|
|
|
|
|
Name: ジュンヤ ..入門者(4,461ポイント)
Date: 2010/08/30(月) 23:06
No:60728
| 解決!
|
Title: Re:音ゲーの作り方
|
|
>Justyさん
丁寧に解説をしていただきまして、ありがとうございました。
1拍あたりのミリ秒をもとめてから、それを分解する数で割った数がmusic.termだったんですね。
ということは、この割る数を調整することで、
32分音譜1つ分でなく、16分音符1つ分や64分音符1つ分という風に調整できるということですね。
bpmのこともよくわかってなかったので、
ググりながらJustyさんの説明を拝見してようやく理解できました。(たぶん)
>めるぽんさん
やはり音楽との同期が問題になってきますよね。
音ゲー作るのは初めてなので、その辺りや譜面の作り方が気になるところです。
>音ゲーの特殊なところは、音楽との同期や、キー入力の細かさでしょうね。ちょっとでもずれるとまともに遊べなくなります。
作り始める前は、少しくらいのズレなら大した事ないだろうと思っても、
ミリ秒単位のズレでもすごく気になりますよね。勉強させてもらいました。
>ISLeさん
>特許に触れて訴えられる可能性が高いというのがあるかもしれません。
やはりその様な事情があったのですか。
将来的には作ったゲームを配布したりしてみたいと思うので、
その辺りも少し勉強した方がよさそうですね。
>Dixgさん
いつもお世話になってます。
わかりやすい説明やサンプルプログラムの数々、本当にありがとうございます。
>特に、あのような譜面の作り方では必ず行き詰まると思います。
やはり譜面の作り方が、問題になってきますよね。
できれば、本格的に作りたいと思っているので、ダンスマニアやBM98などのデータを参考にしてみようと思います。
ただ音ゲー作るのは初めてなので、太鼓の鉄人でも十分楽しいです。
後何曲か作ってみてから、本格的な物の制作を考えてみようと思います。
>後、音ゲーの作り方は需要が無いから無いのではないでしょうか?
たしかに手軽に使えるフリーのオリジナル音ゲー多いですよね。
ただここまでまったく参考にできる物が何もないと思いませんでした。
>また、譜面生成ツールを作らなければならないので、ゲームを2つ作るくらいの手間が必要だと思います。
やはり譜面生成ツールを作らなければ、本格的な音ゲーはできませんよね。
しかしC/C++以外の言語はあまりやったことがないし、ツールも作ったことないので、
できるか少し不安ですが・・
>まず思うように作ってみて、行き詰まりそうになったら質問するという感じで制作を続けてみてはいかがでしょう?
はい!まずは後何曲かこのまま作ってみてから、また最初から自分で設計してみようと思います。
>私も音ゲーなんて作ったことなかったですし、何も参考にした本やサイトはありませんでしたが
何も参考にしないで、そこまで作れるなんて本当にすごいと思います。
自分はそこまでできないと思うので、また質問させていただくと思いますが、
その時はよろしくお願いします。、
1,226ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..ウィザード(1,266,181ポイント)
Date: 2010/08/30(月) 23:26
No:60730
|
|
Title: Re:音ゲーの作り方
|
|
>しかしC/C++以外の言語はあまりやったことがないし、ツールも作ったことないので
ツールもC/C++で作ればいいのではないでしょうか?
どのような仕組みが適切かはやってみないとわからないかもしれませんが、私ならゲーム本体に作成支援ツール部分を組み込むと思います。
DDRにもprojectDIVAにもありますよね、ゲーム内に自分で好きな譜面を作れるコンテンツが。
そんな風にDXライブラリでもし今作っているなら譜面作成部もDXライブラリで作ればよいのではないでしょうか?
私は譜面作成ツールを超手抜きにしましたが・・
音楽からフーリエ変換を通して何とか譜面自動生成ツールが作れないかトライしたりもしました。
ただ結局思うようにいかずに諦めました・・。
余力があればそちらを研究しても面白いかもしれませんね。
193ポイント を手に入れた。
|
|
|
|
|
Name: ジュンヤ ..初心者(5,443ポイント)
Date: 2010/09/01(水) 17:09
No:60800
|
|
Title: Re:音ゲーの作り方
|
|
>ツールもC/C++で作ればいいのではないでしょうか?
規模が大きいツールはC#で作るものだとばかり思ってました。
ゲーム本体にツールを組み込む方法ならC/C++でいけそうですね。
実は、DDRもprojectDIVAもやったことないので、
その様な仕組みになっていると知りませんでした。
>私ならゲーム本体に作成支援ツール部分を組み込むと思います。
ゲーム内のコンテンツで、好きな譜面を作れれば、
プレイするだけでなく、譜面を作ってくれる人も増えそうですしね。
自分もDXライブラリで作っているので、その様な感じでやってみようと思います。
>音楽からフーリエ変換を通して何とか譜面自動生成ツールが作れないかトライしたりもしました。
譜面自動作成ツールなんて見たことないですね。(自分が知らないだけかもしれませんが)
あればとても便利だし、需要がありそうな気もするんですけどね。
けどDixgさんが諦めたとなると、今の自分のレベルでできるとは・・
そういえば、DXライブラリのリファレンスを見たら、
音楽だけでなく動画の再生時間を調べたり、セットしたりする関数がありました。
それを使って、youtubeやニコニコ動画からダウンロードして、
その動画でプレイできる音ゲーなんてあったら面白そうですよね。
またMMDで作った3Dモデルを読み込んで、簡単にプログラム側でアニメーションを
再生できるようになっていたので、3Dアクションゲーム+音ゲーなんかも作れそうですね。
夢が膨らむばかりで、技術が追いつきませんが^^;
2倍のポイントを手に入れた! 982ポイント を手に入れた。
|
|
|
|
|
Name: 通りすがり ..上級者(22,766ポイント)
Date: 2010/09/01(水) 17:56
No:60808
|
|
Title: Re:音ゲーの作り方
|
|
>youtubeやニコニコ動画からダウンロードして、その動画でプレイできる音ゲーなんてあったら面白そうですよね。
既にありますよ。身近なところに。
69ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..ウィザード(1,267,444ポイント)
Date: 2010/09/01(水) 22:41
No:60840
|
|
Title: Re:音ゲーの作り方
|
|
> 規模が大きいツールはC#で作るものだとばかり思ってました。
そんなことは無いでしょう。
むしろ逆で、C/C++の方が大規模なプロジェクトに使われる可能性が非常に高いと思います。
C#は基本的にマイクロソフト用のプログラム言語ですから、C#を全く使わない企業も多いと思いますし。
ただし、windowsプログラムが作りやすいというメリットはあります。
プログラムの規模に応じて使い分けるのではなく、用途に応じて使い分けるべきでしょう。
> youtubeやニコニコ動画からダウンロードして、その動画でプレイできる音ゲーなんてあったら面白そうですよね。
上で、Aerobeatの話をされていたように思いましたが、それはAerobeatの事を仰っているのではなくて・・ですか?
もしよろしければご覧ください。以下紹介サイトと動画です。
http://dixq.net/Aerobeat/
http://www.nicovideo.jp/watch/sm8808750
音楽データフォルダに好きな曲のフォルダを追加すれば曲選択画面に新たな項目が表示されてその曲で遊べるようになります。
音楽は動画の物を利用できるので、ニコニコやYoutubeから動画をDLしてフォルダに入れてやればすぐ遊べます。
譜面はあらかじめいくつか入っていて、無いものでも追加すれば遊べます。
Aerobeatの譜面を作って投稿して下さっているサイトがあります。
http://www26.atwiki.jp/aerobeat/pages/13.html
全部追加するのはちょっと大変ですが、この譜面を導入すれば200曲以上の曲で遊べます。
(しかしそんなに数が増えると思っていなかったのでカテゴリ機能が無い為200曲もあると曲を選ぶのが大変です(汗))
足らない動画データは動画サイトから自動で取ってくるような仕組みを作ればいいのですが、
著作権法が改定され、DLが違法となった現在この仕組みを実装するのはいかがなものかと思い、実装していません・・。
一応DL出来る方法はあるので、せっかく実装出来るのに勿体ない気はするのですが。
> MMDで作った3Dモデルを読み込んで、簡単にプログラム側でアニメーションを再生できるようになっていたので
そうですね、DXライブラリが3D対応になってから、自分のゲームにも組み込みたいと思いつつもなかなか時間が無くて実装出来ていません。
私も実装してみたいなと思っています。
2倍のポイントを手に入れた! 840ポイント を手に入れた。
|
|
|
|
Name: kerotan0820 ..プログラマー(25,945ポイント)
Date: 2010/09/01(水) 21:36
No:60831
|
|
Title: 10. 入力状態を取得する。 の単元
|
|
皆様お久しぶりです
久しぶりにC言語の勉強を再開しました
最初C言語を始めたころに比べ頭がやわらかくなった気がするので、久々にゲームプログラミングの館に再度挑戦しています
高校生のうちに一本ゲームを完成させるのを目標としてがんばってみたいと思います
早々なのですが、「入力状態を取得する」という題の単元(以下URL)について質問があります
http://dixq.net/g/10.html
見本のプログラムは、エンターが押されたらループを終了するとのプログラムですが、どういった仕組みでエンターが押された時にループを抜けているのですか?
( CheckHitKey( KEY_INPUT_RETURN ) == 0
エンターを押したら、 CheckHitKey( KEY_INPUT_RETURN )が1になって、 CheckHitKey( KEY_INPUT_RETURN ) == 0の条件が合わなくなるからループを抜けるということでしょうか
CheckHitKey( KEY_INPUT_RETURN )はひとつの変数なのですか?
intで宣言されているのは Whiteだけですが。
41ポイント を手に入れた。
|
|
|
|
Name: Dixq (管理人) [URL] ..ウィザード(1,266,604ポイント)
Date: 2010/09/01(水) 22:26
No:60836
|
|
Title: Re:10. 入力状態を取得する。 の単元
|
|
> CheckHitKey( KEY_INPUT_RETURN )はひとつの変数なのですか?
いえ、変数ではありません。関数です。
関数についてはご存じでしょうか?
関数は戻り値を持たせることが出来ます。
例えば
int calc(){
return 3;
}
というcalc関数があったとすれば、この関数は3を返すので戻り値が3と同等のものとして扱えます。
このように関数には返り値を持たせることが出来ますから、キーの入力状態を調べるCheckHitKeyという関数に、0か1の返り値を持たせることで、キーの入力状態のチェックが可能となるのです。
このことが良く解らない場合、まず、C言語の基本を入門サイトなどで学ばれると良いと思います。
例えば今回の件で言えば
http://www5c.biglobe.ne.jp/~ecb/c/c00.html
左メニューの「関数」について学ばれると良いと思います。
284ポイント を手に入れた。
|
|
|
|
|
Name: kerotan0820 ..プログラマー(26,016ポイント)
Date: 2010/09/01(水) 22:34
No:60839
| 解決!
|
Title: Re:10. 入力状態を取得する。 の単元
|
|
■管理人様、naohiro19様
回答ありがとうございます
とりあえず関数について今一度学んでみたいと思います
ご指導ありがとうございます
71ポイント を手に入れた。
|
|
|
|
Name: どどんぱち ..ぴよぴよ(96ポイント)
Date: 2010/08/31(火) 23:10
No:60749
|
|
Title: NSDataから任意のサイズ分読み込み
|
|
iPhone / Objective-C
で、
ネット接続〜NSDataとしてバイナリデータをDLまではできるのですが、
このNSDataから、任意のサイズ分(int,short,byte)読み込んでいく方法がわかりません。
readInt()のようなものはないのでしょうか?。
また、
参考になるサイトやサンプル、書籍等ありましたら
ご教授頂けたら幸いです。
よろしくお願いします。
96ポイント を手に入れた。
|
|
|
|
Name: Justy ..伝説なるハッカー(571,131ポイント)
Date: 2010/09/01(水) 00:21
No:60752
|
|
Title: Re:NSDataから任意のサイズ分読み込み
|
|
const unsigned char *pData = (const unsigned char *)[data bytes];
こんな感じにキャストすれば、あとは普通のCと同じにアクセスできます。
サンプルは……そうですね、GKTankとか WiTapあたりでしょうか。
157ポイント を手に入れた。
|
|
|
|
|
Name: どどんぱち ..ぴよぴよ(196ポイント)
Date: 2010/09/01(水) 22:33
No:60838
| 解決!
|
Title: NSDataから任意のサイズ分読み込み
|
|
Justyさん
なるほど。直にアクセスするんですね。
メソッドが何か用意されているものと思っていましたが。
エンディアンとかも考慮して読めるようにしたければ自分でライブラリ化しておくべしって
ことなんですね。
ご回答ありがとうございました。 
100ポイント を手に入れた。
|
|
|
|
Name: こーり ..ぴよぴよ(54ポイント)
Date: 2010/08/30(月) 16:17
No:60692
|
|
Title: フラグからタイマー起動
|
|
龍神録でボスを倒したら、フラグを立てて、
フラグがたったら、タイマーを実行し、
5秒後くらいに画像を表示するにはどうすればいいのでしょうか?
分かりにくくてすみません;;よろしく御願いします。
できればソースもお願いします。
54ポイント を手に入れた。
|
|
|
|
Name: Dixq (管理人) [URL] ..ウィザード(1,265,858ポイント)
Date: 2010/08/30(月) 20:01
No:60711
|
|
Title: Re:フラグからタイマー起動
|
|
イベント管理係を作ってはどうでしょう。
その人に「ボスが倒れたから今から5秒数えてね」と通知したら、担当さんは5秒数えて発火してくれたらよいと思います。
本来は複数受け付けたりする必要があるでしょうが、例えば
typedef struct{
int Flag; //フラグ
int Kind; //起こすイベントの番号
int Count; //カウンタ
int Time; //イベントを起こすまでの時間
}Event_t;
こんな構造体を用意したとしましょう。
イベントを管理すべきかどうかのフラグ、起こすイベントの番号、カウンタと時間を持っています。
登録するイベントの数だけ線形リストに追加するような仕組みにすればflagは必要なくなります。
RegisterEvent( int Kind, int Time );
のような関数を用意して、イベントを登録します。
int RegisterEvent( int Kind, int Time ){
Event.Flag = 1;
Event.Kind=Kind;
Event.Count=0;
Event.Time=Time;
return xx;
}
登録作業はこんな感じですかね。
後は
int CalcEvent(){
if( Event.Flag==1 ){
カウンタを加算
カウンタが時間になれば
登録してあるイベントを発火();
}
return xx;
}
こんな計算をする関数を毎度呼べばよいと思います。
イベントは線形リストなどにすると良いでしょう。
532ポイント を手に入れた。
|
|
|
|
|
Name: こーり ..ぴよぴよ(117ポイント)
Date: 2010/08/30(月) 20:23
No:60714
|
|
Title: Re:フラグからタイマー起動
|
|
ん〜・・・皆さんすごいですね・・
そんなこと言われてもチンプンカンプンというか・・・
まったくわかりません・・・;;
63ポイント を手に入れた。
|
|
|
|
|
Name: array [URL] ..熟練のプログラマー(67,430ポイント)
Date: 2010/08/30(月) 21:04
No:60715
|
|
Title: Re:フラグからタイマー起動
|
|
> まったくわかりません・・・;;
皆さん優しいので、何が分らないのか具体的に示してもらえれば
別の切り口からの解説などが望めるかもしれません。
解答者側から見たら、全部分らないと言われると、何から解説すれば良いのか
困ってしまいます。
事実、管理人さんの解答ではこーりさんには難しすぎたようですし
全部分らないというより、分る部分はある程度コードを書いて
行き詰った部分を質問した方がいいのでは?
156ポイント を手に入れた。
|
|
|
|
|
Name: こーり ..ぴよぴよ(213ポイント)
Date: 2010/08/30(月) 21:30
No:60716
|
|
Title: Re:フラグからタイマー起動
|
|
そうですね・・・;;
では、管理人さんのおっしゃっている、
>RegisterEvent( int Kind, int Time );
のような関数を用意して、イベントを登録します。
とは、どうやって登録をすればいいのでしょうか?
96ポイント を手に入れた。
|
|
|
|
|
Name: こーり ..ぴよぴよ(512ポイント)
Date: 2010/08/31(火) 10:28
No:60739
|
|
Title: Re:フラグからタイマー起動
|
|
恥ずかしながら、初歩的なところを浅くわかっているくらいです。
呼び出し方は、関数名(引数 );だと思います。
作り方はたとえば、 型 sample(引数){処理}
これに、関数は何かを処理するためのものだから、
{
a=5+5;
}
これで一個の関数
型 sample(引数)
{
a=1+1;
}
で、管理人さんは、int型を前につけていらっしゃるので
return 関数値;
関数値がxxということで、たとえば、関数値が5だとすると
int keisan(引数)
{
return 5;
ということだと思います。
そして引数は、
例えば、
int sample( )
{
}
void main( )
{
}
という関数を定義したとして、
これに、引数を入れると
int sample(int num)
{
}
void main( )
{
sample(10);
}
以上のことくらいしかわかりませんが・・
299ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(210,528ポイント)
Date: 2010/08/31(火) 11:29
No:60741
|
|
Title: Re:フラグからタイマー起動
|
|
ありがとうございます。
関数の基本的な事は理解されますね。
Dixq (管理人)さんの書かれた関数を簡単に説明してみますね。
●時限イベントを登録する関数です。
RegisterEvent( int Kind, int Time );
Kindにイベントの種類番号(自分で決めてください)、Timeにイベント発動までの時間(フレーム数)を登録します。この関数を呼ぶのは、時限イベントを設定したいタイミングです。
●イベントのタイミングを計算する関数です。
int CalcEvent(){
メインのループのどこかで呼び出しておきます。
中身が完成していないので関数の中身を自分で書く必要があります。
//カウンタを加算
Event.Count++;
//カウンタが時間になれば
if( Event,Count >= Event.Time ) {
//イベント停止
Event.Flag = 0;
//登録してあるイベントを発火();
if( Event.Kind==自分で決めたイベントの種類番号 ) {
//イベント処理の呼び出し(何をするかは自分で決めてください)
}
120ポイント を落としてしまった。
|
|
|
|
|
Name: こーり ..ぴよぴよ(457ポイント)
Date: 2010/09/01(水) 22:14
No:60834
| 解決!
|
Title: Re:フラグからタイマー起動
|
|
あ、なるほど
やっとわかりました。
いろいろ手間取らせちゃってすみませんでした。
ありがとうございました。
55ポイント を落としてしまった。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..ウィザード(1,266,320ポイント)
Date: 2010/09/01(水) 22:23
No:60835
|
|
Title: Re:フラグからタイマー起動
|
|
softyaさん、ご説明ありがとうございます。
> こーりさん
いきなり具体的なプログラムで少し解りにくかったかもしれません。
上にも書いた通り、イベントドリブンではない設計のゲームプログラムで、○秒後にイベントを発生させるという処理をしたい時は、カウンタをカウントアップさせて時間をはかり、設定したイベントを発火させるのが良いと思います。
その方法は上の方法でなくてもよいと思うので、まずは自分の思うようにプログラムを書いてみるのが良いと思います。
自分に最も合う良い方法は試行錯誤の中で見つけていくのが一番だと思いますので。
139ポイント を手に入れた。
|
|
|
|
Name: ヤマト ..ぴよぴよ(67ポイント)
Date: 2010/09/01(水) 18:12
No:60814
|
|
Title: 開発環境のメモリの増設
|
|
PC関連の質問の場所でないことはわかっているのですが
他に聞く所がわからないので質問させて頂きます。
eMachines ET1830を使っていてメモリを増設したいです。
4GBにしたいのですが相性があるみたいでどのメモリを買えば良いのかがわかりません。
もし詳しい方がおりましたら安くて通販で買えるメモリを教えては頂けないでしょうか?
67ポイント を手に入れた。
|
|
|
Name: シエル [URL] ..熟練のプログラマー(67,797ポイント)
Date: 2010/09/01(水) 19:19
No:60818
|
|
Title: 【DirectXプログラミング】描画されるオブジェクトの大きさについて
|
|
いつもお世話になっております。シエルです。
DirectXにて現在ゲームを作成しており、3D背景を実装しようとしているのですが、
どうも思ったとおりの大きさに描画されず苦戦しています。
まず、
D3DFVF_DIFFUSE,D3DFVF_XYZ,D3DFVF_TEX1の頂点フォーマットを設定し、下記の頂点構造体を作っています。
typedef struct {
D3DXVECTOR3 v;
DWORD color;
D3DXVECTOR2 tex;
}VERTEX;
これを四つくっつけたポリゴン構造体が以下のものです。
typedef struct{
VERTEX v[4];
int flag;
}PORIGON;
これを使って、縦横3.0のポリゴンを作成し、テクスチャマッピングを行って描画したのですが、
イメージとは違う大きさで描画されてしまいます。(約80倍ぐらい。)
おそらくカメラの設定等が関係してくるとは思うのですが、どの部分に問題があるかご指摘願えますでしょうか?
添付したソースで、test.pngという名前のファイルをプロジェクトファイルと同じフォルダに
放り込んで、実行していただければ実行できます。
方向キー上下でZ座標が変化するようにしておりますが、起動直後の最初の画像の大きさに
注目してください。実際にしていした座標より大きくなってますので。
あと、もう一つ質問なんですが、Direct3Dの描画で原点(0,0,0)は必ずウィンドウの中央に自動的に
設定されているのでしょうか?
ソースがかなり長いので、添付させていただきます^^;
それでは、ご教授のほどよろしくお願い致します。
430ポイント を手に入れた。
|
|
|
|
Name: softya [URL] ..ハッカー(211,471ポイント)
Date: 2010/09/01(水) 21:01
No:60824
|
|
Title: Re:【DirectXプログラミング】描画されるオブジェクトの大きさについて
|
|
DirectXを真面目にいじったことがない私ですが、3Dの基本事項の問題だと思いますので回答してみます。
3Dの基本として透視変換は理解されていますか?
3Dの座標系はピクセルではありません。どちらかというとメートルとか単位があるわけでは無いですが距離や大きさを表す単位です。画面に表示される大きさは、カメラの画角とカメラとの距離で決定されます。
すごく現実の世界に近いワケでデジカメで撮影するときに3mの物をちゃんとカメラに収めるには何メートル離しますか?って感覚に近いです。
望む大きさに表示したい場合は、カメラの画角と距離、表示するポリゴンの大きさを元に計算しないといけません。
85ポイント を手に入れた。
|
|
|
|
|
Name: シエル [URL] ..熟練のプログラマー(67,869ポイント)
Date: 2010/09/01(水) 21:15
No:60826
| 解決!
|
Title: Re:【DirectXプログラミング】描画されるオブジェクトの大きさについて
|
|
そんな気がしてたんですけど、やはりそうですか・・・。
難しいですね。何か計算式があればいいんですが。。。
何回も実行して経験を積んで、慣れていくしかなさそうですね。
まあ、ソースに問題があるというわけではなさそうですので、一旦解決にしておきます。 
72ポイント を手に入れた。
|
|
|
|
|
Name: ふぉ [URL] ..ぴよぴよ(236ポイント)
Date: 2010/09/01(水) 21:24
No:60828
|
|
Title: Re:【DirectXプログラミング】描画されるオブジェクトの大きさについて
|
|
//視野角をラジアン単位に変換
FLOAT fovy = 45.0f*D3DX_PI/180.0f;
//基準値の高さ640を視野角を利用して、視点からの距離を求める
FLOAT z = (640.0f*0.5f)/(FLOAT)tan(fovy/2.0f)-10.0f;
//ポリゴン座標セット
PorigonSet(&pr1,-320.0f,320.0f,z,640.0f,640.0f);
視野角が45度で、基準になっているスクリーンサイズを640とすると、
視点とスクリーンサイズを底辺とした二等辺三角形を作ることが出来ます。
さらにその二等辺三角形を分割(視野角を半分に)して直角三角形にすると、
スクリーンサイズ/2を底辺に持つ三角形が出来ます。
これを利用して直角の点から視点までの距離を求めると、
スクリーンのサイズとちょうど一致した距離になります。
最後に-10しているのは、視点と注視点の距離がすでに10ある為です。
それとZが1000を超えてしまうので、射影行列を作るときに、
D3DXMatrixPerspectiveFovLH(&proj,D3DXToRadian(45.0f),
aspect,1.0f,10000.0f);
遠平面のZを上のように適当に大きな数を指定する必要があります。
>あと、もう一つ質問なんですが、Direct3Dの描画で原点(0,0,0)は必ずウィンドウの中央に自動的に
設定されているのでしょうか?
これに関してですが、ビュー行列の視点の位置を変更すれば変わります。
236ポイント を手に入れた。
|
|
|
|
|
Name: シエル [URL] ..熟練のプログラマー(68,019ポイント)
Date: 2010/09/01(水) 21:31
No:60830
| 解決!
|
Title: Re:【DirectXプログラミング】描画されるオブジェクトの大きさについて
|
|
>> ふぉさん
回答ありがとうございます!
非常に分かりやすい説明ありがとうございます!
私の関数を使って説明していただいて、すごいわかりやすいです!
ちょっと実際にやってみます!
あと原点の件もありがとうございます。
ビュー行列の視点の位置がそのまま原点になっていたんですね!
かなりすっきりしました!
あ〜本当にやる気出てきました。ありがとうございました!
103ポイント を手に入れた。
|
|
|
|
Name: AXE ..ぴよぴよ(239ポイント)
Date: 2010/08/30(月) 11:40
No:60676
|
|
Title: C言語と関係ない質問なのですが・・・
|
|
まったく関係なくもありません・・・
インターネットに接続するときのIPアドレスありますよね(グローバルIPアドレス)
通常、固定IPにしていないかぎり変動IPだと思うのですが、
IPを変更するにはルーターの電源を切ったりしなければなりません。
これを好きなときに変更するようなプログラムを作成したいのですが
IPを変更することは可能でしょうか?
自分の使っているルーターはBUFFALOのBBルーターという有線のルーターなのですが
ブラウザからhttp://192.168.11.1/にアクセスするとログインフォームが出てきて
認証すると接続、切断とあるので切断したあとに接続するとIPが変わります。
こんな感じでIPを変更することはできないでしょうか?
239ポイント を手に入れた。
|
|
|
|
Name: シエル [URL] ..熟練のプログラマー(66,578ポイント)
Date: 2010/08/30(月) 12:03
No:60678
|
|
Title: Re:C言語と関係ない質問なのですが・・・
|
|
ipconfig /release
ipconfig /renew
をC言語からでも、コマンドプロンプトからでもやれば行けるかも。
私はたまにやります。
ですが、やるなら自己責任でお願いします。責任は持てません。
44ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..中級者(9,378ポイント)
Date: 2010/08/30(月) 13:52
No:60686
|
|
Title: Re:C言語と関係ない質問なのですが・・・
|
|
C言語で、という話になると、ソケット通信するプログラムで、
1) http://192.168.11.1/ にログイン
2) 切断クリック
3) 接続クリック
だけを行う専用HTTPクライアントを自作する感じでしょうか。
でもけっこう面倒ですね(私には)。
VBScript/JScriptの方が簡単に作れたりするのかな?
あ、それがシエルさんの「VBSでもできる」という事でしょうか。
88ポイント を手に入れた。
|
|
|
|
|
Name: シエル [URL] ..熟練のプログラマー(66,700ポイント)
Date: 2010/08/30(月) 13:58
No:60687
|
|
Title: Re:C言語と関係ない質問なのですが・・・
|
|
>>たろさん
そうです。
私がパッと思い浮かんだのは、IEオブジェクトを作成して該当のアドレスのページを開き、
その後、WSHShellオブジェクトを作成し、Appacitivateで該当ウィンドウをアクティブにした後、
Sendkeysでを駆使して、切断と接続ボタンを押下させるというようなものです。
キー送信を使ってるので、うまくいかないこともありますし、あまりお勧めしません。

118ポイント を手に入れた。
|
|
|
|
|
Name: へろり ..プログラマー(32,105ポイント)
Date: 2010/08/30(月) 14:05
No:60688
|
|
Title: Re:C言語と関係ない質問なのですが・・・
|
|
直接HTTPメッセージを送ればいいのではないでしょうか。
perlとかで簡単に出来そうな気がします。
などと言うだけ言ってみます。
59ポイント を手に入れた。
|
|
|
|
|
Name: AXE ..ぴよぴよ(277ポイント)
Date: 2010/08/31(火) 16:51
No:60748
|
|
Title: Re:C言語と関係ない質問なのですが・・・
|
|
ご返答ありがとうございます。
私もソケットは考えて作成しましたが何度も変更してたら500エラーになってしまいました…
いまの段階ではそこまで短時間のうちに変更することはしないのでいいのですが、
いずれは5分、10分、15分と項目から指定した時間毎に変更するようなものを作りたいので
今のままだとダメです。
なにかいい方法はないでしょうか?
ちなみに私の場合は
http://192.168.11.1/
ですが、これは人によって違うはずです。
友達とかにも配布したりして感想を聞きたいのですが、こっちも解決法があったらお願いします。
38ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..中級者(9,809ポイント)
Date: 2010/09/01(水) 00:44
No:60754
|
|
Title: Re:C言語と関係ない質問なのですが・・・
|
|
>…何度も変更してたら500エラーになってしまいました…
家庭用のブロードバンドルータって、あまり短い間隔で切断・接続が繰り返される
ことを想定していないのでは?という気がします。ですので エラーになってしまう
事があるのは、しょうがないのかな・・と思います。要するに「あまり短い間隔で
切断・接続を繰り返さないでください」という事かなと・・。
>友達とかにも配布したりして感想を聞きたいのですが、こっちも解決法があったらお願いします。
ルータのIPアドレスが違っても、ルータの機種が違っても、動作するようにしたい、
ということでしょうか?
IPアドレスはまあいいとして、メーカーや型式の違うルータに対応するというのは、
なかなか大変そうな気がします。確かにできたらよいなと思いますが。
1つの機種について「ログイン・切断・接続方法の仕様を調べる」「実装する」
「動作を確認」という手順を繰り返して、対応機種を1つずつ増やしていく感じ
でしょうか。機種の違いの多くは、HTTPリクエストの形式が少し違うくらいかな
と思いますが、その情報は恐らく公開されてないでしょうし、そうすると、実機
を使って確認するしかないと思います。
※ルータに詳しいわけではないので違ってたらすみません。 
431ポイント を手に入れた。
|
|
|
|
|
Name: AXE ..ぴよぴよ(284ポイント)
Date: 2010/09/01(水) 17:27
No:60802
|
|
Title: Re:C言語と関係ない質問なのですが・・・
|
|
結論で言うと出来ないということでしょうか?
7ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(211,312ポイント)
Date: 2010/09/01(水) 18:04
No:60812
|
|
Title: Re:C言語と関係ない質問なのですが・・・
|
|
>結論で言うと出来ないということでしょうか?
ルータが繰り返しでエラーになる原因は、返ってくるパケットをちゃんと調べたほうが良いと思いますね。待ち時間とかを制御すれば出来るかも知れませんので。
あとブロードバンドルータが何らかのパケットに応答するという共通仕様は無いとおもいますので、メーカー毎に実装が違うと思います。つまり、色んなメーカーや型番のルータでどんなパケットに応答するか調べて、あとはIPスキャンで探し出すしか無いんじゃないでしょうか?
2倍のポイントを手に入れた! 286ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..中級者(10,147ポイント)
Date: 2010/09/01(水) 18:41
No:60817
|
|
Title: Re:C言語と関係ない質問なのですが・・・
|
|
技術的にはできると思います。
ただ、いろいろなルータに対応する方法を想像すると、
・最初は家族や友人知人が違うルータを使っているなら、それで調査やテストを
させてもらい、対応機種を2つ、3つと増やしていく。
・頼める人がいなくなったら、どうしよう、自分で契約プロバイダやプラン(コース)
を次々に変更して、いろんなルータを手に入れて、対応機種を増やしていくことも、
できなくはないが・・。
という、(プログラミングの問題でなく)手間と時間とお金の話になりました。(私の予想では。)
HTTP500エラーの件は、softyaさんもおっしゃってますが、エラーにならないように
待ち時間を入れて回避することはできないでしょうか?
310ポイント を手に入れた。
|
|
|
|
Name: a ..入門者(3,279ポイント)
Date: 2010/09/01(水) 00:04
No:60751
|
|
Title: 無題
|
|
基本課題 10..3
基本問題8.2で作成したアスタリスクで作成した直角三角形 を印字するプログラムを関数を使って作り直してみよう。指定された文字を指定 された回数だけ連続して印字する処理を関数化する。この関数の宣言を
int run(char c, int length);
とする。すなわち、関数runは文字cを長さlengthだけ印字する。 戻り値は印字した文字の個数(すなわち、length)とする。
この関数runを作成し、キーボードより入力された任意の正の整数を高さと する直角三角形を印字するプログラムを作成せよ。
% decWithFunc
正の整数: 15
1: ***************
2: **************
3: *************
4: ************
5: ***********
6: **********
7: *********
8: ********
9: *******
10: ******
11: *****
12: ****
13: ***
14: **
15: *
%
という課題で、わからないことがあります。
/* ここからコピー */
#include <stdio.h>
# define BUFFER_SIZE (256)
int get_int(void)
{
char buf[BUFFER_SIZE];
fgets(buf, BUFFER_SIZE, stdin);
return atoi(buf);
}
/* ここまでコピー */
int run(char c,int length)
{
int j;
for(j=1;j<=length;j++)
{
printf("%c",c);
}
printf("\n"); ←ーーー@
return length;
}
int main(void)
{
int a,i,kat;
printf("正の整数:");
a = get_int();
//正の整数でないといけないから
if(a>0)
{
int b,c,d;
for(b=0;b<a;b++)
{
printf("%d",b+1);
for(d=0;d<b;d++)
{
printf(" ");
}
kat =run('*',a-b);
//printf("\n"); ←ーーーーA
}
}
return 0;
}
@の場所で改行すればうまくいくのにAの場所で改行してもうまくいかないのはなぜ?
2倍のポイントを手に入れた! 976ポイント を手に入れた。
|
|
|
|
Name: fatens ..上級者(17,877ポイント)
Date: 2010/09/01(水) 00:50
No:60755
|
|
Title: Re:無題
|
|
>@の場所で改行すればうまくいくのにAの場所で改行してもうまくいかないのはなぜ?
試してみたところ同じように表示されましたが?
あと、せっかく関数にしたので空白の出力もrun関数で。
#include <stdio.h>
#define BUFFER_SIZE (256)
int get_int(void);
int run(char, int);
int main(void)
{
int n, i, j;
printf("正の整数: ");
n = get_int();
if (n <= 0)
return 1;
for (i = 1; i <= n; i++) {
printf("%2d:", i);
run(' ', i);
run('*', n - i + 1);
putchar('\n');
}
return 0;
}
int get_int(void)
{
char buf[BUFFER_SIZE];
fgets(buf, BUFFER_SIZE, stdin);
return atoi(buf);
}
int run(char c, int length)
{
int i;
for (i = 0; i < length; i++)
putchar(c);
return length;
}
435ポイント を落としてしまった。
|
|
|
|
|
Name: a ..入門者(3,786ポイント)
Date: 2010/09/01(水) 14:31
No:60767
|
|
Title: Re:無題
|
|
run関数で空白もできるんですね。わかりました。ありがとうございます。
27ポイント を手に入れた。
|
|
|
|
|
Name: a
Date: 2010/09/07(火) 22:59
No:607511283867971
| 解決!
|
|
|
Name: たろ ..ぴよぴよ(684ポイント)
Date: 2010/08/24(火) 19:00
No:59963
|
|
Title: POPUPウィンドウの消し方
|
|
#以前「C言語です」という名前で投稿しましたが、名前変えました。
C言語+Win32APIで、GUIの画像処理ソフトを作ろうとしているのですが、ウィンドウ操作でわからない事があり、質問させてください。
OSはXP Home (SP3)、VC2008EEを使っています。MFCは使っていません。
種類としてはペイントやPhotoshopのような、画像を表示して加工を施すタイプのアプリケーションです。
動作中にユーザのクリックに反応して表示する、小さなポップアップウィンドウを消すタイミングがわかりません。
添付画像は問題のポップアップウィンドウ(赤枠)が出ている画面をキャプチャしたものです。
@ユーザが特定の場所("透明度○○%"の文字)をクリック
A小さなポップアップウィンドウ(TrackBarコントロールを乗せたWS_POPUPウィンドウ)を表示
その後、「このポップアップウィンドウ以外の場所をクリック(マウス押下)したタイミングでウィンドウを消したい」のですが、どう実装するのがよいのかわかりません。
一応、たぶんできそうだけど・・と思っている実装は、
・このポップアップウィンドウ以外の全てのウィンドウで WM_LBUTTONDOWN や WM_RBUTTONDOWN が来た時にポップアップウィンドウを消す処理を入れる。
というものですが、なんだか泥臭いというか・・「他にもっとうまいやり方があるのでは?」と思ってしまいます。
別のソフトでも、「バージョン表示ダイアログ」や「起動時のスプラッシュウィンドウ」などで、「そのウィンドウ(?)以外の場所をクリックしたら消えてくれる(閉じるボタン等を押す必要はない)」という感じのものを見かけることがあります。ああいう動作はどう実装されているのでしょうか・・?それと似たような感じに見えるのですが・・。検索しても解説してくれているサイトなどを見つけることができませんでした。
わかりにくかったらすみません。
ソースは大量になってしまうので載せていませんが、必要でしたらこの話に的を絞った小さなソースを提示させて頂きます。
よろしくお願いします。m(_ _)m
499ポイント を手に入れた。
|
|
|
|
Name: シエル ..熟練のプログラマー(62,406ポイント)
Date: 2010/08/24(火) 19:06
No:59964
|
|
Title: Re:POPUPウィンドウの消し方
|
|
そのウィンドウがアクティブじゃなくなったら消すとかはどうですか?
GetActiveWindowで取得したウィンドウハンドルとそのポップアップウィンドウのハンドルが一致しなければ、
閉じるようにするのはどうでしょう。
追記:
すいません。↑のは却下でお願いします。 
65ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..入門者(3,254ポイント)
Date: 2010/08/24(火) 20:11
No:59967
|
|
Title: Re:POPUPウィンドウの消し方
|
|
ツールチップじゃないですね。
ようやく意味が理解できました。
ShowWindow(hWndPopup, SW_HIDE);
ではだめでしょうか?
2倍のポイントを手に入れた! 46ポイント を手に入れた。
|
|
|
|
|
Name: シエル ..熟練のプログラマー(62,449ポイント)
Date: 2010/08/24(火) 20:13
No:59968
|
|
Title: Re:POPUPウィンドウの消し方
|
|
そのポップアップウィンドウでWM_KILLFOCUSのメッセージを受信したら、
閉じるようにしてはどうでしょうか。
無理かもしれませんが。
43ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..入門者(3,321ポイント)
Date: 2010/08/24(火) 20:21
No:59969
|
|
Title: Re:POPUPウィンドウの消し方
|
|
すみません、問題をよく理解してませんでした。
たとえば、トラックバーをサブクラス化して
トラックバーをダブルクリックしたら非表示とかどうでしょう?
67ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..かけだし(1,050ポイント)
Date: 2010/08/24(火) 20:37
No:59972
|
|
Title: Re:POPUPウィンドウの消し方
|
|
コメントありがとうございます。
説明が乏しくてすみません。やりたい事は、
@クリックしたら独自のWS_POPUPスタイルのウィンドウを表示
Aそのウィンドウ「以外の場所」をクリックしたらウィンドウを消す(それまでは出っぱなし)
ですが、Aの実装方法で、よい方法がないでしょうか?という話です。
>シエルさん
GetActiveWindow()は使ったことがなかったです。何か応用できるか考えてみます。
>palladiumさん
はい、ShowWindow(hWndPopup, SW_HIDE); で消すことができるのは確かめました。ただ、今考えている方式だとShowWindow()を入れる箇所がかなり多くなり、すぐ考慮漏れが発生しそうで、他にうまいやり方がないのだろうか・・という相談でした。
今考えてる方式とは、ポップアップウィンドウ以外の、メインのウィンドウ他、常に表示されている全てのウィンドウの WindowProc で、WM_LBUTTONDOWN が来たら ShowWindow(SW_HIDE) を実行する、という方式です。右ボタンや中ボタンも含めるともっと増えるし、面倒だなあ・・と。
ShowWindow(SW_HIDE) を実行する箇所が、例えば1箇所だけになるようなよい方法があると嬉しいのですが、難しいででしょうか・・。
やはりソースがあった方がよい気がしてきました。小さなソースを、準備したいと思います。 
366ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..かけだし(1,153ポイント)
Date: 2010/08/24(火) 20:46
No:59973
|
|
Title: Re:POPUPウィンドウの消し方
|
|
>シエルさん
WM_KILLFOCUS、こんなメッセージがあるんですね。フォーカスを失ったら来るメッセージでしょうか。ちょっと試してみます。ありがとうございます。
>palladiumさん
なるほど。ユーザインタフェースとしてはそういう方式もありですね。ありがとうございます。ちなみにサブクラス化は見よう見まねで使ってはいますがあまり理解できていません・・。(DefWindowProcを入れ替える=サブクラス化?みたいな・・)
103ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..入門者(3,373ポイント)
Date: 2010/08/24(火) 20:55
No:59975
|
|
Title: Re:POPUPウィンドウの消し方
|
|
サブクラス化についてですが、実行環境次第では
SetWindowSubclass関数が使えるかもしれません。
52ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..入門者(3,579ポイント)
Date: 2010/08/24(火) 22:42
No:59981
|
|
Title: Re:POPUPウィンドウの消し方
|
|
質問の内容に的を絞ったソースコードを作りました。
ちょっと長いですが最後に貼りつけます。。
・メインウィンドウ1つ、その中に子ウィンドウ1つ(操作パネル的な)
・小ウィンドウ上でクリックした地点にトラックバーを表示
・トラックバーは実際はWS_POPUPスタイルのウィンドウ上に乗っている
やりたいことは「トラックバー以外の場所をクリックしたらトラックバーを隠したい」です。トラックバーを隠す処理は、ShowWindow(hPopupWnd,SW_HIDE)でよいのですが、それを(できれば)1箇所だけ記述すれば済むような、簡単な方法はないものでしょうか。。
シエルさんに教えてもらった WM_KILLFOCUS を試してみました。が、あと一歩という感じでした。ポップアップウィンドウのイベントハンドラでShowWindow(SW_HIDE)したところ、「トラックバー以外の場所クリックで消える」はできたのですが、トラックバー自体を操作するためにクリックしても消えてしまいました(トラックバーが使えない)。これは、フォーカスがトラックバーコントロールに移ってしまい、その下地のウィンドウから外れてしまったからでしょうか(?)。トラックバーコントロールにフォーカスを移さないようにできればいいのかな?でもそれだとトラックバー操作できなくなるのかな・・うーん・・。
#include <windows.h>
#include <commctrl.h>
HWND hPopupWnd=NULL; // ポップアップウィンドウハンドル
// ポップアップウィンドウプロシージャ
LRESULT CALLBACK PopupWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
switch( msg ) {
case WM_HSCROLL:
// トラックバーが変更された時の処理をする(省略)
return 0;
case WM_KILLFOCUS:
// フォーカスを失った
// ここで自分自身を隠すと、トラックバーを操作しても消えてしまう
//ShowWindow( hwnd, SW_HIDE );
return 0;
}
return DefWindowProc( hwnd, msg, wp, lp );
}
// 操作パネルウィンドウプロシージャ
LRESULT CALLBACK ChildWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
POINT po;
switch( msg ) {
case WM_LBUTTONDOWN:
// パネル上でマウス押下した地点にトラックバーをポップアップ表示します
po.x = LOWORD( lp );
po.y = HIWORD( lp );
ClientToScreen( hwnd, &po );
MoveWindow( hPopupWnd, po.x, po.y, 150, 30, TRUE );
ShowWindow( hPopupWnd, SW_SHOW );
break;
}
return DefWindowProc( hwnd, msg, wp, lp );
}
// メインウィンドウプロシージャ
LRESULT CALLBACK MainWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
switch( msg ) {
case WM_CREATE:
// 操作パネル(子)ウィンドウ作成
CreateWindowEx( 0, "ChildWindow", "操作パネルのようなもの", WS_CHILD|WS_OVERLAPPEDWINDOW|WS_VISIBLE,
0,0,300,200, hwnd, (HMENU)NULL, (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE), NULL );
// ポップアップウィンドウ作成(親はメインウィンドウ)
hPopupWnd = CreateWindowEx( 0, "PopupWindow", NULL, WS_POPUP, 0,0,0,0, hwnd, (HMENU)NULL,
(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE), NULL );
// トラックバー作成(ポップアップウィンドウに乗せる)
CreateWindowEx( 0, TRACKBAR_CLASS, NULL, WS_CHILD|WS_VISIBLE, 0,0,150,30, hPopupWnd,
(HMENU)NULL, (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE), NULL );
break;
case WM_DESTROY:
// アプリケーション終了
PostQuitMessage(0);
break;
}
return DefWindowProc( hwnd, msg, wp, lp );
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow )
{
MSG msg;
WNDCLASSEX wc;
INITCOMMONCONTROLSEX ic;
// コモンコントロール初期化
ic.dwSize = sizeof(INITCOMMONCONTROLSEX);
ic.dwICC = ICC_BAR_CLASSES;
InitCommonControlsEx( &ic );
// メインウィンドウクラス登録
ZeroMemory( &wc, sizeof(WNDCLASSEX) );
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = MainWindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH)( COLOR_APPWORKSPACE+1 );
wc.lpszClassName = "MainWindow";
RegisterClassEx( &wc );
// 子(操作パネル)ウィンドウクラス登録
wc.lpfnWndProc = ChildWindowProc;
wc.lpszClassName = "ChildWindow";
RegisterClassEx( &wc );
// ポップアップウィンドウクラス登録
wc.lpfnWndProc = PopupWindowProc;
wc.lpszClassName = "PopupWindow";
RegisterClassEx( &wc );
// メインウィンドウ作成
CreateWindowEx( 0, "MainWindow", "メインウィンドウ", WS_OVERLAPPEDWINDOW|WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, (HMENU)NULL, hInstance, NULL );
// メッセージループ
while( GetMessage( &msg, NULL, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return msg.wParam;
}
2,426ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..かけだし(1,981ポイント)
Date: 2010/08/25(水) 01:01
No:59989
|
|
Title: Re:POPUPウィンドウの消し方
|
|
フォーカスの問題は残りますが、ちょっとやってみました。
Windows XP sp3, VS2005 std sp2
#include <windows.h>
#include <commctrl.h>
#pragma comment(lib, "comctl32.lib")
LRESULT CALLBACK PopupWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp );
LRESULT CALLBACK ChildWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp );
HWND hPopupWnd = NULL; // ポップアップウィンドウハンドル
static BOOL TrackBarVisible = FALSE;
void TrackBarState(HWND)
{
if(!TrackBarVisible){
ShowWindow( hPopupWnd, SW_SHOW );
TrackBarVisible = !TrackBarVisible;
} else {
ShowWindow( hPopupWnd, SW_HIDE);
TrackBarVisible = !TrackBarVisible;
}
return;
}
// ポップアップウィンドウプロシージャ
LRESULT CALLBACK PopupWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
switch( msg ) {
case WM_HSCROLL:
// トラックバーが変更された時の処理をする(省略)
return 0;
case WM_KILLFOCUS:
// フォーカスを失った
// ここで自分自身を隠すと、トラックバーを操作しても消えてしまう
//ShowWindow( hwnd, SW_HIDE );
return 0;
}
return DefWindowProc( hwnd, msg, wp, lp );
}
// 操作パネルウィンドウプロシージャ
LRESULT CALLBACK ChildWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
POINT po;
switch( msg ) {
case WM_LBUTTONDOWN:
// パネル上でマウス押下した地点にトラックバーをポップアップ表示します
po.x = LOWORD( lp );
po.y = HIWORD( lp );
ClientToScreen( hwnd, &po );
MoveWindow( hPopupWnd, po.x, po.y, 150, 30, TRUE );
TrackBarState( hPopupWnd );
return 0;
}
return DefWindowProc( hwnd, msg, wp, lp );
}
// メインウィンドウプロシージャ
LRESULT CALLBACK MainWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
HINSTANCE hInst = GetModuleHandle(NULL);
switch( msg ) {
case WM_CREATE:
// 操作パネル(子)ウィンドウ作成
CreateWindowEx( 0, TEXT("ChildWindow"), TEXT("操作パネルのようなもの"),
WS_CHILD | WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, 300, 200, hwnd, (HMENU)NULL, hInst, NULL );
// ポップアップウィンドウ作成(親はメインウィンドウ)
hPopupWnd = CreateWindowEx( 0, TEXT("PopupWindow"), NULL,
WS_POPUP,
0, 0, 0, 0, hwnd, (HMENU)NULL, hInst, NULL );
// トラックバー作成(ポップアップウィンドウに乗せる)
CreateWindowEx( 0, TRACKBAR_CLASS, NULL,
WS_CHILD | WS_VISIBLE,
0, 0, 150, 30, hPopupWnd, (HMENU)NULL, hInst, NULL );
return 0;
case WM_LBUTTONDOWN:
ShowWindow(hPopupWnd, SW_HIDE);
return 0;
case WM_DESTROY:
// アプリケーション終了
PostQuitMessage(0);
return 0;
}
return DefWindowProc( hwnd, msg, wp, lp );
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int nShowCmd )
{
MSG msg;
HWND hwnd;
WNDCLASSEX wc;
INITCOMMONCONTROLSEX ic;
// コモンコントロール初期化
ic.dwSize = sizeof(INITCOMMONCONTROLSEX);
ic.dwICC = ICC_BAR_CLASSES;
InitCommonControlsEx( &ic );
// メインウィンドウクラス登録
SecureZeroMemory( &wc, sizeof(WNDCLASSEX) );
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = MainWindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH)( COLOR_APPWORKSPACE+1 );
wc.lpszClassName = TEXT("MainWindow");
if(!RegisterClassEx( &wc )){ return -1; }
// 子(操作パネル)ウィンドウクラス登録
wc.lpfnWndProc = ChildWindowProc;
wc.lpszClassName = TEXT("ChildWindow");
if(!RegisterClassEx( &wc )){ return -2; }
// ポップアップウィンドウクラス登録
wc.lpfnWndProc = PopupWindowProc;
wc.lpszClassName = TEXT("PopupWindow");
if(!RegisterClassEx( &wc )){ return -3; }
// メインウィンドウ作成
hwnd = CreateWindowEx( 0, TEXT("MainWindow"), TEXT("メインウィンドウ"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, (HMENU)NULL, hInstance, NULL );
if(!hwnd){ return -4; }
ShowWindow( hwnd, nShowCmd);
UpdateWindow( hwnd );
// メッセージループ
while( GetMessage( &msg, NULL, 0, 0 ) > 0 )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return (int)msg.wParam;
}
1,392ポイント を落としてしまった。
|
|
|
|
|
Name: たろ ..入門者(4,114ポイント)
Date: 2010/08/25(水) 01:09
No:59993
|
|
Title: Re:POPUPウィンドウの消し方
|
|
WM_KILLFOCUS の処理変更と、コントロールのウィンドウプロシージャ差し替え(サブクラス化?)でなんとか自己解決しました。
シエルさん、palladiumさん、どうもありがとうございました。
・WM_KILLFOCUSはフォーカスを失う直前に来るようで、またwParamに次にフォーカスが移るウィンドウハンドルが入っている。
・そこで、次にフォーカスが移るウィンドウを調べてからShowWindow(SW_HIDE)するようにした。
・具体的には、下地のWS_POPUPウィンドウと、そこに乗るTrackBarコントロールとの両者で、共にWM_KILLFOCUSを捕まえて、相互にフォーカスが移動する場合は何もしない、その他のウィンドウにフォーカスが移る場合だけShowWindow(SW_HIDE)で隠す。
少々無理やり?感もありますが、他のウィンドウのWM_LBUTTONDOWNにShowWindow(SW_HIDE)を書きまくるのに比べれば、だいぶスマートに収まったと思っています。簡単な確認ですが動作も問題なさそうな感じです。
参考までに、先に提示したソースからの変更箇所を載せておきます。
HWND hPopupWnd; // ポップアップウィンドウハンドル
HWND hTrackbar; // トラックバーウィンドウハンドル
WNDPROC DefTrackbarProc; // トラックバー既定ウィンドウプロシージャ
// トラックバーコントロールウィンドウプロシージャ
LRESULT CALLBACK TrackbarProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
switch( msg ) {
case WM_KILLFOCUS:
// フォーカスを失う直前
// 次にフォーカスが移るウィンドウ(wp)がポップアップウィンドウ(親)以外ならポップアップウィンドウ(親)を隠す
if( (HWND)wp!=hPopupWnd ) ShowWindow( hPopupWnd, SW_HIDE );
return 0;
}
return CallWindowProc( DefTrackbarProc, hwnd, msg, wp, lp );
}
// ポップアップウィンドウプロシージャ
LRESULT CALLBACK PopupWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
switch( msg ) {
:
case WM_KILLFOCUS:
// フォーカスを失う直前
// 次にフォーカスが移るウィンドウ(wp)がトラックバー(子)以外なら自分自身を隠す
if( (HWND)wp!=hTrackbar ) ShowWindow( hwnd, SW_HIDE );
return 0;
}
return DefWindowProc( hwnd, msg, wp, lp );
}
:
// メインウィンドウプロシージャ
LRESULT CALLBACK MainWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
switch( msg ) {
case WM_CREATE:
:
// トラックバー作成(ポップアップウィンドウに乗せる)
hTrackbar = CreateWindowEx( 0, TRACKBAR_CLASS, NULL, WS_CHILD|WS_VISIBLE, 0,0,150,30, hPopupWnd,
(HMENU)NULL, (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE), NULL );
// トラックバーウィンドウプロシージャ差し替え(サブクラス化?)
DefTrackbarProc = (WNDPROC)GetWindowLong( hTrackbar, GWL_WNDPROC );
SetWindowLong( hTrackbar, GWL_WNDPROC, (LONG)TrackbarProc );
break;
:
535ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..入門者(4,178ポイント)
Date: 2010/08/25(水) 01:14
No:59994
|
|
Title: Re:POPUPウィンドウの消し方
|
|
>palladiumさん
すみません、入れ違いになってしまったようです。
わざわざありがとうございました!試して頂いたソース、今から確認します。
2倍のポイントを手に入れた! 64ポイント を手に入れた。
|
|
|
|
|
Name: ISLe ..中級者(14,435ポイント)
Date: 2010/08/25(水) 01:28
No:59996
|
|
Title: Re:POPUPウィンドウの消し方
|
|
トラックバーを操作した時点でSetCaptureしてウインドウ外メッセージを監視する方法は使えないでしょうか。
ツールチップ使っていると相性が悪いかもしれません。
40ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..入門者(4,504ポイント)
Date: 2010/08/25(水) 01:59
No:60000
|
|
Title: Re:POPUPウィンドウの消し方
|
|
>palladiumさん
なるほど、「Show/Hideの状態を保持しておいて交互に切り替える」「メインウィンドウのWM_LBUTTONDOWNで常に隠す」の2点でしょうか。
手元の環境で実行したところ、タイトルバーをクリックした時はトラックバー消えず残ったままになってしまうようでした。クライアント領域外のマウス押下もつかまえてShowWindow(SW_HIDE)を実行すればよさそうかな。
あと、他にもいろいろ手直しありがとうございます。勉強になりました。
・hInstanceって、GetModuleHandle(NULL)で取得できるんですね。知りませんでした。
・MSDNを見たら、while(GetMessage(..)) という書き方はダメよと確かに書いてありました・・。
・nShowCmdってそうやって使うんですね・・知りませんでした。。
身近に相談できる人がいないのですごく助かります!
本当にありがとうございました!
326ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..入門者(4,823ポイント)
Date: 2010/08/25(水) 02:21
No:60001
|
|
Title: Re:POPUPウィンドウの消し方
|
|
>ISLeさん
コメントありがとうございます。
ツールチップは現在使っていませんので相性は大丈夫そうですが、すみません、試してみたいのですが、具体的な実装がすぐイメージできないので、調べてみます。
・トラックバー操作時点でSetCaptureするとは、トラックバーをサブクラス化した?差し替えウィンドウプロシージャで WM_LBUTTONDON/WM_LBUTTONUP を捕まえて実行するのでしょうか・・。
・そしてSetCaptureした後、ウィンドウ外メッセージを監視するというのは・・どこで何をすれば・・すみません・・。SetCaptureはドラッグ操作の処理で使っていますが、「SetCaptureしておけばウィンドウ外に出てもドラッグが続けられる」というくらいの認識しかありませんでした。
とりあえずSetCaptureを調べてきます。
319ポイント を手に入れた。
|
|
|
|
|
Name: ISLe ..中級者(14,646ポイント)
Date: 2010/08/25(水) 04:40
No:60006
|
|
Title: Re:POPUPウィンドウの消し方
|
|
SetCaptureだと下のウインドウにメッセージを投げる透過処理が必要なので面倒臭いですね。
No:59981のソースをもう一度詳しく見てみたのですが、
1) ポップアップウインドウを開くのはWM_LBUTTONDOWNではなくWM_LBUTTONUPで行う。
2) ポップアップウインドウのウインドウプロシージャに以下のメッセージ処理コードを追加。
case WM_ACTIVATE:
{
WORD fActive = LOWORD(wp);
if (fActive == WA_INACTIVE) {
ShowWindow(hwnd, SW_HIDE);
}
}
break;
ではどうでしょう。
211ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..入門者(4,359ポイント)
Date: 2010/08/25(水) 09:11
No:60019
|
|
Title: Re:POPUPウィンドウの消し方
|
|
前回の修正とツールチップの動作確認です。
以下抜粋です。
#include <windows.h>
#include <commctrl.h>
#pragma comment(lib, "comctl32.lib")
LRESULT CALLBACK PopupWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp );
LRESULT CALLBACK ChildWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp );
#define IDTT_TRACKBAR 1 // ToolTip control ID
HWND hPopupWnd = NULL; // ポップアップウィンドウハンドル
HWND hTrackBar = NULL;
static BOOL TrackBarVisible = FALSE;
void TrackBarState(HWND hPopupWnd, PBOOL pTrackBarVisible) // 非グローバル対策
{
if(! *pTrackBarVisible){
ShowWindow( hPopupWnd, SW_SHOW );
} else {
ShowWindow( hPopupWnd, SW_HIDE);
}
*pTrackBarVisible = ! *pTrackBarVisible;
return;
}
BOOL AddToolTip(HWND hOwnerWnd, LPTSTR lpText, UINT_PTR uId)
{
TOOLINFO ti;
HWND hToolTip = CreateWindowEx(
WS_EX_TOPMOST, // タクスバーとの競合を避ける
TOOLTIPS_CLASS, // ツールチップクラス
NULL, // ウィンドウタイトルは不要
TTS_ALWAYSTIP | // 対象のアクティブ・非アクティブにかかわらず常に表示する
TTS_NOPREFIX , // &文字を有効にする(表示される)
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, hOwnerWnd, NULL, GetModuleHandle(NULL), NULL);
if(!hToolTip){ return FALSE; }
GetClientRect(hOwnerWnd, &ti.rect);
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = TTF_SUBCLASS;
ti.hwnd = hOwnerWnd;
ti.uId = uId;
ti.hinst = NULL;
ti.lpszText = lpText;
// 初期化したTOOLINFO構造体データを登録する
if(!SendMessage(hToolTip, TTM_ADDTOOL, 0, (LPARAM)&ti)){ return FALSE; }
// ToolTipが表示されるまでの時間指定(ms)
SendMessage(hToolTip, TTM_SETDELAYTIME, TTDT_INITIAL, 100);
return TRUE;
}
// 操作パネルウィンドウプロシージャ
LRESULT CALLBACK ChildWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
POINT po;
switch( msg ) {
case WM_LBUTTONDOWN:
// パネル上でマウス押下した地点にトラックバーをポップアップ表示します
po.x = LOWORD( lp );
po.y = HIWORD( lp );
ClientToScreen( hwnd, &po );
MoveWindow( hPopupWnd, po.x, po.y, 150, 30, TRUE );
TrackBarState( hPopupWnd, &TrackBarVisible ); // ■
return 0;
}
return DefWindowProc( hwnd, msg, wp, lp );
}
// メインウィンドウプロシージャ
LRESULT CALLBACK MainWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
HINSTANCE hInst = GetModuleHandle(NULL);
switch( msg ) {
case WM_CREATE:
// 操作パネル(子)ウィンドウ作成
CreateWindowEx( 0, TEXT("ChildWindow"), TEXT("操作パネルのようなもの"),
WS_CHILD | WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, 300, 200, hwnd, (HMENU)NULL, hInst, NULL );
// ポップアップウィンドウ作成(親はメインウィンドウ)
hPopupWnd = CreateWindowEx( 0, TEXT("PopupWindow"), NULL,
WS_POPUP,
0, 0, 0, 0, hwnd, (HMENU)NULL, hInst, NULL );
// トラックバー作成(ポップアップウィンドウに乗せる)
hTrackBar = CreateWindowEx( 0, TRACKBAR_CLASS, NULL,
WS_CHILD | WS_VISIBLE,
0, 0, 150, 30, hPopupWnd, (HMENU)NULL, hInst, NULL );
AddToolTip( hTrackBar, TEXT("some text"), IDTT_TRACKBAR ); // ■
return 0;
case WM_LBUTTONDOWN:
ShowWindow(hPopupWnd, SW_HIDE);
return 0;
case WM_DESTROY:
// アプリケーション終了
PostQuitMessage(0);
return 0;
}
return DefWindowProc( hwnd, msg, wp, lp );
}
2倍のポイントを手に入れた! 2,378ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..初心者(5,318ポイント)
Date: 2010/08/25(水) 09:18
No:60020
|
|
Title: Re:POPUPウィンドウの消し方
|
|
>ISLeさん
すみません、SetCaptureを考えてるうちに寝てしまいました。。
MSDNを読みまして、「SetCaptureしたウィンドウは、(自身以外も含めて)以降のマウス操作をすべて拾うことができる」という感じで、「なるほど」と思いました。そして
@トラックバー出現と共にSetCapture(hTrackBar)する
A以降のマウスダウン/アップ等のイベントが、
・自身のウィンドウ上ならトラックバー処理
・自身のウィンドウ上でなければウィンドウ隠してReleaseCaptureして終わり
の発想までいきましたが、具体的にどこにどう実装するか・・まるっと違う方式になるな・・というところでした。仕事おそくてすみません・・。ただ、なるほどこんな考え方もあるか!という感じでとても参考になりました!ありがとうございました。
そして WM_ACTIVATE を使った方式ですが、これ動きました!すごいっ、ShowWindow(SW_HIDE)も1回だけだし、かなりスマートです。こんなやり方があったのか〜。
ちなみに、ポップアップの表示は WM_LBUTTONUP と WM_LBUTTONDOWN とどちらも試してみましたが、特にどっちでも大丈夫そうに見えます・・。何か違うのでしょうか・・。
あと、細かい話ですが、トラックバー表示状態のままメインウィンドウの大きさを変更しようとしてウィンドウ境界部分(矢印カーソル状態)をドラッグしようとすると、なぜか一発目はできません(ドラッグ操作が無視されてしまう感じ)。トラックバーが消えていれば問題ないですが。なぜそんなところの動作に影響があるのだろう・・?まあ気にするほどの事でもないかな・・。
それにしても目から鱗です。ありがとうございました!
>シエルさん
貼り付けたソースはMDIではありませんが、実際作ろうとしている画像処理アプリはMDIです。
MDIの子ウィンドウ(任意数)と、操作パネルのようなウィンドウがいくつかあって、さらに操作パネル上には部品用のウィンドウもたくさんあって・・という感じで、それら全てのウィンドウに「トラックバーを消す」処理を入れるなんて・・、かなり大変だし、もっといい方法ないのかな?ということで質問させて頂きました。 
495ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..初心者(5,535ポイント)
Date: 2010/08/25(水) 09:53
No:60027
|
|
Title: Re:POPUPウィンドウの消し方
|
|
>palladiumさん
たびたびありがとうございます!
おお・・ツールチップの実装コードはじめて見ました。こうやって作るんですね。
これいいですね。いい感じに勝手に出現して勝手に消えてくれます。
ソフトがもっとまともに動くようになったらそのうち入れてみよう・・と何となく考えていましたが、1つ2つ入れてみようかなぁ。これは hToolTip はアプリケーション全体で1つだけで、中身のテキストを変えて使い回せばいいんですよね・・って、やってみればわかるか。
ありがとうございました〜。
217ポイント を手に入れた。
|
|
|
|
|
Name: シエル ..熟練のプログラマー(62,593ポイント)
Date: 2010/08/25(水) 10:30
No:60029
|
|
Title: Re:POPUPウィンドウの消し方
|
|
WM_ACTIVATEって非アクティブのときもこのメッセージで受け取るんですね。
知らなかったので、すごい勉強になりました。
ツールチップも私は使ったことなかったので、非常に勉強になりました。
この掲示板は見てるだけですごい勉強になりますね^^
なんか質問者じゃないですけど、ありがとうございますw
125ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..入門者(4,730ポイント)
Date: 2010/08/25(水) 12:02
No:60040
| 解決!
|
Title: Re:POPUPウィンドウの消し方
|
|
皆様ありがとうございました。おかげさまで問題は解決し、それ以外でもとても勉強になりました。
ちょっと補足を最後に・・しつこくてすみません。WM_ACTIVATE方式で、「なぜかウィンドウの大きさ変更が(一発目だけ)できない」という細かい話を書きました。原因はよくわかりませんが、それを回避する実装を考えました。(無理やり感たっぷりですが・・)
「非アクティブになって次のウィンドウもアクティブ化された後」でポップアップウィンドウ隠すようにしたつもりです。メッセージの到着順序とかあまり詳しく調べておらず不安は残りますが、手元(WinXP Home SP3)では動いているようです。
・非アクティブになった後で来る(つもりの)独自メッセージを定義。
#define WM_APP_INACTIVATED WM_APP
・ポップアップウィンドウプロシージャで、
・非アクティブになる直前(WM_ACTIVATE)に WM_APP_INACTIVATED を PostMessage()。
case WM_ACTIVATE:
{
WORD fActive = LOWORD(wp);
if (fActive == WA_INACTIVE) {
// (これから)非アクティブになります
// 「アクティブになった後」の独自メッセージをポストして終了。
PostMessage( hwnd, WM_APP_INACTIVATED, 0, 0 );
}
}
break;
・WM_APP_INACTIVATED(非アクティブになった後)でウィンドウを隠す。
case WM_APP_INACTIVATED:
// 非アクティブになりました
ShowWindow(hwnd, SW_HIDE); // ウィンドウ隠す
return 0;
質問の内容自体は既に解決していますので、解決マークとさせて頂きます。
ありがとうございました。m(_ _)m 
805ポイント を落としてしまった。
|
|
|
|
|
Name: ISLe ..中級者(14,929ポイント)
Date: 2010/08/26(木) 00:12
No:60115
|
|
Title: Re:POPUPウィンドウの消し方
|
|
> ちなみに、ポップアップの表示は WM_LBUTTONUP と WM_LBUTTONDOWN とどちらも試してみましたが、特にどっちでも大丈夫そうに見えます・・。何か違うのでしょうか・・。
トラックバーのポップアップウインドウが表示されているときに、操作パネルのようなものウインドウのクライアント領域をクリックした時の挙動が違います。
WM_LBUTTONUPで表示しているときは、クリック一回でポップアップウインドウが移動します。
WM_LBUTTONDOWNだとクリックして非表示になり、もう一回クリックすると表示されます。
WM_LBUTTONUPのほうが元の挙動と同じだというのもありますが、WM_LBUTTONDOWNの挙動はたまたまそうなっているという意図しない挙動なのでお勧めしません。
> あと、細かい話ですが、トラックバー表示状態のままメインウィンドウの大きさを変更しようとしてウィンドウ境界部分(矢印カーソル状態)をドラッグしようとすると、なぜか一発目はできません(ドラッグ操作が無視されてしまう感じ)。トラックバーが消えていれば問題ないですが。なぜそんなところの動作に影響があるのだろう・・?まあ気にするほどの事でもないかな・・。
こちら、解決されたようですが、実はShowWindowのポスト版というAPIがあります。
No:60006で紹介したコードの場合
ShowWindow(hwnd, SW_HIDE);
を
ShowWindowAsync(hwnd, SW_HIDE); /* メッセージポスト版 */
に変更してみてください。
283ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..入門者(4,469ポイント)
Date: 2010/08/26(木) 00:46
No:60117
|
|
Title: Re:POPUPウィンドウの消し方
|
|
ShowWindowAsync関数はMSDNによると
The ShowWindowAsync function sets the show state of a window created by a different thread.
とあるので、動作保障が無いかもしれません。
84ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..初心者(5,842ポイント)
Date: 2010/08/26(木) 02:31
No:60125
|
|
Title: Re:POPUPウィンドウの消し方
|
|
>ISLeさん、palladiumさん
細かい話にコメントありがとうございます!実はけっこう気になってました。
>WM_LBUTTONUPで表示しているときは、クリック一回でポップアップウインドウが移動します。
>WM_LBUTTONDOWNだとクリックして非表示になり、もう一回クリックすると表示されます。
おお、本当ですね。気づきませんでした。なるほど。これは、メッセージの到着順による違いでしょうか。
0) 表示されてる状態から、
1) WM_LBUTTONDOWN で表示
2) WM_ACTIVATE で隠す
と
1) WM_ACTIVATE で隠す
2) WM_LBUTTONUP で表示
の違いかな?ちゃんと確認してみたいと思いますが、ここまで考慮して頂いていたとは・・感服しました。
そして ShowWindowAsync 関数!!試してみたら期待通り動きました!うおお・・こんなものがあったとは。すごい、よくご存知ですね。MSDNのShowWindowのページにもなぜかリンクがないし。左側の関数ツリーには出てきたけど・・。う〜んこういうところで差が出るなぁと改めて痛感します。
palladiumさんご指摘の、MSDN説明文「別のスレッドによって作成されたウィンドウの表示状態を設定」は確かに気にかかります。「同じスレッドで作ったウィンドウに使っちゃダメなの?」と。でも下の解説には「イベントをポストします」とあるだけで、スレッドについては触れられていません。なんなの?スレッド関係ないんじゃ?とも思ってしまいますが、ウィンドウとスレッドの結びつき具合をよく知らないし・・謎だ・・。こういう時にどちら側に倒すか・・難しいです。
ひとまず手元の XP Home SP3 では特に問題なさそうな感触です。
できれば ShowWindowAsync が一番スマートなので使いたい。
問題があったら No:60040 (独自メッセージ版)に戻す。
という方針でいこうかなと思ってます。
いろいろ教えていただき本当にありがとうございました!
819ポイント を手に入れた。
|
|
|
|
|
Name: ISLe ..中級者(14,938ポイント)
Date: 2010/08/26(木) 03:38
No:60127
|
|
Title: Re:POPUPウィンドウの消し方
|
|
"(a window created by) a different thread"というのは、ShowWindowAsyncを呼び出すスレッドから見て異なるスレッドという意味ではなく「(ウインドウを作成した)それぞれのスレッド」という意味だと思います。
#日本語サイトは直訳ですけど。
--追記
ウインドウはスレッドと関連付けられメッセージキューもスレッドごとに独立しているので、メッセージのポスト先はそれぞれのスレッドというふうに表現できます。

9ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..初心者(6,556ポイント)
Date: 2010/08/26(木) 12:21
No:60153
|
|
Title: Re:POPUPウィンドウの消し方
|
|
>ISLeさん
なるほど・・! 深いご見識と洞察に脱帽です・・。よろしければもう少し食いつかせてください。
「different thread」という表現。確かにMSDNはShowWindowAsyncの特徴を「他のアプリケーションに対して安全に使える」と書いてます。元々、"別のアプリケーションプロセスに対して使うもの" という感じでしょうか。ググっても、そういった用途の話しか見つかりませんでした。その点を強調した表現かもしれないと思いました。
裏を返すと「単一アプリケーション内で使うのは?」→「そんな意味もないし必要ないだろう?」という感じでしょうか。
でもそれなら、今回の件で辿り着いたこの一番スマートな方式(WM_ACTIVATE+ShowWindowAsync)は何なんだろう・・やりたい機能は、別にそんな独創的な話ではない。でもトリッキーな実装になってしまってるんでしょうか?できれば定石的な実装でいきたいですが・・。
>ウインドウはスレッドと関連付けられメッセージキューもスレッドごとに独立しているので、
このあたりのWindows内部の話、興味深いです。OS側でウィンドウやスレッドがどう管理されているのか?イメージしながらAPIを使えるといいのですが、なかなか難しいです・・。
ウィンドウは、生成したスレッドと紐付いてるんですね。
メッセージキューはウィンドウに1つ存在する、ウィンドウが持ってる感じをイメージしてます。
もっと突っ込んで、ウィンドウの実体=ウィンドウハンドルの先にある構造体かクラスのインスタンス?と、プロセスやスレッドの関係、という話になるともうダメです(笑)プロセス・スレッドの実体も構造体かクラスのインスタンスなのかな・・メモリ上どうなってるのか・・CPUの割り当てとか・・難しいです・・。
>メッセージのポスト先はそれぞれのスレッドというふうに表現できます。
なるほど・・「スレッドにウィンドウメッセージをポスト」というのは、わかるような、わからないような・・。
でもそういえば不思議です。「ShowWindowAsync がメッセージキューにポストする "a show-window event"」って何だ?と。WM_SHOWWINDOW とは違うようですし、WM_XXX 系のウィンドウメッセージとは違うものでしょうか。同じだけど、WM_XXX の名前で公開されてない秘密メッセージ、とかかな。謎です・・。 
714ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..入門者(4,687ポイント)
Date: 2010/08/26(木) 16:02
No:60178
|
|
Title: Re:POPUPウィンドウの消し方
|
|
>もっと突っ込んで、ウィンドウの実体...
この辺りはやっぱり押さえておきたいですよね。
私は「Advanced Windows 改訂第4版 Jeffrey Richter著」を
参考にしました。(ISBN4-7561-3805-5)
たとえば
PostMessageはメッセージをポストするとすぐに制御を返しますが、
呼出し元スレッドからは、メッセージが送り先で処理されたかどうかわかりません。
(処理完了のエラーチェックができない)
もし、送り先での処理完了通知を受け取るとなると問題があります。
送り先がハングアップしていた場合、処理完了通知を受け取れないので
呼出し元スレッドもハングアップしてしまいます。
ShowWindowAsyncはハングアップの連鎖を防ぐために使われるのだと思います。
218ポイント を手に入れた。
|
|
|
|
|
Name: ISLe ..上級者(15,212ポイント)
Date: 2010/08/26(木) 17:59
No:60182
|
|
Title: Re:POPUPウィンドウの消し方
|
|
> 「different thread」という表現。
palladiumさんがおっしゃっているハングアップの連鎖、いわゆるデッドロックは単一スレッドでも発生します。
デッドロックを避けるためにSendMessageとPostMessageを使い分けることは特別なことではないです。
今回のメインウインドウ枠のコントロールが一回目のクリックで効かないというのはShowWindowの副作用が原因ですのである種のデッドロックと考えられなくもないような気がします(弱気)。
ならばSendMessageの代わりにPostMessageを使うようにShowWindowAsyncを使って後回ししてもらうというのは常識の範囲というかしばしば使う手だと思います。
もちろん場合によってはメッセージ処理が遅延することによる影響を考慮する必要があります。
> ウィンドウは、生成したスレッドと紐付いてるんですね。
> メッセージキューはウィンドウに1つ存在する、ウィンドウが持ってる感じをイメージしてます。
後半は違いますよ。
メッセージキューもスレッドに対して1つです。
メッセージキューに溜まったメッセージをウインドウ(プロシージャ)に投げているのはメッセージループにあるDispatchMessage APIです。
> でもそういえば不思議です。「ShowWindowAsync がメッセージキューにポストする "a show-window event"」って何だ?と。WM_SHOWWINDOW とは違うようですし、(後略)
調べたところちゃんとWM_SHOWWINDOWがポストされていましたよ。
274ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..初心者(7,488ポイント)
Date: 2010/08/26(木) 20:19
No:60205
|
|
Title: Re:POPUPウィンドウの消し方
|
|
>palladiumさん
今までWindowsプログラミングの本は読んだことありませんでした。
MSDNとグーグル先生で何とかなるかな?と思ってて・・。
紹介いただいた本、amazonや紹介ブログなども見てみましたが高評価でした。
やはりネットだけでは得られないような情報がまとまっているのでしょうか。
他にも、GUIなら「プログラミングWindows」、Windowsの実装を追求したいなら
「インサイド Microsoft Windows」も揃えておくべき、なんていう人もいて・・。
こんど本屋さんで中身を見てみたいと思います。そして財布と相談します。(^^;
ありがとうございました!
>ISLeさん
なるほど・・。なんだか、単に自分が知らなかったから大げさに考えてしまった気もしてきました。
「デッドロックを避けるためにSendMessageとPostMessageを使い分け」は今まで遭遇したことがありませんし、
ShowWindowAsync も知らなかったし・・。今回 ShowWindowAsync を使う事は、別にトリッキーでもない、
APIを知ってればまあ普通、と思っておきたいと思います。
>メッセージキューもスレッドに対して1つです。
>メッセージキューに溜まったメッセージをウインドウ(プロシージャ)に投げているのはメッセージループにあるDispatchMessage APIです。
なんと、知りませんでした・・orz お恥ずかしい。ありがとうございました(><)
勘違いしたままおかしなコードを書いてきたかも、と思うと恐ろしいです。ひぇ。
>調べたところちゃんとWM_SHOWWINDOWがポストされていましたよ。
ぎゃーすみませんっ(><)
Web検索してチラッと見かけた「WM_SHOWWINDOWで消えないからShowWindowAsync使った」という話から
勝手に違うと思い込んでました。ダメですねちゃんと自分で確認しないと・・。
WM_SHOWWINDOW がポストされること確かめました。お手数おかけしました。m(_ _)m
ふと思い立ちやってみたのですが、
ShowWindow(hwnd,SW_HIDE) の代わりに SendMessage(hwnd,WM_SHOWWINDOW,0,1) を使ってもほぼ同じ。
ShowWindowAsync(hwnd,SW_HIDE) の代わりに PostMessage(hwnd,WM_SHOWWINDOW,0,1) を使ってもほぼ同じ。
※最後の引数1はよくわからないので適当
という結果になりました。
ただ、見た目の挙動は同じですが、ポップアップウィンドウに来るメッセージが微妙に異なりました。
SendMessage/PostMessageの方が、無駄に多くメッセージが来る?ような感じでした。
ふーん・・。いえ、だからどうという話もないです。
ShowWindow/ShowWindowAsyncを使っておきます。
それにしても、今回のスレッドでは本当に勉強させてもらいました!ありがとうございました!
932ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..初心者(5,847ポイント)
Date: 2010/08/27(金) 07:23
No:60253
|
|
Title: Re:POPUPウィンドウの消し方
|
|
一応コード載せておきます。
#include <windows.h>
#include <commctrl.h>
#pragma comment(lib, "comctl32.lib")
LRESULT CALLBACK PopupWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp );
LRESULT CALLBACK ChildWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp );
HWND hPopupWnd = NULL; // ポップアップウィンドウハンドル
HWND hTrackbar = NULL;
WNDPROC DefTrackbarProc; // トラックバー既定ウィンドウプロシージャ
// ポップアップウィンドウプロシージャ
LRESULT CALLBACK PopupWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
switch( msg ) {
case WM_ACTIVATE:
{
WORD fActive = LOWORD(wp);
if (fActive == WA_INACTIVE) {
ShowWindow(hwnd, SW_HIDE);
}
}
return 0;
}
return DefWindowProc( hwnd, msg, wp, lp );
}
// 操作パネルウィンドウプロシージャ
LRESULT CALLBACK ChildWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
POINT po;
switch( msg ) {
case WM_LBUTTONDOWN:
// パネル上でマウス押下した地点にトラックバーをポップアップ表示します
po.x = LOWORD( lp );
po.y = HIWORD( lp );
ClientToScreen( hwnd, &po );
MoveWindow( hPopupWnd, po.x, po.y, 150, 30, TRUE );
ShowWindow( hPopupWnd, SW_SHOW );
return 0;
}
return DefWindowProc( hwnd, msg, wp, lp );
}
// メインウィンドウプロシージャ
LRESULT CALLBACK MainWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
HINSTANCE hInst = GetModuleHandle(NULL);
switch( msg ) {
case WM_CREATE:
// 操作パネル(子)ウィンドウ作成
CreateWindowEx( 0, TEXT("ChildWindow"), TEXT("操作パネルのようなもの"),
WS_CHILD | WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, 300, 200, hwnd, (HMENU)NULL, hInst, NULL );
// ポップアップウィンドウ作成(親はメインウィンドウ)
hPopupWnd = CreateWindowEx( 0, TEXT("PopupWindow"), NULL,
WS_POPUP,
0, 0, 0, 0, hwnd, (HMENU)NULL, hInst, NULL );
// トラックバー作成(ポップアップウィンドウに乗せる)
hTrackbar = CreateWindowEx( 0, TRACKBAR_CLASS, NULL,
WS_CHILD | WS_VISIBLE,
0, 0, 150, 30, hPopupWnd, (HMENU)NULL, GetModuleHandle(NULL), NULL );
return 0;
case WM_DESTROY:
// アプリケーション終了
PostQuitMessage(0);
return 0;
}
return DefWindowProc( hwnd, msg, wp, lp );
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int nShowCmd )
{
MSG msg;
HWND hwnd;
WNDCLASSEX wc;
INITCOMMONCONTROLSEX ic;
// コモンコントロール初期化
ic.dwSize = sizeof(INITCOMMONCONTROLSEX);
ic.dwICC = ICC_BAR_CLASSES | ICC_TREEVIEW_CLASSES; // for ToolTip
InitCommonControlsEx( &ic );
// メインウィンドウクラス登録
SecureZeroMemory( &wc, sizeof(WNDCLASSEX) );
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = MainWindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH)( COLOR_APPWORKSPACE+1 );
wc.lpszClassName = TEXT("MainWindow");
if(!RegisterClassEx( &wc )){ return -1; }
// 子(操作パネル)ウィンドウクラス登録
wc.lpfnWndProc = ChildWindowProc;
wc.lpszClassName = TEXT("ChildWindow");
if(!RegisterClassEx( &wc )){ return -2; }
// ポップアップウィンドウクラス登録
wc.lpfnWndProc = PopupWindowProc;
wc.lpszClassName = TEXT("PopupWindow");
if(!RegisterClassEx( &wc )){ return -3; }
// メインウィンドウ作成
hwnd = CreateWindowEx( 0, TEXT("MainWindow"), TEXT("メインウィンドウ"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, (HMENU)NULL, hInstance, NULL );
if(!hwnd){ return -4; }
ShowWindow( hwnd, nShowCmd );
UpdateWindow( hwnd );
// メッセージループ
while( GetMessage( &msg, NULL, 0, 0 ) > 0 )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return (int)msg.wParam;
}
1,179ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..初心者(7,507ポイント)
Date: 2010/08/27(金) 10:05
No:60262
|
|
Title: Re:POPUPウィンドウの消し方
|
|
これは・・No:60025 のコード、ということでしょうか?
19ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..初心者(7,386ポイント)
Date: 2010/08/27(金) 10:36
No:60265
|
|
Title: Re:POPUPウィンドウの消し方
|
|
すみません貼り間違えました。
#include <windows.h>
#include <commctrl.h>
#pragma comment(lib, "comctl32.lib")
LRESULT CALLBACK PopupWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp );
LRESULT CALLBACK ChildWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp );
HWND hPopupWnd = NULL; // ポップアップウィンドウハンドル
HWND hTrackbar = NULL;
WNDPROC DefTrackbarProc; // トラックバー既定ウィンドウプロシージャ
// ポップアップウィンドウプロシージャ
LRESULT CALLBACK PopupWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
switch( msg ) {
case WM_ACTIVATE:
{
WORD fActive = LOWORD(wp);
if (fActive == WA_INACTIVE) {
ShowWindowAsync( hwnd, SW_HIDE ); // ■ ここ! ■
}
}
return 0;
}
return DefWindowProc( hwnd, msg, wp, lp );
}
// 操作パネルウィンドウプロシージャ
LRESULT CALLBACK ChildWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
POINT po;
switch( msg ) {
case WM_LBUTTONDOWN:
// パネル上でマウス押下した地点にトラックバーをポップアップ表示します
po.x = LOWORD( lp );
po.y = HIWORD( lp );
ClientToScreen( hwnd, &po );
MoveWindow( hPopupWnd, po.x, po.y, 150, 30, TRUE );
ShowWindow( hPopupWnd, SW_SHOW );
return 0;
}
return DefWindowProc( hwnd, msg, wp, lp );
}
// メインウィンドウプロシージャ
LRESULT CALLBACK MainWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
HINSTANCE hInst = GetModuleHandle(NULL);
switch( msg ) {
case WM_CREATE:
// 操作パネル(子)ウィンドウ作成
CreateWindowEx( 0, TEXT("ChildWindow"), TEXT("操作パネルのようなもの"),
WS_CHILD | WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, 300, 200, hwnd, (HMENU)NULL, hInst, NULL );
// ポップアップウィンドウ作成(親はメインウィンドウ)
hPopupWnd = CreateWindowEx( 0, TEXT("PopupWindow"), NULL,
WS_POPUP,
0, 0, 0, 0, hwnd, (HMENU)NULL, hInst, NULL );
// トラックバー作成(ポップアップウィンドウに乗せる)
hTrackbar = CreateWindowEx( 0, TRACKBAR_CLASS, NULL,
WS_CHILD | WS_VISIBLE,
0, 0, 150, 30, hPopupWnd, (HMENU)NULL, GetModuleHandle(NULL), NULL );
return 0;
case WM_DESTROY:
// アプリケーション終了
PostQuitMessage(0);
return 0;
}
return DefWindowProc( hwnd, msg, wp, lp );
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int nShowCmd )
{
MSG msg;
HWND hwnd;
WNDCLASSEX wc;
INITCOMMONCONTROLSEX ic;
// コモンコントロール初期化
ic.dwSize = sizeof(INITCOMMONCONTROLSEX);
ic.dwICC = ICC_BAR_CLASSES | ICC_TREEVIEW_CLASSES; // for ToolTip
InitCommonControlsEx( &ic );
// メインウィンドウクラス登録
SecureZeroMemory( &wc, sizeof(WNDCLASSEX) );
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = MainWindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH)( COLOR_APPWORKSPACE+1 );
wc.lpszClassName = TEXT("MainWindow");
if(!RegisterClassEx( &wc )){ return -1; }
// 子(操作パネル)ウィンドウクラス登録
wc.lpfnWndProc = ChildWindowProc;
wc.lpszClassName = TEXT("ChildWindow");
if(!RegisterClassEx( &wc )){ return -2; }
// ポップアップウィンドウクラス登録
wc.lpfnWndProc = PopupWindowProc;
wc.lpszClassName = TEXT("PopupWindow");
if(!RegisterClassEx( &wc )){ return -3; }
// メインウィンドウ作成
hwnd = CreateWindowEx( 0, TEXT("MainWindow"), TEXT("メインウィンドウ"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, (HMENU)NULL, hInstance, NULL );
if(!hwnd){ return -4; }
ShowWindow( hwnd, nShowCmd );
UpdateWindow( hwnd );
// メッセージループ
while( GetMessage( &msg, NULL, 0, 0 ) > 0 )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return (int)msg.wParam;
}
1,539ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..初心者(7,539ポイント)
Date: 2010/08/27(金) 10:43
No:60268
|
|
Title: Re:POPUPウィンドウの消し方
|
|
あ、最終的なコードですね。すみません私が貼るべきだったかも・・。ありがとうございました!
32ポイント を手に入れた。
|
|
|
|
|
Name: ISLe ..上級者(15,390ポイント)
Date: 2010/08/28(土) 02:45
No:60391
|
|
Title: Re:POPUPウィンドウの消し方
|
|
> case WM_LBUTTONDOWN:
> // パネル上でマウス押下した地点にトラックバーをポップアップ表示します
WM_LBUTTONDOWN→WM_LBUTTONUPをお勧めします。
あと余談ですが、MSのガイドラインではメッセージループに辿り着く前にプログラムを終了するときは戻り値を0にすべきとなっています。
#古い書籍のサンプルコードを見るとFALSEを返していたりしますが結果的に同じでも意味合いが違う。
特に不具合はないと思いますが、Windows7では互換性アシスタントが動き出したりするかもしれません。
WinMain
http://msdn.microsoft.com/ja-jp/library/cc364870.aspx
戻り値の欄を見てください。
DXライブラリのサンプルプログラムとか-1を返しているものを良く見かけますね。
178ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..初心者(8,009ポイント)
Date: 2010/08/28(土) 05:50
No:60395
|
|
Title: Re:POPUPウィンドウの消し方
|
|
PeekMessage
指定されたウィンドウを作成したスレッドに関連付けられているメッセージキューに、
1 つのメッセージをポストします
ShowWindowAsync
別のスレッドによって作成されたウィンドウの表示状態を設定します。
ShowWindowAsyncに関しては
「指定されたウィンドウ」ではなく
「別のスレッドによって作成されたウィンドウ」とはっきり書いてあるので
やはり使い方が適切でないと思います。
今まで問題なく作動していたとしても、それはたまたまそうなだけかもしれませんし、
今後ShowWindowAsyncの内部仕様が変更されないとも限りません。
なので私なら以下のようにします。
// ポップアップウィンドウプロシージャ
LRESULT CALLBACK PopupWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
switch( msg ) {
case WM_ACTIVATE:
{
WORD fActive = LOWORD(wp);
if ( fActive == WA_INACTIVE ) {
PostMessage( hwnd, WM_APP, 0, 0 );
}
}
return 0;
case WM_APP:
ShowWindow( hwnd, SW_HIDE );
return 0;
}
return DefWindowProc( hwnd, msg, wp, lp );
}
505ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..初心者(8,101ポイント)
Date: 2010/08/28(土) 06:10
No:60397
|
|
Title: Re:POPUPウィンドウの消し方
|
|
WinMainの戻り値についてですが0を返した場合
正常終了したことをシステムに伝えることになります。
a return code of zero means that the program completed successfully.
なのでプログラムが正常終了しない場合は0を返してはいけません。
92ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..初心者(8,181ポイント)
Date: 2010/08/28(土) 06:36
No:60398
|
|
Title: Re:POPUPウィンドウの消し方
|
|
WM_LBUTTONDOWNとWM_LBUTTONUPについては
WM_LBUTTONUPですとマウスを下押ししたまま
マウスをウィンドウの外へ移動した場合動作しません。
WM_LBUTTONUPにする場合はこの辺りを考慮すべきかもしれません。
80ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..初心者(7,744ポイント)
Date: 2010/08/28(土) 12:19
No:60409
|
|
Title: Re:POPUPウィンドウの消し方
|
|
WinMainの戻り値はあんまり深く考えたことがなかったです。
それくらいの、まあ大した問題でもないという面はあるでしょうか。(^^;
main関数のCUIコマンドのようなプログラムなら、OS側への通知と共に、戻り値を使った
他のプログラムとの連携という(プロセス間通信的な)わかりやすい用途がありますが、
WinMainの場合はそれは特にないですよねぇ・・よく知りませんが。
そうすると、OS側でWinMainの戻り値はどう扱われるのか?だけがポイントとなり、
その答えがMSDNの「メッセージループ前ならゼロを返せ」というガイドラインでしょうか。
エラーはMessageBox等で表示して、戻り値としてはゼロでよいと・・。
205ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..初心者(8,241ポイント)
Date: 2010/08/28(土) 12:35
No:60410
|
|
Title: Re:POPUPウィンドウの消し方
|
|
crtexe.c
に戻り値の扱いが書いてあります。
おそらく最終的には
crt0dat.c
の中の
ExitProcess(status); // status がWinMainの戻り値
で終了するのだと思います。
60ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..初心者(8,012ポイント)
Date: 2010/08/28(土) 12:47
No:60411
|
|
Title: Re:POPUPウィンドウの消し方
|
|
WM_LBUTTONDOWN と WM_LBUTTONUP の違いについては、好みの問題ですかね・・。
どっちのインタフェースが好きか?マウス押下する地点に何があるか?とか。
ただし WM_LBUTTONDOWN の「ポップアップ表示状態でクリックすると消える」動作は、
メッセージ発生到着順により「意図せずこうなった挙動」というのは覚えておかない
といかんなーと思ってます。ちゃんとコメント書いておく必要がありそうです。
事の発端となった私のへぼアプリでは、今のところ、WM_LBUTTONDOWN 相当の動作で
満足しています。というか、実は WM_LBUTTONDOWN では使っておらず、スタティック
テキストコントロールの WM_COMMAND 通知で使っており、どうも WM_LBUTTONDOWN 相当
の動作になってしまうようなのです・・。
268ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..初心者(8,096ポイント)
Date: 2010/08/28(土) 13:10
No:60412
|
|
Title: Re:POPUPウィンドウの消し方
|
|
WinMain の呼び出し部分のソースがあるんですね。ぜんぜん知りませんでした。。
crtexe.c や crt0dat.c って、検索しても私のPCには見当たらないのですが、
ひょっとして VC2008 Express Edition には入ってない代物でしょうか。
2倍のポイントを手に入れた! 84ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(206,405ポイント)
Date: 2010/08/28(土) 13:52
No:60414
|
|
Title: Re:POPUPウィンドウの消し方
|
|
>crtexe.c や crt0dat.c って、検索しても私のPCには見当たらないのですが、
>ひょっとして VC2008 Express Edition には入ってない代物でしょうか。
C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src
にソースコードがあるはずですが、Express Editionには無いかも知れません。

34ポイント を落としてしまった。
|
|
|
|
|
Name: たろ ..初心者(8,172ポイント)
Date: 2010/08/28(土) 15:21
No:60419
|
|
Title: Re:POPUPウィンドウの消し方
|
|
VC フォルダの中に crt フォルダが見当たりません。
crtexe で検索しても何もヒットしないし、無さそうです。うーん残念。
伝聞を鵜呑みにしてしまわないよう気を付けたいです。上でポカしてますが。(^^;
76ポイント を手に入れた。
|
|
|
|
|
Name: ISLe ..上級者(15,912ポイント)
Date: 2010/08/28(土) 23:11
No:60494
|
|
Title: Re:POPUPウィンドウの消し方
|
|
わたしの解釈はNo:60127に書いたとおりです。
> PeekMessage
> 指定されたウィンドウを作成したスレッドに関連付けられているメッセージキューに、
> 1 つのメッセージをポストします
PostMessage
http://msdn.microsoft.com/en-us/library/ms644944(VS.85).aspx
"Places (posts) a message in the message queue associated with the thread that created the
specified window and returns without waiting for the thread to process the message."
> ShowWindowAsync
> 別のスレッドによって作成されたウィンドウの表示状態を設定します。
ShowWindowAsync
http://msdn.microsoft.com/en-us/library/ms633549(VS.85).aspx
Sets the show state of a window created by a different thread.
PostMessageの表現をそのまま使うと"window"が被ってしまうのでそれを避けたために思いっ切り省略される形になったと推測します。
Remarksに同一スレッドからポストしたときの挙動について何も書いてないですし。
こんな古いAPIで挙動が不安定だったらかなり問題ですよね。
ShowWindowAsyncを嫌うにしてもたろさんがNo:60205で書いているようにWM_SHOWWINDOWをPostMessageで投げれば良いと思います。
--編集
横に長くなるので英文の途中に改行を入れました。 
293ポイント を手に入れた。
|
|
|
|
|
Name: ISLe ..上級者(16,092ポイント)
Date: 2010/08/28(土) 23:57
No:60500
|
|
Title: Re:POPUPウィンドウの消し方
|
|
> WinMainの戻り値についてですが0を返した場合
> 正常終了したことをシステムに伝えることになります。
> a return code of zero means that the program completed successfully.
> なのでプログラムが正常終了しない場合は0を返してはいけません。
WinMainから始まるプログラムをホスト環境とみなすのは無理があると思います。
WinMain Function
http://msdn.microsoft.com/en-us/library/ms633559(VS.85).aspx
WinMain
http://msdn.microsoft.com/ja-jp/library/cc364870.aspx
(引用開始)
戻り値
関数が WM_QUIT メッセージを受け取って正常に終了する場合は、メッセージの wParam パラメータに格納されている終了コードを返してください。関数がメッセージループに入る前に終了する場合は、0 を返してください。
(引用終了)
実験してみたのですが、WinMainでどんな戻り値を返そうとコマンドプロンプトには終了コードが0と返るようです。
WinMainから始まるプログラムの終了コードはCreateProcessして(WaitForSingleObjectで終了を待って)GetExitCodeProcessで取得する必要があると思います。
180ポイント を手に入れた。
|
|
|
|
|
Name: ISLe ..上級者(16,211ポイント)
Date: 2010/08/29(日) 00:19
No:60504
|
|
Title: Re:POPUPウィンドウの消し方
|
|
> WM_LBUTTONUPですとマウスを下押ししたまま
> マウスをウィンドウの外へ移動した場合動作しません。
>
> WM_LBUTTONUPにする場合はこの辺りを考慮すべきかもしれません。
ウインドウズのUIではそれがふつうですけど。
WM_LBUTTONDOWN→WM_LBUTTONUPのあいだにフォーカスが移動すると不具合が発生することがあるというのは既知なので避けたほうが無難だと思います。
例えばポップアップメニューを表示するTrackPopupMenuはデッドロックすることがあるのでWM_RBUTTONUPで表示すべきとされています。
どうしても押した瞬間に反応して欲しいというのであればメッセージをポストすれば良いかもしれません。
--追記
WM_LBUTTONDOWNでクリックした座標を記憶しておいてSetCapture、WM_LBUTTONUPで記憶しておいた場所に表示…というUIはかなり変ですね。 
119ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..初心者(8,482ポイント)
Date: 2010/08/29(日) 04:28
No:60511
|
|
Title: Re:POPUPウィンドウの消し方
|
|
>WinMainから始まるプログラムの終了コードはCreateProcessして(WaitForSingleObjectで終了を待って)GetExitCodeProcessで取得する必要があると思います。
MS自体が公開している終了処理コードではそのようなことはしていないようです。
62ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..初心者(8,738ポイント)
Date: 2010/08/29(日) 06:18
No:60515
|
|
Title: Re:POPUPウィンドウの消し方
|
|
というか、これはもう本件と直接関係ない話になってますね。
まさかWinMainの戻り値でUIがデッドロック起こすわけでもないでしょう。
自分の本音ですとWinMainの戻り値なんかどうでもよいと思ってます。
もちろんMSDNや自分なりにMSの終了処理コードなどを見た上でのことです。
SDKで開発している人にとってはWinMainの戻り値が0なんてことは常識ですが、
可読性の上でも0以外の値なら異常終了とすぐにわかると思います。
他のサイトの説明用コードでもよくあることですし、
スーパークラス系の書き方のところをチェックするには一番簡単な書き方かもしれません。
まあご存知でしょうがVCの出力ウィンドウをみれば自分の決めた戻り値が表示されるので
デバッグ作業も楽だと思いますよ。(コンソールの人、ごめんなさい)
それでも「絶対0にしろ」ってことであれば私はハングアップです。
256ポイント を手に入れた。
|
|
|
|
|
Name: ISLe ..上級者(16,542ポイント)
Date: 2010/08/29(日) 06:58
No:60519
|
|
Title: Re:POPUPウィンドウの消し方
|
|
> >WinMainから始まるプログラムの終了コードはCreateProcessして(WaitForSingleObjectで終了を待って)GetExitCodeProcessで取得する必要があると思います。
>
> MS自体が公開している終了処理コードではそのようなことはしていないようです。
ごめんなさい。
終了処理コードには違いがないようですね。
ウインドウアプリ(WinMain)とコンソールアプリ(main)では起動の仕方が違っていました。
実験手順が不足していたために偏った結論になってしまいました。
拡張機能(既定で有効)が有効なコマンドプロンプトのプロンプトからウインドウアプリを直接起動するとき、あるいはWAITオプション無しのstartコマンドからウインドウアプリ/コンソールアプリを起動するときはアプリの終了を待たずにプロンプトが復帰します。
このとき終了コードが取得できません(反映されません)でした。
アプリが終了するまで待たない呼び出し方をすると終了コードが取得できず(反映されず)、アプリが終了するまで待つ呼び出し方をすれば終了コードは取得できる(反映される)という至極当然の結果でした。
実験してて気付いたのですが、Visual C++って前から終了コードに8ビットのマスク掛けてませんでしたっけ。
#またまた余談ですみません。
exit、_exit
http://msdn.microsoft.com/ja-jp/library/6wdz5232.aspx
(引用開始)
status の下位バイトを利用できます。
(引用終了)
下位バイトって書いてあるのに32ビットまるまる返しているみたいなんですけど。
プログラムで-1を返しているのがバッチファイルでそのまま-1取れるとかダメじゃん。
#自分はもうずっとマイナス使わないようにしてたから気が付かなかっただけですか。
331ポイント を手に入れた。
|
|
|
|
|
Name: ISLe ..上級者(16,782ポイント)
Date: 2010/08/29(日) 07:41
No:60520
|
|
Title: Re:POPUPウィンドウの消し方
|
|
> というか、これはもう本件と直接関係ない話になってますね。
そうですね。最初に余談と断ってましたしね。
最初にMSDNのWinMainのページをリンクしてたんですが「正常終了しない場合は0を返してはいけません 」と断定されていたので再度引用したのが気に触りましたか。
気に触ったのなら申し訳ないです。
> まさかWinMainの戻り値でUIがデッドロック起こすわけでもないでしょう。
これはわざとミスリードしているのですか?
そんなことはどこにも書かれていませんね。
> 自分の本音ですとWinMainの戻り値なんかどうでもよいと思ってます。
> もちろんMSDNや自分なりにMSの終了処理コードなどを見た上でのことです。
> SDKで開発している人にとってはWinMainの戻り値が0なんてことは常識ですが、
> 可読性の上でも0以外の値なら異常終了とすぐにわかると思います。
> 他のサイトの説明用コードでもよくあることですし、
そのとおりで、余談として、良く見かけますね、と書きました。
> それでも「絶対0にしろ」ってことであれば私はハングアップです。
わたしが何か主張しましたでしょうか。
特に不具合は無いと思いますとも書いていますけども。
わたしが関知することではないですからpalladiumさんはご自由にWinMainの戻り値を決められれば良いと思います。
そのかわりではないですがわたしはShowWindowAsyncをShowWindowのポスト版として同一スレッドからも使い続けます。
240ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..初心者(8,471ポイント)
Date: 2010/08/29(日) 09:07
No:60527
|
|
Title: Re:POPUPウィンドウの消し方
|
|
もはや私の知恵ではまったく及びません。
興味深い余談でした。「あとは作る人がそれぞれ自分で決めればよい」という領域ですかね・・。
ちなみに私は「WM_LBUTTONDOWN→WM_LBUTTONUPのあいだにフォーカスが移動すると不具合が発生することがある」という話が気になりました。今回のポップアップ話は、確かに TrackPopupMenu と似てます。中身が違うだけみたいな。
どちらでもいけるようにしておきたいけど、STATICコントロールSS_NOTIFY+親WM_COMMAND だと、WM_LBUTTONUP 相当の検知は不可能・・。やりたかったらサブクラス化などで対応しましょうって話かな。うーんメッセージハンドラがどんどん増えていく・・そういうものなのか・・。
299ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..初心者(8,765ポイント)
Date: 2010/08/29(日) 10:03
No:60531
|
|
Title: Re:POPUPウィンドウの消し方
|
|
>わたしが何か主張しましたでしょうか。
まぁあれだけWinMainのリンク貼り付ければイヤミでしょ。
それはさておき
MSDNの場合はドキュメントと実際の動作が違うことはままありますよね。
(PostQuitMessageでWM_QUITが実際にはポストされていないなど)
それでここからはそのプログラマの判断になる場合もあるかと思いますが
建前のMSDNをとるか、実際の動作を利用するかになると思います。
ただ、何か問題が起きたときにはMSは建前を出してくる(使用法として)でしょうから
そこさえクリアできれば別に問題ないという考えもあるかもしれませんね。
27ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..中級者(9,260ポイント)
Date: 2010/08/29(日) 14:26
No:60557
|
|
Title: Re:POPUPウィンドウの消し方
|
|
本当は全部貼りたいですが著作権とかありそうなので雰囲気だけです
int WinMainCRTStartup(void)
{
.
.
.
static int mainret = WinMain(...)
if ( !managedapp )
exit(mainret); //a return code of zero means that the program completed successfully.
.
}
----------------------------------------------
void __cdecl exit( int code )
{
doexit( code, 0, 0 );
}
----------------------------------------------
static void __cdecl doexit( int code, int quick, int retcaller )
{
.
.
.
__crtExitProcess(code);
}
----------------------------------------------
void __cdecl __crtExitProcess( int status )
{
.
.
.
//プロセスの終了コードを取得するには、GetExitCodeProcess 関数を使います。
//スレッドの終了コードを取得するには、GetExitCodeThread function 関数を使います。
// んなことはMSやっちゃいない
ExitProcess(status);
}
495ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..中級者(9,553ポイント)
Date: 2010/08/29(日) 17:13
No:60577
|
|
Title: Re:POPUPウィンドウの消し方
|
|
>実験してて気付いたのですが、Visual C++って前から終了コードに8ビットのマスク掛けてませんでしたっけ。
#またまた余談ですみません。
exit、_exit
http://msdn.microsoft.com/ja-jp/library/6wdz5232.aspx
(引用開始)
status の下位バイトを利用できます。
(引用終了)
下位バイトって書いてあるのに32ビットまるまる返しているみたいなんですけど。
プログラムで-1を返しているのがバッチファイルでそのまま-1取れるとかダメじゃん。
#自分はもうずっとマイナス使わないようにしてたから気が付かなかっただけですか。
何かご不明な点があるようですが開発環境、実験内容等を明記の上、別スレでご質問なさったらいかがですか。
293ポイント を手に入れた。
|
|
|
|
|
Name: ISLe ..上級者(17,011ポイント)
Date: 2010/08/30(月) 00:16
No:60650
|
|
Title: Re:POPUPウィンドウの消し方
|
|
> >わたしが何か主張しましたでしょうか。
> まぁあれだけWinMainのリンク貼り付ければイヤミでしょ。
二回目の投稿をするのが「あれだけ」と言われるほどひどいことなのですね。
palladiumさんのNo:60397の投稿を見て完全にスルーされたと思いました。
かなりショックだったので読み易く投稿し直したつもりでした。
#わたしもスルー力を鍛える必要がありますね。
> それはさておき
> MSDNの場合はドキュメントと実際の動作が違うことはままありますよね。
> (PostQuitMessageでWM_QUITが実際にはポストされていないなど)
ウインドウプロシージャに届いかないからポストされていないということですか?
GetMessageやPeekMessageでメッセージキューからWM_QUITを取り出したらメッセージループを抜けるようにコーディングしてますよね。
DispatchMessageが実行されないのでウインドウプロシージャには投げられないですけど、GetMessageやPeekMessageに与えたMSG構造体の引数にはWM_QUITが入ってきますけど。
解説願えますか?
--誤字とちょっと表現を訂正 
229ポイント を手に入れた。
|
|
|
|
|
Name: ISLe ..上級者(17,156ポイント)
Date: 2010/08/30(月) 00:32
No:60651
|
|
Title: Re:POPUPウィンドウの消し方
|
|
> 何かご不明な点があるようですが開発環境、実験内容等を明記の上、別スレでご質問なさったらいかがですか。
リンク先がVisual C++ 2010のページなので、開発環境は明示しなくても良いと思ってしまいました。
開発環境はVisual C++ 2010です。2008でも確認しました。
> #自分はもうずっとマイナス使わないようにしてたから気が付かなかっただけですか。
と書いたようにわたし自身は既に何も困っていません。
ホスト環境で負の数(正確には下位8ビット以外のビットが有効な値)を戻り値としたときに移植性が損なわれる要因が見付かったことを紹介させていただきました。
はっきり言いますとpalladiumさんのソースファイルをVCでコンパイルしたときとgccでコンパイルしたときで実行ファイルの戻り値が変化してしまうということです。
余計なことでしたね。
--編集
WinMainから始まるウインドウズアプリでもgcc(cygwin版)でコンパイルすると戻り値が下位8ビットでマスクされるのを確認。

145ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..中級者(9,578ポイント)
Date: 2010/08/30(月) 02:04
No:60656
|
|
Title: Re:POPUPウィンドウの消し方
|
|
>解説願えますか?
Advanced Windows 改訂第4版 Jeffrey Richter著の第26章をお調べください。
25ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..中級者(9,610ポイント)
Date: 2010/08/30(月) 03:18
No:60658
|
|
Title: Re:POPUPウィンドウの消し方
|
|
補足
アプリケーションのメッセージキューにはもちろんポストされています。
システムキューにはポストされないということです。
2倍のポイントを手に入れた! 32ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..中級者(9,758ポイント)
Date: 2010/08/30(月) 04:34
No:60660
|
|
Title: Re:POPUPウィンドウの消し方
|
|
「余談」から本件に直接関係ない「実験」とかに発展してしまうと
本件がだんだんぼけてくるので差し控えていただけませんか。
何かテーマをお持ちでしたら別スレでお願いしたいものです。
(PostQuitMessageでWM_QUITが実際にはポストされていないなど)
これについてはまた発展しちゃうといけないのでお忘れください。
148ポイント を手に入れた。
|
|
|
|
|
Name: ISLe ..上級者(17,656ポイント)
Date: 2010/08/30(月) 05:40
No:60661
|
|
Title: Re:POPUPウィンドウの消し方
|
|
> 「余談」から本件に直接関係ない「実験」とかに発展してしまうと
> 本件がだんだんぼけてくるので差し控えていただけませんか。
自分が投稿する内容や他の方が書いたコードは勉強のために検証して気になることがあればコメントしてきました。
#検証の仕方をミスることが少なくないのは申し訳ないです。
> (PostQuitMessageでWM_QUITが実際にはポストされていないなど)
> これについてはまた発展しちゃうといけないのでお忘れください。
検証した内容は既にNo:60650に書いてますので。
ふるまいはMSDNに書かれているとおりのような気がします。
余談も実験も禁止ということは、ルートの質問に回答だけしてろということですね。
了解しました。
本件がぼけるということであればプログラミングの質問にそのジャンルのゲーム関連ネタを振るのも禁止ですよね。
他のスレですがひとつだけネタふりさせてください。
それで最後にします。
2倍のポイントを手に入れた! 500ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..中級者(9,879ポイント)
Date: 2010/08/30(月) 05:44
No:60662
|
|
Title: Re:POPUPウィンドウの消し方
|
|
>たろさまへ
>実は WM_LBUTTONDOWN では使っておらず、スタティック
テキストコントロールの WM_COMMAND 通知で使っており、どうも WM_LBUTTONDOWN 相当
の動作になってしまうようなのです・・。
このあたりですが、もうすこし詳しい仕様をお願いできますか。
121ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..中級者(9,290ポイント)
Date: 2010/08/30(月) 13:19
No:60684
|
|
Title: Re:POPUPウィンドウの消し方
|
|
えっと・・なんだか残念で悲しい気持ちでいっぱいです・・。
私のコメント方法にも要因があるのか・・わかりませんが、
ネットのコミュニケーションの難しさを改めて感じます。
できるだけ言葉を選びながら書きます。
余談について、今回コメント頂いたくらいの内容なら私は全く気になりません。
むしろ有り難かったです。余談で盛り上がるのも楽しいし、得ることは多いと思います。
問題は、「自分の考えの表現方法」と「自分と対立する考えの受け流し」ですかね・・。
私はコメント書く時「事実以外に断定的な表現を使わない」ように気をつけます。
例えば、MSDNからの引用は「事実」として断定的に書きますが、「だからこうすべき」
という"解釈"には、必ず「〜と思う・〜と考える」等を付けるようにします。
そして人のコメントを読む時、「この人は事実じゃない事を断定して書いている」と
判断した場合は、脳内で勝手に「〜と思う」を付け加えて読みます。
尖ったものが少し丸くなる感覚があります。
自分と対立する考え方の受け流し、まあいわゆる「スルー」ですが、難しいですね・・
我慢できるかどうか、無視できるかどうか、しかないのかな・・。
私は、スルーするのはけっこう得意です・・というか、臆病なのですぐ逃げます。(^^;
なんだか取り留めのない独り言になってきた。。
ISLeさん、palladiumさん、本題から余談までとても勉強になりました。お世話になりました。
お2人とも博識ですね。今後のご活躍も期待しております。
続きで失礼しますが、
>>実は WM_LBUTTONDOWN では使っておらず、スタティック
>>テキストコントロールの WM_COMMAND 通知で使っており、どうも WM_LBUTTONDOWN 相当
>>の動作になってしまうようなのです・・。
>
>このあたりですが、もうすこし詳しい仕様をお願いできますか。
お気遣いありがとうございます。m(_ _)m
ええと・・実はこの話を出したのは、何かちょっと危険な空気を感じたからかも知れません。。
まだ自分でいろいろ試したり確認しておらず、中途半端な状態です。
いろいろやってみて、どうしてもダメだったら、また新しく質問させて頂きたいと思います。
ひとまずお忘れください。
「POPUPウィンドウの消し方」としては、私は解決終了と思ってます。ありがとうございました。 
819ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(210,625ポイント)
Date: 2010/08/30(月) 13:39
No:60685
|
|
Title: Re:POPUPウィンドウの消し方
|
|
横から失礼しますね。
とりあえず、たろさんに落ち度はないですよ。
管理人さんの規約と注意事項にあります通り「目指すはアットホームで温かい」がスローガンですのでその趣旨に沿っていただけるとありがたいです。
多少雑談が交じるのはこの掲示板の常ですので質問者さんが困らない&混乱しない限り、そして質問者さんが止めて欲しいとお願いしない限り、質問者さんの経験とプラスに成るなら問題ないと私は考えます。
もし、別スレ分けが必要だとお感じでしたら穏やかに提案なさってください。
49ポイント を手に入れた。
|
|
|
|
|
Name: palladium ..中級者(9,921ポイント)
Date: 2010/08/30(月) 14:23
No:60689
|
|
Title: Re:POPUPウィンドウの消し方
|
|
1質問1トピと思い、
必要に応じ他にスレを立てることをお勧めしたつもりですが、
私に非があるようなら御容赦下さい。
申し訳ございませんでした。
42ポイント を手に入れた。
|
|
|
|
|
Name: ISLe ..上級者(17,662ポイント)
Date: 2010/09/01(水) 04:28
No:60757
|
|
Title: Re:POPUPウィンドウの消し方
|
|
たろさんへ
表示するときもPost系APIを使うと幸せになれるかもしれません。
WM_LBUTTONDOWNでの動作確認は取れてます。
気にしないでください。
38ポイント を手に入れた。
|
|
|
|
|
Name: たろ ..中級者(9,837ポイント)
Date: 2010/09/01(水) 09:25
No:60758
|
|
Title: Re:POPUPウィンドウの消し方
|
|
あ、はい、実はすでに試してみました。お気遣いありがとうございます。
28ポイント を手に入れた。
|
|
|
|
Name: sin ..ぴよぴよ(881ポイント)
Date: 2010/08/29(日) 18:35
No:60579
|
|
Title: 描写したものに別の画像を合わせる
|
|
はじめましてsinと言います。
field.cppでマップを描写し、その後、cursor.cppでカーソルを作成し、先ほど描写したマップにカーソルを表示したいのですがmain.cppをデバッグすると、真っ暗な画面にカーソルのみが表示されます。
どのあたりを改善すればいいのでしょうか。
Microsoft Visual C++で作成しています。
97ポイント を手に入れた。
|
|
|
|
Name: sin ..入門者(4,285ポイント)
Date: 2010/08/29(日) 18:36
No:60580
|
|
Title: Re:描写したものに別の画像を合わせる
|
|
---main.cpp--------------------------------------------------------------------------
#define _GLOBAL_INSTANCE_
#include "DxLib.h"
#include "GV.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
char Key[256];
int Sound ;
if( SetOutApplicationLogValidFlag(FALSE) || ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() || SetWindowSizeExtendRate(1.0)) return -1;//ウィンドウモード
SetDrawScreen( DX_SCREEN_BACK );
Sound = LoadSoundMem( "my turn.mp3" ); //mp3ファイルを読み込み、ハンドルをint型変数格納
PlaySoundMem( Sound , DX_PLAYTYPE_BACK );//バックグラウンド再生
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
map_graph();
cursor();
ScreenFlip();
}
DxLib_End();
return 0;
}
---field.cpp----------------------------------------------------------------------------------
#include "DxLib.h"
#include "GV.h"
void map_graph(){//マップの描画
int i,j;
int sea[16],sougen[16];
int hantei[15][20] = {
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
{ 1,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1 },
{ 1,0,0,0,0,0,1,1,1,1,0,1,1,0,0,0,0,0,0,1 },
{ 1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1 },
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 },
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1 },
{ 1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1 },
{ 1,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,1 },
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1 },
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1 },
{ 1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1 },
{ 1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1 },
{ 1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1 },
{ 1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
};
LoadDivGraph( "char.sea.png" , 16 , 4 , 4 , 32 , 32 , sea ) ;//画像を分割してsea配列に保存
LoadDivGraph( "char.sougen.png" , 16 , 4 , 4 , 32 , 32 , sougen ) ;//画像を分割してsougen配列に保存
/*mapを描画*/
for(i=0;i<15;i++){
for(j=0;j<20;j++){
if(hantei[i][j]==1){
DrawGraph( j*32 , i*32 , sea[0] , TRUE ) ;//sea[0]の画像を描画
}
if(hantei[i][j]==0){
DrawGraph( j*32 , i*32 , sougen[0] ,TRUE ) ;//sougen[0]
}
}
}
return;
}
2倍のポイントを手に入れた! 3,404ポイント を手に入れた。
|
|
|
|
|
Name: sin ..入門者(4,886ポイント)
Date: 2010/08/29(日) 18:37
No:60581
|
|
Title: Re:描写したものに別の画像を合わせる
|
|
---cursor.cpp-------------------------------------------------------------------------------
#include "DxLib.h"
#include "GV.h"
typedef struct{
int x,y,muki,moving_flag;
}cursor_t;
int hantei[15][20] = {
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
{ 1,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1 },
{ 1,0,0,0,0,0,1,1,1,1,0,1,1,0,0,0,0,0,0,1 },
{ 1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1 },
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 },
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1 },
{ 1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1 },
{ 1,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,1 },
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1 },
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1 },
{ 1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1 },
{ 1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1 },
{ 1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1 },
{ 1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
};
int can_or_cannot(int x,int y,int muki){//進めるかを判定する
if(muki==0)//上向きなら
if(hantei[y/32-1][x/32]==1)//進めるか判定
return 1;//エラー
if(muki==1)//左向きなら
if(hantei[y/32][x/32-1]==1)
return 1;
if(muki==2)//下向きなら
if(hantei[y/32+1][x/32]==1)
return 1;
if(muki==3)//右向きなら
if(hantei[y/32][x/32+1]==1)
return 1;
return 0;//正常
}
void cursor(){
char Key[256];
cursor_t cursor;
cursor.x =320;
cursor.y =160;
cursor.moving_flag=0;
cursor.muki=3;
SetDrawScreen( DX_SCREEN_BACK ) ;
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
if(cursor.x%32==0 && cursor.y%32==0){ //座標が32で割り切れたら入力可能
cursor.moving_flag=1; //歩くフラグを立てる。
if ( Key[ KEY_INPUT_UP ] == 1 ) //上ボタンが押されたら
cursor.muki=0; //上向きフラグを立てる
else if( Key[ KEY_INPUT_LEFT ] == 1 ) //左ボタンが押されたら
cursor.muki=1; //左向きフラグを立てる
else if( Key[ KEY_INPUT_DOWN ] == 1 ) //下ボタンが押されたら
cursor.muki=2; //下向きフラグを立てる
else if( Key[ KEY_INPUT_RIGHT] == 1 ) //右ボタンが押されたら
cursor.muki=3; //右向きフラグを立てる
else //何のボタンも押されてなかったら
cursor.moving_flag=0; //歩かないフラグを立てる
if(cursor.moving_flag==1) //もし歩くなら
if(can_or_cannot(cursor.x,cursor.y,cursor.muki)==1)//行き先が歩けないなら
cursor.moving_flag=0; //歩かないフラグを立てる。
}
if(cursor.moving_flag==1){ //歩くフラグが立っていたら
if (cursor.muki==0) //上向きならch.y座標を減らす
cursor.y--;
else if(cursor.muki==1) //左向きならch.x座標を減らす
cursor.x--;
else if(cursor.muki==2) //下向きならch.y座標を増やす
cursor.y++;
else if(cursor.muki==3) //右向きならch.x座標を増やす
cursor.x++;
}
LoadGraphScreen( cursor.x , cursor.y , "char.cursor.png" , TRUE ) ;
ScreenFlip();
}
return ;
}
601ポイント を手に入れた。
|
|
|
|
|
Name: 迷彩吹雪 ..入門者(2,604ポイント)
Date: 2010/08/29(日) 18:50
No:60583
|
|
Title: Re:描写したものに別の画像を合わせる
|
|
void map_graph()関数に描画の処理が含まれていないように見受けられます。
また、WinMain()関数だけでなくvoid cursor()関数にもメインループがあるので、そこで処理が回り続けているのではないでしょうか。
74ポイント を手に入れた。
|
|
|
|
|
Name: sin ..初心者(5,169ポイント)
Date: 2010/08/29(日) 19:50
No:60595
|
|
Title: Re:描写したものに別の画像を合わせる
|
|
cursor.cpp内の
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
を
while(!ProcessMessage() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
に変更したところmap_graph()で描写した背景にカーソルを合わせることが出来ましたが、カーソルの残像が残るようになりました。
残像を消すにはcursor.cpp内を
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
に戻して
cursor.cpp内にmap_graph()を入れたほうがいいのでしょうか。
それともmain.cpp内で処理をするようにした方がいいのでしょうか。(cursor.cppではカーソルの位置だけを調べてカーソルの位置を返すようにする。)
283ポイント を手に入れた。
|
|
|
|
|
Name: 迷彩吹雪 ..入門者(3,768ポイント)
Date: 2010/08/29(日) 20:49
No:60616
|
|
Title: Re:描写したものに別の画像を合わせる
|
|
そもそもvoid cursor()関数内のwhile文は不要でしょう。
cursor.cppでカーソルの描画まで行っても問題ありません。問題は、そこで無限ループが回っていることなのです。
そうですね、void cursor()関数の処理を以下のものに置き換えてみてはどうでしょうか。
(動く保証はありませんが……。)
//ループが回る度に初期化されてしまうので、グローバルに置きました
char Key[256];
cursor_t cursor;
cursor.x =320;
cursor.y =160;
cursor.moving_flag=0;
cursor.muki=3;
void cursor(){
GetHitKeyStateAll( Key ); //ここで入力状態を更新します
//SetDrawScreen( DX_SCREEN_BACK ) ; //WinMain()で既に呼んでいるので不要です
//ここにあったwhile文を消しました
if(cursor.x%32==0 && cursor.y%32==0){ //座標が32で割り切れたら入力可能
cursor.moving_flag=1; //歩くフラグを立てる。
if ( Key[ KEY_INPUT_UP ] == 1 ) //上ボタンが押されたら
cursor.muki=0; //上向きフラグを立てる
else if( Key[ KEY_INPUT_LEFT ] == 1 ) //左ボタンが押されたら
cursor.muki=1; //左向きフラグを立てる
else if( Key[ KEY_INPUT_DOWN ] == 1 ) //下ボタンが押されたら
cursor.muki=2; //下向きフラグを立てる
else if( Key[ KEY_INPUT_RIGHT] == 1 ) //右ボタンが押されたら
cursor.muki=3; //右向きフラグを立てる
else //何のボタンも押されてなかったら
cursor.moving_flag=0; //歩かないフラグを立てる
if(cursor.moving_flag==1) //もし歩くなら
if(can_or_cannot(cursor.x,cursor.y,cursor.muki)==1)//行き先が歩けないなら
cursor.moving_flag=0; //歩かないフラグを立てる。
}
if(cursor.moving_flag==1){ //歩くフラグが立っていたら
if (cursor.muki==0) //上向きならch.y座標を減らす
cursor.y--;
else if(cursor.muki==1) //左向きならch.x座標を減らす
cursor.x--;
else if(cursor.muki==2) //下向きならch.y座標を増やす
cursor.y++;
else if(cursor.muki==3) //右向きならch.x座標を増やす
cursor.x++;
LoadGraphScreen( cursor.x , cursor.y , "char.cursor.png" , TRUE ) ; //本来はLoadGraph()などで一度だけ画像を読むべきです
}
765ポイント を手に入れた。
|
|
|
|
|
Name: sin ..初心者(6,391ポイント)
Date: 2010/08/30(月) 10:39
No:60672
|
|
Title: Re:描写したものに別の画像を合わせる
|
|
迷彩吹雪さんありがとうございます。
グローバル変数に移す理由は分かったのですが、どのように移せばいいのかわかりません。(グローバル変数の書き方)
そのまま書いてもエラーがでてしまいます。
void cursor(){
//----------------------------------------------------------------------------
char Key[256]; // ↑
cursor_t cursor;
//この部分をグローバル変数に移す
cursor.x=320;
cursor.y=160;
cursor.moving_flag=0; // ↓
cursor.muki=3;
//----------------------------------------------------------------------------
GetHitKeyStateAll( Key );
if(cursor.x%32==0 && cursor.y%32==0){ //座標が32で割り切れたら入力可能
cursor.moving_flag=1; //歩くフラグを立てる。
if ( Key[ KEY_INPUT_UP ] == 1 ) //上ボタンが押されたら
cursor.muki=0; //上向きフラグを立てる
else if( Key[ KEY_INPUT_LEFT ] == 1 ) //左ボタンが押されたら
cursor.muki=1; //左向きフラグを立てる
else if( Key[ KEY_INPUT_DOWN ] == 1 ) //下ボタンが押されたら
cursor.muki=2; //下向きフラグを立てる
else if( Key[ KEY_INPUT_RIGHT] == 1 ) //右ボタンが押されたら
cursor.muki=3; //右向きフラグを立てる
else //何のボタンも押されてなかったら
cursor.moving_flag=0; //歩かないフラグを立てる
if(cursor.moving_flag==1) //もし歩くなら
if(can_or_cannot(cursor.x,cursor.y,cursor.muki)==1)//行き先が歩けないなら
cursor.moving_flag=0; //歩かないフラグを立てる。
}
if(cursor.moving_flag==1){ //歩くフラグが立っていたら
if (cursor.muki==0) //上向きならch.y座標を減らす
cursor.y--;
else if(cursor.muki==1) //左向きならch.x座標を減らす
cursor.x--;
else if(cursor.muki==2) //下向きならch.y座標を増やす
cursor.y++;
else if(cursor.muki==3) //右向きならch.x座標を増やす
cursor.x++;
}
LoadGraphScreen( cursor.x , cursor.y , "char.cursor.png" , TRUE ) ;
}
1,222ポイント を手に入れた。
|
|
|
|
|
Name: 迷彩吹雪 ..入門者(3,970ポイント)
Date: 2010/08/30(月) 11:59
No:60677
|
|
Title: Re:描写したものに別の画像を合わせる
|
|
>どのように移せばいいのかわかりません。(グローバル変数の書き方)
関数の外(ファイルの先頭など)で宣言すればグローバル変数になると思いますが……。
>そのまま書いてもエラーがでてしまいます。
私が示した通りに書き変えてもエラーになる、と言うことでしょうか。
「この部分をグローバル変数に移す」と示してある部分をvoid cursor()関数の定義以前に移動して、それでエラーが出たのでしょうか。
エラーの内容を詳しく教えてもらえますか?
(コンパイルエラーなのか、警告文が出たなら何と出たのか)
157ポイント を手に入れた。
|
|
|
|
|
Name: sin ..初心者(6,653ポイント)
Date: 2010/08/30(月) 12:29
No:60681
|
|
Title: Re:描写したものに別の画像を合わせる
|
|
すいません。わかりにくかったですね。
//------------------------------------------------------------------------------------
char Key[256];
cursor_t cursor;
cursor.x=320;
cursor.y=160;
cursor.moving_flag=0;
cursor.muki=3;
void cursor(){
GetHitKeyStateAll( Key );
if(cursor.x%32==0 && cursor.y%32==0){ //座標が32で割り切れたら入力可能
cursor.moving_flag=1; //歩くフラグを立てる。
if ( Key[ KEY_INPUT_UP ] == 1 ) //上ボタンが押されたら
cursor.muki=0; //上向きフラグを立てる
else if( Key[ KEY_INPUT_LEFT ] == 1 ) //左ボタンが押されたら
cursor.muki=1; //左向きフラグを立てる
else if( Key[ KEY_INPUT_DOWN ] == 1 ) //下ボタンが押されたら
cursor.muki=2; //下向きフラグを立てる
else if( Key[ KEY_INPUT_RIGHT] == 1 ) //右ボタンが押されたら
cursor.muki=3; //右向きフラグを立てる
else //何のボタンも押されてなかったら
cursor.moving_flag=0; //歩かないフラグを立てる
if(cursor.moving_flag==1) //もし歩くなら
if(can_or_cannot(cursor.x,cursor.y,cursor.muki)==1)//行き先が歩けないなら
cursor.moving_flag=0; //歩かないフラグを立てる。
}
後は同じです。
//-------------------------------------------------------
↑のように変更しました。
構文エラー : ';' が '.' の前にありません。
型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
'cursor' : 再定義されています。異なる基本型です。
'cursor' の宣言を確認してください。
といったエラーが表示されます。
262ポイント を手に入れた。
|
|
|
|
|
Name: shuto ..かけだし(2,128ポイント)
Date: 2010/08/30(月) 12:53
No:60682
|
|
Title: Re:描写したものに別の画像を合わせる
|
|
関数外で値を入れているのが原因ではないでしょうか?
初期化と代入は別のものです。
そのやり方なら初期化を行う関数を作り 最初に呼ぶといいと思います。
むしろ、キャラの座標をグローバルにするのはどうなんだろうを思いますが・・・
-----------
グローバル変数を関数で初期化するって表現がなんかおかしいですねw
とりあえず
cursor.x=320;
cursor.y=160;
cursor.moving_flag=0;
cursor.muki=3;
の書く場所を考えるといいです。 
80ポイント を手に入れた。
|
|
|
|
|
Name: 迷彩吹雪 ..入門者(4,095ポイント)
Date: 2010/08/30(月) 18:47
No:60705
|
|
Title: Re:描写したものに別の画像を合わせる
|
|
あ、確かに代入してますね。
「とりあえず動くようにしよう」と思って深く考えずにグローバルに移動させてました。
cursorを宣言する時に初期化してしまえば良いのかな。
トピックの主題ではないし間違えた責任もあるので……
cursor_t cursor = {320, 160, 3, 0};
これで、どうでしょう。
(構造体はほとんど扱ったことがないので自信はないですww)
125ポイント を手に入れた。
|
|
|
|
|
Name: sin ..初心者(7,366ポイント)
Date: 2010/08/31(火) 08:15
No:60737
|
|
Title: Re:描写したものに別の画像を合わせる
|
|
main.cppで構造体の初期化をし、cursor.cppで構造体を呼び出すようにしたのですがカーソルが動きません。(一瞬動くがすぐに元の位置に戻る。)
理由としてmain.cppでcursor()を呼び出して値を変更しているが、ループ(main内)で上書きされていることが原因だと思うのですが、どうすればいいですか?
---main.cpp---------------------------------------------------------------
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
char Key[256];
int Sound ;
int i;
i=0;
if( SetOutApplicationLogValidFlag(FALSE) || ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() || SetWindowSizeExtendRate(1.0)) return -1;//ウィンドウモード
SetDrawScreen( DX_SCREEN_BACK );
struct cursor_t curs= {320, 160, 3, 0};
Sound = LoadSoundMem( "my turn.mp3" ); //mp3ファイルを読み込み、ハンドルをint型変数へ格納
PlaySoundMem( Sound , DX_PLAYTYPE_BACK );//バックグラウンド再生
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
map_graph();
char_graph();
cursor(curs);
ScreenFlip();
}
DxLib_End();
return 0;
}
---cursor.cpp------------------------------------------------------------------------------------
void cursor(struct cursor_t curs){
char Key[256];
GetHitKeyStateAll( Key );
後は同じです
--------------------------------------------------------------------------------------------------
713ポイント を手に入れた。
|
|
|
|
|
Name: shuto ..かけだし(2,356ポイント)
Date: 2010/08/31(火) 08:50
No:60738
|
|
Title: Re:描写したものに別の画像を合わせる
|
|
ループ内に上書きをしているところはないように見えますが・・・どこでそう思ったのでしょう?
上書きしているわけではなく、cursの内容を変更できていませんね。
値渡しと参照渡しの違い、実引数、仮引数は理解できていますか?
わからなければ調べてみてから読んでください。
その void corsor の書き方ですと実引数の struct cursor_t 型の cursをコピーして
関数 void cursor(struct cursor_t curs) の仮引数 curs にコピーされます。
コピーされた curs に対して cursor関数で座標が計算されますので移動はできます。
しかし、コピーに対しての計算なのでmainのなかの curs には影響しません。
これを改善するために参照渡しを使います。
実引数を(&curs)としてアドレスを渡し
cursor関数では仮引数を(struct cursor_t* curs)としてアドレスを受け取ります。
構造体へのポインタからののメンバへのアクセスは . ではなく -> を使います。
つまり curs.moving_flag は curs->moving_flag になります。
こうすればcursor関数の中で curs 自体を変更できます。
228ポイント を手に入れた。
|
|
|
|
|
Name: naohiro19 ..ぴよぴよ(959ポイント)
Date: 2010/08/31(火) 10:57
No:60740
|
|
Title: Re:描写したものに別の画像を合わせる
|
|
typedef stuct cursor_tag {
int x,y; //位置
int moving_flag; //移動可能かどうか
int direction; //向き
}cursor;
typedef を使うといいですよ。
10ポイント を手に入れた。
|
|
|
|
|
Name: sin ..初心者(7,312ポイント)
Date: 2010/08/31(火) 15:28
No:60747
| 解決!
|
Title: Re:描写したものに別の画像を合わせる
|
|
shutoさんの助言を参考に参照渡しに変更したところカーソルが動くようになりました。
皆さんありがとうございました。
54ポイント を落としてしまった。
|
|
|
|
Name: tuya ..ぴよぴよ(206ポイント)
Date: 2010/08/31(火) 11:48
No:60742
|
|
Title: キャラクターに時間内を滑るように移動をさせたい
|
|
はじめまして、いつもお世話になっております。
左右どちらでもいいのでキーを押します。
キーを押している間は通常移動をさせて
キーを放した後、滑る時間を利用してキャラクターを滑らせたいと思っています。
//*_ キャラクターの初期位置及び滑る時間
int x = 320;
int y = 240;
int vx = 0;
float speed = 0.1f;
int slip_time = 30;
int SlipTime = 0;
char KeyBuf[ 256 ] ;
//*_ 滑る時間が0以上あるなら,時間を減らす
if(SlipTime > 0)
{
SlipTime--;
//*_ 時間が0を下回ったら,時間を0にする
if(SlipTime <= 0) SlipTime = 0;
}
//*_ 滑っていなければ
else
{
// キー入力のあと,SlipTime にsliptimeを入れる
if(KeyBuf[KEY_INPUT_LEFT] == 1) SlipTime = slip_time;
// ここからvxにspeedをどのように入れるかが分かりません
}
// vxをキャラクターのxに加算する
x +=vx;
// はみ出し処理
if(x < 0) x =0;
if(x > 640-32) x = 640-32;
//*_ キャラクター
DrawBox(x,y,x+32,y+32,GetColor(0,0,255),TRUE) ;
滑る時間までは書けますがその後のキー入力の部分がうまく書けません。
説明下手で申し訳ありませんが
ご教授頂けないでしょうか?よろしくお願いいたします。
206ポイント を手に入れた。
|
|
|
|
Name: へろり ..プログラマー(32,889ポイント)
Date: 2010/08/31(火) 12:11
No:60743
|
|
Title: Re:キャラクターに時間内を滑るように移動をさせたい
|
|
質問の意味が今ひとつ分かりません。
それら一連の処理がどのように呼ばれるのか分からないので何とも言えないのですが。
ざらっと見た感じ、1秒間にン十回と呼ばれるっぽいですね。
とりあえず通常移動時の処理を書きたいということでしょうか。
正直なところ、なんでもいいんじゃないですか?
vx = speed * 10; でもいいし。 vx = speed * 20; でもいいし。
ただ、変数vxはint型ですから、結局少数以下は丸められますので、vx++; でもいいかと。
滑っている間の移動が行われていないのは仕様ですか?
それとこれらの処理がフレーム毎等1秒間にン十回と呼ばれるのであれば、
if(KeyBuf[KEY_INPUT_LEFT] == 1) の条件を満たした瞬間問答無用で滑ると思うのですが、これも仕様ですか?
とりあえず一連の状態遷移を紙に書いてみるといいですよ。 後は細かいパラメータの調整ですみますから。
2倍のポイントを手に入れた! 784ポイント を手に入れた。
|
|
|
|
|
Name: シエル [URL] ..熟練のプログラマー(67,244ポイント)
Date: 2010/08/31(火) 12:39
No:60745
|
|
Title: Re:キャラクターに時間内を滑るように移動をさせたい
|
|
はいどうぞ。一瞬で作ったから、まともな形にして使ってください。
#include "DxLib.h"
//
/*********************** メイン ****************************/
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
if(ChangeWindowMode(TRUE)||DxLib_Init()||SetDrawScreen(DX_SCREEN_BACK))return -1;
int x = 320;
int y = 240;
int vx =4 ;
float speed = 0.1f;
int slip_time = 20;
int SlipTime = 0;
char KeyBuf[ 256 ] ;
int flag=3;
while(!ScreenFlip()&&!ProcessMessage()&&!ClearDrawScreen()&&!CheckHitKey(KEY_INPUT_ESCAPE)){
GetHitKeyStateAll( KeyBuf ) ;
// キー入力のあと,SlipTime にsliptimeを入れる
if(KeyBuf[KEY_INPUT_LEFT] == 1){
SlipTime = slip_time;
// vxをキャラクターのxに加算する
x-=vx;
flag=0;
}else if(KeyBuf[KEY_INPUT_RIGHT] == 1){
SlipTime = slip_time;
// vxをキャラクターのxに加算する
flag=1;
x+=vx;
}
if(flag){
x+=SlipTime;
if(SlipTime > 0)
SlipTime--;
}else{
x-=SlipTime;
if(SlipTime>0)
SlipTime--;
}
// はみ出し処理
if(x < 0) x =0;
if(x > 640-32) x = 640-32;
//*_ キャラクター
DrawBox(x,y,x+32,y+32,GetColor(0,0,255),TRUE) ;
Sleep(16);
}
DxLib_End();return 0;
} 
336ポイント を手に入れた。
|
|
|
|
|
Name: tuya ..ぴよぴよ(239ポイント)
Date: 2010/08/31(火) 12:59
No:60746
| 解決!
|
Title: Re:キャラクターに時間内を滑るように移動をさせたい
|
|
早速のお返事ありがとうございました。
とても参考になりました。
本当にありがとうございます
33ポイント を手に入れた。
|
|
|
|
Name: btk ..ぴよぴよ(36ポイント)
Date: 2010/08/30(月) 22:14
No:60719
|
|
Title: 描画系のことについて
|
|
みなさん初めまして。
私は今龍神録プログラミングの館を参考に自作STGを作っているのですが、東方のような弾幕遅延を作ることには成功したのですが、弾を連続的に描画していくと、途中から描画する順番がめちゃくちゃになってとても汚くなってしまいます。
後から出した弾を絶対に手前に描画する方法というのはあるのでしょうか?
36ポイント を手に入れた。
|
|
|
|
Name: パコネコ ..プログラマー(37,454ポイント)
Date: 2010/08/30(月) 22:21
No:60721
|
|
Title: Re:描画系のことについて
|
|
試してないですが…
ソート機能を作ってみてはどうですか?
描写の順番がfor文で配列の若い順になっている場合なら、新しく作られた弾は配列の1番前に入るようにとか?
ただそうしようとするといちいち他の弾が消えたり増えたりするたびにソートを行わないといけないですね…
ソートの度にデータを全部ずらさないと、いけませんし…
だめですかね…
116ポイント を手に入れた。
|
|
|
|
|
Name: nns ..ぴよぴよ(612ポイント)
Date: 2010/08/30(月) 22:35
No:60722
|
|
Title: Re:描画系のことについて
|
|
弾の構造体に構造体と同じポインタを2つ宣言し、
それぞれひとつ前と次のアドレスを格納していくことで可能です。
(そのままでは最初と最後が分からなくなるのでこの2つも別に用意します)
弾を追加するときや弾を消すときは前後を繋ぎ変えます。
詳しくは"自己参照構造体"を参照されると良いと思います。
手っ取り早くそれっぽく見せる方法としては、
空いてる弾の構造体配列を毎回0から検索されていると思いますが
弾を作ったときの構造体配列のインデックスを保存しておいて
次に作るときは前回+1の位置から空き配列を検索していきます。
(前回がi番目で作成したとすると、次はi〜最後、最初→i-1の順で空きを検索)
時々順番が狂いますが割といけますよ。
(東方本家もこの方法?)
2倍のポイントを手に入れた! 560ポイント を手に入れた。
|
|
|
|
|
Name: chemo ..ぴよぴよ(148ポイント)
Date: 2010/08/30(月) 22:35
No:60723
|
|
Title: Re:描画系のことについて
|
|
STL の list で管理してみたらどうでしょうか。
後から出した弾はリストの末尾に追加して、
必要なくなった弾は自身でリストから削除。
描画はリストの先頭から順番に行う。
STL の list は双方向リストで実装されているらしいので
項目の追加・削除もそれほどコストはかからないかと
78ポイント を手に入れた。
|
|
|
|
|
Name: btk ..ぴよぴよ(83ポイント)
Date: 2010/08/31(火) 12:37
No:60744
| 解決!
|
Title: Re:描画系のことについて
|
|
みなさんの意見を参考にしたらそれっぽいのが出来上がりました!
完全に解決とまではいきませんが、ここからは自分で考えてみようと思います。
ありがとうございました!
47ポイント を手に入れた。
|
|
|
|
Name: ti-ku ..ぴよぴよ(86ポイント)
Date: 2010/08/31(火) 00:26
No:60731
|
|
Title: 通信対戦ゲームの初歩
|
|
通信対戦の簡易ゲームを作ろうと思うのですが、"サーバー側に複数のクライアントが接続する"という処理がどうもうまくいきません。・ω・
int NetHandle=GetNewAcceptNetWork(); で1対1の接続なら容易にできるのですが、これが1対多の場合にいろいろ苦戦します。。。。
(例
サーバー側に複数のクライアントがランダムに接続、サーバー側では接続してきたクライアントの数を表示。
まずこれだけの処理までできたらいいな、、、、と思います。どなたかアドバイスお願いします!!
86ポイント を手に入れた。
|
|
|
|
Name: Mr.Vince ..かけだし(1,887ポイント)
Date: 2010/08/31(火) 05:36
No:60736
|
|
Title: Re:通信対戦ゲームの初歩
|
|
GetNewAcceptNetWork() のリファレンスを読む限り、「一番新しい」接続したハンドルを返すようなので、ループ内で接続の最大数までGetNewAcceptNetWork()を行えば良いのではないでしょうか?
例:
#define MAX_NETCOUNT 4
int tempNetHandle;
int netCount = 0;
int storedNetHandle[MAX_NETCOUNT] ;
while( !ProcessMessage() )
{
tempNetHandle = GetNewAcceptNetWork() ;
//ESC押すか、最大数(ここでは4)超えたらループ終了
if( CheckHitKey( KEY_INPUT_ESCAPE ) || netCount >= MAX_NETCOUNT ) break ;
if ( tempNetHandle != -1){
//新規接続有
storedNetHandle[netCount] = tempNetHandle;
netCount++;
}
}
printf("%d", netCount);
こんな感じでしょうか。
(自分はルーター環境下の為テストが出来ませんでしたので鵜呑みにはしないでください。飽くまでも解決法の例です。また、ネットワークを開く為の関数他は省いておりますので、ご自分で付け加えてください。)
257ポイント を落としてしまった。
|
|
|
|
Name: array [URL] ..熟練のプログラマー(67,850ポイント)
Date: 2010/08/31(火) 01:10
No:60732
|
|
Title: インスタンス化に失敗した際の処理について
|
|
お世話になっております。今回はC++のクラスの動作について質問させて下さい。
(例)
class CTest
{
CTest() { throw "Error"; }
void print() { std::cout << "Hello" << std::endl; }
};
int main()
{
CTest* test;
try
{
test = new CTest();
}
catch (...)
{
test = NULL;
}
test->print(); // ポイント@
return 0;
}
上記の例の様な(例)でクラスの生成に失敗したら例外を投げるクラスを作成したのですが
失敗(例外を検出)した際に、ポインタにNULLを入れていました。
個人的には、ポイント@の箇所では、test = NULLの時は処理を行わず飛ばしてくれると
有難いのですが、NULLポインタの為、print()メソッドを参照できないみたいです。
纏めると、インスタンス化に失敗してもprint()メソッド部でエラーが起きないようにしたいのですが
可能でしょうか。
宜しくお願いします。
420ポイント を手に入れた。
|
|
|
|
Name: めるぽん ..上級者(18,899ポイント)
Date: 2010/08/31(火) 02:12
No:60734
|
|
Title: Re:インスタンス化に失敗した際の処理について
|
|
if (test != NULL) test->print();
ではダメなんでしょうか?もしくは
print_if_not_null(CTest* p)
{
if (p != NULL) p->print();
}
int main()
{
...
print_if_not_null(test);
...
}
とか。あるいは Proxy パターンなんかも使えるかもしれません。
struct ITest
{
virtual void print() = 0;
};
struct CTest : ITest
{
virtual void print() { std::cout << "Hello" << std::endl; }
};
struct NullTest : ITest
{
virtual void print() { } // 何もしない
} nullTest;
int main()
{
try {
...
} catch (...) {
test = &nullTest;
}
test->print();
}
詳細は Proxy パターンとか調べれば分かると思います。
最後に、トリッキーというか、仕様的に問題がありそうなコードで良ければ、
struct CTest
{
void print()
{
if (this == NULL) return;
std::cout << "Hello" << std::endl;
}
};
int main()
{
CTest* test = NULL;
test->print();
}
と書くこともできますね。
453ポイント を手に入れた。
|
|
|
|
|
Name: array [URL] ..熟練のプログラマー(67,857ポイント)
Date: 2010/08/31(火) 02:30
No:60735
| 解決!
|
Title: Re:インスタンス化に失敗した際の処理について
|
|
色々な案有難うございます♪
個人的にはProxy パターンが一番イメージに近いです。
クラスを1つ経由する事で、インスタンスが正常に
行われていないかのチェックが一纏めに出来るわけですね。
Proxyパターンを参考に再設計させてもらいます。有難うございました^^
--
> if (test != NULL) test->print();
これだと、test->print()の仕様箇所が多くなると
変更時の作業が大変になるのであまり好ましくないのかなと思っていました。
> print_if_not_null()
書き損じましたが、オブジェクト思考を念頭に組んでみたかったので
可能であれば関数は避けようかと思います。
めるぽんさんのコードを見て気づきましたが
「if (test != NULL) test->print();」このコードをマクロ化するのも良いかと思いました。 
7ポイント を手に入れた。
|
|
|
|
Name: C言語勉強中 ..ぴよぴよ(79ポイント)
Date: 2010/08/29(日) 21:00
No:60620
|
|
Title: 文字列検索の質問です
|
|
テキストファイルからの文字列読み出しで
”Http Port=80”
とあった場合、ポート番号の80のみをstrcpyでコピーしたいのですが、
どうやれば実現できるでしょうか?
79ポイント を手に入れた。
|
|
|
|
Name: C言語勉強中 ..ぴよぴよ(102ポイント)
Date: 2010/08/29(日) 21:36
No:60626
| 解決!
|
Title: Re:文字列検索の質問です
|
|
早速の回答ありがとうございます。
strstr()を使用することで解決しました。
ありがとうございましたm(__)m
また、質問の際は宜しくお願いします。
23ポイント を手に入れた。
|
|
|
|
|
Name: C言語勉強中 ..ぴよぴよ(217ポイント)
Date: 2010/08/29(日) 22:02
No:60629
|
|
Title: Re:文字列検索の質問です
|
|
すいません、ちょっと気になったので、再度質問させてもらいます。
ポート番号が変わることがあった場合、”Http Port=”までは確定しているので、
strstrで文字列が一致した場合、以降の文字列を取得する、というようにしたいの
ですが、どうすれば出来るでしょうか?
115ポイント を手に入れた。
|
|
|
|
|
Name: フリオ ..プログラマー(36,955ポイント)
Date: 2010/08/29(日) 22:15
No:60631
|
|
Title: Re:文字列検索の質問です
|
|
strstrで見つかった文字列の先頭と、
それ以降の文字列の先頭の関係を考えてみては
どうでしょうか。

56ポイント を手に入れた。
|
|
|
|
|
Name: シエル [URL] ..熟練のプログラマー(66,192ポイント)
Date: 2010/08/29(日) 22:19
No:60632
|
|
Title: Re:文字列検索の質問です
|
|
ポート番号の後ろはすぐ改行なのであれば、改行まで読むというようにすればよいのではないでしょうか?
テキストモードとバイナリモードとでは、Windows環境の場合改行コードが変わってくるので注意
して下さい。
2倍のポイントを手に入れた! 154ポイント を手に入れた。
|
|
|
|
|
Name: C言語勉強中 ..ぴよぴよ(577ポイント)
Date: 2010/08/29(日) 23:08
No:60641
|
|
Title: Re:文字列検索の質問です
|
|
>フリオさん
それ以降の文字列は、サーバー名やルートパスが書かれていますが、改行されています。
>シエルさん
改行まで読むというのは、"\n"までということですよね?
改行コードが変わるのに注意というのは具体的にどう注意すればいいのですか?
いろいろ検索したのですが、よくわかりません。自分はwindows xp環境で.txtファイルの読み込みを
しようとしています。
2倍のポイントを手に入れた! 360ポイント を手に入れた。
|
|
|
|
|
Name: ちょっと通りますよ ..かけだし(1,314ポイント)
Date: 2010/08/29(日) 23:08
No:60642
|
|
Title: Re:文字列検索の質問です
|
|
汎用性を考慮する必要がなければ
char *parameter = "Http Port=80";
char sPortNo[7];
strcpy(sPortNo, "parameter[10]); //10じゃなかったら11でも9でも調整 parameter[10]に&つけてくださいね
//文字化けするので編集できませんでした
以前、私が作ってた時は、"PROTOCOL_VERSION = 2.0.1"とか
色々その他の長さの違うパラメータも扱う必要があったので、"A = B"といった一定の書式にしました。
即席iniファイルですね。
"HTTP_PORT = 80"
sscanf(parameter,"%*s %*c %s",sPortNo);
//整数値のみ必要な場合
int PortNo;
sscanf(parameter,"%*s %*c %d",&PortNo);
(追記)
sscanf(parameter,"Http Port=%s",sPortNo);//まぁ冗談はさておき、こういうのがいいでしょうねw

2倍のポイントを手に入れた! 362ポイント を手に入れた。
|
|
|
|
|
Name: シエル [URL] ..熟練のプログラマー(66,534ポイント)
Date: 2010/08/29(日) 23:27
No:60647
|
|
Title: Re:文字列検索の質問です
|
|
>改行まで読むというのは、"\n"までということですよね?
>改行コードが変わるのに注意というのは具体的にどう注意すればいいのですか?
>いろいろ検索したのですが、よくわかりません。自分はwindows xp環境で.txtファイルの読み込みを
>しようとしています。
Windowsは改行コードを0x0D0A(\r\n)として表すらしいのですが、
fopen("test.txt","r")としてテキストモードで読むと勝手にこの改行コードを"\n"だけに
直した状態で読み込んでくれるんです。
逆にfopen("test.txt","rb")としてバイナリモードで読むと、そのままデータを読み込むので
"\r\n"として改行コードを読んでしまいます。
そのため、バイナリモードで読んだときは、"\r"の文字があったら改行の始まりを表すことになります。
なので、もしテキストモードで読み込むのであれば"\n"まで読むということで構いません。
342ポイント を手に入れた。
|
|
|
|
|
Name: 初級者 ..初心者(8,973ポイント)
Date: 2010/08/29(日) 23:34
No:60648
|
|
Title: Re:文字列検索の質問です
|
|
テキストファイルを読むっていう質問なのに、
バイナリーモードの話が出てくる理由がさっぱりわかりません。
55ポイント を手に入れた。
|
|
|
|
|
Name: C言語勉強中 ..ぴよぴよ(694ポイント)
Date: 2010/08/31(火) 02:11
No:60733
|
|
Title: Re:文字列検索の質問です
|
|
char *parameter = "Http Port=80";
char sPortNo[7];
@strcpy(sPortNo, ¶meter[10]);
Asscanf(parameter,"Http Port=%s",sPortNo);
上記実装で、確実にsPortNoに"80"を設定することが出来ました。
@とAどちらでも出来るのですが、汎用性を考えるならどちらが好ましいでしょうか?
>シエルさん
丁寧な説明ありがとうございました。
バイナリモードで読むときは気をつけます。
117ポイント を手に入れた。
|
|
|
|
Name: 燈火 ..ぴよぴよ(300ポイント)
Date: 2010/08/30(月) 17:31
No:60698
|
|
Title: ランダムで初期位置を決定する
|
|
マインスイーパーの改造ゲームを作っております。
ゲームの概要は上手く説明できないので
わかりにくいと思うのですがプログラムにバグが出てしまっております。
二次元配列で用意したマップにランダムに0〜2の数字が入っております。
この中から2のマスを数えランダムで2の位置にプレイヤーの初期値をセットしたいです。
MapCount関数で2の数が返ってきます。
これの余りを求めればランダムの初期位置を生成できると思うのですが
毎回同じ値しか返ってきません。
※MapCount関数で返ってくる数字は毎回違います。
わかりにくい質問ですみません。
〜略 Map.Map[20][20]にランダムで0~2の値をセット〜
Map.MoveCount = MapCount( Map.Map ); // 毎回値が変わってるので多分正確に動いてます。
int startPos = rand()%Map.MoveCount;
int startCount = 0;
for (int y=0; y<MAP_H; y++) {
for (int x=0; x<MAP_W; x++) {
if( startCount == startPos ){
Play.Cx = x; // 初期位置の座標
Play.Cy = y; // 初期位置の座標
break;
}else if( Map.Map[y][x] != 0 && Map.Map[y][x] != 1 ) startCount++;
}
300ポイント を手に入れた。
|
|
|
|
Name: パコネコ ..プログラマー(37,133ポイント)
Date: 2010/08/30(月) 17:49
No:60699
|
|
Title: Re:ランダムで初期位置を決定する
|
|
わかりませんが…breakの後あたりに…//ミス
カッコの数とかですか?
=========
elseがもう一個上?
で下に「}」ですか?
=========
一番下に「}」を追加で十分ですね。
それとこっちはどうでもいいのですが、
elseのif文「!=」より「1<」のほうがいいのでは?
(マイナス使うならすいません)

19ポイント を手に入れた。
|
|
|
|
|
Name: バグ ..ハッカー(212,154ポイント)
Date: 2010/08/30(月) 17:50
No:60700
|
|
Title: Re:ランダムで初期位置を決定する
|
|
>>二次元配列で用意したマップにランダムに0〜2の数字が入っております。
>>この中から2のマスを数えランダムで2の位置にプレイヤーの初期値をセットしたいです。
ここまでは分かります。
>>これの余りを求めればランダムの初期位置を生成できると思うのですが
これの意味が分からないです。
差し支えなければ、MapCount関数のソースも公開した方が話しが早いような気がしますよ。
110ポイント を手に入れた。
|
|
|
|
|
Name: dic ..比類無きプログラマー(94,049ポイント)
Date: 2010/08/30(月) 18:27
No:60702
|
|
Title: Re:ランダムで初期位置を決定する
|
|
int startPos = rand()%Map.MoveCount;
が迷路のスタート地点で
これがランダムにしてるけど、毎回同じ値ってことでしょうか?
63ポイント を手に入れた。
|
|
|
|
|
Name: h2so5 ..入門者(2,517ポイント)
Date: 2010/08/30(月) 18:37
No:60704
|
|
Title: Re:ランダムで初期位置を決定する
|
|
あまり理解できないのですがおかしいところを数点。
1.
Map.Map[y][x] != 0 && Map.Map[y][x] != 1 は
Map.Map[y][x] == 2 と同じでは?
2.
startPosが0の時、必ず初期位置が座標[0,0]になる
(1.のチェックが入っていない)
3.
〜略 Map.Map[20][20]にランダムで0~2の値をセット〜
の部分を見ていないので推測ですが、MapCountで2の数を取得しているということは
あるマスが0か1か2になるかは全くランダムなのでしょうか。
それとも必ず配列に2が1つ以上含まれるようにセットしていますか?
しているのなら問題はありませんが。
264ポイント を手に入れた。
|
|
|
|
|
Name: 燈火 ..ぴよぴよ(514ポイント)
Date: 2010/08/30(月) 18:55
No:60706
|
|
Title: Re:ランダムで初期位置を決定する
|
|
皆様ご回答ありがとうございます。
配列内の2の数を数えてその範囲内でランダムの値を出します。
10個あったら0〜9の値をランダムで値を取得し
for文で回して取得した値番目にでてきた2の場所に初期位置をセットすれば
毎回違う2場所を初期位置にセット出来ると思ったのですが・・・
わかりにくい説明ですみません。
Map.MoveCountには毎回違う値が入っております。
(2の数だけ)
初期位置(cx,cy)が毎回同じ値になってしまいます。
214ポイント を手に入れた。
|
|
|
|
|
Name: パコネコ ..プログラマー(37,338ポイント)
Date: 2010/08/30(月) 18:56
No:60707
|
|
Title: Re:ランダムで初期位置を決定する
|
|
breakが1つだけではfor文の「y」のほうでもう一度ループするので必要ないのでは?
うまくカウントできてないと思います。
それと、プレイヤーの位置は2のときだけだと書いてますが、これだとおそらく、2以外でも…
おそらく毎回帰ってきている値は、x=0;y=max?;だと思ったのですが…違いましたでしょうか?
xは違いが出るかもしれませんが…似たような場所のように見えます。
プレイヤーの位置を入力する条件を増やすべきだと思います。
「2のときのみ」とか
elseがついているためif文の中に分けるべきだと思いますが…
==================
for (int y=0; y<MAP_H; y++) {
for (int x=0; x<MAP_W; x++) {
if(map.map[y][x]==2){//条件を満たしていれば判断
if( startCount == startPos ){
Play.Cx = x; // 初期位置の座標
Play.Cy = y; // 初期位置の座標
break;
}else startCount++;
}
}if( startCount == startPos )break;
}
こんな感じだと思うのですが… 
205ポイント を手に入れた。
|
|
|
|
|
Name: box ..ハッカー(157,231ポイント)
Date: 2010/08/30(月) 19:07
No:60708
|
|
Title: Re:ランダムで初期位置を決定する
|
|
> 10個あったら0〜9の値をランダムで値を取得し
このコードはどこにありますか?
15ポイント を手に入れた。
|
|
|
|
|
Name: ISLe ..上級者(17,624ポイント)
Date: 2010/08/30(月) 23:03
No:60726
|
|
Title: Re:ランダムで初期位置を決定する
|
|
> 毎回同じ値しか返ってきません。
srandで乱数の発生系列を初期化していないのでは?
16ポイント を手に入れた。
|
|
|
|
|
Name: 燈火 ..ぴよぴよ(417ポイント)
Date: 2010/08/30(月) 23:10
No:60729
| 解決!
|
Title: Re:ランダムで初期位置を決定する
|
|
皆さんこんなわかりにくい質問なのに回答ありがとうございます。
>>おそらく毎回帰ってきている値は、x=0;y=max?;だと思ったのですが…違いましたでしょうか?
その通りです!!
これはプログラムが原因だったのですね・・・。
頂いたソースに変更したら問題なく動きました。
ありがとうございました!!
97ポイント を落としてしまった。
|
|
|
|
Name: syo ..ぴよぴよ(15ポイント)
Date: 2010/08/30(月) 22:21
No:60720
|
|
Title: BGMと効果音
|
|
PlaySoundでBGMを流しているときに、PlaySoundで効果音を出すとBGMが途切れてしまいます。BGMと効果音を同時に出していたいのですがどうすればいいのですか?初歩的なことかもしれませんが、教えてください
15ポイント を手に入れた。
|
|
|
|
Name: syo ..ぴよぴよ(33ポイント)
Date: 2010/08/30(月) 23:04
No:60727
| 解決!
|
Title: Re:BGMと効果音
|
|
PlayMusicとPlaySoundを使ったらできました。
回答ありがとうございます。
18ポイント を手に入れた。
|
|
|
|
Name: あいす ..かけだし(1,817ポイント)
Date: 2010/08/29(日) 04:10
No:60510
|
|
Title: 管理人様へ
|
|
此処で質問することではないことは分かっていますが、管理人様への連絡手段が此処以外に思いつかないので、此処で質問させてください。
先日、龍神録プログラミングの館に載っているプログラムを参考にしたシューティングゲームを学校に課題として提出したいという内容のメールを送ったのですが、届いていませんか?
Yahoo!Japanのフリーメールで送ったのですが、フリーメールでは管理人様のメールアドレスには届かないのでしょうか?
もし届いていないようなら、別の連絡手段を教えて頂けませんか?
届いているのなら、この場やメール等で何かしらの回答をお願いしたいです。
よろしくお願いします。
この質問は、解決したら削除しようと思います。
245ポイント を手に入れた。
|
|
|
|
Name: あいす ..かけだし(1,780ポイント)
Date: 2010/08/29(日) 10:48
No:60532
| 解決!
|
Title: Re:管理人様へ
|
|
管理人様
こちらこそ、そちらの事情も知らずに急かすようなことをしてしまいすいません。
メールが届いていて良かったです。
37ポイント を落としてしまった。
|
|
|
|
|
Name: 阿久津 ..ぴよぴよ(67ポイント)
Date: 2010/08/29(日) 14:40
No:60562
|
|
Title: Re:管理人様へ
|
|
阿久津と申します。
すみません、人の質問スレに横槍するのはどうかと思ったのですが
何個も立てるのは申し訳ないと思い、こちらにレスさせて下さい。
あいすさん、ごめんなさい・・;
私も、メールを前に送ったのですが
もし届いておりましたらお返事欲しいです。
お手数ですがよろしくお願いします。
148ポイント を落としてしまった。
|
|
|
|
|
Name: 阿久津 ..ぴよぴよ(139ポイント)
Date: 2010/08/29(日) 23:21
No:60646
| 解決!
|
Title: Re:管理人様へ
|
|
こんばんは、阿久津です。
確認してみたら迷惑メールフォルダに入れられてました・・。
確認ミスでごめんなさい!本当に失礼しました;
72ポイント を手に入れた。
|
|
|
|
|
Name: シエル [URL] ..熟練のプログラマー(66,893ポイント)
Date: 2010/08/30(月) 20:09
No:60713
|
|
Title: Re:管理人様へ
|
|
またこのスレあげてしまってすみません。
すいません。キューさん。
パッケージゲットの件で先週の金曜日ぐらいにメールを送ったのですが、
返事がありません。
メール届いてますでしょうか?
届いていましたらお返事よろしくお願い致します。
97ポイント を手に入れた。
|
|
|
|
Name: snsnhi ..ぴよぴよ(182ポイント)
Date: 2010/08/30(月) 09:02
No:60668
|
|
Title: ゲーム作成
|
|
突然すいません。
オンラインゲームで終了したゲームを再構築したいのですができますでしょうか?
ちなみにTE○VIとゆうゲームなのですが一応終了前のクライアントを所持しております。
まったくの初心者なのでほぼとっていいほどわかりません;;
もし再構築できそれの手助けをしていただけるのでしたらコメかメールほしいです。
よろしくお願いします。
※もし違反などあったら消してください><
182ポイント を手に入れた。
|
|
|
|
Name: へろり ..プログラマー(32,046ポイント)
Date: 2010/08/30(月) 10:54
No:60673
|
|
Title: Re:ゲーム作成
|
|
ようするにゲームのサーバを立ち上げたいんですよね。
>ちなみにTE○VIとゆうゲームなのですが一応終了前のクライアントを所持しております。
サーバは所持していないのですか?
82ポイント を手に入れた。
|
|
|
|
|
Name: 五反田 ..ぴよぴよ(890ポイント)
Date: 2010/08/30(月) 11:02
No:60674
|
|
Title: Re:ゲーム作成
|
|
多分ですが、再構築というのは、オンラインゲームのサイトからダウンロード可能だったクライアントソフトから、
ホストサーバーで動かされていたゲーム本体を作り出せるかという意味だと思うのですが、
それはほぼ不可能だと思います。
クライアントソフトにある程度ゲームのデータは入っているかもしれませんが、暗号化されているでしょうし、
たとえ解読出来たとしても、それを元のように動かすプログラムを自分で書かなければ、クライアントソフト
があってもあまり意味はないんじゃないでしょうか?
少なくとも、全くの初心者(自分も含めてですが)が1年や2年で到達できるほど簡単な領域ではない気がします。
260ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(210,523ポイント)
Date: 2010/08/30(月) 11:12
No:60675
|
|
Title: Re:ゲーム作成
|
|
問題点が幾つかあります。
・ゲーム自体の著作権があるので完全に同じものを作るのはまずいと思います。
似たものならOKです。
・「終了前のクライアント」と言うのがセーブデータを持っているなら良いですが、オンライゲームならサーバ側にデータがある可能性が高く「TE○VI」サーバーの終了と共に消失していますので再現は困難です。
・「終了前のクライアント」がクライアントプログラムの場合、クライアント利用自体が権利的にマズイ可能性があります。
・TE○VIを知っていてゲームプログラミング出来て一緒に作業してくれる人に巡り会える可能性はほとんど無いと思います。
・TE○VIに関して攻略本を書けるだけの知識が必要です。
と言うことでsnsnhiさんは、どこまで頑張るれるでしょうか?
プログラミングやグラフィック、シナリオ、音楽、データ全般をsnsnhiさんはTE○VIに似せて制作できそうですか?
プログラミングに関してだけでも数年の月日は必要だと思ってください。
329ポイント を手に入れた。
|
|
|
|
|
Name: たいちう ..ハッカー(102,823ポイント)
Date: 2010/08/30(月) 22:00
No:60718
|
|
Title: Re:ゲーム作成
|
|
アナログ放送が終了すると不便だから、うちにあるテレビをベースに、
放送局を再構築できますか?
に近いレベルではないでしょうか。
48ポイント を手に入れた。
|
|
|
|
Name: アース ..ぴよぴよ(131ポイント)
Date: 2010/08/30(月) 19:12
No:60709
|
|
Title: 画面の大きさ設定
|
|
龍神録で、初期画面の大きさを全画面に変更するには、どこを変えればいいのでしょうか?
くだらない質問ですみません・・・w
できれば、画面だけを残して、画像の赤枠で囲ったところ(外枠?)を消して表示させたいです。
どのようにすればいいのでしょうか?
よろしくお願いします。
131ポイント を手に入れた。
|
|
|
|
Name: アース ..ぴよぴよ(183ポイント)
Date: 2010/08/30(月) 20:02
No:60712
| 解決!
|
Title: Re:画面の大きさ設定
|
|
早速のお返事ありがとうございます。
TRUEに変えるとできました。
結構難しい設定かと思っていたのですが、簡単だったので安心しましたw
ありがとうございました。
52ポイント を手に入れた。
|
|
|
|
Name: 774 ..入門者(4,464ポイント)
Date: 2010/08/30(月) 15:55
No:60690
|
|
Title: ファイルのデータを読み込んで配列に格納する方法
|
|
タイトルの通りですが,例えば
1 10.2
2 9.87
3 21.34
4 15.4
.
.
.
.
といったようなデータがあったとします.
そのときこの例で言えば2列目の要素だけを読み込んで配列に格納したい場合,
どのようにすればいいのでしょうか?
コンパイラはgccを使っています.
128ポイント を手に入れた。
|
|
|
|
Name: パコネコ ..プログラマー(36,914ポイント)
Date: 2010/08/30(月) 16:15
No:60691
|
|
Title: Re:ファイルのデータを読み込んで配列に格納する方法
|
|
gccを知らないので使えなかったらごめんなさい。
私はデータを読み込むときに、番号がついてるなら。
do{
fscanf(fp,"%d %f",a,deta);
}while(a!=serect);
hairetu[a]=deta;//[a]?自分で入れたいところに書き換えて…
みたいな感じでほしいデータがロードできるまでループさせてます。
目的以外の場所も読み込んでいるので、やりたいことと違ったら申し訳ないです。
gccがfscanfじゃなかったらもっとすいません。
116ポイント を手に入れた。
|
|
|
|
|
Name: パコネコ ..プログラマー(37,114ポイント)
Date: 2010/08/30(月) 16:30
No:60696
|
|
Title: Re:ファイルのデータを読み込んで配列に格納する方法
|
|
あれミスったかもしれません。
2列目をって書いてますね。
間違いの可能性もありますが…あってる可能性も高いので。
do{
fscanf(fp,"%d",a);
if(a!=100)
//[a]を[a-1]にしたりすることも…
fscanf(fp,"%f",hairetu[a]);
}while(a!=100);
//ファイルの終わりに100と、書いておく必要があります。
aは使い捨てで読み捨ててます。
fscanfが使えなければ結局無駄ですが…
これではだめでしょうか…
=============
すいません…「&a」および「&hairetu[a]」の間違いな気がします…

200ポイント を手に入れた。
|
|
|
|
|
Name: たかぎ [URL] ..ハッカー(222,065ポイント)
Date: 2010/08/30(月) 16:51
No:60697
|
|
Title: Re:ファイルのデータを読み込んで配列に格納する方法
|
|
組込みとかでなければfscanfが使えない状況というのはまずあり得ないので...
double value;
fscanf(stream, "%*[0-9]%f", &value);
として読み込み、配列に格納するだけです。
ただし、間違ったデータの入力にも対応するには、もっと別の方法が必要になります。
98ポイント を手に入れた。
|
|
|
|
Name: kei ..かけだし(2,137ポイント)
Date: 2010/08/28(土) 15:56
No:60422
|
|
Title: Visual C++ 2010 Expressのコンソールについて
|
|
Visual C++ 2010 Expressを使い始めようと思ったのですが、コンソール画面についてわからないことがあるので質問いたします。
PGをソースファイルにかいてビルドするところまではできたのですが、PGが起動して一瞬で消えてしまいます。
以前のExpressのバージョンでは、
「次に進むには何かボタンを押してください」というようなメッセージが出てきたので
PGがどのようにコンソールに表示していたのかを見ることが出来ました。
コンソールを表示させたままにするにはどのようにしたらよいでしょうか?
2倍のポイントを手に入れた! 420ポイント を手に入れた。
|
|
|
|
Name: palladium ..初心者(8,344ポイント)
Date: 2010/08/28(土) 19:25
No:60454
|
|
Title: Re:Visual C++ 2010 Expressのコンソールについて
|
|
getchar();もありますよね。
こんなのもあります。
#include <stdio.h>
#include <stdlib.h> // for system("pause");
int main()
{
printf("Hello World!\n");
system("pause");
return 0;
}
2倍のポイントを手に入れた! 162ポイント を手に入れた。
|
|
|
|
|
Name: 通りすがり ..上級者(22,697ポイント)
Date: 2010/08/28(土) 23:54
No:60499
|
|
Title: Re:Visual C++ 2010 Expressのコンソールについて
|
|
プロジェクト→プロパティの
構成プロパティ
└リンカ
└システム
で、サブシステムをコンソール (/SUBSYSTEM:CONSOLE)にすればよいかと思います。
53ポイント を手に入れた。
|
|
|
|
|
Name: yoko ..初心者(7,637ポイント)
Date: 2010/08/29(日) 20:01
No:60597
|
|
Title: Re:Visual C++ 2010 Expressのコンソールについて
|
|
デバックなし(Ctrl+F5)で開始ではなく
デバッグ開始(F5)でPGを起動していませんか?
デバッグ開始の場合はPGが最後まで行くと
自動的にプロンプトが終了してしまいます。
46ポイント を落としてしまった。
|
|
|
|
|
Name: kei ..かけだし(2,210ポイント)
Date: 2010/08/30(月) 09:24
No:60669
| 解決!
|
Title: Re:Visual C++ 2010 Expressのコンソールについて
|
|
みなさんありがとうございました。
Ctrl+F5でなく、F5だけでやっていました。
getchar()でも対応できますね。
いろいろと教えていただきありがとうございました。 
73ポイント を手に入れた。
|
|
|
|
|
Name: たかぎ [URL] ..ハッカー(221,967ポイント)
Date: 2010/08/30(月) 13:00
No:60683
|
|
Title: Re:Visual C++ 2010 Expressのコンソールについて
|
|
getcharを入れるとソースを破壊しますし、Ctrl + F5ではデバッガが使えません。
現実解としては、mainの最後のreturn文にブレークポイントを張っておくのがよいと思います。
49ポイント を落としてしまった。
|
|
|
|
Name: たろう ..プログラマー(35,144ポイント)
Date: 2010/08/11(水) 21:21
No:58739
|
|
Title: 当たり判定について
|
|
http://www.play21.jp/board/formz.cgi?action=res&resno=58431&page=&lognum=178&id=dixq&rln=58432
について質問したものですが、返信遅れて申し訳ありません。
当たり判定の処理が出来たのですが、ソースが汚い感じでどうしたらスマートにきれいに出来るのかわかりません。
何かヒントでいいので助言よろしくお願いします。
int atarihantei(float x1,float y1,float x2,float y2,float angle,float spd1,float spd2,float rang1, float rang2)
{
float r=rang1+CRANG;
float r2=rang2+CRANG;
if((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)<(r+r2)*(r+r2))
return 1;
if(spd1<0)
spd1=-1*spd1;
if(spd2<0)
spd2=-1*spd2;
if(spd1+spd2>r)
{
float pre_x1=x1+cos(0.0)*(spd1+spd2),pre_y1=y1+sin(0.0)*(spd1+spd2);
float pre_x2=x2,pre_y2=y2;
float now_x,now_y;
for(int i=0;i<(spd1+spd2)/(r+r2)-1;i++)
{
now_x=pre_x1-pre_x2;
now_y=pre_y1-pre_y2;
if(now_x*now_x+now_y*now_y<(r+r2)*(r+r2))
{
return 1;
}
if(i>=(int)((spd1+spd2)/(r+r2))-1)
{
break;
}
if(i==(int)((spd1+spd2)/(r+r2))-2)
{
float t=((spd1+spd2)-i*(r+r2));
pre_x1-=cos(PI)*t;
pre_y1-=sin(PI)*t;
}
else
{
float t=cos(PI)*(r+r2);
float t2=sin(PI)*(r+r2);
pre_x1+=t;
pre_y1+=t;
}
}
}
if((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)<(r+r2)*(r+r2))
return 1;
return 0;
}
701ポイント を手に入れた。
|
|
|
|
Name: たろう ..プログラマー(34,763ポイント)
Date: 2010/08/11(水) 21:34
No:58741
|
|
Title: Re:当たり判定について
|
|
ソース変更したので載せます。
int atarihantei(float x1,float y1,float x2,float y2,float angle,float spd1,float spd2,float rang1, float rang2)
{
float r=rang1+CRANG;
float r2=rang2+CRANG;
if((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)<(r+r2)*(r+r2))
return 1;
if(spd1<0)
spd1=-1*spd1;
if(spd2<0)
spd2=-1*spd2;
if(spd1+spd2>r)
{
float pre_x1=x1+cos(0.0)*(spd1+spd2),pre_y1=y1+sin(0.0)*(spd1+spd2);
float pre_x2=x2,pre_y2=y2;
float now_x,now_y;
for(int i=0;i<(spd1+spd2)/(r+r2);i++)
{
now_x=pre_x1-pre_x2;
now_y=pre_y1-pre_y2;
if(now_x*now_x+now_y*now_y<(r+r2)*(r+r2))
{
return 1;
}
if(i==(int)((spd1+spd2)/(r+r2))-1)
{
float t=((spd1+spd2)-i*(r+r2));
pre_x1-=cos(PI)*t;
pre_y1-=sin(PI)*t;
}
else
{
float t=cos(PI)*(r+r2);
float t2=sin(PI)*(r+r2);
pre_x1+=t;
pre_y1+=t;
}
}
}
if((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)<(r+r2)*(r+r2))
return 1;
return 0;
}
381ポイント を落としてしまった。
|
|
|
|
|
Name: めるぽん ..中級者(12,213ポイント)
Date: 2010/08/12(木) 05:29
No:58756
|
|
Title: Re:当たり判定について
|
|
スピードが大きいときは x1, y1 の円の位置を戻していって計算しているみたいなのですが、
cos(0) は 1 で、cos(PI) は -1、sin(0), sin(PI) は 0 ということを考えると、これはお互いに横方向に移動している場合しか正しく計算されないように見えます。
そもそも引数に早さのパラメータはあるのに、それがどの方向なのかというパラメータが無いような気がしますね。
2D上で、お互いに高速に移動している円同士の当たり判定を行うのは、自分が思いつく限り以下の方法があります。
1.移動のフレームレートを上げる。
最近のマシンならオブジェクトの移動で使う時間なんてよっぽどすごいことをやってない限り 0 に等しいので、例えば1フレームの間に10回移動させてやっても結構平気だったります。こうすることでトンネリングの発生する確率はかなり低くなると思います。
for (int i = 0; i < 10; i++)
objs.move_all();
objs.draw_all();
2.円が移動してできた軌跡同士で当たり判定を行う。
"円が移動してできた軌跡"というのは競技場のトラックみたいな形です。3Dではカプセル形って言うのですが、2Dの場合は何て呼ぶのかは分かりません。とりあえず今はカプセル形と呼びます。
カプセル形同士が当たっているかどうかを判定することで、トンネリングが発生することは無くなります。カプセル形同士の当たり判定の計算はそんなに難しくないです。
ただし、明らかに当たってない場合も当たってしまうと判断されてしまう場合があります。まあ 60FPS で動くようなゲームであれば気がつくことはまず無いとは思いますが。
3.二分探索を行う
s=0.0 を最初の位置の時間、e=1.0 を最後の位置の時間、sからeまでの軌跡(カプセル形)同士の計算を行います。ここまでは2.と同じ。
もし当たっていた場合は、s=0.0からe=0.5の範囲のカプセル形同士で当たっているかどうかと、s=0.5からe=1.0の範囲のカプセル形同士で当たっているかを調べます。これらが当たっているかどうかで更に当たっている範囲を絞り込んでいきます(図が無いと分かりにくいですね・・・)。
こうすることで、2.のような間違って当たっていると判断されることも無くなり、移動の最初の時間から最後の時間の間の、どの時間で当たったのかというのも分かるようになります。
1,006ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(34,722ポイント)
Date: 2010/08/12(木) 19:14
No:58785
|
|
Title: Re:当たり判定について
|
|
回答ありがとうございます。
>3.二分探索を行う。
二分探索を数学の何を勉強すればよいのでしょうか?
41ポイント を落としてしまった。
|
|
|
|
|
Name: めるぽん ..中級者(13,134ポイント)
Date: 2010/08/12(木) 20:57
No:58788
|
|
Title: Re:当たり判定について
|
|
二分探索法自体は有名なアルゴリズムなのでちょっとグーグル先生に聞けば教えてくれると思います。
ただこの3.の方法は、ほんとに二分探索と言っていいのかちょっと分からないです(これは安易に自分が二分探索って言っちゃったのがいけませんね)
3.の内容も含めて、当たり判定のアルゴリズム全般は、自分は『ゲームプログラミングのためのリアルタイム衝突判定』という本で勉強しました。ただこれは少し内容が難しいかもしれません。
202ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(35,122ポイント)
Date: 2010/08/13(金) 18:06
No:58893
|
|
Title: Re:当たり判定について
|
|
新たに作り直したので載せます。
実行した感じは当たり判定は出来ていると思うのですが、これではダメでしょうか?
int atarihantei(float x1,float y1,float x2,float y2,float angle,float spd1,float spd2,float rang1, float rang2)
{
float r=rang1+CRANG;
float r2=rang2+CRANG;
if(spd1<0)
spd1=-1*spd1;
if(spd2<0)
spd2=-1*spd2;
if(spd1+spd2>r+r2){
double pre_x=x1+cos(atan2(x1-x2,y1-y2))*(spd1+spd2);
double pre_y=y1+sin(atan2(x1-x2,y1-y2))*(spd1+spd2);
double px,py;
for(int j=0;j<(spd1+spd2)/(r+r2);j++){
px=pre_x-x2;
py=pre_y-y2;
if(px*px+py*py<(r+r2)*(r+r2))
return 1;
if(j==(int)((spd1+spd2)/(r+r2))-1){
pre_x+=cos(atan2(x1-x2,y1-y2)+PI)*((spd1+spd2)-(j*(r+r2)));
pre_y+=sin(atan2(x1-x2,y1-y2)+PI)*((spd1+spd2)-(j*(r+r2)));
}
else{
pre_x+=cos(atan2(x1-x2,y1-y2)+PI)*(r+r2);
pre_y+=sin(atan2(x1-x2,y1-y2)+PI)*(r+r2);
}
}
}
if((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)<(r+r2)*(r+r2))
return 1;
}
401ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(35,159ポイント)
Date: 2010/08/13(金) 18:47
No:58897
|
|
Title: Re:当たり判定について
|
|
返信ありがとうございます。
参考にしたいのですが計算式が載ってません。
あと、このソースだとだめという解釈でよろしいのでしょうか?
37ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(35,188ポイント)
Date: 2010/08/13(金) 23:11
No:58914
|
|
Title: Re:当たり判定について
|
|
できたらダメな(当たり判定ができない部分などの)理由など教えてくださると助かります。
わかる方いらしたらよろしくお願いします。
29ポイント を手に入れた。
|
|
|
|
|
Name: めるぽん ..中級者(14,604ポイント)
Date: 2010/08/13(金) 23:44
No:58917
|
|
Title: Re:当たり判定について
|
|
2つの円は必ずお互いに反対の方向に進んでいるわけではなく、ばらばらな方向へ移動してますよね?
その atan2 の使い方だと、(x1,y1) が必ず (x2,y2) の方向に進んでいるという計算になる気がします。
パラメータにそれぞれの円が進む方向というパラメータが足りないので、そのパラメータを追加した上で、(x1,y1)の円だけでなく(x2,y2)も同時に動かす必要がありそうです。
あと atan2 は atan2(Y, X) のように Y 座標を先に指定するので、それも気をつける必要がありますね。
それから、r+r2ずつ移動させて計算すると、例えば
○↑
↓○
という感じでお互いに微妙にずれて(でも物理的に考えれば当たる)移動しているときに、トンネリングが発生する可能性があります。まあこれは分割して判定する方法を使っている限りはどうしようも無いので諦めるしか無いと思います。
コンパイルすらしていないので間違ってる可能性がかなり高いですけど、こんな感じではないでしょうか
// 動いてない円同士の当たり判定
int test_circle_circle(float x1, float y1, float r1, float x2, float y2, float r2)
{
float x = x1 - x2;
float y = y1 - y2;
float r = r1 + r2;
return x * x + y * y <= r * r;
}
// 動いている円同士の当たり判定
int atarihantei(
// X座標, Y座標, 半径, 角度, 速度
float x1, float y1, float r1, float a1, float v1,
float x2, float y2, float r2, float a2, float v2)
{
// 経過時間
// 円がそれぞれ a1, a2 の方向に v1, v2 だけ進んだ時間を 1.0 とする
float t = 0.0f;
while (t < 1.0f)
{
// 初期位置から t だけ進んだ円同士の当たり判定を行う
if (test_circle_circle(
x1 + cos(a1) * v1 * t, y1 + sin(a1) * v1 * t, r1,
x2 + cos(a2) * v2 * t, y2 + sin(a2) * v1 * t, r2))
{
return 1;
}
// 適当に時間を進ませる
// ここの値は r1, r2, v1, v2 から適切に求めるべきだけど、ここでは面倒なのでやらない
t += 0.1f;
}
// 初期位置から 1.0 だけ進んだ円同士の当たり判定を行う
return test_circle_circle(
x1 + cos(a1) * v1, y1 + sin(a1) * v1, r1,
x2 + cos(a2) * v2, y2 + sin(a2) * v1, r2);
}
まあこれだと効率がかなり悪いですけれども、参考になれば幸いです。
2倍のポイントを手に入れた! 1,470ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(35,303ポイント)
Date: 2010/08/14(土) 21:52
No:58967
|
|
Title: Re:当たり判定について
|
|
めるぽんさん回答ありがとうございます。
すみません勉強不足で、まったくわかりません。
出来たら説明していただけないでしょうか。申し訳ないです。
それらは数学やアルゴリズムを勉強すればよいのでしょうか?
「ゲームプログラミングのためのリアルタイム衝突判定」読めばわかるようになるのでしょうか?
115ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(35,738ポイント)
Date: 2010/08/14(土) 22:39
No:58970
|
|
Title: Re:当たり判定について
|
|
あとソース変えてみました。
めるぽんさんのは参考にしていませんが、
以下のサイトを利用させていただきました。
http://www5d.biglobe.ne.jp/~tomoya03/shtml/algorithm/Intersection.htm
これではどうでしょうか?
int atarihantei(float x1,float y1,float x2,float y2,float angle1,float angle2,float spd1,float spd2)
{
float tc=(x1-y1+(cos(angle1)*spd1)*(y2-y1)+(y1-y1+sin(angle2)*spd1)*(x1-x2));
float td=(x1-(y1+cos(angle1)*spd1))*((y2-sin(angle2)*spd2)-y1)+(y1-y1+sin(angle2)*spd1)*(x1-(x2-cos(angle2)*spd2));
float ta=(x2-x2+cos(angle2)*spd2)*(y1-y2)+(y2-(y2+sin(angle2)*spd2))*(x2-x1);
float tb=(x2-x2+cos(angle2)*spd2)*((y1+sin(angle1)*spd1)-y2)+(y2-(y2+sin(angle2)*spd2))*(x2-(x1+cos(angle1)*spd1));
if(tc*td<0&&ta*tb<0)
{
return 1;
}
if((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)<(r+r2)*(r+r2))
return 1;
return 0;
}
ダメでしょうか?
435ポイント を手に入れた。
|
|
|
|
|
Name: 組木紙織 ..比類無きプログラマー(91,273ポイント)
Date: 2010/08/15(日) 20:19
No:59039
|
|
Title: Re:当たり判定について
|
|
>だめな理由をよろしくお願いします。
何故駄目だと思ったのでしょうか?
その理由をお願いします。
>参考にしたいのですが計算式が載ってません。
No:58896
で私が提示したものには、ベクトルと二次関数が理解できれば分かるレベルで計算式と計算手順を載せているつもりです。
分からないとこを指摘していただければ解説します。
あと根本的な問題として、どのような状況の当たり判定を考えているのでしょうか?
具体的に説明をお願いします。
192ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(36,478ポイント)
Date: 2010/08/15(日) 20:56
No:59046
|
|
Title: Re:当たり判定について
|
|
組木紙織さん返信ありがとうございます。
>だめな理由をよろしくお願いします。
>何故駄目だと思ったのでしょうか?
>その理由をお願いします。
すいません。自分の載せたソースがダメな理由が聞きたっかただけです。
ダメじゃなければよいのですが?
どうでしょうか?これで大丈夫でしょうか?
>あと根本的な問題として、どのような状況の当たり判定を考えているのでしょうか?
>具体的に説明をお願いします。
龍神録の18章の当たり判定で相手のスピードが当たり判定の範囲以上の時の当たり判定を知りたいのです。
たとえばスピードが50で相手の当たり判定が4のとき通り抜けてしまうのでそれをなくしたいのです。
わかりにくかったらすみません。
>で私が提示したものには、ベクトルと二次関数が理解できれば分かるレベルで計算式と計算手順を載せている>つもりです。
>分からないとこを指摘していただければ解説します。
わからないのは提示していただいた文章から
1現在重なっているかどうかの判定
係数が負である場合は現在二円が重なっており、そうでない場合は離れている。これは一般的な静的な当り判定と同じである。
2平行移動の判定
係数aが0の場合は二円の運動方向ベクトルが同じなので同じ速度で同じ方向に平行移動をしている状況となる。時間がたっても二円の位置関係が変わらないので結果は1.と変わらない。
3時間間隔後の判定
時間間隔がたった後に当っているかどうかの判定は式(5)の二次式の時間にを入れることによって判定できる。
4時間によらずいつかは重なる可能性があるかどうかの判定
二次式の判別式の時は負の無限大〜正の無限大の時間を考えたときに二円は重なる状況にある。の時は当らず、の場合のみ二円は当る可能性がある。
5次の時刻までに当り判定
1-3よりほとんどの場合の判定ができた。残る条件は現在当っておらず、次の時刻までに当り、次の時刻になったら離れるという場合である。最小値を取る時間が0〜の間にあればよい。
の1は多分わかります。
多分ソースに載せた計算式ですよね?2からがわかりません。
すみません勉強不足で。
すみませんが説明よろしくおねがいします。
713ポイント を手に入れた。
|
|
|
|
|
Name: 組木紙織 ..比類無きプログラマー(91,671ポイント)
Date: 2010/08/15(日) 22:36
No:59054
|
|
Title: Re:当たり判定について
|
|
>解説
状況は分かりました。先に確認したいことがあるので後回し。
>>だめな理由をよろしくお願いします。
>>何故駄目だと思ったのでしょうか?
>>その理由をお願いします。
>すいません。自分の載せたソースがダメな理由が聞きたっかただけです。
>ダメじゃなければよいのですが?
>どうでしょうか?これで大丈夫でしょうか?
大丈夫かどうかの判断は(基本的に)私たち回答者にはできません。
判断できるのは質問者さんです。
今までいくつか方法が提案されていますが、それぞれ特徴があってどの方法が一番適切であるかは
(想像は出来ますが)質問者さんが判断することです。
線分交差法による当たり判定の方法は何故大丈夫だと考えているのでしょうか?
先ほど書いていただいたソースはどうして大丈夫だと思っているのでしょうか?
#線分交差法は厳密な意味で考えると駄目だとおもってます。
#ただ厳密性がどこまで必要かも考える必要がありますよね。
398ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(36,580ポイント)
Date: 2010/08/16(月) 06:48
No:59071
|
|
Title: Re:当たり判定について
|
|
>#線分交差法は厳密な意味で考えると駄目だとおもってます。
の理由を教えて下さい。
>#ただ厳密性がどこまで必要かも考える必要がありますよね。
とりあえず当たり判定が出来てればいいです。
102ポイント を手に入れた。
|
|
|
|
|
Name: シエル ..熟練のプログラマー(49,509ポイント)
Date: 2010/08/16(月) 07:42
No:59073
|
|
Title: Re:当たり判定について
|
|
とりあえず、質問に対して全て答えたほうが良いのでは?
それと、実際に線分交差法で試してみて、正しく当たり判定できていたのですか?
39ポイント を手に入れた。
|
|
|
|
|
Name: 組木紙織 ..比類無きプログラマー(91,676ポイント)
Date: 2010/08/16(月) 08:26
No:59074
|
|
Title: Re:当たり判定について
|
|
>とりあえず当たり判定が出来てればいいです。
それを確認するのはあなたです。
>>#線分交差法は厳密な意味で考えると駄目だとおもってます。
>の理由を教えて下さい。
線分交差法のアルゴリズムを理解していればすぐわかるはずです。(と投げ返してみる)
その方法は円を使ってないからです。
#同じところを堂々巡りしてる。
5ポイント を手に入れた。
|
|
|
|
|
Name: めるぽん ..上級者(15,495ポイント)
Date: 2010/08/16(月) 09:27
No:59078
|
|
Title: Re:当たり判定について
|
|
>出来たら説明していただけないでしょうか。申し訳ないです。
どの辺が分からなかったのでしょうか。
1.その atan2 の使い方だと、(x1,y1) が必ず (x2,y2) の方向に進んでいるという計算になる
2.パラメータを追加した上で(x1,y1)の円だけでなく(x2,y2)も同時に動かす
3.atan2 は atan2(Y, X) のように Y 座標を先に指定する
4.
○↑
↓○
という感じでお互いに微妙にずれて(でも物理的に考えれば当たる)移動しているときに、トンネリングが発生する可能性があります
5.コードのどこか
あと No:58970 のコードですが、計算式の単純なミスが多いようです。例えば
float tc=(x1-y1+(cos(angle1)*spd1)*(y2-y1)+(y1-y1+sin(angle2)*spd1)*(x1-x2));
は、上記のサイトを読む限りは、X1=x1, X2=x1+cos(angle1)*spd1, X3=x2, X4=x2+cos(angle2)*spd2 なので、
float tc=(x1-(x1+cos(angle1)*spd1))*(y2-y1)+(y1-(y1+sin(angle2)*spd1))*(x1-x2);
となるのではないでしょうか(適当に置き換えただけなのでまだ間違ってる可能性もありますが)
で、もし線分交差法で正しく計算できたとしても、以下のような場合(赤い円は移動先です)
http://twitpic.com/2f5jip/full
最初の例と2番目の例は物理的に考えると明らかに当たっていると思うのですけど、線分が交差していないため、交差しないと判定されます。3番目の例は、物理的な時間経過を考えると当たっていないと予想されるのですけど、実際には線分が交差しているため当たっていると判断されます。
ただ物理シミュレーションみたいなことをする場合はもっと正確に計算した方がいいでしょうけど、60FPS でどんどん移動しているゲームでこれらが実際に問題になるかというと、あまり無いような気もします。だから組木紙織さんは
>#ただ厳密性がどこまで必要かも考える必要がありますよね。
と仰っているのだと思います。 
891ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(36,881ポイント)
Date: 2010/08/16(月) 13:16
No:59081
|
|
Title: Re:当たり判定について
|
|
返信ありがとうございます。
3番目の例は、物理的な時間経過を考えると当たっていないと予想されるのですけど、実際には線分が交差しているため当たっていると判断されます。
>物理的な時間経過を考えると当たっていないと予想されるのですけど、実際には線分が交差しているため当た>っていると判断されます。
実際は当たり判定されないと言うことでしょうか?
理解力がなくて申し訳ありません。
>ただ物理シミュレーションみたいなことをする場合はもっと正確に計算した方がいいでしょうけど、60FPS で>どんどん移動しているゲームでこれらが実際に問題になるかというと、あまり無いような気もします。だから>組木紙織さんは
>#ただ厳密性がどこまで必要かも考える必要がありますよね。
とは別に気になしなくてもよいと言うことでしょうか?
301ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(37,014ポイント)
Date: 2010/08/16(月) 13:22
No:59082
|
|
Title: Re:当たり判定について
|
|
シエルさん返信ありがとうございます。
>それと、実際に線分交差法で試してみて、正しく当たり判定できていたのですか?
見た感じは出来ていたと思います。
組木紙織 さん返信ありがとうございます。
>>>#線分交差法は厳密な意味で考えると駄目だとおもってます。
>>の理由を教えて下さい。
>線分交差法のアルゴリズムを理解していればすぐわかるはずです。(と投げ返してみる)
>その方法は円を使ってないからです。
当たり判定は出来ていいるということでしょうか?
133ポイント を手に入れた。
|
|
|
|
|
Name: めるぽん ..上級者(15,563ポイント)
Date: 2010/08/16(月) 13:47
No:59083
|
|
Title: Re:当たり判定について
|
|
>実際は当たり判定されないと言うことでしょうか?
実際にあの小さい円があの軌道上を同時に移動したとして、当たると思いますか?
>別に気になしなくてもよいと言うことでしょうか?
それはたろうさんが考えることです。
68ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(37,026ポイント)
Date: 2010/08/16(月) 22:41
No:59125
|
|
Title: Re:当たり判定について
|
|
>実際にあの小さい円があの軌道上を同時に移動したとして、当たると思いますか?
思いました。これは間違った考えでしょうか?
2倍のポイントを手に入れた! 12ポイント を手に入れた。
|
|
|
|
|
Name: めるぽん ..上級者(15,787ポイント)
Date: 2010/08/16(月) 23:24
No:59126
|
|
Title: Re:当たり判定について
|
|
3番目の例を少しずつ動かしてみました。
http://twitpic.com/2fbos8/full
線分は交差していますが、円同士は当たっていませんよね。
>>別に気になしなくてもよいと言うことでしょうか?
>それはたろうさんが考えることです。
この線分交差による判定方法がダメだということではなく、こういった状況が発生したときに、たろうさんの作っているゲームはそれが許容できるのかどうかということになってきます。
で、それが許容できるかどうかというのはたろうさんにしか判断できないので、どの当たり判定の方法を使うのかはたろうさんが考えて決めることになります。
224ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(37,053ポイント)
Date: 2010/08/17(火) 12:17
No:59150
|
|
Title: Re:当たり判定について
|
|
>線分は交差していますが、円同士は当たっていませんよね。
当たっていないと言うことは、当たり判定ができていないということでしょうか?普通に考えると当たっていると言うことでしょうか?
>この線分交差による判定方法がダメだということではなく、こういった状況が発生したときに、たろうさんの>作っているゲームはそれが許容できるのかどうかということになってきます。
許容できる範囲だと思うのですが、
めるぽんさんならどうでしょうか?
27ポイント を手に入れた。
|
|
|
|
|
Name: めるぽん ..上級者(16,710ポイント)
Date: 2010/08/17(火) 15:24
No:59169
|
|
Title: Re:当たり判定について
|
|
>当たっていないと言うことは、当たり判定ができていないということでしょうか?
>普通に考えると当たっていると言うことでしょうか?
「当たり判定ができている」や「普通に考える」というのがどういう意味なのかによりますね。
現実世界での連続的な移動に対するシミュレーションができているのかどうか、ということであれば、できていませんし、実際にそれをできるようにするのはかなり難しいと思います。
ただ、繰り返しになりますが、たろうさんの作っているゲームで許容できる範囲かどうかということであれば、たろうさんの考え次第ということになります。
>許容できる範囲だと思うのですが、
>めるぽんさんならどうでしょうか?
自分の意見はあまり関係無いと思うのですけれども、多分自分なら大抵のゲームは No:58917 で書いたようなコードにすると思います。
ただまあ、許容できないと感じたら atarihantei 関数の中身を書き換えるだけで済みますし、実際にどんどん作っていってから考えてもいいんじゃないでしょうか。
2倍のポイントを手に入れた! 760ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(37,054ポイント)
Date: 2010/08/17(火) 18:45
No:59198
|
|
Title: Re:当たり判定について
|
|
めるぽんさん返信ありがとうございます。
話を戻しますが、「ゲームプログラミングのためのリアルタイム衝突判定」読めばわかるようになるのでしょうか?
あと、No:58917 で書いたソースで
// ここの値は r1, r2, v1, v2 から適切に求めるべきだけど、ここでは面倒なのでやらない
t += 0.1f;
r1,r2,v1,v2からどうやって求めるのでしょうか?
1ポイント を手に入れた。
|
|
|
|
|
Name: めるぽん ..上級者(17,314ポイント)
Date: 2010/08/18(水) 01:33
No:59296
|
|
Title: Re:当たり判定について
|
|
>「ゲームプログラミングのためのリアルタイム衝突判定」読めばわかるようになるのでしょうか?
この本の内容をちゃんと理解できれば、このコードぐらいはすぐに書けるようになると思います。
>// ここの値は r1, r2, v1, v2 から適切に求めるべきだけど、ここでは面倒なのでやらない
>t += 0.1f;
これが何をやっているかというと、円の移動を 10 分割して判定してるだけです。
で、この値が 0.1f ではなく r1, r2, v1, v2 から適切に求めるべきと書いた理由は、v1 や v2 が r1 や r2 の 10 倍以上の大きさになっている場合にはやっぱりすり抜けてしまう現象が起きてしまう可能性が高くなってしまいますし、v1 や v2 が r1 や r2 より十分に小さい場合には 10 分割して判定するのは処理の無駄だからです。
ただ、v1 や v2 が r1 や r2 の 10 倍以上というのはあまり無いと思いますし、10 倍程度のコストなら大したこと無かったりするので、これで良かったりする可能性もあります。
で、それを踏まえた上でこの加算値を調整するのであれば、上記の問題を解消するために、半径に大して速度が小さいのであれば分割する回数を少なく(つまり加算値を大きくする)して、半径に大して速度が大きいのであれば分割する回数を増やす(つまり加算値を小さくする)ようにしましょう。
float get_atarihantei_add_time(float r1, float v1, float r2, float v2)
{
// 半径に対する速度の割合
float ratio1 = v1 / r1;
float ratio2 = v2 / r2;
// 大きい方を使う
float max_ratio = ratio1 > ratio2 ? ratio1 : ratio2;
// 割合が小さければ加算値を大きくして、割合が大きければ加算値を小さくする必要があるので、逆数にする
//(ratio の計算を r / v として小さい方を求めても構わないけど説明のためにこうする)
float rec = 1 / max_ratio;
// 適当に分割する(この 10 という値は適当に調整する)
float time = rec / 10;
// つまりこれは、1フレームで半径と同じだけの量を進む場合には 0.1f となり 10 分割され、
// 1フレームで半径の10倍の量を進む場合には 0.01f となり 100 分割されることになる。
return time;
}
int atarihantei(...)
{
...
t += get_atarihantei_add_time(r1, v1, r2, v2);
...
}
という感じでしょうか(例によって全然試していないので間違っている可能性があります)。
追記:v1 や v2 が 0 の場合は 0 除算になるので、v1 と v2 の両方が 0 の場合は特別な処理(例えば 1.0f を返すとか)をしてやる必要がありそうですね 
487ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(37,138ポイント)
Date: 2010/08/18(水) 01:58
No:59299
|
|
Title: Re:当たり判定について
|
|
返信ありがとうございます。読みながら考えてみたいと思います。
またわからなくなったら聞きたいと思いますのでそのときはよろしくお願いします。
58ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(198,463ポイント)
Date: 2010/08/18(水) 10:19
No:59328
|
|
Title: Re:当たり判定について
|
|
横から失礼します。
>>「ゲームプログラミングのためのリアルタイム衝突判定」読めばわかるようになるのでしょうか?
>この本の内容をちゃんと理解できれば、このコードぐらいはすぐに書けるようになると思います。
まず、今まで出てきたコードを理解出来ないのに本の内容が理解できるか何とも言えません。高い本ですので、書店で眺めてみると良いと思います。
まずその前に高校数学が大事でしょう。数I〜数IIIまで関係あるところをじっくり読みなおしてみてください。あと分からないコードを読むだけでなく、動かしてみて理解する事も必要だと思います。ダミーのmainを作ってどんなふうに動くか試されてはどうでしょうか?色んなポイントにprintfなどを挟みこんでみると分かりやすくなるかも知れません。
222ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(37,168ポイント)
Date: 2010/08/19(木) 22:31
No:59508
|
|
Title: Re:当たり判定について
|
|
>数I〜数IIIまで関係あるところをじっくり読みなおしてみてください。
高校数学の関係あるところというのは何でしょうか?
30ポイント を手に入れた。
|
|
|
|
|
Name: ぽこ ..プログラマー(29,273ポイント)
Date: 2010/08/19(木) 22:56
No:59509
|
|
Title: Re:当たり判定について
|
|
> 高校数学の関係あるところというのは何でしょうか?
根本的に必要なのは、自分が抱えている問題を数式で表す(立式)能力です。
数式を作成するにあたって、軌跡、領域、ベクトル、三角関数等が役に立つと思います。
73ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(199,473ポイント)
Date: 2010/08/20(金) 00:02
No:59513
|
|
Title: Re:当たり判定について
|
|
私の教科書は古いので同じとは思えませんが、少なくとも三角関数と空間図形とベクトルはみっちりやることと、図形全般は必須として行列も何かと出てくるので理解しておいたほうが良いでしょう。
下記サイトの2D衝突編が理解できるとお望みのものが作れるようになると思います。
http://marupeke296.com/COL_main.html
極端なカーブを描いているものでなければ、楕円と楕円の衝突で時間成分を加味した当たり判定でほぼ実現出来ると思います。ただ、たろうさんのやろうとしてる当たり判定に必要な精度が分からないので断言はできません。
「失礼しました」
名前を打ち間違えていたので修正しました。

198ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(37,237ポイント)
Date: 2010/08/20(金) 23:45
No:59651
|
|
Title: Re:当たり判定について
|
|
返信ありがとうございます。
参考のサイト利用させていただきます。わからなくった時はまたよろしくお願いします。
42ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(37,348ポイント)
Date: 2010/08/21(土) 00:41
No:59664
|
|
Title: Re:当たり判定について
|
|
すみませんどこを具体的に読んでいいかわかりません。
楕円と楕円の衝突のところを読んでみたのですが、当たり判定でどこでどうやって使えばよいのかわかりません。すみません、ご教授願えませんでしょうか。
77ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(37,407ポイント)
Date: 2010/08/21(土) 01:48
No:59677
|
|
Title: Re:当たり判定について
|
|
できました。5ピクセルまでは5個5ピクセルの円は入っています。が6個目から1ピクセルずつ超えてしまいます。
2倍のポイントを手に入れた! 32ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(200,352ポイント)
Date: 2010/08/21(土) 11:47
No:59709
|
|
Title: Re:当たり判定について
|
|
>できました。5ピクセルまでは5個5ピクセルの円は入っています。が6個目から1ピクセルずつ超えてしまいます。
???
絵に書いてみてもらえますか。
>のなぜこの式になるのでしょうか?
私も式を完全に追っているわけではないので、ピンポイトで尋ねられても答えられというか、そもそも式のどの部分を解説して欲しいんでしょうか?
その前にその1からその6は理解されたのでしょうか?
少なくとも「その6 楕円と点の衝突」は先に理解すべきだと思いますが。
答えを急ぎ過ぎというか、一歩一歩しっかり理解していかないと応用はおぼつかないですよ。
96ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(37,543ポイント)
Date: 2010/08/21(土) 18:05
No:59736
|
|
Title: Re:当たり判定について
|
|
返信ありがとうございます。
拙いですが、絵に描いてみました。
>私も式を完全に追っているわけではないので、ピンポイトで尋ねられても答えられというか、そもそも式のどの部分を解説して欲しいんでしょうか?
式自体なぜこうなるのかわからないのです。
>その前にその1からその6は理解されたのでしょうか?
理解していませんでした。その6ですね。勉強してみます。
179ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(200,590ポイント)
Date: 2010/08/21(土) 19:18
No:59747
|
|
Title: Re:当たり判定について
|
|
>拙いですが、絵に描いてみました。
やはり私の言いたいことは伝わっていなかったみたいです。
こちらも絵を用意してみました。
移動する当たり判定は、楕円に近似できるって意味です。
真ん中の黒棒が移動範囲で、円が当たり範囲、黒の楕円が近似できる当たり範囲です。
>>私も式を完全に追っているわけではないので、ピンポイトで尋ねられても答えられというか、そもそも式のどの部分を解説して欲しいんでしょうか?
>式自体なぜこうなるのかわからないのです。
そこに到るまでの計算式は理解されているのでしょうか?
間をすっ飛ばして理解できるとは思えないんですが。
173ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(37,713ポイント)
Date: 2010/08/22(日) 12:16
No:59794
|
|
Title: Re:当たり判定について
|
|
>移動する当たり判定は、楕円に近似できるって意味です。
>真ん中の黒棒が移動範囲で、円が当たり範囲、黒の楕円が近似できる当たり範囲です。
これを知ってどうなるというのでしょうか?
すみません理解力がなくて。。。
2倍のポイントを手に入れた! 170ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(201,236ポイント)
Date: 2010/08/22(日) 12:54
No:59798
|
|
Title: Re:当たり判定について
|
|
>これを知ってどうなるというのでしょうか?
当たり判定の根本的な問題をカバーするための楕円のテクニックを理解してもらうためです。
もっと根本的な当たり判定の話から理解してもらうほうが良いみたいですね。
この質問の流れも、そこが分かっていないと解決に持っていけない気がします。
絵を添えましたので見てください。
状況を説明するとAからBに移動する物体とCからDに移動する物体で1/60秒ごとに直径5ピクセルの円の当たり判定すると仮定しています。移動速度は10ピクセルです。
見てもらうとわかるのですが、円や線分の当たり判定ではABとCDの物体は当たり状態と判定されません。
これは理解できますか?
これらの問題を擬似的、あるいは何とかしようというのが当たり判定の様々な方法なのです。
2倍のポイントを手に入れた! 646ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(201,353ポイント)
Date: 2010/08/22(日) 13:04
No:59800
|
|
Title: Re:当たり判定について
|
|
少し例として悪かったので絵を修正。
これから明日の夜まで出かけますので申し訳ないですが返答できません。
今までの他の皆さんの話も含めて絵を書いてイメージを固めることと各当たり判定方式の問題点をちゃんと把握することを目指してくださいね。
117ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(37,931ポイント)
Date: 2010/08/22(日) 18:09
No:59825
|
|
Title: Re:当たり判定について
|
|
返信ありがとうございます。
>見てもらうとわかるのですが、円や線分の当たり判定ではABとCDの物体は当たり状態と判定されません。
これは理解できますか?
はい。
A,B,C,Dの5ピクセルの範囲内に入っていないのでそれはわかります。
2倍のポイントを手に入れた! 218ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(201,980ポイント)
Date: 2010/08/24(火) 18:36
No:59952
|
|
Title: Re:当たり判定について
|
|
えーと、結局現状はどうなっていますか?
なにも進んでない気がするんですが。
現状を確認してみましょう。
1つ1つ明確に答えてください。
1)自分の目指していて満足できる衝突判定アルゴリズムはありましたか?
2)線分交差法が問題があると言われていた理由が理解できましたか?
3)めるぽんさんのアルゴリズムは理解されましたか?
また、めるぽんさんのアルゴリズムに追加質問はないのでしょうか?
4)実は、楕円と楕円の衝突判定方法にも問題があります。
それは何か理解さていますでしょうか?
めるぽんの名前を間違っていたので修正。 
251ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(38,245ポイント)
Date: 2010/08/24(火) 19:44
No:59965
|
|
Title: Re:当たり判定について
|
|
返信ありがとうございます。
1)自分の目指していて満足できる衝突判定アルゴリズムはありましたか?
めるぽんさんのがいいのかと思いました。
2)線分交差法が問題があると言われていた理由が理解できましたか?
いいえ
3)めるぽんさんのアルゴリズムは理解されましたか?
すみませんが、いいえ、
float max_ratio = ratio1 > ratio2 ? ratio1 : ratio2;
// 割合が小さければ加算値を大きくして、割合が大きければ加算値を小さくする必要があるので、逆数にする
//(ratio の計算を r / v として小さい方を求めても構わないけど説明のためにこうする)
float rec = 1 / max_ratio;
のところの意味がわかりません。
4)実は、楕円と楕円の衝突判定方法にも問題があります。
いいえ。
こんな答え方しか答えられないのですがよろしくお願いします。
314ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(202,301ポイント)
Date: 2010/08/24(火) 21:01
No:59976
|
|
Title: Re:当たり判定について
|
|
じゃあ、更に整理して見ましょう。
絵は、前のが分かりづらいので更に絵に変更を加えましたCD間の移動速度が極端に遅い場合です。
2)私の絵で示したつもりですが、「その2」の場合、当たりと判定すべきでしょうか?それとも当たらなかったとみなすべきでしょうか?(もちろん、線分交差法では当たりではありません)
衝突判定も含めゲームは計算式の理解も大事ですがイメージ力を使って動きを理解しプログラムする側面が大きいです。
3)に関しては根本として
>これが何をやっているかというと、円の移動を 10 分割して判定してるだけです。
辺のことが、まず理解出来ている必要があります。
何のために10分割するか考えてみましたか?
10分割でダメな場合と10分割で無駄な場合ってなんでしょう?
4)に関しては課題としましょう。紙に色々と絵を書いて考えてみてください。
273ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(37,906ポイント)
Date: 2010/08/24(火) 23:56
No:59982
|
|
Title: Re:当たり判定について
|
|
>2)私の絵で示したつもりですが、「その2」の場合、当たりと判定すべきでしょうか?それとも当たらなかったとみなすべきでしょうか?(もちろん、線分交差法では当たりではありません)
A,Bの範囲に入っていないので当たり判定とみなしません。
>何のために10分割するか考えてみましたか?
>3)に関しては根本として
>10分割でダメな場合と10分割で無駄な場合ってなんでしょう?
10分割は長さを細かく計るためにするに10分割すると思いました。
10分割でダメな理由は10分割を細かくしたよりも小さい長さを求められないからだと思います。
>4)に関しては課題としましょう。紙に色々と絵を書いて考えてみてください。
書いてみましたが、楕円の当たり判定の円外のところも計ってしまうからでしょうか?
339ポイント を落としてしまった。
|
|
|
|
|
Name: softya [URL] ..ハッカー(202,858ポイント)
Date: 2010/08/25(水) 01:20
No:59995
|
|
Title: Re:当たり判定について
|
|
もう一度整理してみましょう。
>2)線分交差法が問題があると言われていた理由が理解できましたか?
> ⇒ いいえ ⇒ 2)私の絵で示したつもりですが、「その2」の場合、当たりと判定すべきでしょうか?それとも当たらなかったとみなすべきでしょうか?(もちろん、線分交差法では当たりではありません) ⇒ A,Bの範囲に入っていないので当たり判定とみなしません。
a)それではこの状況はゲームとしては当たっていてほしい状況ですか?
それとも当たらなくても気になりませんか?
b)線分交差法に問題は感じませんか?
>3)めるぽんさんのアルゴリズムは理解されましたか?また、ぬるぽんさんのアルゴリズムに追加質問はないのでしょうか?
> ⇒ float rec = 1 / max_ratio;のところの意味がわかりません。 ⇒ 何のために10分割するか考えてみましたか? 10分割でダメな場合と10分割で無駄な場合ってなんでしょう? ⇒ 10分割は長さを細かく計るためにするに10分割すると思いました。10分割でダメな理由は10分割を細かくしたよりも小さい長さを求められないからだと思います。
c)長さを細かく計ると何が良いのでしょうか?重要なポイントです。私は長さよりも時間と空間の問題だと思うのですが表現が違うだけかも知れませんのでお聞きします。出来るだけ具体例を挙げてください。
d)10分割でダメな理由は10分割を細かくしたよりも小さい長さを求められないからだと思います。
これは何故でしょうか?どういう状態を想定してしていますか?具体的な例を書いてみてください。
e)10分割で無駄な理由の答えがありませんね。考えてみてください。
>4)実は、楕円と楕円の衝突判定方法にも問題があります。 それは何か理解さていますでしょうか?
⇒ いいえ。 ⇒ 4)に関しては課題としましょう。紙に色々と絵を書いて考えてみてください。⇒
書いてみましたが、楕円の当たり判定の円外のところも計ってしまうからでしょうか?
円での当たり判定は理想の当たり判定ですね。楕円は擬似的な当たり判定に過ぎません。
f)これも時間と空間の問題で少なくとも2つ以上の問題があります。思いつく限りの問題を挙げてみてください。
557ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(38,132ポイント)
Date: 2010/08/25(水) 14:07
No:60046
|
|
Title: Re:当たり判定について
|
|
返信ありがとうございます。
>a)それではこの状況はゲームとしては当たっていてほしい状況ですか?
それとも当たらなくても気になりませんか?
当たってほしい状況です。
>b)線分交差法に問題は感じませんか?
感じました。AからBのAB、CからDのCDは当たり判定されるけど、ABとCDでは当たり判定されないと言うことですよね。
>c)長さを細かく計ると何が良いのでしょうか?
すみません、わかりません。教えてください
>d)10分割でダメな理由は10分割を細かくしたよりも小さい長さを求められないからだと思います。
これは何故でしょうか?
すみません。感です。わかりません。教えてください。
e)10分割で無駄な理由の答えがありませんね。考えてみてください。
すみません。検討がつきません。教えてください。
f)これも時間と空間の問題で少なくとも2つ以上の問題があります。思いつく限りの問題を挙げてみてください。
思いつきません。教えてください。
226ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(203,909ポイント)
Date: 2010/08/25(水) 15:40
No:60051
|
|
Title: Re:当たり判定について
|
|
結局、ぬるぽんさんのアルゴリズムを理解されていないんですね。
これだと堂々巡りなので、ぬるぽんさんのプログラムを解析してみてください。
教えるというか、これ以上は理解してもらうしか無いです。
cについて考えてみましょう。d〜fは保留します。
最初のNo:58917 の回答の方にあるプログラムで10分割だけしている方です。
ちなみに距離を10分割しているんじゃなくて時間を10分割していると思ってください。
あちこちにprintf/printfDXを挟んで数値を追うも良し、実際に円をグラフィック化して表示してシミュレーションしてみるも良し、フローチャートなどを書いてみてアルゴリズムを理解するのも良しです。自分で出来るだけの事をやってみてなぜこうなっているのか推論を働かせてみてください。
意味もなく10分割はしていません。2分割だと何が違うんでしょう?プログラムを動かして考えてみてください。
2倍のポイントを手に入れた! 736ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(38,285ポイント)
Date: 2010/08/25(水) 21:06
No:60096
|
|
Title: Re:当たり判定について
|
|
返信ありがとうございます。
>最初のNo:58917 の回答の方にあるプログラムで10分割だけしている方です。
>ちなみに距離を10分割しているんじゃなくて時間を10分割していると思ってください。
これは10分割しているのはわかります。
すみません。ただなぜ、float rec = 1 / max_ratio;
と逆数にする必要があるでしょうか?
153ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(204,104ポイント)
Date: 2010/08/25(水) 22:11
No:60107
|
|
Title: Re:当たり判定について
|
|
うーん。そもそも何故10分割しているか理解されましたか?
そこが理解出来ていないと以下の回答も意味ないんですが。
で質問の
max_ratio自体の意味は、半径に対する速度の割り合いですので逆数にすると言うことは速度に対する半径の割合です。
float rec = 1 / max_ratio;
で求められるのは、速度が大きいほど小さな値で当たり半径が大きいほど大きな値になります。
つまり何をしようとしているかというと、速度が大きくなるほど細かい時間に分割して当たり判定をしようとしています。
当たり判定の円の半径が10で移動速度が10なら、1/10フレームの時間単位で当たり判定をします。
当たり判定の円の半径が10で移動速度が100なら、1/100フレームの時間単位で当たり判定をします。
ただ、めるぽんさも書いている通り
float time = rec / 10;
が適当かは私も疑問ですので調整が必要です。
その調整もアルゴリズムを理解していてこそですので、まず1/10フレームの時間単位でなぜ当たり判定をしているか理解した上って事になります。 
287ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(38,398ポイント)
Date: 2010/08/26(木) 01:19
No:60120
|
|
Title: Re:当たり判定について
|
|
返信ありがとうございます。
10分割している理由は、当たり判定の円の半径が10以上のとき、フレーム数を移動速度に合わせるためでしょうか。。。
だから、当たり判定の円の半径が10未満のときは、当たり判定されなかったのでしょうか?
すみません。わかりません。。。
113ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(204,342ポイント)
Date: 2010/08/26(木) 01:34
No:60122
|
|
Title: Re:当たり判定について
|
|
10分割は時間を分割しているのであって、距離や大きさを分割しているのではありません。時間が関係してくるのは速度だけです。速度は時間あたりの移動距離ですからね。
10分割は1秒間の描画フレーム数と別に当たり判定専用のフレーム数を増やす為です。
10分割するということは、毎秒60回の描画数だとすると当たり判定は毎秒600回になります。
これは何のためでしょうか?毎秒60回を10倍にして毎秒600回だと何がめるぽんの処理で変わるのかよーく考えてみてください。ヒントは今までの私やめるぽんさんや組木紙織さんなどの回答に散りばめられていますよ。
ヒントになる絵も添えておきます。
1、2、3、4、5は時間だと思ってください。仮にmsでも良いです。
赤い丸は移動する当たり範囲。青い丸は停止している当たり範囲です。 
259ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(38,600ポイント)
Date: 2010/08/26(木) 02:11
No:60124
|
|
Title: Re:当たり判定について
|
|
>10分割するということは、毎秒60回の描画数だとすると当たり判定は毎秒600回になります。
これは何のためでしょうか?
より細かい当たり判定ができると思います。
なぜ10分割かは、FPSが60なので、その10倍だと都合がいいからでしょうか?
117ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(204,124ポイント)
Date: 2010/08/26(木) 10:32
No:60139
|
|
Title: Re:当たり判定について
|
|
>より細かい当たり判定ができると思います。
より細かいって言うのが分かってもらえたのか微妙ですね。
念のために具体例を書いてもらえますか?
>なぜ10分割かは、FPSが60なので、その10倍だと都合がいいからでしょうか?
うーん。めるぽんさんが10分割したのは特に理由はないと思います。
ちゃんと当たり判定できるなら、別に4分割でも8分割でも構わないんですよ。
めるぽんさんが機能追加したNo:59296 のmax_ratioの計算は、それを補正するために計算しているわけですしね。
【追記】
念のために追記しておきます。
分割自体は当たり判定としてすごく意味がありますよ。
でも回数自体は10回は最適解じゃないです。
ベストでもベターでも無く、このぐらいやっておけば大丈夫じゃね?ぐらいの意味しかないです。 
218ポイント を落としてしまった。
|
|
|
|
|
Name: たろう ..プログラマー(38,471ポイント)
Date: 2010/08/26(木) 17:54
No:60181
|
|
Title: Re:当たり判定について
|
|
返信ありがとうございます。
>念のために具体例を書いてもらえますか?
1から5までの円が並んであるとして、1なら1の円の直径を10分割を求めるということでしょうか?
これを100分割した場合はより細かく求めるということでしょうか?
例が下手ですみません。。。
129ポイント を落としてしまった。
|
|
|
|
|
Name: softya [URL] ..ハッカー(204,369ポイント)
Date: 2010/08/26(木) 18:05
No:60187
|
|
Title: Re:当たり判定について
|
|
>1から5までの円が並んであるとして、1なら1の円の直径を10分割を求めるということでしょうか?
>これを100分割した場合はより細かく求めるということでしょうか?
>例が下手ですみません。。。
めるぽんさんの回答No:58917 のプログラムは本当にそんなプログラムですか?
No:58917のプログラムのたろうさんなりのアルゴリズムの解説を書いてみてください。
138ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(38,528ポイント)
Date: 2010/08/26(木) 20:27
No:60206
|
|
Title: Re:当たり判定について
|
|
1から5と言うのは、 1につき1 / max_ratioのことです。
それを10分割するということは、より細かくすることにより、移動速度をより細かく処理をするためにと言うことでしょうか?
すませんわかりません。教えてください。。。
57ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(204,467ポイント)
Date: 2010/08/26(木) 20:43
No:60208
|
|
Title: Re:当たり判定について
|
|
>1から5と言うのは、 1につき1 / max_ratioのことです。
>それを10分割するということは、より細かくすることにより、移動速度をより細かく処理をするためにと言うことでしょうか?
>すませんわかりません。教えてください。。。
それはめるぽんさんの回答No:59296ですよね。
そっちじゃなくて、No:58917の方です。検索してみてくださいね。
今回は、1から5も忘れてもらって良いですか。
35ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(38,778ポイント)
Date: 2010/08/26(木) 21:20
No:60217
|
|
Title: Re:当たり判定について
|
|
if (test_circle_circle(
x1 + cos(a1) * v1 * t, y1 + sin(a1) * v1 * t, r1,
x2 + cos(a2) * v2 * t, y2 + sin(a2) * v1 * t, r2))
{
は、V1が50でV2が50のとき、tは1 / max_ratioを10分割したやつをかけてそうすると、
例えば、r1が10でr2が5のとき5/50を10分割して、移動速度をより細かくしていき、
それをtに加算していく。
x1 + cos(a1) * v1 * tは位置に移動速度のV1の距離にtをかけて(0.1なら10分の1それを10回繰り返される)
while(t<1.0f)になるまで繰り返す。
です。
250ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(204,730ポイント)
Date: 2010/08/26(木) 21:43
No:60221
|
|
Title: Re:当たり判定について
|
|
回答No:59296のmax_ratio件は、今は忘れてください。
今回解説してもらいたいのは、回答No:58917だけの話です。
それと書かれているのはプログラムの内容そのもので、アルゴリズムと言うか仕様の説明になっていません。
tは何を表す変数でしょうか?日本語で書くとしたら?
v1,v2,r1,r2は分かりますよね。書いてもらえますか。
x1 + cos(a1) * v1 * t
の式は、何を求めるための式でしょうか?
解説してもらえますか。
これらも含めて全体の内容が解説出来て始めてプログラムを理解したことになります。
200ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(39,076ポイント)
Date: 2010/08/26(木) 21:59
No:60225
|
|
Title: Re:当たり判定について
|
|
>tは何を表す変数でしょうか?日本語で書くとしたら?
tは、任意の数を分割した数を表す変数。
>v1,v2,r1,r2は分かりますよね。書いてもらえますか。
V1,v2は移動速度。r1,r2は当たり判定の範囲です。
x1 + cos(a1) * v1 * t
の式は、何を求めるための式でしょうか?
は移動位置の分割した数を求める式です。
これでいいでしょうか?
2倍のポイントを手に入れた! 298ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(204,948ポイント)
Date: 2010/08/26(木) 22:20
No:60227
|
|
Title: Re:当たり判定について
|
|
めるぽんさんの代わりに解説しているので、勘違いもあるかも知れませんが。
tは時間経過を表す変数で1フレーム内の時間の経過を表します。たぶんtimeの略だと思われます。
t=0が始まりで、t=1で1フレーム分の時間が経過したことになります。
なので、t=0.5なら0.5フレームの時間が経過したことになる訳です。
>V1,v2は移動速度。r1,r2は当たり判定の範囲です。
正確に言うとV1,v2は1フレーム当たりの移動距離で速度としての単位はピクセル/フレームです。
r1,r2は当たり判定の範囲ですが半径ですね。
じゃあ、
x1 + cos(a1) * v1 * t
は何を表す式になるでしょうか?
x1とa1も合わせて解説してください。
>は移動位置の分割した数を求める式です。
これって意味分かってます?
5回とか回数が出る式には見えませんが。
208ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..プログラマー(39,198ポイント)
Date: 2010/08/26(木) 22:30
No:60229
|
|
Title: Re:当たり判定について
|
|
返信あありがとうございます。
>x1 + cos(a1) * v1 * t
>は何を表す式になるでしょうか?
フレームの時間経過分の位置を表しています。
>は移動位置の分割した数を求める式です。
>これって意味分かってます?
意味はわかるのですが、なんて説明していいのかわかりません。
122ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(205,129ポイント)
Date: 2010/08/26(木) 22:53
No:60233
|
|
Title: Re:当たり判定について
|
|
>フレームの時間経過分の位置を表しています。
???
tは1以上になりませんよ。tの値は0〜1の範囲です。
言葉の間違いかも知れませんが。
じゃあ、回答No:58917を使ってWinMainだけを付け加えてt=0.7の時に衝突するプログラムを作ってみてください。
計算の意味がが分かっているならx1,v1,r1などの値も決められるはずです。
画像表示が大変だったら、printfDXだけでも構いません。tの変化と衝突の有無、2つの物体の位置も表示してください。
181ポイント を手に入れた。
|
|
|
|
|
Name: ookami ..熟練のプログラマー(47,325ポイント)
Date: 2010/08/26(木) 23:29
No:60235
|
|
Title: Re:当たり判定について
|
|
なんだか横やりを入れるのがためらわれますが、
たろうさん、「どんな当たり判定を実装したいのか」、すいませんが、もう一度詳しく説明してもらえませんか?
なるべく、誰もが同じように解釈できる表現で、お願いします。
103ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..熟練のプログラマー(40,640ポイント)
Date: 2010/08/27(金) 00:18
No:60237
|
|
Title: Re:当たり判定について
|
|
返信ありがとうございます。
できたのでソース載せます。
#define GLOBAL_INSTANCE
#include "include/DxLib.h"
#include"GV.h"
// 動いてない円同士の当たり判定
int test_circle_circle(float x1, float y1, float r1, float x2, float y2, float r2)
{
float x = x1 - x2;
float y = y1 - y2;
float r = r1 + r2;
return x * x + y * y <= r * r;
}
// 動いている円同士の当たり判定
int atarihantei(
// X座標, Y座標, 半径, 角度, 速度
float x1, float y1, float r1, float a1, float v1,
float x2, float y2, float r2, float a2, float v2)
{
// 経過時間
// 円がそれぞれ a1, a2 の方向に v1, v2 だけ進んだ時間を 1.0 とする
float t = 0.0f;
while (t < 1.0f)
{
// 初期位置から t だけ進んだ円同士の当たり判定を行う
if (test_circle_circle(
x1 + cos(a1) * v1 * t, y1 + sin(a1) * v1 * t, r1,
x2 + cos(a2) * v2 * t, y2 + sin(a2) * v2 * t, r2))
{
return 1;
}
// 適当に時間を進ませる
// ここの値は r1, r2, v1, v2 から適切に求めるべきだけど、ここでは面倒なのでやらない
t += 0.7f;
}
// 初期位置から 1.0 だけ進んだ円同士の当たり判定を行う
return test_circle_circle(
x1 + cos(a1) * v1, y1 + sin(a1) * v1, r1,
x2 + cos(a2) * v2, y2 + sin(a2) * v1, r2);
}
int Prossessloop()
{
if(ProcessMessage()!=0)
return -1;
if(ClearDrawScreen()!=0)
return -1;
GetHitKeyStateAll_2();
GetHitPadStateAll();
return 0;
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
ChangeWindowMode(TRUE);//ウィンドウモード
if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化
while(Prossessloop()!=-1){
//当たり判定
printfDx("%d",atarihantei(7.0f,0.0f,7.0f,0.0f,10.0f,0.0f,0.0f,0.0f,0.0f,0.0f));
//x1を1上げると当たらない、rを下げると当たらない
if(CheckStateKey(KEY_INPUT_ESCAPE)==1)
break;
ScreenFlip();
}
DxLib_End();
return 0;
}
です。
2倍のポイントを手に入れた! 1,442ポイント を手に入れた。
|
|
|
|
|
Name: ookami ..熟練のプログラマー(47,357ポイント)
Date: 2010/08/27(金) 00:30
No:60239
|
|
Title: Re:当たり判定について
|
|
softyaさんは
> t=0.7の時に衝突するプログラムを作ってみてください
との事でしたが、たろうさんのプログラムでは t=0.0の時に衝突するような...
あと、
> tの変化と衝突の有無、2つの物体の位置も表示してください。
は、どこに反映されていますか?
と、あと、私の上の質問も、回答おまちしてます。
47ポイント を落としてしまった。
|
|
|
|
|
Name: たろう ..熟練のプログラマー(40,836ポイント)
Date: 2010/08/27(金) 00:54
No:60240
|
|
Title: Re:当たり判定について
|
|
返信ありがとうございます。
> t=0.7の時に衝突するプログラムを作ってみてください
>との事でしたが、たろうさんのプログラムでは t=0.0の時に衝突するような...
0.7にするの忘れてました。
>衝突の有無。
atarihantei()で判断していると思うのですが
//x1を1上げると当たらない、rを下げると当たらないと書いているのですが、
何か勘違いしていたらすみません。
>2つの物体の位置も表示してください。
これは、 printfDx("%d",atarihantei(7.0f,0.0f,7.0f,0.0f,10.0f,0.0f,0.0f,0.0f,0.0f,0.0f));
のx1とX2、Y1、Y2の所だと思ったのですが・・・
>たろうさん、「どんな当たり判定を実装したいのか」、すいませんが、もう一度詳しく説明してもらえませんか?
>なるべく、誰もが同じように解釈できる表現で、お願いします。
とりあえず、めるぽんさんのような、フレーム数で、当たり判定ができるように実装したいです。
説明が下手でごめんなさい。
196ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..熟練のプログラマー(41,527ポイント)
Date: 2010/08/27(金) 01:41
No:60243
|
|
Title: Re:当たり判定について
|
|
返信ありががとうございます。
ソース変えました。
#define GLOBAL_INSTANCE
#include "include/DxLib.h"
#include"GV.h"
// 動いてない円同士の当たり判定
int test_circle_circle(float x1, float y1, float r1, float x2, float y2, float r2)
{
float x = x1 - x2;
float y = y1 - y2;
float r = r1 + r2;
return x * x + y * y <= r * r;
}
// 動いている円同士の当たり判定
int atarihantei(
// X座標, Y座標, 半径, 角度, 速度
float x1, float y1, float r1, float a1, float v1,
float x2, float y2, float r2, float a2, float v2)
{
// 経過時間
// 円がそれぞれ a1, a2 の方向に v1, v2 だけ進んだ時間を 1.0 とする
float t = 0.0f;
while (t < 1.0f)
{
// 初期位置から t だけ進んだ円同士の当たり判定を行う
if (test_circle_circle(
x1 + cos(a1) * v1 * t, y1 + sin(a1) * v1 * t, r1,
x2 + cos(a2) * v2 * t, y2 + sin(a2) * v2 * t, r2))
{
return 1;
}
// 適当に時間を進ませる
// ここの値は r1, r2, v1, v2 から適切に求めるべきだけど、ここでは面倒なのでやらない
t += 0.1f;
}
// 初期位置から 1.0 だけ進んだ円同士の当たり判定を行う
return test_circle_circle(
x1 + cos(a1) * v1, y1 + sin(a1) * v1, r1,
x2 + cos(a2) * v2, y2 + sin(a2) * v1, r2);
}
int Prossessloop()
{
if(ProcessMessage()!=0)
return -1;
if(ClearDrawScreen()!=0)
return -1;
GetHitKeyStateAll_2();
GetHitPadStateAll();
return 0;
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
ChangeWindowMode(TRUE);//ウィンドウモード
if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化
while(Prossessloop()!=-1){
//当たり判定
printfDx("%d",atarihantei(7.0f,0.0f,7.0f,0.0f,10.0f,21.0f,0.0f,0.0f,0.0f,0.0f));
//x1を1上げると当たらない、rを下げると当たらない
if(CheckStateKey(KEY_INPUT_ESCAPE)==1)
break;
ScreenFlip();
}
DxLib_End();
return 0;
}
です。よろしくお願いします。
691ポイント を手に入れた。
|
|
|
|
|
Name: ookami ..熟練のプログラマー(47,423ポイント)
Date: 2010/08/27(金) 07:39
No:60255
|
|
Title: Re:当たり判定について
|
|
> とりあえず、めるぽんさんのような、フレーム数で、当たり判定ができるように実装したいです。
もうちょっと詳しく書いてもらってもいいですか?
「フレーム数」を具体的にはどうするのでしょう。
「めるぽんさんのような」ではなく、たろうさんの言葉でお聞きしたい。
66ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(205,534ポイント)
Date: 2010/08/27(金) 14:23
No:60282
|
|
Title: Re:当たり判定について
|
|
>例えば、フレーム数を1フレームにつき移動経過時間を計ってそれを調べていくような当たり判定がしたいです。
それは私の例えですね。
ookamiさんの求めているのは、もっと具体的な話だと思いますよ。
ところで私のリクエストは、どうなってます?
99ポイント を手に入れた。
|
|
|
|
|
Name: あろう ..ぴよぴよ(52ポイント)
Date: 2010/08/27(金) 17:18
No:60291
|
|
Title: Re:当たり判定について
|
|
返信ありがとうございます。
>0.0から0.6と0.8から0.9は当たらずに0.7だけに当たるようにしてくださいね。
0.0から0.6までは当たらなくすることは出来るのですが、0.8と0.9は当たらずにすることはできません。
というかできないと思います。
0.8から0.9は範囲内にどうしても入ってしまうからです。
52ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..熟練のプログラマー(41,672ポイント)
Date: 2010/08/27(金) 17:20
No:60292
|
|
Title: Re:当たり判定について
|
|
すみません。名前間違えてしまいました。
返信ありがとうございます。
>0.0から0.6と0.8から0.9は当たらずに0.7だけに当たるようにしてくださいね。
0.0から0.6までは当たらなくすることは出来るのですが、0.8と0.9は当たらずにすることはできません。
というかできないと思います。
0.8から0.9は範囲内にどうしても入ってしまうからです。
106ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(206,246ポイント)
Date: 2010/08/27(金) 17:39
No:60294
|
|
Title: Re:当たり判定について
|
|
>0.0から0.6までは当たらなくすることは出来るのですが、0.8と0.9は当たらずにすることはできません。
というかできないと思います。
>0.8から0.9は範囲内にどうしても入ってしまうからです。
角度も半径も移動速度も自在に調整できるのになぜ出来ないんでしょうか?
理由を教えてください。
ちなみに私は実行できていないのでプログラムを検証していません。
理由は既に書いてあります。
155ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..熟練のプログラマー(42,691ポイント)
Date: 2010/08/27(金) 18:23
No:60303
|
|
Title: Re:当たり判定について
|
|
すみません。気づきませんでした。
>角度も半径も移動速度も自在に調整できるのになぜ出来ないんでしょうか?
>理由を教えてください。
V1の移動速度が10でa1の角度0、r1の半径1.2、V2が8,a2が0,r2が0.0にした場合、
tが0.1の時
return x * x + y * y <= r * r;
のxが0.2、yが0で、rが1.2で当たらなくて、
それをtが0.6まで進めて、tが0.7のときxが1.2でyが0で当たってtが0.8のときが1.4になり当たりになり0.9で1.6になり当たりになるからです。
ソース変えました。
#define GLOBAL_INSTANCE
#include "include/DxLib.h"
#include<math.h>
//#include"GV.h"
// 動いてない円同士の当たり判定
int test_circle_circle(float x1, float y1, float r1, float x2, float y2, float r2)
{
float x = x1 - x2;
float y = y1 - y2;
float r = r1 + r2;
return x * x + y * y <= r * r;
}
// 動いている円同士の当たり判定
int atarihantei(
// X座標, Y座標, 半径, 角度, 速度
float x1, float y1, float r1, float a1, float v1,
float x2, float y2, float r2, float a2, float v2)
{
// 経過時間
// 円がそれぞれ a1, a2 の方向に v1, v2 だけ進んだ時間を 1.0 とする
float t = 0.0f;
while (t < 1.0f)
{
// 初期位置から t だけ進んだ円同士の当たり判定を行う
if (test_circle_circle(
x1 + cos(a1) * v1 * t, y1 + sin(a1) * v1 * t, r1,
x2 + cos(a2) * v2 * t, y2 + sin(a2) * v2 * t, r2))
{
return 1;
}
// 適当に時間を進ませる
// ここの値は r1, r2, v1, v2 から適切に求めるべきだけど、ここでは面倒なのでやらない
t += 0.1f;
}
// 初期位置から 1.0 だけ進んだ円同士の当たり判定を行う
return test_circle_circle(
x1 + cos(a1) * v1, y1 + sin(a1) * v1, r1,
x2 + cos(a2) * v2, y2 + sin(a2) * v1, r2);
}
int Prossessloop()
{
if(ProcessMessage()!=0)
return -1;
if(ClearDrawScreen()!=0)
return -1;
return 0;
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
ChangeWindowMode(TRUE);//ウィンドウモード
if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化
while(Prossessloop()!=-1){
//当たり判定
printfDx("%d",atarihantei(7.0f,0.0f,7.0f,0.0f,10.0f,21.0f,0.0f,0.0f,0.0f,0.0f));
//x1を1上げると当たらない、rを下げると当たらない
ScreenFlip();
}
DxLib_End();
return 0;
}
1,019ポイント を手に入れた。
|
|
|
|
|
Name: ookami ..熟練のプログラマー(47,968ポイント)
Date: 2010/08/27(金) 18:48
No:60306
|
|
Title: Re:当たり判定について
|
|
softyaさんは、
「なぜ当たってしまうか」ではなく
「なぜ当たらないようにできないのか」を聞いているように思います。
atarihanteiに渡すパラメータ次第で、
0.7で当たり、0.8,0.9では当たらないように
できると思います。
> 例えば、フレーム数を1フレームにつき移動経過時間を計ってそれを調べていくような当たり判定がしたいです。
「それ」を具体的に書いてみて下さい。
あと、「ような」ということは、
たろうさんの中でも、
はっきりしていないんでしょうか?
93ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(205,499ポイント)
Date: 2010/08/27(金) 18:48
No:60307
|
|
Title: Re:当たり判定について
|
|
少々処理を変えました。これを使ってください。
それと、半径、角度、速度をうまく調整すればt=0.7の近辺だけ当たる様に必ず出来ます。
【追記】
もし出来ないなら図形のイメージ、動きのイメージ、アルゴリズムのイメージがちゃんと出来ていない事になります。
#define GLOBAL_INSTANCE
#include "include/DxLib.h"
#include<math.h>
//#include"GV.h"
// 動いてない円同士の当たり判定
int test_circle_circle(float x1, float y1, float r1, float x2, float y2, float r2)
{
float x = x1 - x2;
float y = y1 - y2;
float r = r1 + r2;
return x * x + y * y <= r * r;
}
// 動いている円同士の当たり判定
int atarihantei(
// X座標, Y座標, 半径, 角度, 速度
float x1, float y1, float r1, float a1, float v1,
float x2, float y2, float r2, float a2, float v2,
float count
)
{
// 経過時間
// 円がそれぞれ a1, a2 の方向に v1, v2 だけ進んだ時間を 1.0 とする
float t = 0.0f;
while (t < 1.0f)
{
// 初期位置から t だけ進んだ円同士の当たり判定を行う
if (test_circle_circle(
x1 + cos(a1) * v1 * t, y1 + sin(a1) * v1 * t, r1,
x2 + cos(a2) * v2 * t, y2 + sin(a2) * v2 * t, r2))
{
printfDx("t=%f count=%2.f hit=1\n",t,count);
return 1;
}
// 適当に時間を進ませる
// ここの値は r1, r2, v1, v2 から適切に求めるべきだけど、ここでは面倒なのでやらない
t += (1/count);
}
// 初期位置から 1.0 だけ進んだ円同士の当たり判定を行う
int hit =test_circle_circle(
x1 + cos(a1) * v1, y1 + sin(a1) * v1, r1,
x2 + cos(a2) * v2, y2 + sin(a2) * v1, r2);
printfDx("t=1 count=%2.f hit=%d\n",count,hit);
return hit;
}
int Prossessloop()
{
if(ProcessMessage()!=0)
return -1;
if(ClearDrawScreen()!=0)
return -1;
return 0;
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
ChangeWindowMode(TRUE);//ウィンドウモード
if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化
while(Prossessloop()!=-1){
//当たり判定
// X座標, Y座標, 半径, 角度, 速度
for( int icount=1 ; icount<=10 ; icount++ ) {
atarihantei(7.0f, 0.0f, 7.0f, 0.0f, 10.0f,
21.0f,0.0f, 0.0f, 0.0f, 0.0f,
(float)icount);
}
//x1を1上げると当たらない、rを下げると当たらない
ScreenFlip();
}
DxLib_End();
return 0;
} 
908ポイント を落としてしまった。
|
|
|
|
|
Name: たろう ..熟練のプログラマー(42,789ポイント)
Date: 2010/08/27(金) 19:42
No:60313
|
|
Title: Re:当たり判定について
|
|
>もし出来ないなら図形のイメージ、動きのイメージ、アルゴリズムのイメージがちゃんと出来ていない事になります。
出来ていないみたいです。
すみません。
一つ聞いてもよろしいでしょうか?
角度は0のままでも出来るのでしょうか?
98ポイント を手に入れた。
|
|
|
|
|
Name: ookami ..熟練のプログラマー(48,048ポイント)
Date: 2010/08/27(金) 21:43
No:60329
|
|
Title: Re:当たり判定について
|
|
確認なんですが、たろうさんがやりたい当たり判定では、
図のような場合は、当たりとみなしますか?
赤・青、それぞれ、矢印の尾が移動前、先が移動後です。
42ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..熟練のプログラマー(42,884ポイント)
Date: 2010/08/27(金) 22:22
No:60346
|
|
Title: Re:当たり判定について
|
|
softyaさん
返信ありがとうございます。
わかっていなかったみたいです。
ヒントでもいいので教えてもらえませんでしょうか?
66ポイント を手に入れた。
|
|
|
|
|
Name: ookami ..熟練のプログラマー(48,002ポイント)
Date: 2010/08/27(金) 22:52
No:60358
|
|
Title: Re:当たり判定について
|
|
確認しますが、
たろうさんがやりたい当たり判定では、
No.60350でもNo.60354でも、当たってないとみなす、
ということで、ファイナルアンサー?
61ポイント を落としてしまった。
|
|
|
|
|
Name: softya [URL] ..ハッカー(206,359ポイント)
Date: 2010/08/27(金) 22:59
No:60362
|
|
Title: Re:当たり判定について
|
|
ookamiさんの質問の意図は、
>確認なんですが、たろうさんがやりたい当たり判定では、
>図のような場合は、当たりとみなしますか?
なので、それに沿っての返答を求められていると思いますよ。
>わかっていなかったみたいです。
>ヒントでもいいので教えてもらえませんでしょうか?
ヒントと言っても物体2が静止しているならt=0.7だけで当たるためには物体1の速度に応じた適度な小ささの当たり半径を選んでやればそのタイミングだけで当たります。角度0でも。
でも、これは一番簡単な奴なので不十分ですけどね。
図を色々書いてみても分かりませんか?頭の中でイメージできないなら実際に紙の上に書いて考えるしか無いと思いますよ。
310ポイント を手に入れた。
|
|
|
|
|
Name: ookami ..熟練のプログラマー(48,090ポイント)
Date: 2010/08/27(金) 23:06
No:60365
|
|
Title: Re:当たり判定について
|
|
うはwwww ファイナルアンサーに対して罵倒を書くところでしたwwww 確認してよかった。せふせふ。
では、次はこの添付、どう思いますか?
-- 追記:添付しわすれましたw 
32ポイント を手に入れた。
|
|
|
|
|
Name: ookami ..熟練のプログラマー(48,112ポイント)
Date: 2010/08/27(金) 23:19
No:60368
|
|
Title: Re:当たり判定について
|
|
> 当たり範囲に入っていません。
というのは、たろうさんがやりたい当たり判定では、当たってないと見なすんですか?
それとも、関数を工夫して、当たっていると見なせるようにしたいんですか?
22ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(206,515ポイント)
Date: 2010/08/27(金) 23:36
No:60374
|
|
Title: Re:当たり判定について
|
|
良いトレーニング法を思いつきました。
No:60303 でたろうさんの作ったプログラムの物体1と物体2の当たり判定の円を絵に書いてもらえませんか。
tは0.1刻みで0〜1.0の全部を書いてみてください。
2倍のポイントを手に入れた! 156ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(206,639ポイント)
Date: 2010/08/28(土) 11:03
No:60407
|
|
Title: Re:当たり判定について
|
|
>返信ありがとうございます。
>t0.0〜0.5まで書いてみました。
>当たり判定はこんな感じですよね?
No:60303のプログラムの
printfDx("%d",atarihantei(7.0f,0.0f,7.0f,0.0f,10.0f,21.0f,0.0f,0.0f,0.0f,0.0f));
のパラメータで動かした場合の図形ですよね?
物体1と物体2で色変えてもらって良いですか。
それと0.0か1.0まで全てお願いします。
ちゃんと計算して数値も書いてくださいね。
※ プログラムで計算しても良いですけどね。 
124ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..熟練のプログラマー(43,848ポイント)
Date: 2010/08/28(土) 19:23
No:60453
|
|
Title: Re:当たり判定について
|
|
返信ありがとうございます。
出来ました。
#define GLOBAL_INSTANCE
#include "include/DxLib.h"
#include<math.h>
// 動いてない円同士の当たり判定
int test_circle_circle(float x1, float y1, float r1, float x2, float y2, float r2)
{
float x = x1 - x2;
float y = y1 - y2;
float r = r1 + r2;
return x * x + y * y <=r*r;
}
// 動いている円同士の当たり判定
int atarihantei(
// X座標, Y座標, 半径, 角度, 速度
float x1, float y1, float r1, float a1, float v1,
float x2, float y2, float r2, float a2, float v2
)
{
// 経過時間
// 円がそれぞれ a1, a2 の方向に v1, v2 だけ進んだ時間を 1.0 とする
float t = 0.0f;
while (t < 1.0f)
{
// 初期位置から t だけ進んだ円同士の当たり判定を行う
if (test_circle_circle(
x1 + cos(a1) * v1 * t, y1 + sin(a1) * v1 * t, r1,
x2 + cos(a2) * v2 * t, y2 + sin(a2) * v2 * t, r2))
{
return 1;
}
// 適当に時間を進ませる
// ここの値は r1, r2, v1, v2 から適切に求めるべきだけど、ここでは面倒なのでやらない
t +=0.1;
}
// 初期位置から 1.0 だけ進んだ円同士の当たり判定を行う
return test_circle_circle(
x1 + cos(a1) * v1, y1 + sin(a1) * v1, r1,
x2 + cos(a2) * v2, y2 + sin(a2) * v2, r2); ;
}
int Prossessloop()
{
if(ProcessMessage()!=0)
return -1;
if(ClearDrawScreen()!=0)
return -1;
return 0;
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
ChangeWindowMode(TRUE);//ウィンドウモード
if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化
while(Prossessloop()!=-1){
//当たり判定
// X座標, Y座標, 半径, 角度, 速度
printfDx("%d",atarihantei(0.7f,0.0f,0.00000023841858f,//0にしたいのですがプログラムで計算されると誤差が出えるのでこの数値にしました。
0.0f,1.0f, 2.1f,0.0f,0.0f,0.0f,-1.0f));
//x1を1上げると当たらない、rを下げると当たらない
ScreenFlip();
}
DxLib_End();
return 0;
}
691ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(207,196ポイント)
Date: 2010/08/28(土) 19:36
No:60456
|
|
Title: Re:当たり判定について
|
|
>返信ありがとうございます。
>出来ました。
えーと何が?は冗談として、えらく極端な衝突パターンで来ましたね。
理解度を確認したいので図は必ず書いてくださいね。
1)最初のNo:60303
2)最新のNo:60453
の両方でお願いします。
【追記】
ookamiさんの最後の質問にも答えてくださいね。 
109ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(207,689ポイント)
Date: 2010/08/28(土) 20:50
No:60465
|
|
Title: Re:当たり判定について
|
|
とりあえず、No:60303のやつは、
// X座標, Y座標, 半径, 角度, 速度
atarihantei(7.0f,0.0f,7.0f,0.0f,10.0f,
21.0f,0.0f,0.0f,0.0f,0.0f));
ですよね。
X座標, Y座標, 半径, 角度, 速度
物体1 7.0 0.0 7.0 0 10.0
物体2 21.0 0 0 0 0.0
なので物体2は座標(21,0)に静止する(速度0)半径0の当たり範囲もつ物体というわけです。
図と違いますよね?
それと物体1は座標(7,0)から速度10.0/フレームで角度0で移動する当たり判定半径7の円をもつ物体ですよね。
これも図と違うと思います。
ちゃんと計算すれば分かる話ですので、
1.まずちゃんと計算して表などにまとめること。
2.グラフ用紙などに計算結果を反映した図を書くこと。
以上をやってみてください。
出来れば、表だけ先にここに書いてもらうと間違っているかすぐ分かります。
419ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..熟練のプログラマー(44,011ポイント)
Date: 2010/08/28(土) 21:15
No:60474
|
|
Title: Re:当たり判定について
|
|
softyaさん返信ありがとうございます。
物体2は静止してます。
赤い丸がそうなんですが。
>それと物体1は座標(7,0)から速度10.0/フレームで角度0で移動する当たり判定半径7の円をもつ物体ですよね。
当たり判定のx座標を載せていなかったのが間違っていたのでしょうか?
ookamiさん返信ありがとうございます。
>数式で表現できますか?
((x0-?)*cos(a),(y0-?)*sin(a))ですよね。
図のような場合は、当たりとみなしますか?
みなします。
122ポイント を手に入れた。
|
|
|
|
|
Name: ookami ..熟練のプログラマー(48,391ポイント)
Date: 2010/08/28(土) 21:27
No:60476
|
|
Title: Re:当たり判定について
|
|
> ((x0-?)*cos(a),(y0-?)*sin(a))ですよね。
> 図のような場合は、当たりとみなしますか?
> みなします。
ちょっと心が折れそうなのでまた明日お返事します。
もう一度よく考えてみてください。
その回答は、単に間違っているというだけではありません。
すごくまずいです。
54ポイント を落としてしまった。
|
|
|
|
|
Name: softya [URL] ..ハッカー(207,573ポイント)
Date: 2010/08/28(土) 21:36
No:60478
|
|
Title: Re:当たり判定について
|
|
>物体2は静止してます。
>赤い丸がそうなんですが。
図の解釈が間違っているかも知れませんが、赤い丸も緑い丸が移動している様に見えます。
すいません、図にある赤い丸、緑の丸、青丸の意味を教えてください。
それとt=0から1.0までの物体1と2の座標と当たり半径の大きさを書いてもらっても良いですか。
>>それと物体1は座標(7,0)から速度10.0/フレームで角度0で移動する当たり判定半径7の円をもつ物体ですよね。
>当たり判定のx座標を載せていなかったのが間違っていたのでしょうか?
図に描かれている数値は座標ではないのでしょうか?
116ポイント を落としてしまった。
|
|
|
|
|
Name: ookami ..熟練のプログラマー(48,523ポイント)
Date: 2010/08/28(土) 21:42
No:60480
|
|
Title: Re:当たり判定について
|
|
> (r*cos(a),r*sin(a))です。
違います。移動量ではなく座標を聞いています。
あと、「当たるとみなす」ほうは、どうなんです?
--
念のためですが、
ここまで皆さんが紹介されてきたアルゴリズムは、
どれも、すりぬけ(トンネリング)や、
逆に当たっていないのに当たったことにしてしまう場合がある半面、
計算量が少ないなどのメリットがあるから紹介してくださっていることを、理解していますか? 
132ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..熟練のプログラマー(44,081ポイント)
Date: 2010/08/28(土) 21:43
No:60481
|
|
Title: Re:当たり判定について
|
|
すみません。
?のところを書けばよかったのでしょうか?
だとしたら
(x0+r*cos(a),y0+r*sin(a))です。
2倍のポイントを手に入れた! 58ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..熟練のプログラマー(44,195ポイント)
Date: 2010/08/28(土) 21:53
No:60483
|
|
Title: Re:当たり判定について
|
|
赤い丸は、物理1、で緑の丸は物理2で青はここまで当たり判定するです。
>それとt=0から1.0までの物体1と2の座標と当たり半径の大きさを書いてもらっても良いですか。
座標は、(14,0)(13,0)(12,0)(11,0)(10,0)(9,0)(8.0)(7,0)(6,0)(5,0)です。
当たり半径は7です。
>図に描かれている数値は座標ではないのでしょうか?
書き間違えました。すみません。座標です。(x座標の)
114ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(207,615ポイント)
Date: 2010/08/28(土) 22:05
No:60485
|
|
Title: Re:当たり判定について
|
|
>赤い丸は、物理1、で緑の丸は物理2で青はここまで当たり判定するです。
ごめんなさい。やっぱり分からないです。
当たり半径は図に書いてないと思って良いですか?
>座標は、(14,0)(13,0)(12,0)(11,0)(10,0)(9,0)(8.0)(7,0)(6,0)(5,0)です。
>当たり半径は7です。
これは物体1ですよね?
スタートの座標に14がくるのが分かりません。
(14,0)を求めた式と当てはめた数値を書いてもらって良いでしょうか?
>書き間違えました。すみません。座標です。(x座標の)
これは何のX座標でしょうか?
物体1とも違うわけですよね?
2倍のポイントを手に入れた! 10ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..熟練のプログラマー(43,870ポイント)
Date: 2010/08/28(土) 22:26
No:60488
| 解決!
|
Title: Re:当たり判定について
|
|
説明が下手ですみません。
>当たり半径は図に書いてないと思って良いですか?
いいです。
>スタートの座標に14がくるのが分かりません。
// 初期位置から t だけ進んだ円同士の当たり判定を行う
if (test_circle_circle(
7 + cos(0) * 10 * 0, y1 + sin(a1) * v1 * t, r1,
21 + cos(0) * 0 * 0, y2 + sin(a2) * v2 * t, r2))
>これは何のX座標でしょうか?
当たり判定のx座標です。
int test_circle_circle(float x1, float y1, float r1, float x2, float y2, float r2)
{
float x = x1 - x2;
float y = y1 - y2;
float r = r1 + r2;
return x * x + y * y <=r*r; ここのx座標
}
>物体1とも違うわけですよね?
物体1と物体2の当たり判定です。
説明が下手でほんと申し訳ありません。
とりあえず解決とします。こんな馬鹿な自分ですが、
こんな人に回答していただきまして誠に本当にありがとうございました。
325ポイント を落としてしまった。
|
|
|
|
|
Name: softya [URL] ..ハッカー(207,168ポイント)
Date: 2010/08/28(土) 22:47
No:60489
|
|
Title: Re:当たり判定について
|
|
ここまでやったなら最後までやりませんか?
ookamiさんにの最後の質問にも答えてませんし。
>return x * x + y * y <=r*r; ここのx座標
これはX座標ではなく、物体1と2のX方向の距離です。
>当たり判定のx座標です。
つまり物体同士の距離を表す図って事になりますよね。
うーん、それでも図は良く分かりません。
私は、
>No:60303 でたろうさんの作ったプログラムの物体1と物体2の当たり判定の円を絵に書いてもらえませんか。
とお願いしたハズなので、tの値それぞれの時に物体の存在する座標と当たり判定の範囲が分かればよかったのですが。
つまり、スタート地点(t=0)だと座標(7,0)に半径7の円を書いてもらって、これをt=1.0まで書いてもらえば良いんです。これを書くだけでかなりイメージ出来ると思うんですけど。
217ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..熟練のプログラマー(43,988ポイント)
Date: 2010/08/28(土) 23:40
No:60497
|
|
Title: Re:当たり判定について
|
|
返信ありがとうございます。
最後までやるつもりです。
画像です。
ookamiさん
気づきませんでした。
>計算量が少ないなどのメリットがあるから紹介してくださっていることを、理解していますか?
知りませんでした。こんな計算があるんだなとしか。
118ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(207,507ポイント)
Date: 2010/08/29(日) 00:12
No:60501
|
|
Title: Re:当たり判定について
|
|
この図は、No:60303 のものでしょうか?
だとすると円の半径は7ですので今の図だと移動距離に比べて円が小さいです。
それと半径は固定されているので最後の位置の(17,0)までずっと同じ大きさの円になります。
>知りませんでした。こんな計算があるんだなとしか。
当たり判定の正確さとCPUの負荷はトレードオフです。
どこかで妥協しないといけません。
ある程度までは工夫で高速化出来ます。
2倍のポイントを手に入れた! 286ポイント を手に入れた。
|
|
|
|
|
Name: ookami ..熟練のプログラマー(49,103ポイント)
Date: 2010/08/29(日) 00:17
No:60503
|
|
Title: Re:当たり判定について
|
|
>> ここまで皆さんが紹介されてきたアルゴリズムは、
>> どれも、すりぬけ(トンネリング)や、
>> 逆に当たっていないのに当たったことにしてしまう場合がある半面、
>> 計算量が少ないなどのメリットがあるから紹介してくださっていることを、理解していますか?
> 知りませんでした。
これまでの皆さんのアドバイスを振り返ってみましょう。
# No:58756
# 1.移動のフレームレートを上げる。
# 1フレームの間に10回移動させてやっても結構平気だったります。こうすることでトンネリングの発生する確率はかなり低くなると思います。
# 2.円が移動してできた軌跡同士で当たり判定を行う。
# ただし、明らかに当たってない場合も当たってしまうと判断されてしまう場合があります。
# No:58896
# ある時刻と別の時刻では衝突していないが、その間の時間に当る可能性を見過ごしている。
# もちろん、この時間を短くすることによってより正確に判定することは可能であるが、
# 厳密な判定をするためには限りなく無限小に近い時間間隔で計算しなければならず、ゲームに必要な高速性を維持することができない。
# No:59054
# 線分交差法は厳密な意味で考えると駄目だとおもってます。
# ただ厳密性がどこまで必要かも考える必要がありますよね。
# No:59126
# この線分交差による判定方法がダメだということではなく、
# こういった状況が発生したときに、たろうさんの作っているゲームはそれが許容できるのかどうかということになってきます。
# No:59296
# v1 や v2 が r1 や r2 の 10 倍以上の大きさになっている場合にはやっぱりすり抜けてしまう現象が起きてしまう可能性が高くなってしまいます。
ちょっと挙げるの疲れてきましたが、
みなさんが、「いろいろな方法があるが、精度もいろいろだ」と
たろうさんに仰っているんです。
580ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..熟練のプログラマー(44,124ポイント)
Date: 2010/08/29(日) 18:25
No:60578
|
|
Title: Re:当たり判定について
|
|
softyaさん返信ありがとうございます。
>この図は、No:60303 のものでしょうか?
>だとすると円の半径は7ですので今の図だと移動距離に比べて円が小さいです。
>それと半径は固定されているので最後の位置の(17,0)までずっと同じ大きさの円になります。
同じ円が書けなかったのでばらばらな円になってしまいましたが。同じ円です。すみません。
円で書くとどうなるんでしょうか?
ookamiさん返信ありがとうございます。
そうだったんですか、あまり考えていなかったので、全然気づきませんでした。
136ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(210,043ポイント)
Date: 2010/08/29(日) 18:56
No:60584
|
|
Title: Re:当たり判定について
|
|
>同じ円が書けなかったのでばらばらな円になってしまいましたが。同じ円です。すみません。
>円で書くとどうなるんでしょうか?
移動距離が1ピクセルづつに対して円の半径が7ピクセル(直径14ピクセル)なんですが大体想像できませんか?
1cm毎ずらしながら半径7cmの円を11個書くのと同じです。想像できないならグラフ用紙に書いてみたほうが良いと思いますけど。
>ookamiさん返信ありがとうございます。
>そうだったんですか、あまり考えていなかったので、全然気づきませんでした。
理解度が不明なので、もう少し詳しくookamiさん向けに返事してくださいね。
No:60503 と No:60505 の内容にまったく触れられてません。
267ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..熟練のプログラマー(44,256ポイント)
Date: 2010/08/29(日) 18:59
No:60585
|
|
Title: Re:当たり判定について
|
|
>移動距離が1ピクセルづつに対して円の半径が7ピクセル(直径14ピクセル)なんですが大体想像できませんか?
1cm毎ずらしながら半径7cmの円を11個書くのと同じです。想像できないならグラフ用紙に書いてみたほうが良いと思いますけど。
そのつもりで書いたのですが・・・
132ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(210,132ポイント)
Date: 2010/08/29(日) 19:25
No:60589
|
|
Title: Re:当たり判定について
|
|
>そのつもりで書いたのですが・・・
本当に定規とコンパスで書いてみると分かります。1cmづつ移動する半径7cmの円ですよ。
フリーハンドで書いても絶対にこんな円の重なり方はしません。
信じてやってみてください。
こちらで答えを書いても良いのですが、それでは図形を考えるトレーニングになりませんので。
89ポイント を手に入れた。
|
|
|
|
|
Name: ookami ..熟練のプログラマー(49,295ポイント)
Date: 2010/08/29(日) 19:44
No:60594
|
|
Title: Re:当たり判定について
|
|
>> みなさんが、「いろいろな方法があるが、精度もいろいろだ」と
>> たろうさんに仰っているんです。
> そうだったんですか、あまり考えていなかったので、全然気づきませんでした。
もうちょっと書き方を工夫したほうがいいと思いますよ?
たろうさんが考えないで、他に誰が考えるんですか?
2倍のポイントを手に入れた! 92ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..ウィザード(1,265,228ポイント)
Date: 2010/08/30(月) 08:13
No:60667
|
|
Title: Re:当たり判定について
|
|
> たろうさん
規約に従って利用して下さっているにも関わらずすみません。
ここの掲示板の仕様上、1トピック内のレス数があまりにも多いと掲示板のトップページ全体に表示される最新トピック数が減ってしまうようです。
その為、更新から24時間経過していないトピックが過去ログに落ちてしまう場合がいくつか発生しています。
一応掲示板では1質問1トピックを基本とさせて頂いています。
話が長くなってしまう場合や、関連した話でわざわざ別にトピックを立てる必要が無い場合もあると思いますが、
なるべく後から見た人が解りやすいようにトピックごとに細かく質問をわけ、関連性が高い時は、前トピックのリンクを貼って頂けると幸いです。
196ポイント を手に入れた。
|
|
|
|
Name: まる ..入門者(4,372ポイント)
Date: 2010/08/29(日) 13:48
No:60551
|
|
Title: InterfaceBuilderとloadviewの混在
|
|
言語:objective-c
iphoneアプリの制作をしているのですが、
InterfaceBuilderでImageViewや、ボタン配置し、
ViewController.mのloadviewで背景色の設定するように
役割分担させてつくりたいとき、
loadviewの背景色で画面が全部うめられて
IBで作成したボタンなどがみえなくなります。
これを回避するにはどのようにすればいいでしょうか?
loadviewの背景色設定は一般的なコードです。
- (void)loadView
{
CGRect frame = [[UIScreen mainScreen] bounds];
//親Viewに配置された時の位置と大きさ情報付きでViewControllerの持つViewを初期化
self.view = [[[UIView alloc] initWithFrame:frame] autorelease];
self.view.backgroundColor = [UIColor blueColor];
}
215ポイント を手に入れた。
|
|
|
|
Name: Justy ..伝説なるハッカー(570,286ポイント)
Date: 2010/08/29(日) 21:24
No:60623
|
|
Title: Re:InterfaceBuilderとloadviewの混在
|
|
>ViewController.mのloadviewで背景色の設定するように
>役割分担させてつくりたいとき、
loadviewは nibを使わない時に使うものですので、loadviewは全て削除し viewDidLoadの方を
使って下さい。
78ポイント を手に入れた。
|
|
|
|
|
Name: まる ..入門者(4,691ポイント)
Date: 2010/08/30(月) 01:07
No:60653
|
|
Title: Re:InterfaceBuilderとloadviewの混在
|
|
viewDidLoadに同じコードを書いてもIBで作成したボタン等かくれちゃいますね。
なにがわるいんだろ。。。
32ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..伝説なるハッカー(570,799ポイント)
Date: 2010/08/30(月) 01:19
No:60654
|
|
Title: Re:InterfaceBuilderとloadviewの混在
|
|
self.viewを上書きしてしまっているのが原因なんじゃないかなと。
[super viewDidLoad];
self.view.backgroundColor = [UIColor blueColor];
だけ書いたらどうなりますか?
2倍のポイントを手に入れた! 206ポイント を手に入れた。
|
|
|
|
|
Name: まる ..入門者(4,711ポイント)
Date: 2010/08/30(月) 08:11
No:60666
| 解決!
|
Title: Re:InterfaceBuilderとloadviewの混在
|
|
Justyさんのご指摘通り修正するといけました。
ありがとうございました!
20ポイント を手に入れた。
|
|
|
|
Name: 斉藤 ..ぴよぴよ(447ポイント)
Date: 2010/08/29(日) 19:54
No:60596
|
|
Title: 学校の課題
|
|
学校の課題があり、こちらのサイト様を参考に作っていたのですがご相談ごとがあり、書き込ませていただきました。僕の学校は、工業系でもない普通科の学校なので先生もC言語などについてはわからないので、自分一人でやらなくてはなりません。でも、頭もわるくてなかなか覚えられないし、出来るか不安になってきました。僕以外にもゲームを作る人が居て、みんな買ってきた参考書などを参考に参考書と同じものを作っています。それで、僕も此方のサイト様を参考に作ろうと思っているのですが、ネットを参考書として作るゲームと本を片手に作るのでは何か違いがありますか?みんな参考書と全く同じゲームを作ろうとしているので、僕も興味のある弾幕ゲームをこちらのサイト様の説明とおりに作っています。その場合、ネット使ってるほうが卑怯、といわれないか心配です。参考書とおりに作ろうとしているのなら、ネット見ながらでも本見ながらでも同じですよね・・・。説明下手ですみません。
214ポイント を手に入れた。
|
|
|
|
Name: シエル [URL] ..熟練のプログラマー(65,413ポイント)
Date: 2010/08/29(日) 20:14
No:60601
|
|
Title: Re:学校の課題
|
|
?何をお困りなのかよく分からないのですが、すばらしい参考書であれば良いゲームが作れますし、
良くない参考書であれば、ネットの方が良いゲームが作れるかもしれません。
違いと言われてもどういう意味の違いですか?
私も何を答えればいいか分からなくなってきました;
115ポイント を手に入れた。
|
|
|
|
|
Name: ookami ..熟練のプログラマー(49,481ポイント)
Date: 2010/08/29(日) 20:16
No:60602
|
|
Title: Re:学校の課題
|
|
別段、ネットだから卑怯ということは、まったくないと思いますけども...
本にもネットにも、それぞれの良さがあると思います。
ところで、
「普通科の学校なので先生もC言語などについてはわからない」のに「学校の課題」があるんですか?
78ポイント を手に入れた。
|
|
|
|
|
Name: h2so5 ..かけだし(1,961ポイント)
Date: 2010/08/29(日) 20:17
No:60603
|
|
Title: Re:学校の課題
|
|
ネットの場合だとコピー&ペーストするほうが楽でやってしまいがちなので
本を見て手入力する場合に比べると覚えが悪いかもしれません。
(本の場合でも付属CDからそのままコピーしてたら同じですが)
でも違いはそれくらいしかない気がします。
87ポイント を手に入れた。
|
|
|
|
|
Name: たいちう ..ハッカー(102,020ポイント)
Date: 2010/08/29(日) 20:28
No:60605
|
|
Title: Re:学校の課題
|
|
> その場合、ネット使ってるほうが卑怯、といわれないか心配です。
何が卑怯で何が卑怯でないかは仲間内で決めて下さい。
子供の遊びのようなもので、ローカルルールに従ってください。
> 参考書とおりに作ろうとしているのなら、ネット見ながらでも本見ながらでも同じですよね・・・。
そのことをあなたが相手に説得できるならば何も問題はありません。
逆に説得できないならば、この掲示板の世論に意味はありません。
第三者として判定しようにも、あなたの説明では状況が理解できません。
どうしても第三者の意見が聞きたいならば、聞き方を覚えることです。
96ポイント を手に入れた。
|
|
|
|
|
Name: パコネコ ..プログラマー(36,798ポイント)
Date: 2010/08/29(日) 20:33
No:60610
|
|
Title: Re:学校の課題
|
|
>>ネットを参考書として作るゲームと本を片手に作るのでは何か違いがありますか?
どこを参考にするのかとか、どの本を参考にするとかで違う気がします。
多分、ネットだとコピー&ペーストができるので、その辺で差が出るのではないでしょうか?
ここのサイトを参考にしてるらしいのでコピー&ペーストを使って勉強なさっていると思うのですが、
意味を理解しながらでしたら、問題ないと思います…
すべてコピー&ペーストで済ませてしまうとさすがに卑怯だと言われかねない気もします。
ですが自分で理解したうえで、自分なりの改良を加えているのならいいと思います。
ですが結局、私は卑怯だと思うかは人それぞれだと思います。
私なら自分が時間をかけて作っているものが隣で?さくさくと作業していましたら、
ひがんでしまう気がします。
自分と違う手段を使っている部分を…
参考書を見ながらだとどうしてもすべて打ち込む形になりますから。
(参考書にDVD?がついてる時もありますけど…)
あ、ちなみに私が思う違いは、スピードです。(あとはお金…と、習得率?
本は本でいい部分ありますけど…電車の中やちょっとした時間でも、勉強できますから。
本のほうが力はつくと思っています。(難しいものはですが。
私は、ネットの内容をノートに書いてから必要な部分をノートを見ながら作っています。
(あほみたいに時間がかかる…お勧めじゃない)
時々参考書も見ながらノート作ったり…
91ポイント を落としてしまった。
|
|
|
|
|
Name: 斉藤 ..ぴよぴよ(742ポイント)
Date: 2010/08/29(日) 20:34
No:60611
|
|
Title: Re:学校の課題
|
|
お返事ありがとうございます。
シエルさん→そうですね!ありがとうございます。
説明が下手ですみませんでした;
ookamiさん→はい、そうなんです・・。一年通してやるんですが、今度中間発表がありまして・・。普通科なんですが、3年生の課題研究で将来の夢とかに関係ある課題を自分で考えなくてはいけないのですが最初は調べるだけのものだったのが、形に残るものを作らなきゃいけないと言われ、勝手にゲーム製作にされてしまいました;なので、言うだけ言われて、先生はなんのアドバイスもいただけないので困ってしまって・・・。
h2so5さん→はい、それは僕も不安なんです;コピペしただけといわれてしまわないか・・。とりあえず、頑張って作ってみます!ありがとうございます。
295ポイント を手に入れた。
|
|
|
|
|
Name: h2so5 ..かけだし(2,236ポイント)
Date: 2010/08/29(日) 20:51
No:60617
|
|
Title: Re:学校の課題
|
|
>はい、それは僕も不安なんです;コピペしただけといわれてしまわないか・・。
コピペしただけと言われるほど同じものを作ったのでは、
本だろうがネットだろうがあまり意味がない気もします。
ベースはコピペが主体でも原型が分からないほど魔改造(?)
すれば結構勉強になるかも。
2倍のポイントを手に入れた! 266ポイント を手に入れた。
|
|
|
|
|
Name: 斉藤 ..ぴよぴよ(882ポイント)
Date: 2010/08/29(日) 22:39
No:60634
|
|
Title: Re:学校の課題
|
|
たいちうさん→僕の聞き方が成っていなくて不愉快な思いにしてしまいすみませんでした。
パコネコさん→細かくコメントして下さりありがとうございます。
そうですね、やっぱりネットで見ながら打ったと言っても
コピペだろ、と思われても仕方ないかもしれないですね・・。
そう言われないようにしたいです。僕の地域の本屋さんに
ゲーム関係の本が売っていなくてネットで調べてみたんですが
通販とかで探して見てみるのもいいかな、と思いました。
h2so5さん→お返事ありがとうございます。
そうですね、作ったあとにC言語をいっぱい理解して
オリジナル性もちゃんと入れたいと思います。
あと、ついでで申し訳ないのですが、
こちらのサイト様のプログラミングの館11章にある
エクセルデータでの敵キャラの数を増やしたりしてる部分の
『もしDXライブラリのファイル読み込み関数の使い方がわからない方は本家で勉強して下さい。』って
本家ってどこのことでしょうか?
ゲームプログラミングの館のことでしょうか?
エクセルを開いてやってみたんですが、csvファイルになってくれなくて困ってます;;
140ポイント を手に入れた。
|
|
|
|
|
Name: h2so5 ..かけだし(2,253ポイント)
Date: 2010/08/29(日) 22:47
No:60636
|
|
Title: Re:学校の課題
|
|
>本家ってどこのことでしょうか?
DXライブラリの配布元です
ttp://homepage2.nifty.com/natupaji/DxLib/
17ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..ウィザード(1,265,173ポイント)
Date: 2010/08/29(日) 22:55
No:60637
|
|
Title: Re:学校の課題
|
|
> 斉藤さん
こんにちは。
本家とは、DXライブラリの公式ホームページの事です。
http://homepage2.nifty.com/natupaji/DxLib/
私は個人的に愛用しているDXライブラリというライブラリの使い方を説明しているサイトを作っているだけです。
本家にはここより沢山情報があるので、是非本家もご覧ください。
というか各関数の仕様は本家のリファレンス無しには解らないでしょう。
(ヘッダを見るだけでわかる方もいらっしゃるでしょうが、そういう方は今回の議論には関係ないでしょう)
しかし普通科なのにプログラムの課題を出すべき場合があるのでしょうか・・?
先生は誰もプログラムの知識が無いということは、先生が求めている課題はこれではないのではないでしょうか?
まずその辺の確認をされた方が良いと思うのですが大丈夫でしょうか。
では、まず斉藤さんはどれ位Cの知識をお持ちですか?
ゲームプログラミングの館でDXライブラリの使い方の基本は解ると思います。
その後まずはジャンケン程度のゲームでもいいので実際に作ってみる事が大事です。
最初から大規模なゲームを作ろうとすると挫折してしまいます。
専門的に勉強しているわけではないのだから、まずジャンケンのようなものが出来ただけでも十分だと思うのですがいかがでしょうか?
まずDXライブラリを使ってキーボード入力やそれに応じた画像の表示をしてみてはどうでしょう。
DXライブラリなら試行錯誤で何とか作れてしまうと思います。
解らないことがあれば都度聞いていただけたら良いと思いますし。
2倍のポイントを手に入れた! 952ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..ウィザード(1,265,264ポイント)
Date: 2010/08/29(日) 23:06
No:60640
|
|
Title: Re:学校の課題
|
|
>> たいちうさん
> きっと勤勉な管理人さんが時間を見つけて(あるのか?)
> 分かりやすいようにしてくれるでしょう。
修正しました^^;
11章の「本家」リンクのみです。
他でもよく本家という言い方は良くしているので他にもあると思いますが・・。
しかしうちの館は本家DXライブラリのことを知らない方がみていらっしゃることは想定していないので;
というか本家を知らずに使いこなせるとは思いませんし・・。
2倍のポイントを手に入れた! 38ポイント を手に入れた。
|
|
|
|
|
Name: 斉藤 ..かけだし(2,338ポイント)
Date: 2010/08/29(日) 23:13
No:60644
| 解決!
|
Title: Re:学校の課題
|
|
h2so5さん→何度も助けてくださり、ありがとうございます!
配布元さんのことでしたか・・;すみません、ありがとうございました!
管理人さん→URL教えて下さり、ありがとうございます。
はい、授業でやっていることは普通科なのですが
3年生になるとそれぞれ自分達の将来に関係のある課題研究をしなくてはならなくて
(パティシエだったら、オリジナルのお菓子を作る・・・とか)
それで、僕はゲーム関係の仕事に就きたくて専門学校目指しているので
ゲームについて調べ学習をしようと思っていたら担任の先生に
「形に残るものを作りなさい」と言われ、どういう課題にしたら良いのかを聞いたら
ゲームを製作しろ、と言われてすることになってしまいました・・。
今更になって人のせいにして、無理だと言うのも嫌なので
頑張ってやっているのですが・・・orz
C言語については『14歳からはじめるわくわくC言語ゲームプログラミング』を一通り終え、
完璧とまではいかないですが、ちょっとは理解しているかな、と思っています。
はいっ、管理人様の言われるようにジャンケンゲームとか簡単(?)なものなども
作ってみたいのですが、僕以外にもゲームを作っている子がいて、
その子たちが凄いゲームを作っているのに自分だけ簡単なもの・・というのも
なんだか恥ずかしく感じて、
そんなこと言ったら失礼なのも分かってるんですが、どうしても比べてしまい;
でも、管理人様のアドバイス聞いて自分でも1から作ってみようかな、と思います・・。
今回は中間発表が明後日に控えているので
とりあえず、学んできたことを発表してゲームは後期の発表でオリジナルを
作ってみたいと思います。
長くなってしまいごめんなさい。お優しいお言葉をかけてくださりありがとうございます。
皆さん、説明が下手ですみませんでした。ありがとうございました。
2倍のポイントを手に入れた! 1,456ポイント を手に入れた。
|
|
|
|
|
Name: 斉藤 ..入門者(2,514ポイント)
Date: 2010/08/29(日) 23:16
No:60645
|
|
Title: Re:学校の課題
|
|
たいちうさん→あわわ、そんなことないです・・!
僕のほうこそ、勘違いして失礼なコメントをしてすみませんでした!
もっときちんと、読んでから投稿するべきでした;
教えていただいた場所を見てみたらありました・・!
管理人様にもお手数かけました;
2倍のポイントを手に入れた! 176ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..ウィザード(1,265,521ポイント)
Date: 2010/08/29(日) 23:47
No:60649
|
|
Title: Re:学校の課題
|
|
中間発表が明後日?!
現在どこまでできているのでしょう?
それによって今後の方針は分かれそうです。
> 14歳からはじめるわくわくC言語ゲームプログラミング
なるほど・・最近は本家を見なくてもDXライブラリについてかなり知っている方がいらっしゃるのですね。
基本がわかったのなら後は試行錯誤であれこれ作るのが一番だと思います。
これだけネットに情報があふれている今日でさえ、
「これが王道だ。これにならってゲームを作れ」と丁寧に教えてくれるサイトは全然見当たりません。
本にはある程度書いてあるでしょうけど、供給が無いということは、結局人にあれこれ教えられるより試行錯誤の方が良いからかもしれません。
もちろん人から学ぶことは大切でしょう。
しかし、趣味のゲーム制作に関しては自分であれこれ考え「おっ、だんだん出来てきた」とか思いながら作ることが楽しみだと思います。
それに試行錯誤で導き出した自分の理論は忘れませんが、本で流し読みした理論はすぐに忘れがちです。
それに前者は応用が利きますが、後者はなかなか難しい場合が多いです。
まぁ学び方は人それぞれだと思うので、参考程度にどうぞ。
257ポイント を手に入れた。
|
|
|
|
|
Name: ookami ..熟練のプログラマー(49,897ポイント)
Date: 2010/08/30(月) 07:44
No:60664
|
|
Title: Re:学校の課題
|
|
> 僕以外にもゲームを作っている子がいて、
> その子たちが凄いゲームを作っているのに自分だけ簡単なもの・・というのも
> なんだか恥ずかしく感じて
私は、他人と比較する必要はないと思いますよ。
その「他の人」が、どうやって作っているかにもよりますし。
(○○ツクールで作れば、短期間でそこそこの物はできる…など)
課題は「形に残すこと」との事なので、何かしら完成させなければ
ならないようですが、最終的に残るのは、苦労して乗り越えた経験、だと思います。
ぜひ頑張ってください。
あと、将来ゲーム業界を目指すなら、何かひとつ、ゲームとして新しいアイデアを
盛り込んだものを作ってから、面接に望むとよいです。
単にプログラマ、というのではなく、「ゲームへの情熱」を語る気迫が違ってきます。
2倍のポイントを手に入れた! 416ポイント を手に入れた。
|
|
|
|
Name: まる ..入門者(4,619ポイント)
Date: 2010/08/29(日) 20:43
No:60615
|
|
Title: アラートウィンドウ消去方法
|
|
言語:obejective-c
UIAlertViewにてボタンなしのアラートウィンドウを作成したのですが
このウィンドウの消去方法がわかりません。
以下のコードで書いてますが表示されるけど消えない状況です。
アラートウィンドウを消すにはどうすればいいでしょうか?
UIAlertView *progressAlert = [[UIAlertView alloc]
initWithTitle:@""
message:@"Please wait..."
delegate:self
cancelButtonTitle:nil
otherButtonTitles:nil];
progressView = [[[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleBar] autorelease];
progressView.frame = CGRectMake(40.0f, 80.0f, 200.0f, 37.0f);
progressView.progress = progressvalue;
[progressAlert addSubview:progressView];
[progressAlert show];
[progressAlert release];
247ポイント を手に入れた。
|
|
|
|
Name: まる ..入門者(4,659ポイント)
Date: 2010/08/30(月) 01:04
No:60652
| 解決!
|
Title: Re:アラートウィンドウ消去方法
|
|
[alert dismissWithClickedButtonIndex:0 animated:FALSE]
をいれることで消えました。
ありがとうございました。
40ポイント を手に入れた。
|
|
|
|
Name: 京 ..かけだし(1,706ポイント)
Date: 2010/08/28(土) 15:23
No:60420
|
|
Title: ビルドできない。
|
|
ビジュアルC++で、タブみたいなので、複数のプログラムを同時に見ることが出来るようなので活用しようとしたら、複数あるタブのうち、2枚目や3枚目のタブが上手く実行できません。F5でビルドすると、 _WinMain@16はすでに1枚めのタブで定義されています。と出てきてビルドエラーになります。正直なにが原因なのかすら判らない状況です。それぞれのタブの中のプログラムだけであれば、(複数のタブを同時に開かなければ)ちゃんと実行できるのですが...
204ポイント を手に入れた。
|
|
|
|
Name: 京 ..かけだし(1,825ポイント)
Date: 2010/08/28(土) 15:32
No:60421
|
|
Title: Re:ビルドできない。
|
|
すいません追記です。
”_WinMain@16はすでに1枚めのタブで定義されています。”の部分ですが、実際には、
”_WinMain@16はファイル名.objで定義されています。”と出てきてました。すいません。また、ファイルをまたいだ別のスクリプトも、同様に一枚目のタブのスクリプトが入っているファイル名.objで定義されていると出てきます。
119ポイント を手に入れた。
|
|
|
|
|
Name: dic ..比類無きプログラマー(92,172ポイント)
Date: 2010/08/28(土) 16:13
No:60424
|
|
Title: Re:ビルドできない。
|
|
WinMainが2つありませんか?
あと、開発環境を書いておいてください
//===============================================================
ビジュアルC++とありますね
もう少し詳しく書くとフォローしてくれる方があらわれるかもしれません
失礼しました

26ポイント を手に入れた。
|
|
|
|
|
Name: シエル ..熟練のプログラマー(63,508ポイント)
Date: 2010/08/28(土) 18:21
No:60433
|
|
Title: Re:ビルドできない。
|
|
エラーのままだと思います。
WinMainが2つ以上定義されていることが原因と思われます。
まあ2010は使ったことないので、詳しいことは分かりませんが。
42ポイント を手に入れた。
|
|
|
|
|
Name: 京 ..かけだし(1,830ポイント)
Date: 2010/08/29(日) 12:41
No:60539
|
|
Title: Re:ビルドできない。
|
|
すいませんWinMainって何ですか。あまりにも初心者過ぎて開発環境とかいわれても何の子とかさっぱり分からないのですが...本当にすいません。
5ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(207,852ポイント)
Date: 2010/08/29(日) 12:52
No:60540
|
|
Title: Re:ビルドできない。
|
|
ゲームプログラミングの館から画像をお借りしてきました。
http://dixq.net/g/00.html
画面の中にWinMainと言うのが見えると思います。
こんなやつ↓
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
これは1つのプロジェクトに1つしか許されません。
>”_WinMain@16はファイル名.objで定義されています。”と出てきてました。すいません。また、ファイルをまたいだ別のスクリプトも、同様に一枚目のタブのスクリプトが入っているファイル名.objで定義されていると出てきます。
このエラーは、WinMain関数が2つある場合に出るエラーですので、2つあるタブと言うのにそれぞれWinMainがある状況じゃないでしょうか?
解決方法は2つ以上作らないことなのですが、何をしたくてこうなってしまったか書いてもらえるとアドバイスがしやすいです。参考にしているサイトを書いてもらった方が良いですね。
262ポイント を手に入れた。
|
|
|
|
|
Name: 京 ..かけだし(1,449ポイント)
Date: 2010/08/29(日) 13:06
No:60541
|
|
Title: Re:ビルドできない。
|
|
参考にしているのは、このサイトのプログラミングの館の方です。
サンプルスクリプト2つを一つにまとめたくて、タブに開きながら作業していたのですが、実行しようとしても上手くいかなかった。ということです。正直片方が実行できればいいので、現在はプログラムを片方メモ帳に移して作業しているのですが、今後複数のスクリプトを一つのプロジェクトにまとめたいときのためにここに質問させていただきました。どうすれば一つのプロジェクトの中で複数のスクリプトを実行できるように出来ますか?
分かりにくいので言葉を足させていただくと、トップのスクリプトから、条件で別のスクリプトに飛んで別の処理をするようなソフトを作りたいのです。丁度ゲームなんかだと、メニューから選んだ項目によってぜんぜん別のことをしますよね。そういうスクリプトを一つの.ccpのファイルに入れると見辛くなりそうなので。
381ポイント を落としてしまった。
|
|
|
|
|
Name: 京 ..かけだし(1,473ポイント)
Date: 2010/08/29(日) 13:18
No:60543
|
|
Title: Re:ビルドできない。
|
|
了解しました。回答ありがとうございました。
2倍のポイントを手に入れた! 24ポイント を手に入れた。
|
|
|
|
|
Name: 京 ..かけだし(1,482ポイント)
Date: 2010/08/29(日) 13:24
No:60546
|
|
Title: Re:ビルドできない。
|
|
すいません。winmainの前にexternを入れればいいって事ですか?出来れば回答ください。
19ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(207,987ポイント)
Date: 2010/08/29(日) 13:36
No:60549
|
|
Title: Re:ビルドできない。
|
|
タイトル、本編、エンディングなどを別々のファイルにまとめたいと言うことであれば、シエル さんも書いているファイル分割と言う技法が必要となります。
検索キーワードとしては「ファイル分割 C言語」が適切だと思います。
ただ、このファイル分割のためにはC言語の関数の仕組みをちゃんと理解している必要があります。
WinMainって辺りから調べてみてください。
ちなみC言語などのコンパイル型のプログラム場合はプログラムのコードをスクリプトと呼ばずにソースコードと呼びます。プログラムコードをスクリプトと呼ぶのは、HSP,javascript,PHP,Perl,Ruby,Phythonなどインタプリタ型言語が一般的でしょうか。
135ポイント を手に入れた。
|
|
|
|
|
Name: softya [URL] ..ハッカー(208,076ポイント)
Date: 2010/08/29(日) 13:39
No:60550
|
|
Title: Re:ビルドできない。
|
|
>すいません。winmainの前にexternを入れればいいって事ですか?出来れば回答ください。
これもC言語の基礎の問題なのですが、同じ名前の関数は1つしか存在できません。
※関数名のスコープ次第では例外あり。
なのでWinMainが2つ存在する時点でアウトです。
89ポイント を手に入れた。
|
|
|
|
|
Name: 京 ..かけだし(1,540ポイント)
Date: 2010/08/29(日) 13:49
No:60552
|
|
Title: Re:ビルドできない。
|
|
すいません。今softyaさんの書き込みを読み直して気づきました。アウトですね。シエルさんの言っているサイトに行って出直します。
58ポイント を手に入れた。
|
|
|
|
|
Name: シエル ..熟練のプログラマー(64,154ポイント)
Date: 2010/08/29(日) 13:52
No:60553
|
|
Title: Re:ビルドできない。
|
|
私が貼っているページだけ読んでも、WinMainの事がちょこっとかいてあるだけです。
ファイル分割についてはググって調べてください。
39ポイント を手に入れた。
|
|
|
|
|
Name: 京 ..かけだし(1,630ポイント)
Date: 2010/08/29(日) 14:07
No:60555
|
|
Title: Re:ビルドできない。
|
|
あ、はい。今ググって来ました。で、ちょっと質問なんですけど、今typedef structって言うので、幾つかの変数をまとめてWinMainの外で宣言しています。これは分割した方ではexternを頭につけて宣言すれば良いのでしょうか。
90ポイント を手に入れた。
|
|
|
|
|
Name: たいちう ..ハッカー(102,555ポイント)
Date: 2010/08/29(日) 22:46
No:60635
|
|
Title: Re:ビルドできない。
|
|
VCで複数のソースコードを開いて編集したいと言う事ですよね?
そしてそれぞれのソースコードにはWinMainがあると。
結論としては、1つのソリューションに複数のプロジェクトを追加し、
それぞれのプロジェクトが1つずつWinMainを含むようにすればよいです。
softyaさんの添付してくれたファイルで説明すると、
画面左のソリューションエクスプローラでは、
1つのソリューション'DxLib'を開いていますが、
ソリューション'DxLib'は1つのプロジェクト'DxLib'を持っています。
プロジェクト'DxLib'はソースコード'test.cpp'を持っていて、
ソースコード'test.cpp'が関数WinMainを持っています。
既に他の方が説明されているとおり、1つのプロジェクトには
1つのWinMainしか存在してはいけません。
2つのWinMainを含むファイルを同時に管理したい場合、
プロジェクトを追加してください。
ソリューションエクスプローラの『ソリューション'DxLib'』
と書いてある所で右クリックすると、プロジェクトの追加が選択できます。
別の方法として、プロジェクトとは関係ないファイルをVCで開くこともできます。
現在のエラーの内容から、ソリューションエクスプローラから2つのファイルが
見えていると思いますが、そこへの追加は本当に必要な方のみとして、
参考のために開くファイルは、メニューのファイル-開くから開きます。
さらに別の方法として、ソリューションエクスプローラでファイルを選び、
右クリックのプロパティで、そのファイルだけビルドしない設定にすることもできます。
用途に合わせて色々試してみて下さい。
VC以外のテキストエディタで開く、というのも、用途によっては正解の1つです。
さすがにメモ帳よりも良いエディタを使う人が殆どですが。
535ポイント を手に入れた。
|
|
|
|
|