エラーが出る

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
vjhsvb
記事: 6
登録日時: 5年前

エラーが出る

#1

投稿記事 by vjhsvb » 5年前

このプログラムを実行すると
エラー LNK2019 未解決の外部シンボル "int __cdecl ActMain(void)" (?ActMain@@YAHXZ) が関数 WinMain で参照されました。

エラー LNK1120 1 件の未解決の外部参照

というエラーがでます
どうしてこのようなエラーが出るのか分かりません
教えていただけないでしょうか

コード:

#define _USE_MATH_DEFINES
#define _CRT_SECURE_NO_WARNINGS

#include "DxLib.h"
#include <math.h>
#include <string.h>


#define SCREEN_WIDTH     (640)                         // 画面の横幅
#define SCREEN_HEIGHT    (480)                          // 画面の縦幅
#define MAP_PIXEL_WIDTH (1280)
#define MAP_PIXEL_HEIGHT (480)
#define CHIP_SIZE        (32)                           // 一つのチップのサイズ
#define MAP_WIDTH        ( MAP_PIXEL_WIDTH / CHIP_SIZE)     // マップの横幅
#define MAP_HEIGHT       (MAP_PIXEL_HEIGHT / CHIP_SIZE)    // マップの縦幅 

#define G                (0.3F)                         // キャラに掛かる重力加速度
#define JUMP_POWER       (9.0F)                         // キャラのジャンプ力
#define SPEED            (3.0F)                         // キャラの移動スピード
#define CHAR_SIZE        (30)                           // プレイヤーのサイズ

// ショットの最大数
#define MAX_SHOT 10000

// マップデータ
char MapData[MAP_HEIGHT][MAP_WIDTH] =
{
	0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,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,0, 0,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,0, 0,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,0, 0,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,0, 0,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,0, 0,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,0, 0,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,0, 0,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,0, 0,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, 1,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,0,0,1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,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,0, 0,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,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
	0,0,0,0,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1,
};

struct Player
{
	float PlX, PlY;            // プレイヤーの座標(中心座標)
	float PlDownSp;            // プレイヤーの落下速度
	char PlJumpFlag;           // プレイヤーがジャンプ中か、のフラグ


	int Shot;//弾
	int ShotValid[MAX_SHOT];	// ショットが存在するか、フラグ
	int ShotX[MAX_SHOT], ShotY[MAX_SHOT];	// ショットの位置
	int Key;
	int OldKey;	// 前のキー入力状態


	int Input, EdgeInput;      // 入力状態
	int FrameStartTime;        // 60FPS固定用、時間保存用変数	

	int camerax = 0;//カメラの左上座標
	int charx;//自キャラ位置
	int view_charx;//自キャラの表示位置。この座標にdrawする。

};

////プロトタイプ宣言////////////////////////////////////////////////////////////////////////////

	// マップチップの値を取得する関数
	int GetChipParam(float X, float Y);

	// キャラクタをマップとの当たり判定を考慮しながら移動する関数
	int CharMove(float *X, float *Y, float *DownSP,
		float MoveX, float MoveY, float Size, char *JumpFlag);

	// アクションサンプルプログラムメイン関数
	int ActMain(void);

	// マップとの当たり判定( 戻り値 0:当たらなかった  1:左辺に当たった  2:右辺に当たった
	//                                                3:上辺に当たった  4:下辺に当たった
	// 注意:MoveX と MoveY 、どっちか片方が0じゃないとまともに動作しません(爆)
	int MapHitCheck(float X, float Y, float *MoveX, float *MoveY);
///////////////////////////////////////////////////////////////////////////////////////////////


// WinMain関数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpCmdLine, int nCmdShow)
{
	// 警告避け
	(void)hInstance; (void)hPrevInstance; (void)lpCmdLine; (void)nCmdShow;

	ChangeWindowMode(TRUE);
	SetWaitVSyncFlag(FALSE); //画面更新が遅くならないようにする
	// DXライブラリの初期化
	if (DxLib_Init() == -1) return -1;

	// アクションゲームのメイン関数を呼ぶ
	ActMain();

	// DXライブラリの後始末
	DxLib_End();

	// 終了
	return 0;
}

// アクションサンプルプログラムメイン
int ActMain(Player *pz)
{
	int i;

	// 描画先を裏画面にセット
	SetDrawScreen(DX_SCREEN_BACK);

	// 垂直同期信号を待たない
	SetWaitVSyncFlag(FALSE);

	//ロード
	pz->Shot = LoadGraph("ビーム2.jpg");

	// プレイヤーの座標を初期化
	pz->PlX = 320.0F;        pz->PlY = 240.0F;

	// プレイヤーの落下速度を初期化
	pz->PlDownSp = 0.0F;

	// ジャンプ中フラグを倒す
	pz->PlJumpFlag = FALSE;

	// ショットの存在を初期化する
	for (i = 0; i < MAX_SHOT; i++)
		pz->ShotValid[i] = 0;

	// 入力状態の初期化
	pz->Input = 0;
	pz->EdgeInput = 0;

	// 60FPS固定用、時間保存用変数を現在のカウント値にセット
	pz->FrameStartTime = GetNowCount();

	// メインループ開始、ESCキーで外に出る
	while (ProcessMessage() == 0 && CheckHitKey(KEY_INPUT_ESCAPE) == 0)
	{
		// キー入力取得
		pz->Key = 0;
		pz->OldKey = pz->Key;
		pz->Key = GetJoypadInputState(DX_INPUT_KEY_PAD1);

		// 画面のクリア
		ClsDrawScreen();

		// 1/60秒立つまで待つ
		while (GetNowCount() - pz->FrameStartTime < 1000 / 60) {}

		// 現在のカウント値を保存
		pz->FrameStartTime = GetNowCount();

		// 入力状態を更新
		{
			int i;

			// パッド1とキーボードから入力を得る
			i = GetJoypadInputState(DX_INPUT_KEY_PAD1);

			// エッジを取った入力をセット
			pz->EdgeInput = i & ~pz->Input;

			// 入力状態の保存
			pz->Input = i;
		}

////////// プレイヤーの移動処理////////////////////////////////////////////////////////////
		{
			float MoveX, MoveY;

			// 移動量の初期化
			MoveX = 0.0F;
			MoveY = 0.0F;

			// 左右の移動を見る
			if ((pz->Input & PAD_INPUT_LEFT) != 0) MoveX -= SPEED;
			if ((pz->Input & PAD_INPUT_RIGHT) != 0) MoveX += SPEED;

			// 地に足が着いている場合のみジャンプボタン(ボタン1 or Zキー)を見る
			if (pz->PlJumpFlag == FALSE && (pz->EdgeInput & PAD_INPUT_B) != 0)
			{
				pz->PlDownSp = -JUMP_POWER;
				pz->PlJumpFlag = TRUE;
			}

			// 落下処理
			pz->PlDownSp += G;

			// 落下速度を移動量に加える
			MoveY = pz->PlDownSp;

			// 移動量に基づいてキャラクタの座標を移動
			CharMove(&pz->PlX, &pz->PlY, &pz->PlDownSp, MoveX, MoveY, CHAR_SIZE, &pz->PlJumpFlag);
		}

//////////// ショットの移動処理/////////////////////////////////////////////////////////////
			for (i = 0; i < MAX_SHOT; i++)
			{
				// ショットデータが無効だったらスキップ
				if (pz->ShotValid[i] == 0) continue;

				// 位置を上にずらす
				pz->ShotX[i] += 8;

				// 画面外に出ていたらショットデータを無効にする
				if (pz->ShotX[i] < -32) pz->ShotValid[i] = 0;
			}

			// ショットボタンを押していたらショットを出す
			// 一つ前のループでショットボタンを押していたらショットは出さない
			if ((pz->Key & ~pz->OldKey) & PAD_INPUT_A)
			{
				// 使われていないショットデータを探す
				for (i = 0; i < MAX_SHOT; i++)
				{
					if (pz->ShotValid[i] == 0) break;
				}

				// もし使われていないショットデータがあったらショットを出す
				if (i != MAX_SHOT)
				{
					// ショットの位置を設定
					pz->ShotX[i] = (int)pz->PlX + 17;
					pz->ShotY[i] = (int)pz->PlY + 5;

					// ショットデータを使用中にセット
					pz->ShotValid[i] = 1;
				}
			}

////////// マップの描画///////////////////////////////////////////////////////////////////////
			//自キャラの座標の代入
			pz->charx = (int)pz->PlX;
			
			//カメラ位置を計算
			pz->camerax = pz->charx - SCREEN_WIDTH / 2;
			
			//左右の補正
			if (pz->camerax < 0)
			{
				pz->camerax = 0;
			}
			if (pz->camerax > (MAP_PIXEL_WIDTH - SCREEN_WIDTH))
			{
				pz->camerax = (MAP_PIXEL_WIDTH - SCREEN_WIDTH);
			}
			
			//画面内の位置を求める。
			pz->view_charx = pz->charx - pz->camerax;
			
			int i, j;

			for (i = 0; i < MAP_HEIGHT; i++)
			{
				for (j = 0; j < MAP_WIDTH; j++)
				{
					// 1は当たり判定チップを表しているので1のところだけ描画
					if (MapData[i][j] == 1)
					{
						DrawBox(j * CHIP_SIZE - pz->camerax, i * CHIP_SIZE,
							j * CHIP_SIZE + CHIP_SIZE - pz->camerax, i * CHIP_SIZE + CHIP_SIZE,
							GetColor(255, 255, 255), TRUE);
					}
				}
			}
/////////////////////////////////////////////////////////////////////////////////////////////
		
		LoadGraphScreen(0, 0, "map.jpg", FALSE);

		// キャラクタの描画
		LoadGraphScreen((int)(pz->PlX - CHAR_SIZE * 0.5F), (int)(pz->PlY - CHAR_SIZE * 0.5F)+1, "marimo2.jpg", TRUE);

		// ショットを描画する
		for (i = 0; i < MAX_SHOT; i++)
		{
			// ショットデータが有効な時のみ描画
			if (pz->ShotValid[i] == 1)
			{
				DrawGraph(pz->ShotX[i], pz->ShotY[i], pz->Shot, TRUE);
			}
		}

		// 画面の更新
		ScreenFlip();
	}

	// 終了
	return 0;
}

// キャラクタをマップとの当たり判定を考慮しながら移動する
int CharMove(float *X, float *Y, float *DownSP,
	float MoveX, float MoveY, float Size, char *JumpFlag)
{
	float Dummy = 0.0F;
	float hsize;

	// キャラクタの左上、右上、左下、右下部分が当たり判定のある
	// マップに衝突しているか調べ、衝突していたら補正する

	// 半分のサイズを算出
	hsize = Size * 0.5F;

	// 先ず上下移動成分だけでチェック
	{
		// 左下のチェック、もしブロックの上辺に着いていたら落下を止める
		if (MapHitCheck(*X - hsize, *Y + hsize, &Dummy, &MoveY) == 3) *DownSP = 0.0F;

		// 右下のチェック、もしブロックの上辺に着いていたら落下を止める
		if (MapHitCheck(*X + hsize, *Y + hsize, &Dummy, &MoveY) == 3) *DownSP = 0.0F;

		// 左上のチェック、もしブロックの下辺に当たっていたら落下させる
		if (MapHitCheck(*X - hsize, *Y - hsize, &Dummy, &MoveY) == 4) *DownSP *= -1.0F;

		// 右上のチェック、もしブロックの下辺に当たっていたら落下させる
		if (MapHitCheck(*X + hsize, *Y - hsize, &Dummy, &MoveY) == 4) *DownSP *= -1.0F;

		// 上下移動成分を加算
		*Y += MoveY;
	}

	// 後に左右移動成分だけでチェック
	{
		// 左下のチェック
		MapHitCheck(*X - hsize, *Y + hsize, &MoveX, &Dummy);

		// 右下のチェック
		MapHitCheck(*X + hsize, *Y + hsize, &MoveX, &Dummy);

		// 左上のチェック
		MapHitCheck(*X - hsize, *Y - hsize, &MoveX, &Dummy);

		// 右上のチェック
		MapHitCheck(*X + hsize, *Y - hsize, &MoveX, &Dummy);

		// 左右移動成分を加算
		*X += MoveX;
	}

	// 接地判定
	{
		// キャラクタの左下と右下の下に地面があるか調べる
		if (GetChipParam(*X - Size * 0.5F, *Y + Size * 0.5F + 1.0F) == 0 &&
			GetChipParam(*X + Size * 0.5F, *Y + Size * 0.5F + 1.0F) == 0)
		{
			// 足場が無かったらジャンプ中にする
			*JumpFlag = TRUE;
		}
		else
		{
			// 足場が在ったら接地中にする
			*JumpFlag = FALSE;
		}
	}

	// 終了
	return 0;
}


// マップとの当たり判定( 戻り値 0:当たらなかった  1:左辺に当たった  2:右辺に当たった
//                                                3:上辺に当たった  4:下辺に当たった
// 注意:MoveX と MoveY 、どっちか片方が0じゃないとまともに動作しません(爆)
int MapHitCheck(float X, float Y,
	float *MoveX, float *MoveY)
{
	float afX, afY;

	// 移動量を足す
	afX = X + *MoveX;
	afY = Y + *MoveY;

	// 当たり判定のあるブロックに当たっているかチェック
	if (GetChipParam(afX, afY) == 1)
	{
		float blx, bty, brx, bby;

		// 当たっていたら壁から離す処理を行う

		// ブロックの上下左右の座標を算出
		blx = (float)((int)afX / CHIP_SIZE) * CHIP_SIZE;        // 左辺の X 座標
		brx = (float)((int)afX / CHIP_SIZE + 1) * CHIP_SIZE;    // 右辺の X 座標

		bty = (float)((int)afY / CHIP_SIZE) * CHIP_SIZE;        // 上辺の Y 座標
		bby = (float)((int)afY / CHIP_SIZE + 1) * CHIP_SIZE;    // 下辺の Y 座標

																// 上辺に当たっていた場合
		if (*MoveY > 0.0F)
		{
			// 移動量を補正する
			*MoveY = bty - Y - 1.0F;

			// 上辺に当たったと返す
			return 3;
		}

		// 下辺に当たっていた場合
		if (*MoveY < 0.0F)
		{
			// 移動量を補正する
			*MoveY = bby - Y + 1.0F;

			// 下辺に当たったと返す
			return 4;
		}

		// 左辺に当たっていた場合
		if (*MoveX > 0.0F)
		{
			// 移動量を補正する
			*MoveX = blx - X - 1.0F;

			// 左辺に当たったと返す
			return 1;
		}

		// 右辺に当たっていた場合
		if (*MoveX < 0.0F)
		{
			// 移動量を補正する
			*MoveX = brx - X + 1.0F;

			// 右辺に当たったと返す
			return 2;
		}

		// ここに来たら適当な値を返す
		return 4;
	}

	// どこにも当たらなかったと返す
	return 0;
}

// マップチップの値を取得する関数
int GetChipParam(float X, float Y)
{
	int x, y;

	// 整数値へ変換
	x = (int)X / CHIP_SIZE;
	y = (int)Y / CHIP_SIZE;

	// マップからはみ出ていたら 0 を返す
	if (x >= MAP_WIDTH || y >= MAP_HEIGHT || x < 0 || y < 0) return 0;

	// 指定の座標に該当するマップの情報を返す
	return MapData[y][x];
}


アバター
みけCAT
記事: 6426
登録日時: 10年前
住所: 千葉県
連絡を取る:

Re: エラーが出る

#2

投稿記事 by みけCAT » 5年前

vjhsvb さんが書きました:このプログラムを実行すると
コンパイルが通らないプログラムは実行できないはずです。前件が偽である含意文は真なので、あらゆる可能性が考えられます。
vjhsvb さんが書きました: エラー LNK2019 未解決の外部シンボル "int __cdecl ActMain(void)" (?ActMain@@YAHXZ) が関数 WinMain で参照されました。

エラー LNK1120 1 件の未解決の外部参照

というエラーがでます
エラーメッセージの通り、"int __cdecl ActMain(void)が未定義だからでしょう。
C++では関数のオーバーロードがサポートされているので、
int ActMain(Player *pz)とint ActMain(void)は別物になります。
(C言語でも定義はint ActMain(Player *pz)なのにint ActMain(void)と宣言して呼び出してはいけませんが…)
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

vjhsvb
記事: 6
登録日時: 5年前

Re: エラーが出る

#3

投稿記事 by vjhsvb » 5年前

みけCAT さんが書きました: コンパイルが通らないプログラムは実行できないはずです。前件が偽である含意文は真なので、あらゆる可能性が考えられます。
すみません。
「実行しようとすると」ですね

みけCAT さんが書きました: エラーメッセージの通り、"int __cdecl ActMain(void)が未定義だからでしょう。
C++では関数のオーバーロードがサポートされているので、
int ActMain(Player *pz)とint ActMain(void)は別物になります。
(C言語でも定義はint ActMain(Player *pz)なのにint ActMain(void)と宣言して呼び出してはいけませんが…)
プロトタイプ宣言はint ActMain(Player *pz)にしましたが、
WinMainのほうの呼び出し部分のカッコの中はどうすれば良いのでしょうか。
勉強不足で本当にすみません。

アバター
みけCAT
記事: 6426
登録日時: 10年前
住所: 千葉県
連絡を取る:

Re: エラーが出る

#4

投稿記事 by みけCAT » 5年前

vjhsvb さんが書きました:プロトタイプ宣言はint ActMain(Player *pz)にしましたが、
WinMainのほうの呼び出し部分のカッコの中はどうすれば良いのでしょうか。
WinMain関数のローカル変数として適当なPlayer型の変数(例えばp)を宣言・定義し、
ActMain(&p);とすればいいでしょう。
オフトピック
現状のコードを見る限り、pzを引数ではなくPlayer型(ポインタではない)のActMain関数のローカル変数にして、
ActMainの引数は無くして、pz->をpz.に置換するべきである気が…何か深い考えがあるのだろうか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

vjhsvb
記事: 6
登録日時: 5年前

Re: エラーが出る

#5

投稿記事 by vjhsvb » 5年前

現状のコードを見る限り、pzを引数ではなくPlayer型(ポインタではない)のActMain関数のローカル変数にして、
ActMainの引数は無くして、pz->をpz.に置換するべきである気が…
「Player型の」とはどういう意味ですか?
またpz.はどういう機能ですか?

pz.の機能がよく分かっていないので、
自分は下のプログラムのように解釈しました。
エラーが出たので違うと思いますが..

コード:

// アクションサンプルプログラムメイン
int ActMain(int pz)
{
	int i;


	// 描画先を裏画面にセット
	SetDrawScreen(DX_SCREEN_BACK);

	// 垂直同期信号を待たない
	SetWaitVSyncFlag(FALSE);

	//ロード
	pz.Shot =LoadGraph("ビーム2.jpg");

	// プレイヤーの座標を初期化
	pz.PlX = 320.0F;        pz->PlY = 240.0F;

超初級者
記事: 54
登録日時: 6年前

Re: エラーが出る

#6

投稿記事 by 超初級者 » 5年前

構造体の定義
構造体に別名を付ける
構造体へのポインター

このあたりについて、
どの程度ご存じですか?

アバター
みけCAT
記事: 6426
登録日時: 10年前
住所: 千葉県
連絡を取る:

Re: エラーが出る

#7

投稿記事 by みけCAT » 5年前

vjhsvb さんが書きました:「Player型の」とはどういう意味ですか?
「型がPlayerである」という意味です。
vjhsvb さんが書きました:またpz.はどういう機能ですか?
pzのメンバにアクセスする機能…といえばいいのでしょうか?
vjhsvb さんが書きました:pz.の機能がよく分かっていないので、
自分は下のプログラムのように解釈しました。
エラーが出たので違うと思いますが..
具体的にどう解釈したのか自然言語で説明していただけますか?
  • 演算子として全角の=を使ってはいけません。
  • pz->が残っています。
  • pzに関して「引数ではなくローカル変数」「Player型」のどっちも達成されていません。
  • そもそもint型のデータに対し.演算子や->演算子を使うことは多分できません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

vjhsvb
記事: 6
登録日時: 5年前

Re: エラーが出る

#8

投稿記事 by vjhsvb » 5年前

お世話になりました。

閉鎖

“C言語何でも質問掲示板” へ戻る