Add start of ship editing grid

This commit is contained in:
asraelite 2018-03-05 00:57:33 +00:00
parent b88c0eb358
commit 2fbabc785e
16 changed files with 249 additions and 18 deletions

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
.cache/ .cache/
*.min.js *.min.js
*.map

File diff suppressed because one or more lines are too long

View file

@ -18,9 +18,11 @@ export const MAX_ZOOM = 100;
export const DEFAULT_ZOOM = 10; export const DEFAULT_ZOOM = 10;
export const ZOOM_SPEED = 0.01; export const ZOOM_SPEED = 0.01;
// Ship landing. Angle in radians. // Ship landing. Angle in radians.
export const TIP_ANGLE = 30.3; export const TIP_ANGLE = 0.3;
export const TIP_SPEED = 0.015; export const TIP_SPEED = 0.015;
// Ship flight mechanics. Speed measured in units per tick. // Ship flight mechanics. Speed measured in units per tick.
export const FUEL_BURN_RATE = 0.01; export const FUEL_BURN_RATE = 0.01;
// Distance at which an orbited planet will not be considered a parent body. // Distance at which an orbited planet will not be considered a parent body.
export const MAX_PARENT_CELESTIAL_DISTANCE = 120; export const MAX_PARENT_CELESTIAL_DISTANCE = 120;
// Ship editing.
export const EDIT_MARGIN = 2;

View file

@ -1,10 +1,66 @@
import * as game from './index.mjs'; import * as game from './index.mjs';
import * as graphics from '../graphics/index.mjs'; import * as graphics from '../graphics/index.mjs';
import * as world from '../world/index.mjs';
import * as consts from '../consts.mjs';
export let tiles = new Map();
export let width = 0;
export let height = 0;
export let position = [0, 0];
export let bounds = [0, 0, 0, 0];
export let currentModule = null;
export function init() { export function init() {
graphics.setZoom(20); let ship = world.playerShip;
let modules = ship.modules;
let margin = consts.EDIT_MARGIN;
modules.forEach(m => {
let pos = [m.x, m.y];
tiles.set(posId(...pos), new Tile(...pos, m));
});
let [sx, ex, sy, ey] = getBoundaries();
[width, height] = [ex - sx + margin * 2 + 1, ey - sy + margin * 2 + 1];
position = [sx - margin, sy - margin];
let neededZoom = graphics.canvas.width / (Math.max(width, height) + 10);
graphics.changePerspective('planet', 0, -5);
graphics.setZoom(neededZoom);
} }
export function end() { export function end() {
} }
export function getTile(x, y) {
let id = posId(x, y);
if (!tiles.has(id))
tiles.set(id, new Tile(x, y, null));
return tiles.get(id);
}
function posId(x, y) {
return `${x}.${y}`;
}
function getBoundaries() {
return [0, 0, 0, 2];
}
class Tile {
constructor(x, y, module) {
this.module = module;
this.x = x;
this.y = y;
}
get valid() {
return true;
}
get drawPos() {
let [px, py] = pos;
return [this.x + px, this.y + py];
}
}

View file

@ -22,8 +22,6 @@ export function launchShip() {
} }
export function editShip() { export function editShip() {
console.log('a');
graphics.changePerspective('parent', -5, 0);
game.state.editing = true; game.state.editing = true;
edit.init(); edit.init();
} }

16
js/graphics/edit.mjs Normal file
View file

@ -0,0 +1,16 @@
import {context} from './index.mjs';
import * as edit from '../game/edit.mjs';
import * as world from '../world/index.mjs';
export function render() {
let ship = world.playerShip;
context.save();
context.translate(...ship.com);
context.rotate(ship.r);
let [cx, cy] = ship.localCom;
context.translate(-cx, -cy);
context.restore();
}

View file

@ -12,8 +12,12 @@ function renderElement(element) {
if (element.type == 'frame') renderFrame(element); if (element.type == 'frame') renderFrame(element);
if (element.type == 'image') renderImage(element); if (element.type == 'image') renderImage(element);
if (element.type == 'button') renderButton(element); if (element.type == 'button') renderButton(element);
if (element.type == 'edit') renderEdit(element);
if (element.type == 'itemButton') renderItemButton(element);
} }
element.children.forEach(renderElement);
if (element.options.drawChildren)
element.children.forEach(renderElement);
} }
function renderFrame(element) { function renderFrame(element) {
@ -42,3 +46,40 @@ function renderButton(element) {
context.font = '12pt Consolas'; context.font = '12pt Consolas';
context.fillText(element.text, ...element.center); context.fillText(element.text, ...element.center);
} }
function renderItemButton(element) {
context.globalAlpha = 0.5;
if (element.mouseHeld) {
context.fillStyle = '#080808';
} else {
context.fillStyle = element.mouseOver ? '#222' : '#0e0e0e';
}
context.fillRect(...element.shape);
context.strokeStyle = '#333';
context.strokeWidth = 4;
context.strokeRect(...element.shape);
context.globalAlpha = 1;
if (element.image) {
context.drawImage(element.image, ...element.shape);
}
}
function renderEdit(element) {
/*
element.tiles.forEach(t => {
let tile = edit.getTile(x, y);
let [dx, dy] = tile.drawPos;
context.globalAlpha = 0.5;
context.fillStyle = '#000';
context.fillRect(dx, dy, 1, 1);
context.globalAlpha = 1;
let module = tile.module;
if (module !== null) {
context.drawImage(module.currentImage, dx, dy, 1, 1);
}
});
*/
}

View file

@ -3,6 +3,7 @@ import * as draw from './draw.mjs';
import * as input from '../input.mjs'; import * as input from '../input.mjs';
import {render as renderWorld} from './world.mjs'; import {render as renderWorld} from './world.mjs';
import {render as renderBackground} from './background.mjs'; import {render as renderBackground} from './background.mjs';
import {render as renderEdit} from './edit.mjs';
import * as world from '../world/index.mjs'; import * as world from '../world/index.mjs';
import * as consts from '../consts.mjs'; import * as consts from '../consts.mjs';
@ -77,7 +78,7 @@ class Perspective {
} }
changeRotationMode(mode) { changeRotationMode(mode) {
this.oldTarget = this.targetRotation; this.oldTarget = this.currentRotation;
this.rotationMode = mode; this.rotationMode = mode;
} }
@ -181,7 +182,7 @@ class Perspective {
transformCanvas() { transformCanvas() {
let [,,bw, bh] = this.bounds; let [,,bw, bh] = this.bounds;
let [sx, sy] = this.rotateVector(...this.currentShift, -this.rotation); let [sx, sy] = this.rotateVector(...this.currentShift, this.rotation);
let tx = -(this.x + sx) * this.zoom; let tx = -(this.x + sx) * this.zoom;
let ty = -(this.y + sy) * this.zoom; let ty = -(this.y + sy) * this.zoom;
context.translate(tx + bw / 2, ty + bh / 2); context.translate(tx + bw / 2, ty + bh / 2);

View file

@ -1,6 +1,8 @@
import {canvas, context} from './index.mjs'; import {canvas, context} from './index.mjs';
import {images as assets} from '../assets.mjs'; import {images as assets} from '../assets.mjs';
import * as world from '../world/index.mjs'; import * as world from '../world/index.mjs';
import * as edit from './edit.mjs';
import {state} from '../game/index.mjs';
export function render() { export function render() {
world.particles.forEach(renderParticle); world.particles.forEach(renderParticle);
@ -20,6 +22,10 @@ function renderShip(ship) {
let [cx, cy] = ship.localCom; let [cx, cy] = ship.localCom;
context.translate(-cx, -cy); context.translate(-cx, -cy);
ship.modules.forEach(m => { ship.modules.forEach(m => {
let [mx, my] = [m.x, m.y];
if (state.editing) {
}
context.drawImage(m.currentImage, m.x, m.y, 1, 1); context.drawImage(m.currentImage, m.x, m.y, 1, 1);
}); });
context.restore(); context.restore();

69
js/gui/edit.mjs Normal file
View file

@ -0,0 +1,69 @@
import * as gui from './index.mjs';
import GuiElement from './element.mjs';
import GuiItemButton from './item.mjs';
import {state} from '../game/index.mjs';
import * as edit from '../game/edit.mjs';
export default class GuiEdit extends GuiElement {
constructor(x, y, w = 100, h = 30) {
super(x, y, w, h);
this.type = 'edit';
this.tileWidth = 0;
this.tileHeight = 0;
this.active = false;
}
updateTiles() {
this.children.clear();
[this.tileWidth, this.tileHeight] = [edit.width, edit.height];
let tileRatio = this.tileWidth / this.tileHeight;
let rectRatio = this.w / this.h;
let tileSize;
let [ox, oy] = [0, 0];
if (tileRatio < rectRatio) {
tileSize = this.h / this.tileHeight;
ox = (this.w - (tileSize * this.tileWidth)) / 2;
} else {
tileSize = this.w / this.tileWidth;
oy = (this.h - (tileSize * this.tileHeight)) / 2;
}
let spacing = 0.1 * tileSize;
for (let x = 0; x < this.tileWidth; x++)
for (let y = 0; y < this.tileHeight; y++) {
let tile = this.getTile(x, y);
let ex = x * tileSize + spacing / 2 + ox + this.x;
let ey = y * tileSize + spacing / 2 + oy + this.y;
let [ew, eh] = [tileSize - spacing, tileSize - spacing];
let onclick = (button) => {
this.tileClicked(x, y, button);
};
let el = new GuiItemButton(tile.module, onclick, ex, ey, ew, eh);
this.append(el);
}
}
tick() {
if (state.editing && !this.active) this.updateTiles();
this.active = state.editing;
this.options.draw = this.options.drawChildren = this.active;
if (!this.active) return;
[this.tileWidth, this.tileHeight] = [edit.width, edit.height];
}
getTile(x, y) {
let [px, py] = edit.position;
return edit.getTile(x + px, y + py);
}
tileClicked(x, y, button) {
console.log(x, y, button);
}
}

0
js/gui/inventory.mjs Normal file
View file

18
js/gui/item.mjs Normal file
View file

@ -0,0 +1,18 @@
import * as gui from './index.mjs';
import GuiButton from './button.mjs';
export default class GuiItemButton extends GuiButton {
constructor(module, onclick, x, y, w = 50, h = 50) {
super(null, onclick, x, y, w, h);
this.image = module === null ? null : module.currentImage;
this.type = 'itemButton';
}
click() {
this.onclick('left');
}
rightClick() {
this.onclick('right');
}
}

View file

@ -9,10 +9,15 @@ export class Rect {
this.onclick = null; this.onclick = null;
this.mouseHeld = false; this.mouseHeld = false;
this.rightMouseHeld = false;
this.onRightClick = null;
} }
click() {} click() {}
rightClick() {}
tickMouse() { tickMouse() {
if (this.mouseHeld == true && !input.mouse.held[0] && this.mouseOver) if (this.mouseHeld == true && !input.mouse.held[0] && this.mouseOver)
this.click(); this.click();
@ -20,6 +25,14 @@ export class Rect {
this.mouseHeld = true; this.mouseHeld = true;
if (!input.mouse.held[0]) if (!input.mouse.held[0])
this.mouseHeld = false; this.mouseHeld = false;
if (this.rightMouseHeld == true && !input.mouse.held[2]
&&this.mouseOver)
this.rightClick();
if (!this.rightMouseHeld && input.mouse.pressed[2] && this.mouseOver)
this.rightMouseHeld = true;
if (!input.mouse.held[2])
this.rightMouseHeld = false;
} }
get shape() { get shape() {

View file

@ -4,6 +4,7 @@ import {canvas} from '../graphics/index.mjs';
import GuiFrame from './frame.mjs'; import GuiFrame from './frame.mjs';
import GuiImage from './image.mjs'; import GuiImage from './image.mjs';
import GuiButton from './button.mjs'; import GuiButton from './button.mjs';
import GuiEdit from './edit.mjs';
import * as events from '../game/events.mjs'; import * as events from '../game/events.mjs';
import {state} from '../game/index.mjs'; import {state} from '../game/index.mjs';
@ -38,13 +39,19 @@ export function title() {
export function game() { export function game() {
let shadow = root(); let shadow = root();
let edit = new GuiButton('Edit rocket', events.editShip, 0, 0, 200); let editButton = new GuiButton('Edit rocket', events.editShip, 0, 0, 200);
shadow.append(edit); shadow.append(editButton);
edit.posRelative({ x: 0.5, xc: 0.5, y: 1 }); editButton.posRelative({ x: 0.5, xc: 0.5, y: 1 });
edit.y -= 45; editButton.y -= 45;
edit.tick = () => { editButton.tick = () => {
edit.options.draw = state.landed && !state.editing; editButton.options.draw = state.landed && !state.editing;
} }
let edit = new GuiEdit(0, 0, 0, 0);
shadow.append(edit);
edit.posRelative({x: 0.45, y: 0, w: 0.55, h: 0.6});
edit.x -= 10;
edit.y += 10;
return shadow; return shadow;
} }

View file

@ -48,4 +48,8 @@ export function init() {
window.addEventListener('wheel', event => { window.addEventListener('wheel', event => {
mouse.scroll = event.deltaY; mouse.scroll = event.deltaY;
}); });
window.addEventListener('contextmenu', event => {
event.preventDefault();
});
} }

View file

@ -40,9 +40,9 @@ export default class Ship extends Body {
} }
tick() { tick() {
this.tickMotion(); if (!state.editing) this.tickMotion();
if (!this.landed) this.tickGravity(world.celestials); if (!this.landed) this.tickGravity(world.celestials);
this.resolveCollisions(); if (!state.editing) this.resolveCollisions();
this.modules.forEach(m => { this.modules.forEach(m => {
if (m.type == 'thruster' && m.power !== 0) { if (m.type == 'thruster' && m.power !== 0) {