12
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

クソアプリAdvent Calendar 2017

Day 7

スマホゲーム制作記

Last updated at Posted at 2017-12-11

#その名は"食材フィーバー"

ルールは簡単。

上から落ちてくる食材やお金を集めよう。
それ以外のアイテムをひろうとゲームオーバー。

より多くのスコアを出そう!

こんなゲームです。
syoku.png

とにかく沢山の食材(+お金)を集めるゲームです。

プラットフォームはWindows(.exe)~~(Windows版は諸事情により公開していません)~~とAndroid(.apk)です。
開発はVisualStudio2017、C++、DXライブラリです。

https://play.google.com/store/apps/details?id=com.gaccho
↑ダウンロードURLはこちら

#操作方法
画面左半分をタッチすると左に移動、
画面右半分をタッチすると右に移動します。

ただ、それだけです。

#コード
このコードはCの構造体を学習している時期に作ったものなので、とても汚いです……。今でも汚いけど

main.cpp
#include "DxLib.h"
#define PIXELX 1920
#define PIXELY 1080
#define MUSIC_COUNT 32
#define RL_ITEM_EMPTY 0
#define RL_ITEM_MONEY 1
#define RL_ITEM_RED_MUSHROOM 6
#define RL_ITEM_BLUE_MUSHROOM 7

#define RL_MONSTER_IKARI 1 //イカリー;;;;;;;;;;


#define RL_ITEM_SEAWEED 15
#define RL_ITEM_STONE 16
#define RL_ITEM_CHESTNUT 17
#define RL_ITEM_DRUG 18

#define RL_ITEM_BLACK_GLASSES 30
#define RL_ITEM_ROUND_GLASSES 31
#define RL_ITEM_MONEY_GLASSES 32

#define PI 3.14159265358979323846
#define WHITE GetColor(255,255,255) //白

#define ITEM_SE 1
#define IMPORTANT_SE 2
#define END_SE 3

struct Eat_MG
{
	int score = 0; //ゲームのスコア
	int playerX = 0; //プレイヤーのX座標
	int playerY = 0; //プレイヤーのY座標(頭の高さ)
	int playerSpeed = 10; //プレイヤーの速さ
	int playerItemCount = 0; //プレイヤーが持っているアイテムの数
	unsigned char itemCount = 0; //降ってくるアイテムの数
	unsigned char gameoverNumber = 0; //降ってくるゲームオーバーアイテムの数

	int safeareaStart = 0;
	int safeareaEnd = 0;

	//int itemY = 0; //持っているアイテムの高さ
	int widthX = 1920; //ゲーム内のX軸の長さ
	int widthY = 1080; //ゲーム内のY軸の長さ

	double probability = 5; //1fps間でアイテムが出る確率
	double probability2 = 2;
	int itemNumberData = 5; //出る個数
	int itemNumber = 0; //

	unsigned char playerItem[1024]; //持っているアイテムの数
	unsigned char playerItemS[1024]; //持っているアイテム向き
	int playerItemX[1024]; //持っているアイテムのX座標
	int playerItemY[1024]; //持っているアイテムのY座標

	unsigned char item[256]; //降ってくるアイテムのID
	unsigned char itemS[256]; //降ってくるアイテムの向き
	int itemX[256]; //降ってくるアイテムのX座標
	int itemY[256]; //降ってくるアイテムのY座標
};

int gacha(double kakuritu)
{
	if (kakuritu >= 100) {
		return 1;
	}
	if (kakuritu <= 0) {
		return 0;
	}
	int bangou = (int)(20000000 * kakuritu);
	int atari = 1 + GetRand(1999999999);
	if (bangou >= atari) {
		return 1;
	}

	return 0;
}

#ifdef __ANDROID__
//Android版のコンパイルだったら android_main
int android_main() 
#else
//Windows版のコンパイルだったら WinMain
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 
#endif
{
	//logの出力を無しにする
	if (SetOutApplicationLogValidFlag(FALSE)) return -1; 

#ifndef __ANDROID__
	// Windows版のコンパイルだったら ChangeWindowMode を実行する
	if (ChangeWindowMode(TRUE)) return -1; 

	//タイトル文字
	if (SetMainWindowText("Food Fever")) return -1;
#endif

	SetGraphMode(1920, 1080, 32);
	if (DxLib_Init() == -1)     // DXライブラリ初期化処理
	{
		return -1;          // エラーが起きたら直ちに終了
	}

	SetDrawScreen(DX_SCREEN_BACK);

	struct Eat_MG eat;
	int mainBGM = LoadSoundMem("Music/BGM/stage09.ogg");
	PlaySoundMem(mainBGM, DX_PLAYTYPE_LOOP);
	for (int i = 0; i < 256; i++) {
		eat.item[i] = 0;
		eat.itemS[i] = 0;
		eat.itemX[i] = 0;
		eat.itemY[i] = 0;
	}
	for (int i = 0; i < 1024; i++) {
		eat.playerItem[i] = 0;
		eat.playerItemS[i] = 0;
		eat.playerItemX[i] = 0;
		eat.playerItemY[i] = 0;
	}

	//比率に関する変数宣言
	int pixelX2 = PIXELX >> 1; //X座標の半分の画面解像度
	int pixelY2 = PIXELY >> 1; //Y座標の半分の画面解像度
	int pixelX32 = PIXELX >> 5; //X座標の1/32の画面解像度
	int pixelX64 = PIXELX >> 6; //X座標の1/64の画面解像度


	eat.playerX = eat.widthX / 2; //プレイヤーのX座標
	eat.playerY = (int)(eat.widthY*0.7); //プレイヤーのY座標

	int softSE[MUSIC_COUNT];
	int mainSE[MUSIC_COUNT];

	softSE[ITEM_SE] = LoadSoftSound("Music/SE/item.wav");
	mainSE[ITEM_SE] = LoadSoundMemFromSoftSound(softSE[ITEM_SE]);

	softSE[END_SE] = LoadSoftSound("Music/SE/end.wav");
	mainSE[END_SE] = LoadSoundMemFromSoftSound(softSE[END_SE]);

	int back = LoadGraph("Picture/Run/back.png");
	int basket = LoadGraph("Picture/Eat/basket.png");
	int ground = LoadGraph("Picture/Eat/ground.png");
	int test3 = LoadGraph("Picture/Run/test3.png");
	int brush = LoadGraph("Picture/Run/brush.png");
	int brush2 = LoadGraph("Picture/Run/brush2.png");
	int keisanX = 0;

	int mapChipItem[256];
	//アイテム画像をロード
	mapChipItem[RL_ITEM_MONEY] = LoadGraph("Picture/RogueLike/Item/money.png");
	mapChipItem[RL_ITEM_RED_MUSHROOM] = LoadGraph("Picture/RogueLike/Item/mushroom.png");
	mapChipItem[RL_ITEM_BLUE_MUSHROOM] = LoadGraph("Picture/RogueLike/Item/mushroom2.png");
	mapChipItem[RL_ITEM_SEAWEED] = LoadGraph("Picture/RogueLike/Item/seaweed.png");
	mapChipItem[RL_ITEM_STONE] = LoadGraph("Picture/RogueLike/Item/stone.png");
	mapChipItem[RL_ITEM_CHESTNUT] = LoadGraph("Picture/RogueLike/Item/chestnut.png");
	mapChipItem[RL_ITEM_DRUG] = LoadGraph("Picture/RogueLike/Item/drug.png");

	mapChipItem[255] = LoadGraph("Picture/Eat/gameover.png");

	int monsterPicture[2][64];//16個の画像を格納する配列
	LoadDivGraph("Picture/RogueLike/Player/ikari.png", 64, 8, 8, 120, 120, monsterPicture[RL_MONSTER_IKARI]);

	eat.safeareaStart = GetRand(eat.widthX - 300);
	eat.safeareaEnd = eat.safeareaStart + 300;

	unsigned char direction = 3; //mobの向き
	unsigned char move = 0; //mobの動き(パラパラ漫画)
	unsigned char moveTime = 0; //

	int FontHandle = CreateFontToHandle("メイリオ", pixelX32, 10, DX_FONTTYPE_ANTIALIASING_EDGE_8X8);
	int FontHandle2 = CreateFontToHandle("メイリオ", pixelX64, 10, DX_FONTTYPE_ANTIALIASING_EDGE_8X8);

	int moveCount = 0; //動いているか
	int rand = 0;

	int gameCount = 0;

	int timeCount = 0;

	int x[10] = { 0,0,0,0,0,0,0,0,0,0 };
	int y[10] = { 0,0,0,0,0,0,0,0,0,0 };

	int left = 0, right = 0;

	while (1)
	{
		/*エラー処理////////////////////////////////////////////////////////////////////////*/
		if (ProcessMessage() != 0) {
			break;
		}
		if (ClearDrawScreen() != 0) {
			break;
		}
		//if (updateKey() != 0) {//CheckHitKey(KEY_INPUT_ESCAPE)
		//	break;
		//}
		/*終了処理////////////////////////////////////////////////////////////////////////*/

		DrawRotaGraph(pixelX2, pixelY2, 1.0, 0.0, back, TRUE);
		DrawRotaGraph(pixelX2, pixelY2, 1.0, 0.0, ground, TRUE);
		moveCount = 0;

		for (int i = 0; i < GetTouchInputNum(); i++) {
			GetTouchInput(i, &x[i], &y[i]);
			if (x[i] < (PIXELX >> 1)) {
				left++;
			}
			else {
				right++;
			}
		}


		switch (gameCount)
		{
		case 0:
			eat.playerX += (eat.playerSpeed*(right + (-1 * left)));
			if (right + (-1 * left) != 0) {
				moveCount++;
			}
			break;
		}

		right = 0;
		left = 0;

		switch (timeCount)
		{
		case 120:
			eat.safeareaStart = GetRand(eat.widthX - 300);
			eat.safeareaEnd = eat.safeareaStart + 300;
			timeCount = -1;
			break;
		default:
			timeCount++;
			break;
		}


		if (eat.playerX >= eat.widthX) {
			eat.playerX = eat.widthX;
		}
		else if (eat.playerX <= 0) {
			eat.playerX = 0;
		}

		/*プレイヤーの向きや移動系*/
		if (moveCount >= 1) {
			if (moveTime >= 7) {
				if (move >= 16) {
					move = 0;
				}
				else {
					move += 8;
				}
				moveTime = 0;
			}
			else {
				moveTime++;
			}
			direction = move;
		}
		else {
			direction = 0;
		}

		if (gacha(eat.probability2) == 1) {
			eat.gameoverNumber = GetRand(eat.score >> 9);

			for (int i = 0; i < eat.gameoverNumber; i++) {
				for (int j = 0; j < 256; j++) {
					if (eat.item[j] == 0) {
						eat.item[j] = 255;
						eat.itemS[j] = GetRand(179);
						eat.itemX[j] = GetRand(eat.widthX);
						eat.itemY[j] = -100;

						if (eat.safeareaStart <= eat.itemX[j] && eat.safeareaEnd >= eat.itemX[j]) {
							eat.item[j] = 0;
						}
						break;
					}
				}
			}
		}

		if (gacha(eat.probability) == 1) {
			eat.itemNumber = 1 + GetRand(eat.itemNumberData - 1);


			for (int i = 0; i < eat.itemNumber; i++) {
				for (int j = 0; j < 256; j++) {
					if (eat.item[j] == 0) {
						rand = GetRand(4);
						switch (rand)
						{
						case 1:
							eat.item[j] = RL_ITEM_RED_MUSHROOM;
							break;
						case 2:
							eat.item[j] = RL_ITEM_BLUE_MUSHROOM;
							break;
						case 3:
							eat.item[j] = RL_ITEM_SEAWEED;
							break;
						case 4:
							eat.item[j] = RL_ITEM_CHESTNUT;
							break;
						default:
							eat.item[j] = RL_ITEM_MONEY;
							break;
						}

						eat.itemS[j] = GetRand(179);
						eat.itemX[j] = GetRand(eat.widthX);
						eat.itemY[j] = -100;
						break;
					}
				}
			}
		}


		for (int i = 0; i < 256; i++) {
			switch (eat.item[i]) {
			case 0:
				break;
			default:
				switch (gameCount)
				{
				case 0:
					eat.itemY[i] += 5;
					break;
				}
				if (eat.playerItemCount < 1024 && eat.itemY[i] + 30 <= eat.playerY + 50 - eat.playerItemCount * 2 && eat.itemY[i] >= eat.playerY - eat.playerItemCount * 2 && eat.itemX[i] >= eat.playerX - 60 && eat.itemX[i] <= eat.playerX + 60) {
					switch (eat.item[i]) {
					case 255:
						PlaySoundMem(mainSE[END_SE], DX_PLAYTYPE_BACK); //ゲームオーバー音を流す
						gameCount = 1;
						break;
					default:
						PlaySoundMem(mainSE[ITEM_SE], DX_PLAYTYPE_BACK); //アイテム音を流す
						break;
					}

					eat.playerItem[eat.playerItemCount] = eat.item[i];
					eat.playerItemS[eat.playerItemCount] = eat.itemS[i];
					eat.playerItemX[eat.playerItemCount] = eat.itemX[i] - eat.playerX;
					eat.playerItemY[eat.playerItemCount] = eat.itemY[i] - eat.playerY;
					switch (eat.item[i])
					{
					case RL_ITEM_RED_MUSHROOM:
						eat.score += 10;
						break;
					case RL_ITEM_BLUE_MUSHROOM:
						eat.score += 50;
						break;
					case RL_ITEM_SEAWEED:
						eat.score += 20;
						break;
					case RL_ITEM_CHESTNUT:
						eat.score += 15;
						break;
					default:
						eat.score += 60;
						break;
					}
					eat.item[i] = 0;
					eat.itemS[i] = 0;
					eat.itemX[i] = 0;
					eat.itemY[i] = 0;
					eat.playerItemCount++;
				}

				if (eat.itemY[i] - 30 >= eat.widthY) {
					eat.item[i] = 0;
					eat.itemS[i] = 0;
					eat.itemX[i] = 0;
					eat.itemY[i] = 0;
				}
				else {
					DrawRotaGraph((int)(eat.itemX[i]), (int)(eat.itemY[i]), 0.5, eat.itemS[i] / 90.0*PI, mapChipItem[eat.item[i]], TRUE);
				}
				break;
			}
		}

		for (int i = eat.playerItemCount - 1; i >= 0; i--) {
			DrawRotaGraph((int)((eat.playerX + eat.playerItemX[i])), (int)((eat.playerY + eat.playerItemY[i])), 0.5, eat.playerItemS[i] / 90.0*PI, mapChipItem[eat.playerItem[i]], TRUE);
		}

		if (CheckHitKey(KEY_INPUT_ESCAPE) && gameCount == 0 && eat.score > 0)
		{
			break;
		}

		switch (gameCount)
		{
		case 1:
			DrawFormatStringToHandle((int)((PIXELX >> 1) - 250), (int)((PIXELY >> 1) - 100), WHITE, FontHandle, "ゲームオーバー");
			DrawFormatStringToHandle((int)((PIXELX >> 1) - 250), (int)((PIXELY >> 1)), WHITE, FontHandle, "スコア: %d円相当", eat.score);
			DrawFormatStringToHandle((int)(PIXELX - 540), (int)(PIXELY - 50), WHITE, FontHandle2, " Produced by Gaccho , Music tsuzu");

			if (CheckHitKey(KEY_INPUT_ESCAPE))
			{
				gameCount = 0;
				eat.score = 0;
				for (int i = 0; i < 256; i++) {
					eat.item[i] = 0;
					eat.itemS[i] = 0;
					eat.itemX[i] = 0;
					eat.itemY[i] = 0;
				}
				for (int i = 0; i < 1024; i++) {
					eat.playerItem[i] = 0;
					eat.playerItemS[i] = 0;
					eat.playerItemX[i] = 0;
					eat.playerItemY[i] = 0;
				}
				eat.playerX = eat.widthX / 2; //プレイヤーのX座標
				eat.playerY = (int)(eat.widthY*0.7); //プレイヤーのY座標

				eat.playerSpeed = 10; //プレイヤーの速さ
				eat.playerItemCount = 0; //プレイヤーが持っているアイテムの数
				eat.itemCount = 0; //降ってくるアイテムの数
				eat.gameoverNumber = 0; //降ってくるゲームオーバーアイテムの数

			}

			break;
		}

		DrawRotaGraph((int)(eat.playerX), (int)((eat.playerY + 60)), 1.0, 0.0, monsterPicture[RL_MONSTER_IKARI][direction], TRUE);
		DrawRotaGraph((int)(eat.playerX), (int)((eat.playerY + 60)), 1.0, 0.0, basket, TRUE);
		DrawFormatStringToHandle(0, 0, WHITE, FontHandle, "スコア: %d円相当", eat.score);
		if (ScreenFlip() != 0) {
			break;
		}
	}
	DxLib_End();				// DXライブラリ使用の終了処理

	return 0;					// ソフトの終了 
}

#おわりに
こんな形でゲームを紹介しましたが、何か疑問点や改善点などがあれば教えてください。
最後までお付き合いいただきありがとうございました。
「いいね!」していただけると、とても励みになります。

##ソースコードのライセンス

These codes are licensed under CC0.
CC0

ソースコードは自由に使用してください。

12
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?