|
|
Line 1: |
Line 1: |
| {{ShanghaitechChina}} | | {{ShanghaitechChina}} |
| <html> | | <html> |
− | <html lang="en">
| |
− | <head>
| |
− | <meta charset="UTF-8">
| |
− | <title>Pong</title>
| |
− |
| |
− | <!-- Basic styling, centering the canvas -->
| |
− | <style>
| |
− | canvas {
| |
− | display: block;
| |
− | position: absolute;
| |
− | margin: auto;
| |
− | top: 0;
| |
− | bottom: 0;
| |
− | left: 0;
| |
− | right: 0;
| |
− | }
| |
− | </style>
| |
− | </head>
| |
| <body> | | <body> |
− | <script> | + | </div></div></div></div></div> |
− | var
| + | |
− | /**
| + | |
− | * Constants
| + | |
− | */
| + | |
− | WIDTH = 700,
| + | |
− | HEIGHT = 600,
| + | |
− | pi = Math.PI,
| + | |
− | UpArrow = 38,
| + | |
− | DownArrow = 40,
| + | |
− | /**
| + | |
− | * Game elements
| + | |
− | */
| + | |
− | canvas,
| + | |
− | ctx,
| + | |
− | keystate,
| + | |
− | /**
| + | |
− | * The player paddle
| + | |
− | *
| + | |
− | * @type {Object}
| + | |
− | */
| + | |
− | player = {
| + | |
− | x: null,
| + | |
− | y: null,
| + | |
− | width: 20,
| + | |
− | height: 100,
| + | |
− | /**
| + | |
− | * Update the position depending on pressed keys
| + | |
− | */
| + | |
− | update: function() {
| + | |
− | if (keystate[UpArrow]) this.y -= 7;
| + | |
− | if (keystate[DownArrow]) this.y += 7;
| + | |
− | // keep the paddle inside of the canvas
| + | |
− | this.y = Math.max(Math.min(this.y, HEIGHT - this.height), 0);
| + | |
− | },
| + | |
− | /**
| + | |
− | * Draw the player paddle to the canvas
| + | |
− | */
| + | |
− | draw: function() {
| + | |
− | ctx.fillRect(this.x, this.y, this.width, this.height);
| + | |
− | }
| + | |
− | },
| + | |
− | /**
| + | |
− | * The ai paddle
| + | |
− | *
| + | |
− | * @type {Object}
| + | |
− | */
| + | |
− | ai = {
| + | |
− | x: null,
| + | |
− | y: null,
| + | |
− | width: 20,
| + | |
− | height: 100,
| + | |
− | /**
| + | |
− | * Update the position depending on the ball position
| + | |
− | */
| + | |
− | update: function() {
| + | |
− | // calculate ideal position
| + | |
− | var desty = ball.y - (this.height - ball.side)*0.5;
| + | |
− | // ease the movement towards the ideal position
| + | |
− | this.y += (desty - this.y) * 0.1;
| + | |
− | // keep the paddle inside of the canvas
| + | |
− | this.y = Math.max(Math.min(this.y, HEIGHT - this.height), 0);
| + | |
− | },
| + | |
− | /**
| + | |
− | * Draw the ai paddle to the canvas
| + | |
− | */
| + | |
− | draw: function() {
| + | |
− | ctx.fillRect(this.x, this.y, this.width, this.height);
| + | |
− | }
| + | |
− | },
| + | |
− | /**
| + | |
− | * The ball object
| + | |
− | *
| + | |
− | * @type {Object}
| + | |
− | */
| + | |
− | ball = {
| + | |
− | x: null,
| + | |
− | y: null,
| + | |
− | vel: null,
| + | |
− | side: 20,
| + | |
− | speed: 12,
| + | |
− | /**
| + | |
− | * Serves the ball towards the specified side
| + | |
− | *
| + | |
− | * @param {number} side 1 right
| + | |
− | * -1 left
| + | |
− | */
| + | |
− | serve: function(side) {
| + | |
− | // set the x and y position
| + | |
− | var r = Math.random();
| + | |
− | this.x = side===1 ? player.x+player.width : ai.x - this.side;
| + | |
− | this.y = (HEIGHT - this.side)*r;
| + | |
− | // calculate out-angle, higher/lower on the y-axis =>
| + | |
− | // steeper angle
| + | |
− | var phi = 0.1*pi*(1 - 2*r);
| + | |
− | // set velocity direction and magnitude
| + | |
− | this.vel = {
| + | |
− | x: side*this.speed*Math.cos(phi),
| + | |
− | y: this.speed*Math.sin(phi)
| + | |
− | }
| + | |
− | },
| + | |
− | /**
| + | |
− | * Update the ball position and keep it within the canvas
| + | |
− | */
| + | |
− | update: function() {
| + | |
− | // update position with current velocity
| + | |
− | this.x += this.vel.x;
| + | |
− | this.y += this.vel.y;
| + | |
− | // check if out of the canvas in the y direction
| + | |
− | if (0 > this.y || this.y+this.side > HEIGHT) {
| + | |
− | // calculate and add the right offset, i.e. how far
| + | |
− | // inside of the canvas the ball is
| + | |
− | var offset = this.vel.y < 0 ? 0 - this.y : HEIGHT - (this.y+this.side);
| + | |
− | this.y += 2*offset;
| + | |
− | // mirror the y velocity
| + | |
− | this.vel.y *= -1;
| + | |
− | }
| + | |
− | // helper function to check intesectiont between two
| + | |
− | // axis aligned bounding boxex (AABB)
| + | |
− | var AABBIntersect = function(ax, ay, aw, ah, bx, by, bw, bh) {
| + | |
− | return ax < bx+bw && ay < by+bh && bx < ax+aw && by < ay+ah;
| + | |
− | };
| + | |
− | // check againts target paddle to check collision in x
| + | |
− | // direction
| + | |
− | var pdle = this.vel.x < 0 ? player : ai;
| + | |
− | if (AABBIntersect(pdle.x, pdle.y, pdle.width, pdle.height,
| + | |
− | this.x, this.y, this.side, this.side)
| + | |
− | ) {
| + | |
− | // set the x position and calculate reflection angle
| + | |
− | this.x = pdle===player ? player.x+player.width : ai.x - this.side;
| + | |
− | var n = (this.y+this.side - pdle.y)/(pdle.height+this.side);
| + | |
− | var phi = 0.25*pi*(2*n - 1); // pi/4 = 45
| + | |
− | // calculate smash value and update velocity
| + | |
− | var smash = Math.abs(phi) > 0.2*pi ? 1.5 : 1;
| + | |
− | this.vel.x = smash*(pdle===player ? 1 : -1)*this.speed*Math.cos(phi);
| + | |
− | this.vel.y = smash*this.speed*Math.sin(phi);
| + | |
− | }
| + | |
− | // reset the ball when ball outside of the canvas in the
| + | |
− | // x direction
| + | |
− | if (0 > this.x+this.side || this.x > WIDTH) {
| + | |
− | this.serve(pdle===player ? 1 : -1);
| + | |
− | }
| + | |
− | },
| + | |
− | /**
| + | |
− | * Draw the ball to the canvas
| + | |
− | */
| + | |
− | draw: function() {
| + | |
− | ctx.fillRect(this.x, this.y, this.side, this.side);
| + | |
− | }
| + | |
− | };
| + | |
− | /**
| + | |
− | * Starts the game
| + | |
− | */
| + | |
− | function main() {
| + | |
− | // create, initiate and append game canvas
| + | |
− | canvas = document.createElement("canvas");
| + | |
− | canvas.width = WIDTH;
| + | |
− | canvas.height = HEIGHT;
| + | |
− | ctx = canvas.getContext("2d");
| + | |
− | document.body.appendChild(canvas);
| + | |
− | keystate = {};
| + | |
− | // keep track of keyboard presses
| + | |
− | document.addEventListener("keydown", function(evt) {
| + | |
− | keystate[evt.keyCode] = true;
| + | |
− | });
| + | |
− | document.addEventListener("keyup", function(evt) {
| + | |
− | delete keystate[evt.keyCode];
| + | |
− | });
| + | |
− | init(); // initiate game objects
| + | |
− | // game loop function
| + | |
− | var loop = function() {
| + | |
− | update();
| + | |
− | draw();
| + | |
− | window.requestAnimationFrame(loop, canvas);
| + | |
− | };
| + | |
− | window.requestAnimationFrame(loop, canvas);
| + | |
− | }
| + | |
− | /**
| + | |
− | * Initatite game objects and set start positions
| + | |
− | */
| + | |
− | function init() {
| + | |
− | player.x = player.width;
| + | |
− | player.y = (HEIGHT - player.height)/2;
| + | |
− | ai.x = WIDTH - (player.width + ai.width);
| + | |
− | ai.y = (HEIGHT - ai.height)/2;
| + | |
− | ball.serve(1);
| + | |
− | }
| + | |
− | /**
| + | |
− | * Update all game objects
| + | |
− | */
| + | |
− | function update() {
| + | |
− | ball.update();
| + | |
− | player.update();
| + | |
− | ai.update();
| + | |
− | }
| + | |
− | /**
| + | |
− | * Clear canvas and draw all game objects and net
| + | |
− | */
| + | |
− | function draw() {
| + | |
− | ctx.fillRect(0, 0, WIDTH, HEIGHT);
| + | |
− | ctx.save();
| + | |
− | ctx.fillStyle = "#fff";
| + | |
− | ball.draw();
| + | |
− | player.draw();
| + | |
− | ai.draw();
| + | |
− | // draw the net
| + | |
− | var w = 4;
| + | |
− | var x = (WIDTH - w)*0.5;
| + | |
− | var y = 0;
| + | |
− | var step = HEIGHT/20; // how many net segments
| + | |
− | while (y < HEIGHT) {
| + | |
− | ctx.fillRect(x, y+step*0.25, w, step*0.5);
| + | |
− | y += step;
| + | |
− | }
| + | |
− | ctx.restore();
| + | |
− | }
| + | |
− | // start and run the game
| + | |
− | main();
| + | |
− | </script> | + | |
| </body> | | </body> |
− | </html>
| |
− | <div class="column full_size">
| |
− |
| |
− |
| |
− | <p>Please visit <a href="https://2016.igem.org/Safety">the main Safety page</a> to find this year's safety requirements & deadlines, and to learn about safe & responsible research in iGEM.</p>
| |
− |
| |
− | <p>On this page of your wiki, you should write about how you are addressing any safety issues in your project. The wiki is a place where you can <strong>go beyond the questions on the safety forms</strong>, and write about whatever safety topics are most interesting in your project. (You do not need to copy your safety forms onto this wiki page.)</p>
| |
− |
| |
− | </div>
| |
− |
| |
− |
| |
− | <div class="column full_size">
| |
− | <h5>Safe Project Design</h5>
| |
− |
| |
− | <p>Does your project include any safety features? Have you made certain decisions about the design to reduce risks? Write about them here! For example:</p>
| |
− |
| |
− | <ul>
| |
− | <li>Choosing a non-pathogenic chassis</li>
| |
− | <li>Choosing parts that will not harm humans / animals / plants</li>
| |
− | <li>Substituting safer materials for dangerous materials in a proof-of-concept experiment</li>
| |
− | <li>Including an "induced lethality" or "kill-switch" device</li>
| |
− | </ul>
| |
− |
| |
− | </div>
| |
− |
| |
− | <div class="column half_size">
| |
− | <h5>Safe Lab Work</h5>
| |
− |
| |
− | <p>What safety procedures do you use every day in the lab? Did you perform any unusual experiments, or face any unusual safety issues? Write about them here!</p>
| |
− |
| |
− | </div>
| |
− |
| |
− | <div class="column half_size">
| |
− | <h5>Safe Shipment</h5>
| |
− |
| |
− | <p>Did you face any safety problems in sending your DNA parts to the Registry? How did you solve those problems?</p>
| |
− | </div>
| |
− | <iframe src="http://www.ipfingerprints.com/" frameBorder="0" width="900" scrolling="no" height="90"></iframe>
| |
− |
| |
| </html> | | </html> |