basic viewport

by greg gorlen

HTML

<div>arrow keys to move</div>

CSS

body { 
  font-family: monospace;
  font-size: 11px;
  display: flex; 
  flex-direction: column;
  align-items: center; 
  justify-content: center;
}

html, body { 
  height: 98%; 
}

body > canvas { 
  margin: auto; 
  border: 4px solid #222; 
}

body > div {
  background: #222;
  color: #fff;
  padding: 2px;
}

JavaScript

/*
 * assign the viewport to a target on each frame:
 *     viewport.x = -target.x + canvas.width / 2;
 *     viewport.y = -target.y + canvas.height / 2;
 * ... and clamp it to the map if desired
 *
 * draw each entity relative to the viewport:
 *     entity.x + viewport.x
 *     entity.y + viewport.y
*/

"use strict";

const clamp = (n, lo, hi) => n < lo ? lo : n > hi ? hi : n;
const tau = Math.PI * 2;
const canvas = document.createElement("canvas");
canvas.style.background = "#eee";
const ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
canvas.height = 400;
canvas.width = 400;
const map = {
  height: 1000,
  width: 2000
};
const viewport = {};

let kbd;
let ship;


const Ship = function (x, y, angle, size, color) {
  this.x = x;
  this.y = y;
  this.vx = 0;
  this.vy = 0;
  this.ax = 0;
  this.ay = 0;
  this.rv = 0;
  this.angle = angle;
  this.accelerationAmount = 0.05;
  this.decelerationAmount = 0.02;
  this.friction = 0.9;
  this.rotationSpd = 0.01;
  this.size = size;
  this.radius = size;
  this.color = color;
};

Ship.prototype = {
	accelerate: function (backwards) {
  	if (backwards) {
	  	this.ax -= this.decelerationAmount;
  		this.ay -= this.decelerationAmount;
    }
    else {
    	this.ax += this.accelerationAmount;
  		this.ay += this.accelerationAmount;
    }
  },

	move: function () {
  	this.angle += this.rv;
    this.vx += this.ax;
    this.vy += this.ay;
    this.x += this.vx * Math.cos(this.angle);
    this.y += this.vy * Math.sin(this.angle);
    this.ax *= this.friction;
    this.ay *= this.friction;
    this.vx *= this.friction;
    this.vy *= this.friction;
    this.rv *= this.friction;
  },
  
  rotate: function (dir) {
  	if (dir === "left") {
	  	this.rv -= this.rotationSpd;
    }
  	else if (dir === "right") {
	  	this.rv += this.rotationSpd;
    }
  },
  
	draw: function (ctx, viewport) {
  	ctx.save();
  	ctx.translate(this.x + viewport.x,
                  this.y + viewport.y);
 		ctx.rotate(this.angle);
   ...