core2d 2.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Diogo Eichert
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,62 @@
1
+ ![core2d logo](./core2d.jpg)
2
+
3
+ # About
4
+ Core2D is the powerhouse used by [Maragato マラガト](https://maragato.itch.io) apps, among others. It is the evolution of Videogame, which in turn was the evolution of Quick. In its current form, it adopts [JavaScript modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules), leveraging the full power of [Object-oriented programming](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object-oriented_programming).
5
+
6
+ ## Concept
7
+ Apps created with Core2D are made of one or more [scenes](src/Scene.mjs), which may contain one or more [sprites](src/Sprite.mjs). These objects have properties that can be customized to shape their behavior. It's that simple.
8
+
9
+ # Get Started
10
+ [Download](https://github.com/dgchrt/core2d-skel/archive/refs/heads/main.zip) or clone/fork the [skeleton project](https://github.com/dgchrt/core2d-skel/) to start building your app. Alternatively, the library can be also installed to your existing/new project:
11
+ ```shell
12
+ npm install core2d
13
+ ```
14
+
15
+ ## Learn
16
+ The best way to learn is by doing, and you can see what Core2D is capable of through existing open-sourced apps. Check the [Hall of Fame](#hall-of-fame) below for some source code.
17
+
18
+ ## Support
19
+ Please consider joining the [Discussions](https://github.com/dgchrt/core2d/discussions) for collaboration and support.
20
+
21
+ # Features
22
+
23
+ ## Collision Detection
24
+ Translated to callbacks, to keep update logic clean.
25
+
26
+ ## Assets Caching
27
+ Assets and their transformations are reused automatically to keep a solid performance.
28
+
29
+ ## User Input
30
+ Human interaction is unified via abstractions, so that apps will just work, regardless of the devices in use.
31
+
32
+ ### Controllers
33
+ ![controllers](controller.png)
34
+
35
+ Gamepads or keyboard. When using a keyboard, sensible defaults (minding accessibility) are used, as seen in [KeyMap.mjs](https://github.com/dgchrt/core2d/blob/main/src/KeyMap.mjs).
36
+
37
+ ### Pointers
38
+ ![pointer](pointer.png)
39
+
40
+ Mice or touch screen.
41
+
42
+ ## Virtual Resolution
43
+ Internal geometry frees the app logic from displays, i.e. your app can have an internal logic resolution of 800x600, while running on any display size.
44
+
45
+ # Contributing
46
+ The core of the library (under `src/`) should remain agnostic and lean. Updates to the core library are usually related to technology developments in the platform (web API advances), while staying true to the basic concepts of the library, which are common to all apps.
47
+
48
+ Opinionated functionality should be implemented in the form of a plugin (under `src/plugin/`). Plugins can add features that are domain driven, such as elements that can be reused by multiple apps, but not necessarily by every app.
49
+
50
+ # Hall of Fame
51
+ Apps created with Core2D:
52
+ - [Asteroids Remake](https://chamun.github.io/asteroids-remake/) ([source](https://github.com/chamun/asteroids-remake))
53
+ - [Cityscape](https://puter.com/app/cityscape) - Single-player arcade survival game
54
+ - [Cucurbita's Halloween](https://www.kongregate.com/games/bbastudios/cucurbitas-halloween)
55
+ - [Dragonfire](http://staudt.github.io/dragonfire) ([source](https://github.com/staudt/dragonfire))
56
+ - [Missile Commander](https://dgchrt.github.io/missile-commander/) ([source](https://github.com/dgchrt/missile-commander))
57
+ - [Ms. Starship](https://puter.com/app/ms-starship) - Multi-player arcade shoot'em up
58
+ - [Mythology](https://puter.com/app/mythology) - Single-player arcade pinball
59
+ - [Raycaster](https://staudt.github.io/raycaster/) ([source](https://github.com/staudt/raycaster))
60
+ - [Starship](https://puter.com/app/starship) - Single-player arcade shoot'em up
61
+ - [Super Breakout Bros.](https://staudt.github.io/SuperBreakoutBros/) ([source](https://github.com/staudt/SuperBreakoutBros))
62
+ - [Tower Defense](https://danielcolnaghi.github.io/towerdefense) ([source](https://github.com/danielcolnaghi/towerdefense))
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "core2d",
3
+ "type": "module",
4
+ "version": "2.10.2",
5
+ "description": "Multiplatform 2D interaction engine",
6
+ "files": [
7
+ "src"
8
+ ],
9
+ "scripts": {
10
+ "lint": "eslint",
11
+ "prepublishOnly": "git checkout main && git pull --rebase && npm test && git push && git push --tags",
12
+ "test": "npm run lint && for test in ./test/*.mjs; do node $test; done"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/diogoeichert/core2d.git"
17
+ },
18
+ "keywords": [
19
+ "2d",
20
+ "core",
21
+ "core2d",
22
+ "engine",
23
+ "game",
24
+ "game-engine",
25
+ "gamepad",
26
+ "interaction",
27
+ "keyboard",
28
+ "mouse",
29
+ "multi-platform",
30
+ "multimedia",
31
+ "object-oriented",
32
+ "sprites",
33
+ "scenes",
34
+ "touch"
35
+ ],
36
+ "author": "Diogo Eichert",
37
+ "license": "MIT",
38
+ "bugs": {
39
+ "url": "https://github.com/diogoeichert/core2d/issues"
40
+ },
41
+ "funding": {
42
+ "url": "https://github.com/sponsors/diogoeichert"
43
+ },
44
+ "homepage": "https://diogoeichert.github.io/core2d/",
45
+ "devDependencies": {
46
+ "@eslint/js": "^9.30.1",
47
+ "eslint": "^9.30.1",
48
+ "globals": "^16.3.0"
49
+ }
50
+ }
package/src/ACL.mjs ADDED
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Sets up the environment based on its runtime (browser or not).
5
+ */
6
+ if (typeof(global) != "undefined") {
7
+ global.addEventListener = () => {};
8
+
9
+ global.document = {
10
+ createElement: (name) => {
11
+ if (name == "canvas") {
12
+ return {
13
+ getContext: () => {
14
+ return {
15
+ measureText: (text) => {
16
+ return {
17
+ width: text.length,
18
+ };
19
+ },
20
+ };
21
+ },
22
+ };
23
+ }
24
+ },
25
+ getElementById: (id) => {
26
+ if (id == "app") {
27
+ return {
28
+ focus: () => {},
29
+ getContext: () => {
30
+ return {
31
+ fillRect: () => {},
32
+ };
33
+ },
34
+ height: 400,
35
+ offsetLeft: 0,
36
+ offsetTop: 0,
37
+ style: {},
38
+ width: 640,
39
+ };
40
+ }
41
+
42
+ return {};
43
+ },
44
+ getElementsByTagName: () => {
45
+ return [];
46
+ }
47
+ };
48
+
49
+ global.localStorage = {};
50
+
51
+ /**
52
+ * For older Node.js versions.
53
+ */
54
+ if (!global.navigator) {
55
+ global.navigator = {};
56
+ }
57
+
58
+ global.window = {
59
+ focus: () => {},
60
+ innerHeight: 600,
61
+ innerWidth: 800,
62
+ requestAnimationFrame: () => true
63
+ };
64
+ }
65
+
66
+ /**
67
+ * Anti-Corruption Layer, to be used instead of direct API calls.
68
+ */
69
+ export const ACL = {
70
+ document,
71
+ window,
72
+ };
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+
3
+ import { Frame } from "./Frame.mjs";
4
+
5
+ export class Animation {
6
+ constructor(frames) {
7
+ this._frames = frames;
8
+ this._index = 0;
9
+ this._tick = 0;
10
+ }
11
+
12
+ static fromImages(images, duration) {
13
+ return new this(images.map(image => new Frame(image, duration)));
14
+ }
15
+
16
+ get image() {
17
+ return this._frames[this._index].image;
18
+ }
19
+
20
+ get width() {
21
+ return this._frames[this._index].width;
22
+ }
23
+
24
+ get height() {
25
+ return this._frames[this._index].height;
26
+ }
27
+
28
+ setFrameIndex(index) {
29
+ if (index < this._frames.length) {
30
+ this._index = index;
31
+ this._tick = 0;
32
+ }
33
+ }
34
+
35
+ set frameIndex(index) {
36
+ this.setFrameIndex(index);
37
+ }
38
+
39
+ sync() {
40
+ const DURATION = this._frames[this._index].duration;
41
+ let hasLooped = false;
42
+
43
+ if (DURATION && ++this._tick >= DURATION) {
44
+ let index = this._index + 1;
45
+
46
+ if (index == this._frames.length) {
47
+ hasLooped = true;
48
+ index = 0;
49
+ }
50
+
51
+ this.setFrameIndex(index);
52
+ }
53
+
54
+ return hasLooped;
55
+ }
56
+ }
package/src/Axis.mjs ADDED
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+
3
+ import { Static } from "./Static.mjs";
4
+
5
+ export const Axis = Static.makeEnum([
6
+ "LEFT_X",
7
+ "LEFT_Y",
8
+ "RIGHT_X",
9
+ "RIGHT_Y",
10
+ ]);
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+
3
+ import { Static } from "./Static.mjs";
4
+
5
+ export const ButtonLayout = {
6
+ reversed: Static.makeEnum([
7
+ "B",
8
+ "A",
9
+ "Y",
10
+ "X",
11
+ "L1",
12
+ "R1",
13
+ "L2",
14
+ "R2",
15
+ "SELECT",
16
+ "START",
17
+ "L3",
18
+ "R3",
19
+ "UP",
20
+ "DOWN",
21
+ "LEFT",
22
+ "RIGHT",
23
+ ]),
24
+
25
+ standard: Static.makeEnum([
26
+ "A",
27
+ "B",
28
+ "X",
29
+ "Y",
30
+ "L1",
31
+ "R1",
32
+ "L2",
33
+ "R2",
34
+ "SELECT",
35
+ "START",
36
+ "L3",
37
+ "R3",
38
+ "UP",
39
+ "DOWN",
40
+ "LEFT",
41
+ "RIGHT",
42
+ ])
43
+ };
@@ -0,0 +1,5 @@
1
+ "use static";
2
+
3
+ export const ButtonLayoutMap = {
4
+ "8bitdo s": "reversed"
5
+ };
package/src/Color.mjs ADDED
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+
3
+ import { Static } from "./Static.mjs";
4
+
5
+ export const Color = Static.makeHash([
6
+ "AliceBlue",
7
+ "AntiqueWhite",
8
+ "Aqua",
9
+ "Aquamarine",
10
+ "Azure",
11
+ "Beige",
12
+ "Bisque",
13
+ "Black",
14
+ "BlanchedAlmond",
15
+ "Blue",
16
+ "BlueViolet",
17
+ "Brown",
18
+ "BurlyWood",
19
+ "CadetBlue",
20
+ "Chartreuse",
21
+ "Chocolate",
22
+ "Coral",
23
+ "CornflowerBlue",
24
+ "Cornsilk",
25
+ "Crimson",
26
+ "Cyan",
27
+ "DarkBlue",
28
+ "DarkCyan",
29
+ "DarkGoldenRod",
30
+ "DarkGray",
31
+ "DarkGreen",
32
+ "DarkGrey",
33
+ "DarkKhaki",
34
+ "DarkMagenta",
35
+ "DarkOliveGreen",
36
+ "Darkorange",
37
+ "DarkOrchid",
38
+ "DarkRed",
39
+ "DarkSalmon",
40
+ "DarkSeaGreen",
41
+ "DarkSlateBlue",
42
+ "DarkSlateGray",
43
+ "DarkSlateGrey",
44
+ "DarkTurquoise",
45
+ "DarkViolet",
46
+ "DeepPink",
47
+ "DeepSkyBlue",
48
+ "DimGray",
49
+ "DimGrey",
50
+ "DodgerBlue",
51
+ "FireBrick",
52
+ "FloralWhite",
53
+ "ForestGreen",
54
+ "Fuchsia",
55
+ "Gainsboro",
56
+ "GhostWhite",
57
+ "Gold",
58
+ "GoldenRod",
59
+ "Gray",
60
+ "Green",
61
+ "GreenYellow",
62
+ "Grey",
63
+ "HoneyDew",
64
+ "HotPink",
65
+ "IndianRed",
66
+ "Indigo",
67
+ "Ivory",
68
+ "Khaki",
69
+ "Lavender",
70
+ "LavenderBlush",
71
+ "LawnGreen",
72
+ "LemonChiffon",
73
+ "LightBlue",
74
+ "LightCoral",
75
+ "LightCyan",
76
+ "LightGoldenRodYellow",
77
+ "LightGray",
78
+ "LightGreen",
79
+ "LightGrey",
80
+ "LightPink",
81
+ "LightSalmon",
82
+ "LightSeaGreen",
83
+ "LightSkyBlue",
84
+ "LightSlateGray",
85
+ "LightSlateGrey",
86
+ "LightSteelBlue",
87
+ "LightYellow",
88
+ "Lime",
89
+ "LimeGreen",
90
+ "Linen",
91
+ "Magenta",
92
+ "Maroon",
93
+ "MediumAquaMarine",
94
+ "MediumBlue",
95
+ "MediumOrchid",
96
+ "MediumPurple",
97
+ "MediumSeaGreen",
98
+ "MediumSlateBlue",
99
+ "MediumSpringGreen",
100
+ "MediumTurquoise",
101
+ "MediumVioletRed",
102
+ "MidnightBlue",
103
+ "MintCream",
104
+ "MistyRose",
105
+ "Moccasin",
106
+ "NavajoWhite",
107
+ "Navy",
108
+ "OldLace",
109
+ "Olive",
110
+ "OliveDrab",
111
+ "Orange",
112
+ "OrangeRed",
113
+ "Orchid",
114
+ "PaleGoldenRod",
115
+ "PaleGreen",
116
+ "PaleTurquoise",
117
+ "PaleVioletRed",
118
+ "PapayaWhip",
119
+ "PeachPuff",
120
+ "Peru",
121
+ "Pink",
122
+ "Plum",
123
+ "PowderBlue",
124
+ "Purple",
125
+ "RebeccaPurple",
126
+ "Red",
127
+ "RosyBrown",
128
+ "RoyalBlue",
129
+ "SaddleBrown",
130
+ "Salmon",
131
+ "SandyBrown",
132
+ "SeaGreen",
133
+ "SeaShell",
134
+ "Sienna",
135
+ "Silver",
136
+ "SkyBlue",
137
+ "SlateBlue",
138
+ "SlateGray",
139
+ "SlateGrey",
140
+ "Snow",
141
+ "SpringGreen",
142
+ "SteelBlue",
143
+ "Tan",
144
+ "Teal",
145
+ "Thistle",
146
+ "Tomato",
147
+ "Turquoise",
148
+ "Violet",
149
+ "Wheat",
150
+ "White",
151
+ "WhiteSmoke",
152
+ "Yellow",
153
+ "YellowGreen",
154
+ ]);
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ import { Static } from "./Static.mjs";
4
+
5
+ export const Command = Static.makeEnum([
6
+ "UP",
7
+ "DOWN",
8
+ "LEFT",
9
+ "RIGHT",
10
+ "A",
11
+ "B",
12
+ "X",
13
+ "Y",
14
+ "SELECT",
15
+ "START",
16
+ ]);
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ export const CompositeOperations = {
4
+ COPY: "copy",
5
+ DESTINATION_ATOP: "destination-atop",
6
+ DESTINATION_IN: "destination-in",
7
+ DESTINATION_OUT: "destination-out",
8
+ DESTINATION_OVER: "destination-over",
9
+ LIGHTER: "lighter",
10
+ SOURCE_ATOP: "source-atop",
11
+ SOURCE_IN: "source-in",
12
+ SOURCE_OUT: "source-out",
13
+ SOURCE_OVER: "source-over",
14
+ XOR: "xor",
15
+ };
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+
3
+ import { Command } from "./Command.mjs";
4
+
5
+ export class Controller {
6
+ constructor() {
7
+ this.tolerance = 0;
8
+ this._active = {};
9
+ this._device = null;
10
+ this._hold = {};
11
+ this._sequence = [];
12
+ this._tick = 0;
13
+ }
14
+
15
+ didPerform(commands) {
16
+ for (let i = 1; i <= commands.length; ++i) {
17
+ if (this._sequence[this._sequence.length - i] != commands[commands.length - i]) {
18
+ return false;
19
+ }
20
+ }
21
+
22
+ this._sequence = [];
23
+ return true;
24
+ }
25
+
26
+ keyDown(command) {
27
+ return this._active[command];
28
+ }
29
+
30
+ keyPush(command) {
31
+ return this._active[command] && !this._hold[command];
32
+ }
33
+
34
+ setDevice(device) {
35
+ this._device = device;
36
+ }
37
+
38
+ update() {
39
+ if (!this._device) {
40
+ return;
41
+ }
42
+
43
+ this._hold = {};
44
+ const LAST = this._active;
45
+ this._active = this._device.commands;
46
+
47
+ for (let i in this._active) {
48
+ if (LAST[i]) {
49
+ this._hold[i] = true;
50
+ }
51
+ }
52
+
53
+ if (this.tolerance && ++this._tick > this.tolerance) {
54
+ this._sequence = [];
55
+ this._tick = 0;
56
+ }
57
+
58
+ for (let i in Command) {
59
+ const COMMAND = Command[i];
60
+
61
+ if (this.keyPush(COMMAND)) {
62
+ this._sequence.push(COMMAND);
63
+ this._tick = 0;
64
+ }
65
+ }
66
+ }
67
+ }