// =============================== // create canvas and context // =============================== var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); //canvas.width = window.innerWidth * 0.75; //canvas.height = window.innerHeight * 0.75; canvas.width = 400; canvas.height = 400; // =============================== // =============================== // images // =============================== // text var story_text = ["As an astronaut with the Artemis program, I have an amazing opportunity to visit the Moon.", "I'm so lucky! I'll be able to collect soil samples, conduct experiments, and observe the Moon's surface.", "In today's mission, we'll travel from the Gateway to the surface of the Moon. I'll check on my experiment testing the effects of low gravity on growing plants.", "Time to exit orbit and land on the Moon!", "Here on the moon, I can't wait to see how well the plants are growing!", "This information is invaluable if we want to be able to grow our own food away from Earth.", "Now with all of this data, I can start the launch sequence and head back to the Gateway."] // =============================== // background image var background = new Image(); background.src = 'space_1.jpeg'; //background.src = 'space_2.png'; background.onload = draw; // moon image var moon = new Image(); moon.src = 'moon.png'; var moon_dims = {'w':1, 'h':1} moon.onload = function(){ var height = moon.height; var width = moon.width; moon_dims.w = width; moon_dims.h = height; // code here to use the dimensions //console.log(moon_dims); moon_scale = (canvas.width * .2) / moon_dims.w; moon_scale = clamp(moon_scale, 0.2, 0.4); //console.log(moon_scale * moon.width); lander.scale = 0.3 * moon_scale / 0.4; lander.orbit_radius = Math.min(canvas.height, canvas.width) * 0.4; }; var moon_scale = 1; var moon_pos = { 'x': (canvas.width / 2), 'y': (canvas.height / 2) }; // =============================== // =============================== // lander properties // =============================== var lander = { 'x':canvas.width / 4, 'y':canvas.height / 2, 'old_x':0, 'old_y':0, 'velocity':0, 'acceleration':0.1, 'width':20, 'height':35, 'orbit_radius':240, 'scale':0.3 }; var lander_img = new Image(); lander_img.src = 'lander.png'; lander_img.onload = draw; // =============================== // =============================== // frame animation variables // =============================== var theta = 0; var frames = 0; var angle = 0; var anim_time = 5 * 60; var start_time = 0; var lerper; var lander_states = {FLYING:0, LANDING:1} var lander_curr_state = lander_states.FLYING; var lander_landing_angle = 0; // switch between flying and landing function activate() { start_time = frames; if(lander_curr_state == lander_states.FLYING) { lander_curr_state = lander_states.LANDING; lander_landing_angle = angle; } else if(lander_curr_state == lander_states.LANDING) { lander_curr_state = lander_states.FLYING; } } function wrapText(context, text, x, y, maxWidth, lineHeight) { var words = text.split(' '); var line = ''; for(var n = 0; n < words.length; n++) { var testLine = line + words[n] + ' '; var metrics = context.measureText(testLine); var testWidth = metrics.width; if (testWidth > maxWidth && n > 0) { context.fillText(line, x, y); line = words[n] + ' '; y += lineHeight; } else { line = testLine; } } context.fillText(line, x, y); } var lander_final_radius = lander.orbit_radius; // =============================== // let's draw stuff function draw() { // =============================== // background elements // =============================== moon_pos.x = (canvas.width / 2 - moon.width / 2 * moon_scale); moon_pos.y = (canvas.height / 2 - moon.height / 2 * moon_scale); context.drawImage(background, 0, 0, canvas.width, canvas.height); context.drawImage(moon, moon_pos.x, moon_pos.y, moon.width * moon_scale, moon.height * moon_scale); // =============================== // =============================== // calculate lander orbit position // =============================== lander.x = lander_final_radius * Math.cos(2 * Math.PI + theta) + canvas.width/2; lander.y = lander_final_radius * Math.sin(2 * Math.PI + theta) + canvas.height/2; if(lander_curr_state == lander_states.FLYING) { theta += 0.003; } // =============================== // =============================== // Draw the Lander // =============================== context.save(); context.translate( lander.x, lander.y); angle = lerp(angle, Math.atan2(lander.y - lander.old_y, lander.x - lander.old_x) + Math.PI / 2.0, 0.7); lerper = clamp((frames - start_time) / anim_time, 0.0, 1); if(lander_curr_state == lander_states.FLYING) { lerper = 1.0 - lerper; } angle = lerp(angle % (Math.PI * 2), (lander_landing_angle - Math.PI / 2.0) % (Math.PI * 2), smoothstep(0.1, .95, lerper * 1.4)); lander_final_radius = lerp(lander.orbit_radius, moon.width * moon_scale / 2 * 1.4, lerper); context.rotate(angle); if(Math.random() <= 0.9) { var engine = (Math.random() * 0.4 + 0.5); var engine_fill = "rgba(255, 120, 30," + engine + ")"; var engine_lerp = -Math.cos(2 * Math.PI * lerper) * 0.5 + 0.5; context.fillStyle = engine_fill; context.beginPath(); context.ellipse(0, lander_img.height / 2 * lander.scale, 20 * engine_lerp * lander.scale, 40 * engine_lerp * lander.scale, 0, 0, Math.PI * 2, false); context.fill(); } context.drawImage(lander_img, - lander_img.width / 2 * lander.scale, - lander_img.height / 2 * lander.scale, lander_img.width * lander.scale, lander_img.height * lander.scale); context.restore(); // =============================== // need this to animate window.requestAnimationFrame(draw); // =============================== // do post draw stuff // =============================== frames ++; lander.old_x = lander.x; lander.old_y = lander.y; // =============================== if (frames < 9750) { wrapText(context, story_text[Math.round(frames/1500)], 15, 300, 350, 20); } if (frames == 4500 || frames == 9000) { activate(); } } context.font = "20px Roboto"; // call the draw function draw();