GameMaker 日本語掲示板

views
17 フォロー
1,131 件中 121 から 160 までを表示しています。
3
生高橋 2024/07/06 (土) 15:32:15

オブジェクトごとに作成したメソッドにF1で飛べるようになってますね。
https://github.com/YoYoGames/GameMaker-Bugs/issues/4322

1
名前なし 2024/07/06 (土) 07:51:57 修正

編集したりするときは、全部の言語一緒の方が、一覧性だったり保管に便利だから一つのファイルの方が楽というのは、わかります。

fontのデータをゲーム実行時に追加できるfont_addがあるので、asaさんのやりたいことができそうかと思いました。

しかし、font_addはGameMakerのフォント画像に追加する文字を、開始と終了の範囲でしか指定できませんでした。
使っている文字だけ追加するエディター上のフォント追加と機能的違いがあります。

今のゲームメッセージリソースCSVはそのままで、
外部ツールとして、PHPでもpythonでもC#でも何でもよいのでCSVを読み込んで、所定の列を入れた新しいCSVを生成するプログラムを作成し、フォント作成のFont Rangeに各CSVを入れるようにするというのはどうでしょうか。
Excelでデータを作っているなら、ExcelのVBAなんかで、ファイル保存したときに自動的に各言語用CSVが生成されるようにすると手間がなくてよいかもしれません。

ゲームメッセージリソースCSVを読み込み
・日本語と英語の文字データだけのCSVを作成する。
・中国語の文字データだけのCSVを作成する。

日本語用と中国語用のフォントを作成し、Font Rangeに各ファイルを入れる。

これで各フォント必要な文字だけ入ったものが出来上がりそうです。

2
名前なし 2024/07/05 (金) 19:32:02 修正

GameMakerで使う乱数は、「疑似乱数」となるので、乱数生成器にrandom_set_seed()で乱数の種を入れて、random()を呼ぶたびに出てくる数字の順番は毎回同じです。
random_set_seedを自発的に記述していない場合でも、内部的にrandom_set_seed(0)で乱数生成を行っているようです。

randomize() or randomise()を呼び出したときは、乱数の種に入れる数字を作り、random_set_seed()にその種を入れるようになっています。

歴史を遡って同じ乱数の値をとるためには、「データの作成時」にrandomizeを呼び出した後、random_get_seed()を使い、乱数の種を取得し、セーブデータや一時データに保管しておく。

その後、randomを使うときは、何回使ったかの回数を保管しておく。

セーブデータロードや戻るコマンド?などで3ターン目や2ターン目に戻ったときは、保管しておいた乱数の種をrandom_set_seed(種の数字)でリセットして、使った回数分randomize()呼び出しを行う。
すると、同じ乱数を取得することができます。

まとめると、

▼メイン処理
randomize()←最初の一回だけ
乱数の種変数「保管する」=random_get_seed()

▼乱数を使うとき
random(数字)
randomを呼び出した回数変数++「保管する」

▼元に戻したいとき
random_set_seed(乱数の種変数)
randomを呼び出した回数変数をループなどでまわして「random(00)」繰り返し呼ぶ
1つ前の乱数を使いたいのでループは「randomを呼び出した回数変数-1」にすればよいと思います。

保管しておくデータは
・乱数の種
・randomを呼び出した回数
だけで同じ乱数を取得できます。

1
生高橋 2024/07/05 (金) 15:35:19 修正

一つ前だけに戻るのであれば、一つ前のサイコロの結果を保存するというのはどうでしょうか

2

レイヤーのインスタンスリストとインスタンスのインスペクターが同時に使えるようになったっぽい?
同時に使えないっていう仕様にずーっと苦労しているので、新しいバージョン使いたい……

2

マリオで言う所のクリボーを作るかクッパを作るかの違いってことですね!確かに作りたいものによりますよね.......ありがとうございます!!!

1

アクションゲームでいうと、
敵キャラが左右に歩き左右の壁にぶつかったら反転するだけというものから、
もっと複雑な条件で複雑に動くもの、そして本来の意味でのAIに近いようなものまであるので
何を作りたいか次第だと思います。

簡単なものなら初心者でも作れると思いますよ。

12
生高橋 2024/06/26 (水) 09:54:23 >> 10

一応次のようなワークフローでやっていこうと思いやす。

1当たり判定ルームをそのままメインルームとして活用し、それをコピーしてタイル追加ルームを作成します(この時点で当たり判定が共有されます)
2タイルが完成したらタイル追加ルームをGITにプッシュします。
3受け取ったタイル追加ルームのタイル情報をツールを使ってメインルームにコピペします。
3当たり判定の変更やステージの追加の変更が起きたら1を繰り返します。

複数ルーム+コピペの自動化ツールというものにとりあえずなりました。
ツールといってもタイル追加ルームの.yyファイルにあるタイル情報を抜き取りそれをメインルームの.yyファイルに上書きするというだけのものです。
一旦はこれでコピペ作業が一瞬で終わらせることができます。

ここからまたいろんな問題がありますがとりあえずこれでなんとかやっていきます。
アイデアありがとうございました。

2
どすこいさん 2024/06/25 (火) 17:07:10

詳しい解説ありがとうございます!解決しました!

11

jsonファイルを扱うライブラリは各言語に星の数ほどあり、jsonを扱うという処理自体、プログラムでよくやりたいことにあがってくることなので、サンプルも数多ありなので、ツール作成の難易度やコストはそこまで高くないかもしれません。GMLがわかる人なら、たぶん簡単に作れるレベルそうです。

問題点があるとすれば、中身のデータが今回のようにただのテキストファイルだと楽ですが、バイナリなど独自の形式になったり、yyのフォーマットが変わったりしたときに、ツールをメンテナンスする必要があることがリスクかもしれません。
yoyoのさじ加減でアップデートが行われることを考えれば、メンテナンスコストの方が、高いかもしれません。

10
生高橋 2024/06/24 (月) 21:43:33

>> 9
ツール作成のコストがかかりますが、実現できたらかなり有効だと感じました。
アイデアありがとうございます!

9
名前なし 2024/06/24 (月) 21:24:24 修正

.yyの中身はjsonフォーマットの様に見えて、中身を見るとレイヤーごとにデータが存在しています。

当たり判定オブジェクトレイヤーと背景などのグラフィックレイヤーが分かれているのであれば、レイヤーごとのデータを取得することができるので、yyに対してインポートやエクスポートできるツールを作って、抜き出したデータのみをgitなどのバージョン管理ツールで管理します。

抜き出したデータは、好きなバージョンをとってきてから、インポートツールでyyに入れることで、やり直したり、当たり判定オブジェクト担当者が、背景のタイル担当者の変更を入れ込むなどの開発ができそうです。

開発用サブツールは、pythonとかrubyとかphpとかwindowsで動く適当な言語で、サブツールを作ると便利になると思います。

8
生高橋 2024/06/24 (月) 16:57:18 修正

>> 6
同じファイル(ここではroomの.yyファイル)を複数人で変更した際に起こる状態で、どちらかの変更を優先するかを選ばないといけません。
ですので、どちらかの変更をなかったことにしないといけないです。

7
生高橋 2024/06/24 (月) 15:41:31

案ありがとうございます!
作業用ルームと最終的なルームで分けるのはいいかもしれません。
ちょっと試してみようかなと思います

6

自分の作業用roomにコピペして作業してる間に相手も作業を進めるので、リアルタイムに同期するのは無理なのでこれがどれくらい問題になるか。
コピペして自分の作業用roomに反映させるのがどれくらい面倒くさいか。
が気になるところです。

追記
ここまで書いて、根本的に的外れか面倒にするだけのことを書いた気がします…!
「競合する」というのは具体的にどういうことが起こるのか教えてもらえるでしょうか?
同じプロジェクトを複数人で編集すると「上書きしちゃう」ってことが起こるという話でしょうか?

4

もっといい方法がある気がしますしどれくらい効率化できるかはやってみないと分かりませんが、
競合させずに同時並行する方法を考えました。
(1)と(2)の作業用roomを用意します。
(1)と(2)の担当者は「相手の作業用roomを変更しない」というルールを守ることとします。
(1)と(2)の作業が完了したら、最終的にroom1に統合します

(1)
当たり判定オブジェクト配置作業用room : room1_for_obj
必要なら背景をroom1_for_backgroundからコピペしてもってくる

(2)
背景制作用room : room1_for_background
必要なら当たり判定objをroom1_for_objからコピペしてもってくる

(3)
(1)(2)を統合して完成させるroom : room1
room1_for_objから当たり判定オブジェクトをコピペする
room1_for_backgroundから背景レイヤーをコピペする

3
生高橋 2024/06/24 (月) 14:07:32 >> 1

(2)のところは背景タイルレイヤーのタイルを追加していく作業も含めます。

1
asa 2024/06/24 (月) 14:03:00 修正

個人的にすごく興味があるこのトピック。
以下の内容で間違いないでしょうか?違っていたら教えて下さい。

roomの構成

  • 移動の当たり判定を、roomに配置した当たり判定用オブジェクトで行う
  • 背景はタイルレイヤーに表示する

(1) 当たり判定オブジェクトを置いてレベルを設計をする担当
ここでの作業は当たり判定用オブジェクトをroomに配置することでしょうか。

(2) 当たり判定オブジェクトに背景のタイルを追加する担当
ここでの作業は背景を描いて背景タイルレイヤーを作ることでしょうか。


同時並行して進めると時間は短縮されるはずだが、競合が起こる。
(1)→(2)または(2)→(1)の順で進めると競合はしないが時間がかかる。
という問題意識でしょうか。

1
生高橋 2024/06/24 (月) 09:16:36

Uses Physicsにチェックが入ってるとオブジェクト側で設定したfixtureがバインドされます。
そこから新たにコード上で用意したfixtureをバインドすると二つのfixtureがバインドされた状態になります。
fixtureは複数バインドすることが可能ですので現状だと複数のfixtureがバインドされている状態になっていると予想します。
どうしても、コード上で独自に用意したfixtureを用意する場合はUses Physicsのチェックを外し、物理変数を全部指定しないといけないっぽいです。
めんどくさいですが、次のようにするとよいかもしれません。

var fixture = physics_fixture_create();
physics_fixture_set_box_shape(fixture,32,32);
physics_fixture_set_density(fixture,0.5);
physics_fixture_set_restitution(fixture,0.5);
physics_fixture_set_collision_group(fixture,1);
physics_fixture_set_linear_damping(fixture,0.1);
physics_fixture_set_angular_damping(fixture,0.1);
physics_fixture_set_friction(fixture,0.2);
physics_fixture_bind(fixture,self);
physics_fixture_delete(fixture);

また、set_restitutionにはややこしいですが二つの関数があります。
・physics_fixture_set_restitution
・physics_set_restitution

physics_fixture_set_restitutionは上の例のように作成したfixtureのrestitutionを変更する関数です。
physics_set_restitutionはすでにバインドされたfixtureのrestitutionを変更する関数です。
physics_set_restitutionの使い方は次の通りです。

var fixture = physics_fixture_create();
physics_fixture_set_box_shape(fixture,16,16);
physics_fixture_set_density(fixture,0.5);
physics_fixture_set_restitution(fixture,0.5);
physics_fixture_set_collision_group(fixture,1);
physics_fixture_set_linear_damping(fixture,0.1);
physics_fixture_set_angular_damping(fixture,0.1);
physics_fixture_set_friction(fixture,0.2);
var bindFixture = physics_fixture_bind(fixture,self);
physics_fixture_delete(fixture);

physics_set_restitution(bindFixture,0.1)

physics_fixture_bindの戻り値を利用してバインドされたfixtureを取得し、そのfixtureのrestitutionを変更します。
バインド済みなので再バインドする必要がありません。

1
生高橋 2024/06/20 (木) 20:57:58

かゆいところに手が届いてないですが、一応使ってます

4
program_suck 2024/06/18 (火) 09:12:28

ありがとうございます!
無事実行できました!

3
生高橋 2024/06/17 (月) 22:23:03 >> 2

了解です。

これを一つに関数にするのはとても難しいと思いますのでオブジェクトで一旦サンプルをつくってみました。
説明しやすいようかなり助長に書いたのでお好きに改善してもらえたらと思います。

CreateEvent

moveway = ["right","down","left","up"];//移動方向の指定
moveSpd = 1;//移動速度
moveDistance = 64;//移動距離
targetX = 0;//目的地のx座標
targetY = 0;//目的のy座標
isMove = 0;//移動中かどうか

StepEvent

//停止中の状態
if(isMove == false)
{
	 //配列の中身があるか
	if(array_length(moveway) > 0)
	{
		//配列の先頭を取得
		var dir = array_first(moveway);
		
		//方向によって目的の座標を決定
		if(dir == "right")
		{
			targetX = x + moveDistance;
			targetY = y;
		}
		else if(dir == "left")
		{
			targetX = x - moveDistance;
			targetY = y;
		}
		else if(dir == "down")
		{
			targetX = x;
			targetY = y + moveDistance;
		}
		else if(dir == "up")
		{
			targetX = x;
			targetY = y - moveDistance;
		}
		
		//先頭の配列を削除
		array_delete(moveway,0,1);
		
		//移動中に設定
		isMove = true;
	}
}

//移動中の状態
if(isMove == true)
{
	//指定した位置まで移動
	x = approach(x, targetX, moveSpd);
	y = approach(y, targetY, moveSpd);
	
	//到着したら移動停止
	if(x == targetX && y == targetY)
	{
		isMove = false;
	}
}

まず移動中と停止中で状態を分けました。
・停止中は配列に値があるか確認して、ある場合はその値を確認して目的座標を決定、移動中にします。
・移動中は目的座標まで移動し、到着したら停止中にします。
以上を配列がなくなるまで繰り返すことで実現しています。
移動させたい場合は配列に方向の文字列を入れればいつでも先頭の順番で移動します。

ここではapproachという目的の数値まで一定の値で加算させるGameMakerではかなり有名な自作関数を使っています。
中身は次の通りです。

function approach(a,b,c)
{
	return a < b ? min(a + c,b) : max(a - c,b);
}

わからないことがあれば聞いてください。

2
program_suck 2024/06/16 (日) 22:22:29 >> 1

説明を全くしておらず申し訳ないです。

objが64移動するのをmovewayの配列によって方向を決める関数なのですが,例えばmoveway=["left","left","down"]だった際,左に128,下に64行った地点に瞬間的に移動してしまいます。
そうではなく,左に64,少しの空き時間,左に64,少しの空き時間...というように,for文が繰り返されるたびに若干の空き時間をつくり、段階的に移動している様に見せたいです。

1
生高橋 2024/06/16 (日) 18:38:48

この関数だとどんな問題があるのですか?

1

Webページ上で遊べる形にしたいということでしたら、
HTML5でエクスポートする形になります

1
program_suck 2024/06/16 (日) 10:16:35

彩度とは少し違いますが、以下のコードで修正することが出来ました。

if (active == false) {
    if (sprite_index != -1) {
        image_blend = c_gray; // グレースケールにする色調
    }
} else {
    if (sprite_index != -1) {
        image_blend = c_white; // 元の色調に戻す
    }
}

2
program_suck 2024/06/14 (金) 23:56:56

ありがとうございます!

1
asa 2024/06/14 (金) 23:07:02 修正

複数のオブジェクトから利用するなら一般的にScriptsに定義するのがいいと思います。
scriptsアセットで定義するとゲーム起動と同時に読み込まれスコープはグローバルになります(つまりどこからでも使えるようになります)。
scriptsには関数、構造体を1つだけ書いてもいいし複数書いてもいいです。

画像1

参考 https://manual.gamemaker.io/beta/en/GameMaker_Language/GML_Overview/Script_Functions.htm

2
ZUN is my dream(19) 2024/06/14 (金) 02:54:51

分かりやすい説明ありがとうございます!!
無事に動くことが出来ました!!

1
//Create Event
//表示する文章
text = ["Hellooooooooooo","Godnightttttttttt"]; //配列にしないと少し面倒なため([]内は一つだけでも大丈夫です)
//配列番号(初期値が0だと一つ目の会話がスキップされてしまうため)
array_index = -1;
//表示可能な文字数
index = 0;
//表示速度(フレーム)
textSpeed = 5;
//文字がすべて表示されたか(初期値が1でないと最初が再生できないため)
next = 1;
//Step Event
//Enterを押したら再生
if(keyboard_check_pressed(vk_enter))
{
     if(next == 1){
        //表示可能文字を0に設定
	index = 0;
        //文字数が最大でないので0に設定
	next = 0;
        //次の会話へ
        array_index ++;
        //アラームイベントをtextSpeedフレーム後に起動
	alarm[0] = textSpeed;
	 }else if(next == 0){
        //index(文字表示数)にテキストの最大文字数を入れる
        index = string_length(text[array_index]);
        //文字数が最大になったので1に設定
        next=1
       }
}

if(array_index!=-1){//array_indexが-1の状態でtext[array_index]を参照させるとエラーが起こるため
if(index == string_length(text[array_index])){
    //文字数が最大になったので1に設定
    next = 1;
}
}
//Alarm[0] Event
//表示可能文字数を増やす
index++;

//表示可能文字数がテキストの文字数未満なら
if(index < string_length(text[array_index]))
{
	//再度アラームイベントをtextSpeedフレーム後に起動
	alarm[0] = textSpeed;
}
//Draw Event
if(array_index>=0){//array_indexが-1の状態でtext[array_index]を参照させるとエラーが起こるため
//テキストの1番目から表示可能文字数までの数を取得
var str = string_copy(text[array_index],1,index);
//それを表示
draw_text(x,y,str);
}

回答者様のコードをベースに色々加えました。元々textは配列ではなかったのですが、配列の方がコードをシンプルにしやすいのと会話イベントなので配列にしても問題ないと思い配列にしています。今回の主な変更としてstepイベント内のEnterを押したときの処理を文字数が最大表示であるかどうかで、「indexにstring_length(text[array_index])、つまり会話の最大文字数を入れる」か、「次の会話に行く」になるようにしました。次の会話がない状態で次の会話へ行こうとするとエラーが起こってしまうので、「次の会話がない時、会話を終了する」等の処理を施してください。

4

if(a==1),if(a==2).......ってやるよりもswitch(a)でやった方がいいのと同じってことですね!!ありがとうございました!!

3

なるほど.....既存のゲームで考えると結構納得できます!!ありがとうございました!!

2

グリッドでデータを管理するインベントリとか、
縦横軸がある表のような形でデータを持たせたい場面があったらそこで使います。
でもそれも一次元配列で作ることはできますので、多次元配列が絶対不可欠というわけではないです。

極論をいうと変数をいっぱい使えば一次元配列すらいらない場面はたくさんあると思います。
でも配列を使うと何かと便利だし分かりやすくなるので使います。

配列、多次元配列を使うと分かりやすくて扱いやすい、便利だから使ういうことじゃないでしょうか。
今現在一次元配列で足りてるのであればそれでいいと思いますよ。

1
生高橋 2024/06/10 (月) 21:34:04

ぷよぷよや不思議のダンジョンなどの格子状形式のシステムでは2次元配列を使います。
3次元、4次元などは使ったことないです。

1
すいか 2024/06/07 (金) 07:53:07

_retを構造体の配列にすることで解決しました!