2D WebGL中的动画

时间:2015-11-05 18:06:14

标签: javascript animation graphics

我试图在给定角度和初始速度的情况下为射弹的轨迹(以炮弹的形式)制作动画。我已经以一条线的形式建造了“大炮”,并且我的目标是以盒子的形式瞄准,我知道它是基本的,但我只想暂时让炮弹动作。目前,我正在弄乱硬编码的角度和速度,但最终想输入角度和速度,并在输入后进行大炮射击。目标与发射点平行,所以我知道大炮的x值将是(initialVelocity)cos(角度)(时间),而y将是(initialVelocity)sin(角度)(时间) - (g * t ^ 2)/ 2,其中g是长度或距离。目前我所拥有的是一个在屏幕上线性移动的炮弹,它甚至没有在正确的位置开始。

我不是要求为我编写代码,我只想知道如何让大炮从正确的位置移动,并知道我哪里完全错了。如果我教会如何正确操作着色器,我相信我可以让它达到目标。

着色器:

<script id="vertex-shader" type="x-shader/x-vertex">

precision mediump float;

attribute vec4 vPosition;
attribute vec4 vColor;
varying vec4 fColor;
uniform float time;

void main()
{
 /*old code from manipulating clock hands*/
 /* fColor = vColor;
  float length = sqrt(vPosition.x*vPosition.x + vPosition.y * vPosition.y);
  gl_Position.x = length*cos(theta);
  gl_Position.y = length*sin(theta);
  gl_Position.z = 0.0;
  gl_Position.w = 1.0; */
  fColor = vColor;
  gl_Position = vPosition;
}
</script>

<script id="background-vertex-shader" type="x-shader/x-vertex">

precision mediump float;

attribute vec4 vPosition;
attribute vec4 vColor;
varying vec4 fColor;

void main()
{
  fColor = vColor;
  gl_Position = vPosition;
}
</script>

<script id="fragment-shader" type="x-shader/x-fragment">

precision mediump float;
varying vec4 fColor;

void main()
{
  gl_FragColor = fColor;
}
</script>

WebGL代码:

var gl;
var points = [];
var colors = [];
var cannonpoints = [];
var circlepoints;

var squarepoints;

var baseColors = [
vec3(1.0,0.0,0.0),
vec3(0.0,1.0,0.0),
vec3(0.0,0.0,1.0),
vec3(1.0,1.0,1.0),
vec3(0.0,0.0,0.0)
];

var program;
var backgroundprogram;

var Time; 
var thetaLoc;

var angle;
var initialVel;
var vx;
var vy;



var ballX = -0.5;
var ballY = -0.5;
window.onload = function init(){
var canvas = document.getElementById("gl-canvas");   

gl = WebGLUtils.setupWebGL(canvas);
if(!gl) {
   alert("webGL isn't available");
}

// configuring WebGL
gl.viewport(0,0, 
          canvas.width,canvas.height);
gl.clearColor(0.0,0.0,1.0,1.0); // set background color to black.

// load the shaders and initialize
// the attrbibute buffers.

  program = initShaders(gl, "vertex-shader", "fragment-shader");
 backgroundprogram = initShaders(gl, "background-vertex-shader",    "fragment-  shader");

   document.getElementById("shoot").onclick = function() {
    velocity = document.getElementById("velocity").value;
        angle = document.getElementById("angle").value;
        console.log("angle="+angle);
      vx = (Math.cos(angle*(Math.PI/180))*velocity);
        console.log("vx="+vx);
        vy = (Math.sin(angle*(Math.PI/180))*velocity);
        console.log("vy="+vy);

   }



Time = 0.0;
   thetaLoc = gl.getUniformLocation(program,"time");

   initBackground();
   /******************
   initBall(Time,1);
   *******************/
   initBall(Time);
   //render();
   setInterval(render, 100);
};

function render(){
    gl.clear(gl.COLOR_BUFFER_BIT);

     /* draw the circle */
    gl.drawArrays(gl.TRIANGLE_FAN,0,circlepoints);
    /* draw the square(s) */
    gl.drawArrays(gl.TRIANGLES,circlepoints,squarepoints);
    //draw the cannon
    gl.drawArrays(gl.LINES,circlepoints+squarepoints,2);
    //draw the cannon ball
    //starting index is the amount of points already drawn
      //amount of points for circle + amount of points for square + amount of points for line
    var start = circlepoints + squarepoints + 2;
    Time += 0.01;
    initBall(Time);   //,1);
    gl.uniform1f(thetaLoc,Time);
    //amount of points to draw is length of points array minus the start index
    gl.drawArrays(gl.TRIANGLE_FAN,start,points.length-start);
}

function initBall(Time) {   //,r){
   gl.useProgram(program);

    /*******************************************************
  filled_circle(vec2(r*Math.cos(Time),r*Math.sin(Time)),0.05,4);*/
    vx= (Math.cos(60*(Math.PI/180))*1);
    vy= (Math.sin(60*(Math.PI/180))*1);

  filled_circle(vec2(-0.8+(vx*Time),-0.3+(vy*Time)),0.05,4);

   // Load the data into the GPU
   var bufferId = gl.createBuffer();
   gl.bindBuffer(gl.ARRAY_BUFFER,                  bufferId);
   gl.bufferData(gl.ARRAY_BUFFER, 
                 flatten(points),
                 gl.STATIC_DRAW);

   // Associate our shader variables with
   // the data buffer.
   var vPosition = gl.getAttribLocation(program,"vPosition");
   gl.vertexAttribPointer(vPosition,2,gl.FLOAT,false,0,0);
   gl.enableVertexAttribArray(vPosition);

   // load color data to the gpu
   var cBuffer = gl.createBuffer();
   gl.bindBuffer(gl.ARRAY_BUFFER,
                 cBuffer);
   gl.bufferData(gl.ARRAY_BUFFER,
                 flatten(colors),
                 gl.STATIC_DRAW);

   var vColor = gl.getAttribLocation(
                program, "vColor");
   gl.vertexAttribPointer(vColor,3,
                gl.FLOAT, false, 0, 0);
   gl.enableVertexAttribArray(vColor);

}

1 个答案:

答案 0 :(得分:0)

我认为最简单的方法是给你的射弹一个起始位置,速度和加速度。然后射弹在任何时间的位置是位置+速度*时间+加速度*时间*时间。射弹的角度只是射弹当前速度的角度。

如果你想最终添加碰撞之类的其他东西,那么使射弹跟踪当前的速度和加速度可能是一个好主意;并且在每个帧上,位置和速度基于每帧之间经过的时间而改变。像这样:

Projectile.prototype.update = function(dt){
     this.velocity += this.acceleration * dt;
     this.position += this.velocity * dt;
     this.angle = getAngle(this.velocity);
};

在每个框架上,请致电projectile.update(dt) dt = currentFrameTime - lastFrameTime