C言語何でも質問掲示板


アンケートにご協力下さい → >> アンケートフォーム <<

規約と使い方

 
   Cとアセンブリ   
     ・[15622] やそ 
     ・[15650] たぬき 
   またも質問です   
     ・[15630] 学食 
     ・[15631] ボムボム 
     ・[15634] 学食 
     ・[15636] ボムボム 
     ・[15639] 学食 
     ・[15645] ボムボム 
   文字列の初歩的な問題 ....   
     ・[15624] バグ 
     ・[15625] マルクス 
     ・[15626] toyo 
     ・[15644] YK 
   ゲームをwebサイトに設 ....   
     ・[15637] 管理人 
     ・[15638] 鏡 
   ボン○ーマンもどきを ....   
     ・[15611] 管理人 
     ・[15612] yos 
     ・[15614] 管理人 
     ・[15627] やそ 
     ・[15628] yos 
   開発目的   
     ・[15469] tkmakwins15 
     ・[15471] GPGA 
     ・[15474] やそ 
     ・[15619] たろう 
   質問です。   
     ・[15589] toyo 
     ・[15590] バグ 
     ・[15591] ボムボム 
     ・[15592] バグ 
     ・[15593] バグ 
     ・[15594] 管理人 
     ・[15595] 組木紙織 
     ・[15596] ボムボム 
     ・[15597] Mist 
     ・[15598] バグ 
     ・[15599] やそ 
     ・[15600] やそ 
     ・[15601] バグ 
     ・[15602] やそ 
     ・[15606] ボムボム 
     ・[15607] やそ 
     ・[15608] バグ 
     ・[15609] ボムボム 
     ・[15618] しっぽ 
   引数の記述   
     ・[15571] box 
     ・[15581] kazuoni 
   メモリの解放について   
     ・[15530] Justy 
     ・[15557] ほにゃー 
     ・[15558] GPGA 
     ・[15562] Justy 
     ・[15576] ほにゃー 
   下のソースをifを使わ ....   
     ・[15541] バグ 
     ・[15542] knight 
     ・[15543] GPGA 
     ・[15544] knight 
     ・[15574] toyo 
     ・[15575] バグ 
   C#のネットワークプロ ....   
     ・[15555] keichan 
     ・[15556] バグ 
     ・[15560] Justy 
     ・[15564] バグ 
     ・[15572] バグ 
   数値から数を判定する ....   
     ・[15569] Justy 
     ・[15570] 水孤 
   分割コンパイルについ ....   
     ・[15521] 管理人 
     ・[15561] DD 
     ・[15563] 通りすがり 
     ・[15565] Justy 
     ・[15566] 管理人 
   もう限界・・・   
     ・[15546] バグ 
     ・[15547] バグ 
     ・[15548] 超初心者 
     ・[15549] 超初心者 
     ・[15550] 超初心者 
     ・[15551] バグ 
     ・[15552] 超初心者 
     ・[15553] バグ 
     ・[15554] 超初心者 
   ゲームの構成   
     ・[15520] 管理人 
     ・[15527] kazuoni 
     ・[15534] 管理人 
     ・[15535] kazuoni 
     ・[15536] 管理人 
   参考書のような物を・ ....   
     ・[15523] ジーコ 
     ・[15524] 管理人 
     ・[15532] ジーコ 
     ・[15533] 管理人 
   2Dゲームの作成につい ....   
     ・[15526] kazuoni 
     ・[15528] Kirby 
     ・[15529] kazuoni 
     ・[15531] Kirby 
   入力キーのチェック   
     ・[15482] 管理人 
     ・[15487] kazuoni 
     ・[15488] 管理人 
     ・[15489] トウラ 
     ・[15491] トウラ 
     ・[15492] kazuoni 
     ・[15496] 管理人 
     ・[15503] トウラ 
     ・[15504] トウラ 
     ・[15505] バグ 
     ・[15507] kazuoni 
     ・[15508] 管理人 
     ・[15509] 管理人 
     ・[15510] Justy 
     ・[15511] 管理人 
     ・[15513] kazuoni 
     ・[15516] Justy 
     ・[15517] kazuoni 
   ウイルスバスター2008 ....   
     ・[15481] 管理人 
     ・[15501] 湖乃夜路 
     ・[15502] 管理人 
     ・[15506] Mist 
     ・[15514] 湖乃夜路 
   ゲームプログラミング ....   
     ・[15475] やそ 
     ・[15480] 管理人 
     ・[15490] Justy 
     ・[15493] 管理人 
     ・[15494] Justy 
     ・[15495] 管理人 
     ・[15497] 木霊 
     ・[15498] Justy 
     ・[15499] 管理人 
     ・[15500] tkmakwins15 
     ・[15512] 管理人 
   while文とキー入力   
     ・[15457] Justy 
     ・[15486] piyo 
   初歩的な事ですいませ ....   
     ・[15470] tkmakwins15 
     ・[15472] t 
   シューティングゲーム ....   
     ・[15419] 管理人 
     ・[15424] 電気さぼてん 
     ・[15425] やそ 
     ・[15427] 管理人 
     ・[15466] 電気さぼてん 
   初期画面が表示されま ....   
     ・[15460] やそ 
     ・[15461] 管理人 
     ・[15463] CLP 
   シューティングでの敵 ....   
     ・[15450] tny 
     ・[15451] 水孤 
     ・[15455] nayo 
     ・[15462] 水孤 
   マルチスレッドクラス   
     ・[15247] Justy 
     ・[15281] 組木紙織 
     ・[15290] Justy 
     ・[15298] 組木紙織 
     ・[15299] Justy 
     ・[15302] 組木紙織 
     ・[15316] Justy 
     ・[15363] 組木紙織 
     ・[15369] Justy 
     ・[15400] 組木紙織 
     ・[15413] Justy 
     ・[15428] 組木紙織 
     ・[15456] Justy 
   レースゲームのアクセ ....   
     ・[15432] tkmakwins15 
     ・[15434] やそ 
     ・[15435] toyo 
     ・[15436] tkmakwins15 
     ・[15438] やそ 
     ・[15445] 管理人 
   競合   
     ・[15433] YuO 
   自作関数について   
     ・[15370] 名無し 
     ・[15371] 通りすがり 
     ・[15372] バグ 
     ・[15374] toyo 
     ・[15375] 管理人 
     ・[15377] 北欧マニア 
     ・[15378] lbfuvab 
     ・[15388] オプーナを買う権利を授けよう 
     ・[15391] 北欧マニア 
     ・[15393] 管理人 
     ・[15420] 北欧マニア 
     ・[15422] tkmakwins15 
     ・[15431] 北欧マニア 
   シューティングゲーム ....   
     ・[15386] Justy 
     ・[15387] RYU2 
     ・[15389] tkmakwins15 
     ・[15390] Justy 
     ・[15402] bodomcross 
     ・[15415] RYU2 
     ・[15416] RYU2 
     ・[15426] RYU2 
   画像の高速なスケーリ ....   
     ・[15350] GPGA 
     ・[15361] GPGA 
     ・[15362] GPGA 
     ・[15373] へろり 
     ・[15379] GPGA 
     ・[15380] GPGA 
     ・[15381] ま〜く 
     ・[15403] へろり 
     ・[15404] ま〜く 
     ・[15405] へろり 
     ・[15406] へろり 
     ・[15414] ま〜く 
     ・[15421] へろり 
     ・[15423] ま〜く 
   構造体の初期化につい ....   
     ・[15394] 管理人 
     ・[15395] オプーナを買う権利を授けよう 
     ・[15396] 管理人 
     ・[15397] 管理人 
     ・[15398] box 
     ・[15401] オプーナを買う権利を授けよう 
     ・[15412] 管理人 
     ・[15417] オプーナを買う権利を授けよう 
   ファイルとディレクト ....   
     ・[15408] Justy 
     ・[15409] tkmakwins15 
     ・[15410] Justy 
     ・[15411] tkmakwins15 
   マウスポインタについ ....   
     ・[15384] Justy 
     ・[15399] ほにゃー 
   C++ オブジェクト指向   
     ・[15366] バグ 
     ・[15376] tkmakwins15 
     ・[15382] 大工 
   クラス+DxLibに ....   
     ・[15357] GPGA 
     ・[15367] bodomcross 
   構造体宣言について   
   文字列について   
     ・[15334] 管理人 
     ・[15335] 管理人 
     ・[15336] tkmakwins15 
     ・[15337] オプーナを買う権利を授けよう 
     ・[15338] 名無し 
     ・[15339] フリオ 
     ・[15340] フリオ 
     ・[15341] box 
     ・[15342] tkmakwins15 
     ・[15343] やそ 
     ・[15344] バグ 
     ・[15345] YuO 
     ・[15346] box 
     ・[15347] Mist 
     ・[15348] box 
     ・[15349] kazuoni 
     ・[15351] Mist 
     ・[15352] GPGA 
     ・[15353] Mist 
     ・[15355] YuO 
     ・[15356] バグ 
     ・[15358] 管理人 
     ・[15359] box 
     ・[15360] kazuoni 
   ポインタが分かりませ ....   
     ・[15320] tkmakwins15 
     ・[15323] やそ 
     ・[15324] そら 
     ・[15327] バグ 
     ・[15328] バグ 
     ・[15329] そら 
     ・[15332] バグ 

Name: たぬき  ..ぴよぴよ(140ポイント)   Date: 2008/04/17(木) 10:11   No:15620       
Title: Cとアセンブリ    
C言語のプログラムとアセンブリ言語のプログラムを比べた時に、実質的に同じ点や個となっている点ってなんですか?

どなたか教えて下さい。


41ポイント を手に入れた。


Name: やそ  ..熟練のプログラマー(42,306ポイント)   Date: 2008/04/17(木) 11:22   No:15622     
Title: Re:Cとアセンブリ    
うーむ、漠然とした質問で答えにくいですが、

人間がまともに読めるコード(ソースプログラム)を翻訳して機械語に直して実行するやり方は一緒です。
翻訳の仕方をCはコンパイル、アセンブラはアセンブルと呼んでいます。

一番分かりやすい違いはソースプログラムの命令ですよね。
Cでは関数と言う形で表現していますが、アセンブラでは1命令=機械語が基本です。
もちろん、命令を組み合わせてライブラリを作ったりしてますが。

また、変数の定義においても特徴的な違いが有りますね。
Cでは自分の好きな名前で変数を宣言できますが、アセンブラでは基本的にはレジスタで管理されます。レジスタはCPUによって個数が決まっています。
レジスタにはそれぞれに役割があり、汎用的に使用できるレジスタもありますが、計算用やスタックポインタ用、アドレス指標(インデックス)用など用途が決まっているものもあります。
なので変数を使いまわしたい場合などは、メモリを使います。Cのポインタと同様にメモリを確保して、
そこの値を操作し、計算する際にはレジスタにコピーして使用したりします。

なので、直接的にメモリ操作をする機会が非常に多いアセンブラはプログラムの危険度がCに比べて飛躍的に高いです。
また、今ではツールやライブラリが充実しているのでCに近い概念でいろいろな処理を出来ると思います(DirectXなど)が、原則的にはアセンブラはハードウェアと密接した言語なので、ひとつの処理をするための手続きが非常に複雑です。
アセンブラに興味がおありなら、直接MASMを使ってみるのもいいですし、
概念を勉強したいならZ80アセンブラや基本情報処理などで使用されているCASLなどをご覧になってみてはどうでしょう?Z80なら8ビット系のアセンブラなので、命令が単純で理解しやすいと思います。


595ポイント を手に入れた。

Name: たぬき  ..ぴよぴよ(210ポイント)   Date: 2008/04/18(金) 10:35   No:15650 解決!     
Title: Re:Cとアセンブリ    
ありがとうございます。
これを参考にしてアセンブラにちょっと手を出してみたいとおもいます。


2倍のポイントを手に入れた! 70ポイント を手に入れた。



Name: ボムボム  ..ぴよぴよ(643ポイント)   Date: 2008/04/17(木) 18:47   No:15629       
Title: またも質問です    
最長10文字の文字列を二件入力して、char型の配列にそれぞれ格納する。文字列を比較して同じならequal、違うならnot equalを表示するプログラムをつくる。ただし一件ごとの入力はユーザー定義関数で行なう。という課題がでました。
途中まで作ったのですが、fgetsをgetcharに直す上手いやり方がわかりません。教えて下さい。お願いします。


#include<stdio.h>
#include<string.h>

#define max_length 10

void get_string (char *p_str, int size);

int main(void)
{
char string1[max_length+1];
char string2[max_length+1];

get_string(string1,max_length+1);
get_string(string2,max_length+1);

if(!strncmp(string1,string2,max_length))
{
printf("equal");
}
else
{
printf("Not equal");
}
return 0;
}



void get_string (char *p_str, int size)
{

fgets(p_str,size,stdin);

}


267ポイント を落としてしまった。


Name: 学食  ..ぴよぴよ(83ポイント)   Date: 2008/04/17(木) 19:51   No:15630     
Title: Re:またも質問です    
fgetsではダメな理由があるのでしょうか?


「またも質問です」よりも、「文字列の入力と比較」のように、
投稿内容を的確に反映したタイトルを
考えてみてはいかがですか?


83ポイント を手に入れた。

Name: ボムボム  ..ぴよぴよ(696ポイント)   Date: 2008/04/17(木) 20:15   No:15631     
Title: Re:またも質問です    
fgetsでは2,30文字を入力するとバグが発生するので使えません。
タイトルについてはすいませんでした。


53ポイント を手に入れた。

Name: 学食  ..ぴよぴよ(94ポイント)   Date: 2008/04/17(木) 20:29   No:15634     
Title: Re:またも質問です    
fgetsの直後に
rewind(stdin);
を書くと、配列の定義を超える長さの
文字を入力したとき遭遇する現象を
回避できると思います。


11ポイント を手に入れた。

Name: ボムボム  ..ぴよぴよ(735ポイント)   Date: 2008/04/17(木) 20:36   No:15636     
Title: Re:またも質問です    
返信ありがとうございます。
rewind(stdin); は試して指導員に見せたのですが
「getcharにしろ」と言われました。


39ポイント を手に入れた。

Name: 学食  ..ぴよぴよ(3ポイント)   Date: 2008/04/17(木) 21:55   No:15639     
Title: Re:またも質問です    
最大10回まわるループを作ります。
入力した文字がEOFならば、
10回まわらないうちにループから抜ける
ことを考慮に入れておきます。

ループの中では、入力した文字を
所定の場所に格納します。

ループから抜けたら、文字列終端の'\0'をセットします。


91ポイント を落としてしまった。

Name: ボムボム  ..ぴよぴよ(803ポイント)   Date: 2008/04/18(金) 00:25   No:15645 解決!     
Title: Re:またも質問です    
試してみます。
やはりfgetにもバグというか良くない点があるみたいですね。
そういった点を回避するならfgetでもいいと言われました。
そこを詳しく調べつつ課題をやってみます。
ご協力有難う御座いました。


68ポイント を手に入れた。



Name: YK  ..かけだし(1,129ポイント)   Date: 2008/04/17(木) 12:33   No:15623       
Title: 文字列の初歩的な問題で苦戦しています    
文字列を入力したとき、その中に「A」が含まれていたら「B」に書き換えて表示する
プログラムを作成せよ。という問題です。(「ABC」の場合、「BBC」になる)
自分なりにやってはみたのですが、文字の書き換えが上手くいっていないようです。
どの辺りがおかしいのかご教授頂けないでしょうか。

#include <stdio.h>

void exchange(const char ch[])
{
unsigned i = 0;

while (ch[i]){

if(ch[i]=='A')
ch[i]=='B';

putchar(ch[i]);
i++;

}

}

int main(void)
{
char ab[100];

scanf("%s",ab);

exchange(ab);

return(0);
}



225ポイント を手に入れた。


Name: バグ  ..比類無きプログラマー(83,885ポイント)   Date: 2008/04/17(木) 12:53   No:15624     
Title: Re:文字列の初歩的な問題で苦戦しています    
>> ch[i]=='B';

これがおかしいですね。

ch[i] = 'B';

でないと置き換えはできません。


26ポイント を手に入れた。

Name: マルクス  ..かけだし(2,094ポイント)   Date: 2008/04/17(木) 13:05   No:15625     
Title: Re:文字列の初歩的な問題で苦戦しています    
const 修飾子があるとうまくいかないと思いますよ!
ググってみましょうw


2倍のポイントを手に入れた! 64ポイント を手に入れた。

Name: toyo  ..初心者(7,440ポイント)   Date: 2008/04/17(木) 13:58   No:15626     
Title: Re:文字列の初歩的な問題で苦戦しています    
元の文字列を変更しないで表示だけなら

void exchange(const char ch[])
{
unsigned i = 0;

while (ch[i]) {
if(ch[i]=='A') {
putchar('B');
} else {
putchar(ch[i]);
}
i++;
}
}



94ポイント を手に入れた。

Name: YK  ..かけだし(1,169ポイント)   Date: 2008/04/18(金) 00:13   No:15644 解決!     
Title: Re:文字列の初歩的な問題で苦戦しています    
呆れる様な単純なミス申し訳ありません。
返信して下さった方の内容を踏まえた結果、上手く動きました。

稚拙な質問にお答え頂き大変ありがとうございました。


40ポイント を手に入れた。



Name:  ..ぴよぴよ(61ポイント)   Date: 2008/04/17(木) 20:32   No:15635       
Title: ゲームをwebサイトに設置できるのかどうか    
フラッシュゲームがサイトに置いてあるのはよく見るのですが
ここのサイトを参考にして作ったゲームを自分のwebサイトに設置することはできますか?
ダウンロードして保存しなくても、IEで遊べるようにできるのかどうか知りたいです


61ポイント を手に入れた。


Name: 管理人 [URL]  ..伝説のハッカー(556,314ポイント)   Date: 2008/04/17(木) 21:06   No:15637     
Title: Re:ゲームをwebサイトに設置できるのかどうか    
ウェブ上で遊べるのはFLASHかJAVAとかじゃないでしょうか?

32ポイント を手に入れた。

Name:  ..ぴよぴよ(49ポイント)   Date: 2008/04/17(木) 21:09   No:15638 解決!     
Title: Re:ゲームをwebサイトに設置できるのかどうか    
わかりました
ご返事ありがとうございます


12ポイント を落としてしまった。



Name: yos  ..ぴよぴよ(80ポイント)   Date: 2008/04/16(水) 18:22   No:15605       
Title: ボン○ーマンもどきを作っているのですが・・    
はじめまして。
プログラムなんぞ、書いた事の無い超初心者です。

ボン○ーマンでは、爆弾を置いた時には、その爆弾の上に乗ってる間は爆弾の上を通過できますよね?
でも一度、離れると通過できなくなります。
でも、敵は爆弾を置いた直後から通過できない。
これを表現したいのですが・・。
ちょっと分かりにくいですが、誰か教えて下さい。


80ポイント を手に入れた。


Name: 管理人 [URL]  ..伝説のハッカー(556,630ポイント)   Date: 2008/04/16(水) 20:10   No:15611     
Title: Re:ボン○ーマンもどきを作っているのですが・・    
「進入禁止エリアにいるときは動けない」のではなく、「進入禁止エリアに入れない」という意味でプログラムをかけばなんてこと無いと思います。

32x32を一区間としているのであれば、32で割り切れるときにだけ、次の要素に入れるかどうかを判定すればよく、
既に進入禁止エリアに入ってしまっているのであれば、動けて当然です。
RPG的にプログラムを組むのなら、その要素を爆弾を置いた瞬間フラグを1にでもすれば、もう敵は入ってこれないでしょう。
普通にゲームプログラミングの館で紹介しているような2次元マップで表現し、その部分を1とか2とかにすれば解決すると思いますよ


143ポイント を手に入れた。

Name: yos  ..かけだし(2,056ポイント)   Date: 2008/04/16(水) 21:35   No:15612     
Title: Re:ボン○ーマンもどきを作っているのですが・・    
お早い回答ありがとうございます。

一応、32x32を一区間にしていますけど、プレイヤーは1づつ歩くので、
管理人さんの言われている方法だと、半端なところにいる場合、問題になりませんか?

でも、ちょっとよく分からないので、ソースを見ていただけますか?



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,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1 },
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1 },
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1 },
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1 },
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1 },
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1 },
{ 1,0,0,0,0,0,0,0,0,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 },
};

if(player.flag==1){
//up
if( Key[ KEY_INPUT_UP ] == 1 ){
player.count++ ;
DrawGraph(player.x,player.y-16,image[player.count%80/20+player.muki*4],TRUE) ;//画像を描画
for(i=0;i<player.speed;i++){
if(player.x%64==32){
player.muki=0;
if(hantei[(player.y-1)/32][player.x/32]==1){
break;
}
else if(hantei[(player.y-1)/32][player.x/32]==2){
if(player.kabe_t==0)
break;
else
player.y-=1;
}
else if(hantei[(player.y-1)/32][player.x/32]==3){
if(player.bom_t==0)
break;
else
player.y-=1;
}
else{
player.y-=1;
}
}
else if(player.x%64<32){
player.muki=3;
if(hantei[player.y/32][player.x/32+1]==1){
break;
}
else if(hantei[player.y/32][player.x/32+1]==2){
if(player.kabe_t==0)
break;
else
player.x+=1;
}
else if(hantei[player.y/32][player.x/32+1]==3){
if(player.bom_t==0)
break;
else
player.x+=1;
}
else{
player.x+=1;
}
}
else if(player.x%64>32){
player.muki=1;
if(hantei[player.y/32][(player.x-1)/32]==1){
break;
}
else if(hantei[player.y/32][(player.x-1)/32]==2){
if(player.kabe_t==0)
break;
else
player.x-=1;
}
else if(hantei[player.y/32][(player.x-1)/32]==3){
if(player.bom_t==0)
break;
else
player.x-=1;
}
else{
player.x-=1;
}
}
}
}


//爆弾の設置
if(Key[KEY_INPUT_Z]==1){
if(bb_flag==0){
if((hantei[player.y/32][player.x/32]==0)||(hantei[player.y/32][player.x/32]==5)){
for(i=0;i<player.bom;i++){
if(bom[i].flag==0){
bom[i].counter=0;//カウンター初期化
if(player.x%32<17)
bom[i].x=player.x-player.x%32;
else
bom[i].x=player.x-player.x%32+32;
if(player.y%32<17)
bom[i].y=player.y-player.y%32;
else
bom[i].y=player.y-player.y%32+32;


         hantei[bom[i].y/32][bom[i].x/32]=3;
bom[i].flag=1;
break;
}
}
}


このソースですと、爆弾にかぶってる方にいけないんですよね。
左に爆弾があって、右にプレイヤーが少し出ている場合でも左にいけない。
というところを直したいのです。


1,976ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(556,282ポイント)   Date: 2008/04/16(水) 21:50   No:15614     
Title: Re:ボン○ーマンもどきを作っているのですが・・    
コードを投稿される時は、最低限の注釈と変数の意味を付けて貰えると助かります。
ざっとしか読んでいませんが、恐らく属している配列要素の管理が出来ていないのではないでしょうか。

私もボンバーマンを作ったとき、属する要素関連付けるのに少し苦労しました。

中間にいるとき、進行方向に属する2つの要素を見る必要があるときもあります。

例えば、キャラを赤の□と青の□であらわしたとき、



こちらの図の赤いキャラと青いキャラはほとんど同じ場所にいますが、属している区間がx,yともに違います。
赤は[y][x]において[0][0]に属しているのに対し、青は[1][1]に属していますよね?

今、赤の下が移動可能かどうかを調べる時、単純に[player.y/32+1]で調べると、左下を調べる事になってしまいます。
つまり、この時に調べるべきはxの属する要素+1のy要素+1じゃないといけません。そして移動しているうちに、x%32==0の座標に自動的に移動させる必要があります。

ボンバーマンの移動がかなりやっかりで苦労した覚えがあります。
わかりにくかったらまず図を書いて考えてみて下さい。


348ポイント を落としてしまった。

Name: やそ  ..熟練のプログラマー(42,943ポイント)   Date: 2008/04/17(木) 17:33   No:15627     
Title: Re:ボン○ーマンもどきを作っているのですが・・    
>一応、32x32を一区間にしていますけど、プレイヤーは1づつ歩くので、
>管理人さんの言われている方法だと、半端なところにいる場合、問題になりませんか?

32×32を1区画としてMAPを構成しており、キャラクタの移動はその半分の16ピクセル単位で動かせる仕様になっている。

管理人さんが言われている通り、注釈が少なく、ロジックの解読が非常に困難です。
各変数(構造体)がどのような意味を持つのか。
自分の決めた「仕様」の明記。(どう動いて欲しいのか)は必須です。

キャラは半区画ごとに移動できるが、爆弾の設置は区画に沿った位置に置かれる。
なのでずれた位置で爆弾を設置したとき、爆弾のある方向にキャラクタがかぶっているので、その方向に移動したい。

ならば、管理人さんの言われている通り、32で割り切れる時のみ移動先の障害物判定をすればよく、
32で割り切れない”1歩(16ピクセル)ずれた位置”にいるときはどちらにも移動できる。とすればよい。
(0,0)=壁
(0,1)=通路
(0,2)=通路
(0,3)=壁
※各マスの幅は32ピクセル
キャラクタがX=48,Y=0((0,1)と(0,2)の中間)にいて、爆弾を(0,1)に設置した場合、
キャラの左半分は爆弾とかぶっている状態です。

移動判定の際は自分の今現在いる座標を調べて、32で割り切れるときにその方向の先にある障害物を判定すればよい。
この場合Y座標は32で割り切れるので、上下方向については移動方向の障害物判定を行い、
X座標については32で割り切れないので、そのまま移動できる。

というように判定すればよいのかな?







637ポイント を手に入れた。

Name: yos  ..かけだし(2,108ポイント)   Date: 2008/04/17(木) 17:42   No:15628 解決!     
Title: Re:ボン○ーマンもどきを作っているのですが・・    
ありがとうございました。
上手くいきました。

すみません。
次回から注意します。



52ポイント を手に入れた。



Name: たろう  ..ぴよぴよ(454ポイント)   Date: 2008/04/10(木) 16:32   No:15467       
Title: 開発目的    
UNIX、LINUX、Mac、Windowsがなぜ開発されたのか?ということを調べているのですが、全然わかりません。教えて下さい。

19ポイント を手に入れた。


Name: tkmakwins15 [URL]  ..比類無きプログラマー(67,788ポイント)   Date: 2008/04/10(木) 17:22   No:15469     
Title: Re:開発目的    
http://ja.wikipedia.org/wiki/Unix

とか参考になりそうです。


18ポイント を落としてしまった。

Name: GPGA  ..熟練のプログラマー(47,683ポイント)   Date: 2008/04/10(木) 17:45   No:15471     
Title: Re:開発目的    
これとかもどうですか?

68ポイント を手に入れた。

Name: やそ  ..プログラマー(39,366ポイント)   Date: 2008/04/11(金) 09:34   No:15474     
Title: Re:開発目的    
「WINDOWS WIKI」とかのキーワードで十分検索できると思うのですが・・・
まあ、100%の信頼性があるかは別として(笑)



46ポイント を手に入れた。

Name: たろう  ..ぴよぴよ(455ポイント)   Date: 2008/04/17(木) 10:06   No:15619 解決!     
Title: Re:開発目的    
わかりました。
それらのサイトを参考にもう少し調べてみます。


1ポイント を手に入れた。



Name: ボムボム  ..ぴよぴよ(883ポイント)   Date: 2008/04/15(火) 23:39   No:15585       
Title: 質問です。    
入力された2つの整数の差を絶対値を出力するプログラム

課題で、入力された2つの整数の差を絶対値を出力するプログラムをつくりました.
整数には、負数を入力される場合も考慮し,入力される数値は、正数の場合は最大8桁まで有効とし、9桁目以降を無視、負数の場合は '-'を含め、最大9桁まで有効とし,10桁目以降を無視します。
今日指導員に見せたところ、「入力した数値を保存する必要はない」、「a[ i ] = atoi( n[ i ] ) は使わないように」、「scanf,get,do-whileを使わないように」等の指導を受けました。
どのように直したらよいか教えてください. お願いします.
下記のプログラムには多々エラーがありますがご指導宜しくお願い致します。
私は自宅ではCPad、会社ではTeraPadを使っています。

#include <stdio.h>

#include <stdlib.h>

#define SIZE 11
#define TASU_MAX 8
#define HIKU_MAX 9
#define C_NULL ('\0')
#define RC_OK 0 /*入力OK*/
#define RC_ND -1 /*入力データなし*/
#define RC_ID -2 /*無効な入力データ*/
#define RC_MD -3 /*負のデータ*/

int absolute( int n1, int n2 ) ;

int main(void)
{
char n[ 2 ][ SIZE ];
int i ; /*文字入力回数のカウント*/
int a[ 2 ] ; /*整数データ*/
int ab ; /*絶対値*/
int count ; /*入力文字個数*/
int n_pos ; /*null付与位置*/
char c ; /*入力文字*/


for( i = 0 ; i < 2 ; i ++ )
{

printf( "%d番目の数値を入力 :", i + 1 ) ;
for( count = 0 ; count <= SIZE ; count ++ )
{
c = getchar() ;
/*cが数字もしくは一文字目が-なら*/
if( c >= '0' && c <= '9' || count == 0 && c == '-' )
{
n[i][ count ] = c ;
continue ;
}
}
/*改行なら*/
if( c == '\n' ) break ;
printf( "Error!! : 数値以外の入力\n" ) ;
return( RC_ID ) ;

}
/*入力文字数が0なら*/
if( count == 0 )
{
printf("Error!! : 改行のみまたは、'−'のみの入力\n");
return( RC_ND );
}
/*入力が1文字のみかつ-入力なら*/
else if( n[ i ][ 0 ] == '-' && count < 2 )
{
printf("Error!! : 改行のみまたは、'−'のみの入力\n");
return( RC_ID ) ;
}


/*null付与位置の設定*/
/*一文字目が-かつ9文字以上なら*/
if( n[ i ][ 0 ] == '-' && count > HIKU_MAX )
{
n_pos = HIKU_MAX ;
}
else
{
/*8文字以上なら*/
if( count > TASU_MAX )
{
n_pos = TASU_MAX ;
}
else
{
n_pos = count ;
}
}
n[ i ][ n_pos ] = '\0' ;/*null付与*/
a[ i ] = atoi( n[ i ] ) ;/*文字列を数字に変換*/


}
ab = absolute( a[ 0 ], a[ 1 ] ) ;
printf( "%d と %dの差の絶対値は %d \n", a[ 0 ], a[ 1 ], ab ) ;
return( RC_OK );
}


int absolute(int n1, int n2)
{
int i ;

i = n1 - n2 ;
return i >= 0 ? i : -i ;
}


883ポイント を手に入れた。


Name: toyo  ..初心者(7,346ポイント)   Date: 2008/04/16(水) 09:19   No:15589     
Title: Re:質問です。    
scanfもdo-whileも使ってないようですが「使うように」の間違いかな?
scanfで入力するなら

#include <stdio.h>

int main(void)
{
int number;

printf("数値を入力 ");
scanf("%9d", &number);
while (number > 99999999 || number < -99999999)
{
number /= 10;
}
printf("number=%d\n", number);

return 0;
}

とか


146ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(82,401ポイント)   Date: 2008/04/16(水) 09:49   No:15590     
Title: Re:質問です。    
scanfとdo〜whileを使えるならば、こんな感じかな?


#include <stdio.h>
#include <stdlib.h>

void input_number(int* number, const char* comment)
{
do
{
printf("%sを入力して下さい\n", comment);
scanf("%9d", number);
}
while (*number > 99999999 || *number < -99999999);
}

int main(void)
{
int num_1 = 0, num_2 = 0;

// 数値の入力
input_number(&num_1, "数値1");
input_number(&num_2, "数値2");

// 入力された数値の表示
printf("\n");
printf("数値1 = %d\n", num_1);
printf("数値2 = %d\n", num_2);

// 2つの整数の絶対値の算出
printf("絶対値 = %d\n", abs(num_1 - num_2));

return 0;
}


129ポイント を手に入れた。

Name: ボムボム  ..ぴよぴよ(939ポイント)   Date: 2008/04/16(水) 12:02   No:15591     
Title: Re:質問です。    
表現が悪くて申し訳ありませんでした。
「使ってはいけない」というのは、この課題だけでなく研修全体のルールです。
なので返信して頂いたプログラムは使用できません。


56ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(82,467ポイント)   Date: 2008/04/16(水) 12:18   No:15592     
Title: Re:質問です。    
getを使ってはいけないという事は、getc、gets、getcharなども駄目なんですか?
同じように、scanfを使ってはいけないという事は、fscanf、sscanfなんかも駄目なんでしょうか?


66ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(82,536ポイント)   Date: 2008/04/16(水) 12:29   No:15593     
Title: Re:質問です。    
あ、ひょっとして、入力系関数の使用に制限が掛かっているという事は、コマンドライン引数で指定しないさいという事なのかもしれませんね♪

69ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(556,487ポイント)   Date: 2008/04/16(水) 12:46   No:15594     
Title: Re:質問です。    
http://www.google.co.jp/search?hl=ja&q=scanf+%E5%8D%B1%E9%99%BA&lr=

この辺のことを理解させる為の課題なんですかね?
もしそうならリンク先の解決手段を用いて実装すればいいと思います。
もしコマンドライン引数で指定する場合は

http://www.geocities.jp/bananajuku/r_c/argv.html

この辺参考になると思います。


101ポイント を落としてしまった。

Name: 組木紙織  ..熟練のプログラマー(47,745ポイント)   Date: 2008/04/16(水) 12:52   No:15595     
Title: Re:質問です。    
do-whileがだめだということはwhileやforをつかえということなのかな。
それともifとgoto。。。


30ポイント を手に入れた。

Name: ボムボム  ..かけだし(1,005ポイント)   Date: 2008/04/16(水) 12:58   No:15596     
Title: Re:質問です。    
for while等を使っています。
gotoは使えないルールです。
fgetも使っていいと言われていますが使うと「getcharに直せ」と
注意されます。


66ポイント を手に入れた。

Name: Mist  ..かけだし(1,554ポイント)   Date: 2008/04/16(水) 13:13   No:15597     
Title: Re:質問です。    
時期的に会社の新人研修かと思いますが、こういったところで答えを
求めるよりも自分で調べられるだけ調べて、それでもわからなかった
ら指導員に聞くほうがいいと思いますけどね。(その場合、自分がどこ
まで調べてどこがわからないのかを具体的に提示すること。ここの質
問に書かれたような内容ではOUTです)

新人研修というのはその会社で必要とする技術を身につける場でもあり
ますが、自分で調べる力やグループ作業をしていく上で必要な手順やマ
ナー等を学ぶステージでもあるから、ソースコードとして満点回答を出
すことにはあんまり意味がなかったりします。

と、研修指導したことのある人からのアドバイスです。


244ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(83,715ポイント)   Date: 2008/04/16(水) 14:42   No:15598     
Title: Re:質問です。    
うーん、かなり力技だけど、こんな感じ?


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

// 文字列を入力する
// char* buf = 文字列格納用配列へのポインタ
// int size = バッファのサイズ
void strinput(char* buf, int size)
{
// カウント用変数
int cnt, minus = 0;

// 文字列の入力
for (cnt = 0; cnt < size - 1; cnt++)
{
// アドレスをずらしながらバッファに代入していく
*(buf + cnt) = (char)getchar();

// 改行文字が入力されたらループを抜ける
if (*(buf + cnt) == '\n')
{
break;
}
}

// 終端文字を追加
*(buf + size) = '\0';

// 数字符号以外を'\0'にする
for (cnt = 0; cnt < size; cnt++)
{
switch (*(buf + cnt))
{
case '-':
if (cnt != 0)
{
// 1文字目以外でマイナス符号が見つかった
minus++;
}
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
// 1文字目以外でマイナス符号が見つかっていたら、それ以降の文字は全て無効とする
if (minus != 0)
{
*(buf + cnt) = '\0';
}
break;
default:
// マイナス符号と数字以外は無効
*(buf + cnt) = '\0';
break;
}
}

// ストリームのフラッシュ処理
fflush(stdin);
}

int convert(int val, int cnt, int size)
{
return (int)pow(10.0, (double)(size - cnt - 1)) * val;
}

// 文字列をint型の数値に変換する
// char* str = 変換したい文字列
int strint(char* str)
{
int cnt, result = 0;

// 1桁ずつ数値に変換していく
for (cnt = 0; cnt < (int)strlen(str); cnt++)
{
switch (*(str + cnt))
{
case '-':
break;
case '0':
break;
case '1':
result += convert(1, cnt, (int)strlen(str));
break;
case '2':
result += convert(2, cnt, (int)strlen(str));
break;
case '3':
result += convert(3, cnt, (int)strlen(str));
break;
case '4':
result += convert(4, cnt, (int)strlen(str));
break;
case '5':
result += convert(5, cnt, (int)strlen(str));
break;
case '6':
result += convert(6, cnt, (int)strlen(str));
break;
case '7':
result += convert(7, cnt, (int)strlen(str));
break;
case '8':
result += convert(8, cnt, (int)strlen(str));
break;
case '9':
result += convert(9, cnt, (int)strlen(str));
break;
default:
if (*str == '-')
{
return result *= -1;
}
else
{
return result;
}
}
}

if (*str == '-')
{
return result *= -1;
}
else
{
return result;
}
}

int main()
{
int num_1 = 0, num_2 = 0;
char str[10];

// 数値1の入力
printf("数値1を入力して下さい\n");
strinput(str, 10);
num_1 = strint(str);

// 数値2の入力
printf("数値2を入力して下さい\n");
strinput(str, 10);
num_2 = strint(str);

// 数値と絶対値の表示
printf("数値1 = %d\n", num_1);
printf("数値2 = %d\n", num_2);
printf("絶対値 = %d\n", abs(num_1 - num_2));

// 終了
return 0;
}


1,179ポイント を手に入れた。

Name: やそ  ..熟練のプログラマー(40,624ポイント)   Date: 2008/04/16(水) 14:48   No:15599     
Title: Re:質問です。    
>fgetも使っていいと言われていますが使うと「getcharに直せ」と注意されます。

scanf()の危険性を考慮して使わせないのは悪いことではありませんが、getchar()も同様な危険性があります。
以下、別サイトの抜粋文
----------------------------------------
getchar() はキーボードから 1 文字取得する関数ですが、 Windows や Unix ではキーボードから 1 文字入れただけでは getchar() から帰ってきません。1 文字入力した後に「リターン」を入れる必要があります。しかし、getchar() から帰って来た時点で「リターン」は入力用のバッファに残ったままであり、次に getchar() を呼ぶと、残っていた「リターン」を入れて帰ってきます。このように getchar() はバグを誘発しそうな危険な関数なので、i = getchar() あるいは scanf("%c",&c) などはお勧めしません。
----------------------------------------
getchar()は1文字入力用ですし、1文字入力するたびにリターンキーが必要となります。コレでは現実的なプログラムの作成は難しい(面倒くさい)と思われます。

getchar()で作った場合、入力イメージは(-123456、654321の場合)
-
1
2
3
4
5
6

6
5
4
3
2
1
と入力させるわけですよね。現実的な入力方法じゃないです^^;

たとえば、
 1.スタート
 2.終了
 3.つづきから
などのメニューがあって、番号を選択する場合などにはgetchar()も使えると思うのですがね^^;

fgets()とsscanfの組み合わせで入力させるのがいいんじゃないかな?
標準入力のstdinを指定すればキーボードから入力できるし^^

sscanfをする場合、事前にfets()で読み取った文字列の妥当性をチェックしたほうが良いでしょう。
あくまで文字列なので、どんな入力の仕方でも受け付けますから^^;
1.空エンター
2.桁数制限越え
3.マイナスの位置や数の妥当性
  →123-、--2345、1-234などなど
4.数字以外の文字

とかでしょうか。
それらを踏まえて、もう一度挑戦してみて下さいね^^


635ポイント を手に入れた。

Name: やそ  ..熟練のプログラマー(40,705ポイント)   Date: 2008/04/16(水) 14:54   No:15600     
Title: Re:質問です。    
バグさんお疲れ様です^^
かなりの力技、恐れ入ります^^;

指導員から課題を与えられて〜というボムボムさんのレベルで、正直そこまで求められているのか??
と言う疑問は置いといて(笑)

コレを提出したときの指導員の顔を見てみたくなるのは私だけ??(だいたひかる風)


81ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(83,818ポイント)   Date: 2008/04/16(水) 15:02   No:15601     
Title: Re:質問です。    
>>やそさん
オーバーフローチェックをしてなかったり、fflushが本来の使い方でなかったりと、かなり突っ込みどころ満載のソースではありますが、とりあえず私の環境では問題なく動きました(笑)
ちなみにWindowsXP、VC++6.0で開発してます。

なんというか、ポインタや文字列の扱いに慣れるという意味では、面白い課題ではないかな〜?と思いますね(^-^)


103ポイント を手に入れた。

Name: やそ  ..熟練のプログラマー(41,012ポイント)   Date: 2008/04/16(水) 16:17   No:15602     
Title: Re:質問です。    

>>バグさんへ
ボムボムさんは絶対値計算を自作していますね。
もしかしたらabs()も使用禁止??

case '1':
result += convert(1, cnt, (int)strlen(str));
break;

の方法にはこだわりを感じました(笑)
また、char str[10];
を使いまわすことによって、「入力した数値を保存する必要はない」の要件を満たしていますね。
ある程度なれた方なら当たり前にやっていることではありますが、初心者などは、ロジックの分かりやすさから
2つの変数用に入力バッファも分けて用意したりすることがありますからね。
指導員の言いたいこと(狙い)もその辺なのでしょうね^^




307ポイント を手に入れた。

Name: ボムボム  ..ぴよぴよ(908ポイント)   Date: 2008/04/16(水) 18:28   No:15606     
Title: Re:質問です。    
申し訳ありません。
int absolute(int n1, int n2)
{
int i ;

i = n1 - n2 ;
return i >= 0 ? i : -i ;
}

int absolute(int n1, int n2)は使わないといけないユーザー関数なのでこれがないと提出できません。


97ポイント を落としてしまった。

Name: やそ  ..熟練のプログラマー(41,649ポイント)   Date: 2008/04/16(水) 18:55   No:15607     
Title: Re:質問です。    
>int absolute(int n1, int n2)は使わないといけないユーザー関数なのでこれがないと提出できません。

やはりそうでしたか。
ボムボムさんに質問です。いまさらですが、10進数8桁の正数はご使用になられているコンパイラのintの制限内に収まっていますでしょうか?
収まっていない場合、誤差が出ますよね?(何誤差だったか忘れました。丸め?情報落ち?桁落ち?)
またabsolute()の引数もint?




177ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(83,859ポイント)   Date: 2008/04/16(水) 19:12   No:15608     
Title: Re:質問です。    
>>ボムボムさん
私の書いたソースの中で絶対値を計算している場所があります。そこで使用している関数と、その自前のabsolute関数を入れ替えていただくだけで動くように思います。

あと、やそさんも書かれていましたが、getchar関数の動きは環境によって異なります。私はVisualStudioでの開発でしたので、それにあわせた組み方をしています。何が言いたいかというと、ボムボムさんの環境でも同じように動いてくれる保障は無いという事なんです。

その辺りの確認作業まではこちらではアドバイスのしようがありませんので、ご自分でお願いしますね。


41ポイント を手に入れた。

Name: ボムボム  ..ぴよぴよ(910ポイント)   Date: 2008/04/16(水) 19:26   No:15609 解決!     
Title: Re:質問です。    
わかりました。
皆さん色々と有難う御座いました。
お世話になりました。


2ポイント を手に入れた。

Name: しっぽ  ..中級者(9,625ポイント)   Date: 2008/04/17(木) 01:32   No:15618     
Title: Re:質問です。    

/*
久しぶりの投稿です。投稿したコードは、処理順が変テコだったり、
可読性が悪かったりしてますが、短いコードとの折り合いを
もちべーじょん にして作ってみました。
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define KETA_MAX 9 // 符号も1桁に数えて、8+1=9
#define ERRSTRLEN 256

int absolute(int n1, int n2)
{
int value = n1 - n2;
return value > 0 ? value : -value;
}

int main()
{
int j, k;
int ch;
int sign; // 符号
int value[2]; // 入力数値
char err[ERRSTRLEN] = {0};

for(j = 0 ; j < 2 ; j++){

printf("%d番目の数値を入力 :", j + 1) ;

for(k = 0, value[j] = 0, sign = 1; (ch = getchar()) != '\n'; ++k){

if(k == 0){
if(ch == '-') sign = -1;
if(ch == '-' || ch == '+') continue;
++k; // 符号も1桁として数えるので+1する
}

value[j] = value[j] * 10 + ch - '0';

if(k >= KETA_MAX) strncpy(err, "桁数がオーバーした", ERRSTRLEN - 1);
else if(ch < '0' || ch > '9') strncpy(err, "数値以外の入力があった", ERRSTRLEN - 1);
}

if(k < 2) strncpy(err, "数値入力がなかった", ERRSTRLEN - 1);
if(err[0]) break;

value[j] *= sign;
}

if(err[0]) return printf("エラー : %s", err) != 0;

return !printf("差分の絶対値 : %d\n", absolute(value[0], value[1]));
}



414ポイント を手に入れた。



Name: kazuoni  ..中級者(9,415ポイント)   Date: 2008/04/15(火) 00:35   No:15568       
Title: 引数の記述    
お邪魔します。以下のコードについてなんですが、
void draw_state_left_graph(const char *naming[@] , int selection_number){//ステータスメニュー画面左側

int i;
for(i=0;i<=(selection_number-1);i++){
if(state_menu_font_flag==(i-1) && state_which_flag==0)
DrawStringToHandle( 19 , (27+(i*45)) , naming[i] , GetColor(150,2,2) , state_menu_font );
else
DrawStringToHandle( 19 , (27+(i*45)) , naming[i] , GetColor(0,0,0) , state_menu_font );
}
}

〜関数の目的〜
state_menu_font_flagと一致するchar型へのポインタの配列の文字列の色とそれ以外の文字列の色を分け、記述することを目的としています。例えば、

const char *selection_names[6]={"アイテム" , "装備" , "魔法" , "ステータス" , "セーブ" , "ゲーム終了"}
state_menu_font_flag=3
state_which_flag=0

の条件のとき、
draw_state_left_graph(selection_names[6] , 6)

この結果は魔法は色つき、それ以外は黒字で順に縦に表示されるようにしたいのです。
int selection_numberは*selection_names
の要素の数と一致します。

そこで質問なんですが、
draw_state_left_graph
のカッコの中の
const char *naming[@]
には何と記述したらよいのでしょうか?またこの関数のプロトタイプ宣言の記述はどうしたらよいでしょうか?[int〜]と書くとエラーになってしまいます。

よろしくお願いします。


30ポイント を手に入れた。


Name: box  ..ハッカー(109,614ポイント)   Date: 2008/04/15(火) 09:06   No:15571     
Title: Re:引数の記述    

こんなサンプルコードを動かして体感してみてください。


#include <stdio.h>

void draw_state_left_graph(const char **naming, int selection_number);

int main(void)
{
const char *selection_names[] = {
"アイテム" , "装備" , "魔法" , "ステータス" , "セーブ" , "ゲーム終了"
};
int i;

for (i = 0; i < sizeof(selection_names) / sizeof(selection_names[0]); i++) {
draw_state_left_graph(selection_names, i);
}
return 0;
}

void draw_state_left_graph(const char **naming, int selection_number)
{
printf("%s\n", naming[selection_number]);
}



279ポイント を手に入れた。

Name: kazuoni  ..中級者(9,482ポイント)   Date: 2008/04/15(火) 19:01   No:15581 解決!     
Title: Re:引数の記述    
boxさんご回答ありがとうございます!!
ポインタのポインタですかっ^^;うーん・・・分かっていないところがどんどん出てきますね(汗)
とりあえずうまくいきました^^
今からググりに行ってきますww

ありがとうございました!またよろしくお願いします。


67ポイント を手に入れた。



Name: ほにゃー  ..かけだし(1,076ポイント)   Date: 2008/04/13(日) 05:56   No:15515       
Title: メモリの解放について    
どうも、再び質問をさせてもらいます。
私はC++を使いシューティングゲームを作成しています。


そのシューティングゲームの敵や弾、爆風などはそれぞれのクラスを作り、
listを使い追加と削除をしております。
しかし、キチンとeraseを使い要素の削除をしているはずなのですが、
タスクマネージャーで確認するとゲームを起動している間はメモリの使用率は
徐々に上がっていき、下がることがありません。

InitGraph()などでメモリに読み込んだ画像や音楽を消去した場合は
画像や音楽の分だけメモリの使用率がさがるのですが、
それ以外の部分は使用したままです。

そのため、ゲームを続けているとメモリリークを起こしてしまいます。
どうしたらメモリの使用率の上昇を防ぐことができるでしょうか?

どなたかご教授お願いいたします。


使用コンパイラ
VC++2005ExpressEdition


388ポイント を手に入れた。


Name: Justy  ..ハッカー(189,060ポイント)   Date: 2008/04/13(日) 21:32   No:15530     
Title: Re:メモリの解放について    
>タスクマネージャーで確認するとゲームを起動している間はメモリの使用率は
>徐々に上がっていき、下がることがありません

 細かい説明は省略しますが、Windowsのタスクマネージャーのメモリ使用量では
アプリケーションのメモリリークを厳密に調べることは出来ません。

(ハンドルの解放漏れとかはタスクマネージャでもちゃんと把握できるのですが・・・)


>そのため、ゲームを続けているとメモリリークを起こしてしまいます

 ソースコードと実際に実行したときの挙動を見てみないと正確な判断はできませんが、
上記の情報だけですとリークが発生している、と断定出来る状態ではないようです。

 まずは本当にリークしているかどうかを調べることが重要です。
 MSVC環境とのことですので、

ttp://msdn2.microsoft.com/ja-jp/library/e5ewb1h3(VS.80).aspx
ttp://www.microsoft.com/japan/msdn/vs_previous/visualc/techmat/feature/MemLeaks/

 この方法でも試してみてはどうでしょう?

 MSVCの CRTライブラリを使えばメモリの状態のスナップショットを取ったり、
その比較をしたりできますので、比較的簡単にリークの検出・特定ができる可能性があります。



>どうしたらメモリの使用率の上昇を防ぐことができるでしょうか?

 使用率の上昇を防ぎたいのであれば、とにかく無駄なメモリを使わない
こと以外にはありません。

 画面に描画していないデータ(画像とか)はメモリから削除するとか、
音声は全てを読み込まないでストリーミング再生にするとか。


609ポイント を手に入れた。

Name: ほにゃー  ..かけだし(1,536ポイント)   Date: 2008/04/14(月) 19:13   No:15557     
Title: Re:メモリの解放について    
Justyさん、回答ありがとうございます。
CRTライブラリを使用しメモリの状態を調べてみたところ、
やはりメモリリークを起こしているようでした。

そしてその原因はlistのあるようでした。
erase()やclear()で要素を削除してみても完全に消えきらずに4分の一ほど残っているようでした。
以下はlistのメモリ解放の実験に使用したプログラムのソース(一部略)です。


_CrtMemState s1;
_CrtMemCheckpoint( &s1 );

list<C_test*> test;

_CrtMemCheckpoint( &s1 );
_CrtMemDumpStatistics( &s1 );

for(a = 0; a<1000 ; a++)
test.push_back(new C_test(5));

_CrtMemCheckpoint( &s1 );
_CrtMemDumpStatistics( &s1 );

test.clear();

_CrtMemCheckpoint( &s1 );
_CrtMemDumpStatistics( &s1 );


結果はこのようになりました。(一部略)

12 bytes in 1 Normal Blocks.
Largest number used: 11423 bytes.
Total allocations: 26123 bytes.

16012 bytes in 2001 Normal Blocks.
Largest number used: 27216 bytes.
Total allocations: 42123 bytes.

4012 bytes in 1001 Normal Blocks.
Largest number used: 27216 bytes.
Total allocations: 42123 bytes.


listの要素を完全に削除するにはどうしたらよいのでしょうか?
ご教授お願いします。


460ポイント を手に入れた。

Name: GPGA  ..熟練のプログラマー(47,824ポイント)   Date: 2008/04/14(月) 19:32   No:15558     
Title: Re:メモリの解放について    
newしたオブジェクトをdeleteしていませんから、メモリリーク起こして当然です。
test.clear();の前に以下の文を入れてください。


list<C_test*>::iterator it = test.begin();
for (; it != test.end(); ++it) {
delete *it;
}
 


79ポイント を手に入れた。

Name: Justy  ..ハッカー(189,606ポイント)   Date: 2008/04/14(月) 22:17   No:15562     
Title: Re:メモリの解放について    
 まずは GPGAさんの書かれている通りなのですが、

list<C_test*>
 ポインタである必要が本当にありますか?
 必要なら仕方ないですが、list<C_test>とできないかどうか検討してみて下さい。


 基本的にリストの削除の度に deleteしなければならないのは著しく面倒で、
バグの元になります。

 どうしてもポインタにしたいのであれば、リストの削除を行ったときに
自動的に deleteしてくれるようなコンテナの使用(或いは作成)をしてみてはどうでしょう。



256ポイント を手に入れた。

Name: ほにゃー  ..かけだし(1,596ポイント)   Date: 2008/04/15(火) 15:38   No:15576 解決!     
Title: Re:メモリの解放について    
なるほど、deleteを呼びだすのを忘れていたからですね。
deleteを追加したらメモリリークは起こらなくなりました。
ありがとうございます。

list<C_test*>となっていたのは、
listのことを勉強したサイトで<>の中身をポインタにしていたからです。
今見てみると、ゲームで使うのならばポインタである必要はありませんでした。

これでようやくゲーム制作を進めることができます。
本当にありがとうございました。


60ポイント を手に入れた。



Name: knight  ..ぴよぴよ(155ポイント)   Date: 2008/04/14(月) 14:45   No:15540       
Title: 下のソースをifを使わないで書く方法    
#include <stdio.h>

int main(void)
{
int i, j;

for(i=5; i>0; i--){
for(j=1; j<=5; j++){
if(j > i){
printf("■ ");
}else{
printf("□ ");
}
}
printf("\n");
}

return 0;
}
これをifを使わないで書く方法を教えてください。
とりあえず、自分で、途中までしたのを下に書きます。
#include <stdio.h>

int main(void)
{
int i, j;

for(i=0; i<5; i++){
for(j=4; j>=i; j--){
printf("□ ");
}
printf("■ ");
printf("\n");
}

return 0;
}


155ポイント を手に入れた。


Name: バグ  ..比類無きプログラマー(81,267ポイント)   Date: 2008/04/14(月) 14:49   No:15541     
Title: Re:下のソースをifを使わないで書く方法    
switchを使ってみては如何でしょうか?

13ポイント を手に入れた。

Name: knight  ..ぴよぴよ(192ポイント)   Date: 2008/04/14(月) 14:57   No:15542     
Title: Re:下のソースをifを使わないで書く方法    
ありがとうございます。for分だけで書く場合はどうなるのでしょうか?

37ポイント を手に入れた。

Name: GPGA  ..熟練のプログラマー(47,745ポイント)   Date: 2008/04/14(月) 15:09   No:15543     
Title: Re:下のソースをifを使わないで書く方法    
これはどうでしょうか?

#include <stdio.h>

int main(void)
{
int i, j;

for(i=5; i>0; i--){
for(j=1; j<=5; j++){
printf("%s ", j > i ? "■" : "□");
}
printf("\n");
}
return 0;
}


62ポイント を手に入れた。

Name: knight  ..ぴよぴよ(220ポイント)   Date: 2008/04/14(月) 15:13   No:15544 解決!     
Title: Re:下のソースをifを使わないで書く方法    
ありがとうございます〜。助かりました。感謝いたします。

28ポイント を手に入れた。

Name: toyo  ..初心者(6,928ポイント)   Date: 2008/04/15(火) 09:48   No:15574     
Title: Re:下のソースをifを使わないで書く方法    
もう解決したようですが
私の答えはこれだ

#include <stdio.h>

int main(void)
{
int i, j;

for(i=5; i>0; i--){
for(j=1; j<= i; j++){
printf("□ ");
}
for(; j<= 5; j++){
printf("■ ");
}
printf("\n");
}

return 0;
}



168ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(82,253ポイント)   Date: 2008/04/15(火) 10:25   No:15575     
Title: Re:下のソースをifを使わないで書く方法    
では、私はこれで(笑)


#include <stdio.h>

int main(void)
{
printf("□□□□□\n");
printf("□□□□■\n");
printf("□□□■■\n");
printf("□□■■■\n");
printf("□■■■■\n");
return 0;
}


90ポイント を手に入れた。



Name: バグ  ..比類無きプログラマー(81,254ポイント)   Date: 2008/04/14(月) 14:19   No:15539       
Title: C#のネットワークプログラムについて    
C#の質問なので場違いかもしれませんが…

今、TcpClientクラスとTcpListenerクラスを使用した通信クラスを作成しています。

そこで質問なのですが、クライアントPCがなんらかのアクシデント(例えば停電など)で正規の手続きを踏まずにPC自体の電源が切られて強制的にアプリケーションが終了した場合に、サーバー側からそれを知る事というのは出来るのでしょうか?

通常の強制終了は例外が発生するので、それを拾えば処理できるのですが、こういうイレギュラーな強制終了の場合には例外が発生しないので困っております。もし、ご存知の方がいらっしゃったら、是非ご教授願えないでしょうか?

やはりSocketクラスを使用するしかないのでしょうか…


180ポイント を手に入れた。


Name: keichan  ..プログラマー(30,518ポイント)   Date: 2008/04/14(月) 17:59   No:15555     
Title: Re:C#のネットワークプログラムについて    
ネットワークに詳しくないので参考になりそうなリンクだけ張っておきます。

http://yanesdkdotnet.sourceforge.jp/wiki/index.php?Yanesdk.Network
「切断検知のメカニズムについて」


グーグルでの検索キーワード
「ネットワーク クライアント 例外 切断」


121ポイント を落としてしまった。

Name: バグ  ..比類無きプログラマー(81,926ポイント)   Date: 2008/04/14(月) 18:12   No:15556     
Title: Re:C#のネットワークプログラムについて    
返信ありがとうございます。一応、気になるキーワードでググってみてはいるので、紹介いただいたページもブックマーク済だったりします(^_^;)

ただ、私の質問は切断検知のアルゴリズムではなくて、前述のクラスに切断検知を行なう機能があるかどうか…だったんですよね…


2倍のポイントを手に入れた! 2ポイント を手に入れた。

Name: Justy  ..ハッカー(189,350ポイント)   Date: 2008/04/14(月) 21:39   No:15560     
Title: Re:C#のネットワークプログラムについて    
>前述のクラスに切断検知を行なう機能があるかどうか

 無いと思います。
 クライアントの電源が切られたら、通信して知らせる暇無く落ちます。
 UPSがあれば別ですが。


>サーバー側からそれを知る事というのは出来るのでしょうか?

 クライアントが次に起動したときに、ならなんとかなるんじゃないでしょうか。

 起動時に何かしておいて、正常な終了時に元に戻す。
 起動したときに、元に戻っていなかったら前回異常終了した、とクライアントが判定して
サーバーにその情報を送る、とか。


 次に起動したときでは遅い、できるだけ早く知りたい、のであれば

・ 一定間隔おきに通信を行って、正常な終了時の信号なしに突然途切れたら
(ネットワーク異常だとか別の要因だとしても)サーバー側で異常終了したと判定する。

・ マシンをもう一台用意して、対象のクライアントの状態を監視する
(その別のマシンが電源の状態も監視できるとベスト)

 とかはどうでしょうか。


290ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(82,067ポイント)   Date: 2008/04/14(月) 22:42   No:15564     
Title: Re:C#のネットワークプログラムについて    
返信ありがとうございます。
やはり、基本はハンドシェイクさせないと駄目なんですね。ただ、ポーリングさせるのはCPUに掛かる負担が大きくなってしまうので、極力避けたいんですよね…。
となると、クライアント側の正常終了時に情報を更新させるという処理がよさそうですね。実際、異常切断状態を検知するよりも、異常切断から復旧させる手段を知りたかったものでして…非常に助かりました。
正直、この発想は思い付かなかったので、目から鱗でした。


141ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(82,099ポイント)   Date: 2008/04/15(火) 09:26   No:15572 解決!     
Title: Re:C#のネットワークプログラムについて    
おっと、携帯からの書き込みだったので解決マークを付け忘れてました(^_^;)

32ポイント を手に入れた。



Name: 水孤  ..ぴよぴよ(978ポイント)   Date: 2008/04/15(火) 00:18   No:15567       
Title: 数値から数を判定するには    
タイトルが少しわかりにくてすいません。
何をいいたいかというと、ある変数scoreがあったとしてscore=12345678 とし、このとき配列のscore_a[0]に8、score_a[1]に7、score_a[2]に6・・・という感じで代入をしたいと思っています。
しかし、scoreからどうやったら各桁の数字を求めればよいのかがわからないので、四苦八苦しています。
考え方でのよろしいので何か教えてくれるとうれしいです。

また、特に絶対このやり方でないというわけではないので、違う方法で同じことが出来るというのがあればそちらの方でも全くかまいません。


246ポイント を手に入れた。


Name: Justy  ..ハッカー(189,796ポイント)   Date: 2008/04/15(火) 00:46   No:15569     
Title: Re:数値から数を判定するには    
 scoreを 10で割ったときの余りを出せば1桁目が出ますよね?(score=12345678なら、score%10 で 8)
 あとは一度scoreを 10で割って(score=1234567)再び余りを計算すれば 10の位の数字(7)が求まります。

 これを scoreが 0になるまで繰り返せば全桁を求めることができます。


Name: 水孤  ..かけだし(1,005ポイント)   Date: 2008/04/15(火) 01:39   No:15570     
Title: Re:数値から数を判定するには    
回答ありがとうございます。
無事自分のやりたかったことが出来ました。
まだまだ、プログラムについては初心者なのでこれからもがんばります。


27ポイント を手に入れた。



Name: DD  ..ぴよぴよ(146ポイント)   Date: 2008/04/13(日) 15:04   No:15518       
Title: 分割コンパイルについて    
シューティングゲームの館の分割コンパイルをやってみたんですが、

プロジェクト : error PRJ0002 : エラーの結果 -1073741819 が 'C:\Program Files\Microsoft Visual Studio 8\VC\bin\mt.exe' より返されました。

というエラーが出てきて、コンパイルできずに困っています。
解決法がわかる方、ご教授おねがいします。


146ポイント を手に入れた。


Name: 管理人 [URL]  ..伝説のハッカー(555,144ポイント)   Date: 2008/04/13(日) 16:07   No:15521     
Title: Re:分割コンパイルについて    
エラー番号でググってみてはいかがでしょうか。

PRJ0002
http://www.google.co.jp/search?hl=ja&q=PRJ0002&btnG=%E6%A4%9C%E7%B4%A2&lr=lang_ja

コンパイラ名などを添えていただけると回答が得やすいかもしれません。


87ポイント を手に入れた。

Name: DD  ..ぴよぴよ(193ポイント)   Date: 2008/04/14(月) 22:06   No:15561     
Title: Re:分割コンパイルについて    
ググってみても的を獲た回答がありませんでした。
新規プロジェクトで最初からやり直してみようと思います。
ありがとうございました。


47ポイント を手に入れた。

Name: 通りすがり  ..初心者(7,605ポイント)   Date: 2008/04/14(月) 22:34   No:15563     
Title: Re:分割コンパイルについて    
誤:的を獲た
正:的を射た


12ポイント を手に入れた。

Name: Justy  ..ハッカー(189,796ポイント)   Date: 2008/04/14(月) 22:57   No:15565     
Title: Re:分割コンパイルについて    
>ググってみても的を獲た回答がありませんでした
 もう遅いでしょうが、ぐぐったら一発目で出てきました。

MSDN Forums
ttp://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=214591&SiteID=1


2倍のポイントを手に入れた! 190ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(556,588ポイント)   Date: 2008/04/14(月) 23:43   No:15566     
Title: Re:分割コンパイルについて    
こんな調べ方でも同じような結果が出てきます。
http://www.google.co.jp/search?hl=ja&q=%5CVC%5Cbin%5Cmt.exe&lr=


2倍のポイントを手に入れた! 96ポイント を手に入れた。



Name: 超初心者  ..入門者(3,904ポイント)   Date: 2008/04/14(月) 15:19   No:15545       
Title: もう限界・・・    
学校の課題で、
ABCDE
BCDEA
CDEAB
DEABC
EABCD
ABCDE
という結果になるようなpgをmainでchange(上のように形式をととのえるところ)とdisp(結果を表示するところ)を呼んで、書けという課題を出されました。
自分は下のところまで書きましたがもう限界です。
#include <stdio.h>

//プロトタイプ宣言
void change(char str[]);
void disp(int flag);

//main文
int main(void)
{
char str[] = "ABCDE";
int flag = 1;

while(flag){
flag = change(str);
disp(flag);
}

return 0;
}
//並び替えを行うエリア
void change(char str[])
{


}
//結果を表示するエリア
void disp(int flag)
{

}


289ポイント を落としてしまった。


Name: バグ  ..比類無きプログラマー(81,405ポイント)   Date: 2008/04/14(月) 15:24   No:15546     
Title: Re:もう限界・・・    
うーん、自分で書いたと言われても…私の目には穴埋め課題文そのまんまで、全く進んでいないように見えてしまうのですが…気のせいでしょうか?(^_^;)

それで、この課題の何が分かりませんか?それから学校では何を習っていて、何を習っていないかを教えてください。話はそれからだと思いますよ(^-^)


138ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(81,430ポイント)   Date: 2008/04/14(月) 15:26   No:15547     
Title: Re:もう限界・・・    
あ、それからもう一つ、disp関数の引数は何に使うのでしょうか?
こちらの解答もよろしくお願いします。


25ポイント を手に入れた。

Name: 超初心者  ..入門者(3,901ポイント)   Date: 2008/04/14(月) 15:28   No:15548     
Title: Re:もう限界・・・    
とりあえず、ifと関数とforは習いました。
mainにある配列ABCDEをchange関数で入れ替えるのがわかんないです。


3ポイント を落としてしまった。

Name: 超初心者  ..入門者(3,969ポイント)   Date: 2008/04/14(月) 15:34   No:15549     
Title: Re:もう限界・・・    
問題を出されたときの状態です。
#include <stdio.h>

//main文
int main(void)
{
char str[] = "ABCDE";
int flag = 1;

while(flag){

}

return 0;
}
//並び替えを行うエリア
void change(char str[])
{


}
//結果を表示するエリア
void disp()
{

}


2倍のポイントを手に入れた! 68ポイント を手に入れた。

Name: 超初心者  ..入門者(3,992ポイント)   Date: 2008/04/14(月) 15:37   No:15550     
Title: Re:もう限界・・・    
disp関数のflagは間違ってしまったものです。スミマセン


23ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(81,482ポイント)   Date: 2008/04/14(月) 15:44   No:15551     
Title: Re:もう限界・・・    
何度も申し訳ないんですけど…
1つ確認なのですが、disp関数の引数は何もなかったですか?
下記のようではなかったですか?


#include <stdio.h>

//プロトタイプ宣言
void change(char str[]);
void disp(char str[]);

//main文
int main(void)
{
char str[] = "ABCDE";
int flag = 1;

while(flag){

}

return 0;
}

//並び替えを行うエリア
void change(char str[])
{


}

//結果を表示するエリア
void disp(char str[])
{

}


52ポイント を手に入れた。

Name: 超初心者  ..入門者(3,927ポイント)   Date: 2008/04/14(月) 15:57   No:15552     
Title: Re:もう限界・・・    
とりあえず、問題にはそこの引数は何も書いてませんでした。
引数が同じだから書かなかったのか?、違う引数だった?のかはわかりません。
とりあえず、引数をchar str[]にするとどういうふうになるんですか?
スミマセンが、教えていただけないでしょうか?


65ポイント を落としてしまった。

Name: バグ  ..比類無きプログラマー(81,924ポイント)   Date: 2008/04/14(月) 16:23   No:15553     
Title: Re:もう限界・・・    
文字列はmain関数内で定義されていますよね?そういう事なので、基本的にはmain関数の中でしかこの文字列は使用できない訳です。
それでは、どうすれば他の関数で使用できるようになるかというと、change関数の引数のように教えてやる必要がある訳なんですね。
そういう訳で、disp関数に表示する文字列を教える必要はないのかな?と思った訳です。

とりあえず、文字列の入れ替えの考え方を書いておきますね。
文字列は下記のように格納されています。

str[0] = 'A'
str[1] = 'B'
str[2] = 'C'
str[3] = 'D'
str[4] = 'E'
str[5] = 'F'
str[6] = '\0' // 文字列の終端をあらわす文字です。

という事は、"ABCDEF"を"BCDEFA"にしたい場合は、何を入れ替えればいいでしょうか?

str[0] = str[1]
str[1] = str[2]
str[2] = str[3]
str[3] = str[4]
str[4] = str[5]
str[5] = str[0]
str[6] = str[6]

こういう事ですね?しかし、ここで問題が発生してしまいます。
最初の(str[0] = str[1])の時点で、str[0]の値がstr[1]の値に変わってしまう為、後の(str[5] = str[0])の式を実行しても、str[0]の値は保持されていませんので、str[5]の値は変換前のstr[1]の値になってしまいます。
具体的にどういう状態になるかというと…

str[0]('A') = str[1]('B') // str[0] = 'B' (この段階でstr[0]が'A'から'B'に変わってしまう)
str[1]('B') = str[2]('C') // str[1] = 'C'
str[2]('C') = str[3]('D') // str[2] = 'D'
str[3]('D') = str[4]('E') // str[3] = 'E'
str[4]('E') = str[5]('F') // str[4] = 'F'
str[5]('F') = str[0]('B') // str[5] = 'B'

こんなことになってしまいます。
そこで下記のように、str[0]の値をどこか別の場所で保持しておいて、上記の入れ替えが終了した段階でstr[5]に保持しておいた文字を代入してあげると見事に入れ替えが完成する訳です。

str[0]('A') = buf; // buf = 'A'
str[0]('A') = str[1]('B') // str[0] = 'B'
str[1]('B') = str[2]('C') // str[1] = 'C'
str[2]('C') = str[3]('D') // str[2] = 'D'
str[3]('D') = str[4]('E') // str[3] = 'E'
str[4]('E') = str[5]('F') // str[4] = 'F'
str[5]('F') = buf('A') // str[5] = 'A'


442ポイント を手に入れた。

Name: 超初心者  ..入門者(3,948ポイント)   Date: 2008/04/14(月) 16:28   No:15554     
Title: Re:もう限界・・・    
ありがとうございます。これで何とかがんばってみます

21ポイント を手に入れた。



Name: kazuoni  ..初心者(8,948ポイント)   Date: 2008/04/13(日) 15:25   No:15519       
Title: ゲームの構成    
お邪魔します。
なんだか質問してばっかですみません。。

管理人さんはよくScreenFlip()は一回だけメイン文に書いて、毎回そこを通るようにしたほうがいいとおっしゃっていたんですが、これはゲームプログラミングでは必須ですか?^^;今気がついたら、自分はメイン文以外でwhile文を使用し、その中でScreenFlip()を書いていました。。やはり変えていったほうがいいでしょうか^^;


162ポイント を手に入れた。


Name: 管理人 [URL]  ..伝説のハッカー(555,057ポイント)   Date: 2008/04/13(日) 16:03   No:15520     
Title: Re:ゲームの構成    
私もプロの世界でどのように作られるのが主流なのかわかりませんし、最適なプログラミングの方法も存じませんから、私の我流を、単なる参考としてしかかけないのですが、
それを承知の上でご覧下さい。


画面クリア関数や裏画面反映関数はプログラムの中1箇所で書けばよく色んな場所で書く必要が無いということをはじめ、色んなところでループして、あちこちで処理が返ってこないとバグが出た時に追いにくく、管理がしにくいです。
ブレイクポイントを設定したとしても、それを通らなかったり、一体何処で不具合が出ているのかわからなくなってきます。
小さいゲームではそれが明確に実感できないかもしれませんが、少し規模が大きくなり、運営や常時バグ取りが必須になってくると、あちこちでループしたり、似たような処理が色んな箇所で行われていると、
とてもじゃないけど、効率的にそれが行えません。

それに、「1周に1度この処理を入れたい」と思ったとしても、あちこちにループがあると、その挿入をあちこちでしなければならなくなります。
つまり

ループA

ループB

ループC

メインループ

が合った時、それぞれのループは独立して処理はメインに返ってこないものだとすると、処理1を追加したい時、

ループA 処理1

ループB 処理1

ループC 処理1

メインループ

と追加しなければならず、とても無駄であり、追加ミスも出てくるでしょう。でも、メインループでABCがまわっていれば
処理1はメインループにだけ追加すればよく、便利です。

私は是非ともメインループには必ず1周に1回返って来るようなプログラムをオススメします。


486ポイント を手に入れた。

Name: kazuoni  ..中級者(9,237ポイント)   Date: 2008/04/13(日) 20:46   No:15527 解決!     
Title: Re:ゲームの構成    
管理人さんご回答ありがとうございます!

今自分の書いたコードを見直してたんですけど・・・なんて効率の悪いことを最初しているんだっ・・・って落胆しました^^;ww
一ヶ月前に書いたものがなんだか残念すぎるものだったので、これを機に全体的にきれいにしてきます。flagの使いすぎで、どれがどのflagか究極にわかりづらいです。。

ありがとうございました!またよろしくお願いします。


109ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(556,188ポイント)   Date: 2008/04/13(日) 23:58   No:15534     
Title: Re:ゲームの構成    
フラグはそのフラグごとに構造体にするといいですよ。
それらのフラグはまた更に一つの構造体に纏めます。
するとすべてflag.〜〜で指定出来るのでカテゴリごとにまとめられますし、
初期化する時はmemsetで全て一気に0に出来るので初期化漏れも生まれません。



typedef struct{
  int ○○;
}メニューフラグ_t;

typedef struct{
  int ○○;
}ステータスフラグ_t;

typedef struct{
  int ○○;
}自機フラグ_t;

typedef struct{
メニューフラグ_t メニューフラグ;
  ステータスフラグ_t ステータス;
  自機フラグ_t 自機フラグ;
}flag_t;

flag_t flag;

こうすればflag.メニューフラグ.○○と指定出来るので、カテゴリわけされて管理でき、便利です。



2倍のポイントを手に入れた! 436ポイント を手に入れた。

Name: kazuoni  ..中級者(9,385ポイント)   Date: 2008/04/14(月) 00:28   No:15535 解決!     
Title: Re:ゲームの構成    
こりゃすごいっ!!ww思いつきませんでした。。

即座に変えます^^

ありがとうございました。またよろしくお願いします。


37ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(556,492ポイント)   Date: 2008/04/14(月) 02:37   No:15536     
Title: Re:ゲームの構成    
おぉ、そんなに驚いてもらえるとは^^;

初期化漏れが起きそうな、初期化する必要のある何か量の多い変数は全て構造体にしてしまえばいいと思います。

更にもっと量が多いものについてはVector等を用いるといいと思います。
これはC++の機能になりますので、STL関係の本じゃないと詳しく載ってなかったりするのですが、
簡単に言うと、配列の長さが自由に調整できるもの、
配列の中に挿入したり、切り取ったり、特定の中身を取り出して後ろから前に詰めてくれたり、自動でしてくれる機能です。

まぁmallocや線形リスト等で自分で実装してもいいと思いますが、こちらの方が処理が早いんですかね・・?詳細はよくわかりませんけど、覚えてしまうと便利です。


304ポイント を手に入れた。



Name: old  ..ぴよぴよ(120ポイント)   Date: 2008/04/13(日) 16:24   No:15522       
Title: 参考書のような物を・・・    
こんにちわ

私はまだ学生の身でC言語を勉強中のものですが、
自分の力量を図るためにシューティングやRPGと言ったゲーム物を製作しています。


何度もコチラのHPを拝見させて貰ってますが、
やはり、身近な所に参考書などが欲しい物で・・・


猫でも解るシリーズは全て読破しましたが
シューティングに関する本は、かなりの量のためどれを選べば良いか迷っています。

初心者〜中級者向けの基本が詰まった本であると嬉しいのですが・・・

管理人さんとは無縁かもしれませんが、
一つ、オススメできるゲームC言語参考書を紹介していただきたいなと
皆様のご意見をお聞かせ願えないでしょうか?


120ポイント を手に入れた。


Name: ジーコ  ..ぴよぴよ(108ポイント)   Date: 2008/04/13(日) 16:40   No:15523     
Title: Re:参考書のような物を・・・    
ボクは14歳からはじめるC言語ゲームプログラミング
http://www.rutles.net/books/151.html
これを最初にしました。

14歳なんて子供っぽいなぁとおもっていたのですが、かなり参考になります。

この本を最後まで勉強すれば横スクロールシューティングゲームが作成できるようになります。



とはいってもボクもCをやり始めて1年目なんですけどね・・・・
一緒に頑張りましょう。


108ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(555,571ポイント)   Date: 2008/04/13(日) 18:52   No:15524     
Title: Re:参考書のような物を・・・    
>oldさん

こんにちは。

ジーコさんも仰っているように、DXライブラリには書籍が出ていますので
http://homepage2.nifty.com/natupaji/DxLib/
もしDXライブラリの書籍がほしければそちらを参考にされてはいかがでしょうか。

私はゲームプログラム系の書籍を全く読んでいないので、書籍関係はわかりません、ごめんなさい。

書籍を選ぶときは私は大きな本屋に行って端から読んでみます。
その人のスキルや好みによって読みやすい本は様々だと思います。
全員が同じ本を読みやすいと感じたらその本だけ売れるはずですしね。

まだプログラムがよくわからないときは、図式が書いてあったり、説明が少し抽象的なほうがわかりやすいこともあるでしょうし、
熟練者なら難い書き方でも、詳しく正確に書いてあるほうがいいと思うでしょう。

なので、一度大きな書店に行って、端から読んでみることをオススメしますよ。
私も以前このように、オススメの本を質問して、買ってみたけど、結局読みにくくてよめなかったことがありました。
ちなみに私はまだまだ駆け出しなので、本やウェブにはお世話になりまくりです;


427ポイント を手に入れた。

Name: ジーコ  ..ぴよぴよ(259ポイント)   Date: 2008/04/13(日) 23:26   No:15532     
Title: Re:参考書のような物を・・・    
>管理人さん
そうなんですか。
最初にGUIのゲームを作成するときにシューティングがいいと友達から言われたので漠然とそれにあったゲームプログラミングを作成できる参考書を選んだだけなのですがね・・・。

ところで話が脱線してしまうのですが・・・・・(これは違った場所で新しく質問したほうがいいのかもしれない・・・)
東方系の(サイトで紹介している)ゲームで自機と敵のあたり判定。敵の弾と自機とのあたり判定のソースって公表してるんですか??
それがわからなくて参考書を参考にしていやってるんですが全然うまくいかなくて・・・


151ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(555,752ポイント)   Date: 2008/04/13(日) 23:53   No:15533     
Title: Re:参考書のような物を・・・    
あ、DXライブラリのとこから出版されているようですよ、あの本は。

四聖龍神録のことでしょうか?
シューティングの館でも、そのコードは紹介していません。
・・というか、シューティングゲームの館で紹介しているコードは拡張する事を想定していません・・。

でも自機と敵の当たり判定は、単にピタゴラスの定理で、判定すればいいのではないでしょうか?
斜辺^2==x^2+y^2
になるため、敵と自機とのx距離差とy距離差から距離がわかるはずです。
それを自機フィールド+敵フィールドの値以内になればあたったと判定すればいいでしょう。

弾と自機なら、表示中の弾全てと自機との距離を計算する必要があります。

考え方はこちらに書いてあります。
http://dixq.net/g/#s11


181ポイント を手に入れた。



Name: Kirby  ..ぴよぴよ(222ポイント)   Date: 2008/04/13(日) 19:15   No:15525       
Title: 2Dゲームの作成について    
初めまして。
まだC言語暦は1週間もない初心者ですが、よろしくお願いします。
今、2Dゲームを作成中なのですが、どうしても左にキャラクターを移動できません。
このHPの運営者のC言語ゲーム解説ページの2D解説では、右方向のみの解説なので、
どうしたらいいのか分かりません。
私はマリオのような左右に移動するゲームを作成したいのです。
4方向の解説もあったので、ソースをいじって、左右にのみいけるようにしようとしましたが、
やはり失敗しました。
回答お願いします。

私が作成中のソースも載せておきます。
DXライブラリを使用しています。
ソフトは、Visual Studio 2005 Proです。


222ポイント を手に入れた。


Name: kazuoni  ..中級者(9,128ポイント)   Date: 2008/04/13(日) 20:19   No:15526     
Title: Re:2Dゲームの作成について    
初めての回答なんでどこまでヒントを出したらいいのか分からないですけどっ^^;

とりあえず

if( Key[ KEY_INPUT_LEFT ] == 1 ) //左ボタンが押されたら
ch.muki=0; //左向きフラグを立てる
if( Key[ KEY_INPUT_RIGHT] == 1 ) //右ボタンが押されたら
ch.muki=1; //右向きフラグを立てる
else //何のボタンも押されてなかったら
ch.walking_flag=0; //歩かないフラグを立てる

ここの記述がおかしくないですか?・・・ifとelseの関係がみたいな・・・^^;
このままだとLEFTキーが入力された場合、ch.mukiが0になるんですけど、その下のifでelseに入ってしまい、一向に左には動かないかと思われます。。


180ポイント を手に入れた。

Name: Kirby  ..ぴよぴよ(291ポイント)   Date: 2008/04/13(日) 21:04   No:15528     
Title: Re:2Dゲームの作成について    
回答ありがとうございます。
右向きフラグの部分のみを削除してビルドすると、左へ動きました。
ここまでは理解できましたが、左右に動かすにはソースのどこを修正すればいいのでしょうか?
ややこしくてすいません;


69ポイント を手に入れた。

Name: kazuoni  ..中級者(9,348ポイント)   Date: 2008/04/13(日) 21:14   No:15529     
Title: Re:2Dゲームの作成について    
FEFTキー、RIGHTキー、それ以外
この三つに分類すればいけます。

if〜
else if〜
else〜


うまく説明できないので
http://www9.plala.or.jp/sgwr-t/c/sec06-1.html

などを参考にしてください。


111ポイント を手に入れた。

Name: Kirby  ..ぴよぴよ(330ポイント)   Date: 2008/04/13(日) 21:57   No:15531 解決!     
Title: Re:2Dゲームの作成について    
無事、解決しました。親切に回答していただき、誠にありがとうございました^^


39ポイント を手に入れた。



Name: kazuoni  ..初心者(7,716ポイント)   Date: 2008/04/11(金) 16:37   No:15478       
Title: 入力キーのチェック    
お邪魔します。
題名が管理人さんが投稿したものににてしまいましたがっ^^;まずは下のコードを見てください。

void state(){
...

while(@){
...
switch(flag){
case 0:
...A  
break;
case 1:
...
break;
case 2:
...
break;

}
ScreenFlip();
}
...
return;
}

こんな単純なものなんですが。。やりたいことは、flagが1、2のときで、バックスペースが押されたらflag=0になり、case 0を実行し、case 0でバックスペースが押されたらwhileを抜けるというものにしたいんです。上のコードの@、Aに Key[ KEY_INPUT_BACK ]を書いてしまうと、case 2→case 0→脱出までが一瞬で行われてしまいます。どうしたらうまくいくでしょうか?なんだか管理人さんの上げたものにヒントがありそうな臭いがプンプンするんですが・・・^^;

よろしくお願いします。


250ポイント を手に入れた。


Name: 管理人 [URL]  ..伝説のハッカー(552,473ポイント)   Date: 2008/04/11(金) 17:03   No:15482     
Title: Re:入力キーのチェック    


私のたてた他トピでも紹介していますが、こちらをご覧下さい。
http://dixq.net/g/#40

GetHitKeyStateAll_2なる関数を実装してあります。
これは、どれ位キーが押されたかを判定する関数です。

キー情報が
0なら押されてない、
1なら今押された、
2なら押されてから2カウント、
3なら押されてから3カウント、
4なら押されてから4カウント、
・・・

となるわけです。今やりたいことは、「今押された」時に処理をしたいわけですよね。
・・ということは・・?

if(Key[KEY_INPUT_BACK]==1)
flag=○○;


266ポイント を手に入れた。

Name: kazuoni  ..初心者(7,978ポイント)   Date: 2008/04/11(金) 20:44   No:15487     
Title: Re:入力キーのチェック    
必死に考えました^^;

Keyがcharからintに変わっていたのですね^^;額に汗をかくぐらいにらめっこしてましたww

疑問はint GetHitKeyStateAll_2(){...}をどこに書くかなんですが・・・ヘッダーに書く場合どうしたら一番よいでしょうか?"DxLib.h"の中に入れられたらなぁなんて思っているのですが・・・やり方が全く分かりません。。


2倍のポイントを手に入れた! 262ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(553,983ポイント)   Date: 2008/04/11(金) 21:03   No:15488     
Title: Re:入力キーのチェック    
ご自分で実装された関数などは、別のヘッダファイルに入れたほうがいいと思いますよ。
というのも、もし、他のゲームを作ったり、作り直したりするとき、
DxLib.hと自分で実装した.hファイルをインクルードすればよく、
DXライブラリのバージョンアップなどにも、対応がしやすいです。


int GetHitKeyStateAll_2(int KeyStateBuf[]){
char GetHitKeyStateAll_Key[256];
GetHitKeyStateAll( GetHitKeyStateAll_Key );
for(int i=0;i<256;i++){
if(GetHitKeyStateAll_Key[i]==1) KeyStateBuf[i]++;
else KeyStateBuf[i]=0;
}
return 0;
}

 
これをDxLib2.hとでも、名前をつけてインクルードファイルがおいてあるフォルダに入れておけばいいと思います。
プログラムを書くときは

#include "DxLib.h"
#include "DxLib2.h"

と書いて下さい。
また、これはオーバーフローを考慮していない関数なので、きちんとライブラリ化するなら、
オーバーフローをしないように関数をつくった方がいいと思います。
具体的には

if(GetHitKeyStateAll_Key[i]==1) KeyStateBuf[i]++;

ここの加算はKeyStateBuf[i]+1がint型の扱える範囲内か、というif文を追加することです。


540ポイント を手に入れた。

Name: トウラ  ..ぴよぴよ(5ポイント)   Date: 2008/04/11(金) 21:30   No:15489     
Title: Re:入力キーのチェック    
はじめましてトウラと言います & はじめましてが横からですみません。
私も同じ(?)ところで躓いていたので、思わず書き込みです。

>>kazuoniさん
whileでbackspaceの入力状態をチェックしたあと
switchに入る前、あるいはcase 0とAの間に最初にもう一度GetHitKeyStateAll(key)を呼ぶとどうでしょう?

while内でチェックしてそのままswitchに入るので
switch内ではすでにkey[KEY_INPUT_BACK]が1になってるのが原因だと思います。
とりあえず私はこれで何とかなりました。
これが正しいやり方なのかは不明ですが・・・


もし、よろしくない場合はどなたかつっこんでください。


5ポイント を手に入れた。

Name: トウラ  ..ぴよぴよ(123ポイント)   Date: 2008/04/11(金) 23:31   No:15491     
Title: Re:入力キーのチェック    
あれ・・・もう一度試してきたら思ったように動作してなかった。
最初の1回だけうまくできたように見えてて、できたと勘違いしてたみたいです。

やっぱりどこかおかしかったのかな・・・
しゃしゃり出てきておいて申し訳ありません。


118ポイント を手に入れた。

Name: kazuoni  ..初心者(8,069ポイント)   Date: 2008/04/11(金) 23:47   No:15492     
Title: Re:入力キーのチェック    
>管理人さん
>

> int GetHitKeyStateAll_2(int KeyStateBuf[]){
> char GetHitKeyStateAll_Key[256];
> GetHitKeyStateAll( GetHitKeyStateAll_Key );
> for(int i=0;i<256;i++){
> if(GetHitKeyStateAll_Key[i]==1) KeyStateBuf[i]++;
> else KeyStateBuf[i]=0;
> }
> return 0;
> }
>

>  
> これをDxLib2.hとでも、名前をつけてインクルードファイルがおいてあるフォルダに入れておけばいいと思います。
> プログラムを書くときは
>
> #include "DxLib.h"
> #include "DxLib2.h"
>
> と書いて下さい。

普通に書いたらint GetHitKeyStateAll_2が重複に定義されてしまいました。こういう関数の定義ってヘッダーではどうかいたらよいのでしょうか?
ちなみに自分はすべてのファイルが読み込むGV.hにDxLib2.hをインクルードしたのですが。。


> if(GetHitKeyStateAll_Key[i]==1) KeyStateBuf[i]++;
>
> ここの加算はKeyStateBuf[i]+1がint型の扱える範囲内か、というif文を追加することです。

これを書き、戻り値でエラーが返ってきたら終了・・・みたいな感じですか?


91ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(554,206ポイント)   Date: 2008/04/12(土) 03:07   No:15496     
Title: Re:入力キーのチェック    
>トウラさん

40節にサンプルを置いていますけど、それをみてもよくわからなかったでしょうか?
もしご覧になっていない場合はどうぞ。

>kazuoniさん

ヘッダに書いたのでしたら、Cファイルの方の記述は消しました?
GetHitKeyStateAll_2の関数はCファイルから消してください。

>これを書き、戻り値でエラーが返ってきたら終了・・・みたいな感じですか?

そういうことですね。
if文の中にはいらず、elseにはいったらreturn -1;しましょう。


232ポイント を手に入れた。

Name: トウラ  ..ぴよぴよ(424ポイント)   Date: 2008/04/12(土) 16:32   No:15503     
Title: Re:入力キーのチェック    
>>管理人さん
40節のコードはつまり
「33節のものを全てのキーに対応させ、さらにどれだけの間押されているのかも計算するように拡張した」
という風な理解の仕方でいいのでしょうか?

また40節のコードを利用してみましたが、やはりkazuoniさんと同じように処理が一瞬で行われてしまいます。
私の場合は、

if( ( Key[KEY_INPUT_SPACE]==1 && flag==0 ) || flag>0 ){
if( flag==0 )
flag=1;
if( flag==1 ){
画像描画
if( Key[KEY_INPUT_SPACE]==1 && flag==1 ) ・・・@
flag=2;
}
if( flag==2 ){
画像描画
if( Key[KEY_INPUT_SPACE]==1 && flag==2 ) ・・・A
flag=0;
}
}

という感じです。
@をKey[KEY_INPUT_RETURN]==1、AをKey[KEY_INPUT_BACK]==1
など、チェックするキーを分けると私の考える動作をしてくれます。
書き方自体がいけないでしょうか?


301ポイント を手に入れた。

Name: トウラ  ..ぴよぴよ(616ポイント)   Date: 2008/04/12(土) 16:37   No:15504     
Title: Re:入力キーのチェック    
すみません。忘れてました・・・


if( ( Key[KEY_INPUT_SPACE]==1 && flag==0 ) || flag>0 ){
if( flag==0 )
flag=1;
if( flag==1 ){
画像描画
if( Key[KEY_INPUT_SPACE]==1 && flag==1 ) ・・・@
flag=2;
}
if( flag==2 ){
画像描画
if( Key[KEY_INPUT_SPACE]==1 && flag==2 ) ・・・A
flag=0;
}
}


こんな感じです。


192ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(80,975ポイント)   Date: 2008/04/12(土) 16:52   No:15505     
Title: Re:入力キーのチェック    
面白そうなので、クラスにしてみました。自前のミリ秒タイマーと組み合わせて、押した時間がミリ秒単位で取得できます。デバッグしていないので、バグがあった場合は申告してもらうか、自己修正で対応をお願いします(ぉぃぉぃ)

クラス名:DxLibExtra

以下、publicメンバ関数のリファレンスです。

BOOL GetHitKeyStateAllEx()
戻り値:関数の成否です。TRUEは成功、FALSEは失敗です。基本的にはGetHitKeyStateAll関数と同じように使用します。

BOOL GetKeyState(INT iVirtKey)
戻り値:指定されたキーの押下状態を取得します。押されている場合はTRUE、そうでない場合はFALSEです。引数にありえない数値が指定された場合もFALSEになります。これも基本的には元祖の同名関数と同じように使用しますが、戻り値が違う部分だけ注意して下さい。

ULONGLONG GetKeyPushTime(INT iVirtKey)
戻り値:指定されたキーの押下状態の継続時間を取得します。GetHitKeyStateAllEx関数で押されたと判定された瞬間から現在までの時間をミリ秒単位で返します。指定されたキーが押されていない、もしくは引数にありえない数値が指定された場合は0が返ります。※『64ビット非負整数なので大丈夫だろう♪』という事で、とりあえずオーバーフローは考慮しておりません(苦笑)


312ポイント を手に入れた。

Name: kazuoni  ..初心者(8,641ポイント)   Date: 2008/04/12(土) 22:27   No:15507     
Title: Re:入力キーのチェック    
> ヘッダに書いたのでしたら、Cファイルの方の記述は消しました?
> GetHitKeyStateAll_2の関数はCファイルから消してください。

消してます。

すべてが読み込むヘッダーをGv.hとして、その冒頭に#include "DxLib2.hをし、DxLib2.hの中身は、

int GetHitKeyStateAll_2(int KeyStateBuf[]){
char GetHitKeyStateAll_Key[256];
GetHitKeyStateAll( GetHitKeyStateAll_Key );
for(int i=0;i<256;i++){
if(GetHitKeyStateAll_Key[i]==1) KeyStateBuf[i]++;
else KeyStateBuf[i]=0;
}
return 0;
}

です。DxLib2.hはGv.hと同じ場所にあります。(visual c++ 2008でいう、ヘッダーファイルにあります。Gv.hもここです)


現状はこんな感じなんですが・・・。


2倍のポイントを手に入れた! 572ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(554,474ポイント)   Date: 2008/04/12(土) 23:47   No:15508     
Title: Re:入力キーのチェック    
> トウラさん

if文はelseでつなげないと期待する動作をしないことが多いです。
今の場合、どういう順序でプログラムが流れているかみてみましょう。
また、flag==1でイフ文に入ってるので、その中でさらにflag==1を判定する必要はないです。
2も同様。
そして、
flag=2をしてif文を出た瞬間、次のif文に入っているので、連続してしまうのです。
if(){
}
else if(){
}
という風につなげればいいです。



175ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(554,537ポイント)   Date: 2008/04/12(土) 23:49   No:15509     
Title: Re:入力キーのチェック    
>kazuoniさん

DxLib2.hの中で最初に

#include "DxLib.h"

は書いていますか?これを書くとDxLib.hを他でインクルードする必要はありません。


63ポイント を手に入れた。

Name: Justy  ..ハッカー(187,930ポイント)   Date: 2008/04/13(日) 00:00   No:15510     
Title: Re:入力キーのチェック    
#kazuoniさん
>すべてが読み込むヘッダーをGv.hとして、その冒頭に#include "DxLib2.hをし、DxLib2.hの中身は
> 〜
 これはマズイです。ヘッダファイルに関数の実体を書いて、それをあちらこちらでインクルードすると
その全部で定義されるのでリンク時に多重定義になります。

 ヘッダファイルである "DxLib2.h"には関数のプロトタイプ宣言を書いて、
対になる DxLib2.cppを作ってそちらに実体であるその関数の中身を書いて下さい。


 これが面倒なら、"DxLib2.h"の
int GetHitKeyStateAll_2(int KeyStateBuf[]){
 の部分を
inline int GetHitKeyStateAll_2(int KeyStateBuf[]){
 としても構いません。
 関数がインライン化されるので、リンク時の多重定義にはならなくなります。


240ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(554,554ポイント)   Date: 2008/04/13(日) 01:15   No:15511     
Title: Re:入力キーのチェック    
すみません、ボケてました;
#include"DxLib.h"を書くべきは、cppファイル内です。


17ポイント を手に入れた。

Name: kazuoni  ..初心者(8,735ポイント)   Date: 2008/04/13(日) 01:22   No:15513     
Title: Re:入力キーのチェック    
管理人さん、Justyさんご回答ありがとうございます!

とりあえずはJustyさんの前者のやり方でできました。
DxLib2.h DxLib2.cpp両方で、GetHitKeyStateAll_2(int KeyStateBuf[])という風にかいて、一方の(int KeyStateBuf[])のカッコの中身省略したい(統一したい)なぁ〜なんて考えてたんですけど、(まぁこれでいいんですけどねっ^^;)GetHitKeyStateAll_2()ってしてしまうと(void)と認識されてしまって、戻り値っておかしくなってしまいますかね?
メイン文で
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE] && !GetHitKeyStateAll_2(Key_n))

をかいているのですが・・・

これで解決なんですけど、Justyさんのおっしゃっていた後者のほうがどうもよく分かりません。。ググってもいまいち分からな
かったのですが・・・関数のインライン化の意味は何なんでしょうか?あと何がしたいときに使用するものなのでしょうか?



94ポイント を手に入れた。

Name: Justy  ..ハッカー(188,451ポイント)   Date: 2008/04/13(日) 12:12   No:15516     
Title: Re:入力キーのチェック    
>GetHitKeyStateAll_2()ってしてしまうと(void)と認識されてしまって、戻り値っておかしくなってしまいますかね?

 引数と戻り値の指定を省略したプロトタイプ宣言をする、ってことですか?
 コンパイル時かリンク時に怒られると思いますよ。万が一動いても正常な動作は
期待できないと思います。

 引数の変数名くらいは省力しても構いませんが、あとは同じにしておいて下さい。



>関数のインライン化の意味は何なんでしょうか?
>あと何がしたいときに使用するものなのでしょうか?

 一言で言えば高速化が目的です。
 
 通常関数呼び出しは少し時間がかかるのですが、インライン関数は幾つかのデメリットと引き替えに
その呼び出し時間を極力減らすようコンパイラが努力してくれます。

 ただ、努力してくれるだけで実際にしてくれるとは限りませんし、実はインライン指定しなくても
もう既に努力済みである可能性もありますが。


インライン関数は普通の関数とは異なり、各モジュール(cpp)単位で“定義”が必要なので、
大抵の場合関数の中身はヘッダに書いておくのですが、リンク時に多重定義に
ならないようにコンパイラ・リンカが調整してくれます。


 細かいところは
 
インライン関数 - Wikipedia
http://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%B3%E3%83%A9%E3%82%A4%E3%83%B3%E9%96%A2%E6%95%B0

インライン展開 - Wikipedia
http://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%B3%E3%83%A9%E3%82%A4%E3%83%B3%E5%B1%95%E9%96%8B#.E6.AC.A0.E7.82.B9

インライン関数
http://wisdom.sakura.ne.jp/programming/cpp/cpp14.html

 とかを読んでみて下さい。


521ポイント を手に入れた。

Name: kazuoni  ..初心者(8,786ポイント)   Date: 2008/04/13(日) 13:49   No:15517 解決!     
Title: Re:入力キーのチェック    
Justyさんお返事ありがとうございます!

もう少し自分で煮詰めてみたいと思います^^ご丁寧な解説ありがとうございました!

またよろしくお願いします。


51ポイント を手に入れた。



Name: 湖乃夜路  ..ぴよぴよ(141ポイント)   Date: 2008/04/10(木) 17:03   No:15468       
Title: ウイルスバスター2008から警告    
初めまして。イズミノヨミチと名乗らせてもらっています。
このサイトの入門編0番、導入で躓いてしまった愚か者です。
サンプルプログラム実行用フォルダを開いてVC++起動まではできるのですが、ウインドウを表示させて画像を出そうとすると、ウイルスバスター2008が不審な変更を拒否しました、と警告、そのまま終了してしまいます。
かなり初歩的な質問と思いますが、どなたか回答をお願いします。


141ポイント を手に入れた。


Name: 管理人 [URL]  ..伝説のハッカー(552,207ポイント)   Date: 2008/04/11(金) 16:58   No:15481     
Title: Re:ウイルスバスター2008から警告    
そのウィルスバスターの操作を存じないのですが、
実行を許す実行ファイル名にDxLib.exeを追加すればいいのではないでしょうか?


47ポイント を手に入れた。

Name: 湖乃夜路  ..ぴよぴよ(79ポイント)   Date: 2008/04/12(土) 15:09   No:15501 解決!     
Title: Re:ウイルスバスター2008から警告    
画面にキャラクターを表示することはできました。
相変わらず警告表示はとまりませんが……
回答、ありがとうございました。


62ポイント を落としてしまった。

Name: 管理人 [URL]  ..伝説のハッカー(554,299ポイント)   Date: 2008/04/12(土) 16:19   No:15502     
Title: Re:ウイルスバスター2008から警告    
ウィルスバスターを起動して、設定レベルを変更したり、実行許可したりしてみたらいいのではないでしょうか?


40ポイント を手に入れた。

Name: Mist  ..かけだし(1,310ポイント)   Date: 2008/04/12(土) 16:53   No:15506     
Title: Re:ウイルスバスター2008から警告    
http://www.fenrir.co.jp/blog/2008/02/2008_sleipnir.html

このページに記述されている方法で実行したいexeを登録すれば警告は表示されないのではないですか?


66ポイント を手に入れた。

Name: 湖乃夜路  ..ぴよぴよ(152ポイント)   Date: 2008/04/13(日) 01:36   No:15514 解決!     
Title: Re:ウイルスバスター2008から警告    
解決しました。
ウイルスバスターの例外設定をしているつもりだったのですが、間違ってtest.exeを登録していました。
Mistさん管理人さん、そのほかの方お騒がせしてすいません。


73ポイント を手に入れた。



Name: 管理人 [URL]  ..伝説のハッカー(552,023ポイント)   Date: 2008/04/11(金) 04:08   No:15473       
Title: ゲームプログラミングの館において    
「今の瞬間入力があった」ということを苦労して判定していらっしゃる方も多いのではないでしょうか。

DXライブラリにおいて、キーの入力は
「押しているか」「押していないか」しか判定できず、「どれ位押したか」は判定出来ません。
よって、どれ位押したかを判定する為の関数を作ってみました。

もしよければお使い下さい。
押している時間もカウントされるので、色々と幅広く利用できるのではないかと思います。

http://dixq.net/g/#40


147ポイント を手に入れた。


Name: やそ  ..プログラマー(39,754ポイント)   Date: 2008/04/11(金) 13:35   No:15475     
Title: Re:ゲームプログラミングの館において    
を、開発ご苦労様です(^-^)

その瞬間に入力されたかどうかのチェックって直前の状態を必要とするので以外にアルゴリズムが気づきにくいのかな?

でも確かに需要のありそうなユーティリティですね。
検証というほどではないですが、ずーーーーーーっと押しっぱなしだった場合どのくらいの時間でオーバーフローします?
良くオンラインゲームで寝落ちする人なので、そういうアホなことが気になったりします(笑)

FPSで処理を管理していて、60FPSごとに1回通るループでチェックするならint型が4バイトの処理系なら問題ナシでしょうけどね。
FPS管理をしない、CPU性能に依る場合、CPU性能が高いほどオーバフローの危険性が増しますね。
ふつうにこのサイトでお勉強している型にはFPS管理しない天邪鬼な人なんていないか(^^ゞ


2倍のポイントを手に入れた! 388ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(552,160ポイント)   Date: 2008/04/11(金) 16:57   No:15480     
Title: Re:ゲームプログラミングの館において    
そうですね〜。確かに、リフレッシュに同期しないと、すごい早さで加算されてしまう可能性も・・。
60FPSならオーバーフローするまでに、1年位かかると思うので大丈夫だと思ったんですが、

if(押されていたら)
 if(値+1がint型の扱える範囲内なら)
   加算;

とするべきでしょうかね?
別にライブラリでもなければ、初心者用HPなので、厳密さよりわかりやすさ重視の方がいいとはおもいますが^^;


137ポイント を手に入れた。

Name: Justy  ..ハッカー(187,446ポイント)   Date: 2008/04/11(金) 21:59   No:15490     
Title: Re:ゲームプログラミングの館において    
 えーと、気になったのですが、仕様として以下の文言を追加しておく必要はないでしょうか?

・ 引数 KeyStateBufには毎回同じバッファを指定すること
・ 最初に使うときは KeyStateBufを全て0初期化しておくこと。

 この2点が守られないと期待通りの動作をしないと思います。


>リフレッシュに同期しないと、すごい早さで加算されてしまう可能性も・・
 本家と同じように、最後に呼ばれた時間を調べて・・・、ということをすれば
防げますが、複雑になりそうですね。

 範囲チェックも本当はした方がいいのでしょうが、limits.h/climitsのインクルードを
しないと intの最大値がわからない、というのも初心者向けではないでしょうし・・・。


197ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(553,943ポイント)   Date: 2008/04/12(土) 01:46   No:15493     
Title: Re:ゲームプログラミングの館において    
Justyさん、アドバイスありがとうございます。
そうですね、その注意は必要ですね。

int型の最大値はsizeof(int)から計算出来ないのでしょうか?


40ポイント を落としてしまった。

Name: Justy  ..ハッカー(187,556ポイント)   Date: 2008/04/12(土) 02:33   No:15494     
Title: Re:ゲームプログラミングの館において    
>int型の最大値はsizeof(int)から計算出来ないのでしょうか?
 あー、現実的には可能ですね。

 この関数自体が DXライブラリに依存している関係上、
当然環境は x86+Windows、しかもコンパイラまで限られるので、
sizeof(int)の結果による決め打ちはできそうです。

 ただ、言語的には1バイトが 8bitとは限らないですし、sizeof(int)の中に
詰め物ビットがあるかもしれないので、難しいです。


2倍のポイントを手に入れた! 110ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(553,974ポイント)   Date: 2008/04/12(土) 03:04   No:15495     
Title: Re:ゲームプログラミングの館において    
>言語的には1バイトが 8bitとは限らないですし

え、そうなんですか?!
それはコンパイラに依存するのでしょうか?


31ポイント を手に入れた。

Name: 木霊  ..初心者(7,766ポイント)   Date: 2008/04/12(土) 03:17   No:15497     
Title: Re:ゲームプログラミングの館において    
 以前、たかぎさんが2、3回こちらの掲示板でもレスされていましたよ。

確か

「C言語の規格でchar型が1byteとは決まっているが、char型が8bitとは決まっていない。
   現実にchar型が9bitのコンパイラも存在する」

 だったような・・・

 うろ覚えで申し訳ないですが、コンパイラ依存みたいです。


123ポイント を手に入れた。

Name: Justy  ..ハッカー(187,690ポイント)   Date: 2008/04/12(土) 03:26   No:15498     
Title: Re:ゲームプログラミングの館において    
>それはコンパイラに依存するのでしょうか?
 コンパイラというか対象のCPU、メモリ、コンパイラなど全てを含めた環境に
依存してます。
 その為に CHAR_BITという定数があるわけで。

 実際9というのは実在しますし、ひょっとしたら自由にビット数を
変更できるのとかあるかもしれません。
(ソフトウェアで仮想的に作られた CPUならありそう)


134ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(554,259ポイント)   Date: 2008/04/12(土) 05:14   No:15499     
Title: Re:ゲームプログラミングの館において    
>木霊さん
>Justyさん

なるほど、そうだったのですか、勉強になりました、ありがとうございますm(_ _)m


53ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..比類無きプログラマー(68,158ポイント)   Date: 2008/04/12(土) 13:24   No:15500     
Title: Re:ゲームプログラミングの館において    
>管理人さん

static変数を使ったほうが、より直感的な動作になると思います。
実装例としては、こんな感じです。

int GetHitKeyStateAll_3(int KeyStateBuf[]){
char GetHitKeyStateAll_Key[256];
static int NowTotalKeyStateBuf[256];
GetHitKeyStateAll( GetHitKeyStateAll_Key );
for(int i=0;i<256;i++){
if(GetHitKeyStateAll_Key[i]==1) NowTotalKeyStateBuf[i]++;
else NowTotalKeyStateBuf[i]=0;
}
memcpy(KeyStateBuf,NowTotalKeyStateBuf,sizeof(NowTotalKeyStateBuf));
return 0;
}

こうすれば毎回違うバッファを指定したところで、誤動作せずにしっかりと入れてくれます。引数バッファを初期化をする必要性すらありません。


339ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(554,571ポイント)   Date: 2008/04/13(日) 01:19   No:15512     
Title: Re:ゲームプログラミングの館において    
そうですね。
こちらのほうがよりよいですね、ありがとうございます。


17ポイント を手に入れた。



Name: piyo  ..ぴよぴよ(604ポイント)   Date: 2008/04/08(火) 23:47   No:15452       
Title: while文とキー入力    
先日初投稿させて頂きました。

キー入力のところを読んでいての質問なのですが、

例えば、
while( CheckHitKey( KEY_INPUT_ESCAPE) == 0 ){
if(ProcessMessage() == -1 ) break ; //@

if(CheckHitKey( KEY_INPUT_Z)==1) x=x+4; //A
if(CheckHitKey( KEY_INPUT_X)==1) y=y+4;  //B


}

等という文の時、
while文ですので、@→A→Bという判定を繰り返していると考えて良いのでしょうか?
そう考えると、0.000…1秒差で、Aの判定をしている時に、Xキーを押すとすると、Xキーを押してない事になりますか?
この例だと、少ないのでそう誤差はありそうにないですが、
相当長い文になった時、一番上のifのCheckHitKey関数と、一番下のそれとでは、
判定されない時が出てきそうに思えます。
どうなのでしょうか?


ps:解説ページの事で要望なのですが、決まっている言葉(ifや、while)と、関数や変数等の、適当な名前を付けられるものとの区別を、色をつける事等でして欲しいです。
宣言をきちんと見ておけばよい話なのですが、「Buf」等の、決まり言葉っぽいものが出てくると
少し混乱してしまいます。


310ポイント を手に入れた。


Name: Justy  ..ハッカー(187,249ポイント)   Date: 2008/04/09(水) 02:11   No:15457     
Title: Re:while文とキー入力    
>while文ですので、1→2→3という判定を繰り返していると考えて良いのでしょうか?
 Y
 但し、1の判定が真の場合 breakしてしまうので、2以降は判定されません。



>2の判定をしている時に、Xキーを押すとすると、Xキーを押してない事になりますか?
 「Xキーが押されていないことになる」というのが同一フレームでの2や3の判定で、
ということでしたらあり得ます。

 キーボードの押下チェックはハード・OSレベル的にこれほど短時間での検出はしていませんし、
そもそも DXライブラリの仕様では前回の取得からの経過時間が最大約 1ms未満の場合、
前回と同じ情報を元に押下判定をするようになっていますので、2の段階で押しても
それが3で反映されるとは限りません。
(2と3で1ms以上の時間が空けば別ですが)


>判定されない時が出てきそうに思えます]
 if文を通過さえすれば判定しないことはないですが、判定の結果が食い違うことはあり得ますね。
 しかし、通常 CheckHitKey()を複数回呼ぶようなことはあまりしません。
 もしそのような使い方をするのであれば、GetHitKeyStateAll()の使用を検討するべきではないかと。


323ポイント を手に入れた。

Name: piyo  ..ぴよぴよ(676ポイント)   Date: 2008/04/11(金) 20:24   No:15486     
Title: Re:while文とキー入力    
回答ありがとうございます。
分かりました。
GetHitKeyStateAll()を使うようにすれば、
それほど気にしなくて良いということですね。

ありがとうございました。



72ポイント を手に入れた。



Name: t  ..ぴよぴよ(806ポイント)   Date: 2008/04/10(木) 08:18   No:15465       
Title: 初歩的な事ですいませんが教えてください。    
自分で考えられるだけ考えたんですがどうしても分からないので教えてください。

SetDrawScreenを使って描画先グラフィック領域を裏の画面にする。

ClearDrawScreenを使って画面に描かれたものを消去する。

画像を裏の画面に描画する。

ScreenFlipを使って表画面に描画する。

という事をした時にどうしても画面に黒い線がチラつくのですが何がいけないのでしょうか?

サンプルプログラムを見て相違点を探したのですが結局分かりませんでした。

初歩的な事ですみませんが教えてください。

#include "DxLib.h"

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
int haikei;

if( DxLib_Init() == -1 )return -1;

SetDrawScreen(DX_SCREEN_BACK);
ChangeWindowMode(TRUE);

haikei = LoadGraph("仮背景.bmp");

while(ProcessMessage() == 0){
ClearDrawScreen();
DrawGraph(0, 0, haikei, TRUE);
ScreenFlip();
if(CheckHitKey(KEY_INPUT_ESCAPE)==1)break;
}

DxLib_End();

return(0);
}


523ポイント を手に入れた。


Name: tkmakwins15 [URL]  ..比類無きプログラマー(67,819ポイント)   Date: 2008/04/10(木) 17:24   No:15470     
Title: Re:初歩的な事ですいませんが教えてください。    
SetDrawScreen(DX_SCREEN_BACK);
を、ループに入る前に一回呼んでみてください。


31ポイント を手に入れた。

Name: t  ..ぴよぴよ(826ポイント)   Date: 2008/04/10(木) 20:03   No:15472 解決!     
Title: Re:初歩的な事ですいませんが教えてください。    
ありがとうございます。
解決しました。


20ポイント を手に入れた。



Name: 電気さぼてん  ..ぴよぴよ(239ポイント)   Date: 2008/04/07(月) 02:14   No:15418       
Title: シューティングゲームを勉強しているのですが…    
初めまして、電気さぼてんと言う者です、よろしくおねがいします。
今年の1月にプログラミングをやろうと思って始めた初心者です。

管理人さんのシューティングゲーム講座を見て、勉強させていただいています。
で、敵の弾が自機に向かってくるところを勉強させていただいた時点で、
「ホーミングミサイルとかほしいな・・・」
とか思って、色々やったのですが、どうにもうまくいきません。
何か上手く作る方法などございませんか?
何か、見本などがありますとうれしいです。

頼りっきりな質問で申し訳ありません。
でも、どうしてもつけてみたくて・・・。


239ポイント を手に入れた。


Name: 管理人 [URL]  ..伝説のハッカー(550,550ポイント)   Date: 2008/04/07(月) 04:25   No:15419     
Title: Re:シューティングゲームを勉強しているのですが…    
龍神録のミドリの弾のような単純なホーミングでいいんでしょうか?
それならピタゴラスの定理で自機と敵との距離を全て求め、一番近い敵にターゲットを定めます。
そして、その敵との角度をatan2関数を使って求め、そちらに発射します。
発射後は常に、弾と敵との角度をatan2で変更すれば、自動的に当たりますよね。
どうでしょうか?


63ポイント を手に入れた。

Name: 電気さぼてん  ..ぴよぴよ(172ポイント)   Date: 2008/04/07(月) 15:19   No:15424     
Title: Re:シューティングゲームを勉強しているのですが…    
お早い返答ありがとうございます。

敵が撃ってくる弾にそのようなホーミングをつける場合も、同じように考えてよろしいのですか?


67ポイント を落としてしまった。

Name: やそ  ..プログラマー(38,084ポイント)   Date: 2008/04/07(月) 16:11   No:15425     
Title: Re:シューティングゲームを勉強しているのですが…    
>敵が撃ってくる弾にそのようなホーミングをつける場合も、同じように考えてよろしいのですか?

いいんじゃないかな?

あとはどのようなホーミング軌道をとるか(とらせたいか)によるでしょう。
管理人さんの説明されているホーミングの軌道のイメージは掴んでいるでしょうか?
その辺のイメージがずれていると堂々巡りになります^^;

サンプルをよく読んで、というか実際に自分なりに組んでテストしてみると良いでしょう。
自分のイメージした動きと組んでみた動き方とサンプルの動きが同じかどうか、
試してみれば一目瞭然。ですよね?



252ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(550,863ポイント)   Date: 2008/04/07(月) 19:33   No:15427     
Title: Re:シューティングゲームを勉強しているのですが…    
自機が敵にうつホーミングは「絶対当たる」という仕様でいいですが、敵が自機にうつホーミングは「逃げられる」仕様じゃないとダメなので、同じではダメかと思いますが、まぁ考え方としては似ていると思います。
いつまでも追跡してたんじゃ、逃げ場がなくなりますから、何カウントまで追跡するとか、角度変更は徐々にしかしないとか、そういう仕様を実装しないとホーミングっぽくならないと思います。
特に常にもろ自分へと同じ角度に向いているとホーミングっぽさは低くなってしまうと思います。

自機狙い弾とホーミングは違いますけど、後者で間違いないですよね?

自機狙い弾なら、うつ前に敵と自機との座標からatan2を使って求めて直線発射すればいいだけです。
どっちにしてもatan2という関数を使いこなせば結構簡単に出来ると思います。


313ポイント を手に入れた。

Name: 電気さぼてん  ..ぴよぴよ(238ポイント)   Date: 2008/04/10(木) 10:53   No:15466 解決!     
Title: Re:シューティングゲームを勉強しているのですが…    
返事が送れてもうしわけありません。

なんとかできそうです!
ありがとうございました。


2倍のポイントを手に入れた! 66ポイント を手に入れた。



Name: CLP  ..かけだし(1,938ポイント)   Date: 2008/04/09(水) 17:50   No:15458       
Title: 初期画面が表示されません…    
はじめまして…
今RPG系のゲームをこのサイト様を参考に作っているのですが…
最初にフェードインフェードアウトを使って会社名を表示した後(自分の仮名)
初期画面が表示するようにしたのですが…表示されません。
色々試したのですがどうしてもなりません。
過去ログもすべてみましたが同じ様なのがありませんでした。
main.cpp内は以下のようになっております。
#include "test.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
ChangeWindowMode( TRUE ) ; //ウィンドウモードに変更
if( DxLib_Init() == -1 ) return -1; // DXライブラリ初期化処理 エラーが起きたら終了
feed();
startgamen();
}
そして初期画面用に作ったcppは以下になります。
大体ここのサイト様のコピペですが…
syokigamen.cpp内
#include "test.h"

void feed(){
int c=0,l=1;

SetDrawScreen( DX_SCREEN_BACK ) ; // 描画先を裏画面に設定

while( c!=858 ){
ClearDrawScreen(); // 裏画面のデータを全て削除

if(c>=0 && c<256) //cが0~256の時
SetDrawBright( c , c , c ); //段々あかるく(c= 0->255)
if(c>=256 && c<600) //cが256~400の時
SetDrawBright( 255 , 255 , 255 ); //通常の明るさ
if(c>=600 && c<600+256) //cが400~400+256の時
SetDrawBright( 255-(c-600) , 255-(c-600) , 255-(c-600) );//段々暗く(c= 255->0)
LoadGraphScreen( 0 , 0 , "HatsuneMiku146.bmp" , TRUE) ; //画面全体に描画

c+=2; //cをカウントアップ
ScreenFlip() ; // 裏画面データを表画面へ反映
if( ProcessMessage() == -1 ) break ; //エラーが起きたら終了
}
}

void startgamen(){
int White , y=100; //y座標の宣言
int DownOshita=0,NewDown=0,OldDown=0,DownPusingCounter=0;//各種フラグの宣言
char KeyBuf[ 256 ] ; //キー入力状態を格納する変数
White = GetColor( 255 , 255 , 255 ) ;
SetDrawScreen( DX_SCREEN_BACK ) ; // 描画先を裏画面に設定
while( 1 ){
ClearDrawScreen(); // 裏画面のデータを全て削除
GetHitKeyStateAll( KeyBuf ) ; // すべてのキーの状態を得る
if( KeyBuf[ KEY_INPUT_ESCAPE ] == 1 ) break ; // Escapeが押されたらブレイク

char_disp(White,y); // 文字を描画

if( KeyBuf[ KEY_INPUT_DOWN ] == 1 ) // 下キーが押されたら
NewDown=1; // 今押されている状態に
else // 押されていなかったら
NewDown=0; // 今押されていない状態に

if( OldDown==0 && NewDown==1 ) // 前回押されてなく、今回押されていたら
DownOshita=1; // たった今押された状態に
else // それ以外なら
DownOshita=0; // たったいま押されていない状態に

if( OldDown==1 && NewDown==1 ) // 前回も押され、今回も押されていたら
DownPusingCounter++; // 押しっぱなしカウンターを増加
else
DownPusingCounter=0;

if( DownOshita==1 || DownPusingCounter>30){ // たった今押したか、30カウンター以上押しっぱなしなら
if(DownPusingCounter>30) // 30カウンター以上押しっぱなしならカウンターを27へ
DownPusingCounter=27; // オートの場合4回に1回下に下がる。
y+=20;
if(y==260) // y座標が260なら(選択が一番下なら)
y=100; // 選択座標を一番上に
}
OldDown=NewDown; // 新しい入力情報を古い入力情報へ

if( ProcessMessage() == -1 ) break ; //エラーが起きたら終了
ScreenFlip() ; // 裏画面データを表画面へ反映
}
}

void char_disp(int White,int y){
DrawString( 150 , y , "■" , White );
DrawString( 170 , 100 , "NEW GAME" , White );
DrawString( 170 , 120 , "CONTINUE1" , White );
DrawString( 170 , 140 , "CONTINUE2" , White );
DrawString( 170 , 160 , "CONTINUE3" , White );
DrawString( 170 , 180 , "CONTINUE4" , White );
DrawString( 170 , 200 , "CONTINUE5" , White );
DrawString( 170 , 220 , "CONTINUE6" , White );
DrawString( 170 , 240 , "LOG OUT" , White );
}

どうかよろしくお願いします。


1,938ポイント を手に入れた。


Name: やそ  ..プログラマー(39,320ポイント)   Date: 2008/04/09(水) 19:32   No:15460     
Title: Re:初期画面が表示されません…    
ふーん。
で、結局質問は何なのでしょう?質問と思われる文章が見当たりませぬ。
まあ、初期画面が表示されないと愚痴をこぼされているので、何が原因なのか見て欲しいと言うことなのでしょうが・・・。

と、最近黒いやそです(笑)

最初のステップのフェードインフェードアウト処理(会社名の表示部分?)は正常に表示されていましたか?
真っ暗
 ↓
だんだん明るく
 ↓
明るさMAX
 ↓
だんだん暗く
 ↓
真っ暗

次に初期画面へ
ESCAPEが押されていなければ文字表示

という流だと思います。

ちょっと思ったのは、フェードアウト終了後、画面の明るさ設定値はどのような状態になっているのでしょうか?
初期画面表示処理ルーチンで、表示前に一度明るさを設定しなおしておくことをオススメします。


307ポイント を手に入れた。

Name: 管理人  ..伝説のハッカー(551,876ポイント)   Date: 2008/04/09(水) 19:35   No:15461     
Title: Re:初期画面が表示されません…    
test.hはDxLib.hが含まれていると思っていいのですね?

まず、画面消去や裏画面反映関数があちこちに書いてあるので、読みにくいプログラムになってしまっています。
後からの管理もしにくくなってしまうでしょう。
なので、これらの関数はメイン関数に一度だけ書いてください。
フラグを使って処理を分岐させるのが適切でしょう。

http://dixq.net/g/#34

こちらに例がありますので、参考にしてください。
これらは更に、計算部、登録部、描画部などにわけていくのがいいと思います。
今後のことを考えて、まず、キレイに整理してみることをおススメします。


257ポイント を手に入れた。

Name: CLP  ..かけだし(1,990ポイント)   Date: 2008/04/09(水) 23:24   No:15463     
Title: Re:初期画面が表示されません…    
ありがとうございます。
やそさんの言ったように画面の明るさを設定しなおしたらなりました!
全然気づきませんでした…ありがとうございます。
又これからも質問することがあるかと思いますがよろしくお願いします。
キレイに整理は…がんばります!


52ポイント を手に入れた。



Name: 水孤  ..ぴよぴよ(571ポイント)   Date: 2008/04/08(火) 21:44   No:15448       
Title: シューティングでの敵の同時出現    
シューティングゲームの館では、敵の出現するタイミングをcounterの値を元にswitch文で制御していますが
その方法で、敵を全く同じタイミングで出現させるにはどうしたら良いでしょうか?

1日考えてあれこれ試してみましたが、どうもうまくいきません。
ヒントでもいいので誰か教えてくれるとうれしいです。


129ポイント を手に入れた。


Name: tny  ..かけだし(2,115ポイント)   Date: 2008/04/08(火) 22:43   No:15450     
Title: Re:シューティングでの敵の同時出現    
複数の敵が同じcounterの時期に出現する、ということですよね。
STG館の12章にある関数EnemyCalc()を使ってらっしゃるとすれば、

void EnemyCalc(){
int i;

switch(counter){
case 100:
case 150:
case 200:
case 250:
// 一体目の敵出現
for(i=0;i<100;i++)
if(enemy[i].flag==0)
break;
enemy[i].flag=1; //出現フラグを立てる
enemy[i].counter=0;//出現して何カウント目か測るカウンター初期化
enemy[i].pattern=1; //どういう軌道を描くか
enemy[i].size=0.5f;//敵の大きさ
enemy[i].x=100.0; //xの初期座標
enemy[i].y=-10.0; //yの初期座標

// 二体目の敵出現
for(i=0;i<100;i++)
if(enemy[i].flag==0)
break;
enemy[i].flag=1;
enemy[i].counter=0;
enemy[i].pattern=1;
enemy[i].size=0.5f;
enemy[i].x=200.0; // ここだけ、同じ出現位置で出すとマズいでしょうから、勝手に200にしました
enemy[i].y=-10.0;
break;
default:
break;
}
}

このようにすると、上手くいくと思います。


更に突っ込んでしまいますけど、

for(i=0;i<100;i++)
if(enemy[i].flag==0)
break;
enemy[i].flag=1;
enemy[i].counter=0;
enemy[i].pattern=1;
enemy[i].size=0.5f;
enemy[i].x=200.0; // ここだけ、同じ出現位置で出すとマズいでしょうから、勝手に200にしました
enemy[i].y=-10.0;

という部分のうち、for文とflagとcounterのところは、どんな敵を出現させるとしても同じ動作になると思います(違ったらすいません)。
ですので、
・pattern:動きのパターン
・size:敵の大きさ
・x:x座標
・y:y座標
を引数とした関数でも作ってあげると、楽になると思います。


製作頑張って下さいね。


1,009ポイント を手に入れた。

Name: 水孤  ..ぴよぴよ(676ポイント)   Date: 2008/04/08(火) 23:37   No:15451     
Title: Re:シューティングでの敵の同時出現    
丁寧な解説ありがとうございました。おかげで敵を同時に出すことが出来ました。

それで、もう一つ質問があるのですがよろしいでしょうか?

シューティングゲームの館のプログラムを元に、敵が消えると弾を撃つのをやめるようにしたのですが
そのすると場合によっては、敵が消えた後、別の敵が打つときに全然違う場所からショットがでるようなことが起こってしまいました。(玉の出る場所は敵の中心から出るようにしています。)

正直何が原因なのかもさっぱりなので、わかる人がいたらどうか教えてください。


105ポイント を手に入れた。

Name: nayo  ..かけだし(2,039ポイント)   Date: 2008/04/09(水) 00:38   No:15455     
Title: Re:シューティングでの敵の同時出現    
私も以前同じようなところで悩んでましたね…

敵呼び出し部分には
for(i=0;i<100;i++)
if(enemy[i].flag==0)
break;

敵ショットパターン呼び出し部分には
for(i=0;i<ENEMY_SHOT_NUM;i++)//記憶が曖昧…
if(EnemyShot[i].flag==0)
break;

とありますがおそらくショットパターンのiと敵のiを同じと勘違いしてると思ったのですが…
この敵番号のiの値をショットパターンの構造体に変数を用意して記憶しておけば良いと思います
EnemyShot[i].e_numなど
これを上に書いてある敵ショットパターン呼び出し部分に
EnemyShot[i].e_num = i;
を追加してやるとできるかと
(これ以外の原因でしたらすみません)

敵が消えたときに撃たないようにするにはショットパターンのところで
if(EnemyShot[i].counter==0&&enemy[EnemyShot[i].e_num].hp>0)
を追加してやるとできるかも、です


269ポイント を手に入れた。

Name: 水孤  ..ぴよぴよ(732ポイント)   Date: 2008/04/09(水) 22:56   No:15462 解決!     
Title: Re:シューティングでの敵の同時出現    
貴重な意見ありがとうございます。とても参考になりました。
あのバグは、最終的には自分の凡ミスが一番の原因でしたが、なんとか解決しました。



56ポイント を手に入れた。



Name: 組木紙織  ..熟練のプログラマー(45,974ポイント)   Date: 2008/03/30(日) 01:10   No:15237       
Title: マルチスレッドクラス    
過去ログ マルチスレッドクラス
ttp://www.play21.jp/board/formz.cgi?action=res&resno=13859&page=&lognum=46&id=dixq&rln=14641&vino=28

時間がかかりましたが、
色々な皆様(特にJusty様)のおかげで只今作成中のマルチスレッドクラスがだんだんと完成に近づいてきました。
欲しい機能を全て盛り込み、今までに指摘された問題についても注意して実装をしました。

色々と機能を盛り込みすぎて複雑になってしまいましたが、今回も前回と同様に批評を
お願いしたいと思います。



140ポイント を手に入れた。


Name: Justy  ..ハッカー(182,250ポイント)   Date: 2008/03/31(月) 03:49   No:15247     
Title: Re:マルチスレッドクラス    
 途中でいろいろと変わってきていると思うので、ここいらで現時点での設計のコンセプトとか
実現したいこと、したくないとなどを整理する為にも書いておくといいかもしれません。


 とりあえず、ざっくりと見てみました。

・ Threadクラスを使うと、ハンドルが1つ解放されないものがありそうです。
 多分 TK::_threadBase::threadBreak()の aliveThread判定が逆なのではと疑っています。

・ _threadBaseクラスのメンバ hEndedハンドルは何に使っているのでしょうか?
(今は削除されてしまっているスレッドのキャンセル機能かな、と推測されますが)


・ ThreadOpeのデストラクタの動作は自動で join()されるのですが、
Threadクラスみたいに選べないのでしょうか。


・ _threadBaseを継承している関係で、継承先の Threadクラスなどで start()など内部で使用する関数が
使用できてしまいますが、それは問題ないでしょうか?


・ using namespace TK;
 ヘッダでこれをすると、TK名前空間の意味が全く無くなってしまいます。


312ポイント を手に入れた。

Name: 組木紙織  ..熟練のプログラマー(46,681ポイント)   Date: 2008/03/31(月) 21:18   No:15281     
Title: Re:マルチスレッドクラス    
気をつけたのに、頑張ったのに、ざっくり見られただけでも凡ミスが色々と発見されて、
こんなんじゃプログラマー目指せないなと自分に落ち込んでいます。
もっと頑張らないと。

コンセプトを書く前に、コメントについて返事をしておきます。

>・ Threadクラスを使うと、ハンドルが1つ解放されないものがありそうです。
>多分 TK::_threadBase::threadBreak()の aliveThread判定が逆なのではと疑っています。

はい。ifの判定が逆でした。falseのときにfalseとするような判定をしても意味がないです。


>・ _threadBaseを継承している関係で、継承先の Threadクラスなどで start()など内部で使用する関数が
>使用できてしまいますが、それは問題ないでしょうか?

あ、protectedにするのを忘れていました。


>・ using namespace TK;
> ヘッダでこれをすると、TK名前空間の意味が全く無くなってしまいます。

消去し忘れていました。


/**ここからがコンセプトなどなど********/

1.マルチスレッドを扱うクラスを作る。

2.子スレッドの生存期間は親スレッド中のこのマルチスレッドを扱うクラスを同じものとする。

3.マルチスレッドを扱うクラスと子スレッドの関係は1対1とする。

4.コピーコンストラクタやコピー代入演算子は禁止にする。

5.そのマルチスレッドを扱うクラスは、動作クラスをテンプレートにするもの(Thread)、関数を引数にして動作するもの(ThreadOpe)
の2つを用意する。

6.Threadクラスが破棄されるときに必ず子スレッドの終了を待つ(安全側)か、子スレッドを強制的に終了させる(危険側)のかの選択権を
 ユーザーが持つ。
 この選択権は明示的に示さない限り必ず安全側であるものとする。

7.ThreadOpeクラスはThreadクラスのような選択権を持たずに、必ず安全側であるものとする。

8.動作クラスはBaseRun<"引数","選択権">を継承するものとする。

9.Threadクラスのコンストラクタは明示的に定義しなければ引数を持たない。

10.ThreadOpeクラスのコンストラクタは次のようなものとする。
ThreadOpe<"引数の型">("動作関数へのポインタ","引数");
 なお動作関数はvoidを返し、引数を必ず1つもつものとする。

11.Threadクラスは次のような公開メンバ関数を持つ。
void resume()
void suspend()
void interrupt()
int isEnd()
void join()
voi sleep(double)

12.ThreadOpeクラスはThreadクラスのinterrupt()を除いた公開メンバ関数を持つ。


13.公開メンバ関数interrupt()は安全側では動作クラス中にキャンセルポイントinterruptPoint()を必要とするが、
 危険側では必要としない。


/*ここまで*/

コンセプトというより仕様書っぽくなってしましましたが、こんな感じのを作りたいと考えています。
矛盾した部分はないとは思うのですが、自信はあまりありません。

まとめてみると少し実装し忘れていたのが残っいました。
続きを作らないと。


707ポイント を手に入れた。

Name: Justy  ..ハッカー(182,600ポイント)   Date: 2008/04/01(火) 00:39   No:15290     
Title: Re:マルチスレッドクラス    
>気をつけたのに、頑張ったのに、ざっくり見られただけでも凡ミスが色々と発見されて、
 テストファースト、とまでは言いませんが、全メソッドを使ったユニットテスト用のコードを用意して
実行するだけである程度エラーを検知できるようにしておくといいいかも。


>コンセプトというより仕様書っぽくなってしましましたが、こんな感じのを作りたいと考えています
 仕様が明確になったので、意図がよく分かりました。ありがとうございます。
 基本的には前のスレでも書きましたが、デストラクタでの子スレッド扱いに関すること以外は
仕様的に問題はないように思います。


>6.Threadクラスが破棄されるときに必ず子スレッドの終了を待つ(安全側)か、
>子スレッドを強制的に終了させる(危険側)のかの選択権を ユーザーが持つ
 「子スレッドを放置する」という選択肢はないのでしょうか?(でも現時点での実装は放置になってますよね?)
 
 ついでに言えばスレッドクラスとしての安全性を考慮するなら
逆に「子スレッドを強制的に終了」は要らないと思います。


350ポイント を手に入れた。

Name: 組木紙織  ..熟練のプログラマー(47,067ポイント)   Date: 2008/04/01(火) 23:34   No:15298     
Title: Re:マルチスレッドクラス    
>>6.Threadクラスが破棄されるときに必ず子スレッドの終了を待つ(安全側)か、
>>子スレッドを強制的に終了させる(危険側)のかの選択権を ユーザーが持つ
> 「子スレッドを放置する」という選択肢はないのでしょうか?(でも現時点での実装は放置になってますよね?)

子スレッド放置というつもりで実装はしてないので、後で確認してみます。

子スレッドの終了に関してのコンセプトは、
子スレッドはSleep()で一定時間停止させて使うことが多いと考えており、基本的に子スレッドは安全に終了させるが、その場合には親スレッドは子スレッドが停止している時間待つ必要がある。
速度が必要な場合にはこの静止している時間がもったいないと思うことが出てくる可能性があるので、明示的な場合のみ子スレッドを強制的に終了させて速度を確保することが出来るようにする。
と、考えています。

また子スレッドの放置は、メモリーリークの可能性や、子スレッドが悪さをする可能性があると
考えており、また子スレッドを放置する利点が現時点で見つからないので子スレッド放置の実装は考えていません。


386ポイント を手に入れた。

Name: Justy  ..ハッカー(184,022ポイント)   Date: 2008/04/02(水) 02:55   No:15299     
Title: Re:マルチスレッドクラス    
>子スレッド放置というつもりで実装はしてないので、後で確認してみます。
 えーと、CanBreakが使われる(join()しない方)と放置になります。



>子スレッドの終了に関してのコンセプトは、
> 〜
>と、考えています。
 なんとなく言わんとするところは理解できますが、問題は「放置する」選択肢がないこと
なんです。

 コンセプトとして、絶対にデストラクタが終わった時にはスレッドは終了していることを
保証し、それに反するような使い方をするスレッドを作る場合は別の関数・クラスを使うなりする
ということであればそのままでも問題はありません(その場合以下は無視して下さい)。


 もし、そうではなく汎用的なスレッドクラスを目指しているのであれば幾つか問題があります。

 まず、前スレでも指摘したのでご存じだと思いますが、無限ループ"的"な子スレッドの場合、
Threadクラスがデストラクタで join()を行うと復帰が困難になります。

 又、デストラクタで強制的に子スレッドを破壊することは、子スレッドの状況如何では
非常に危険を伴います。
 従ってこの場合、放置する(勿論ハンドルは解放しますが)か、キャンセルポイントによるスレッドの
キャンセルをするのが最適なのではないでしょうか。


 次に

> 必ず子スレッドの終了を待つ(安全側)か、子スレッドを強制的に終了させる(危険側)のか
 ということは
 
 Threadクラスのライフサイクル > 子スレッドのライフサイクル
 ということになります。

 これが便利なケースもありますが、逆にいつ終わるか判らない子スレッドの為に、
Threadクラスが存在していなければならないことになり、スレッドの本来の目的である
非同期性が失われ、運用が不便になる可能性もあります。

 例えばある関数の機能として、リクエストだけして戻っていき、
(一定時間で終わるだろう)処理そのものは子スレッドで行うような場合、
どうしたらいいでしょう。

TK::ThreadOpe<int>* test()

{
return new TK::ThreadOpe<int>(bar2,0);
}

 とか、
boost::shared_ptr< TK::ThreadOpe<int> > test()

{
return new TK::ThreadOpe<int>(bar2,0);
}

 なら、即座に関数を抜けていきますが、戻値を受け取って管理しないと
いけません。

void test()

{
TK::ThreadOpe<int> thread1(bar2,0);
}


 というようなコードですと、現状の仕様ではbar2が終わるまで戻れませんし、
強制破棄するタイプだとしても、すぐに関数を抜けて戻っていきますが
それでは bar2()の処理が終わりません。

 これがもし「放置」するタイプであれば、最後のコードで旨く動きます。
 こういう、リクエスト系の使い方はしないのでしょうか?



>また子スレッドの放置は、メモリーリークの可能性や、子スレッドが悪さをする可能性があると
 もちろん、放置は万能ではありません。
 マズイのであれば、キャンセルポイントによるスレッドのキャンセルをするなり、
実行の終了を親スレッド側でまったり、或いは最悪スレッドの強制終了も視野にいれる必要はあります。



 ちなみに前スレで話題にした C++0xの std::threadなど多くのスレッドクラスのデストラクタは
基本的に実行している子スレッドに何もすることなく終えるようです。


1,422ポイント を手に入れた。

Name: 組木紙織  ..熟練のプログラマー(47,294ポイント)   Date: 2008/04/02(水) 15:35   No:15302     
Title: Re:マルチスレッドクラス    
リクエスト系の使い方は今までしたことがなかったので、考えていませんでした。
子スレッドの放置を考えなかった一番の理由はスレッドをリークしたメモリみたいな
状態にすることに非常に違和感を感じたからです。

> ちなみに前スレで話題にした C++0xの std::threadなど多くのスレッドクラスのデストラクタは
>基本的に実行している子スレッドに何もすることなく終えるようです。

このことは知ってはいたのですが、上記のような理由で考慮していませんでした。
「放置」が実際に使われるテクニックであるのなら実装に含めてもいいと考えています。


汎用性をどこまで求めるかというのは、
そもそもマルチスレッドを扱うクラスを製作しようとした理由がダブルバッファリングをマルチスレッド
で扱いたいなと考え、WindowsAPIのスレッド関係の関数が使いにくそうだったので、c++でラップした
クラスを使ってマルチスレッドプログラミングの練習をしようかな思ったからです。


227ポイント を手に入れた。

Name: Justy  ..ハッカー(184,265ポイント)   Date: 2008/04/03(木) 02:48   No:15316     
Title: Re:マルチスレッドクラス    
>子スレッドの放置を考えなかった一番の理由はスレッドをリークしたメモリみたいな
>状態にすることに非常に違和感を感じたからです。
 あー、なるほど。
 そういわれると何かこう説明出来ない気持ち悪さはありますね(w


>「放置」が実際に使われるテクニックであるのなら実装に含めてもいいと考えています。
 スレッドクラスの一番重要な役割はスレッドの起動とスレッドハンドルの管理なわけで、
それを考えると理論的にはスレッドハンドルを使って何かする(スレッドの終了待ちとか休止とか)場合は
放置ではまずいですが、逆にハンドルを使わないのであれば放置でいいはずです。


>ダブルバッファリングをマルチスレッド で扱いたい
 ダブルバッファとスレッドがどう関係してくるのかはあまりよくわかっていないのですが、
どちらかという同期オブジェクトクラスも必要ですよね。


#あれ? そういえば前は同期オブジェクトを扱うクラスがあったと思ったのですが、
無くなりました?


243ポイント を手に入れた。

Name: 組木紙織  ..熟練のプログラマー(48,250ポイント)   Date: 2008/04/04(金) 16:30   No:15363     
Title: Re:マルチスレッドクラス    
>スレッドクラスの一番重要な役割はスレッドの起動とスレッドハンドルの管理なわけで、
そう考えると、放置の実装もあるわけですね。
スマートポインタはメモリの確保から解放までを管理するものであるのに対し、スレッドクラスは
必要に応じて子スレッドの終了を子スレッド自身に任せてもよいということですか。


>ダブルバッファとスレッドがどう関係してくるのかはあまりよくわかっていないのですが、
前回のコメントは急いでいて意味が分からない文章を書いてしまってすみません。
えっと、要約すると、ダブルバッファリングが扱える程度の汎用性は欲しいというつもりで作っています。
ということです。


>#あれ? そういえば前は同期オブジェクトを扱うクラスがあったと思ったのですが、
同期クラスは完成したので、現在考えている部分のみをあげていました。

今まで安全側の動作を通常の終了の場合は安全なように、
例外が働いているときは危険側のように実装をさせてたのですが、
どちらも同じようにjoin()をして同じ動作をするようにした方が良いのかどうなのか
悩んでいます。




2倍のポイントを手に入れた! 956ポイント を手に入れた。

Name: Justy  ..ハッカー(184,703ポイント)   Date: 2008/04/05(土) 02:45   No:15369     
Title: Re:マルチスレッドクラス    
>スマートポインタはメモリの確保から解放までを管理するものであるのに対し、
 結局スレッドクラスが何を管理するか、に依るわけですよ。

 多くのスレッドクラスはハンドルを管理するので、スマートポインタ同様デストラクタで
ハンドルを解放します。

 もしスレッドクラスがハンドルだけでなく“子スレッドの存在”も管理するのであれば、
放置は絶対にありえない設計となります。


 そういう意味では多くのスレッドクラスは std::auto_ptrとか boost::shared_ptrとかより、
std::fstreamに近いかと思います。

 内部のファイルハンドルをデストラクタで解放しても、別にファイルが
なくなってしまうわけではなく、あくまでそのファイルをハンドリング(制御)する権利を
失うだけですから。




>スレッドクラスは 必要に応じて子スレッドの終了を子スレッド自身に任せてもよいということですか。
 適切に設計されているなら、私はいいと思います。


>>#あれ? そういえば前は同期オブジェクトを扱うクラスがあったと思ったのですが、
>同期クラスは完成したので、現在考えている部分のみをあげていました。
 なるほど。そうでしたか。


>今まで安全側の動作を通常の終了の場合は安全なように、
>例外が働いているときは危険側のように実装をさせてたのですが、
>どちらも同じようにjoin()をして同じ動作をするようにした方が良いのかどうなのか悩んでいます。
 スレッドの存在”も管理するタイプの方ですね?
 例外に巻き込まれているのは Threadクラスのインスタンスがある方で、
子スレッドとは基本的には関係はありませんので、通常時が join()するなら、
例外時も join()した方がいいのではないでしょうか。

 たとえて言うなら、例外に巻き込まれて破棄されるスマートポインタがポインタを
破棄しない、なんて・・・。。



438ポイント を手に入れた。

Name: 組木紙織  ..熟練のプログラマー(48,069ポイント)   Date: 2008/04/06(日) 08:22   No:15400     
Title: Re:マルチスレッドクラス    
> たとえて言うなら、例外に巻き込まれて破棄されるスマートポインタがポインタを
>破棄しない、なんて・・・。。

その例示を出されたら例外時と通常時の動作を同一にする理由がよくわかります。
ただ、私が気になったのは、"スレッドの存在も管理するクラス"で安全側にした時に、
例外に巻き込まれたら、デットロックが起こる危険性はを考えたからです。

例外時と通常時の動作を同じようにし、デットロックの危険性は実装者に回避してもらうような
実装にしようかな。


181ポイント を落としてしまった。

Name: Justy  ..ハッカー(186,462ポイント)   Date: 2008/04/06(日) 18:16   No:15413     
Title: Re:マルチスレッドクラス    
>ただ、私が気になったのは、"スレッドの存在も管理するクラス"で安全側にした時に、
>例外に巻き込まれたら、デットロックが起こる危険性はを考えたからです。
 
 安全側は join()するだけですよね?
 普通に考えて、例外に巻き込まれた結果デストラクタで join()してデッドロックを
起こすようであれば、通常時に join()してもデッドロックするのではないでしょうか。


>例外時と通常時の動作を同じようにし、デットロックの危険性は実装者に回避してもらうような
>実装にしようかな。

 その方向でいいと思います。



 あ、キャンセルポイントの機能を作成する予定があるのでしたら、
今ちょっとアイデアが浮かびました。


 前のスレの私のサンプル Z::Threadのインターフェースでは
「Threadクラスの Interruptメンバ関数を呼ぶと、子スレッド側の InterruptPoint関数で
スレッドが終了する、でした。
 Z::Threadはハンドル管理型なのでこのままでいいのですが、スレッドの存在も管理するので
あれば、予期しない例外に巻き込まれた時の挙動として、もう1種類のキャンセルポイントを
用意してはどうでしょうか。


・ 通常のキャンセルポイント
 Threadクラスに Interruptメンバ関数(public)を用意して、ユーザーがこれを呼ぶと
子スレッド側の InterruptPoint() / InterruptPointEx()でスレッドが終了します。

・ 例外発生時のキャンセルポイント
 Threadクラスに ExceptionInterruptメンバ関数(private)を用意して、
例外に巻き込まれて Threadクラスのデストラクタが実行されたら join()する前に
これを呼ぶようにします。

 子スレッド側は InterruptPointEx()でスレッドが終了します。


 こうしておくと、子スレッド側で InterruptPoint()を使ったか、InterruptPointEx()を
使ったかで、例外に巻き込まれたときの挙動が変えられます。

 例外に巻き込まれてもそのまま実行して欲しいけどユーザーがキャンセルしたときは
実行を止めて欲しいときは InterruptPoint()で、例外時も実行を止めて欲しいときは
InterruptPointEx()を使用します。

 又、InterruptPointEx()は、通常のキャンセルポイントとしても機能するようにしておけば
両方に反応させたいとき2つ書く必要がありません。



 うーん、自分で書いておきながら蛇足的な感もありますが、Threadクラスのデストラクタで
join()するなら、こういう仕組みで子スレッド側に通知するのも有りかなと思います。

(ちょっと迷うのは ExceptionInterrupt()を呼ぶのは例外に巻き込まれたときだけに
した方がいいのか、デストラクタ実行時常に呼んだ方がいいのか、ですね)


774ポイント を手に入れた。

Name: 組木紙織  ..熟練のプログラマー(47,715ポイント)   Date: 2008/04/07(月) 22:18   No:15428     
Title: Re:マルチスレッドクラス    
>>ただ、私が気になったのは、"スレッドの存在も管理するクラス"で安全側にした時に、
>>例外に巻き込まれたら、デットロックが起こる危険性はを考えたからです。
 
> 安全側は join()するだけですよね?

はい現在の実装はjoin()するだけです。
デットロックが起こる可能性があると思ったのは無限ループのスレッドで
通常側はinterrupt()をするようにしているが、例外側はinterrupt()をしないのでは。
と思ったからです。

#最終的な実装はinterrupt()をしてjoin()をする予定だったので、気にする必要はなかったです。


> あ、キャンセルポイントの機能を作成する予定があるのでしたら、
>今ちょっとアイデアが浮かびました。



通常時はjoin()で例外時は放置
通常時と例外時どちらもjoin()
をする中断ポイントを用意するのは、利点があまりないような気がします。
(利点があれば実装したいと思うのですが、利点がなければさらに複雑になるので。)



現在は単一のスレッドしか扱えるようになっていませんが、実装が安定してきたら
次は複数のスレッドをまとめて管理できるようなクラスも作ろうかなと考えています。


354ポイント を落としてしまった。

Name: Justy  ..ハッカー(186,926ポイント)   Date: 2008/04/09(水) 02:08   No:15456     
Title: Re:マルチスレッドクラス    
>最終的な実装はinterrupt()をしてjoin()をする予定だったので、気にする必要はなかったです
 なるほど。


>をする中断ポイントを用意するのは、利点があまりないような気がします
 なければ、別にいいのですが。



464ポイント を手に入れた。



Name: ガルディ  ..ぴよぴよ(98ポイント)   Date: 2008/04/08(火) 00:20   No:15430       
Title: レースゲームのアクセルについて    
今レースゲームの制作をしていて、どうしていいのかわからなくなってしまったので、この掲示板を利用させてもらってます。

その質問の内容というのが
レースゲームじゃなくてもリアルのレースでもアクセルから足を離しても、何秒(?)何分(?)間くらいは走っていますよね?
それをプログラムでかかないとかなり不自然なレースゲームになってしまいます。
いろいろ思考錯誤をしたりして解決しようとしてるのですが、何故か最終的にパッド・キーボードから手を離すと止まってしまいます。
どういった演算処理(?)をすればいいのでしょうか。
是非教えてください


98ポイント を手に入れた。


Name: tkmakwins15 [URL]  ..比類無きプログラマー(67,791ポイント)   Date: 2008/04/08(火) 02:16   No:15432     
Title: Re:レースゲームのアクセルについて    
止まるまでの時間は、速度の2乗と物体の質量に比例しますので…

単位を決定し、スピード×スピード×質量を計算して、単位経過と共に速度をどんどん減らしていきます。

というのはどうでしょうか?


77ポイント を手に入れた。

Name: やそ  ..プログラマー(38,208ポイント)   Date: 2008/04/08(火) 09:36   No:15434     
Title: Re:レースゲームのアクセルについて    
>何故か最終的にパッド・キーボードから手を離すと止まってしまいます。
そのように処理を書いているから・・・何だと思いますよ^^;

この辺の物理法則について分かりやすく解説されているのは・・・
教習所の教本やホームページでしょうね。
空走距離や制動距離を調べれば分かると思います。

後は自分の納得の行くように処理を書く!コレだけです。

がんばってください。





124ポイント を手に入れた。

Name: toyo  ..初心者(6,760ポイント)   Date: 2008/04/08(火) 09:55   No:15435     
Title: Re:レースゲームのアクセルについて    
単純に考えると

アクセルを踏んだら正の加速度に acce = 10;
離したら負の加速度に acce = -1;
ブレーキで負の加速度を追加 acce -= 10;
フレーム処理毎に速度を変化 velo += acce * tekitounakeisuu;

数字は適当なので実際に動かしながら調整

でもこういうのって実際に作ると思った挙動をしてくれないんですよね


96ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..比類無きプログラマー(67,806ポイント)   Date: 2008/04/08(火) 10:48   No:15436     
Title: Re:レースゲームのアクセルについて    
整数値の加速度で良いんなら、enum型を使うと、ミスが減ると思います。(enumが強ければもっといいんですが…)

15ポイント を手に入れた。

Name: やそ  ..プログラマー(38,386ポイント)   Date: 2008/04/08(火) 11:41   No:15438     
Title: Re:レースゲームのアクセルについて    
>でもこういうのって実際に作ると思った挙動をしてくれないんですよね
でも、そういう所を繰り返しプログラム&検証(デバッグ)するのもゲーム製作の楽しみ方(苦行?)のひとつだと思いますよ^^

完全に物理法則を当てはめる必要も無いので、それっぽい挙動だったり、「お、これいいじゃん」と思ったらそれでOK。
自分なりの作り方、演出などが出来れば一人前っすよ^^
それで分からなくなったらまたここで聞けばベテラン勢がヒントをくれる!
いい環境ですな^^






178ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(551,619ポイント)   Date: 2008/04/08(火) 17:08   No:15445     
Title: Re:レースゲームのアクセルについて    
物理演算をするようなプログラムなら完璧な物理の公式にあてはめないといけませんけど、
ゲームは案外そんな必要ないです。

・・というのも、アクションゲーム、例えばストリートファイター(ふるっ)とかのジャンプって完全に物理的におかしいですよね。
でもそれで楽しいゲームとして成り立つ。
ゲーム性がよくなったり、見栄えがしたりするのは、物理的に正確である事ではないんだと思います。

正確にとか言い出したらタイヤと路面との摩擦から空気抵抗を含めた流体力学の話にまで発展するので不可能だと思います。

リッジレーサーやグランツーみたいなゲームになるとそれなりのこだわりがあるのかもしれませんが、
自作ゲームの範囲でしたら、やってみておかしくない程度の計算式を試行錯誤で調整すればそれでいいんじゃないでしょうか?

ただボタンを離して止まってしまうのは、そのようにプログラムを書いたならしょうがないでしょう・・としかいいようがないです・・。


290ポイント を手に入れた。



Name: 小谷野 雅雄  ..ぴよぴよ(16ポイント)   Date: 2008/04/08(火) 00:16   No:15429       
Title: 競合    
競合Visual C++で下記のような警告が出て画像が出ません。どうしたらいいですか。

リンク中...
LINK : warning LNK4098: defaultlib "LIBCMTD" は他のライブラリの使用と競合しています; /NODEFAULTLIB:library を使用してください

p9999.exe - エラー 0、警告 1


16ポイント を手に入れた。


Name: YuO  ..上級者(19,365ポイント)   Date: 2008/04/08(火) 02:31   No:15433     
Title: Re:競合    
使用しているCRTはリンクされる全ての.obj/.libで一致していますか?
例えば,Release版のCRTを利用する.libをDebug版のCRTを利用するプロジェクトで利用していると,そのようなエラーが出ます。
解決策は,すべてのCRTを同一版に統一する事です。


89ポイント を手に入れた。



Name: 北欧マニア  ..ぴよぴよ(297ポイント)   Date: 2008/04/05(土) 02:25   No:15368       
Title: 自作関数について    
課題が出ておりまして自分でできるとこまでやったんですが、もう限界です。。
どなたか助けて下さい。
OSはウィンドウズ、コンパイラはボーランドを使っています。
作っている関数は、データを保存する配列の関数を作っています。
一応エラーは出ないんですが、画面には何も表示されません。

今はdata_set0,1,2 と関数を分けていますが、data_set関数だけで、変数を使って、1024個のデータを
格納したいと考えています。格納したデータを表示出来るようにしたいです。
期限がもうギリギリなので、宜しくお願いします。

#include <stdio.h>

int data[4];
int data_set0(void);
int data_set1(void);
int data_set2(void);
int data_set3(void);


int data_set0()
{
data[0] = 100;

return data[0];
}

int data_set1()
{
data[1] = 101;

return data[1];
}

int data_set2()
{
data[2] = 102;

return data[2];
}

int data_set3()
{
data[3] = 103;

return data[3];
}



int main()
{
data_set0();
data_set1();
data_set2();
data_set3();

return 0 ;
}


297ポイント を手に入れた。


Name: 名無し  ..入門者(4,625ポイント)   Date: 2008/04/05(土) 03:16   No:15370     
Title: Re:自作関数について    
1024個のデータはどこにあるのですか?
何をしたいのかよくわかりません・・・
表示するだけでよいのなら

#include <stdio.h>

int data[4];

int data_set0()
{
data[0] = 100;

return data[0];
}

int data_set1()
{
data[1] = 101;

return data[1];
}

int data_set2()
{
data[2] = 102;

return data[2];
}

int data_set3()
{
data[3] = 103;

return data[3];
}



int main()
{
printf("data[0]=%d\n",data_set0());
printf("data[1]=%d\n",data_set1());
printf("data[2]=%d\n",data_set2());
printf("data[3]=%d\n",data_set3());

return 0 ;
}


214ポイント を手に入れた。

Name: 通りすがり  ..初心者(7,593ポイント)   Date: 2008/04/05(土) 04:41   No:15371     
Title: Re:自作関数について    
まず、何をしたいのかさっぱりわかりませんし、1024個のデータに何を入れるのかもわかりません。
仕様がわからなければ答えようが無いですし、出来る事はやったと言っていますが、
画面に文字を表示するのは、プログラムで一番最初に習うべきハローワールドでも有名なprintf。
これを使わないと画面に文字が表示されない事はC言語歴1時間の入門者でもわかるでしょう。


家に書籍が無いのなら、ネットで勉強しましょう。
ググればいくらでも出てきます。
http://www.google.co.jp/search?hl=ja&q=C%E8%A8%80%E8%AA%9E%E3%80%80%E5%85%A5%E9%96%80&lr=


254ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(80,155ポイント)   Date: 2008/04/05(土) 08:14   No:15372     
Title: Re:自作関数について    
こちらで勝手に深読みしたのと同じ内容であれば、配列、ループ…がキーワードになりそうですね(^O^)

32ポイント を手に入れた。

Name: toyo  ..初心者(6,664ポイント)   Date: 2008/04/05(土) 13:08   No:15374     
Title: Re:自作関数について    
4つの関数を1個で済ませるならこんな関数になります

int data_set(int n)
{
data[n] = 100 + n;
return data[n];
}



77ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(549,147ポイント)   Date: 2008/04/05(土) 13:27   No:15375     
Title: Re:自作関数について    
期限がギリギリと言う事なんですが、課題でしょうか?
課題の内容はどんなものなのでしょうか?


24ポイント を手に入れた。

Name: 北欧マニア  ..ぴよぴよ(337ポイント)   Date: 2008/04/05(土) 15:29   No:15377     
Title: Re:自作関数について    
皆様、アドバイスありがとうございます。 課題の内容なんですが、1024個を数字を格納する配列を作ること、またその個数をデファインで変えられるようにすること。 そのなかで、関数を用いて、どこに何の数字を格納しているか わかるようにする事。出来たらそれをPRINTF以外の関数で表示したいと考えています。わかりずらくて申し訳ありません、

40ポイント を手に入れた。

Name: lbfuvab  ..ぴよぴよ(237ポイント)   Date: 2008/04/05(土) 15:49   No:15378     
Title: Re:自作関数について    
#include<stdio.h>

#include<string.h>
#define SIZE 1024

int buf[SIZE];

int ShowData(int n){
if(n<0 || n>=SIZE)
return 0;
return buf[n];
}
int main(){
int i,data;
char szData[7];

do{
printf("何個目のデータを見ますか?(0〜%4d)\n",SIZE);
scanf("%d",&i);
data=ShowData(i);
sprintf(szData,"%d",data);
puts(szData);
puts("続けますか?(0-No,1-Yes)");
scanf("%d",&i);
}while(i);
return 0;
}


こんな感じですか?(データを入れてないので全て0が表示されます


195ポイント を手に入れた。

Name: オプーナを買う権利を授けよう  ..ぴよぴよ(131ポイント)   Date: 2008/04/06(日) 00:59   No:15388     
Title: Re:自作関数について    
>1024個を数字を格納する配列を作ること、またその個数をデファインで変えられるようにすること。
あまり得意ではないのでほかの方に解説していただきたいのですがmalloc関数のことじゃないんですかね?



81ポイント を落としてしまった。

Name: 北欧マニア  ..ぴよぴよ(362ポイント)   Date: 2008/04/06(日) 01:27   No:15391     
Title: Re:自作関数について    
<ぴよぴよさん

コードありがとうございます。
コードはほぼ自分がイメージしていたものでした。
ちょっと欲を言うとデータをscanfとかで入力したものを表示できたらいいな…と
あとここから自分で追加してみようと思ったんですが、古いデータから上書きとかも考えています。
時間がおありでいたら宜しくお願いします。


<オプーナを買う権利を授けよう さん

自分も一番最初にmallocで作ろうかとしたら、mallocは使わないようにと言われました。


25ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(549,473ポイント)   Date: 2008/04/06(日) 02:21   No:15393     
Title: Re:自作関数について    
>オプーナを買う権利を授けようさん

defineで定義すると言う事は、定数で配列の要素数が変動しないので、mallocは使う必要が無いと思います。
配列要素数を変数で指定する時にmallocを使えばいいと思います。
まぁ色んな定数を利用すると言うなら話は別ですが・・。

>北欧マニアさん

いまいちやりたいことがわからないのですが、scanfで何を入力したいのでしょう?
具体的に何をしたいかがわからないと答えられないので、その辺を最初から明確にしてもらえると皆さんの回答も早く得られると思います。

もう代入の仕方はわかったんですよね?
それなら単に
scanfで取り込んだ変数の値を代入したらいいだけです。

int d,hairetu[1000];
scanf("%d",&d);
hairetu[0]=d;
printf("%d",d);

これだけでも出来てますが、それだけの量の配列を用意する意味がよくわかりません。
printfは使わないという仕様なのでしょうか?
printf以外なら何でもいいのでしょうか?


326ポイント を手に入れた。

Name: 北欧マニア  ..ぴよぴよ(431ポイント)   Date: 2008/04/07(月) 08:16   No:15420     
Title: Re:自作関数について    
←管理人さん      配列に入力したいのは数字です。代入の仕方はわかりました。表示の仕方ですが、PRINTFは出来るだけ使わないで、別のやり方でやるように言われました。

69ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..比類無きプログラマー(67,714ポイント)   Date: 2008/04/07(月) 09:45   No:15422     
Title: Re:自作関数について    
printfを使うなということであれば、

fprintf(stdout,/*printfの第一引数*/,/*第二引数以降*/);

とか…

char buffer[1024];
sprintf(buffer,,/*printfの第一引数*/,/*第二引数以降*/);
fputs(buffer,stdout);

printf系関数を使わないようにということならば、

http://www.play21.jp/board/formz.cgi?action=res&resno=12356&page=&lognum=38&id=dixq&rln=12373

が参考になると思います。


2倍のポイントを手に入れた! 290ポイント を手に入れた。

Name: 北欧マニア  ..ぴよぴよ(448ポイント)   Date: 2008/04/08(火) 01:45   No:15431     
Title: Re:自作関数について    
< tkmakwins15 さん

大変参考になりました。ありがとうございます。
あと余談なのですが、登録データがMAXになったら古いデータから上書きを考えていて、
for文で現在作成中なのですが、もっと良いやり方はあるでしょうか?



17ポイント を手に入れた。



Name: RYU2  ..かけだし(1,042ポイント)   Date: 2008/04/05(土) 22:52   No:15385       
Title: シューティングゲームの館で・・・    
こんばんは、初投稿です。
いきなりすみませんが不思議に思ったことがあるので質問させてもらいます。

まず、自分の環境ですが、
OS:VISTA
開発環境:BCC Developer(VC++はなぜか動かないので・・)

独学でCを勉強していて、ポインタと構造体を大体理解することはできました。
そこで、コンソールアプリに飽きてしまって^^;ゲームを作ろうと思いこのページを見て勉強していました。

それで、シューティングゲームの館を見ていて、例を使ってみていたところ、
(8)「ショットを打つ」 で、

/* main.cpp */

#include "DxLib.h"
#include "GlobalVariable.h"


int WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){

extern void img_sound_load();
extern void initialization();
extern void SetColor();
extern void Background();
extern void PlayerShotCalc();
extern void PlayerShotDisp();
extern void PlayerControl();
extern void EnemyControl();
extern void EnemyCalcDisp();
extern void EnemyShotControl();
extern void EnemyShotCalcDisp();
extern void CollisionDetection();
extern void Background2();
extern void FpsTimeFanction();
int RefreshTime=0;

// ChangeWindowMode( TRUE ) ;
if( DxLib_Init() == -1 ) return -1;

SetDrawScreen( DX_SCREEN_BACK ) ; //裏画面を使用する。

のように打ったところ、メイク(デバッグ)時に、

Error: 外部シンボル '_img_sound_load' が未解決(C:\WORK\BCC\MAIN\DEBUG\MAIN.OBJ が参照)
Error: 外部シンボル '_initialization' が未解決(C:\WORK\BCC\MAIN\DEBUG\MAIN.OBJ が参照)
(これがFpsTimeFantion();まで続きます)

となってしまいます。


そこで、extern宣言をすべてヘッダファイルに移したらどうなるかな?? と思い
GlobalVariable.hのほうに移してみたところ、正常に動きました。

ちゃんと動いたのでよかったのですが、原因が気になったので質問しました。
どなたかわかる方、教えてください。

長文ですみませんでした。


1,042ポイント を手に入れた。


Name: Justy  ..ハッカー(184,819ポイント)   Date: 2008/04/05(土) 23:41   No:15386     
Title: Re:シューティングゲームの館で・・・    
 過去ログより。

http://www.play21.jp/board/formz.cgi?action=res&resno=6091&page=&lognum=20&id=dixq&rln=6294

 一応エラーになる直接的な原因は分かっていますが、BCCがどうしてこういう仕様にしているかは
わかりません。


37ポイント を手に入れた。

Name: RYU2  ..かけだし(1,724ポイント)   Date: 2008/04/06(日) 00:22   No:15387     
Title: Re:シューティングゲームの館で・・・    
Justyさん、本当にありがとうございます。

完璧には理解できませんでしたが、とりあえずBCCを使うときは
Main関数内でextern宣言してはいけないということがわかりました。

//

VC++2008ExpressEditionを本当はBCCよりも先にダウンロードしたのでVC++を使いたいのですが、
コンソールアプリはできるのに、DXライブラリ関係のことをするとこれまたなぜか使えないのです;;

で、仕方なくBCCを使っていました。
(実際使いやすかったのですが・・)

でもやっぱりVC++も使いたいので質問させてもらいます。

例として

#include "DxLib.h"


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {

ChangeWindowMode(TRUE);

if(DxLib_Init() == -1) return -1;
DrawPixel(240, 240, 0xffff);
WaitKey();
DxLib_End();

return 0;
}


のような簡単なプログラムをVC++で作ったのですが、
デバッグすると

warning C4819: ファイルは、現在のコード ページ (932) で表示できない文字を含んでいます。データの損失を防ぐために、ファイルを Unicode 形式で保存してください。

というエラーが出ます。

DXライブラリの本家のサイトに書いてあったとおりにしたはずなのにエラーが出ます。

なので、一度
「プロジェクト」→「プロパティ」→「構成プロパティ」→「全般」より

「マルチバイト文字セットを使用する」を変更し「Unicode文字セットを使用する」に変更して見たのですが、
やはり同様のエラーが出ます。

上記のエラーでググってみたのですが、理解できませんでした。
どなたか教えてください。

よろしくお願いします。


682ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..比類無きプログラマー(67,199ポイント)   Date: 2008/04/06(日) 01:22   No:15389     
Title: Re:シューティングゲームの館で・・・    
>warning C4819: ファイルは、現在のコード ページ (932) で表示できない文字を含んでいます。データの損失を防ぐために、ファイルを Unicode 形式で保存してください。

これはエラーではありませんよ。単なる警告です。
マルチバイトの設定で間違いありません。「Unicode文字セットを使用する」ではそれこそエラーが出てしまいます。

メニュー→「デバッグ」→「デバッグなしで開始」で実行できないんですよね?


178ポイント を手に入れた。

Name: Justy  ..ハッカー(185,590ポイント)   Date: 2008/04/06(日) 01:25   No:15390     
Title: Re:シューティングゲームの館で・・・    
>とりあえずBCCを使うときは
>Main関数内でextern宣言してはいけないということがわかりました
 かなりレアなんですよね、この問題って。
 通常関数内で externすること自体が珍しいですし、仮にしても大抵の場合は問題なく
動作するわけで。


>warning C4819: ファイルは、現在のコード ページ (932) で表示できない文字を含んでいます。
>データの損失を防ぐために、ファイルを Unicode 形式で保存してください。
>というエラーが出ます。
 エラーじゃないです。警告です。
 多分ビルド自体は成功しているので、実行もできるはずです。

 この警告は対象のソースコードの中にそのファイルの文字コードでは扱えない文字が存在する場合に
出るのですが、 VC2005の時はバグでその警告が出てしまうケースが多々ありました。

 しかし、VC2008だとなると本当に扱えない文字がソースコード中にある可能性があります。
 例えばソースコードが Shift-JISで書かれているのにShift-JISでは扱えない文字が入っているとか。

 その警告が出るソースを提示して頂ければ、どこに問題があるのか見つけられると思いますが、
とりあえず以下のどれかを試してみて下さい。

・  VisualStudio上でそのファイルを開き、適当なところに1文字空白を挿入し、
その文字をdeleteキーで消したあと保存。

・ VisualStudio上でそのファイルを開き、先頭付近にある /* */コメントの中で
1文字空白を入れて保存

・ VisualStudioか適当なエディターを使って Unicodeで保存し直す

 これでビルドして警告が出なくなれば成功ですが、まだ出るようでしたら
そのソースを見ないと何とも言えません。


 ちなみにあまりお薦めはできませんが、最後の手段として警告を黙らせる方法もあります。
 警告対象のソースに

#pragma warning(disable : 4819)
 を入れて下さい。
 これで、C4819の警告は出なくなります。


771ポイント を手に入れた。

Name: bodomcross  ..ぴよぴよ(331ポイント)   Date: 2008/04/06(日) 09:51   No:15402     
Title: Re:シューティングゲームの館で・・・    
私もBCCを使っていましたが

VC2005++EEに変更したときに、最初は躓きました

まず、マルチスレッドデバックでしたか・・・ あれの設定しわすれと

プロジェクトを作成するときに、コンソールアプリを選んでたのが原因でした

Dxライブラリを使うときは、Win32プロジェクトで、Windowsアプリケーションを指定し

空のプロジェクトを作ってしています

当方も初心者なので、参考程度にしてくださいね^^


128ポイント を手に入れた。

Name: RYU2  ..かけだし(2,146ポイント)   Date: 2008/04/06(日) 22:21   No:15415     
Title: Re:シューティングゲームの館で・・・    
皆さん、回答本当にありがとうございます。

まず、Justyさんが教えてくれた
>・  VisualStudio上でそのファイルを開き、適当なところに1文字空白を挿入し、
その文字をdeleteキーで消したあと保存。

>・ VisualStudio上でそのファイルを開き、先頭付近にある /* */コメントの中で
1文字空白を入れて保存。

をしてみましたが、やはり警告が出ます・・


>・ VisualStudioか適当なエディターを使って Unicodeで保存し直す

ということをしてみようと思いましたが、Word2007で保存しなおす方法がいまいちわかりません。
またググってみたのですが、Word2007について詳しく書いてあるページが少なくわかりませんでした。

そこで、tkmakwins15さんが教えてくれた
>メニュー→「デバッグ」→「デバッグなしで開始」で実行できないんですよね?

という方法を使ったところ、警告は出なくなりました!


が、実行できません。何でかなぁ?と思っていたら、もうひとつのエラーを見落としていました。
本当に申し訳ありません。

error PRJ0003 : 'rc.exe' の起動中にエラーが発生しました。

というエラーです。

このことについてはここで既出でしたが↓
http://www.play21.jp/board/formz.cgi?action=res&resno=15313&page=&id=dixq%0A&rln=15314

具体的な解決法が出ていなかったので、またまたググってみたのですが、
やはりよくわかりませんでした。

どなたか教えてください。 よろしくお願いします。


422ポイント を手に入れた。

Name: RYU2  ..かけだし(2,194ポイント)   Date: 2008/04/06(日) 22:26   No:15416     
Title: Re:シューティングゲームの館で・・・    
何度もすみません。

今マイクロソフトのサイトで、WindowsSDKというものを見つけたので、
試しにダウンロードしてみます。


48ポイント を手に入れた。

Name: RYU2  ..入門者(2,682ポイント)   Date: 2008/04/07(月) 18:35   No:15426 解決!     
Title: Re:シューティングゲームの館で・・・    
こんばんわ。

ようやくWindowsSDKを入手できました!

入手した後、もう一度

#include "DxLib.h"

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {

ChangeWindowMode(TRUE);

if(DxLib_Init() == -1) return -1;
DrawPixel(240, 240, 0xffff);
WaitKey();
DxLib_End();

return 0;
}


を入力し、「デバッグ開始」をしたところ、うまくいきました!

何故か
warning C4819: ファイルは、現在のコード ページ (932) で表示できない文字を含んでいます。データの損失を防ぐために、ファイルを Unicode 形式で保存してください。

の警告まで出なくなりました。
WindowsSDKは偉大なんだなぁと思いました(笑)

これで自分もVC++を使えます。

質問に答えてくれた皆さん、本当にありがとうございました!


2倍のポイントを手に入れた! 488ポイント を手に入れた。



Name: へろり  ..入門者(3,800ポイント)   Date: 2008/04/03(木) 17:54   No:15330       
Title: 画像の高速なスケーリング・描画    
いつもお世話になっています。

今、画像ビュアを作っています。
そこで、画像をウィンドウサイズに合わせて表示するという機能を実装中なのですが、
ウィンドウサイズをマウスでぐりぐりと変更中に、リアルタイムで拡大・縮小を行いながら、
表示したいと考えています。

しかし、StretchBlt()では実用に耐えれる程の速度が出ません。

デジカメで撮った写真を整理するのに、利便を求めて作っていますのでJPEGに特化した方法でも構いません。
また、IJGが配布しているlibjpegライブラリを利用しています。

速度的にはInternet Explorer程度出ればなと思っています。

どなたか良い知恵をお持ちの方、力をお貸しください。 よろしくお願いします。



234ポイント を手に入れた。


Name: GPGA  ..熟練のプログラマー(43,708ポイント)   Date: 2008/04/04(金) 10:49   No:15350     
Title: Re:画像の高速なスケーリング・描画    
DirectXを使うのはダメですか?

15ポイント を手に入れた。

Name: GPGA  ..熟練のプログラマー(44,029ポイント)   Date: 2008/04/04(金) 15:31   No:15361     
Title: Re:画像の高速なスケーリング・描画    
DirectXを使用したサンプルプログラムを添付しました。

★ イメージビューア
●開発環境
 VS2008 & DirectX9.0c (October 2004)

●操作方法
 ImageViewer.exeを起動後、出現したウインドウに画像をドラッグ&ドロップする。
 ウインドウサイズを変更することで、ウインドウサイズに合わせた拡大縮小を行う。
 Cキーを押すことで、画像の元の大きさに戻る。

●対応フォーマット
 .bmp .dds .dib .hdr .jpg .pfm .png .ppm .tga


143ポイント を手に入れた。

Name: GPGA  ..熟練のプログラマー(44,092ポイント)   Date: 2008/04/04(金) 15:35   No:15362     
Title: Re:画像の高速なスケーリング・描画    
あれ、おかしいなアップできない。容量164kbなんですけど、この容量アウトだったかな?
仕方ないので、こちらにアップしました。


63ポイント を手に入れた。

Name: へろり  ..入門者(4,232ポイント)   Date: 2008/04/05(土) 08:27   No:15373     
Title: Re:画像の高速なスケーリング・描画    
返事が遅れました。

DirectXも考えましたが、扱う画像が当面デジカメで撮影したものをと考えていますので、
サイズが、4000x3000pixなどと平気で行きます。

DirectXだと、サーフェスや、テクスチャのサイズには2の累乗でなければならない等と、
いろいろと制限があったと聞いた記憶があり、ちょっと敬遠してました。

改めて調べて見たのですが、今ひとつ要領を得ません。 実際はどうなんでしょう。

言い忘れていましたが、私の環境はWindows2000で、VisualStudio2003を利用しています。

提示頂いたサンプルですが、実行するとMSVCR90.DLLが無いと怒られ、プロジェクトファイルを開くと
バージョンが違うと怒られてしまいます。

ので、新しくプロジェクトを作成し、ビルドしてみました。
しかし、ファイルをドラッグしても画像が表示されません。
デバッガで追いかけ、DirectX回りの関数呼び出しの戻り値をチェックしてみましたが、
特にエラーを返しているものはありませんでした。

プロジェクトファイルをメモ帳で開いて、それを元に、VisualStudio2003の方でも同じ設定に
しているはずですが、何か注意する点などはあるでしょうか。

DirectXは扱ったことがほとんど無く、3Dに関する知識の持ち合わせも無いもので、色々と
調べてはいるのですが、書かれているコードを追おうにもちょっと、いまいち理解が追いつかない状況です。

よろしくお願いします。


432ポイント を手に入れた。

Name: GPGA  ..熟練のプログラマー(44,901ポイント)   Date: 2008/04/05(土) 16:59   No:15379     
Title: Re:画像の高速なスケーリング・描画    
>しかし、ファイルをドラッグしても画像が表示されません。
DirectX9.0cであれば、どのバージョンでも動くと思いますので
考えられる範囲では、作成しようとしたテクスチャーのサイズがビデオカードの対応サイズより
大きいのかもしれません。まず、小さい画像で表示されるかどうか試してみてください。
ビデオカードが対応しているテクスチャーサイズを確認するときは
m_pD3D->CreateDeviceでデバイスを作成した後に

D3DCAPS9 caps;
m_pDevice->GetDeviceCaps(&caps);
 
を追加し、caps.MaxTextureWidthとcaps.MaxTextureHeightの値を確認してください。

プログラムはテクスチャーの作成と描画周りのみ説明します。
ウインドウの作成とDirectXの初期化についてはリファレンスで調べてください。

まず、扱うサーフェイスやテクスチャが2乗数である必要はありますが
使用する画像そのものが2乗数である必要はありません。
D3DXCreateTextureFromFileExの第5引数に1を与えると、読み込む画像を
テクスチャにするときに、幅と高さを2乗数にし、追加された部分を自動的に黒で埋めてくれます。
たとえば、800x600の画像を読み込んだ場合、テクスチャのサイズは1024x1024となり
横は800dot〜1024dot、縦は600dot〜1024dotの部分を自動的に黒で埋めてくれます。

> hr = m_pTexture->GetLevelDesc(0, &m_Desc);
これは作成したテクスチャーの情報を取得しています。
上記の画像の場合、
m_Desc.Width == 1024
m_Desc.Height == 1024
となります。

>hr = ::D3DXGetImageInfoFromFile(szFileName, &m_Info);
これは読み込む画像の情報を取得しています。
上記の画像の場合、
m_Info.Width == 800
m_Info.Height == 600
となります。


次に描画周りです。
>m_pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 80, 200), 1.0f, 0);
これは、その名の通りバックバッファをクリアするのに使用します。

>m_pDevice->BeginScene();
>m_pDevice->EndScene();
DirectXで描画をする場合、その処理はBeginScene〜EndSceneの中で行う必要があります。

>hr = m_pDevice->Present(NULL, NULL, NULL, NULL);
描画がした内容を実際の画面に反映させています。

一旦切ります。


809ポイント を手に入れた。

Name: GPGA  ..熟練のプログラマー(47,615ポイント)   Date: 2008/04/05(土) 17:42   No:15380     
Title: Re:画像の高速なスケーリング・描画    
>m_pDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
これは、描画する頂点の情報を設定しています。
D3DFVF_XYZRHWは座標を持ち、頂点でデータを定義する構造体に
float x, y, z, rhw;
を入れる必要があります。

D3DFVF_DIFFUSEはディフューズ色成分を持ち、頂点でデータを定義する構造体に
DWORD color
を入れる必要があります。

D3DFVF_TEX1はテクスチャ座標を持ち、頂点でデータを定義する構造体に
float tu, tv
を入れる必要があります。

>const float tu = (float)m_Info.Width / m_Desc.Width;
>const float tv = (float)m_Info.Height / m_Desc.Height;
 
テクスチャの座標は0.0f〜1.0fで扱います。
今回のテクスチャのサイズは1024x1024であり、表示した領域は800x600なので
上記の計算式で、表示するための座標を出しています。


struct VERTEX2D
{
float x, y, z, rhw;
DWORD color;
float tu, tv;
} v[4];
 
これはm_pDevice->SetFVFで設定した内容に基づいた構造体を定義しています。
その後の代入式をバラスと

// 左上の頂点
v[0].x = 0.0f; // X座標
v[0].y = 0.0f; // Y座標
v[0].z = 0.0f; // Z座標
v[0].rhw = 1.0f; // 説明が難しいので割愛
v[0].color = D3DCOLOR_XRGB(255, 255, 255); // 色
v[0].tu = 0.0f; // テクスチャのX座標
v[0].tv = 0.0f; // テクスチャのY座標

// 右上の頂点
v[1].x = (float)m_Info.Width; // X座標
v[1].y = 0.0f; // Y座標
v[1].z = 0.0f; // Z座標
v[1].rhw = 1.0f; // 説明が難しいので割愛
v[1].color = D3DCOLOR_XRGB(255, 255, 255); // 色
v[1].tu = tu; // テクスチャのX座標
v[1].tv = 0.0f; // テクスチャのY座標

// 左下の頂点
v[2].x = 0.0f; // X座標
v[2].y = (float)m_Info.Height; // Y座標
v[2].z = 0.0f; // Z座標
v[2].rhw = 1.0f; // 説明が難しいので割愛
v[2].color = D3DCOLOR_XRGB(255, 255, 255); // 色
v[2].tu = 0.0f; // テクスチャのX座標
v[2].tv = tv; // テクスチャのY座標

// 右下の頂点
v[3].x = (float)m_Info.Width; // X座標
v[3].y = (float)m_Info.Height; // Y座標
v[3].z = 0.0f; // Z座標
v[3].rhw = 1.0f; // 説明が難しいので割愛
v[3].color = D3DCOLOR_XRGB(255, 255, 255); // 色
v[3].tu = tu; // テクスチャのX座標
v[3].tv = tv; // テクスチャのY座標

ここまで書いて気づいたのですが、アップしたソースのrhwが0.0fになっていました。
1.0fが正しい数値ですので、直して置いてください。表示されない原因はこっちかもしれません。(私のほうは、なぜか表示されましたが(汗))


>hr = m_pDevice->SetTexture(0, m_pTexture);
>hr = m_pDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v, sizeof(VERTEX2D));
最後にデバイスにテクスチャーをセットして、三角ストリップ形式で描画をしています。


2倍のポイントを手に入れた! 2,714ポイント を手に入れた。

Name: ま〜く  ..入門者(4,644ポイント)   Date: 2008/04/05(土) 18:47   No:15381     
Title: Re:画像の高速なスケーリング・描画    
気になったので^^;
表示したい画像は数千ピクセルx数千ピクセルなのですよね・・
であれば、重たいのは仕方ない気がします。
で、表示させたい場所、つまりディスプレイの解像度も数千ピクセルx数千ピクセルなのでしょうか?
もし普通の(1024x768,1280x1024,1600x1200くらい?)解像度でしたら数千ピクセルx数千ピクセルを
いっぺんに表示できませんよね。
つまり、表示する情報量としてはディスプレイ解像度だけあれば良い事になりませんか?

メモリDCに表示領域を最大に広げた時の画像を一時的に保持し、それを画面に表示させては如何でしょうか?
ビューアにどのような機能があるか分かりませんが、当然拡大機能を使用する場合などは、そのメモリDCではなく
元の画像情報を使う必要がありますが。


212ポイント を手に入れた。

Name: へろり  ..入門者(4,876ポイント)   Date: 2008/04/06(日) 12:29   No:15403     
Title: Re:画像の高速なスケーリング・描画    
GPGAさん、詳細な情報ありがとうございます。

>考えられる範囲では、作成しようとしたテクスチャーのサイズがビデオカードの対応サイズより
>大きいのかもしれません。まず、小さい画像で表示されるかどうか試してみてください。
>ビデオカードが対応しているテクスチャーサイズを確認するときは
>m_pD3D->CreateDeviceでデバイスを作成した後に

>D3DCAPS9 caps;
>m_pDevice->GetDeviceCaps(&caps);

 
>を追加し、caps.MaxTextureWidthとcaps.MaxTextureHeightの値を確認してください。


>1.0fが正しい数値ですので、直して置いてください。表示されない原因はこっちかもしれません。(私のほうは、なぜか表示されましたが(汗))


結論から言いますと、表示されなかった原因は後者でした。 1.0fと書き直したら無事表示されました。
しかし調べてみましたところ、caps.MaxTextureWidthとcaps.MaxTextureHeight共に1024でした。
これを超えるサイズになりますと、当然1枚のテクスチャで、1枚の画像を保持することが出来ません。
そこで、1枚の画像を複数のテクスチャで分割して保持し、それらを表示するという方法を取ってみましたが、
速度的にちょっと実用に耐えれるものではありませんでした。

多少の画質を落としてでも、画像のロード時に1枚のテクスチャに収まるサイズにスケーリングし、
それを描画して行った方がいいのかなと思案中です。
画像のロードにかかるオーバーヘッドの解決が鍵になりそうです。



ま〜くさん。

>つまり、表示する情報量としてはディスプレイ解像度だけあれば良い事になりませんか?

おっしゃる通りです、当然そのように書いています。
どのみち、描画に関して、デバイスコンテキストの範囲外については何もしなくても勝手にクリップされますので、
全く問題はありません。

>ビューアにどのような機能があるか分かりませんが、当然拡大機能を使用する場合などは、そのメモリDCではなく
>元の画像情報を使う必要がありますが。

さし当たって、まさにここを問題としています。
今、実装しなければならない機能は、指定の範囲(ウィンドウサイズ)に収まるように、画像をスケーリングして、
その全てを描画する。 という機能です。

結局画像全体をスケーリングするには、その画像が持つ全ピクセルを走査しなければならず、これが最大の
ボトルネックとなっています。

私の説明が不十分だったようです。 申し訳ありません。


644ポイント を手に入れた。

Name: ま〜く  ..入門者(4,849ポイント)   Date: 2008/04/06(日) 14:50   No:15404     
Title: Re:画像の高速なスケーリング・描画    
ごめんなさい。まだ良く理解できてないです^^;

>今、実装しなければならない機能は、指定の範囲(ウィンドウサイズ)に収まるように、画像をスケーリングして、
その全てを描画する。 という機能です

との事ですが、表示する情報量に一旦抑えたものを利用しているのですよね?それで遅いのですか?


処理のイメージとして以下のようになると思ったのですが。

1 画像を読み込む(巨大)

2 表示縮尺 == 1.0倍 -> BitBlt

3 表示縮尺 < 1.0 (縮小 今回のお話)

3.1 GetDeviceCapsなどで取得したディスプレイ解像度で作成したメモリDCに一度だけStretchBlt
3.2 メモリDCから画面にStretchBlt
3.3 画面の再描画 −> 3.2 から処理する

4 表示縮尺 > 1.0 (拡大)
4.1 ...
4.2 ...






205ポイント を手に入れた。

Name: へろり  ..初心者(5,336ポイント)   Date: 2008/04/06(日) 15:19   No:15405     
Title: Re:画像の高速なスケーリング・描画    
>との事ですが、表示する情報量に一旦抑えたものを利用しているのですよね?それで遅いのですか?

その通りです。

>処理のイメージとして以下のようになると思ったのですが。

>1 画像を読み込む(巨大)

>2 表示縮尺 == 1.0倍 -> BitBlt

>3 表示縮尺 < 1.0 (縮小 今回のお話)

>3.1 GetDeviceCapsなどで取得したディスプレイ解像度で作成したメモリDCに一度だけStretchBlt
>3.2 メモリDCから画面にStretchBlt
>3.3 画面の再描画 −> 3.2 から処理する

現在の実装は概ね、この通りで間違いありませんが、正確には、メモリDCから画面へはBitBlt()で行います。
すでに、3.1でスケーリング処理は行われているので、3.2でまた行う必要も無いという判断です。

ここで、ボトルネックになる部分はStretchBlt()です。

上記の手順で、3の処理を行うのに私の環境では体感で約0.3秒ほどかかります。
これでは使い物にならないのです。

ウィンドウサイズが固定ならばこれでもいいのですが、ウィンドウサイズの変更中(ウィンドウのフレームをマウスでぐりぐりしている)では、致命的な重さとなります。

そして、その処理にかかる時間の内そのほとんどが、3.1の処理に割かれています。
ですから、このStretchBlt()に替わる高速なスケーリング処理を模索中というわけでした。



460ポイント を手に入れた。

Name: へろり  ..初心者(5,636ポイント)   Date: 2008/04/06(日) 15:27   No:15406     
Title: Re:画像の高速なスケーリング・描画    
ちょっと訂正します。

スケーリングアルゴリズムそのものを探しているのではなく、スケーリング処理を含めた総合的な処理方法を、ということで。

例えば、画像をロード時に、平均的なウィンドウサイズにフィットする画像を別スレッドで生成し、
拡大縮小時には、これをベースとして行う。 等でも構いません。

力をお貸しください。


2倍のポイントを手に入れた! 300ポイント を手に入れた。

Name: ま〜く  ..初心者(5,017ポイント)   Date: 2008/04/06(日) 18:22   No:15414     
Title: Re:画像の高速なスケーリング・描画    
>現在の実装は概ね、この通りで間違いありませんが、正確には、メモリDCから画面へはBitBlt()で行います。
すでに、3.1でスケーリング処理は行われているので、3.2でまた行う必要も無いという判断です。

ウィンドウのリサイズに対応するためには3.2でStretchBltが必要だと思うのですが認識間違ってますか?

>そして、その処理にかかる時間の内そのほとんどが、3.1の処理に割かれています。

3.1は一度だけ処理するものなので、初回表示時だけ重くなる感じで考えていました。



168ポイント を手に入れた。

Name: へろり  ..初心者(5,770ポイント)   Date: 2008/04/07(月) 09:07   No:15421     
Title: Re:画像の高速なスケーリング・描画    
>ウィンドウのリサイズに対応するためには3.2でStretchBltが必要だと思うのですが認識間違ってますか?

>>そして、その処理にかかる時間の内そのほとんどが、3.1の処理に割かれています。

>3.1は一度だけ処理するものなので、初回表示時だけ重くなる感じで考えていました。

なるほど、ようやくおっしゃりたい事が分かりました。
3.2での処理速度を稼ぐために、便宜的に表示するに考え得る最大のサイズをあらかじめ3.1で作っておく
という事ですね。



134ポイント を手に入れた。

Name: ま〜く  ..初心者(5,111ポイント)   Date: 2008/04/07(月) 10:44   No:15423     
Title: Re:画像の高速なスケーリング・描画    
>なるほど、ようやくおっしゃりたい事が分かりました。
3.2での処理速度を稼ぐために、便宜的に表示するに考え得る最大のサイズをあらかじめ3.1で作っておく
という事ですね。


説明が足りなかったようですみません^^;

あとは、読み込みや3.1の処理を別スレッドで処理するなどして、アプリ自体の重みを感じさせないようにすれば良いかと思います。


94ポイント を手に入れた。



Name: オプーナを買う権利を授けよう  ..ぴよぴよ(132ポイント)   Date: 2008/04/06(日) 02:19   No:15392       
Title: 構造体の初期化について    
追記
MapImage[0].x等はまだ単に初期化してるだけで特に意味はありません。
この構造体の初期化ができないと次にすすめないので
イメージとしては管理人さんのページにあったのはマップが固定でキャラクターが歩いていましたが、相対的にみるとキャラクターを画面中央に固定して背景を逆方向に動かす(例:ロックマン、マリオの動き方)ということをやろうとしています。
よろしくお願いします。


1ポイント を手に入れた。


Name: 管理人 [URL]  ..伝説のハッカー(549,503ポイント)   Date: 2008/04/06(日) 02:22   No:15394     
Title: Re:構造体の初期化について    
追記っていうのはどこの追記ですか??

2倍のポイントを手に入れた! 30ポイント を手に入れた。

Name: オプーナを買う権利を授けよう  ..かけだし(1,316ポイント)   Date: 2008/04/06(日) 02:31   No:15395     
Title: Re:構造体の初期化について    
うわぁ
送信したはずなのに入ってない><
長いのはだめなんですかね?
分けます



管理人さんのまね
//壁2次元配列
//0=床,1=壁,2=机,3,4=ベッド,10=部屋移動用入り口
int kabe1[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,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,0,0,0,0,0,0,1 },
{ 1,0,0,0,0,0,0,0,2,2,2,0,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,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,0,0,0,0,0,0,1 },
{ 1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 },
{ 1,0,0,4,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,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,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,1,1,1,1,1,1,1,10,10,1,1,1,1,1,1,1,1,1,1 },
};
//構造体
typedef struct{
int x,y;//マップ左上の位置
int image[75][100];//マップ画像格納用
} MAP_IMAGE;

MAP_IMAGE MapImage[1];//将来性を考えて配列で宣言
初期化
void Initiarize()
{
    MapImage[0].x=0;
MapImage[0].y=0;
int l=0;
while(l<75){
int m=0;
while(m<100){
if(l==0 || l==74 || m == 0 || m == 99){
MapImage[0].image[l][m]=1;
}
else if(l == 1 && m == 1){
MapImage[0].image[l][m]=10;
}
else {
MapImage[0].image[l][m] = 0;
}
m++;
}
l++;
}
}
エラー

1>.\Country.cpp(48) : error C2109: 配列または、ポインタでない変数に添字が使われました。
1>.\Country.cpp(51) : error C2109: 配列または、ポインタでない変数に添字が使われました。
1>initiarize.cpp
1>.\initiarize.cpp(33) : error C2109: 配列または、ポインタでない変数に添字が使われました。
1>.\initiarize.cpp(36) : error C2109: 配列または、ポインタでない変数に添字が使われました。
1>.\initiarize.cpp(39) : error C2109: 配列または、ポインタでない変数に添字が使われました。



一部カットしてみたんでもしかしたらこのままコンパイルできるかどうかは未確認です。
↑のようなエラーがでて構造体を初期化できませんでした。
MapImage[0].image[l][m]=1;このような使い方はできないのでしょうかね?


1,184ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(549,685ポイント)   Date: 2008/04/06(日) 03:06   No:15396     
Title: Re:構造体の初期化について    
>MapImage[0].x等はまだ単に初期化してるだけで特に意味はありません。

グローバル変数は宣言するだけで初期化されますよ。
ローカル変数は初期化せずに使うとおかしなことになりますが、グローバル変数はそのまま使えます。
ただ、ゲームを作る上で、変数を初期化するのはもちろん必要なので、初期化関数を作るのは適切です。
なお、構造体の初期化はmemsetを使うと一行で初期化できるので便利ですよ。

本題ですが、
MapImage[0].image[l][m]=1;
これは出来ますよ。
どこか違うところでエラーが出てるんじゃないでしょうか?


182ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(550,363ポイント)   Date: 2008/04/06(日) 03:12   No:15397     
Title: Re:構造体の初期化について    
以下、このプログラムでは普通にコンパイル通りますよね?


#include <stdio.h>

typedef struct{
int x,y;//マップ左上の位置
int image[75][100];//マップ画像格納用
} MAP_IMAGE;
MAP_IMAGE MapImage[1];//将来性を考えて配列で宣言

int main(){
MapImage[0].x=0; MapImage[0].y=0;
int l=0;
while(l<75){
int m=0;
while(m<100){
if(l==0 || l==74 || m == 0 || m == 99){
MapImage[0].image[l][m]=1;
}
else if(l == 1 && m == 1){
MapImage[0].image[l][m]=10;
}
else {
MapImage[0].image[l][m] = 0;
}
m++;
}
l++;
}
return 0;
}


なお、コードを投稿する時は、<pre>と</pre>タグで囲んで投稿お願いします。(<>は半角)

こういう違いがあります。

プレタグを使わなかったとき

if(a==2){
for(i=0;i<10;i++){
if(b==2){
printf("a");
}
}
}

使ったとき


if(a==2){
for(i=0;i<10;i++){
if(b==2){
printf("a");
}
}
}
 

文字数制限はありますが、もし投稿できなかった時は「文字数が多すぎて投稿できません」のような画面が出るはずです。
よほどかなりの量でなければ制限はかからないと思いますが、とても多い時は、参照からソースコードを添付していただければと思います。


678ポイント を手に入れた。

Name: box  ..ハッカー(109,335ポイント)   Date: 2008/04/06(日) 06:43   No:15398     
Title: Re:構造体の初期化について    
> エラー
>
> 1>.\Country.cpp(48) : error C2109: 配列または、ポインタでない変数に添字が使われました。
> 1>.\Country.cpp(51) : error C2109: 配列または、ポインタでない変数に添字が使われました。
> 1>initiarize.cpp
> 1>.\initiarize.cpp(33) : error C2109: 配列または、ポインタでない変数に添字が使われました。
> 1>.\initiarize.cpp(36) : error C2109: 配列または、ポインタでない変数に添字が使われました。
> 1>.\initiarize.cpp(39) : error C2109: 配列または、ポインタでない変数に添字が使われました。

上記エラーメッセージで、カッコの中の数値は当該ファイルの何行目で
エラーが出ているかを示しています。
当該ファイルの当該行の内容を見せてください。


59ポイント を手に入れた。

Name: オプーナを買う権利を授けよう  ..かけだし(1,629ポイント)   Date: 2008/04/06(日) 09:23   No:15401 解決!     
Title: Re:構造体の初期化について    
>管理人さん
そのまま実行してみると
1>LIBCMTD.lib(wincrt0.obj) : error LNK2019: 未解決の外部シンボル _WinMain@16 が関数 ___tmainCRTStartup で参照されました。
というエラーがでました><
DXLibをインクルードしてメインの中に入れるとエラーは出ませんでした

>box
エラーの位置はすべてMapImage[0].image[l][m]=
の形の位置です。

すみません、今いじってたらできました
原因はextern宣言の中身で

typedef struct{

int x,y;//マップ左上の位置

int image[75];//マップ画像格納用

} MAP_IMAGE;

extern MAP_IMAGE MapImage[1];

となっていたことが原因でした
お騒がせしました
ありがとうございました。


313ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(550,487ポイント)   Date: 2008/04/06(日) 17:55   No:15412     
Title: Re:構造体の初期化について    
私が先ほど書いたプログラムはコンソールアプリケーションのプロジェクトじゃないとコンパイルできないので、
int mainで始まるプログラムを書く、DXライブラリじゃないプロジェクトでコンパイルしていただく事を想定していました。
恐らくそちらでやってもらったら出来たと思いますが、解決したようなので、もう必要ないですねm(_ _)m


124ポイント を手に入れた。

Name: オプーナを買う権利を授けよう  ..かけだし(1,795ポイント)   Date: 2008/04/06(日) 23:38   No:15417     
Title: Re:構造体の初期化について    
>管理人さん
設定いじるとうわぁってことになりそうだったので><

マリオみたいに動かすって内容の続きなんで新しくスレッドたてなかったんですが、このCountry1()で実現したいのです(添付ファイル
使ってる関数はコメントアウトでつけたしてあります
これを実行すると目に見える障害物の位置と実際にぶつかる位置が3ますずれてしまってるのですが、何か原因わかりますでしょうか?

画像表示のためしにiにi+3を入れて表示させてみると障害物の位置と画像表示の位置は一致しましたがなんでそうなってしまったのかがわからないんです・・・
よろしくおねがいします。


166ポイント を手に入れた。



Name: tkmakwins15 [URL]  ..比類無きプログラマー(67,318ポイント)   Date: 2008/04/06(日) 15:57   No:15407       
Title: ファイルとディレクトリの判別    
C++でWindows APIを操作しているのですが、コマンドラインから渡されたパスがファイル名なのかそれともディレクトリ名なのか判別する方法はあるのでしょうか?

拡張子の有無だけでは、ディレクトリ名に.が含まれていた場合誤動作を引き起こしてしまいます。なので、それ以外の判別法をご教授お願いします。


119ポイント を手に入れた。


Name: Justy  ..ハッカー(185,625ポイント)   Date: 2008/04/06(日) 16:21   No:15408     
Title: Re:ファイルとディレクトリの判別    
 GetFileAttributes()とか GetFileAttributesEx()でファイルの属性を確認すればいいかと。


35ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..比類無きプログラマー(67,400ポイント)   Date: 2008/04/06(日) 16:24   No:15409 解決!     
Title: Re:ファイルとディレクトリの判別    
Justyさん、回答ありがとうございます。

「"ファイルとディレクトリの判別"」でググっても全然出てこなかったので、質問させていただきました。
ありがとうございました。


82ポイント を手に入れた。

Name: Justy  ..ハッカー(185,688ポイント)   Date: 2008/04/06(日) 17:33   No:15410     
Title: Re:ファイルとディレクトリの判別    
 Win32 とか API とかも検索ワードに追加するとそれなりに出てきますよ。

「Win32 ファイル ディレクトリ 判別」

 とか。


63ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..比類無きプログラマー(67,424ポイント)   Date: 2008/04/06(日) 17:41   No:15411     
Title: Re:ファイルとディレクトリの判別    
アドバイスありがとうございます。今度からの検索の時の参考にさせていただきます。

24ポイント を手に入れた。



Name: ほにゃー  ..ぴよぴよ(627ポイント)   Date: 2008/04/05(土) 21:51   No:15383       
Title: マウスポインタについて    
どうも、ほにゃーというものです。

現在マウスを使用するシューティングゲームを作成しているのですが、
どうしてもわからない問題があるのです。

ゲームをウィンドウモードで起動し、ゲームをプレイします。
前述のとおりマウスを用いたシューティングゲームですので、
激しくマウスを動かすことになります。
その際、ゲーム画面からマウスポインタが飛び出してしまい、
画面外でマウスをクリックするとゲームが中断されてしまうのです。
このようにならないよう

"ゲームを起動中はゲームウィンドウからマウスポインタが外に出ないようにしたい"

のですが、いろいろ調べてみたのですがどうにも解決できませんでした。
どなたか知恵をお貸しください。


使用コンパイラ
VC++2005ExpressEdition


196ポイント を手に入れた。


Name: Justy  ..ハッカー(184,782ポイント)   Date: 2008/04/05(土) 22:49   No:15384     
Title: Re:マウスポインタについて    
 GetCursorPos()で位置を取得して、座標をチェック。
 範囲外にあるなら SetCursorPos()でマウスカーソルがウインドウから出ないようにすれば
いいんじゃないでしょうか。


79ポイント を手に入れた。

Name: ほにゃー  ..ぴよぴよ(688ポイント)   Date: 2008/04/06(日) 08:03   No:15399 解決!     
Title: Re:マウスポインタについて    
ありがとうございました!

GetCursorPos()なんて関数があったとは知りませんでした。
そこからいろいろと調べていき、解決することができました!


61ポイント を手に入れた。



Name: 大工  ..プログラマー(27,048ポイント)   Date: 2008/04/04(金) 20:33   No:15365       
Title: C++ オブジェクト指向    
http://www.geocities.jp/turtle_wide/java/javalect/out07.htm

このサイトでオブジェクト指向について勉強してたんですがオブジェクト指向はどう考えてもC言語で関数を使ってmain関数で呼び出してることと同じ風に取れて混乱しています。。。

どこがどう違うのでしょうか・・・・?

こんな投稿でも大丈夫・・・・ですよね???


2倍のポイントを手に入れた! 244ポイント を手に入れた。


Name: バグ  ..比類無きプログラマー(80,123ポイント)   Date: 2008/04/04(金) 22:02   No:15366     
Title: Re:C++ オブジェクト指向    
私も最初はそう思ってました。
しかし、実際にクラスを使用して組んでいくうちに、『あぁ、こういう事か!』とおぼろげながら分かってきたんですよ。
オブジェクト指向ってのは、乱暴な言い方をすれば『使い回しのできるものは再利用して(というよりも、使い回しのきくパーツを作って)、楽にコーディングしましょう』というものだと思います。
試しに全てのメンバ変数をprivateにしてクラスを作ってみて下さい。そうすれば、パーツという意味が分かると思いますよ(^-^)


153ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..比類無きプログラマー(67,021ポイント)   Date: 2008/04/05(土) 14:55   No:15376     
Title: Re:C++ オブジェクト指向    
オブジェクト指向と聞くと、かなり難しい気がしますが、そんなに難しくもありませんよ。

処理の過程で必要になるモノを、箱の中に必要なデータの類は詰め込んで、提供されたリモコンで操作するような感じで捉えて行くと分かり易いと思います。

結局、処理の中でモノを扱うわけなので、C言語のようなオブジェクト指向プログラムもできるのです。


2倍のポイントを手に入れた! 268ポイント を手に入れた。

Name: 大工  ..プログラマー(27,122ポイント)   Date: 2008/04/05(土) 19:40   No:15382     
Title: Re:C++ オブジェクト指向    
バグさん

>メンバ変数をprivate・・・

なるほど!この言葉で全てが開けました!ありがとうございます。


tkmakwins15さん

そこまでは知ってたんですけど, 関数と同義で扱っていたので混乱してました。


74ポイント を手に入れた。



Name: bodomcross  ..ぴよぴよ(81ポイント)   Date: 2008/04/04(金) 11:18   No:15354       
Title: クラス+DxLibに関して    
はじめまして、いつも参考にさせていただいています

質問なのですが、

C++なので投稿違いかもしれませんが、

プレイヤー操作クラスなどでのコンストラクタでLoadDivGraphを使うと

実行できるのですが、ウィンドウが出てきませんがどうしてでしょう?

今はPlayer::Load を定義して別に操作しています

また、コンストラクタで画像を読み込もうとするのは間違いなのでしょうか?

ご教授お願いします


81ポイント を手に入れた。


Name: GPGA  ..熟練のプログラマー(43,886ポイント)   Date: 2008/04/04(金) 11:21   No:15357     
Title: Re:クラス+DxLibに関して    
DxLib_Init()を呼ぶ前に、LoadDivGraphを呼んでいませんか?

21ポイント を手に入れた。

Name: bodomcross  ..ぴよぴよ(203ポイント)   Date: 2008/04/04(金) 22:06   No:15367     
Title: Re:クラス+DxLibに関して    
GPGAさんの言われたとおりDxLib_Init()を呼ぶ前にコンストラクタを呼んでました(汗

クラスの中にクラスを宣言している分、プログラムが解りににくくなり

トレースが出来ていなかったことを実感いたしました

今後もこの経験が役立ちそうです

ありがとうございました


122ポイント を手に入れた。



Name: 名無し  ..入門者(4,411ポイント)   Date: 2008/04/04(金) 18:55   No:15364       
Title: 構造体宣言について    
度々すみません。
キャラデータを構造体で宣言しようとしているのですが、
シューティングの館の6節のように書いたつもりなのですが、エラーが
たくさん出てきます。ご指摘をお願いします。
エラー内容↓

Extern_etc.h 13: 'chara_data' の宣言が複数見つかった
global_define.h 11: 一つ前の 'chara_data' の定義位置
Extern_etc.h 15: 'syuyaku' の再宣言で型が一致していない
global_define.h 14: 一つ前の 'syuyaku' の定義位置
Extern_etc.h 13: 'chara_data' の宣言が複数見つかった
Extern_etc.h 13: 一つ前の 'chara_data' の定義位置
Extern_etc.h 15: 'syuyaku' の再宣言で型が一致していない
global_define.h 14: 一つ前の 'syuyaku' の定義位置
Extern_etc.h 13: 'chara_data' の宣言が複数見つかった
Extern_etc.h 13: 一つ前の 'chara_data' の定義位置
Extern_etc.h 15: 'syuyaku' の再宣言で型が一致していない
global_define.h 14: 一つ前の 'syuyaku' の定義位置

ヘッダファイルの中身↓

----global_define.h----

int scene=0;
int chara_img[96];
int keybuf[256];
int white;
int str1,str2;
int y=260;

typedef struct{
int x,y;
int img[12];
}chara_data;


chara_data syuyaku;


----Extern_etc.h----

extern int scene,str1,str2;
extern int white;
extern int y;
extern int chara_img[96];
extern int keybuf[256];
extern void start(void);
extern void key_check(int key[]);
extern void field(void);

typedef struct{
int x,y;
int img[12];
}chara_data;

extern chara_data syuyaku;





613ポイント を手に入れた。




Name: kazuoni  ..初心者(7,192ポイント)   Date: 2008/04/03(木) 23:32   No:15333       
Title: 文字列について    
お邪魔します。基礎的なところで躓きました。まず構造体で、

typedef struct{
char name;//後に変数の数を増やしていくつもりです
}charname_t;

と宣言し、
charname_t charname[10];

として、charname[0]のなかにひらがな、カタカナ、漢字の文字列を格納したいのですが、まず配列の中に英数字以外のものって入れれるんですか?あと、charname[0]="キャラ"なんてやるとまずいですよね?

自分がやりたいこととしては、この構造体+配列でゲーム中に出てくるすべての文字列(キャラ名や武器名、防具名等)を扱いたいと考えています。

初歩的な質問ですみません。。
言語の参考書っというのはやはり持っていて、一度すべて頭に叩き込んだほうがよいでしょうか^^;なんだか頭に入ってすぐ抜けてしまいそうな気がしますが・・・(汗)
まず今すぐ役に立つのがCなのか、C++なのかよくわかりません^^;今まではだいたいHPめぐりで答えを見つけてきたのですが・・・ポインタはどのページを見てもあいまいにしかわかりませんでした。。文字列についても同様です。。もしよろしければ、この本&HPはおススメっというのがありましたら教えていただけないでしょうか?
よろしくお願いします。


544ポイント を手に入れた。


Name: 管理人 [URL]  ..伝説のハッカー(548,876ポイント)   Date: 2008/04/04(金) 00:20   No:15334     
Title: Re:文字列について    

宣言と同時にだけできるわざは

char str[64]="ハローワールド";

こうです。でも、一度宣言してしまうと

char str[64];
str = "ハローワールド";

こうは出来ません。宣言した後に入れるときは、コピー関数を使います。
strcpyと言う関数です。

strcpy(@,A);

@=コピー先の配列、A=コピーしたい文字列
です。つまりstrという配列に文字をいれたければ

strcpy(str,"ハローワールド");

となります。

char str[64],str2[64] = "ハローワールド";
strcpy(str,str2);

でも同じ結果になります。この関数を使う時は最初にstring.hをインクルードする必要があります。
気をつけるべきは、全角は1文字で2バイト使用します。
そして文字列の最後には終端記号が1バイト入ることから、
文字列の2倍+1バイト要素が必要です。つまり

char str[7]="バイト";

のように、必要となる最小要素数は文字数X2+1この場合7なのです。
コピー先の配列がコピーするのに十分な領域を確保している事に注意が必要です。

サンプルを書いたので実行してみて下さい。


#include <stdio.h>
#include <string.h>

int main(){
char str[64],str2[64]="バイト";

strcpy(str,"ハローワールド");
printf("%s\n",str);

strcpy(str,str2);
printf("%s\n",str);

return 0;
}

実行結果

ハローワールド
バイト
 




413ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(548,926ポイント)   Date: 2008/04/04(金) 00:23   No:15335     
Title: Re:文字列について    
まず、標準関数としてどんなものがあるのか一通り見てみるのがいいでしょう。

http://always-pg.com/c/runtime_rd/

この辺とか用途別で確認できるので便利です。


50ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..比類無きプログラマー(66,724ポイント)   Date: 2008/04/04(金) 00:29   No:15336     
Title: Re:文字列について    
そもそも、文字列はchar型の配列で扱います。「ABC」という文字列を配列に格納するには、

char abc[4];
abc[0]='A';
abc[1]='B';
abc[2]='C';
abc[3]='\0';

のようにします。初期化であれば、

char abc[4]={"ABC"};

でもいけます。

文字列を本格的に扱いたいのであれば、C言語の配列、ポインタあたりを知っておく必要があります。
参考になりそうなURLを載せときます。

http://homepage3.nifty.com/mmgames/c_guide/
http://www9.plala.or.jp/sgwr-t/index.html


220ポイント を手に入れた。

Name: オプーナを買う権利を授けよう  ..ぴよぴよ(212ポイント)   Date: 2008/04/04(金) 02:34   No:15337     
Title: Re:文字列について    
うわぁ
ワタシもスレ主さんと同じ勘違いしてました><
つまり
char str[64];

str = "ハローワールド";

これしてました

助かりました〜


4ポイント を手に入れた。

Name: 名無し  ..入門者(3,798ポイント)   Date: 2008/04/04(金) 06:38   No:15338     
Title: Re:文字列について    
#include <stdio.h>

int main(){
char *str;
str="ああ";
printf("%s\n",str);
return 0;
}

これじゃダメなんですか?


41ポイント を手に入れた。

Name: フリオ  ..上級者(22,393ポイント)   Date: 2008/04/04(金) 08:10   No:15339     
Title: Re:文字列について    
> char abc[4]={"ABC"};
> でもいけます。

 これは、"abc"というcha型の配列を、
"ABC"という文字列の先頭のポインタ(char)で
初期化していることになるので、

char abc[4] = "ABC";
または、
char abc[4] = {'A', 'B', 'C', '\0'};

とすべきではないでしょうか。
 

> char *str;
> str="ああ";
> これじゃダメなんですか?

char str[5] = "ああ";
と、
char *str = "ああ";
は、意味が違います。
前者は、char型の配列"str"を、"ああ"という値で初期化していますが、
後者は、Char型へのポインタ型の変数"str"を、
"ああ"という文字列の先頭のポインタで初期化しています。
ですから、sizeof(str)は、
前者は、sizeof(char) * 5を返しますが、
後者は、sizeof(char *)を返します。
 





2倍のポイントを手に入れた! 294ポイント を手に入れた。

Name: フリオ  ..上級者(22,429ポイント)   Date: 2008/04/04(金) 08:15   No:15340     
Title: Re:文字列について    
 
 訂正
文字列の先頭のポインタ(char) -> 文字列の先頭のポインタ(char *)
 


36ポイント を手に入れた。

Name: box  ..ハッカー(109,043ポイント)   Date: 2008/04/04(金) 08:18   No:15341     
Title: Re:文字列について    
> char *str;
> str="ああ";
>
> これじゃダメなんですか?

ダメではありません。char型へのポインタを使った、
正しいプログラムです。

char型の配列とは意味合いが異なるだけです。


47ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..比類無きプログラマー(66,753ポイント)   Date: 2008/04/04(金) 08:57   No:15342     
Title: Re:文字列について    
>フリオさん

あー、ミスってました。{}いりませんね。


29ポイント を手に入れた。

Name: やそ  ..プログラマー(37,832ポイント)   Date: 2008/04/04(金) 09:21   No:15343     
Title: Re:文字列について    
> char *str;
> str="ああ";
>
> これじゃダメなんですか?

ほほぉ、この形の代入はあまり使った記憶がないので新鮮でした(笑)
ポインタ変数に直接文字列をぶち込むのか。うむ、お勉強になりますね^^
ん?この場合'\0'はつかないの?


2倍のポイントを手に入れた! 94ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(79,936ポイント)   Date: 2008/04/04(金) 09:49   No:15344     
Title: Re:文字列について    
>> char *str;
>> str="ああ";

この場合、"ああ"の為に確保された領域というのはどのタイミングで解放されるんでしょうか?
やはりmain関数が終了した段階での解放になるんですか?
となると、少々のデータならばともかく、あまりに大量なデータになってくると、マズイ事になったりしないのかなぁ…とか思うんですが…


138ポイント を手に入れた。

Name: YuO  ..上級者(18,878ポイント)   Date: 2008/04/04(金) 09:51   No:15345     
Title: Re:文字列について    
>> char *str;
>> str="ああ";
> ん?この場合'\0'はつかないの?

付いていますよ。
上記の式は,例えば実行時にShift_JISをエンコーディングとする処理系においては,
char *str;

static char __\u3042\u3042[] = { 0x82, 0xA0, 0x82, 0xA0, 0x00 }; // \u3042 : あ
str = __\u3042\u3042;

と同じですから。


あと,@15334
> char str[7]="バイト";
はダメです。
strlen("バイト")が6を返すとは限りません。
実行拡張文字集合の多バイト文字の表現方式 (実行時エンコーディング) がUTF-8の場合,9を返すことでしょう。
char str[] = "バイト";

と,[]内はコンパイラに任せた方が賢いです。


182ポイント を落としてしまった。

Name: box  ..ハッカー(109,085ポイント)   Date: 2008/04/04(金) 09:52   No:15346     
Title: Re:文字列について    
くだんの例では、文字列終端の'\0'を含めた5バイトを、
どこかのエリアに確保します。
char *型のstrには、その「どこかのエリア」の先頭アドレスが入ります。


42ポイント を手に入れた。

Name: Mist  ..かけだし(1,033ポイント)   Date: 2008/04/04(金) 10:08   No:15347     
Title: Re:文字列について    
> どこかのエリアに確保します。
私の知る限りではプログラムエリアに確保されます。(exeに埋め込まれている)
なので、間違って書き換えないようにするために

const char *str = "ああ";

としています。


59ポイント を手に入れた。

Name: box  ..ハッカー(109,192ポイント)   Date: 2008/04/04(金) 10:27   No:15348     
Title: Re:文字列について    
くだんのstrが別の領域を指すようにすることは可能です。

char *str;
str = "12345";
/* strを使った何かの処理 */
str = "abcde";
/* また別の処理 */

というわけで、何が何でもconstでなければならない、
ということはありません。
もちろん、プログラムの仕様上constにする必要があれば、
別の話です。


107ポイント を手に入れた。

Name: kazuoni  ..初心者(7,359ポイント)   Date: 2008/04/04(金) 10:43   No:15349     
Title: Re:文字列について    
朝起きてものすごい返信があってびっくりしましたwなんだかいろいろ書かれすぎて要点が絞りきれてませんが^^;コピー関数についてはなんとなくわかりました!ありがとうございます^^

管理人さんの書いてくれたコードなんですが、strでは、

str[0]→ハ
str[1]→ロ
str[2]→ー
str[3]→ワ
....

となっていますよね?
これを

str[0]→ハローワールド0
str[1]→ハローワールド1
str[2]→ハローワールド2
str[3]→ハローワールド3

のようにしたいのですが・・・。これはできないでしょうか?


167ポイント を手に入れた。

Name: Mist  ..かけだし(1,169ポイント)   Date: 2008/04/04(金) 10:49   No:15351     
Title: Re:文字列について    
私がconstつけるようにしているのはstrに格納されるアドレスを変えないようにするためではなく
"ああ"のエリアが書き換えられないようにするためです。

const char *str = "ああ";
str[0]='a';

これはコンパイルエラーになる。
プログラムエリアを書き換えるのはご法度ですから、そういったミスコーディングがコンパイル
で見つけられるようにするための一つの手段です。


136ポイント を手に入れた。

Name: GPGA  ..熟練のプログラマー(43,865ポイント)   Date: 2008/04/04(金) 11:05   No:15352     
Title: Re:文字列について    
まず文字リテラルは、boxが書いたようにどこかのエリアに
展開されるのであって、展開先がプログラムエリアになるかどうかは、
コンパイラの仕様になると思います。

>const char *str = "ああ";
>str[0]='a';
>プログラムエリアを書き換えるのはご法度ですから
ダメなのは、言語仕様で文字リテラルに対する書き込みが未定義動作だからです。


157ポイント を手に入れた。

Name: Mist  ..かけだし(1,244ポイント)   Date: 2008/04/04(金) 11:18   No:15353     
Title: Re:文字列について    
> str[0]→ハ
> str[1]→ロ
> str[2]→ー
> str[3]→ワ
> となっていますよね?
なってません。
管理人さんのレスをよく読みなおしてください。
>> 気をつけるべきは、全角は1文字で2バイト使用します。
この辺り。

> str[0]→ハローワールド0
> str[1]→ハローワールド1
> str[2]→ハローワールド2
> str[3]→ハローワールド3
> のようにしたいのですが・・・。これはできないでしょうか?
2次元配列を使えば出来ます。

char str[][64] = { "ハローワールド0", "ハローワールド1", "ハローワールド2", "ハローワールド3" };


75ポイント を手に入れた。

Name: YuO  ..上級者(19,276ポイント)   Date: 2008/04/04(金) 11:19   No:15355     
Title: Re:文字列について    
@15347
>> どこかのエリアに確保します。
> 私の知る限りではプログラムエリアに確保されます。(exeに埋め込まれている)

どこにリテラルを確保するかは規格で定められていません。
ISO/IEC 9899:1999 6.4.5のString literalsに,
> The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence.
と定めがあるのみです。
# なので,static char __\u3042\u3042[]のような記述にした。


@15349
> これを
> str[0]→ハローワールド0
> str[1]→ハローワールド1
> str[2]→ハローワールド2
> str[3]→ハローワールド3
> のようにしたいのですが・・・。これはできないでしょうか?

文字と文字列の違いを勉強しましょう。
charは「文字」を扱うためのものです。
文字列を扱うにはcharの配列 (or char *)を使います。

ここでは文字列を複数扱いたいわけですから,文字列の配列が必要になります。
const char * str[] = { "ハローワールド0", "ハローワールド1", "ハローワールド2", "ハローワールド3" };

のようにすればよいです。
# 文字列リテラルの変更は未定義動作なので,それを避けやすくするためにchar *の配列ではなくconst char *の配列としている。


2倍のポイントを手に入れた! 398ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(79,970ポイント)   Date: 2008/04/04(金) 11:20   No:15356     
Title: Re:文字列について    
>>kazuoniさん
できますよ。char型の配列ではなく、char型へのポインタの配列に変更すれば動くはずです。


34ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(549,123ポイント)   Date: 2008/04/04(金) 13:38   No:15358     
Title: Re:文字列について    
>YUOさん、

>>>char str[7]="バイト";
>はダメです。
>strlen("バイト")が6を返すとは限りません。
>実行拡張文字集合の多バイト文字の表現方式 (実行時エンコーディング) がUTF-8の場合,9を返すことでしょう。

そうでしたか、失礼しました。


>Kazuoniさん

str[0]→ハ
str[1]→ロ
str[2]→ー
str[3]→ワ

ではなく、

str[0]→ハ
str[2]→ロ
str[4]→ー
str[6]→ワ

です。全角1文字は2バイトで表現するので。
では要素一つ分に何が入ってるの?と思うかもしれませんが、2つの領域のデータを使って一つの文字を表現しているので、要素一つのデータだけでは意味不明な値になります。


197ポイント を手に入れた。

Name: box  ..ハッカー(109,276ポイント)   Date: 2008/04/04(金) 14:01   No:15359     
Title: Re:文字列について    
>str[0]→ハ
>str[2]→ロ
>str[4]→ー
>str[6]→ワ

もっと正確に、

str[0], str[1]→ハ
str[2], str[3]→ロ
str[4], str[5]→ー
str[6], str[7]→ワ

と書く方が、ある種の環境においては
いわゆる全角文字1文字分のために
2バイトの領域が必要であることが
よりはっきりすることでしょう。


84ポイント を手に入れた。

Name: kazuoni  ..初心者(7,466ポイント)   Date: 2008/04/04(金) 15:23   No:15360 解決!     
Title: Re:文字列について    
皆様からしたら単純すぎる質問にご回答いただき本当にありがとうございました。

今回の部分は理解&解決できました!

文字と文字列の違い等まだまだ理解できていないので、きちんと基礎つんできます^^;

本当にありがとうございました^^

またよろしくお願いします。


107ポイント を手に入れた。



Name: そら  ..かけだし(1,515ポイント)   Date: 2008/04/03(木) 11:56   No:15319       
Title: ポインタが分かりません    

ポインタが苦手で、解決法が分かりません。
どなたか、力を貸して下さい。

以下、サンプルです。

#include "stdio.h"
#include "string.h"

typedef struct {
int a;
int b;
char c[32];
} DATA_T;

void Code001();
void Code002();
int Code003(DATA_T *tData1, DATA_T *tData2);

DATA_T tData[10];

void Code001()
{
int i;

memset(&tData, 0, sizeof(tData));
for(i=0;i<5;i++){
tData[0].a = 1;
}

return;
}
void Code002()
{
DATA_T *tData1 = NULL;

if( 0 == Code003(tData1, &tData[0]) ){
printf("1-%08x\n", tData1);
printf("2-%08x\n", &tData); // ---(1)
}

return;
}
int Code003(DATA_T *tData1, DATA_T *tData2)
{
int i;

for(i=0;i<10;i++){ // ---(2)
if( tData2->a == 0 ){
tData1 = tData2; // ---(3)
return (0);
}
tData2++;
}

return (1);
}
int main(int argc, char* argv[])
{
char aaa[64];

Code001();
Code002();

printf("おしまい: ");
scanf("%s", aaa);

return 0;
}

分からないこと
1. (1)で、(3)のときの tData1 のアドレスが返らない(NULLのまま)
2. (2)で、10ではなく配列数を動的に取りたい

以上、よろしくお願いします。


387ポイント を手に入れた。


Name: tkmakwins15 [URL]  ..比類無きプログラマー(66,504ポイント)   Date: 2008/04/03(木) 12:30   No:15320     
Title: Re:ポインタが分かりません    
(2)malloc関数を使ってください。使い方は…

型 *p;
p=malloc(確保したい要素数*sizeof(型));
使い終わったら…
free(p);

とします。
(1)まず、(tData2->a == 0)の結果が偽ですから、その中の文は実行されませんし、関数にアドレスを渡しているわけですが、
アドレスは値なので、書き換えても、それはコピーを書き換えた事になるのです。
つまり、元の変数のアドレスが変わることはありません。そもそも、変数のアドレスはコロコロ変わったりしません。


242ポイント を手に入れた。

Name: やそ  ..プログラマー(37,342ポイント)   Date: 2008/04/03(木) 15:05   No:15323     
Title: Re:ポインタが分かりません    
流れを追うと
---------------------------

DATA_Tという構造体を定義した。
DATA_T型の配列 tData[10];を定義した。

void Code001()
では値の代入を行っている。戻り値はなし。
( tData[0].a = 1;なのでforでループさせたところで、[0]にしか代入していないが・・・)


void Code002()
{
DATA_T *tData1 = NULL;

(ポインタを宣言しているにも関わらず、代入する値(アドレス)がNULLって・・・メモリを破壊したいのでしょうか?)

if( 0 == Code003(tData1, &tData[0]) ){
printf("1-%08x\n", tData1);
printf("2-%08x\n", &tData); // ---(1)
}
Code003の戻り値が0の時に実施させると言うif文自体は問題なさそうですね。
ただ、Code003の第一引数がtData1なのでNULLが渡されることになりますね・・・。

int Code003の関数では・・・
tData2->a == 0は必ず偽を返します。
なぜなら、Code001で
tData[0].a = 1;
としているからです。
なので戻り値は
return (1);
を返し、結果、Code002のif文は必ず偽になり、printf文は実行されません。
また、main関数のコマンドライン引数とか、scanfとか全く意味を成さないように見えますが???



470ポイント を手に入れた。

Name: そら  ..かけだし(1,755ポイント)   Date: 2008/04/03(木) 15:33   No:15324     
Title: Re:ポインタが分かりません    

回答有難う御座います。

> アドレスは値なので、書き換えても、それはコピーを書き換えた事になるのです
DATA_T *Code003(int index, DATA_T *tData2);
とかでしか、ポインタは返せないのかな・・・

> ( tData[0].a = 1;なのでforでループさせたところで、[0]にしか代入していないが・・・)
気付かなかった。
tData[i].a = 1;
の間違い

> (ポインタを宣言しているにも関わらず、代入する値(アドレス)がNULLって・・・メモリを破壊したいのでしょうか?)
理解不足ですね。
とりあえず何でも空にしようとするので・・・

> tData2->a == 0は必ず偽を返します。
そんなことはないと思うけど・・・。
tData2++;
で、実質 tData[i].a を参照できてるはず。

> main関数のコマンドライン引数とか、scanfとか全く意味を成さないように見えますが???
実行確認用。



Code003を汎用化して
DATA_T tDataA[10];
DATA_T tDataB[20];
DATA_T tDataC[30];
とかから検索させたかったけども無理そうだ。

int Code003(int *index, DATA_T *tData2);

if( 0 == Code003(&index, &tData[0]) ){
tData1 = &tData[index];

的な逃げ方しかないのかな・・・。
1手間増えるけど。


240ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(79,607ポイント)   Date: 2008/04/03(木) 17:02   No:15327     
Title: Re:ポインタが分かりません    
アドレスを代入させたい変数にポインタのポインタを利用すればいけるはずですよ。
ちょっとややこしくなるかもしれませんけど…


void Code002()
{
DATA_T* pData1 = NULL;
if (Code003(&pData1, &tData[0]) == 0)
{
if (pData1 != NULL)
{
printf("1-%08x\n", pData1);
printf("2-%08x\n", tData);
}
}
}

int Code003(DATA_T** ppData1, DATA_T* pData2)
{
int i;

for (i = 0; i < 10; i++)
{
if (pData2->a == 0)
{
*ppData1 = pData2; // ---(3)
return 0;
}

pData2++;
}

return 1;
}


236ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(79,721ポイント)   Date: 2008/04/03(木) 17:04   No:15328     
Title: Re:ポインタが分かりません    
おっと、書き忘れていましたが、個人的な趣味の話になりますが、Code003関数に関しては、下記のような書き方の方が個人的には好きですね。まぁ、参考程度に…という事で(^_^;)


int Code003(DATA_T** ppData1, DATA_T* pData2)
{
int i;

for (i = 0; i < 10; i++)
{
if ((pData2 + i)->a == 0)
{
*ppData1 = (pData2 + i); // ---(3)
return 0;
}
}

return 1;
}


114ポイント を手に入れた。

Name: そら  ..かけだし(1,905ポイント)   Date: 2008/04/03(木) 17:44   No:15329 解決!     
Title: Re:ポインタが分かりません    

> バグさん
欲しかったアドレスが返って来ました。
有難う御座いました。

(2)については、

int Code003(DATA_T** ppData1, DATA_T* pData2, int num);

if (Code003(&pData1, &tData[0], sizeof(tData)/sizeof(DATA_T)) == 0)

で、要素数も引数に混ぜます。
さすがにポインタから要素数を求めるのは無理か・・・


150ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(79,798ポイント)   Date: 2008/04/03(木) 22:54   No:15332     
Title: Re:ポインタが分かりません    
要素数に関しては、静的に確保するにしろ、動的に確保するにしろ、プログラマ側が管理してやらなければいけない領域だと思います。ですから、毎回要素数を求めるよりは、定数なり変数なりで保持しておいた方が使い勝手のよい関数になると思いますよ。


77ポイント を手に入れた。




 
[ 1 , ... ]
 
 
管理者画面   RSS   + Powered By 21style +