トップページ > 過去ログ > 記事閲覧
わくわくC言語の116pサンプルでエラー
名前:AZS 日時: 2010/06/19 18:50

C言語わくわくゲームプログラミング教室2008の116ページのサンプルでリンクエラーが起きます。 myhelper.hとmyhelper.cppを[既存項目の追加]で追加し、mymain.hに関数プロトタイプを書いてmymain.cpp追加するというサンプルですが手順通りに進めたはずが以下のようなエラーが発生しました。どうすればいいでしょうか。 環境はVISTA、VISUALSTUDIO 2008 VISUALSTUDIO 2008の設定は本に書かれている通り行い、104ページのサンプルまで問題なく動作しました。(プロジェクト名やファイル名も全く同じ名前です) ━━━━━━━━━━━━━━━━━━━ エラー ━━━━━━━━━━━ mymain.obj : error LNK2001: 外部シンボル ""int __cdecl CheckClearJyouken04(void)" (?CheckClearJyouken04@@YAHXZ)" は未解決です。 mymain.obj : error LNK2001: 外部シンボル ""void __cdecl DrawEnemies04(void)" (?DrawEnemies04@@YAXXZ)" は未解決です。 mymain.obj : error LNK2001: 外部シンボル ""void __cdecl InitializeGame04(void)" (?InitializeGame04@@YAXXZ)" は未解決です。 libjpeg_d.lib(jpegtran.obj) : error LNK2019: 未解決の外部シンボル _jtransform_execute_transformation が関数 _main で参照されました。 libjpeg_d.lib(jpegtran.obj) : error LNK2019: 未解決の外部シンボル _jcopy_markers_execute が関数 _main で参照されました。 libjpeg_d.lib(jpegtran.obj) : error LNK2019: 未解決の外部シンボル _jtransform_adjust_parameters が関数 _main で参照されました。 libjpeg_d.lib(jpegtran.obj) : error LNK2019: 未解決の外部シンボル _jtransform_request_workspace が関数 _main で参照されました。 libjpeg_d.lib(jpegtran.obj) : error LNK2019: 未解決の外部シンボル _jcopy_markers_setup が関数 _main で参照されました。 libjpeg_d.lib(jpegtran.obj) : error LNK2019: 未解決の外部シンボル _write_stdout が関数 _main で参照されました。 libjpeg_d.lib(jpegtran.obj) : error LNK2019: 未解決の外部シンボル _read_stdin が関数 _main で参照されました。 libjpeg_d.lib(jpegtran.obj) : error LNK2019: 未解決の外部シンボル _read_scan_script が関数 _parse_switches で参照されました。 libjpeg_d.lib(jpegtran.obj) : error LNK2019: 未解決の外部シンボル _keymatch が関数 _parse_switches で参照されました。 C:\Users\あああ\Documents\Visual Studio 2008\Projects\chap4\Debug\chap4.exe : fatal error LNK1120: 外部参照 12 が未解決です。 ビルドログは "file://c:\Users\あああ\Documents\Visual Studio 2008\Projects\chap4\chap4\Debug\BuildLog.htm" に保存されました。 chap4 - エラー 13、警告 0 ━━━━━━━━━━━ myhelper.h ━━━━━━━━━━━━━━━━━ #include "DXLib.h" #include <limits.h> #include <math.h> //構造体宣言 //座標またはベクトルを記録する構造体 struct Vector{ float x,y; }; typedef Vector Point2D; //線を記録する構造体 struct Line2D{ Point2D startpos, endpos; float katamuki; //傾きをラジアン値で記録 Vector speed; //移動している場合は速度をセット }; //球体を記録する構造体 struct Ball2D{ Point2D position; float hankei; //半径 }; //四角形を記録する構造体 struct Rect2D{ Point2D lefttop; Point2D rightbottom; float width; float height; }; //ライブラリ関数 Point2D PosInView(Point2D in); int XInView(float inx); int YInView(float iny); void ScrollToLeft(float jikiposx); void ScrollToRight(float jikiposx); void ScrollToUp(float jikiposy); void ScrollToDown(float jikiposy); void DrawLineInView(float x1, float y1, float x2, float y2, int Color, int Thickness); void DrawCircleInView(float x, float y, float r, int Color, int FillFlag); void DrawAnimation(float x, float y, double ExtRate, double Angle,int TurnFlag, int *imgarray, int allframe, float fps); //ベクトル関数 Vector CreateVector(Vector in, float veclen); Vector AddVector(Vector v1, Vector v2); Vector SubVector(Vector v1, Vector v2); Vector AddVectorInFrameTime(Vector pos, Vector speed); Vector AddVectorInFrameTime2(Vector pos, Vector speed, Vector accel); Vector Normalize(Vector in); Vector RotateVector(Vector in, float radian); float VectorLengthSquare(Vector in); float DotProduct(Vector v1, Vector v2); float CrossProduct(Vector v1, Vector v2); void SetLine2DKatamuki(Line2D *in); void DrawLine2D(Line2D in, int Color, int Thickness); void DrawBall2D(Ball2D in, int Color, int Fill); //当たり判定関数 bool HitTestLineAndBall(Line2D linein, Ball2D ballin); bool IsPointAtLineFace(Line2D linein, Point2D ptin); bool HitTestLineAndLine(Line2D line1, Line2D line2); bool HitTestBallAndBall(Ball2D a, Ball2D b); bool HitTestPointAndBox(Rect2D rect, Point2D pt); //タイマー関数 void SetSimpleTimer(int idx, int time); int GetPassedTime(int idx); //グローバル変数 extern float g_frametime; extern Rect2D g_framerect; //画面領域(当たり判定) extern Point2D g_current_field_pos; //現在の左上座標 extern Rect2D g_stagesize; //ステージサイズ //定数宣言 const float ZEROVALUE = 1e-10f; const float PIE = 3.1415926f; const int SCROLL_LIMIT = 200; ━━━━━━━━━━━ myhelper.cpp ━━━━━━━━━━━━━━━━━ #include "myhelper.h" #include "mymain.h" //グローバル変数 int g_lasttime; //前回のループ終了時間(ミリ秒) float g_frametime = 0.017f; //1フレームの表示にかかった時間(秒) // プログラムの開始関数 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { if (strcmp(lpCmdLine, "-f") != 0) ChangeWindowMode(TRUE); //DXライブラリの初期化処理 if( DxLib_Init() == -1 ) return -1; //描画対象を裏画面に設定 SetDrawScreen(DX_SCREEN_BACK); //ファイルの読み込み if( LoadFiles() == -1 ) return -1; //画面サイズ(当たり判定用)の初期化 Rect2D gf = { {-64,-64}, {640+64,480+64}, 768, 608}; memcpy( &g_framerect, &gf, sizeof(Rect2D) ); //スクロール開始点の初期化 g_current_field_pos.x = 0; g_current_field_pos.y = 0; //ステージサイズの初期化 Rect2D gs = { {0,0}, {639,479}, 640,480} ; memcpy( &g_stagesize, &gs, sizeof(Rect2D) ); //メインループ g_lasttime = GetNowCount() & INT_MAX; while(ProcessMessage()==0 && CheckHitKey(KEY_INPUT_ESCAPE)==0){ ClsDrawScreen(); //画面を消去 MyMain(); ScreenFlip(); //画面を切り替え //1ループにかかった時間を計測 int curtime = GetNowCount() & INT_MAX; g_frametime = (float)(curtime - g_lasttime) / 1000.0f; g_lasttime = curtime; if (g_frametime > 0.03f) g_frametime = 0.03f; } DxLib_End() ; // DXライブラリ使用の終了処理 return 0 ; // ソフトの終了 } //スクロール用データ Rect2D g_framerect = { {-64,-64}, {640+64,480+64}, 768, 608}; //画面領域(当たり判定) Point2D g_current_field_pos = {0,0}; //現在の左上座標 Rect2D g_stagesize = { {0,0}, {639,479}, 640,480}; //ステージサイズ //スクロール用関数 //データ上の座標を画面表示用座標に変更する Point2D PosInView(Point2D in){ return SubVector(in, g_current_field_pos); } //そのX座標版とY座標版 int XInView(float inx){ return (int)(inx - g_current_field_pos.x); } int YInView(float iny){ return (int)(iny - g_current_field_pos.y); } /*画面を左へスクロール (自キャラから200ピクセルを保つようスクロール)*/ void ScrollToLeft(float jikiposx){ //スクロール可能かをチェック if ((int)jikiposx - SCROLL_LIMIT > (int)g_stagesize.lefttop.x){ g_current_field_pos.x = jikiposx - SCROLL_LIMIT; g_framerect.lefttop.x = g_current_field_pos.x - 64; g_framerect.lefttop.y = g_current_field_pos.y - 64; g_framerect.rightbottom.x = g_current_field_pos.x + 640 + 64; g_framerect.rightbottom.y = g_current_field_pos.y + 480 + 64; } } /*画面を右へスクロール (自キャラから200ピクセルを保つようスクロール)*/ void ScrollToRight(float jikiposx){ if ((int)jikiposx + SCROLL_LIMIT < (int)g_stagesize.rightbottom.x){ g_current_field_pos.x = jikiposx - (640 - SCROLL_LIMIT); g_framerect.lefttop.x = g_current_field_pos.x - 64; g_framerect.lefttop.y = g_current_field_pos.y - 64; g_framerect.rightbottom.x = g_current_field_pos.x + 640 + 64; g_framerect.rightbottom.y = g_current_field_pos.y + 480 + 64; } } /*画面を上へスクロール*/ void ScrollToUp(float jikiposy){ //スクロール可能かをチェック if ((int)jikiposy - SCROLL_LIMIT > (int)g_stagesize.lefttop.y){ g_current_field_pos.y = jikiposy - SCROLL_LIMIT; g_framerect.lefttop.x = g_current_field_pos.x - 64; g_framerect.lefttop.y = g_current_field_pos.y - 64; g_framerect.rightbottom.x = g_current_field_pos.x + 640 + 64; g_framerect.rightbottom.y = g_current_field_pos.y + 480 + 64; } } /*画面を下へスクロール*/ void ScrollToDown(float jikiposy){ if ((int)jikiposy + SCROLL_LIMIT < (int)g_stagesize.rightbottom.y){ g_current_field_pos.y = jikiposy - (480 - SCROLL_LIMIT); g_framerect.lefttop.x = g_current_field_pos.x - 64; g_framerect.lefttop.y = g_current_field_pos.y - 64; g_framerect.rightbottom.x = g_current_field_pos.x + 640 + 64; g_framerect.rightbottom.y = g_current_field_pos.y + 480 + 64; } } /*スクロールを計算に入れた描画関数*/ void DrawLineInView(float x1, float y1, float x2, float y2, int Color, int Thickness){ DrawLine(XInView(x1), YInView(y1), XInView(x2), YInView(y2), Color, Thickness); } void DrawCircleInView(float x, float y, float r, int Color, int FillFlag){ DrawCircle(XInView(x), YInView(y), (int)r, Color, FillFlag); } /*アニメーション表示をする関数 画像を表示する座標xとy、 イメージデータの配列imgarray、総コマ数framenum、アニメの表示速度fps アニメーション用の一時データanimtmpを引数とする。 1枚絵を表示する場合は、 imgarrayにint型変数のアドレス、allframeに1、fpsに1.0fを指定すること。 */ void DrawAnimation(float x, float y, double ExtRate, double Angle,int TurnFlag, int *imgarray, int allframe, float fps){ //現在の経過秒数を求める float t = (float)( GetNowCount() & INT_MAX ); //表示すべきコマ数を求める int animpat = (int)(t/(1000/fps)) % allframe; //そのコマを描画 DrawRotaGraph(XInView(x),YInView(y), ExtRate, Angle, imgarray[animpat], TRUE, TurnFlag); } /*ベクトルを作成する関数 入力ベクトルを正規化してから長さを掛ける*/ Vector CreateVector(Vector in, float veclen){ Vector result; in = Normalize(in); result.x = in.x * veclen; result.y = in.y * veclen; return result; } /*ベクトルの足し算を行う関数*/ Vector AddVector(Vector v1, Vector v2){ Vector result; result.x = v1.x + v2.x; result.y = v1.y + v2.y; return result; } /*ベクトルの引き算を行う関数 座標からベクトルを求める場合にも使える その場合v1は終点、v2は始点とする*/ Vector SubVector(Vector v1, Vector v2){ Vector result; result.x = v1.x - v2.x; result.y = v1.y - v2.y; return result; } /*座標に速度ベクトルを足す関数(等速運動用) g_frametimeを考慮する*/ Vector AddVectorInFrameTime(Vector pos, Vector speed){ Vector result; result.x = pos.x + speed.x * g_frametime; result.y = pos.y + speed.y * g_frametime; return result; } /*座標に速度ベクトルと加速度を足す関数(等加速度運動用) g_frametimeを考慮する*/ Vector AddVectorInFrameTime2(Vector pos, Vector speed, Vector accel){ Vector result; result.x = pos.x + speed.x * g_frametime + accel.x * pow(g_frametime,2) / 2; result.y = pos.y + speed.y * g_frametime + accel.y * pow(g_frametime,2) / 2; return result; } /*ベクトルを正規化する関数*/ Vector Normalize(Vector in){ Vector result; float l = sqrt( in.x * in.x + in.y * in.y ); result.x = in.x / l; result.y = in.y / l; return result; } /*内積を求める関数*/ float DotProduct(Vector v1, Vector v2){ return v1.x * v2.x + v1.y * v2.y; } /*外積を求める関数*/ float CrossProduct(Vector v1, Vector v2){ return v1.x * v2.y - v1.y * v2.x; } /*ベクトルを回転させる関数*/ Vector RotateVector(Vector in, float radian){ Vector result; result.x = -sin(radian)*in.y + cos(radian)*in.x; result.y = cos(radian)*in.y + sin(radian)*in.x; return result; } /*ベクトルの長さの二乗を求める関数 長さが必要なときはsqrtで平方根を求める*/ float VectorLengthSquare(Vector in){ return in.x * in.x + in.y * in.y; } /*Line2Dを描画する関数*/ void DrawLine2D(Line2D in, int Color, int Thickness){ DrawLine(XInView(in.startpos.x), YInView(in.startpos.y), XInView(in.endpos.x), YInView(in.endpos.y), Color, Thickness); } /*Ball2Dを描画する関数*/ void DrawBall2D(Ball2D in, int Color, int FillFlag){ DrawCircle(XInView(in.position.x), YInView(in.position.y), (int)in.hankei, Color, FillFlag); } /*線の傾きを求めてLine2Dのメンバkatamukiにセットする関数*/ void SetLine2DKatamuki(Line2D *in){ in->katamuki = atan2(in->endpos.y - in->startpos.y, in->endpos.x - in->startpos.x); } /*Ball2DとLine2Dの当たり判定を行う関数*/ bool HitTestLineAndBall(Line2D linein, Ball2D ballin){ Vector avec, bvec; avec = SubVector(ballin.position, linein.startpos); bvec = SubVector(linein.endpos, linein.startpos); float dot = DotProduct(avec, bvec); //内積を求める float bl = VectorLengthSquare(bvec); //ベクトルbの長さの二乗を求める if ( (dot > -ZEROVALUE) && (dot < bl) ) { //衝突の可能性有り //円と線の距離を求める //ボールの中心から垂直におろした線の交点を求める Vector bnvec = Normalize(bvec); //ベクトルbの正規化 float dot2 = DotProduct(avec, bnvec); bnvec.x *= dot2; bnvec.y *= dot2; Point2D kouten = AddVector(linein.startpos, bnvec); Vector dist = SubVector(ballin.position, kouten); float al = VectorLengthSquare(dist); #ifdef _DEBUG DrawBall2D(ballin, GetColor(128,128,128),FALSE); DrawLineInView(linein.startpos.x, linein.startpos.y, linein.startpos.x+avec.x, linein.startpos.y+avec.y, 65535,1); DrawLineInView(linein.startpos.x, linein.startpos.y, kouten.x, kouten.y, GetColor(255,0,0),1); DrawLineInView(kouten.x, kouten.y, ballin.position.x, ballin.position.y, GetColor(255,0,0),1); #endif if ( al < (ballin.hankei * ballin.hankei) ){ return TRUE; } } return FALSE; } /*頂点と線の位置関係を調べる関数 線の左または上側にあればTRUE、右または下側にあればFALSEを返す*/ bool IsPointAtLineFace(Line2D linein, Point2D ptin){ Vector avec, bvec; avec = SubVector(ptin, linein.startpos); bvec = SubVector(linein.endpos, linein.startpos); float cross = CrossProduct(avec, bvec); //外積が正なら点は線の表側(左側)にある if ( cross > -ZEROVALUE ) return TRUE; return FALSE; } /*Line2D同士の当たり判定を行う関数*/ bool HitTestLineAndLine(Line2D line1, Line2D line2){ Vector avec, bvec, cvec, dvec, evec, fvec; avec = SubVector(line1.endpos, line1.startpos); //a2-a1 bvec = SubVector(line2.startpos, line1.startpos); //b1-a1 cvec = SubVector(line2.endpos, line1.startpos); //b2-a1 dvec = SubVector(line2.endpos, line2.startpos); //b2-b1 evec = SubVector(line1.startpos, line2.startpos); //a1-b1 fvec = SubVector(line1.endpos, line2.startpos); //a2-b1 float a,b,c,d; a = CrossProduct(avec, bvec); b = CrossProduct(avec, cvec); c = CrossProduct(dvec, evec); d = CrossProduct(dvec, fvec); if( ((a*b) < ZEROVALUE) && ((c*d) < ZEROVALUE) ){ return TRUE; } return FALSE; } /*Ball2D同士の当たり判定を行う関数*/ bool HitTestBallAndBall(Ball2D ball1, Ball2D ball2){ #ifdef _DEBUG DrawBall2D(ball1, GetColor(128,128,128),FALSE); DrawBall2D(ball2, GetColor(128,128,128),FALSE); #endif if ( pow(ball1.position.x - ball2.position.x, 2) + pow(ball1.position.y - ball2.position.y,2) < pow(ball1.hankei+ball2.hankei, 2) ){ return TRUE; }else{ return FALSE; } } /*Point2DとRect2Dの当たり判定を行う関数*/ bool HitTestPointAndBox(Rect2D rect, Point2D pt){ if ( (rect.lefttop.x < pt.x) && (pt.x < rect.rightbottom.x) && (rect.lefttop.y < pt.y) && (pt.y < rect.rightbottom.y) ){ return TRUE; } return FALSE; } //シンプルタイマー関数 const int MAXTIMER = 32; int g_goaltimes[MAXTIMER]; /*タイマーに目標値を設定して始動させる関数 目標値timeはミリ秒で設定する*/ void SetSimpleTimer(int idx, int time){ if(idx>MAXTIMER) return; g_goaltimes[idx] = (GetNowCount() & INT_MAX) + time; } /*タイマーの結果を取得する関数 返値が負ならまだ目標値に達していない 正なら目標値を超えている*/ int GetPassedTime(int idx){ return (GetNowCount() & INT_MAX) - g_goaltimes[idx]; } ━━━━━━━━━━━ mymain.cpp ━━━━━━━━━━━━━━━━━━━━━━━ #include "myhelper.h" #include "mymain.h" //自キャラのデータ Point2D g_jikipos = {40,400}; //自キャラの座標 //画像ハンドル int g_jikiimage[11]; //色々なファイルの読み込み int LoadFiles(){ //画像ファイルの読み込み if(LoadDivGraph("media\\player01.bmp",11,11,1,64,64,g_jikiimage) == -1) return -1; return 1; } ━━━━━━━━━━━ mymain.h ━━━━━━━━━━━ void MyMain(); int LoadFiles(); どなたかわかる方いましたら教えてください。 よろしくお願いします。

Page: 1 |

Re: わくわくC言語の116pサンプルでエラー ( No.1 )
名前:いっち 日時:2010/06/19 19:41

提示されているエラーの内容とソースの内容が一致しないように思います。 問題となっているプロジェクトを丸ごと圧縮してアップローダに上げて頂けますでしょうか?
Re: わくわくC言語の116pサンプルでエラー ( No.2 )
名前:AZS 日時:2010/06/19 22:09

いっちさん プロジェクトを消去してもう一度同じ手順で試しましたがエラーが出てしまいました。 つきましてはttp://www.dotup.org/uploda/www.dotup.org975160.zip.htmlにプロジェクトごとアップロードしましたので教えていただけると幸いです。 パスワードは[cgame]です。 よろしくお願いいたします。
Re: わくわくC言語の116pサンプルでエラー ( No.3 )
名前:いっち 日時:2010/06/19 22:46

ご提供頂いたプロジェクトを私の環境でリビルドしたところ、エラーは以下のようなリンクエラーのみでした。 1>リンクしています... 1>myhelper.obj : error LNK2019: 未解決の外部シンボル "void __cdecl MyMain(void)" (?MyMain@@YAXXZ) が関数 _WinMain@16 で参照されました。 1>C:\Programming\Project\chap4\Debug\chap4.exe : fatal error LNK1120: 外部参照 1 が未解決です。 1>ビルドログは "file://c:\Programming\Project\chap4\chap4\Debug\BuildLog.htm" に保存されました。 1>chap4 - エラー 2、警告 0 エラーの内容としては関数 MyMain の定義が見つからないというものです。 mymain.cpp(おそらく) に関数 MyMain を定義することで解決すると思います。 (書籍があるのでしたら MyMain についてご確認下さい)
Re: わくわくC言語の116pサンプルでエラー ( No.4 )
名前:AZS 日時:2010/06/19 22:57

ありがとうございます。 書籍には ------------------------------ myhelper.cppのWinMain関数ではLoadFiles関数と MyMain関数を呼び出します。これらの関数はmymain.cppからすると外部ファイルの関数になるため、ヘッダファイルを書いて名前や引数・。戻り値を伝えなければいけません。 そこでまず新しいヘッドファイルのmymain.hを作成します。 ------------------------------ とありますので、mymain.hを作成し、mymain.hの中に ---------------- void MyMain(); ---------------- とプロトタイプ宣言というものを書いたはずですが、そういうことではないのですか? 他に何か定義するべきでしょうか?
Re: わくわくC言語の116pサンプルでエラー ( No.5 )
名前:いっち 日時:2010/06/19 23:21

> とありますので、mymain.hを作成し、mymain.hの中に > ---------------- > void MyMain(); > ---------------- > とプロトタイプ宣言というものを書いたはずですが、そういうことではないのですか? AZSさんご自身が「プロトタイプ宣言」と仰っている通りそれは"宣言"であって"定義"ではありません。 プロジェクトに含まれるソースファイルのどこかに関数 MyMain の処理内容を記述した定義が必要になります。 たとえば mymain.cpp 内に以下のようなコードを追加するとエラーはなくなると思います。 void MyMain( void ) { return; // 何もせずに終了 }
Re: わくわくC言語の116pサンプルでエラー ( No.6 )
名前:AZS 日時:2010/06/19 23:49

いっちさん コードを追加したところエラー表示が消えました。 MyMainの定義に関して何も説明が書かれてなかったのと、よくわからないサンプルが掲載されていたようです。 次ページのキャラクターが走るサンプルは動作しましたのでMyMain関数が定義されていなかったのが原因だと思います。 一つ勉強になりました。 どうもありがとうございました。

Page: 1 |