2015-11-05 51 views
0

我试图给出一个角度和初始速度的弹丸弹道(形式为炮弹球)的动画。我已经以线条形式构建了“大炮”,并且我以箱子的形式瞄准了目标,我知道这个目标是基本的,但我现在只想让弹丸动作向下。目前,我正在使用硬编码的角度和速度,但最终还是希望输入角度和速度,并在输入后进行大炮拍摄。目标是平行于发射点,所以我知道大炮的x值将是(初始速度)cos(角度)(时间),并且y将是(initialVelocity)sin(角度)(时间) - (g * t^2)/ 2,其中g是长度或距离。目前我所拥有的是一个在屏幕上线性移动的炮弹球,它甚至不在正确的位置开始。在2D WebGL中进行动画制作

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

着色器:

<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); 

} 
+0

这不是一个真正的WebGL问题。 WebGL只是一个光栅化/绘图库。在Javascript中,你可以计算一个位置,方向,然后绘制。您可以使用HTML元素或SVG或Canvas 2D或WebGL进行绘制。执行动画的代码不会改变。 – gman

回答

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