Compare commits
	
		
			1 Commits
		
	
	
		
			develop
			...
			laptop-bac
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| cece0ee870 | 
@@ -1,14 +1,14 @@
 | 
			
		||||
{
 | 
			
		||||
	"width": 575,
 | 
			
		||||
	"height": 523,
 | 
			
		||||
	"animations": {
 | 
			
		||||
		"idle": {
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"frames": 6
 | 
			
		||||
		},
 | 
			
		||||
		"walk": {
 | 
			
		||||
			"y": 3,
 | 
			
		||||
			"frames": 8
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
{
 | 
			
		||||
	"width": 575,
 | 
			
		||||
	"height": 523,
 | 
			
		||||
	"animations": {
 | 
			
		||||
		"idle": {
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"frames": 6
 | 
			
		||||
		},
 | 
			
		||||
		"walk": {
 | 
			
		||||
			"y": 3,
 | 
			
		||||
			"frames": 8
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,11 @@
 | 
			
		||||
{
 | 
			
		||||
	"width": 50,
 | 
			
		||||
	"height": 50,
 | 
			
		||||
	"animations": [
 | 
			
		||||
		{
 | 
			
		||||
			"name": "idle",
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"frames": 8
 | 
			
		||||
		}
 | 
			
		||||
	]
 | 
			
		||||
}
 | 
			
		||||
{
 | 
			
		||||
	"width": 50,
 | 
			
		||||
	"height": 50,
 | 
			
		||||
	"animations": [
 | 
			
		||||
		{
 | 
			
		||||
			"name": "idle",
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"frames": 8
 | 
			
		||||
		}
 | 
			
		||||
	]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,58 +1,58 @@
 | 
			
		||||
{
 | 
			
		||||
	"sprites": {
 | 
			
		||||
		"generic": {
 | 
			
		||||
			"x": 0,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"text": {
 | 
			
		||||
			"x": 100,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"code": {
 | 
			
		||||
			"x": 200,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"zip": {
 | 
			
		||||
			"x": 300,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"image": {
 | 
			
		||||
			"x": 400,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"audio": {
 | 
			
		||||
			"x": 500,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"video": {
 | 
			
		||||
			"x": 600,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"pdf": {
 | 
			
		||||
			"x": 700,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"bubble": {
 | 
			
		||||
			"x": 0,
 | 
			
		||||
			"y": 100,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
{
 | 
			
		||||
	"sprites": {
 | 
			
		||||
		"generic": {
 | 
			
		||||
			"x": 0,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"text": {
 | 
			
		||||
			"x": 100,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"code": {
 | 
			
		||||
			"x": 200,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"zip": {
 | 
			
		||||
			"x": 300,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"image": {
 | 
			
		||||
			"x": 400,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"audio": {
 | 
			
		||||
			"x": 500,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"video": {
 | 
			
		||||
			"x": 600,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"pdf": {
 | 
			
		||||
			"x": 700,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"bubble": {
 | 
			
		||||
			"x": 0,
 | 
			
		||||
			"y": 100,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,87 +1,87 @@
 | 
			
		||||
export type SpriteDefinitions = {
 | 
			
		||||
	width?: number;
 | 
			
		||||
	height?: number;
 | 
			
		||||
	animations?: {[key: string]: {y: number, frames: number}};
 | 
			
		||||
	sprites?: {[key: string]: {x: number, y: number, width?: number, height?: number}};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class SpriteSheet {
 | 
			
		||||
	private readonly definitions!: SpriteDefinitions;
 | 
			
		||||
	private readonly spriteSheet!: HTMLImageElement;
 | 
			
		||||
 | 
			
		||||
	private animation = '';
 | 
			
		||||
	private frame = -1;
 | 
			
		||||
 | 
			
		||||
	constructor(private readonly ctx: CanvasRenderingContext2D,
 | 
			
		||||
				public readonly spriteSheetPath: string,
 | 
			
		||||
				public readonly spriteDefPath: string,
 | 
			
		||||
	) {
 | 
			
		||||
		this.spriteSheet = new Image();
 | 
			
		||||
		this.spriteSheet.src = spriteSheetPath;
 | 
			
		||||
		this.definitions = require(spriteDefPath);
 | 
			
		||||
 | 
			
		||||
		// Backfill coordinates if shorthand is used
 | 
			
		||||
		if(this.definitions.sprites?.length) {
 | 
			
		||||
			Object.entries(this.definitions.sprites).forEach(sprite => {
 | 
			
		||||
				const [name, def] = sprite;
 | 
			
		||||
				if(def.width == null) {
 | 
			
		||||
					if(this.definitions.width == null)
 | 
			
		||||
						throw new Error(`Sprite is missing it's width: ${name}`);
 | 
			
		||||
					this.definitions.sprites[name].x = this.definitions.width * def.x;
 | 
			
		||||
					this.definitions.sprites[name].width = this.definitions.width;
 | 
			
		||||
				}
 | 
			
		||||
				if(def.height == null) {
 | 
			
		||||
					if(this.definitions.height == null)
 | 
			
		||||
						throw new Error(`Sprite is missing it's height: ${name}`);
 | 
			
		||||
					this.definitions.sprites[name].y = this.definitions.height * def.y;
 | 
			
		||||
					this.definitions.sprites[name].height = this.definitions.height;
 | 
			
		||||
				}
 | 
			
		||||
			});
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	animate(x: number, y: number, name: string = this.animation, flip = false, scale = 1) {
 | 
			
		||||
		const animation = this.definitions.animations[name];
 | 
			
		||||
		if(!animation) throw new Error(`Animation doesn't exist: ${name}`);
 | 
			
		||||
		if(name == this.animation) {
 | 
			
		||||
			this.frame++;
 | 
			
		||||
			if(this.frame >= animation.frames) this.frame = 0;
 | 
			
		||||
		} else {
 | 
			
		||||
			this.animation = name;
 | 
			
		||||
			this.frame = 0;
 | 
			
		||||
		}
 | 
			
		||||
		this.drawFrame(x, y, this.animation, this.frame, flip, scale);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	drawFrame(x: number, y: number, name: string, frame: number, flip = false, scale = 1, centerX = true, centerY = false) {
 | 
			
		||||
		const sprite = this.definitions.animations[name];
 | 
			
		||||
		if(!sprite) throw new Error(`Animation doesn't exist: ${name}`);
 | 
			
		||||
		this.ctx.save();
 | 
			
		||||
		this.ctx.translate(centerX ?
 | 
			
		||||
				this.definitions.width * scale / 2 * (flip ? 1 : -1) :
 | 
			
		||||
				flip ? this.definitions.width : 0,
 | 
			
		||||
			centerY ? this.definitions.height / -2 : 0);
 | 
			
		||||
		this.ctx.scale(flip ? -1 : 1, 1);
 | 
			
		||||
		this.ctx.drawImage(this.spriteSheet,
 | 
			
		||||
			frame * this.definitions.width, sprite.y * this.definitions.height, this.definitions.width, this.definitions.height,
 | 
			
		||||
			x * (flip ? -1 : 1), this.ctx.canvas.height - (this.definitions.height * scale + y),
 | 
			
		||||
			this.definitions.width * scale, this.definitions.height * scale);
 | 
			
		||||
		this.ctx.restore();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	drawSprite(x: number, y: number, name: string, flip = false, scale = 1, centerX = true, centerY = false) {
 | 
			
		||||
		const sprite = this.definitions.sprites[name];
 | 
			
		||||
		if(!sprite) throw new Error(`Sprite doesn't exist: ${name}`);
 | 
			
		||||
		this.ctx.save();
 | 
			
		||||
		this.ctx.translate(centerX ?
 | 
			
		||||
				this.definitions.width * scale / 2 * (flip ? 1 : -1) :
 | 
			
		||||
				flip ? this.definitions.width : 0,
 | 
			
		||||
			centerY ? this.definitions.height / -2 : 0);
 | 
			
		||||
		this.ctx.scale(flip ? -1 : 1, 1);
 | 
			
		||||
		this.ctx.drawImage(this.spriteSheet,
 | 
			
		||||
			sprite.x, sprite.y, sprite.width, sprite.height,
 | 
			
		||||
			x * (flip ? -1 : 1), this.ctx.canvas.height - (sprite.height * scale + y),
 | 
			
		||||
			sprite.width * scale, sprite.height * scale);
 | 
			
		||||
		this.ctx.restore();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
export type SpriteDefinitions = {
 | 
			
		||||
	width?: number;
 | 
			
		||||
	height?: number;
 | 
			
		||||
	animations?: {[key: string]: {y: number, frames: number}};
 | 
			
		||||
	sprites?: {[key: string]: {x: number, y: number, width?: number, height?: number}};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class SpriteSheet {
 | 
			
		||||
	private readonly definitions!: SpriteDefinitions;
 | 
			
		||||
	private readonly spriteSheet!: HTMLImageElement;
 | 
			
		||||
 | 
			
		||||
	private animation = '';
 | 
			
		||||
	private frame = -1;
 | 
			
		||||
 | 
			
		||||
	constructor(private readonly ctx: CanvasRenderingContext2D,
 | 
			
		||||
				public readonly spriteSheetPath: string,
 | 
			
		||||
				public readonly spriteDefPath: string,
 | 
			
		||||
	) {
 | 
			
		||||
		this.spriteSheet = new Image();
 | 
			
		||||
		this.spriteSheet.src = spriteSheetPath;
 | 
			
		||||
		this.definitions = require(spriteDefPath);
 | 
			
		||||
 | 
			
		||||
		// Backfill coordinates if shorthand is used
 | 
			
		||||
		if(this.definitions.sprites?.length) {
 | 
			
		||||
			Object.entries(this.definitions.sprites).forEach(sprite => {
 | 
			
		||||
				const [name, def] = sprite;
 | 
			
		||||
				if(def.width == null) {
 | 
			
		||||
					if(this.definitions.width == null)
 | 
			
		||||
						throw new Error(`Sprite is missing it's width: ${name}`);
 | 
			
		||||
					this.definitions.sprites[name].x = this.definitions.width * def.x;
 | 
			
		||||
					this.definitions.sprites[name].width = this.definitions.width;
 | 
			
		||||
				}
 | 
			
		||||
				if(def.height == null) {
 | 
			
		||||
					if(this.definitions.height == null)
 | 
			
		||||
						throw new Error(`Sprite is missing it's height: ${name}`);
 | 
			
		||||
					this.definitions.sprites[name].y = this.definitions.height * def.y;
 | 
			
		||||
					this.definitions.sprites[name].height = this.definitions.height;
 | 
			
		||||
				}
 | 
			
		||||
			});
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	animate(x: number, y: number, name: string = this.animation, flip = false, scale = 1) {
 | 
			
		||||
		const animation = this.definitions.animations[name];
 | 
			
		||||
		if(!animation) throw new Error(`Animation doesn't exist: ${name}`);
 | 
			
		||||
		if(name == this.animation) {
 | 
			
		||||
			this.frame++;
 | 
			
		||||
			if(this.frame >= animation.frames) this.frame = 0;
 | 
			
		||||
		} else {
 | 
			
		||||
			this.animation = name;
 | 
			
		||||
			this.frame = 0;
 | 
			
		||||
		}
 | 
			
		||||
		this.drawFrame(x, y, this.animation, this.frame, flip, scale);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	drawFrame(x: number, y: number, name: string, frame: number, flip = false, scale = 1, centerX = true, centerY = false) {
 | 
			
		||||
		const sprite = this.definitions.animations[name];
 | 
			
		||||
		if(!sprite) throw new Error(`Animation doesn't exist: ${name}`);
 | 
			
		||||
		this.ctx.save();
 | 
			
		||||
		this.ctx.translate(centerX ?
 | 
			
		||||
				this.definitions.width * scale / 2 * (flip ? 1 : -1) :
 | 
			
		||||
				flip ? this.definitions.width : 0,
 | 
			
		||||
			centerY ? this.definitions.height / -2 : 0);
 | 
			
		||||
		this.ctx.scale(flip ? -1 : 1, 1);
 | 
			
		||||
		this.ctx.drawImage(this.spriteSheet,
 | 
			
		||||
			frame * this.definitions.width, sprite.y * this.definitions.height, this.definitions.width, this.definitions.height,
 | 
			
		||||
			x * (flip ? -1 : 1), this.ctx.canvas.height - (this.definitions.height * scale + y),
 | 
			
		||||
			this.definitions.width * scale, this.definitions.height * scale);
 | 
			
		||||
		this.ctx.restore();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	drawSprite(x: number, y: number, name: string, flip = false, scale = 1, centerX = true, centerY = false) {
 | 
			
		||||
		const sprite = this.definitions.sprites[name];
 | 
			
		||||
		if(!sprite) throw new Error(`Sprite doesn't exist: ${name}`);
 | 
			
		||||
		this.ctx.save();
 | 
			
		||||
		this.ctx.translate(centerX ?
 | 
			
		||||
				this.definitions.width * scale / 2 * (flip ? 1 : -1) :
 | 
			
		||||
				flip ? this.definitions.width : 0,
 | 
			
		||||
			centerY ? this.definitions.height / -2 : 0);
 | 
			
		||||
		this.ctx.scale(flip ? -1 : 1, 1);
 | 
			
		||||
		this.ctx.drawImage(this.spriteSheet,
 | 
			
		||||
			sprite.x, sprite.y, sprite.width, sprite.height,
 | 
			
		||||
			x * (flip ? -1 : 1), this.ctx.canvas.height - (sprite.height * scale + y),
 | 
			
		||||
			sprite.width * scale, sprite.height * scale);
 | 
			
		||||
		this.ctx.restore();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18901
									
								
								v2/package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										18901
									
								
								v2/package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										2
									
								
								v2/src/constants.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								v2/src/constants.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
export const FRAME_RATE = 10;
 | 
			
		||||
export const GRAVITY = 9.8;
 | 
			
		||||
@@ -1,12 +1,23 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
  <head>
 | 
			
		||||
    <meta charset="UTF-8" />
 | 
			
		||||
    <title>Hello World!</title>
 | 
			
		||||
 | 
			
		||||
  </head>
 | 
			
		||||
  <body>
 | 
			
		||||
    <h1>💖 Hello World!</h1>
 | 
			
		||||
    <p>Welcome to your Electron application.</p>
 | 
			
		||||
  </body>
 | 
			
		||||
<html>
 | 
			
		||||
    <head>
 | 
			
		||||
        <meta charset="UTF-8" />
 | 
			
		||||
        <title>Desktop Daemon</title>
 | 
			
		||||
        <link rel="icon" type="img/png" src="assets/logo.png">
 | 
			
		||||
 | 
			
		||||
        <style>
 | 
			
		||||
            html, body {
 | 
			
		||||
                margin: 0;
 | 
			
		||||
                padding: 0;
 | 
			
		||||
                height: 100%;
 | 
			
		||||
                width: 100%;
 | 
			
		||||
                overflow: hidden;
 | 
			
		||||
            }
 | 
			
		||||
        </style>
 | 
			
		||||
    </head>
 | 
			
		||||
 | 
			
		||||
    <body>
 | 
			
		||||
        <canvas id="canvas"></canvas>
 | 
			
		||||
    </body>
 | 
			
		||||
</html>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,54 +1,45 @@
 | 
			
		||||
import { app, BrowserWindow } from 'electron';
 | 
			
		||||
// This allows TypeScript to pick up the magic constants that's auto-generated by Forge's Webpack
 | 
			
		||||
// plugin that tells the Electron app where to look for the Webpack-bundled app code (depending on
 | 
			
		||||
// whether you're running in development or production).
 | 
			
		||||
import {app, BrowserWindow, screen} from 'electron';
 | 
			
		||||
import path from 'path';
 | 
			
		||||
 | 
			
		||||
declare const MAIN_WINDOW_WEBPACK_ENTRY: string;
 | 
			
		||||
declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: string;
 | 
			
		||||
 | 
			
		||||
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
 | 
			
		||||
if (require('electron-squirrel-startup')) {
 | 
			
		||||
  // eslint-disable-line global-require
 | 
			
		||||
  app.quit();
 | 
			
		||||
}
 | 
			
		||||
if(require('electron-squirrel-startup')) app.quit();
 | 
			
		||||
 | 
			
		||||
const createWindow = (): void => {
 | 
			
		||||
  // Create the browser window.
 | 
			
		||||
  const primaryDisplay = screen.getPrimaryDisplay();
 | 
			
		||||
  const height = 250;
 | 
			
		||||
 | 
			
		||||
  const mainWindow = new BrowserWindow({
 | 
			
		||||
    height: 600,
 | 
			
		||||
    width: 800,
 | 
			
		||||
    x: 0,
 | 
			
		||||
    y: primaryDisplay.workArea.height - height,
 | 
			
		||||
    height: height,
 | 
			
		||||
    width: primaryDisplay.size.width,
 | 
			
		||||
    frame: false,
 | 
			
		||||
    transparent: true,
 | 
			
		||||
    roundedCorners: false,
 | 
			
		||||
    resizable: false,
 | 
			
		||||
    fullscreen: false,
 | 
			
		||||
    alwaysOnTop: true,
 | 
			
		||||
    icon: path.join(__dirname, "../assets/logo.png"),
 | 
			
		||||
    title: 'Desktop Daemon',
 | 
			
		||||
    webPreferences: {
 | 
			
		||||
      // nodeIntegration:  true,
 | 
			
		||||
      // contextIsolation: false,
 | 
			
		||||
      preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // and load the index.html of the app.
 | 
			
		||||
  mainWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);
 | 
			
		||||
 | 
			
		||||
  // Open the DevTools.
 | 
			
		||||
  mainWindow.webContents.openDevTools();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// This method will be called when Electron has finished
 | 
			
		||||
// initialization and is ready to create browser windows.
 | 
			
		||||
// Some APIs can only be used after this event occurs.
 | 
			
		||||
app.on('ready', createWindow);
 | 
			
		||||
 | 
			
		||||
// Quit when all windows are closed, except on macOS. There, it's common
 | 
			
		||||
// for applications and their menu bar to stay active until the user quits
 | 
			
		||||
// explicitly with Cmd + Q.
 | 
			
		||||
app.on('window-all-closed', () => {
 | 
			
		||||
  if (process.platform !== 'darwin') {
 | 
			
		||||
    app.quit();
 | 
			
		||||
  }
 | 
			
		||||
  if (process.platform !== 'darwin') app.quit();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
app.on('activate', () => {
 | 
			
		||||
  // On OS X it's common to re-create a window in the app when the
 | 
			
		||||
  // dock icon is clicked and there are no other windows open.
 | 
			
		||||
  if (BrowserWindow.getAllWindows().length === 0) {
 | 
			
		||||
    createWindow();
 | 
			
		||||
  }
 | 
			
		||||
  if (BrowserWindow.getAllWindows().length === 0) createWindow();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// In this file you can include the rest of your app's specific main process
 | 
			
		||||
// code. You can also put them in separate files and import them here.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										84
									
								
								v2/src/npc.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								v2/src/npc.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
			
		||||
import {GRAVITY} from './constants';
 | 
			
		||||
import {SpriteSheet} from './sprite-sheet';
 | 
			
		||||
 | 
			
		||||
export type NPCOptions = {
 | 
			
		||||
	bubbleOffset?: [number, number];
 | 
			
		||||
	noBounds?: boolean;
 | 
			
		||||
	noGravity?: boolean;
 | 
			
		||||
	scale?: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class NPC {
 | 
			
		||||
	private readonly emojis = [
 | 
			
		||||
		0x1F600, 0x1F601, 0x1F603, 0x1F603, 0x1F604, 0x1F605, 0x1F606,
 | 
			
		||||
		0x1F607, 0x1F609, 0x1F60A, 0x1F642, 0x1F643, 0x1F355, 0x1F354,
 | 
			
		||||
	];
 | 
			
		||||
	private readonly texturePack: any;
 | 
			
		||||
 | 
			
		||||
	private random: number = 0;
 | 
			
		||||
	private sprite!: any;
 | 
			
		||||
	private text: string;
 | 
			
		||||
 | 
			
		||||
	public pos = [0, 0];
 | 
			
		||||
	public vel = [0, 0];
 | 
			
		||||
 | 
			
		||||
	constructor(private readonly ctx: CanvasRenderingContext2D,
 | 
			
		||||
				public readonly spriteSheetPath: string,
 | 
			
		||||
				public readonly spriteDefPath: string,
 | 
			
		||||
				public readonly options: NPCOptions = {},
 | 
			
		||||
	) {
 | 
			
		||||
		this.texturePack = new SpriteSheet(this.ctx,
 | 
			
		||||
			'./assets/sprites/texture-pack/spritesheet.png',
 | 
			
		||||
			'../assets/sprites/texture-pack/spritesheet.json');
 | 
			
		||||
 | 
			
		||||
		if(this.options.bubbleOffset == null) this.options.bubbleOffset = [0, 0];
 | 
			
		||||
		if(this.options.scale == null) this.options.scale = 1;
 | 
			
		||||
		this.sprite = new SpriteSheet(ctx, spriteSheetPath, spriteDefPath);
 | 
			
		||||
 | 
			
		||||
		setInterval(() => {
 | 
			
		||||
			this.message(String.fromCodePoint(this.emojis[~~(Math.random() * this.emojis.length)]));
 | 
			
		||||
		}, 10000);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	animate(name: string, reverse = false) {
 | 
			
		||||
		if(this.text) {
 | 
			
		||||
			const bubble = this.texturePack.definitions.sprites['bubble'];
 | 
			
		||||
			const x = this.pos[0] + this.options.bubbleOffset[0] * (reverse ? -1 : 1);
 | 
			
		||||
			const y = this.pos[1] + this.options.bubbleOffset[1];
 | 
			
		||||
			this.texturePack.drawSprite(x, y, 'bubble', reverse);
 | 
			
		||||
			this.ctx.save();
 | 
			
		||||
			this.ctx.textAlign = 'center';
 | 
			
		||||
			this.ctx.textBaseline = 'middle';
 | 
			
		||||
			this.ctx.font = '24px serif';
 | 
			
		||||
			this.ctx.fillText(this.text, x + (bubble.width / 2 * (reverse ? -1 : 1)), y + (bubble.height / 2));
 | 
			
		||||
			this.ctx.restore();
 | 
			
		||||
		}
 | 
			
		||||
		this.sprite.animate(this.pos[0], this.pos[1], name, reverse, this.options.scale);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tick() {
 | 
			
		||||
		if(this.random <= 0) {
 | 
			
		||||
			const move = Math.random();
 | 
			
		||||
			if(move < 0.333) this.vel = [0, 0];
 | 
			
		||||
			else if(move < 0.666) this.vel = [-10, 0];
 | 
			
		||||
			else this.vel = [10, 0];
 | 
			
		||||
			this.random = Math.random() * 50;
 | 
			
		||||
		}
 | 
			
		||||
		this.random--;
 | 
			
		||||
 | 
			
		||||
		this.pos = [this.pos[0] + this.vel[0], this.pos[1] + this.vel[1]];
 | 
			
		||||
		if(!this.options.noGravity) this.vel[1] -= GRAVITY;
 | 
			
		||||
		if(this.pos[1] < 0) this.pos[1] = 0;
 | 
			
		||||
		if(!this.options.noBounds) {
 | 
			
		||||
			if(this.pos[0] < 0) this.pos[0] = 0;
 | 
			
		||||
			if(this.pos[0] > this.ctx.canvas.width) this.pos[0] = this.ctx.canvas.width;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		this.animate(this.vel[0] == 0 ? 'idle' : 'walk', this.vel[0] < 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	message(text: string, ms = 5000) {
 | 
			
		||||
		setTimeout(() => this.text = null, ms);
 | 
			
		||||
		this.text = text;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -1,2 +0,0 @@
 | 
			
		||||
// See the Electron documentation for details on how to use preload scripts:
 | 
			
		||||
// https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts
 | 
			
		||||
 
 | 
			
		||||
@@ -1,31 +1,28 @@
 | 
			
		||||
/**
 | 
			
		||||
 * This file will automatically be loaded by webpack and run in the "renderer" context.
 | 
			
		||||
 * To learn more about the differences between the "main" and the "renderer" context in
 | 
			
		||||
 * Electron, visit:
 | 
			
		||||
 *
 | 
			
		||||
 * https://electronjs.org/docs/latest/tutorial/process-model
 | 
			
		||||
 *
 | 
			
		||||
 * By default, Node.js integration in this file is disabled. When enabling Node.js integration
 | 
			
		||||
 * in a renderer process, please be aware of potential security implications. You can read
 | 
			
		||||
 * more about security risks here:
 | 
			
		||||
 *
 | 
			
		||||
 * https://electronjs.org/docs/tutorial/security
 | 
			
		||||
 *
 | 
			
		||||
 * To enable Node.js integration in this file, open up `main.js` and enable the `nodeIntegration`
 | 
			
		||||
 * flag:
 | 
			
		||||
 *
 | 
			
		||||
 * ```
 | 
			
		||||
 *  // Create the browser window.
 | 
			
		||||
 *  mainWindow = new BrowserWindow({
 | 
			
		||||
 *    width: 800,
 | 
			
		||||
 *    height: 600,
 | 
			
		||||
 *    webPreferences: {
 | 
			
		||||
 *      nodeIntegration: true
 | 
			
		||||
 *    }
 | 
			
		||||
 *  });
 | 
			
		||||
 * ```
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import './index.css';
 | 
			
		||||
import {FRAME_RATE} from './constants';
 | 
			
		||||
import {NPC} from './npc';
 | 
			
		||||
 | 
			
		||||
console.log('👋 This message is being logged by "renderer.js", included via webpack');
 | 
			
		||||
const canvas = <HTMLCanvasElement>document.getElementById('canvas');
 | 
			
		||||
const ctx = canvas.getContext('2d');
 | 
			
		||||
const screenHeight = window.innerHeight;
 | 
			
		||||
const screenWidth = window.innerWidth;
 | 
			
		||||
 | 
			
		||||
canvas.width = screenWidth;
 | 
			
		||||
canvas.height = screenHeight;
 | 
			
		||||
 | 
			
		||||
function clearScreen() { ctx.clearRect(0, 0, screenWidth, screenHeight); }
 | 
			
		||||
 | 
			
		||||
const dog = new NPC(ctx, '/static/sprites/shadow-dog/spritesheet.png', '/static/sprites/shadow-dog/spritesheet.json', {
 | 
			
		||||
	bubbleOffset: [50, 75],
 | 
			
		||||
	scale: 0.25
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
let frame = 0, once = true;
 | 
			
		||||
setInterval(() => {
 | 
			
		||||
	requestAnimationFrame(() => {
 | 
			
		||||
		frame++;
 | 
			
		||||
		clearScreen();
 | 
			
		||||
 | 
			
		||||
		dog.tick();
 | 
			
		||||
	})
 | 
			
		||||
}, 1000 / FRAME_RATE);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										87
									
								
								v2/src/sprite-sheet.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								v2/src/sprite-sheet.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,87 @@
 | 
			
		||||
export type SpriteDefinitions = {
 | 
			
		||||
	width?: number;
 | 
			
		||||
	height?: number;
 | 
			
		||||
	animations?: {[key: string]: {y: number, frames: number}};
 | 
			
		||||
	sprites?: {[key: string]: {x: number, y: number, width?: number, height?: number}};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class SpriteSheet {
 | 
			
		||||
	private readonly definitions!: SpriteDefinitions;
 | 
			
		||||
	private readonly spriteSheet!: HTMLImageElement;
 | 
			
		||||
 | 
			
		||||
	private animation = '';
 | 
			
		||||
	private frame = -1;
 | 
			
		||||
 | 
			
		||||
	constructor(private readonly ctx: CanvasRenderingContext2D,
 | 
			
		||||
				public readonly spriteSheetPath: string,
 | 
			
		||||
				public readonly spriteDefPath: string,
 | 
			
		||||
	) {
 | 
			
		||||
		this.spriteSheet = new Image();
 | 
			
		||||
		this.spriteSheet.src = spriteSheetPath;
 | 
			
		||||
		this.definitions = require(spriteDefPath);
 | 
			
		||||
 | 
			
		||||
		// Backfill coordinates if shorthand is used
 | 
			
		||||
		if(this.definitions.sprites?.length) {
 | 
			
		||||
			Object.entries(this.definitions.sprites).forEach(sprite => {
 | 
			
		||||
				const [name, def] = sprite;
 | 
			
		||||
				if(def.width == null) {
 | 
			
		||||
					if(this.definitions.width == null)
 | 
			
		||||
						throw new Error(`Sprite is missing it's width: ${name}`);
 | 
			
		||||
					this.definitions.sprites[name].x = this.definitions.width * def.x;
 | 
			
		||||
					this.definitions.sprites[name].width = this.definitions.width;
 | 
			
		||||
				}
 | 
			
		||||
				if(def.height == null) {
 | 
			
		||||
					if(this.definitions.height == null)
 | 
			
		||||
						throw new Error(`Sprite is missing it's height: ${name}`);
 | 
			
		||||
					this.definitions.sprites[name].y = this.definitions.height * def.y;
 | 
			
		||||
					this.definitions.sprites[name].height = this.definitions.height;
 | 
			
		||||
				}
 | 
			
		||||
			});
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	animate(x: number, y: number, name: string = this.animation, flip = false, scale = 1) {
 | 
			
		||||
		const animation = this.definitions.animations[name];
 | 
			
		||||
		if(!animation) throw new Error(`Animation doesn't exist: ${name}`);
 | 
			
		||||
		if(name == this.animation) {
 | 
			
		||||
			this.frame++;
 | 
			
		||||
			if(this.frame >= animation.frames) this.frame = 0;
 | 
			
		||||
		} else {
 | 
			
		||||
			this.animation = name;
 | 
			
		||||
			this.frame = 0;
 | 
			
		||||
		}
 | 
			
		||||
		this.drawFrame(x, y, this.animation, this.frame, flip, scale);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	drawFrame(x: number, y: number, name: string, frame: number, flip = false, scale = 1, centerX = true, centerY = false) {
 | 
			
		||||
		const sprite = this.definitions.animations[name];
 | 
			
		||||
		if(!sprite) throw new Error(`Animation doesn't exist: ${name}`);
 | 
			
		||||
		this.ctx.save();
 | 
			
		||||
		this.ctx.translate(centerX ?
 | 
			
		||||
				this.definitions.width * scale / 2 * (flip ? 1 : -1) :
 | 
			
		||||
				flip ? this.definitions.width : 0,
 | 
			
		||||
			centerY ? this.definitions.height / -2 : 0);
 | 
			
		||||
		this.ctx.scale(flip ? -1 : 1, 1);
 | 
			
		||||
		this.ctx.drawImage(this.spriteSheet,
 | 
			
		||||
			frame * this.definitions.width, sprite.y * this.definitions.height, this.definitions.width, this.definitions.height,
 | 
			
		||||
			x * (flip ? -1 : 1), this.ctx.canvas.height - (this.definitions.height * scale + y),
 | 
			
		||||
			this.definitions.width * scale, this.definitions.height * scale);
 | 
			
		||||
		this.ctx.restore();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	drawSprite(x: number, y: number, name: string, flip = false, scale = 1, centerX = true, centerY = false) {
 | 
			
		||||
		const sprite = this.definitions.sprites[name];
 | 
			
		||||
		if(!sprite) throw new Error(`Sprite doesn't exist: ${name}`);
 | 
			
		||||
		this.ctx.save();
 | 
			
		||||
		this.ctx.translate(centerX ?
 | 
			
		||||
				this.definitions.width * scale / 2 * (flip ? 1 : -1) :
 | 
			
		||||
				flip ? this.definitions.width : 0,
 | 
			
		||||
			centerY ? this.definitions.height / -2 : 0);
 | 
			
		||||
		this.ctx.scale(flip ? -1 : 1, 1);
 | 
			
		||||
		this.ctx.drawImage(this.spriteSheet,
 | 
			
		||||
			sprite.x, sprite.y, sprite.width, sprite.height,
 | 
			
		||||
			x * (flip ? -1 : 1), this.ctx.canvas.height - (sprite.height * scale + y),
 | 
			
		||||
			sprite.width * scale, sprite.height * scale);
 | 
			
		||||
		this.ctx.restore();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								v2/src/utils.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								v2/src/utils.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
export function sleep(ms: number) {
 | 
			
		||||
	return new Promise(res => setTimeout(res, ms));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								v2/static/logo.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								v2/static/logo.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 1018 B  | 
							
								
								
									
										14
									
								
								v2/static/sprites/shadow-dog/spritesheet.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								v2/static/sprites/shadow-dog/spritesheet.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
{
 | 
			
		||||
	"width": 575,
 | 
			
		||||
	"height": 523,
 | 
			
		||||
	"animations": {
 | 
			
		||||
		"idle": {
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"frames": 6
 | 
			
		||||
		},
 | 
			
		||||
		"walk": {
 | 
			
		||||
			"y": 3,
 | 
			
		||||
			"frames": 8
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								v2/static/sprites/shadow-dog/spritesheet.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								v2/static/sprites/shadow-dog/spritesheet.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 1.8 MiB  | 
							
								
								
									
										11
									
								
								v2/static/sprites/template/spritesheet.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								v2/static/sprites/template/spritesheet.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
{
 | 
			
		||||
	"width": 50,
 | 
			
		||||
	"height": 50,
 | 
			
		||||
	"animations": [
 | 
			
		||||
		{
 | 
			
		||||
			"name": "idle",
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"frames": 8
 | 
			
		||||
		}
 | 
			
		||||
	]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								v2/static/sprites/template/spritesheet.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								v2/static/sprites/template/spritesheet.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 228 B  | 
							
								
								
									
										58
									
								
								v2/static/sprites/texture-pack/spritesheet.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								v2/static/sprites/texture-pack/spritesheet.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
{
 | 
			
		||||
	"sprites": {
 | 
			
		||||
		"generic": {
 | 
			
		||||
			"x": 0,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"text": {
 | 
			
		||||
			"x": 100,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"code": {
 | 
			
		||||
			"x": 200,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"zip": {
 | 
			
		||||
			"x": 300,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"image": {
 | 
			
		||||
			"x": 400,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"audio": {
 | 
			
		||||
			"x": 500,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"video": {
 | 
			
		||||
			"x": 600,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"pdf": {
 | 
			
		||||
			"x": 700,
 | 
			
		||||
			"y": 0,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		},
 | 
			
		||||
		"bubble": {
 | 
			
		||||
			"x": 0,
 | 
			
		||||
			"y": 100,
 | 
			
		||||
			"width": 100,
 | 
			
		||||
			"height": 100
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								v2/static/sprites/texture-pack/spritesheet.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								v2/static/sprites/texture-pack/spritesheet.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 28 KiB  | 
		Reference in New Issue
	
	Block a user