トップページgamedev
818コメント302KB

Windowsゲームプログラミング 質問スレ

■ このスレッドは過去ログ倉庫に格納されています
0001うゆ ◆vvvK3Fcqdg 2008/11/06(木) 21:28:45ID:lNn2skuQ
※回答する人も、質問する人も必ず読んでください

【 回答してくださる方 】
・ できるだけ優しく質問に答えてあげてください。
・ 優しく教えるのが嫌でしたら、解決するためのヒントだけでも結構です。
 「ググれ」以外の回答でおながいします。
・ 神ですら理解不能な質問は無視して下さい。

【 質問する香具師 】
・ どんな事で躓いているのか明確にしる。
・ 長くならないなら躓いている部分のコードを晒してみれ。
・ 解決した場合、お礼を言うのは当然だが、何をどうしたら解決したかを明確に書け。
0002名前は開発中のものです。2008/11/06(木) 21:30:16ID:lNn2skuQ
       /  // \`ー  ヾ \ へー-、  `二ー-、
      /   / ハ 「   ヽ、   、     \ \へ  `ヽゝ
    / ノ / /´   \   \  ヽ   ヽ 、 ヽ \\  } }
   /イ   / / / ,| ヽ ヘ、   ヽ  } ヘ   l ヽ ト、 \イ ノ
  ,/ /  / /  l | l  ヽ 、\  }_ェl,,ュ_l_  l  ハ l \ `゙ ヽ
 / /  / l  l   l | l   ト、\_ヽ´lノ イ `/l _lヘ_l_  ヽヘ  \
,/  l  / l l l  l | ,.k  | `ー-ゝソ r _,.= ._  ソyハヽ`Y  }ヽ 、  }、
|  l  l  l l l l  ヘイ  ゝノ     ≠" ̄`゙  |l l人 } l  l  }/丿
| i   |  トヘゝ ト、 rメ r _二_       〃〃 |l  l lイ / / /
| l   l  l \j、ゝィ'、 ≠ ̄`   丶 . - =y、   ノj} l l | ∧{ /
ヘ ハ  、l  l  / /|ハ ′〃   , ´     l   ハノ lリ  lヘ(
   トイl  l {八l| ヘゝ     く      /   // / ィ l丿 Y    >>1 乙♪
    | l   l l\| l "、    丶._   /   /ィ イ´ノノ
    |  ヘ ヽ ハルァl ヽヘ、      ̄  / |从/
     l  ヘY 、ヽ_ル‐-、廴_≧==ェ-、-イ  |
    ∨ヘ  ト'/ ‐、: : l`ヽ二トミーニ._二   |  __
     \ベ/  : : :\: l     \  `゙´ ̄~ ̄. :/
       `゙/  : : : : : : : l  \  \ .,,_.: : : : : /
       /´ : : : : : : : : : | ヽ、ヽ   ー=: : /`ー--‐、
      / /: : : : : : : : : :l   \  /    イ `)\: : : }
   /゙/: : : : : : : /l: : : : :|    ∨       メ、ヘ : :|
  /    : : : : : : :): }: : : /           /´/ヘハ: :l
‐'´    : : : : : : : : : : l: /           l  lο: \ : {
     : : : : : : : : : : : : l                |  |:. :.  ゙l: `l
\    : : : : : : : : : : : : :{                l  l:. :.   | : : \
/\ : : : : : : : : : : : : : : :|            \ \:. . / : : : : |
0003名前は開発中のものです。2008/11/06(木) 21:45:18ID:MY0vkdOy
>>1-2
0004名前は開発中のものです。2008/11/07(金) 11:26:17ID:zpZ6H2po
自演禁止
0005名前は開発中のものです。2008/11/08(土) 02:44:21ID:HuLbUvGn
簡単なアクションゲームだったら、経験から言って制御文、構造体(自己参照構造体含む。これ重要。)、
グラフィックの表示まで分かれば十分作れると思う。
まあ、本気で勉強すれば半年で、物分りの悪い人でも1年やればできると思うよ。
多分、以下のソースがなにやろうとしてるか分かれば制御文については大丈夫だと思う。
(もちろん実行しないで。2分ぐらいで作ったんでscanf使っててスマソ)

#include<stdio.h>

void main(void)
{
  int a,b,i,j
  a=1;
  b=0;
  i=0;
  scanf("%d",&j);
  while(i<j)
  {
    switch(i%2)
    {
      case 0:
        a+=b;
        printf("%d\n",a);
        i++;
        break;
      case 1:
        b+=a;
        printf("%d\n",b);
        i++;
        break;
    }
  }
}
0006名前は開発中のものです。2008/11/08(土) 02:46:36ID:HuLbUvGn
二次元のマップって普通1次元配列でするよね?

X方向120、Y方向100のマップがあったら

$define MAPX 120
$define MAPY 100
$define MAP_SIZE MAPX*MAPY

int main(void) {

int map[MAP_SIZE];
int x=0,Y=0;

for(i=0;i<MAP_SIZE;i++) map[i]=0;
// もし X:54 Y:33 の位置に1を代入したければ
x=54; y=33;
map[x+(y*MAPX)]=1;
}

でいいんだよね??
2次元使ったほうがいいかいな?

76 名前:名前は開発中のものです。 投稿日:02/08/11 23:35 ID:YyqnVN0I
>>73
サイズが大きかったり可変長だったりすると配列ではなくalloc系で取得する
ことになるだろうし、1次元のほうがいいとおもう。

77 名前:名前は開発中のものです。 投稿日:02/08/12 14:35 ID:???
>>76
callocだと0クリアしてくれるから便利だよな
0007名前は開発中のものです。2008/11/08(土) 02:51:52ID:HuLbUvGn
C言語でアクションゲームが作りたい
http://pc11.2ch.net/test/read.cgi/gamedev/1020417733/
110 名前:名前は開発中のものです。 投稿日:03/05/29 11:44 ID:xadUaM2+
まともだよね
Cがテーマだったりすると厨房は書きこまないのかな
0008名前は開発中のものです。2008/11/08(土) 02:58:07ID:dxRdOPSU
>>6
2次元のデータを1次元配列で管理しようとするのは、
俺みたいな昔の貧乏性のプログラマだけでいい。
斜め移動でも座標計算1回で済むとか、そんな貧乏臭い発想。

コンパイル時にサイズ不定でも、簡単なラッパ作ればいい。

2次元のものは2次元のまま扱った方が、デバッグもしやすい。
0009名前は開発中のものです。2008/11/08(土) 09:53:33ID:UXTY631e
左右がつながってるマップだと境界のこと考えなくて済むしな。


『延々と西に向かってたら、いつのまにか北極に立っていた』
な…、何をいっているのかわからねーと思うが(ry
0010名前は開発中のものです。2008/11/10(月) 07:44:57ID:qLM/iweq
>>8
1次元でも2次元でもバイナリ的には同じじゃん。
ただ表記方法が異なるだけ。
アクセススピードも同じだから、好きな方使えばいい。
0011名前は開発中のものです。2008/11/10(月) 18:09:32ID:sl4Agbo8
記述的に分かりやすいのは多次元にする方だと思う。
多次元のメモリの確保、開放は少しややこしいけど、
ライブラリとして4次元ぐらいまで作っておけば便利。
0012名前は開発中のものです。2008/11/11(火) 07:30:30ID:Cky45WKB
>>8
日本語わかる?
0013名前は開発中のものです。2008/11/11(火) 09:46:35ID:sZyTNaq5
ワカリマセーン、ニホンゴムツカシーネ!
0014名前は開発中のものです。2008/11/11(火) 22:02:10ID:v37PimrE
ブロック崩しを作ろうとしているのですが、
ブロックとの当たり判定でボールがブロックとぶつかった際、本来跳ね返らなければいけないのに
時々跳ね返らず貫通して進んでしまうことが起きてしまいます、貫通弾はまだ書いてないのに……
どうしたらいいのでしょうか
言語は基本C、クラスとか途中で変数宣言とかちょっとだけC++入ってるかも、DxLibを使用しています

肝心の当たり判定の部分のソース
for(int i=0;i<BlockX;i++){
 for(int s=0;s<BlockY;s++){
  if(BlockFlag[i][s]){
   if(ShellX>=LeftEdge+35*i-ShellR && ShellX<=LeftEdge+35*(i+1)+ShellR){ //X範囲の判定
    if(ShellY>=UpEdge+20*s-ShellR && ShellY<=UpEdge+20*(s+1)+ShellR){ //Y範囲の判定
     BlockFlag[i][s]=0;
     ShellVX*=(-1);
     ShellVY*=(-1);
    }
   }
  }
 }
}
0015名前は開発中のものです。2008/11/11(火) 22:04:00ID:v37PimrE
主な変数説明
・BlockX、BlockY :ブロックがx・y軸に最大いくつ並んでいるか
・BlockFlag[][] :ブロックが存在しているかいないか、0以外で存在
・ShellX、ShellY :弾のx・y座標
・ShellR :弾の半径
・LeftEdge、UpEdge :ブロック崩しの画面の左端、上端の位置
・ShellVX、ShellVY :弾のx・y速度

当たっているのが縦からなのか、横からなのかの判定がどうにもわからなかったので
当たったらx・y速度両方反転するようにしてしまっています
よければその判定方法も教えてください
宜しくお願いします
0016名前は開発中のものです。2008/11/11(火) 22:07:21ID:z2MnAfhy
移動前と移動後の間も含めて接触判定をするだけ
0017名前は開発中のものです。2008/11/11(火) 23:33:50ID:v37PimrE
>>16
移動前と移動後の間も含めて接触判定……って
いまいちピンと来ない、どういうことでしょうか?
0018名前は開発中のものです。2008/11/12(水) 01:01:19ID:M3s12QpR
>>17
ボールとブロックの距離が、
ボールの(1 フレームの)移動距離よりも短いとき、
ボールはブロックに衝突することなくすり抜けしまう。
対処方法として、
ボールの移動前後を結ぶ線分との交差判定を行う
ことが挙げられる。
0019名前は開発中のものです。2008/11/12(水) 06:00:58ID:xaKS9jsU
>>15
> ShellVX*=(-1);
同時に2つのブロックに接触すると元に戻りそうな嫌なコードだ
0020名前は開発中のものです。2008/11/12(水) 10:40:33ID:kFb9KO8q
>>14
>>19でも指摘されてるけど、2つのブロックに同時に触れた場合は
移動方向が元に戻るから貫通するよ。
だから「ShellVY*=(-1);」の後に「break;」を入れれば
とりあえず貫通するバグは無くなる。

でもそもそも判定ロジックが間違ってるので、全部書き直さなきゃダメ。

当たった部分が縦の面か横の面かの判定をしなきゃまともに跳ね返らない。
前フレームの玉の位置と現在の位置を線で結んで、各ブロックの
4つの側面のどこと交差しているかを判定する必要がある。
横面と交差してるならYだけ反転、縦面と交差してるならXだけ
反転させる。

玉のスピードが速いと、複数のブロックと同時交差する場合もある。
その時は一番玉に近いブロックとの判定だけに絞り、玉の位置も
そのブロックに接触する直前のポジションまで移動させる。
0021142008/11/12(水) 15:58:41ID:58FrgqUc
なるほど、理屈は理解できました
しかしどういうソースを書けばいいのかがまるで思いつかない……
いったいどういしたらいいのでしょうか?
0022名前は開発中のものです。2008/11/13(木) 09:45:19ID:KTGSzFRw
>>21
ベクトルが理解できてないみたいだね。
まずは数学の勉強から始めないと。
線分交差の判定はここを参考にしてみたら?
http://www5d.biglobe.ne.jp/~tomoya03/shtml/algorithm/Intersection.htm
0023142008/11/14(金) 05:07:34ID:wWFUvlwz
>>22
ありがとうございます
しかし読んでみたはいいのですがそれをどう組み込んでいいかがやっぱり思いつきませんでした

なのでがんばって自己流で判定組んでみたら
「○○.exe の 0x0056e0b6 でハンドルされていない例外が発生しました: 0xC0000094: Integer division by zero」
とか出されてしまいました、一体これはどういうことなんでしょうか?
0024142008/11/14(金) 05:14:12ID:wWFUvlwz
ソース

int ShellAX, ShellAY, ShellXT, ShellYT;
//xが次のエリアに到達するまでの時間
if(ShellVX==0){ //分母が0防止
 ShellXT=0;
}else{
 if(ShellVX>0){ //右に変化中
  ShellXT=(35-(ShellBX%35))/ShellVX;
 }else{ //左に変化中
  ShellXT=(-1)*(ShellBX%35)/ShellVX;
 }
}
//yが次のエリアに到達するまでの時間
if(ShellVY==0){ //分母が0防止
 ShellYT=0;
}else{
 if(ShellVY>0){ //下に変化中
  ShellYT=(20-(ShellBY%20))/ShellVY;
 }else{ //上に変化中
  ShellYT=(-1)*(ShellBY%35)/ShellVY;
 }
}
ShellAX=ShellBX/35;
ShellAY=ShellBY/20;
0025142008/11/14(金) 05:14:58ID:wWFUvlwz
while(ShellX>LeftEdge&&ShellX<LeftEdge+350&&ShellY>0&&ShellY<20*BlockY){ //ブロックが存在しうる範囲かどうか
 if(ShellXT<ShellYT){ //Xのエリアが先に変化
  if(ShellVX>0){ //右方向に突入
   if(BlockFlag[ShellAX+1][ShellAY]){ //突入した先にブロックが存在
    BlockFlag[ShellAX+1][ShellAY]=0;
    ShellVX*=(-1);
    ShellX=35*(ShellAY+1); //エリア突入時の境界線へ移動
    ShellY=ShellBY+(ShellVY/ShellVX)*(35*(ShellAY+1)-ShellBY); //エリア突入時にyが進んだ分だけ増加
    break;
   }else{ //突入してもなかったよ
    ShellAX++; //判定を次のエリアへ移行
    ShellXT+=35/ShellVX; //次のエリアへの突入時間加算
   }
  }else{ //左方向に突入
   if(BlockFlag[ShellAX-1][ShellAY]){ //突入した先にブロックが存在
    BlockFlag[ShellAX-1][ShellAY]=0;
    ShellVX*=(-1);
    ShellX=35*ShellAX; //エリア突入時の境界線へ移動
    ShellY=ShellBY+(ShellVY/ShellVX)*(35*ShellAX-ShellBX); //エリア突入時にyが進んだ分だけ増加
    break;
   }else{ //突入してもなかったよ
    ShellAX--; //判定を次のエリアへ移行
    ShellXT=35/ShellVX; //次のエリアへの突入時間加算
   }
  }
0026142008/11/14(金) 05:15:41ID:wWFUvlwz
 }else{ //Yのエリアが先に変化
  if(ShellVY>0){ //下方向に突入
   if(BlockFlag[ShellAX][ShellAY+1]){ //突入した先にブロックが存在
    BlockFlag[ShellAX][ShellAY+1]=0;
    ShellVY*=(-1);
    ShellY=20*(ShellAY+1); //エリア突入時の境界線へ移動
    ShellX=ShellBX+(ShellVX/ShellVY)*(20*(ShellAY+1)-ShellBY); //エリア突入時にxが進んだ分だけ増加
    break;
   }else{ //突入してもなかったよ
    ShellAY--; //判定を次のエリアへ移行
    ShellYT+=20/ShellVY; //次のエリアへの突入時間加算
   }
  }else{ //上方向に突入
   if(BlockFlag[ShellAX][ShellAY-1]){ //突入した先にブロックが存在
    BlockFlag[ShellAX][ShellAY-1]=0;
    ShellVY*=(-1);
    ShellY=20*ShellAY; //エリア突入時の境界線へ移動
    ShellX=ShellBX+(ShellVX/ShellVY)*(20*ShellAY-ShellBY); //エリア突入時にxが進んだ分だけ増加
    break;
   }else{ //突入してもなかったよ
    ShellAY++;
    ShellYT+=20/ShellVY;
   }
  }
 }
 //抜け出し要素判定
 if(ShellAX==ShellX/35||ShellAY==ShellY/20){ //判定エリアが既にボールが来たことになっている場所とおなじなら
  break;
 }
}
0027名前は開発中のものです。2008/11/14(金) 07:16:14ID:EfjKu0FE
0除算例外
>>25>>26にある除算全てが該当するな

アルゴリズムまでは読んでないのでほかの人に任せた
0028142008/11/15(土) 03:43:14ID:NhltAbHO
前のほうでやってるのに忘れていました
とりあえず
ShellXT<ShellYT のところを
ShellXT<ShellYT && ShellXT!=0 にしてみたら動いたは動いたのですが
ボールがあらぬ挙動をします
当たっているのに当たった動きをしなかったり、突然わけのわからないところへ移動したり
原因がさっぱりです……

一応上記の判定は、画面を35*20のエリアに分けて、今いるエリアから別のエリアに移動したら、
そこにブロックが有るか無いか判定、という形で組んでみています
(今更ですが、ブロックを35*20でやっているので、ですね)

もしかしたらこのあたり判定でなく、>>20の方法でやらなければダメなのでしょうか
でしたら、よければそのソースを教えていただけませんでしょうか?
0029名前は開発中のものです。2008/11/17(月) 07:17:05ID:Pi/WdcU7
もしかしなくても、お前の方法は完全に間違い。
先にベクトルの勉強しろって。
0030名前は開発中のものです。2008/11/17(月) 08:29:32ID:4WZ1RBFj
線分単位の当たり判定まではいらないにしても
少なくともどちらに跳ね返すかの判定はいるだろう
ボールの速度がブロックの厚みを超えないようにするだけでだいぶ計算量はへるし
0031名前は開発中のものです。2008/11/17(月) 15:27:54ID:p5mj6MH5
>>29
間違ってはいないよ。14の考え方は論理的には合っている。
自分で思いついた方法なら、そのまま突き進むのを俺は薦める。

とりあえず、問題がありそうな点
・XT,YTはintだと精度が足りない(AX,AY以外は全てfloatの方が望ましい)
・「左方向に突入」の部分のShellXT=35/ShellVX;は+=の間違い
・XT,YTが1フレーム分の時間を超えていたらループから抜ける必要がある
0032名前は開発中のものです。2008/11/19(水) 06:25:45ID:pWNBSaSF
合ってねーよバカw
0033名前は開発中のものです。2008/11/20(木) 02:14:48ID:njtRhxXk
なんかわからんけど >>14>>19 を見た感じ
これでいんじゃね?

CurShellVX = ShellVX;
CurShellVY = ShellVY;
for(int i=0;i<BlockX;i++){
 for(int s=0;s<BlockY;s++){
  if(BlockFlag[i][s]){
   if(ShellX>=LeftEdge+35*i-ShellR && ShellX<=LeftEdge+35*(i+1)+ShellR){ //X範囲の判定
    if(ShellY>=UpEdge+20*s-ShellR && ShellY<=UpEdge+20*(s+1)+ShellR){ //Y範囲の判定
     BlockFlag[i][s]=0;
     ShellVX = -CurShellVX;
     ShellVY = -CurShellVY;
    }
   }
  }
 }
}
0034名前は開発中のものです。2008/11/20(木) 07:27:59ID:ILiqIbsP

来た方向にそのまま戻ってくだけじゃねーかよw
反射させろよw

0035名前は開発中のものです。2008/11/20(木) 10:05:54ID:4yNvzVLI
回帰性があるんですね
0036名前は開発中のものです。2008/11/20(木) 17:22:35ID:rpm+4CxU
ゲーム作るならついにD言語のほうがとうとういいよ
0037名前は開発中のものです。2008/11/20(木) 17:55:39ID:2O47CO/r
ついにとうとうDの時代が来たか
0038名前は開発中のものです。2008/12/04(木) 15:02:10ID:tF31gb+s
Vista対応のゲームをつくる場合、
\Program Files以下にsavedataを作るのはまずいのでしょうか?
0039名前は開発中のものです。2008/12/04(木) 15:13:47ID:f93IhlbP
>>38
まずいよ
fopen( )だと NULL が帰ってくるから
0040名前は開発中のものです。2008/12/04(木) 15:15:55ID:+ofge7Nr
まずいと思うよ。書き込めるように対策してたとしても、
プレイする人の環境によって、そのまま保存されたりVirtualStoreディレクトリに
自動的に置き換わったり、警告出たり出なかったりと、動作がまちまちになるからねえ。
0041名前は開発中のものです。2008/12/04(木) 19:26:59ID:tF31gb+s
ありがとうございます。やはりそうでしたか。

savedataどこに作るか悩みますね。。
どこに作るのが一般的なのか調査してきます。
こちらでもアドバイスいただけると幸いです。
0042名前は開発中のものです。2008/12/04(木) 23:28:46ID:L0NPB3+N
マイドキュメントでも良いけど、ユーザーが直接ファイルを参照する必要がないなら
CSIDL_APPDATAのが適切かな。
0043名前は開発中のものです。2008/12/05(金) 09:49:13ID:tEf/k/KB
そうだな。
他のアプリでも使う可能性がある場合はMyDocument、専用ならAppDataだな。
■ このスレッドは過去ログ倉庫に格納されています