Hatena::Groupgamehell

ゲームプログラムめも日記 このページをアンテナに追加 RSSフィード

けんもほろろ  / オススメゲームプログラム本  / 作ったもの置き場  
ゲーム開発のデザパタまとめ  / めも日記まとめ  

2006-11-08

[]RectWinderプレイ動画 RectWinderプレイ動画 - ゲームプログラムめも日記 を含むブックマーク はてなブックマーク - RectWinderプレイ動画 - ゲームプログラムめも日記 RectWinderプレイ動画 - ゲームプログラムめも日記 のブックマークコメント

そういえば、RectWinderって、9000点も取れたっけ?

と思って、どんなプレイをしたのか気になっていたのですが、

おめがさんがプレイ動画をアップしてくれました。

凄すぎ!こんなプレイ想定外です!!

発狂モード発狂モードじゃないよー。

 

[]RectWinder感想続きの感想 RectWinder感想続きの感想 - ゲームプログラムめも日記 を含むブックマーク はてなブックマーク - RectWinder感想続きの感想 - ゲームプログラムめも日記 RectWinder感想続きの感想 - ゲームプログラムめも日記 のブックマークコメント

おめがさんが、濃い内容の感想続きを書いてくれたので、それに対する感想いいわけ?)を、、。

 

「打ち返し」が非常に強力なんだけど、
前述のように敵弾が散発的にしかこないので無駄撃ちは厳禁。
打ち返しの連射をするためには、
1発の発射で必ず1機の中型きを落としてクイックリロードを成功させる必要がある。
要求されるのは「敵弾幕の把握」と「打ち返し発動タイミング」。

ここなんですよね。やりたかったのは。

kenmoはピンクが、

高速レーザーのような回避困難な攻撃に対して、(それを覚えて・予測して)

ローズクラッカータイミングよく発動させる

というゲーム性に面白みを感じていたので、

それに特化した感じです。

 

ただ、

結果的に「敵弾をどこに、どれだけ撃たせるか」までを含めたパターン化が必要になる。
上記の要素のうち、どれか一つをミスると、敵弾の増加、打ち返し不能といった致命的状況に落ち込まれる。
平均台の上でバランス崩すと、即落下みたいな。振り落とされないようにする印象。

というのはやりすぎですね。

 

タイミングゲー、ということで少しだけトレジャーの影響を受けているかも、ですが

例えば、エイリアンソルジャーの場合、ミスがジリ貧につながるけど、

弾をカウンターフォースで喰い続けていれば、逆転が可能です。

しかし、RectWinderはそれがないですね。

とにかく逆転の要素が見つからないなー、と。

 

いくつか感じるのはkenmoさんのゲームは「誘導」が足りないと思う。
ほんのりと解法を匂わせるとかそういう…、センス?テクニック?
多少露骨で良いので、プレーヤーが見つけて
「はは~ん、見つけたぞ!そういうことか!」
とニヤニヤできるようにしておく。
プレーヤーが自分で見つけた発見は、プレイのモチベーションに繋がる。
露骨さをコントロールできれば、発見に難易度がつけれるのでより良い。

「誘導」という点を「打ち返し」で言えば、

ギガウィングラジルギもマーズマトリックスも未プレイなので、それらとの比較ができないのですが、

WispLispで言えば、打ち返し(弾喰いチャージ⇒発射)が前方発射のみなので、

戦略が立てやすい作りになっていますね。

 

その点、RectWinderは、打ち返し方向に自由度を持たせているのですが、

「その方向を操作している余裕がない」ので、結局前方が安定になってしまっています。

 

そこを本当に楽しませたいならば、

レベルデザインでうまく調整する必要がありますね。

 

具体的には、

「その方向を操作している余裕がない」ならば、

「特定の方向にグリッドを向けていることが有利な状況」が「継続」するとか。

 

例えば、敵のアルゴリズムが、

1.その場に停止(もしくはゆっくり移動)

2.狙い撃ち弾

という行動を取り続けるならば、敵の方向にグリッドを向けて、

打ち返し狙いをすれば、安定ですよね。

 

そして、その方向を変えることなく、打ち返しを行えるような敵の出現パターンにする。

f:id:kenmo:20061108142747p:image

そうすると、自機の移動のみで、打ち返しで敵を撃破できるようになります。

 

なんとなくですが、

グリッドの操作の特性から考えると、「継続」っていうのがキーワードになるような気もします。

 

もう一つは「選択肢」。
例えば、yes/noの選択肢があるアドベンチャーゲームがあるとしよう。
普通ならyesの後のストーリーも、noの後のストーリーも作り調整するハズ。
これはシューティングでも同様で、アイテムを取った/取らない、中型を倒した/倒さない、
それぞれ両方の状況を考慮する必要がある。
今回の例だと、アイテムを取れなかった/打ち返しを外した状態が極端に不利になる。
この部分は未調整のように感じました。

うまくいくこと前提なんですよね。

それで、本流から外れると、即バットエンド。

 

これじゃ、プレイヤーを納得させることはできないですよね。

 

「なぜ、ミスしたかの理由をプレイヤーに理解・納得させる」

 

ゲーム作りの基本ですね、、。はい。

 

ただ、逆に考えればスペランカー/プリンスオブペルシャばりの、
「基本行為が一撃死を含むような」個性的な特徴を持つゲームとも言える。

kenmo的には、スペランカープリンスオブペルシャも良ゲーなので、

そこらへんの趣向がモロに出ている感じですね。

 

もう少し、一般ユーザーの考えも理解しないと……。

ショット時の自機の移動が遅すぎるのも、一般的な感覚が無いためですね。

虫姫さまふたり」とかもそんなに遅くなるわけじゃないし……。

 

下部分は表示がゲージと被るので、進入不可と認識するか、入りたくない場所として認識すると思います。

これも後付け仕様の弊害か、、。

ゲージは、プレイ邪魔にならないよう配置しないと、、。

 

バグ技発見。
1フレーム中に同種類の弾を複数発当てて敵を倒すと、当てた分の点数が入る/アイテムが出るっぽい。
偶然見つけた後、ソースコード上でも確認した。

敵の当たり判定ループで、ヒット時にbreakしてないという、

しょーもないバグですね、、。

 

 

 

なにはともあれ、おめがさんには楽しんで(苦しんで?)もらえたみたいで光栄ですねー。

作者冥利に尽きます。はい。

[]めも めも - ゲームプログラムめも日記 を含むブックマーク はてなブックマーク - めも - ゲームプログラムめも日記 めも - ゲームプログラムめも日記 のブックマークコメント

private import SDL;
private import opengl;
private import openglu;
private import std.math;

void main()
{
	if(SDL_Init(SDL_INIT_VIDEO) < 0)
	{
		throw new Error("SDL Init Failed.");
	}
	SDL_Surface* screen = SDL_SetVideoMode(640, 480, 0, SDL_OPENGL);
	
	// OpenGL初期化
	glLoadIdentity();
	glMatrixMode(GL_PROJECTION);
	glViewport(0, 0, 640, 480);
	gluPerspective(30, 640.0/480, 1, 1000);

	glClearColor(0, 0, 0, 0);
	// イベントループ
	float x, y;
	x = 0, y = 0;
	
	float r = 0;
	bool done = false;
	SDL_Event e;
	while ( !done ) {
		while ( SDL_PollEvent(&e) ) {
			done = e.type == SDL_QUIT;
		}
		glClear(GL_COLOR_BUFFER_BIT);

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		gluLookAt(0, 480, 50, 0, 0, 0, 0, 1, 0);
		drawWall();

		if(isPress(SDLK_LEFT))  x -= 5;
		if(isPress(SDLK_UP))    y -= 5;
		if(isPress(SDLK_RIGHT)) x += 5;
		if(isPress(SDLK_DOWN))  y += 5;
		glTranslatef(x, 0, y);
		r += 1;
		glRotated(r, 0, 5, 0);
		
		
		glBegin(GL_POLYGON);
		{
			float size = 12;
			glColor3f(1, 0, 0);
			glVertex3d(-size/2, 0, -size/2);
			glColor3f(0, 1, 0);
			glVertex3d(size/2,  0, -size/2);
			glColor3f(0, 0, 1);
			glVertex3d(size/2,  0, size/2);
			glColor3f(1, 1, 0);
			glVertex3d(-size/2, 0, size/2);
		}
		glEnd();
		
		glFlush();
		SDL_GL_SwapBuffers();
		SDL_Delay(1000/30);
	}
	SDL_Quit();

}

void drawWall()
{
	float w = 160;
	float h = 240;
	foreach(y; [-10.0, 10.0])
	{
		drawLine(-w/2, y, -h/2,  w/2, y, -h/2);
		drawLine( w/2, y, -h/2,  w/2, y,  h/2);
		drawLine( w/2, y,  h/2, -w/2, y,  h/2);
		drawLine(-w/2, y,  h/2, -w/2, y, -h/2);
	}
}

void drawLine(float x1, float y1, float z1, float x2, float y2, float z2)
{
	glBegin(GL_LINES);
	{
		glVertex3d(x1, y1, z1);
		glVertex3d(x2, y2, z2);
	}
	glEnd();
}

bool isPress(int id)
{
	Uint8* keys = SDL_GetKeyState(null);
	return keys[id] == SDL_PRESSED;
}