Last active
October 10, 2023 18:43
-
-
Save haehn/c690ed365d2a0367e16834d5ac23beec to your computer and use it in GitHub Desktop.
CS460 Assignment 4 Starter Code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<style> | |
html, body { | |
background-color:#000; | |
margin: 0; | |
padding: 0; | |
height: 100%; | |
overflow: hidden !important; | |
} | |
#computerwrist { | |
background: url('https://cs460.org/assignments/keen/bg.png'); | |
width:1234px; | |
height:814px; | |
position: absolute; | |
top: 50%; | |
left: 50%; | |
transform: translate(-50%, -50%); | |
} | |
#c { | |
width:620px; | |
height:328px; | |
position: absolute; | |
top: 50%; | |
left: 50%; | |
transform: translate(-50%, -50%); | |
} | |
.score { | |
color: rgb(0,255,0); | |
font-size: 30px; | |
font-family: monospace; | |
font-weight: bold; | |
} | |
#keen { | |
position: relative; | |
top: 200px; | |
left: 445px; | |
} | |
#comp { | |
position: relative; | |
top: 200px; | |
left: 855px; | |
} | |
.result { | |
width:332px; | |
height:124px; | |
position: absolute; | |
top: 50%; | |
left: 50%; | |
transform: translate(-50%, -50%); | |
display: none; | |
} | |
#overlay { | |
background-color: rgba(0,0,0,0.7); | |
position: absolute; | |
top: 0px; | |
left: 0px; | |
width: 100%; | |
height: 100%; | |
z-index: 1000; | |
display: none; | |
} | |
</style> | |
<script id="vertexshader" type="glsl"> | |
attribute vec3 position; | |
uniform mat4 transform; | |
void main(void) { | |
vec4 final_position = transform * vec4( position, 1.); | |
gl_Position = final_position; | |
// TODO Part 2 | |
} | |
</script> | |
<script id="fragmentshader" type="glsl"> | |
precision mediump float; | |
uniform vec4 color; | |
void main(void) { | |
gl_FragColor = color; //vec4(1., 1., 1., 1.); | |
} | |
</script> | |
<script> | |
window.onload = function() { | |
//************************************************************// | |
// | |
// INITIALIZE WEBGL | |
// | |
c = document.getElementById( 'c' ); // setup canvas | |
gl = c.getContext( 'webgl' ); // setup GL context | |
gl.viewport(0, 0, c.width, c.height ); | |
//************************************************************// | |
// | |
// SHADERS | |
// | |
v_shader = gl.createShader( gl.VERTEX_SHADER ); | |
f_shader = gl.createShader( gl.FRAGMENT_SHADER ); | |
// compile vertex shader | |
gl.shaderSource( v_shader, document.getElementById( 'vertexshader' ).innerText ); | |
gl.compileShader( v_shader ); | |
if (!gl.getShaderParameter( v_shader, gl.COMPILE_STATUS)) { | |
console.log(gl.getShaderInfoLog( v_shader )); | |
} else { | |
console.log('Vertex Shader compiled!'); | |
} | |
// compile fragment shader | |
gl.shaderSource( f_shader, document.getElementById( 'fragmentshader' ).innerText ); | |
gl.compileShader( f_shader ); | |
if (!gl.getShaderParameter( f_shader, gl.COMPILE_STATUS)) { | |
console.log(gl.getShaderInfoLog( f_shader )); | |
} else { | |
console.log('Fragment Shader compiled!'); | |
} | |
// attach and link the shaders | |
shaderprogram = gl.createProgram(); | |
gl.attachShader( shaderprogram, v_shader ); | |
gl.attachShader( shaderprogram, f_shader ); | |
gl.linkProgram( shaderprogram ); | |
gl.useProgram( shaderprogram ); | |
SCALE = 1; | |
STEP = .1; | |
MAX_SCORE = 5; | |
STOPPED = false; | |
OBJECTS = []; | |
OBJECTS.push( createPaddle( [0.,1.,0.,1.], [0., 0.9, 0.]) ); // TOP PADDLE | |
OBJECTS.push( createPaddle( [0.,1.,0.,1.], [0., -0.9, 0.]) ); // BOTTOM PADDLE | |
OBJECTS.push( createBall( [0., 1., 0., 1.], [0., 0., 0.]) ); | |
resetBall(1); | |
animate(); | |
}; | |
// TODO Part 1 | |
function createRectangle(color, offset) { | |
//************************************************************// | |
// | |
// CREATE GEOMETRY | |
// | |
// | |
// TODO Part 1 | |
// | |
vertices = new Float32Array( [ | |
-0.5, 0.5, 0.0, // V0 // 0 | |
-0.5, -0.5, 0.0, // V1, V4 // 1 | |
0.5, 0.5, 0.0, // V2, V3 // 2 | |
0.5, -0.5, 0.0 // V5 // 3 | |
] ); | |
indices = new Uint8Array( [ 0, 1, 2, // Triangle 1 | |
2, 1, 3 ] ); // Triangle 2 | |
v_buffer = gl.createBuffer(); // create | |
gl.bindBuffer( gl.ARRAY_BUFFER, v_buffer ); // bind | |
gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW ); // put data in | |
gl.bindBuffer( gl.ARRAY_BUFFER, null ); // unbind | |
i_buffer = gl.createBuffer(); // create | |
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, i_buffer ); // bind | |
gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW ); // put data in | |
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, null ); // unbind | |
// TODO Part 2 | |
return [v_buffer, i_buffer, color, offset, 6]; | |
} | |
function createBall(color, offset) { | |
// | |
// TODO Part 2 | |
// | |
} | |
function animate() { | |
if (STOPPED) { | |
return; | |
} | |
requestAnimationFrame( animate ); | |
// CLEAR NOW BEFORE ANY DRAWING | |
gl.clearColor( 0., 0., 0., 0.) | |
gl.clear( gl.COLOR_BUFFER_BIT ); | |
// TODO Part 4 and 5 | |
for(var o=0; o<OBJECTS.length; o++) { | |
var current = OBJECTS[o]; | |
var v_buffer = current[0]; | |
var i_buffer = current[1]; | |
var COLOR = current[2]; | |
var OFFSET = current[3]; | |
var VERTEXCOUNT = current[4]; | |
// TODO Part 2 | |
//************************************************************// | |
// | |
// CONNECT SHADER WITH GEOMETRY | |
// | |
gl.bindBuffer( gl.ARRAY_BUFFER, v_buffer ); | |
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, i_buffer ); | |
// find the attribute in the shader source | |
var a_position = gl.getAttribLocation( shaderprogram, 'position' ); | |
gl.vertexAttribPointer( a_position, 3, gl.FLOAT, false, 0, 0 ); | |
gl.enableVertexAttribArray ( a_position ); | |
var u_color = gl.getUniformLocation( shaderprogram, 'color' ); | |
gl.uniform4fv( u_color, new Float32Array(COLOR)); | |
// var u_offset = gl.getUniformLocation( shaderprogram, 'offset' ); | |
var u_transform = gl.getUniformLocation( shaderprogram, 'transform' ); | |
current_transform = new Float32Array([ | |
SCALE, 0, 0, 0, | |
0, SCALE, 0, 0, | |
0, 0, SCALE, 0, | |
OFFSET[0], OFFSET[1], 0, 1 | |
]); | |
gl.uniformMatrix4fv( u_transform, false, current_transform ); | |
//************************************************************// | |
// | |
// DRAW! | |
// | |
// gl.drawArrays( gl.LINES, 0, 6 ); | |
// TODO Part 2 | |
gl.drawElements( gl.TRIANGLES, VERTEXCOUNT, gl.UNSIGNED_BYTE, 0); | |
} | |
} | |
function resetBall(direction) { | |
OBJECTS[2][3][0] = Math.random() / 10.; // SET TO CENTER | |
OBJECTS[2][3][1] = Math.random() / 10.; | |
BALLDIRECTION = (Math.PI / 8) + Math.random(); | |
BALLDIRECTION *= direction; | |
}; | |
function score(who) { | |
// console.log(who, 'scored!') | |
var old_score = document.getElementById(who).innerText; | |
document.getElementById(who).innerText = parseInt(old_score) + 1; | |
if (parseInt(old_score) == MAX_SCORE-1) { | |
STOPPED = true; | |
document.getElementById('overlay').style.display = 'block'; | |
if (who == 'keen') { | |
document.getElementById('won').style.display = 'block'; | |
} else if (who == 'comp') { | |
document.getElementById('lost').style.display = 'block'; | |
} | |
} | |
if (who == 'keen') { | |
resetBall(1); | |
} else if (who == 'comp') { | |
resetBall(-1); | |
} | |
} | |
function updateComputer() { | |
BALL_X = OBJECTS[2][3][0]; | |
BALL_Y = OBJECTS[2][3][1]; | |
TOP_PADDLE_X = OBJECTS[0][3][0]; | |
TOP_PADDLE_Y = OBJECTS[0][3][1]; | |
if (BALL_X < TOP_PADDLE_X) { | |
OBJECTS[0][3][0] -= STEP/20; | |
} else if (BALL_X > TOP_PADDLE_X) { | |
OBJECTS[0][3][0] += STEP/20; | |
} | |
} | |
function updateBall() { | |
BALL_X = OBJECTS[2][3][0]; | |
BALL_Y = OBJECTS[2][3][1]; | |
TOP_PADDLE_X = OBJECTS[0][3][0]; | |
TOP_PADDLE_Y = OBJECTS[0][3][1]; | |
TOP_PADDLE_WIDTH = 0.2; | |
BOTTOM_PADDLE_X = OBJECTS[1][3][0]; | |
BOTTOM_PADDLE_Y = OBJECTS[1][3][1]; | |
BOTTOM_PADDLE_WIDTH = 0.2; | |
if (BALL_X >= .98) { | |
// RIGHT WALL | |
BALLDIRECTION = (Math.PI - BALLDIRECTION); | |
} else if (BALL_X <= -.98) { | |
// LEFT WALL | |
BALLDIRECTION = (Math.PI - BALLDIRECTION); | |
} else if (BALL_Y >= .85) { | |
// TOP | |
TOP_PADDLE_LEFT = TOP_PADDLE_X - (TOP_PADDLE_WIDTH/2); | |
TOP_PADDLE_RIGHT = TOP_PADDLE_X + (TOP_PADDLE_WIDTH/2); | |
// LET'S CHECK IF A PADDLE IS THERE | |
if (BALL_X >= TOP_PADDLE_LEFT && BALL_X <= TOP_PADDLE_RIGHT) { | |
// console.log('top bounce') | |
// YES, REFLECT | |
BALLDIRECTION = -BALLDIRECTION; | |
} else { | |
// SCORE! | |
score('keen'); | |
return; | |
} | |
} else if (BALL_Y <= -.85) { | |
// BOTTOM | |
BOTTOM_PADDLE_LEFT = BOTTOM_PADDLE_X - (BOTTOM_PADDLE_WIDTH/2); | |
BOTTOM_PADDLE_RIGHT = BOTTOM_PADDLE_X + (BOTTOM_PADDLE_WIDTH/2); | |
// LET'S CHECK IF A PADDLE IS THERE | |
if (BALL_X >= BOTTOM_PADDLE_LEFT && BALL_X <= BOTTOM_PADDLE_RIGHT) { | |
// console.log('bottom bounce') | |
// YES, REFLECT | |
BALLDIRECTION = -BALLDIRECTION; | |
} else { | |
// SCORE! | |
score('comp'); | |
return; | |
} | |
} | |
// UPDATE BALL POSITION | |
OBJECTS[2][3][0] += Math.cos(BALLDIRECTION) * STEP * 0.1; | |
OBJECTS[2][3][1] += Math.sin(BALLDIRECTION) * STEP * 0.1; | |
} | |
window.onkeydown = function(e) { | |
if (STOPPED) { | |
// restart the game | |
window.location.reload(); | |
} | |
// TODO Part 3 | |
} | |
</script> | |
</head> | |
<body> | |
<div id='computerwrist'> | |
<span id='keen' class='score'>0</span> | |
<span id='comp' class='score'>0</span> | |
<div id='overlay'> | |
<img id='won' class='result' src='https://cs460.org/assignments/keen/won.png'> | |
<img id='lost' class='result' src='https://cs460.org/assignments/keen/lost.png'> | |
</div> | |
<canvas id='c'></canvas> | |
</div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment