« 【JavaSE】サイドビューの実験(8/17) | トップページ | 【JavaSE】サイドビューの実験(10/17) »

2010年9月25日 (土)

【JavaSE】サイドビューの実験(9/17)

移動するブロックに関する不具合を修正。

  • 上昇するブロックに乗らずに重なった(スクリーンショット参照)とき、ワタワタしないようにした。
  • 上昇するブロックに乗っていて天井に当たると横方向に座標補正してしまっていたのを真下に落ちるようにした。

移動するブロックに乗っているときの天井の当たり判定のために頭上と足元の境界ラインを分けて管理するようにした。

現時点でキャラクタの状態は地面に立っているかどうかしか必要ないので整理した。

まだ不具合が残っているので次回で修正。

  • カーソルキーで左右移動
  • Zキーでジャンプ

SideViewExp09.java

import isle.videogame.*;
import isle.videogame.image.*;
import java.awt.*;

@SuppressWarnings("serial")
public class SideViewExp09 extends VGStretchCanvas
{
	static final int SCREEN_WIDTH  = 240;
	static final int SCREEN_HEIGHT = 240;

	int pad_states_last;

	byte[][] map = {
		{ 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,0,0,0,0,0 },
		{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,2 },
		{ 1,1,2,2,0,0,2,2,1,1,1,1,1,2,2 },
		{ 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,0,0,0,0,0 },
		{ 1,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,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,1 },
		{ 0,0,0,0,0,0,0,2,0,0,0,0,0,0,1 },
		{ 2,0,0,0,0,0,0,2,0,0,0,0,0,1,2 },
		{ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 },
	};
	VGImage[] BG_imgs;

	VGImage[] Girl_imgs;
	Rectangle Girl_rc = new Rectangle();
	int Girl_nImg;
	int Girl_cWalk;
	boolean Girl_bLeft;
	int Girl_ga;
	int Girl_borderHead; // 当たり判定の頭上の境界
	int Girl_borderFoot; // 当たり判定の足元の境界
	boolean Girl_bStand; // 立っているか

	int[][][] FloatBlockMovements = {
		{{ 0, 0, 50 }, { 0, -1, 64 }, { 0, 0, 50 }, { 0, 1, 64 }},
		{{ 0, 0, 50 }, { 1, 0, 80 }, { 0, 0, 50 }, { -1, 0, 80 }},
	};
	int[] FloatBlock_kind = { 1, 2 };
	Point[] FloatBlock_pt = new Point[2];
	int[] FloatBlock_index = new int[2];
	int[] FloatBlock_count = new int[2];

	Rectangle rcBump = new Rectangle(); // 当たり判定対象用

	public SideViewExp09()
	{
		super(SCREEN_WIDTH, SCREEN_HEIGHT, 60);
		setBackground(Color.DARK_GRAY);

		Image img = getResourceImage("buruma.png");
		Girl_imgs = VGImage.createImages(img, 0, 0, 16, 24, 6);
		Girl_rc.setSize(32-3*2, 48); // 当たり判定基準
		Girl_rc.setLocation(3, 0);

		img = getResourceImage("bg.png");
		BG_imgs = VGImage.createImages(img, 0, 0, 16, 16, 3);

		FloatBlock_pt[0] = new Point(160, 176);
		FloatBlock_index[0] = 0;
		FloatBlock_count[0] = FloatBlockMovements[0][FloatBlock_index[0]][2];
		FloatBlock_pt[1] = new Point(32, 144);
		FloatBlock_index[1] = 0;
		FloatBlock_count[1] = FloatBlockMovements[1][FloatBlock_index[1]][2];
	}

	@Override
	protected void frameUpdate(int skipped)
	{
		int pad_states = getPadStates();
		int pad_trigger = (pad_states_last ^ pad_states) & pad_states;
		pad_states_last = pad_states;
		// 移動前の座標で頭上と足元の当たり判定の境界ラインを設定
		Girl_borderHead = Girl_rc.y;
		Girl_borderFoot = Girl_rc.y + Girl_rc.height;
		// ユーザー操作によるキャラクタの移動処理
		if (Girl_bStand) {
			Girl_nImg = 4;
			if ((pad_states & (1<<PAD_LEFT))  != 0) {
				--Girl_rc.x;
				++Girl_cWalk;
				Girl_cWalk %= 16;
				Girl_nImg = Girl_cWalk / 4;
				Girl_bLeft = true;
			}
			if ((pad_states & (1<<PAD_RIGHT)) != 0) {
				++Girl_rc.x;
				++Girl_cWalk;
				Girl_cWalk %= 16;
				Girl_nImg = Girl_cWalk / 4;
				Girl_bLeft = false;
			}
			if ((pad_trigger & (1<<PAD_BUTTON1)) != 0) {
				Girl_ga = -12;
			}
		}
		else {
			Girl_nImg = 5;
			if (Girl_ga < 8) ++Girl_ga;
			Girl_rc.y += Girl_ga;
			if ((pad_states & (1<<PAD_LEFT))  != 0) {
				--Girl_rc.x;
			}
			if ((pad_states & (1<<PAD_RIGHT)) != 0) {
				++Girl_rc.x;
			}
		}

		// 浮動ブロックの移動
		for (int i=0; i<FloatBlockMovements.length; ++i) {
			int vx = FloatBlockMovements[i][FloatBlock_index[i]][0];
			int vy = FloatBlockMovements[i][FloatBlock_index[i]][1];
			boolean bJoin = false; // キャラクターが乗っているかどうか
			rcBump.setBounds(FloatBlock_pt[i].x, FloatBlock_pt[i].y-1, 32, 1);
			if (FloatBlock_pt[i].y >= Girl_borderFoot && rcBump.intersects(Girl_rc)) bJoin = true;
			// X方向に移動する場合
			if (vx != 0) {
				// キャラクタが乗っていれば同じく移動
				if (bJoin) {
					Girl_rc.x += vx;
				}
				FloatBlock_pt[i].x += vx;
			}
			// Y方向に移動する場合
			if (vy != 0) {
				// キャラクタが乗っていれば同じく移動
				if (bJoin) {
					Girl_rc.y += vy;
					// 下降時に他の床に引っ掛かるよう足元の境界はそのまま
					if (vy < 0) Girl_borderFoot += vy;
				}
				FloatBlock_pt[i].y += vy;
			}
			if (--FloatBlock_count[i] <= 0) {
				FloatBlock_index[i] = (FloatBlock_index[i] + 1) % FloatBlockMovements[i].length;
				FloatBlock_count[i] = FloatBlockMovements[i][FloatBlock_index[i]][2];
			}
		}

		Girl_bStand = false;
		// 固定ブロックとの当たり判定
		for (int i=0,y=0; i<15; ++i,y+=16) {
			for (int j=0,x=0; j<15; ++j,x+=16) {
				doCollideBlock(x, y, map[i][j]);
			}
		}
		// 浮動ブロックとの当たり判定
		for (int i=0; i<FloatBlockMovements.length; ++i) {
			doCollideBlock(FloatBlock_pt[i].x   , FloatBlock_pt[i].y, FloatBlock_kind[i]);
			doCollideBlock(FloatBlock_pt[i].x+16, FloatBlock_pt[i].y, FloatBlock_kind[i]);
		}

		// 最終座標補正
		if (Girl_rc.x < 0) Girl_rc.x = 0;
		if (Girl_rc.x > SCREEN_WIDTH-Girl_rc.width) Girl_rc.x = SCREEN_WIDTH-Girl_rc.width;
	}

	void doCollideBlock(int x, int y, int kind)
	{
		// 天井の判定
		switch (kind) {
		case 2:
			// 横に吹っ飛ばないための除外
			if (y + 16 > Girl_borderHead) break;
			// 天井の当たり判定はブロックの下端だけ
			rcBump.setBounds(x, y+16-1, 16, 1);
			if (!Girl_rc.intersects(rcBump)) break;
			Girl_rc.y = y + 16;
			Girl_ga = 0;
			// 当たり判定境界をリセット
			Girl_borderHead = Girl_rc.y;
			Girl_borderFoot = Girl_rc.y + Girl_rc.height;
		}
		// 床の判定
		switch (kind) {
		case 1: case 2:
			if (Girl_ga < 0) break;
			// 引っ張り上げられないための除外
			if (y < Girl_borderFoot) break;
			// 床の当たり判定はブロックの上端だけ
			// 足元の当たり判定を1ピクセル伸ばすことで
			// 座標補正後もブロックの上に居る状態を維持
			rcBump.setBounds(x, y-1, 16, 2);
			if (!Girl_rc.intersects(rcBump)) break;
			Girl_rc.y = y - Girl_rc.height;
			Girl_ga = 0;
			// 当たり判定境界をリセット
			Girl_borderHead = Girl_rc.y;
			Girl_borderFoot = Girl_rc.y + Girl_rc.height;
			Girl_bStand = true;
		}
		// 壁の判定
		switch (kind) {
		case 2:
			rcBump.setBounds(x, y, 16, 16);
			if (!Girl_rc.intersects(rcBump)) break;
			// 壁にめり込んでいる
			if (Girl_rc.x < x) {
				// ブロックより左寄りなら左に座標補正
				Girl_rc.x = x - Girl_rc.width;
			}
			else {
				// 右に座標補正
				Girl_rc.x = x + 16;
			}
		}
	}

	@Override
	protected void frameStretchRender(Graphics g)
	{
		// 固定ブロックを描画
		for (int i=0,y=0; i<15; ++i,y+=16) {
			for (int j=0,x=0; j<15; ++j,x+=16) {
				BG_imgs[map[i][j]].paint(g, x, y, 0);
			}
		}
		// 浮動ブロックを描画
		for (int i=0; i<FloatBlockMovements.length; ++i) {
			BG_imgs[FloatBlock_kind[i]].paint(g, FloatBlock_pt[i].x   , FloatBlock_pt[i].y, 0);
			BG_imgs[FloatBlock_kind[i]].paint(g, FloatBlock_pt[i].x+16, FloatBlock_pt[i].y, 0);
		}

		g.setColor(Color.YELLOW);
		g.drawLine(0, Girl_borderHead, SCREEN_WIDTH-1, Girl_borderHead);
		g.drawLine(0, Girl_borderFoot-1, SCREEN_WIDTH-1, Girl_borderFoot-1);
		Girl_imgs[Girl_nImg].paint(g, Girl_rc.x-3, Girl_rc.y, 32, 48, Girl_bLeft ? 0 : VGImage.FLIP_HORIZONTAL);
		g.setColor(Color.RED);
		g.drawRect(Girl_rc.x, Girl_rc.y, Girl_rc.width-1, Girl_rc.height-1);
	}

	// $> java -cp SideViewExp.jar SideViewExp09
	public static void main(String[] args)
	{
		new VGFrame(new SideViewExp09(), 640, 480, "サイドビュー実験");
	}
}

|

« 【JavaSE】サイドビューの実験(8/17) | トップページ | 【JavaSE】サイドビューの実験(10/17) »

JavaSE」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)




« 【JavaSE】サイドビューの実験(8/17) | トップページ | 【JavaSE】サイドビューの実験(10/17) »