Обработка пользовательского ввода

Последнее обновление: 1.11.2015

Обработка пользовательского ввода предполагает обработку событий клавиатуры и мыши и не сильно отличается от общей модели, что используется в javascript, например, при создании игр с использованием элемента canvas.

Создадим программу, которая будет по нажатию клавиатуры перемещать куб вперед, назад, а также вращать его:

<script type="text/javascript">
var gl;
var shaderProgram;
var vertexBuffer;
var indexBuffer;
  
var angle = 2.0;//угол вращения в радианах
var zTranslation = -2.0; // смещение по оси Z

var mvMatrix = mat4.create(); 
var pMatrix = mat4.create();

function initShaders() {
	var fragmentShader = getShader(gl.FRAGMENT_SHADER, 'shader-fs');
	var vertexShader = getShader(gl.VERTEX_SHADER, 'shader-vs');

	shaderProgram = gl.createProgram();

	gl.attachShader(shaderProgram, vertexShader);
	gl.attachShader(shaderProgram, fragmentShader);

	gl.linkProgram(shaderProgram);
	 
	if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
		alert("Не удалось установить шейдеры");
	}
	 
	gl.useProgram(shaderProgram);

	shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
	gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
	
	shaderProgram.MVMatrix = gl.getUniformLocation(shaderProgram, "uMVMatrix");
    shaderProgram.ProjMatrix = gl.getUniformLocation(shaderProgram, "uPMatrix");
}

function setMatrixUniforms(){
	gl.uniformMatrix4fv(shaderProgram.ProjMatrix,false, pMatrix);
	gl.uniformMatrix4fv(shaderProgram.MVMatrix, false, mvMatrix);  
} 

function getShader(type,id) {
	var source = document.getElementById(id).innerHTML;

	var shader = gl.createShader(type);
	
	gl.shaderSource(shader, source);

	gl.compileShader(shader);
  
	if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
		alert("Ошибка компиляции шейдера: " + gl.getShaderInfoLog(shader));
		gl.deleteShader(shader);   
		return null;
	}
	return shader;  
}

function initBuffers() {

	var	vertices =[
				-0.5, -0.5, 0.5,
				-0.5, 0.5, 0.5,
				 0.5, 0.5, 0.5,
				 0.5, -0.5, 0.5,

				-0.5, -0.5, -0.5,
				-0.5, 0.5, -0.5,
				 0.5, 0.5, -0.5,
				 0.5, -0.5, -0.5];
				 
    var indices = [0, 1, 1, 2, 2, 3, 3, 0, 0, 4, 4, 5, 5, 6, 6,7, 7,4, 1, 5, 2, 6, 3, 7];
	
	vertexBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

	vertexBuffer.itemSize = 3;

	indexBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
	gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
	indexBuffer.numberOfItems = indices.length;
}
 
function draw() {    
	
	gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 
                         vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);

	gl.drawElements(gl.LINES, indexBuffer.numberOfItems, gl.UNSIGNED_SHORT,0);
}
function setupWebGL()
{
	gl.clearColor(0.0, 0.0, 0.0, 1.0); 	
	gl.clear(gl.COLOR_BUFFER_BIT); 
	
	gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
	mat4.perspective(pMatrix, 1.04, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0);
	mat4.identity(mvMatrix);
	mat4.translate(mvMatrix,mvMatrix,[0, 0, zTranslation]);
	mat4.rotate(mvMatrix,mvMatrix, angle, [0, 1, 0]);	
}
 
window.onload=function(){

	var canvas = document.getElementById("canvas3D");
	try {
		gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
	}
	catch(e) {}
  
	  if (!gl) {
		alert("Ваш браузер не поддерживает WebGL");
	  }
	if(gl){
		document.addEventListener('keydown', handleKeyDown, false);
		gl.viewportWidth = canvas.width;
		gl.viewportHeight = canvas.height;
		initShaders();
		
		initBuffers();
		// функция анимации
		(function animloop(){
			setupWebGL();
			setMatrixUniforms();
			draw(); 
		  requestAnimFrame(animloop, canvas);
		})();
		 
	}
}
function handleKeyDown(e){
	switch(e.keyCode)
	{
		case 39:  // стрелка вправо
			angle+=0.1;
			break;
		case 37:  // стрелка влево
			angle-=0.1;
			break;
		case 40:  // стрелка вниз
			zTranslation+=0.1;
			break;
		case 38:  // стрелка вверх
			zTranslation-=0.1;
			break;
	}
}
// настройка анимации
window.requestAnimFrame = (function(){
      return  window.requestAnimationFrame       || 
              window.webkitRequestAnimationFrame || 
              window.mozRequestAnimationFrame    || 
              window.oRequestAnimationFrame      || 
              window.msRequestAnimationFrame     ||
         function(callback, element) {
           return window.setTimeout(callback, 1000/60);
         };
})();
</script>

Вначале для фиксации перемещения задаем две переменных:

var angle = 2.0;//	угол поворота в радианах
var zTranslation = -2.0; // смещение по оси Z

Дальше если у нас задан контекст WebGL, мы регистрируем обработчик события нажатия клавиши: document.addEventListener('keydown', handleKeyDown, false);. Соответственно добавляем в конце функцию обработчика:

function handleKeyDown(e){
	switch(e.keyCode)
	{	
		// изменяем угол поворота
		case 39:  // стрелка вправо
			angle+=0.1;
			break;
		case 37:  // стрелка влево
			angle-=0.1;
			break;
		// изменяем смещение по оси Z
		case 40:  // стрелка вниз
			zTranslation+=0.1;
			break;
		case 38:  // стрелка вверх
			zTranslation-=0.1;
			break;
	}
}

С помощью свойства e.keyCode мы можем узнать код нажатой клавиши и в зависимости от этого выполнить определенные действия. А так как у нас задействована функция анимации requestAnimFrame, то в цикле функции для установки матриц получают новые значения и, таким образом, изменяют положение объекта.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850