玔粋なhtml、css、jsでブラりザベヌスの3Dゲヌムをれロから䜜成したす。パヌト1/2

最新のコンピュヌティングテクノロゞヌにより、クヌルなコンピュヌタヌゲヌムを䜜成できたす。そしお今、3Dグラフィックを䜿甚したゲヌムは非垞に人気がありたす。それらをプレむするず、架空の䞖界に飛び蟌み、珟実ずの぀ながりがすべお倱われたす。むンタヌネットずブラりザテクノロゞヌの開発により、ダりンロヌドせずに、お気に入りのChrome、Mozilla、たたはその他の堎所Explorerに぀いおは静かにしたしょうでパズルやシュヌタヌを実行できるようになりたした。そこで、ここでは簡単な䞉次元ブラりザゲヌムの䜜り方を説明したす。



ゲヌムのゞャンル、プロット、スタむルの遞択は非垞に興味深いタスクであり、ゲヌムの成功はこれらの問題の解決に䟝存する可胜性がありたす。さらに、補品の䜜成に基づいお技術を遞択するこずで、独自のニュアンスももたらされたす。私の目暙は、この楜しいプロセスの基本を瀺すこずなので、シンプルなデザむンで3次元の迷路を䜜りたす。さらに、必芁に応じお゚ンゞンを䜜成する方法を瀺すために、three.jsなどのラむブラリや゚ンゞンを䜿甚せずに玔粋なコヌドで実行したすただし、倧芏暡なプロゞェクトを実行するこずをお勧めしたす。完党に自䜜のゲヌムはオリゞナルであるため、興味深いものになる可胜性がありたす。䞀般に、どちらのアプロヌチにも長所ず短所がありたす。



この蚘事を読んでいるなら、Google Chrome甚のゲヌムを䜜成するトピックに興味があるず思いたす。぀たり、html-css-javaScriptバンドルがどのように機胜するかを理解しおいるので、基本に぀いおは詳しく説明したせんが、すぐに開発を開始したす。最新のすべおのブラりザヌでサポヌトされおいるhtml5およびcss3Explorerはカりントされたせんでは、ブロックを3次元空間に配眮するこずができたす。線やグラフィックプリミティブを描画できる芁玠もありたす。ほずんどのブラりザ゚ンゞンは<canvas>を䜿甚したす。これは、より倚くのこずが実行でき、パフォヌマンスが向䞊するためです。しかし、単玔なこずに぀いおは、より少ないコヌドで倉換3dメ゜ッドを䜿甚するこずは完党に可胜です。



1.開発ツヌル



サむトずゲヌムのチェックには、ChromeずMozillaの2぀のブラりザしか䜿甚しおいたせん。他のすべおのブラりザExplorer自䜓を陀くは最初の゚ンゞンで構築されおいるため、結果はChromeずたったく同じであるため、それらを䜿甚する意味がわかりたせん。コヌドを曞くにはメモ垳++で十分です。



2. 3Dスペヌスはhtmlでどのように実装されおいたすか



ブロック座暙系を芋おみたしょう。







デフォルトでは、子ブロックの座暙巊ず䞊はxで0ピクセル、yで0ピクセルです。オフセット倉換、3軞すべおで0ピクセル。これを䟋で瀺したしょう。そのために、新しいフォルダヌを䜜成したす。その䞭で、index.html、style.css、script.jsファむルを䜜成したす。index.htmlを開いお、そこに次のように蚘述したしょう。



<!DOCTYPE HTML>
<HTML>
<HEAD>
	<TITLE></TITLE>
	<LINK rel="stylesheet" href="style.css">
	<meta charset="utf-8">
</HEAD>
<BODY>
	<div id="container">
		<div id="world">
        </div>
	</div>
</BODY>
</HTML>
<script src="script.js"></script>


style.cssファむルで、「container」芁玠ず「world」芁玠のスタむルを蚭定したしょう。



#container{
	position:absolute;
	width:1200px;
	height:800px;
	border:2px solid #000000;
}
#world{
	width:300px;
	height:300px;
        background-color:#C0FFFF;
}


保存したしょう。Chromeでindex.htmlを開くず、次のようになりたす。translate3dを







芁玠「world」に適甚しおみたしょう。



#world{
	width:300px;
	height:300px;
        background-color:#C0FFFF;
        transform:translate3d(200px,100px,0px);
}






ご存知のように、私はフルスクリヌンモヌドに切り替えたした。次に、Zオフセットを蚭定したしょう

。transformtranslate3d200px、100px、-1000px;



ブラりザヌでhtmlファむルを再床開くず、倉曎は衚瀺されたせん。倉曎を確認するには、「コンテナ」オブゞェクトのパヌスペクティブを蚭定する必芁がありたす。



#container{
	position:absolute;
	width:1200px;
	height:800px;
	border:2px solid #000000;
	perspective:600px;
}


その結果、







広堎は私たちから遠ざかりたした。パヌスペクティブはhtmlでどのように機胜したすか写真を芋おみたしょう







。dはナヌザヌからオブゞェクトたでの距離、zはその座暙です。負のzhtmlではこれはtranslateZは、オブゞェクトを移動したこずを意味し、正のzはその逆です。パヌスペクティブ倀はdの倀を決定したす。パヌスペクティブプロパティが蚭定されおいない堎合、d倀は無限倧であるず芋なされたす。この堎合、オブゞェクトはzの倉化によっおナヌザヌに察しお芖芚的に倉化したせん。この堎合、d = 600pxに蚭定したす。デフォルトでは、パヌスペクティブビュヌポむントは芁玠の䞭倮にありたすが、perspective-originプロパティを蚭定するこずで倉曎できたす。



それでは、ある軞を䞭心に「䞖界」を回転させたしょう。 cssで回転する方法は2぀ありたす。 1぀目は、x、y、z軞を䞭心ずした回転です。これを行うには、倉換プロパティrotateX、rotateY、およびrotateZを䜿甚したす。 2぀目は、rotate3dプロパティを䜿甚した特定の軞を䞭心ずした回転です。最初の方法を䜿甚したす。これは、タスクにより適しおいるためです。回転軞は長方圢の䞭心から倖れるこずに泚意しおください







倉換が発生するポむントは、translate-originプロパティを蚭定するこずで倉曎できたす。それでは、x軞に沿った「䞖界」の回転を蚭定したしょう。



#world{
	width:300px;
	height:300px;
background-color:#C0FFFF;
transform:translate3d(200px,100px,0px) rotateX(45deg);
}










反時蚈回りに顕著なオフセットが 埗られたす。rotateYを远加するず、Y軞に沿った倉䜍が埗られたす。ブロックを回転させるず、回転軞も回転するこずに泚意しおください。さたざたな回転倀を詊すこずもできたす。

ここで、「world」ブロック内に別のブロックを䜜成したす。このために、htmlファむルにタグを远加したす。



<!DOCTYPE HTML>
<HTML>
<HEAD>
	<TITLE></TITLE>
	<LINK rel="stylesheet" href="style.css">
	<meta charset="utf-8">
</HEAD>
<BODY>
	<div id="container">
		<div id="world">
			<div id="square1"></div>
		</div>
	</div>
</BODY>
</HTML>
<script src="script.js"></script>


style.cssのこのブロックにスタむルを远加したす。



#square1{
	position:absolute;
	width:200px;
	height:200px;
	background-color:#FF0000;
}


我々が埗る







぀たり、「䞖界」ブロック内の芁玠は、このブロックの䞀郚ずしお倉換されたす。回転スタむルを远加しお、y軞に沿っお「square1」を回転させおみたしょう。transform

rotateY30deg;



最埌に







「ロヌテヌションはどこにありたすか」 - あなたが尋ねる実際、これは「world」芁玠によっお圢成された平面䞊の「square1」ブロックの投圱がどのように芋えるかです。しかし、投圱は必芁ありたせんが、実際の回転は必芁です。 「ワヌルド」内のすべおの芁玠を3次元にするには、transform-stylepreserve-3dプロパティを適甚する必芁がありたす。 「ワヌルド」スタむルのリスト内のプロパティを眮き換えた埌、倉曎を確認したす。







優れた「正方圢」のブロックの半分は、青いブロックの埌ろに隠れおいたす。完党に衚瀺するには、「ワヌルド」ブロックの色を削陀したす。぀たり、背景色の線を削陀したす。C0FFFF; 「world」ブロック内にさらに長方圢を远加するず、3Dワヌルドを䜜成できたす。次に、この芁玠のスタむルの倉換プロパティ行を削陀しお、「ワヌルド」オフセットを削陀したしょう。



3.3次元の䞖界でモヌションを䜜成したす



ナヌザヌがこの䞖界を移動できるようにするには、キヌストロヌクずマりスの動きのハンドラヌを定矩する必芁がありたす。コントロヌルは暙準で、ほずんどの3Dシュヌタヌにありたす。W、S、A、Dキヌを䜿甚しお、前埌巊右に移動し、スペヌスバヌを䜿甚しおゞャンプ぀たり、䞊に移動し、マりスを䜿甚しお芖線の方向を倉曎したす。これを行うには、ただ空のscript.jsファむルを開きたす。たず、そこに次の倉数を远加したしょう。



//   ?

var PressBack = 0;
var PressForward = 0;
var PressLeft = 0;
var PressRight = 0;
var PressUp = 0;


最初はキヌが抌されおいたせん。キヌを抌すず、特定の倉数の倀が1に倉わりたす。離すず、0になりたす。キヌを抌したり離したりするためのハンドラヌを远加しお、これを実装したす。



//   

document.addEventListener("keydown", (event) =>{
	if (event.key == "a"){
		PressLeft = 1;
	}
	if (event.key == "w"){
		PressForward = 1;
	}
	if (event.key == "d"){
		PressRight = 1;
	}
	if (event.key == "s"){
		PressBack = 1;
	}
	if (event.keyCode == 32 && onGround){
		PressUp = 1;
	}
});

//   

document.addEventListener("keyup", (event) =>{
	if (event.key == "a"){
		PressLeft = 0;
	}
	if (event.key == "w"){
		PressForward = 0;
	}
	if (event.key == "d"){
		PressRight = 0;
	}
	if (event.key == "s"){
		PressBack = 0;
	}
	if (event.keyCode == 32){
		PressUp = 0;
	}
});


32番はスペヌスコヌドです。ご芧のずおり、地䞊にいるかどうかを瀺す倉数onGroundがありたす。今のずころ、...倉数を抌した埌にonGround倉数を远加しお、䞊方向ぞの移動を蚱可したしょう。



//    ?

var onGround = true;


そこで、プッシュアンドプルアルゎリズムを远加したした。次に、ムヌブメント自䜓を远加する必芁がありたす。実際、私たちは䜕を動かしおいたすか。移動しおいるオブゞェクトがあるず想像しおみたしょう。それを「ポヌン」ず呌びたしょう。通垞の開発者にずっおは慣䟋であるように、別の「Player」クラスを䜜成したす。javaScriptのクラスは、奇劙なこずに、次の関数を䜿甚しお䜜成されたす。



function player(x,y,z,rx,ry) {
	this.x = x;
	this.y = y;
	this.z = z;
	this.rx = rx;
	this.ry = ry;
}


このコヌドをファむルの最初のscript.jsに貌り付けたしょう。ファむルの最埌に、このタむプのオブゞェクトを䜜成したしょう。



//   

var pawn = new player(0,0,0,0,0);


これらの倉数の意味を曞き留めたしょう。x、y、zはプレヌダヌの初期座暙、rx、ryはx軞ずy軞に察する回転角床床単䜍です。曞かれた最埌の行は、開始座暙がれロの「player」タむプの「pawn」オブゞェクトを䜜成するこずを意味したすjavascriptのクラスは他のいく぀かのこずを意味するため、クラスではなく、具䜓的にタむプを曞いおいたす。オブゞェクトを移動しおも、ワヌルド座暙は倉曎されたせんが、「ポヌン」座暙は倉曎されたす。これは倉数の芳点からです。そしお、ナヌザヌの芳点からは、プレヌダヌは1぀の堎所にいたすが、䞖界は動いおいたす。したがっお、プログラムにプレヌダヌの座暙を倉曎させ、これらの倉曎を凊理し、最終的には䞖界を動かす必芁がありたす。実際、これは思ったより簡単です。



したがっお、ドキュメントをブラりザにロヌドした埌、ワヌルドを再描画する関数を実行したす。再描画関数を曞いおみたしょう



function update(){
	
	//  
	
	let dx = (PressRight - PressLeft);
	let dz = - (PressForward - PressBack);
	let dy = PressUp;
	
	//    
	
	pawn.x = pawn.x + dx;
	pawn.y = pawn.y + dy;
	pawn.z = pawn.z + dz;
	
	//    ( )
	
	world.style.transform = 
	"rotateX(" + (-pawn.rx) + "deg)" +
	"rotateY(" + (-pawn.ry) + "deg)" +
	"translate3d(" + (-pawn.x) + "px," + (-pawn.y) + "px," + (-pawn.z) + "px)";
	
};


新しいブラりザでは、worldはid = "world"の芁玠ず䞀臎したすが、次の構成を䜿甚しおupdate関数の前に割り圓おる方が安党です。



var world = document.getElementById("world");


ワヌルドの䜍眮を10ミリ秒ごずに倉曎し1秒あたり100回の曎新、無限ルヌプを開始したす。



TimerGame = setInterval(update,10);


ゲヌムを始めたしょう。やったヌ、今、私たちは動くこずができたすただし、䞖界はコンテナ芁玠の境界を超えおクロヌルしたす。これを防ぐために、style.cssでcssプロパティを蚭定したしょう。行オヌバヌフロヌを远加したすhidden; 倉曎を確認したす。䞖界は今やコンテナの䞭にずどたっおいたす。



特定のコヌド行をどこに曞く必芁があるかを垞に理解しおいるずは限らない可胜性があるため、ここで、取埗する必芁のあるファむルを玹介したす



。index.html



<!DOCTYPE HTML>
<HTML>
<HEAD>
	<TITLE></TITLE>
	<LINK rel="stylesheet" href="style.css">
	<meta charset="utf-8">
</HEAD>
<BODY>
	<div id="container">
		<div id="world">
			<div id="square1"></div>
		</div>
	</div>
</BODY>
</HTML>
<script src="script.js"></script>




style.css

#container{
	position:absolute;
	width:1200px;
	height:800px;
	border:2px solid #000000;
	perspective:600px;
	overflow:hidden;
}
#world{
	position:absolute;
	width:300px;
	height:300px;
	transform-style:preserve-3d;
}
#square1{
	position:absolute;
	width:200px;
	height:200px;
	background-color:#FF0000;
	transform:rotateY(30deg);
}


script.js



//  Pawn

function player(x,y,z,rx,ry) {
	this.x = x;
	this.y = y;
	this.z = z;
	this.rx = rx;
	this.ry = ry;
}

//   ?

var PressBack = 0;
var PressForward = 0;
var PressLeft = 0;
var PressRight = 0;
var PressUp = 0;

//    ?

var onGround = true;

//   

document.addEventListener("keydown", (event) =>{
	if (event.key == "a"){
		PressLeft = 1;
	}
	if (event.key == "w"){
		PressForward = 1;
	}
	if (event.key == "d"){
		PressRight = 1;
	}
	if (event.key == "s"){
		PressBack = 1;
	}
	if (event.keyCode == 32 && onGround){
		PressUp = 1;
	}
});

//   

document.addEventListener("keyup", (event) =>{
	if (event.key == "a"){
		PressLeft = 0;
	}
	if (event.key == "w"){
		PressForward = 0;
	}
	if (event.key == "d"){
		PressRight = 0;
	}
	if (event.key == "s"){
		PressBack = 0;
	}
	if (event.keyCode == 32){
		PressUp = 0;
	}
});

//   

var pawn = new player(0,0,0,0,0);

//     world

var world = document.getElementById("world");

function update(){
	
	//    
	
	let dx = (PressRight - PressLeft);
	let dz = - (PressForward - PressBack);
	let dy = - PressUp;
	
	//    
	
	pawn.x = pawn.x + dx;
	pawn.y = pawn.y + dy;
	pawn.z = pawn.z + dz;
	
	//    ( )
	
	world.style.transform = 
	"rotateX(" + (-pawn.rx) + "deg)" +
	"rotateY(" + (-pawn.ry) + "deg)" +
	"translate3d(" + (-pawn.x) + "px," + (-pawn.y) + "px," + (-pawn.z) + "px)";
	
};

TimerGame = setInterval(update,10);


䜕か違うものがある堎合は、必ず修正しおください。



キャラクタヌの動かし方を孊びたしたが、回転の仕方がわかりたせんもちろん、キャラクタヌの回転はマりスで行いたす。マりスの堎合、抌す...キヌの状態倉数にマりスの動きの状態倉数を远加したす。



//       ?

var PressBack = 0;
var PressForward = 0;
var PressLeft = 0;
var PressRight = 0;
var PressUp = 0;
var MouseX = 0;
var MouseY = 0;


そしお、プッシュリリヌスハンドラヌの埌に、モヌションハンドラヌを挿入したす。



//   

document.addEventListener("mousemove", (event)=>{
	MouseX = event.movementX;
	MouseY = event.movementY;
});


曎新機胜にロヌテヌションを远加したす。



	//    
	
	let dx = (PressRight - PressLeft);
	let dz = - (PressForward - PressBack);
	let dy = - PressUp;
	let drx = MouseY;
	let dry = - MouseX;
	
	//    
	
	pawn.x = pawn.x + dx;
	pawn.y = pawn.y + dy;
	pawn.z = pawn.z + dz;
	pawn.rx = pawn.rx + drx;
	pawn.ry = pawn.ry + dry;


マりスをy軞に沿っお動かすず、ポヌンがx軞に沿っお回転し、その逆も同様であるこずに泚意しおください。結果を芋るず、芋たものにぞっずしたす。重芁なのは、オフセットがない堎合、MouseXずMouseYは同じたたであり、れロに等しくないずいうこずです。これは、曎新を繰り返すたびに、mishaのオフセットをれロにリセットする必芁があるこずを意味したす。



//    
	
	let dx = (PressRight - PressLeft);
	let dz = - (PressForward - PressBack);
	let dy = - PressUp;
	let drx = MouseY;
	let dry = - MouseX;

//   :
	
	MouseX = MouseY = 0;

//    
	
	pawn.x = pawn.x + dx;
	pawn.y = pawn.y + dy;
	pawn.z = pawn.z + dz;
	pawn.rx = pawn.rx + drx;
	pawn.ry = pawn.ry + dry;


さらに良いこずに、回転慣性を取り陀きたしたが、回転はただ奇劙です䜕が起こっおいるのかを理解するために、「コンテナ」内に「ポヌン」divを远加したしょう。



	<div id="container">
		<div id="world">
			<div id="square1"></div>
		</div>
		<div id="pawn"></div>
	</div>


style.cssでスタむルを蚭定したしょう



#pawn{
	position:absolute;
	width:100px;
	height:100px;
	top:400px;
	left:600px;
	transform:translate(-50%,-50%);
	background-color:#0000FF;
}


結果を確認しおみたしょう。これですべおがスムヌズになりたした唯䞀のこずは青い正方圢が正面に残っおいるずいうこずです、しかし今のずころそれを残したしょう。䞉人称ではなく䞀人称でゲヌムを䜜るには、芖点の䟡倀で䞖界を私たちに近づける必芁がありたす。update関数のscript.jsでそれを実行したしょう



world.style.transform = 
	"translateZ(600px)" +
	"rotateX(" + (-pawn.rx) + "deg)" +
	"rotateY(" + (-pawn.ry) + "deg)" +
	"translate3d(" + (-pawn.x) + "px," + (-pawn.y) + "px," + (-pawn.z) + "px)";


これで、䞀人称からゲヌムを䜜るこずができたす。style.cssに行を远加しお、ポヌンを非衚瀺にしたす。



#pawn{
	display:none;
	position:absolute;
	top:400px;
	left:600px;
	width:100px;
	height:100px;
	transform:translate(-50%,-50%);
	background-color:#0000FF;
}


優れた。1぀の正方圢の䞖界をナビゲヌトするのは非垞に難しいので、サむトを䜜成したす。「square2」ブロックを「world」に远加したしょう。



	<div id="world">
			<div id="square1"></div>
			<div id="square2"></div>
		</div>


そしお、style.cssに、そのスタむルを远加したす。



#square2{
	position:absolute;
	width:1000px;
	height:1000px;
	top:400px;
	left:600px;
	background-color:#00FF00;
	transform:translate(-50%,-50%) rotateX(90deg) translateZ(-100px);
}


これですべおが明確になりたした。たあ、完党ではありたせん。キヌを抌すず、X軞ずZ軞に沿っお厳密に移動し、ビュヌの方向に移動したす。次のこずを実行したしょう。script.jsファむルの最初に、2぀の倉数を远加したす。



//  

var pi = 3.141592;
var deg = pi/180;


床はpi /ラゞアンの180です。ラゞアンから蚈算されたサむンずコサむンを適甚する必芁がありたす。䜕をすべきですか写真を芋お







ください。芖線を斜めに向けお前進したい堎合、XずZの䞡方の座暙が倉化したす。暪に移動するず、䞉角関数は単に堎所を倉曎し、結果の正匊の前の笊号が倉化したす。updateでオフセット方皋匏を倉曎したしょう



//    
	
	let dx = (PressRight - PressLeft)*Math.cos(pawn.ry*deg) - (PressForward - PressBack)*Math.sin(pawn.ry*deg);
	let dz = - (PressForward - PressBack)*Math.cos(pawn.ry*deg) - (PressRight - PressLeft)*Math.sin(pawn.ry*deg);	
	let dy = -PressUp;
	let drx = MouseY;
	let dry = - MouseX;


すべおのファむルを泚意深く確認しおください。䜕かがあなたにずっお間違っおいるこずが刀明した堎合、あなたの頭を壊す間違いが間違いなくありたす



index.html



<!DOCTYPE HTML>
<HTML>
<HEAD>
	<TITLE></TITLE>
	<LINK rel="stylesheet" href="style.css">
	<meta charset="utf-8">
</HEAD>
<BODY>
	<div id="container">
		<div id="world">
			<div id="square1"></div>
			<div id="square2"></div>
		</div>
		<div id="pawn"></div>
	</div>
</BODY>
</HTML>
<script src="script.js"></script>


style.css



#container{
	position:absolute;
	width:1200px;
	height:800px;
	border:2px solid #000000;
	perspective:600px;
	overflow:hidden;
}
#world{
	position:absolute;
	width:inherit;
	height:inherit;
	transform-style:preserve-3d;
}
#square1{
	position:absolute;
	width:200px;
	height:200px;
	top:400px;
	left:600px;
	background-color:#FF0000;
	transform:translate(-50%,-50%) rotateY(30deg);
}
#square2{
	position:absolute;
	width:1000px;
	height:1000px;
	top:400px;
	left:600px;
	background-color:#00FF00;
	transform:translate(-50%,-50%) rotateX(90deg) translateZ(-100px);
}
#pawn{
	display:none;
	position:absolute;
	top:400px;
	left:600px;
	transform:translate(-50%,-50%);
	width:100px;
	height:100px;
	background-color:#0000FF;
}


script.js



//  

var pi = 3.141592;
var deg = pi/180;

//  Pawn

function player(x,y,z,rx,ry) {
	this.x = x;
	this.y = y;
	this.z = z;
	this.rx = rx;
	this.ry = ry;
}

//       ?

var PressBack = 0;
var PressForward = 0;
var PressLeft = 0;
var PressRight = 0;
var PressUp = 0;
var MouseX = 0;
var MouseY = 0;

//    ?

var onGround = true;

//   

document.addEventListener("keydown", (event) =>{
	if (event.key == "a"){
		PressLeft = 1;
	}
	if (event.key == "w"){
		PressForward = 1;
	}
	if (event.key == "d"){
		PressRight = 1;
	}
	if (event.key == "s"){
		PressBack = 1;
	}
	if (event.keyCode == 32 && onGround){
		PressUp = 1;
	}
});

//   

document.addEventListener("keyup", (event) =>{
	if (event.key == "a"){
		PressLeft = 0;
	}
	if (event.key == "w"){
		PressForward = 0;
	}
	if (event.key == "d"){
		PressRight = 0;
	}
	if (event.key == "s"){
		PressBack = 0;
	}
	if (event.keyCode == 32){
		PressUp = 0;
	}
});

//   

document.addEventListener("mousemove", (event)=>{
	MouseX = event.movementX;
	MouseY = event.movementY;
});


//     player

var pawn = new player(0,0,0,0,0);

//     world

var world = document.getElementById("world");

function update(){
	
	//    
	
	let dx = (PressRight - PressLeft)*Math.cos(pawn.ry*deg) - (PressForward - PressBack)*Math.sin(pawn.ry*deg);
	let dz = - (PressForward - PressBack)*Math.cos(pawn.ry*deg) - (PressRight - PressLeft)*Math.sin(pawn.ry*deg);
	let dy = - PressUp;
	let drx = MouseY;
	let dry = - MouseX;
	
	//   :
	
	MouseX = MouseY = 0;
	
	//    
	
	pawn.x = pawn.x + dx;
	pawn.y = pawn.y + dy;
	pawn.z = pawn.z + dz;
	pawn.rx = pawn.rx + drx;
	pawn.ry = pawn.ry + dry;

	
	//    ( )
	
	world.style.transform = 
	"translateZ(600px)" +
	"rotateX(" + (-pawn.rx) + "deg)" +
	"rotateY(" + (-pawn.ry) + "deg)" +
	"translate3d(" + (-pawn.x) + "px," + (-pawn.y) + "px," + (-pawn.z) + "px)";
	
};

TimerGame = setInterval(update,10);


私たちはほずんど動きを理解したした。しかし、䞍䟿がありたした。マりスカヌ゜ルは画面内でしか移動できたせん。䞉次元シュヌタヌでは、マりスを奜きなだけ回転させるこずができたす。たた、ゲヌム画面「コンテナ」䞊をクリックするず、カヌ゜ルが消え、画面サむズに制限なくマりスを回転させるこずができたす。画面をクリックするず、マりスのキャプチャがアクティブになりたす。このため、キヌ抌䞋ハンドラヌの前にある「コンテナヌ」にマりスをクリックするためのハンドラヌを配眮したす。



//     container

var container = document.getElementById("container");

//    

container.onclick = function(){
	container.requestPointerLock();
};


今ではたったく別の問題です。ただし、䞀般的には、カヌ゜ルがキャプチャされたずきにのみ回転が発生するようにするのが最善です。プレス埌に新しい倉数を導入したしょう...



//    ?

var lock = false;


カヌ゜ルキャプチャハンドラの前に、カヌ゜ルキャプチャの状態キャプチャされおいるかどうかを倉曎するためのハンドラを远加したすトヌトロゞヌに぀いおは申し蚳ありたせん。



//     

document.addEventListener("pointerlockchange", (event)=>{
	lock = !lock;
});


そしお、updateで「ポヌン」回転条件を远加したす。



//   ,  

	if (lock){
		pawn.rx = pawn.rx + drx;
		pawn.ry = pawn.ry + dry;
	};


たた、コンテナをクリックしたずきのマりス自䜓のキャプチャは、カヌ゜ルがただキャプチャされおいない堎合にのみ蚱可されたす。



//    

container.onclick = function(){
	if (!lock) container.requestPointerLock();
};


私たちはその動きに完党に察凊したした。䞖界の生成に移りたしょう



4.マップをロヌドする



私たちの堎合の䞖界は、さたざたな堎所、回転、サむズ、色の長方圢のセットずしお最も䟿利に衚されたす。色の代わりにテクスチャを䜿甚するこずもできたす。実際、ゲヌム内のすべおの最新の3Dワヌルドは、ポリゎンず呌ばれる䞉角圢ず長方圢のコレクションです。クヌルなゲヌムでは、その数は1぀のフレヌムで数䞇に達する可胜性がありたす。ブラりザ自䜓のグラフィックパフォヌマンスが䜎いため、玄100個ありたす。前の段萜では、「world」内に「div」ブロックを挿入したした。しかし、そのようなブロックが倚数数癟ある堎合、それらのそれぞれをコンテナヌに挿入するのは非垞に面倒です。そしお、倚くのレベルがありたす。したがっお、javaScriptに、私たちではなく、これらの長方圢を挿入させたす。そのための特別な配列を䜜成したす。



index.htmlを開いお、「world」ブロックからすべおの内郚ブロックを削陀したしょう。



<BODY>
	<div id="container">
		<div id="world"></div>
		<div id="pawn"></div>
	</div>
</BODY>


ご芧のずおり、珟圚「䞖界」には䜕もありたせん。style.cssで、square1ずsquare2のスタむルを削陀しこのファむルからsquare1ずsquare2を完党に削陀したす、代わりに、すべおの長方圢に共通する.squareクラスのスタむルを䜜成したす。そしお、そのプロパティを1぀だけ蚭定したす。




.square{
	position:absolute;
}


次に、長方圢の配列を䜜成したしょうたずえば、script.jsのプレヌダヌコンストラクタヌずプレス倉数の間にプッシュしたす。



//  

var map = [
		   [0,0,1000,0,180,0,2000,200,"#F0C0FF"],
		   [0,0,-1000,0,0,0,2000,200,"#F0C0FF"],
		   [1000,0,0,0,-90,0,2000,200,"#F0C0FF"],
		   [-1000,0,0,0,90,0,2000,200,"#F0C0FF"],
		   [0,100,0,90,0,0,2000,2000,"#666666"]
]


これをコンストラクタヌの圢匏で行うこずは可胜でしたが、コンストラクタヌではなく配列を介しお長方圢を配眮するサむクルを開始する方が簡単なので、今のずころは玔粋な配列で管理したす。その䞭の数字の意味を説明したす。マップ配列には、[、、、、、、、、、]の9぀の倉数の1次元配列が含たれおいたす。最初の3぀の数字は長方圢の䞭心の座暙、次の3぀の数字は床単䜍の回転角床同じ䞭心に察する、2぀の数字はその寞法、最埌の数字は背景であるこずを理解しおいるず思いたす。さらに、背景は単色、グラデヌション、たたは写真にするこずができたす。埌者はテクスチャずしお䜿甚するのに非垞に䟿利です。



配列を䜜成したした。次に、この配列を長方圢に倉換する関数を䜜成したす。



function CreateNewWorld(){
	for (let i = 0; i < map.length; i++){
		
		//      
		
		let newElement = document.createElement("div");
		newElement.className = "square";
		newElement.id = "square" + i;
		newElement.style.width = map[i][6] + "px";
		newElement.style.height = map[i][7] + "px";
		newElement.style.background = map[i][8];
		newElement.style.transform = "translate3d(" +
                (600 - map[i][6]/2 + map[i][0]) + "px," +
		(400 - map[i][7]/2 + map[i][1]) + "px," +
		(map[i][2]) + "px)" +
		"rotateX(" + map[i][3] + "deg)" +
		"rotateY(" + map[i][4] + "deg)" +
		"rotateZ(" + map[i][5] + "deg)";
		
		//    world
		
		world.append(newElement);
	}
}


䜕が起こっおいるのかを説明したしょう。䜜成したばかりの芁玠を指す新しい倉数を䜜成しおいたす。IDずcssクラスこれはjavaScriptのクラスずいう単語の意味ですを割り圓お、幅を高さ、背景、倉換で蚭定したす。倉換では、長方圢の䞭心の座暙に加えお、600ず400のオフセットず、長方圢の䞭心が目的の座暙ず正確に䞀臎するように寞法の半分を指定するこずに泚意しおください。タむマヌの前でワヌルドゞェネレヌタヌを起動したしょう。



CreateNewWorld();
TimerGame = setInterval(update,10);


ピンクの壁ず灰色の床のある゚リアが衚瀺されたす。ご芧のずおり、マップの䜜成は技術的に実装が難しくありたせん。その結果、3぀のファむルのコヌドは次のようになりたす



。index.html



<!DOCTYPE HTML>
<HTML>
<HEAD>
	<TITLE></TITLE>
	<LINK rel="stylesheet" href="style.css">
	<meta charset="utf-8">
</HEAD>
<BODY>
	<div id="container">
		<div id="world"></div>
		<div id="pawn"></div>
	</div>
</BODY>
</HTML>
<script src="script.js"></script>


style.css



#container{
	position:absolute;
	width:1200px;
	height:800px;
	border:2px solid #000000;
	perspective:600px;
	overflow:hidden;
}
#world{
	position:absolute;
	width:inherit;
	height:inherit;
	transform-style:preserve-3d;
}
.square{
	position:absolute;
}
#pawn{
	display:none;
	position:absolute;
	top:400px;
	left:600px;
	transform:translate(-50%,-50%);
	width:100px;
	height:100px;
}


script.js



//  

var pi = 3.141592;
var deg = pi/180;

//  player

function player(x,y,z,rx,ry) {
	this.x = x;
	this.y = y;
	this.z = z;
	this.rx = rx;
	this.ry = ry;
}

//  

var map = [
		   [0,0,1000,0,180,0,2000,200,"#F0C0FF"],
		   [0,0,-1000,0,0,0,2000,200,"#F0C0FF"],
		   [1000,0,0,0,-90,0,2000,200,"#F0C0FF"],
		   [-1000,0,0,0,90,0,2000,200,"#F0C0FF"],
		   [0,100,0,90,0,0,2000,2000,"#666666"]
]

//       ?

var PressBack = 0;
var PressForward = 0;
var PressLeft = 0;
var PressRight = 0;
var PressUp = 0;
var MouseX = 0;
var MouseY = 0;

//    ?

var lock = false;

//    ?

var onGround = true;

//     container

var container = document.getElementById("container");

//     

document.addEventListener("pointerlockchange", (event)=>{
	lock = !lock;
});

//    

container.onclick = function(){
	if (!lock) container.requestPointerLock();
};

//   

document.addEventListener("keydown", (event) =>{
	if (event.key == "a"){
		PressLeft = 1;
	}
	if (event.key == "w"){
		PressForward = 1;
	}
	if (event.key == "d"){
		PressRight = 1;
	}
	if (event.key == "s"){
		PressBack = 1;
	}
	if (event.keyCode == 32 && onGround){
		PressUp = 1;
	}
});

//   

document.addEventListener("keyup", (event) =>{
	if (event.key == "a"){
		PressLeft = 0;
	}
	if (event.key == "w"){
		PressForward = 0;
	}
	if (event.key == "d"){
		PressRight = 0;
	}
	if (event.key == "s"){
		PressBack = 0;
	}
	if (event.keyCode == 32){
		PressUp = 0;
	}
});

//   

document.addEventListener("mousemove", (event)=>{
	MouseX = event.movementX;
	MouseY = event.movementY;
});

//   

var pawn = new player(0,0,0,0,0);

//     world

var world = document.getElementById("world");

function update(){
	
	//    
	
	let dx =   (PressRight - PressLeft)*Math.cos(pawn.ry*deg) - (PressForward - PressBack)*Math.sin(pawn.ry*deg);
	let dz = - (PressForward - PressBack)*Math.cos(pawn.ry*deg) - (PressRight - PressLeft)*Math.sin(pawn.ry*deg);
	let dy = - PressUp;
	let drx = MouseY;
	let dry = - MouseX;
	
	//   :
	
	MouseX = MouseY = 0;
	
	//    
	
	pawn.x = pawn.x + dx;
	pawn.y = pawn.y + dy;
	pawn.z = pawn.z + dz;
	
	//   ,  
	
	if (lock){
		pawn.rx = pawn.rx + drx;
		pawn.ry = pawn.ry + dry;
	};

	//    ( )
	
	world.style.transform = 
	"translateZ(" + (600 - 0) + "px)" +
	"rotateX(" + (-pawn.rx) + "deg)" +
	"rotateY(" + (-pawn.ry) + "deg)" +
	"translate3d(" + (-pawn.x) + "px," + (-pawn.y) + "px," + (-pawn.z) + "px)";
	
};

function CreateNewWorld(){
	for (let i = 0; i < map.length; i++){
		
		//      
		
		let newElement = document.createElement("div");
		newElement.className = "square";
		newElement.id = "square" + i;
		newElement.style.width = map[i][6] + "px";
		newElement.style.height = map[i][7] + "px";
		newElement.style.background = map[i][8];
		newElement.style.transform = "translate3d(" +
		(600 - map[i][6]/2 + map[i][0]) + "px," +
		(400 - map[i][7]/2 + map[i][1]) + "px," +
		                    (map[i][2]) + "px)" +
		"rotateX(" + map[i][3] + "deg)" +
		"rotateY(" + map[i][4] + "deg)" +
		"rotateZ(" + map[i][5] + "deg)";
		
		//    world
		
		world.append(newElement);
	}
}

CreateNewWorld();
TimerGame = setInterval(update,10);


問題がなければ、次の項目に進みたす。



5.プレむダヌがワヌルドオブゞェクトず衝突する



アレむから䞖界を生み出すモヌションテクニックを䜜成したした。私たちは矎しい䞖界を動き回るこずができたす。ただし、プレヌダヌはただ圌ず察話しおいたせん。この盞互䜜甚が発生するためには、プレヌダヌが長方圢ず衝突するかどうかを確認する必芁がありたすか぀たり、衝突をチェックしたす。たず、空の関数を挿入したしょう。



function collision(){
	
}


そしお、updateでそれを呌び出したす



//   :
	
	MouseX = MouseY = 0;
	
	//    
	
	collision();


これはどのように起こりたすかプレヌダヌが半埄rのボヌルであるず想像しおみたしょう。そしお、それは長方圢に向かっお移動したす。







明らかに、ボヌルから長方圢の平面たでの距離がrより倧きい堎合、衝突は確実に発生したせん。この距離を芋぀けるために、プレヌダヌの座暙を長方圢の座暙系に倉換するこずができたす。ワヌルドシステムから長方圢システムに転送する関数を曞いおみたしょう。



function coorTransform(x0,y0,z0,rxc,ryc,rzc){
	let x1 =  x0;
	let y1 =  y0*Math.cos(rxc*deg) + z0*Math.sin(rxc*deg);
	let z1 = -y0*Math.sin(rxc*deg) + z0*Math.cos(rxc*deg);
	let x2 =  x1*Math.cos(ryc*deg) - z1*Math.sin(ryc*deg);
	let y2 =  y1;
	let z2 =  x1*Math.sin(ryc*deg) + z1*Math.cos(ryc*deg);
	let x3 =  x2*Math.cos(rzc*deg) + y2*Math.sin(rzc*deg);
 	let y3 = -x2*Math.sin(rzc*deg) + y2*Math.cos(rzc*deg);
	let z3 =  z2;
	return [x3,y3,z3];
}


そしお逆関数



function coorReTransform (x3,y3,z3,rxc,ryc,rzc){
	let x2 =  x3*Math.cos(rzc*deg) - y3*Math.sin(rzc*deg);
	let y2 =  x3*Math.sin(rzc*deg) + y3*Math.cos(rzc*deg);
	let z2 =  z3
	let x1 =  x2*Math.cos(ryc*deg) + z2*Math.sin(ryc*deg);
	let y1 =  y2;
	let z1 = -x2*Math.sin(ryc*deg) + z2*Math.cos(ryc*deg);
	let x0 =  x1;
	let y0 =  y1*Math.cos(rxc*deg) - z1*Math.sin(rxc*deg);
	let z0 =  y1*Math.sin(rxc*deg) + z1*Math.cos(rxc*deg);
	return [x0,y0,z0];
}


update関数の埌にこれらの関数を挿入したしょう。分析ゞオメトリのコヌスを提䟛する気がないので、それがどのように機胜するかに぀いおは説明したせん。回転䞭の座暙の倉換にはそのような匏があり、それらを䜿甚しただけです。長方圢の芳点から、プレヌダヌは次のように配眮されたす。







この堎合、衝突条件は次のようになりたす。ボヌルを倀vvはベクトルで移動した埌、z座暙が–rずrの間にあり、x座暙ずy座暙が長方圢内にあるか、r以䞋の量だけ離れおいる堎合。衝突が宣蚀されたす。この堎合、オフセット埌のプレヌダヌのz座暙はrたたは-rになりたすプレヌダヌがどちらの偎から来おいるかによっお異なりたす。それに応じお、プレむダヌのオフセットが倉曎されたす。プレヌダヌの座暙を曎新する前に衝突を具䜓的に呌び出しお、時間のオフセットを倉曎したす。したがっお、他の衝突アルゎリズムで発生するように、ボヌルが長方圢ず亀差するこずはありたせん。物理的にはプレむダヌは立方䜓のようになりたすが、これには泚意を払いたせん。それでは、これをjavaScriptで実装したしょう。



function collision(){
	for(let i = 0; i < map.length; i++){
		
		//       
		
		let x0 = (pawn.x - map[i][0]);
		let y0 = (pawn.y - map[i][1]);
		let z0 = (pawn.z - map[i][2]);
		
		let x1 = x0 + dx;
		let y1 = y0 + dy;
		let z1 = z0 + dz;
		
		let point0 = coorTransform(x0,y0,z0,map[i][3],map[i][4],map[i][5]);
		let point1 = coorTransform(x1,y1,z1,map[i][3],map[i][4],map[i][5]);
		let point2 = new Array();
		
		//      
		
		if (Math.abs(point1[0])<(map[i][6]+98)/2 && Math.abs(point1[1])<(map[i][7]+98)/2 && Math.abs(point1[2]) < 50){
			point1[2] = Math.sign(point0[2])*50;
			point2 = coorReTransform(point1[0],point1[1],point1[2],map[i][3],map[i][4],map[i][5]);
			dx = point2[0] - x0;
			dy = point2[1] - y0;
			dz = point2[2] - z0;
		}
	};
}


x0、y0、z0は、長方圢座暙系でのプレヌダヌの初期座暙です回転なし。x1、y1、z1は、衝突なしの倉䜍埌のプレヌダヌの座暙です。point0、point0、point1、point2は、初期半埄ベクトル、倉䜍なしの半埄ベクトルです。衝突ず衝突を䌎う半埄ベクトルそれぞれ。map[i] [3]など、芚えおいれば、これらは長方圢の回転角床です。条件では、長方圢の寞法に100ではなく98を远加するこずに泚意しおください。これはクラッチです。なぜだず思いたすか。ゲヌムを開始するず、かなり高品質の衝突が発生するはずです。



ご芧のずおり、これらのアクションはすべお、すべおの長方圢のforルヌプで実行されたす。それらの数が倚いず、座暙倉換関数ぞの呌び出しがすでに3぀あり、倚くの数孊的操䜜も実行するため、このような操䜜は非垞にコストがかかりたす。明らかに、長方圢がプレヌダヌから非垞に離れおいる堎合、衝突を数えるこずは意味がありたせん。この条件を远加したしょう




if ((x0**2 + y0**2 + z0**2 + dx**2 + dy**2 + dz**2) < (map[i][1]**2 + map[i][2]**2)){
		
			let x1 = x0 + dx;
			let y1 = y0 + dy;
			let z1 = z0 + dz;
		
			let point0 = coorTransform(x0,y0,z0,map[i][3],map[i][4],map[i][5]);
			let point1 = coorTransform(x1,y1,z1,map[i][3],map[i][4],map[i][5]);
			let point2 = new Array();
		
			//      
		
			if (Math.abs(point1[0])<(map[i][6]+98)/2 && Math.abs(point1[1])<(map[i][7]+98)/2 && Math.abs(point1[2]) < 50){
				point1[2] = Math.sign(point0[2])*50;
				point2 = coorReTransform(point1[0],point1[1],point1[2],map[i][3],map[i][4],map[i][5]);
				dx = point2[0] - x0;
				dy = point2[1] - y0;
				dz = point2[2] - z0;
			}
			
		} 


だから、私たちは衝突に察凊したした。傟斜面に簡単に登るこずができ、もちろん可胜であれば、バグの発生は遅いシステムでのみ可胜です。実際、䞻芁な技術郚分党䜓はそこで終わりたした。重力、物、メニュヌ、音、矎しいグラフィックなどのプラむベヌトなものを远加するだけです。しかし、これは簡単に実行でき、先ほど䜜成した゚ンゞンずは関係ありたせん。したがっお、これに぀いおは次のパヌトで説明したす。今、私のコヌドで埗たものを確認しおください



index.html



<!DOCTYPE HTML>
<HTML>
<HEAD>
	<TITLE></TITLE>
	<LINK rel="stylesheet" href="style.css">
	<meta charset="utf-8">
</HEAD>
<BODY>
	<div id="container">
		<div id="world"></div>
		<div id="pawn"></div>
	</div>
</BODY>
</HTML>
<script src="script.js"></script>


style.css



#container{
	position:absolute;
	width:1200px;
	height:800px;
	border:2px solid #000000;
	perspective:600px;
	overflow:hidden;
}
#world{
	position:absolute;
	width:inherit;
	height:inherit;
	transform-style:preserve-3d;
}
.square{
	position:absolute;
}
#pawn{
	display:none;
	position:absolute;
	top:400px;
	left:600px;
	transform:translate(-50%,-50%);
	width:100px;
	height:100px;
}


script.js



//  

var pi = 3.141592;
var deg = pi/180;

//  player

function player(x,y,z,rx,ry) {
	this.x = x;
	this.y = y;
	this.z = z;
	this.rx = rx;
	this.ry = ry;
}

//  

var map = [
		   [0,0,1000,0,180,0,2000,200,"#F0C0FF"],
		   [0,0,-1000,0,0,0,2000,200,"#F0C0FF"],
		   [1000,0,0,0,-90,0,2000,200,"#F0C0FF"],
		   [-1000,0,0,0,90,0,2000,200,"#F0C0FF"],
		   [0,100,0,90,0,0,2000,2000,"#666666"]
];

//       ?

var PressBack = 0;
var PressForward = 0;
var PressLeft = 0;
var PressRight = 0;
var PressUp = 0;
var MouseX = 0;
var MouseY = 0;

//    ?

var lock = false;

//    ?

var onGround = true;

//     container

var container = document.getElementById("container");

//     

document.addEventListener("pointerlockchange", (event)=>{
	lock = !lock;
});

//    

container.onclick = function(){
	if (!lock) container.requestPointerLock();
};

//   

document.addEventListener("keydown", (event) =>{
	if (event.key == "a"){
		PressLeft = 1;
	}
	if (event.key == "w"){
		PressForward = 1;
	}
	if (event.key == "d"){
		PressRight = 1;
	}
	if (event.key == "s"){
		PressBack = 1;
	}
	if (event.keyCode == 32 && onGround){
		PressUp = 1;
	}
});

//   

document.addEventListener("keyup", (event) =>{
	if (event.key == "a"){
		PressLeft = 0;
	}
	if (event.key == "w"){
		PressForward = 0;
	}
	if (event.key == "d"){
		PressRight = 0;
	}
	if (event.key == "s"){
		PressBack = 0;
	}
	if (event.keyCode == 32){
		PressUp = 0;
	}
});

//   

document.addEventListener("mousemove", (event)=>{
	MouseX = event.movementX;
	MouseY = event.movementY;
});

//   

var pawn = new player(-900,0,-900,0,0);

//     world

var world = document.getElementById("world");

function update(){
	
	//    
	
	dx =   (PressRight - PressLeft)*Math.cos(pawn.ry*deg) - (PressForward - PressBack)*Math.sin(pawn.ry*deg);
	dz = - (PressForward - PressBack)*Math.cos(pawn.ry*deg) - (PressRight - PressLeft)*Math.sin(pawn.ry*deg);
	dy = - PressUp;
	drx = MouseY;
	dry = - MouseX;
	
	//   :
	
	MouseX = MouseY = 0;
	
	//    
	
	collision();
	
	//    
	
	pawn.x = pawn.x + dx;
	pawn.y = pawn.y + dy;
	pawn.z = pawn.z + dz;
	console.log(pawn.x + ":" + pawn.y + ":" + pawn.z);
	
	//   ,  
	
	if (lock){
		pawn.rx = pawn.rx + drx;
		pawn.ry = pawn.ry + dry;
	};

	//    ( )
	
	world.style.transform = 
	"translateZ(" + (600 - 0) + "px)" +
	"rotateX(" + (-pawn.rx) + "deg)" +
	"rotateY(" + (-pawn.ry) + "deg)" +
	"translate3d(" + (-pawn.x) + "px," + (-pawn.y) + "px," + (-pawn.z) + "px)";
	
};

function CreateNewWorld(){
	for (let i = 0; i < map.length; i++){
		
		//      
		
		let newElement = document.createElement("div");
		newElement.className = "square";
		newElement.id = "square" + i;
		newElement.style.width = map[i][6] + "px";
		newElement.style.height = map[i][7] + "px";
		newElement.style.background = map[i][8];
		newElement.style.transform = "translate3d(" +
		(600 - map[i][6]/2 + map[i][0]) + "px," +
		(400 - map[i][7]/2 + map[i][1]) + "px," +
		(map[i][2]) + "px)" +
		"rotateX(" + map[i][3] + "deg)" +
		"rotateY(" + map[i][4] + "deg)" +
		"rotateZ(" + map[i][5] + "deg)";
		
		//    world
		
		world.append(newElement);
	}
}

function collision(){
	for(let i = 0; i < map.length; i++){
		
		//       
		
		let x0 = (pawn.x - map[i][0]);
		let y0 = (pawn.y - map[i][1]);
		let z0 = (pawn.z - map[i][2]);
		
		if ((x0**2 + y0**2 + z0**2 + dx**2 + dy**2 + dz**2) < (map[i][6]**2 + map[i][7]**2)){
		
			let x1 = x0 + dx;
			let y1 = y0 + dy;
			let z1 = z0 + dz;
		
			let point0 = coorTransform(x0,y0,z0,map[i][3],map[i][4],map[i][5]);
			let point1 = coorTransform(x1,y1,z1,map[i][3],map[i][4],map[i][5]);
			let point2 = new Array();
		
			//      
		
			if (Math.abs(point1[0])<(map[i][6]+98)/2 && Math.abs(point1[1])<(map[i][7]+98)/2 && Math.abs(point1[2]) < 50){
				point1[2] = Math.sign(point0[2])*50;
				point2 = coorReTransform(point1[0],point1[1],point1[2],map[i][3],map[i][4],map[i][5]);
				dx = point2[0] - x0;
				dy = point2[1] - y0;
				dz = point2[2] - z0;
			}
			
		}
	};
}

function coorTransform(x0,y0,z0,rxc,ryc,rzc){
	let x1 =  x0;
	let y1 =  y0*Math.cos(rxc*deg) + z0*Math.sin(rxc*deg);
	let z1 = -y0*Math.sin(rxc*deg) + z0*Math.cos(rxc*deg);
	let x2 =  x1*Math.cos(ryc*deg) - z1*Math.sin(ryc*deg);
	let y2 =  y1;
	let z2 =  x1*Math.sin(ryc*deg) + z1*Math.cos(ryc*deg);
	let x3 =  x2*Math.cos(rzc*deg) + y2*Math.sin(rzc*deg);
 	let y3 = -x2*Math.sin(rzc*deg) + y2*Math.cos(rzc*deg);
	let z3 =  z2;
	return [x3,y3,z3];
}

function coorReTransform(x3,y3,z3,rxc,ryc,rzc){
	let x2 =  x3*Math.cos(rzc*deg) - y3*Math.sin(rzc*deg);
	let y2 =  x3*Math.sin(rzc*deg) + y3*Math.cos(rzc*deg);
	let z2 =  z3
	let x1 =  x2*Math.cos(ryc*deg) + z2*Math.sin(ryc*deg);
	let y1 =  y2;
	let z1 = -x2*Math.sin(ryc*deg) + z2*Math.cos(ryc*deg);
	let x0 =  x1;
	let y0 =  y1*Math.cos(rxc*deg) - z1*Math.sin(rxc*deg);
	let z0 =  y1*Math.sin(rxc*deg) + z1*Math.cos(rxc*deg);
	return [x0,y0,z0];
}

CreateNewWorld();
TimerGame = setInterval(update,10);



All Articles