2Dマップ(チップ)の回転について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
とっくん

2Dマップ(チップ)の回転について

#1

投稿記事 by とっくん » 13年前

初めまして、C言語を始めて2ヶ月のとっくんと申します。

早速なのですが、ナムコの『アサルト』のような左右キーに対応してマップを90度ずつ回転するプログラムを作りたいのですが・・・(サンプルプログラム(マップスクロール基本)を使ってなんとか上下左右にマップをスクロールさせる事はできました)回転がどうしても分からず躓いてます・・・よろしくお願いいたします。
画像

ゆーずぃ

Re:2Dマップ(チップ)の回転について

#2

投稿記事 by ゆーずぃ » 13年前

それは90°回転し終わったものを描くんですか?
それとも描きながら90°まで回転させるんですか?

とっくん

Re:2Dマップ(チップ)の回転について

#3

投稿記事 by とっくん » 13年前

> それは90°回転し終わったものを描くんですか?
> それとも描きながら90°まで回転させるんですか?
返信ありがとうございます。
描きながら90°まで回転させたいのですが・・・ 画像

softya

Re:2Dマップ(チップ)の回転について

#4

投稿記事 by softya » 13年前

DrawRotaGraph2で回転可能です。
http://homepage2.nifty.com/natupaji/DxL ... html#R3N19
中心座標が画面中心になる様に計算してください。

ISLe

Re:2Dマップ(チップ)の回転について

#5

投稿記事 by ISLe » 13年前

マップチップをひとつずつ描画すると角度によってチップのあいだに隙間ができたりゴミのようなピクセルが現れたりすると思います。
オフスクリーンに水平垂直の座標系で描画してからオフスクリーンを回転して描画すると良いです。

DXライブラリでは空のグラフィックを描画対象にできないようなのでいったん回転なしで描画したものを取り込むことになると思います。
【追記】オフスクリーンは1.5倍のサイズがないと回転したとき切れてしまいます。描画と取り込みを最低4回に分けて行う必要がありますね。

#むかしのハードウェアをいまの(汎用の)APIで再現するのは難しいんですよね。
画像

とっくん

Re:2Dマップ(チップ)の回転について

#6

投稿記事 by とっくん » 13年前

皆さん!皆さんありがとうございました。なんとか解決しました。
サンプルプログラムをちょと変更しただけど今の僕にはこれが精一杯です。
見にくくて長いプログラムになってると思いますがこれが僕の限界!です。、
プログラムを送付しておきます。(見にくいけど)
これからも皆さん宜しくご指導お願いします!本当にありがとうございました。これでやっと眠れます・・・

画像

とっくん
記事: 1
登録日時: 13年前

Re: Re:2Dマップ(チップ)の回転について

#7

投稿記事 by とっくん » 13年前

とっくん さんが書きました:サイト新しくなったのですね!
皆さん!ありがとうございました。なんとか解決しました。

新しくなった掲示板へのテスト表示も兼ねてます!

コード:

// 2D回転マップスクロール基本
#include "DxLib.h"
#include <math.h>
#define MAP_SIZE	64			// マップチップ一つのドットサイズ

#define MAP_WIDTH	20			// マップの幅
#define MAP_HEIGHT	16			// マップの縦長さ

#define MOVE_FRAME	32			// 移動にかけるフレーム数

// マップのデータ
int 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, 1, 1, 0, 0, 0, 0, 0, 0, 0 ,  1, 1, 1, 1, 1, 1, 1, 1, 1, 0 } ,
	{ 0, 0, 1, 1, 1, 0, 0, 0, 0, 0 ,  1, 0, 0, 0, 0, 0, 0, 0, 1, 0 } ,
	{ 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 ,  1, 1, 1, 1, 1, 1, 0, 0, 1, 0 } ,
	{ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0 ,  0, 0, 0, 0, 0, 1, 0, 0, 1, 0 } ,
	{ 0, 1, 0, 0, 1, 0, 0, 1, 1, 0 ,  0, 0, 1, 1, 1, 1, 1, 0, 1, 0 } ,
	{ 0, 1, 0, 0, 1, 0, 0, 1, 1, 0 ,  0, 0, 1, 0, 0, 1, 1, 0, 1, 0 } ,
	{ 0, 1, 0, 0, 1, 0, 0, 1, 1, 0 ,  0, 0, 1, 0, 0, 1, 1, 0, 1, 0 } ,

	{ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0 ,  0, 1, 1, 0, 0, 1, 1, 0, 1, 0 } ,
	{ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0 ,  0, 1, 1, 0, 0, 1, 1, 0, 1, 0 } ,
	{ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0 ,  0, 1, 1, 0, 0, 1, 1, 0, 1, 0 } ,
	{ 0, 0, 0, 1, 1, 0, 0, 1, 0, 0 ,  0, 1, 1, 0, 0, 1, 1, 0, 1, 0 } ,
	{ 0, 1, 1, 1, 1, 0, 0, 1, 1, 1 ,  1, 1, 1, 0, 0, 1, 1, 0, 1, 0 } ,
	{ 0, 1, 1, 1, 1, 0, 0, 0, 0, 0 ,  0, 0, 0, 0, 0, 0, 0, 0, 1, 0 } ,
	{ 0, 1, 1, 1, 1, 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 } ,
} ;

// プレイヤーの位置
	int PlayerX , PlayerY ;
	int movx, movy ;	// 移動先の座標
	int Muki ;		// 向き
	int NowInput ;		// 現在のフレームの入力
	int State ;		// 状態
	int Count = 0 ;
	int px,py;
	int kabeGraph,tx,ty;
	float Roll ;
	int time=0;
	float Roll_d;
// マップとプレイヤーの描画関数
void GraphDraw( int ScrollX, int ScrollY )
{
	int j , i ;
	int MapDrawPointX , MapDrawPointY ;		// 描画するマップ座標値
	int DrawMapChipNumX , DrawMapChipNumY ;	// 描画するマップチップの数

	// 描画するマップチップの数をセット
	DrawMapChipNumX = 640 / MAP_SIZE + 2 ;
	DrawMapChipNumY = 480 / MAP_SIZE + 2 ;

	// 画面左上に描画するマップ座標をセット
	MapDrawPointX = PlayerX - ( DrawMapChipNumX / 2 - 1 ) ;
	MapDrawPointY = PlayerY - ( DrawMapChipNumY / 2 - 1 ) ;

	// マップを描く

	px=320;py=240;
	for( i = -1 ; i < DrawMapChipNumY ; i ++ )
	{
		for( j = -1 ; j < DrawMapChipNumX ; j ++ )
		{
		
			// 画面からはみ出た位置なら描画しない
			if( j + MapDrawPointX < 0 || i + MapDrawPointY < 0 ||
				j + MapDrawPointX >= MAP_WIDTH || i + MapDrawPointY >= MAP_HEIGHT ) continue ;

			// マップデータが0だったら四角を描画する
			if( MapData[ i + MapDrawPointY ][ j + MapDrawPointX ] == 0 )
			{
			
			DrawRotaGraph2( px, py,px+32-j * MAP_SIZE-ScrollX,py-i * MAP_SIZE-ScrollY-24,1.5f,Roll+Roll_d,kabeGraph , TRUE,0 ) ;
		
			}
	
		}
	}
	
}
	

// WinMain関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
						 LPSTR lpCmdLine, int nCmdShow )
{
	
	int ScrollX, ScrollY ;
	int PlayerGraph;
	int Map_Rote;
	int movx=0, movy=0 ;	// 移動先の座標
	int Muki ;		// 向き
	int NowInput ;		// 現在のキー入力
	int State ;		// 状態
	int Count=0 ;

// ウインドウモードで起動
	ChangeWindowMode( TRUE );
	if( DxLib_Init() == -1 )	// DXライブラリ初期化処理
	{
		 return -1;				// エラーが起きたら直ちに終了
	}

	// 描画先画面を裏画面にする
	SetDrawScreen( DX_SCREEN_BACK ) ;
	
	// 状態の初期化
	State = 0 ;
	Muki = 0 ;
	PlayerGraph = LoadGraph( "Player.bmp" ) ;
	kabeGraph=LoadGraph( "Tex3.bmp" ) ;
	
	// プレイヤーの初期位置をセット
	PlayerX = 2 ;
	PlayerY = 2 ;

	// ループ
	while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )
	{
		// 画面を初期化
		ClearDrawScreen() ;
	
			// キー入力を得る
			NowInput = GetJoypadInputState( DX_INPUT_KEY_PAD1 ) ;
// 状態によって処理を分岐
		switch( State )
		{
		case 0 :	// 入力待ち状態

			// 上が押されたら向いている方向に移動する状態に移行する
			if( ( NowInput & PAD_INPUT_UP ) != 0 )
			{
				// 向きによって移動方向が変わる
				switch( Muki )
				{
				case 0 : movx =  0 ; movy =  -1 ; break ;		// 上方向
				case 1 : movx =  -1 ; movy = 0 ; break ;		// 左方向
				case 2 : movx = 0 ; movy =  1 ; break ;		// 下方向
				case 3 : movx =  1 ; movy =  0 ; break ;		// 右方向
				}

				// 移動先のマスが道だったら移動する
				if( MapData[ PlayerY + movy ][ PlayerX + movx ] == 1 )
				{
					// 状態を前進中にする
					State = 1 ;
					Count = 0 ;
				}
			}
				// 下が押されたら向いている方向と逆方向に移動する
			if( ( NowInput & PAD_INPUT_DOWN ) != 0 )
			{
				// 向きによって移動方向が変わる
				switch( Muki )
				{
				case 0 : movx = 0 ; movy =  1 ; break ;		// 下方向
				case 1 : movx =  1 ; movy =  0 ; break ;		// 右方向
				case 2 : movx =  0 ; movy =  -1 ; break ;		// 上方向
				case 3 : movx =  -1 ; movy = 0 ; break ;		// 左方向
				}

				// 移動先のマスが道だったら移動する
				if( MapData[ PlayerY + movy ][ PlayerX + movx ] == 1 )
				{
					// 状態を後退中にする
					State = 2 ;
					Count = 0 ;
				}
			}

			// 左が押されていたら向いている方向を左に90度変更する
			if( ( NowInput & PAD_INPUT_LEFT ) != 0 )
			{
				// 状態を左旋回中にする
				State = 3 ;
				Count = 0 ;
			}

			// 右が押されていたら向いている方向を右に90度変更する
			if( ( NowInput & PAD_INPUT_RIGHT ) != 0 )
			{
				// 状態を右旋回中にする
				State = 4 ;
				Count = 0 ;
			}

			break ;

		case 1 :	// 前進中状態
			// カウントを進める
			Count ++ ;

			// カウントが移動時間に達したら実座標を移動して入力待ち状態に戻る
			if( Count == MOVE_FRAME )
			{
				PlayerX += movx ;
				PlayerY += movy ;

				State = 0 ;
				Count = 0 ;
			}
			break ;

		case 2 :	// 後退中状態
			// カウントを進める
			Count ++ ;		

			// カウントが移動時間に達したら実座標を移動して入力待ち状態に戻る
			if( Count == MOVE_FRAME )
			{
				PlayerX += movx ;
				PlayerY += movy ;

				State = 0 ;
				Count = 0 ;
			}
			break ;

		case 3 :	// 左旋回中状態
			// カウントを進める
			Count ++ ;
			Map_Rote=1;
			movx=0;
			movy=0;
	
			Roll_d=((float)Count/32.0f)*PHI_F/2*Map_Rote; //回転

			// カウントが推移時間に達したら実方向を変更して入力待ち状態に戻る
			if( Count == MOVE_FRAME )
			{
				if( Muki == 3 )
				{
					Muki = 0 ;
				}
				else
				{
					Muki ++ ;
				}
				ScrollX = 0 ;
				ScrollY = 0 ;
				Roll+=Roll_d;

				Roll_d=0.0f;
				State = 0 ;
				Count = 0 ;
			}
			break ;

		case 4 :	// 右旋回中状態
			// カウントを進める
			Count ++ ;
			Map_Rote=-1;
			movx=0;
			movy=0;
			Roll_d=((float)Count/32.0f)*PHI_F/2*Map_Rote; //回転


			// カウントが推移時間に達したら実方向を変更して入力待ち状態に戻る
			if( Count == MOVE_FRAME )
			{
				if( Muki == 0 )
				{
					Muki = 3 ;
				}
				else
				{
					Muki -- ;
				}
					// 停止中は画面のスクロールは行わない
				ScrollX = 0 ;
				ScrollY = 0 ;
				Roll+=Roll_d; //回転更新

				Roll_d=0.0f;  //回転+分をリセット
				State = 0 ;
				Count = 0 ;
			}
			break ;
		}

				// 経過時間からスクロール量を算出する
				ScrollX = -(movx * MAP_SIZE * Count / MOVE_FRAME ) ;
				ScrollY = -( movy * MAP_SIZE * Count / MOVE_FRAME ) ;

		// マップとプレイヤーを描画
		GraphDraw( ScrollX, ScrollY ) ;
	
			// プレイヤーを描画する
		DrawGraph( 320-16 , 240-32 , PlayerGraph , TRUE ) ;


		// 裏画面の内容を表画面に映す
		ScreenFlip() ;
	}

	DxLib_End() ;				// DXライブラリ使用の終了処理

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

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: 2Dマップ(チップ)の回転について

#8

投稿記事 by ISLe » 13年前

#解決マークが付いてますが。
MakeScreenというリファレンスページには載っていない命令でオフスクリーンを作成できるそうです。
1) MakeScreenが返したグラフィックハンドルをSetDrawScreenで指定して描画対象をオフスクリーンにします。
2) 直交座標でマップを描画します。
3) SetDrawScreen(DX_SCREEN_BACK)で描画対象を裏画面に戻します。
4) MakeScreenが返したグラフィックハンドルでDrawGraph系の命令を呼び出しオフスクリーンに描いたマップを裏画面に描画します。
以上の手順でコードを大きく変更することなしに綺麗に回転させることができると思います。

閉鎖

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