Add zooming

This commit is contained in:
asraelite 2018-03-03 13:29:14 +00:00
parent 56a09f98c5
commit b02675f4fb
12 changed files with 156 additions and 29 deletions

View file

@ -13,6 +13,11 @@ export const images = {
thruster: {
light: 'modules/light_thruster.svg'
}
},
celestials: {
green: {
"0": 'celestials/green_0.svg'
}
}
};

View file

@ -1,11 +1,18 @@
/*
* Constants that do not change during gameplay.
* This can kind of be treated like a configuration file, I guess.
*
* All le
*/
// Pixel length of sector.
// Unit length of sector. Only for internal representation.
export const SECTOR_SIZE = 512;
// Star count per sector.
export const STAR_DENSITY = (SECTOR_SIZE ** 2) / 10000;
// G, G-boy, The big G, Mr. G, g's big brother, G-dog
export const GRAVITATIONAL_CONSTANT = 0.01;
// Perspective constraints. Higher zoom value = closer.
export const MIN_ZOOM = 2;
export const MAX_ZOOM = 30;
export const DEFAULT_ZOOM = 10;
export const ZOOM_SPEED = 0.01;

View file

@ -1,5 +1,8 @@
import * as game from './index.mjs';
import * as graphics from '../graphics/index.mjs';
import * as world from '../world/index.mjs';
export function startGame() {
game.changeView('game');
graphics.perspective.focusPlayer();
}

View file

@ -18,7 +18,9 @@ export async function init() {
gui.init();
input.init();
//events.startGame();
events.startGame();
//tick(); return;
// Recursive `requestAnimationFrame` can cause problems with Parcel.
while(true) {

View file

@ -1,12 +1,13 @@
import {game} from '../game/index.mjs';
import {getContainedSectors} from '../world/index.mjs';
import * as background from './background.mjs';
import * as gui from './gui.mjs';
import * as draw from './draw.mjs';
import * as ship from './ship.mjs';
import * as input from '../input.mjs';
import {render as renderWorld} from './world.mjs';
import {render as renderBackground} from './background.mjs';
import * as world from '../world/index.mjs';
import * as consts from '../consts.mjs';
export let canvas, context, tempCanvas, tempContext;
export let view;
export let perspective;
export function init() {
canvas = document.querySelector('#main');
@ -17,12 +18,7 @@ export function init() {
canvas.width = 600;
canvas.height = 600;
view = {
bounds: [0, 0, canvas.width, canvas.height],
x: 0,
y: 0,
zoom: 1
}
perspective = new Perspective();
draw.text('Loading...', canvas.width / 2, canvas.height / 2,
{ align: 'center', valign: 'middle' });
@ -32,18 +28,84 @@ export function render() {
context.clearRect(0, 0, canvas.width, canvas.height);
context.fillStyle = '#000';
context.fillRect(0, 0, canvas.width, canvas.height);
renderBackground();
context.save();
// TODO: Translate canvas.
background.render();
ship.render();
perspective.tick();
perspective.transformCanvas();
renderWorld();
context.restore();
gui.render();
}
export function getVisibleSectors() {
return getContainedSectors(...view.bounds);
return world.getContainedSectors(...perspective.bounds);
}
class Perspective {
constructor() {
this.x = 0;
this.y = 0;
this.bounds = [0, 0, canvas.width, canvas.height];
this.reset();
}
tick() {
if (input.mouse.scroll !== 0) {
this.zoomDelta(-input.mouse.scroll);
}
if (this.focus !== null) {
this.x = this.focus.x;
this.y = this.focus.y;
}
if (this.rotationFocus !== null) {
this.targetRotation = this.rotationFocus.r;
} else {
this.targetRotation = 0;
}
if (this.smoothRotation) {
this.rotation = (this.rotation * 0.9 + this.targetRotation * 0.1);
} else {
this.rotation = this.targetRotation;
}
}
reset() {
this.rotation = 0;
this.targetRotation = 0;
this.smoothRotation = false;
this.zoom = consts.DEFAULT_ZOOM;
this.focus = null;
this.rotationFocus = null;
}
focusPlayer() {
this.focus = world.playerShip;
this.rotationFocus = world.playerShip;
this.smoothRotation = false;
}
zoomDelta(delta) {
let factor = 1 + (consts.ZOOM_SPEED * Math.abs(delta));
this.zoom *= delta > 0 ? factor : 1 / factor;
this.normalize();
}
normalize() {
this.zoom = Math.max(consts.MIN_ZOOM,
Math.min(consts.MAX_ZOOM, this.zoom));
}
transformCanvas() {
let [bx, by, bw, bh] = this.bounds;
let tx = -this.x + bw / 2;
let ty = -this.y + bh / 2;
context.translate(tx, ty);
context.scale(this.zoom, this.zoom);
}
}

View file

@ -4,12 +4,13 @@ import * as world from '../world/index.mjs';
export function render() {
world.ships.forEach(renderShip);
world.celestials.forEach(renderCelestial);
}
function renderShip(ship) {
context.fillStyle = 'red';
//context.fillRect(ship.x, ship.y, 10, 10);
let size = 100;
let size = 1;
context.drawImage(assets.modules.capsule.small, ship.x, ship.y,
size, size);
context.drawImage(assets.modules.fuel.small, ship.x, ship.y + size,
@ -17,3 +18,11 @@ function renderShip(ship) {
context.drawImage(assets.modules.thruster.light, ship.x,
ship.y + size * 2, size, size);
}
const celestialImages = {
green: Object.values(assets.celestials.green)
}
function renderCelestial(cel) {
context.drawImage(cel.image, cel.x, cel.y, cel.diameter, cel.diameter);
}

View file

@ -1,6 +1,6 @@
import {canvas} from './graphics/index.mjs';
export const mouse = { pressed: {}, held: {}, x: 0, y: 0 };
export const mouse = { pressed: {}, held: {}, x: 0, y: 0, scroll: 0 };
export const keyCode = { pressed: {}, held: {} };
export const key = { pressed: {}, held: {} };
export const action = {};
@ -11,6 +11,7 @@ export function tick() {
mouse.pressed = {};
keyCode.pressed = {};
key.pressed = {};
mouse.scroll = 0;
}
export function init() {
@ -43,4 +44,8 @@ export function init() {
mouse.x = event.clientX - rect.left;
mouse.y = event.clientY - rect.top;
});
window.addEventListener('wheel', event => {
mouse.scroll = event.deltaY;
});
}

View file

@ -1,10 +1,29 @@
import {images as assets} from '../assets.mjs';
import Body from './body.mjs';
export default class Celestial extends Body {
constructor(x, y, radius, {
density = 1,
mass = (radius ** 2) * density
type = 'rock'
}) {
let mass = (radius ** 2) * density
super(x, y, mass);
this.radius = radius;
this.type = type;
let imageArr = Object.values(assets.celestials[this.type]);
this.image = imageArr[Math.random() * imageArr.length | 0];
}
tick() {
}
get center() {
return [this.x + this.radius / 2, this.y + this.radius / 2];
}
get diameter() {
return this.radius * 2;
}
}

View file

@ -17,6 +17,8 @@ export function init() {
entities.clear();
celestials.clear();
spawn.player();
spawn.startPlanet();
}
export function tick() {

View file

@ -3,6 +3,9 @@ export default class Module {
name = 'Unnamed Module',
type = 'block',
mass = 1,
// Fuel
filled = false,
fuelCapacity = 0,
...properties
}) {
this.x = x;
@ -10,6 +13,7 @@ export default class Module {
this.name = name;
this.type = type;
this.mass = mass;
// Fuel
this.fuel = filled ? fuelCapacity : 0;
}
}

View file

@ -1,6 +1,6 @@
import Ship from './ship.mjs';
import Module from './module.mjs';
import Celestial from './ship.mjs';
import Celestial from './celestial.mjs';
import {modules} from '../data.mjs';
import * as world from './index.mjs';
@ -11,9 +11,18 @@ export function player() {
ship.addModule(0, 2, modules.thruster.light);
world.ships.add(ship);
world.setPlayerShip(ship);
return ship;
}
// Make module length = 1, define all other length off that.
export function celestial() {
let celestial = new Celestial(0, 50, 45)
export function startPlanet() {
return celestial(-40, 10, 40, {
density: 1,
type: 'green'
});
}
export function celestial(x, y, radius, params) {
let celestial = new Celestial(x, y, radius, params);
world.celestials.add(celestial);
return celestial;
}