├── asset
├── link.js
├── image
│ ├── hud
│ │ ├── item.png
│ │ ├── ability.png
│ │ └── avatar.png
│ ├── cursor
│ │ ├── alt.cur
│ │ ├── busy.ani
│ │ ├── diag1.cur
│ │ ├── diag2.cur
│ │ ├── help.cur
│ │ ├── horiz.cur
│ │ ├── link.cur
│ │ ├── loc.cur
│ │ ├── move.cur
│ │ ├── text.cur
│ │ ├── vert.cur
│ │ ├── README.txt
│ │ ├── normal.cur
│ │ ├── oldhand.cur
│ │ ├── person.cur
│ │ ├── preview.png
│ │ ├── working.ani
│ │ ├── crosshair.cur
│ │ ├── handwriting.cur
│ │ ├── unavailable.cur
│ │ └── Install.inf
│ ├── more
│ │ ├── biglogo.png
│ │ └── newlogo.png
│ ├── spell
│ │ └── Flash.png
│ └── champion
│ │ ├── ahri
│ │ ├── Charm.ability.png
│ │ ├── Ahri.avatar.circle.png
│ │ ├── Ahri.avatar.square.png
│ │ ├── Fox-Fire.ability.png
│ │ ├── Spirit-Rush.ability.png
│ │ └── Orb-of-Deception.ability.png
│ │ └── jinx
│ │ ├── Zap.ability.png
│ │ ├── Jinx.avatar.circle.png
│ │ ├── Jinx.avatar.sqaure.png
│ │ ├── Flame-Chompers.ability.png
│ │ ├── Switcheroo.Fishbones.ability.png
│ │ ├── Switcheroo.Pow-Pow.ability.png
│ │ └── Super-Mega-Death-Rocket.ability.png
└── sound
│ └── test_bosca.ceol
├── css
├── game-scene.css
├── hextech-css
│ ├── img
│ │ └── btn.jpg
│ ├── fonts
│ │ ├── Beaufort-Bold.ttf
│ │ ├── Beaufort-Bold.woff
│ │ ├── Spiegel-Italic.ttf
│ │ ├── Beaufort-Italic.ttf
│ │ ├── Beaufort-Italic.woff
│ │ ├── Beaufort-Regular.ttf
│ │ ├── Beaufort-Regular.woff
│ │ ├── Spiegel-Italic.woff
│ │ ├── Spiegel-Regular.ttf
│ │ └── Spiegel-Regular.woff
│ ├── LICENSE
│ └── hextech.min.css
├── style.css
├── loading-scene.css
├── pre-game-scene.css
└── menu-scene.css
├── .prettierrc
├── .vscode
└── settings.json
├── temp
├── gameCore
│ ├── maps
│ │ ├── SummonersRift.js
│ │ └── GameMap.js
│ ├── ObjectManager.js
│ ├── utils
│ │ ├── Uuid.js
│ │ └── Collision.js
│ ├── gameObjects
│ │ ├── stats
│ │ │ ├── StatModifier.js
│ │ │ ├── ChampionStats.js
│ │ │ ├── Stat.js
│ │ │ └── Stats.js
│ │ ├── GameObject.js
│ │ └── attackableUnits
│ │ │ └── Champion.js
│ └── Game.js
├── _enums
│ ├── Packets
│ │ ├── ChatType.js
│ │ ├── Emotions.js
│ │ ├── Pings.js
│ │ ├── MoveType.js
│ │ ├── MasterMask.js
│ │ ├── SurrenderReason.js
│ │ ├── Channel.js
│ │ └── SummonerSpellIds.js
│ ├── DrawPathMode.js
│ ├── AttackType.js
│ ├── InhibitorState.js
│ ├── DamageType.js
│ ├── SpellState.js
│ ├── MinionSpawnType.js
│ ├── TurretType.js
│ ├── Announces.js
│ ├── MinionSpawnPosition.js
│ ├── DamageResultType.js
│ ├── LaneID.js
│ ├── GroundAttackMode.js
│ ├── UnitAnnounces.js
│ ├── CrowdControlType.js
│ ├── MoveOrder.js
│ ├── PrimaryAbilityResourceType.js
│ ├── NavigationGridCellFlags.js
│ ├── ClassifyUnit.js
│ ├── ActionState.js
│ ├── BuffType.js
│ ├── BuffAddType.js
│ ├── DamageSource.js
│ ├── FloatTextType.js
│ └── SpellFlags.js
├── enums
│ ├── TeamID.js
│ ├── EventType.js
│ └── StatusFlags.js
└── gameScripts
│ └── champions
│ └── Ahri
│ └── Q.js
├── favicon
├── favicon.ico
├── favicon-16x16.png
├── favicon-32x32.png
├── apple-touch-icon.png
├── mstile-150x150.png
├── android-chrome-192x192.png
├── android-chrome-512x512.png
├── browserconfig.xml
├── site.webmanifest
└── safari-pinned-tab.svg
├── playzone
├── hud
│ ├── asset
│ │ ├── item.png
│ │ ├── ability.png
│ │ └── avatar.png
│ ├── main.js
│ ├── index.html
│ └── style.css
├── programming-patterns
│ ├── component
│ │ ├── core
│ │ │ ├── MonoBehaviour.js
│ │ │ ├── Scene.js
│ │ │ ├── Camera.js
│ │ │ ├── Behaviour.js
│ │ │ ├── Transform.js
│ │ │ ├── Vector.js
│ │ │ ├── Component.js
│ │ │ ├── BaseObject.js
│ │ │ ├── SceneManager.js
│ │ │ └── GameObject.js
│ │ ├── README.md
│ │ ├── components
│ │ │ └── TestComponent.js
│ │ ├── index.html
│ │ ├── main.js
│ │ └── scenes
│ │ │ └── TestScene.js
│ ├── command
│ │ ├── README.md
│ │ ├── index.html
│ │ └── main.js
│ ├── observer
│ │ ├── index.html
│ │ ├── main.js
│ │ ├── Subject.js
│ │ └── EventEmitter.js
│ └── README.md
├── buffer
│ ├── index.html
│ └── main.js
├── fixedupdate
│ ├── index.html
│ └── main.js
├── sight
│ ├── index.html
│ └── main.js
├── contour
│ ├── index.html
│ └── main.js
├── gradient
│ ├── index.html
│ └── main.js
├── sat
│ ├── index.html
│ └── main.js
├── animejs
│ ├── index.html
│ └── main.js
├── quadtree
│ ├── index.html
│ ├── main.js
│ └── lib
│ │ └── quadtree.js
├── decomp-polygon
│ ├── index.html
│ └── main.js
├── visibility
│ ├── index.html
│ └── main.js
└── shader
│ └── index.html
├── src
├── app.js
├── game
│ ├── enums
│ │ ├── SpellKeys.js
│ │ └── StatusFlags.js
│ ├── stats
│ │ ├── StatModifier.js
│ │ ├── StatsModifier.js
│ │ ├── Stat.js
│ │ └── Stats.js
│ ├── Game.js
│ ├── champions
│ │ └── Champion.js
│ └── maps
│ │ ├── Camera.js
│ │ └── GroundMap.js
├── managers
│ ├── InputManager.js
│ ├── AssetManager.js
│ ├── EventManager.js
│ └── SceneManager.js
├── utils
│ └── Helpers.js
├── scenes
│ ├── MenuScene.js
│ ├── GameScene.js
│ └── LoadingScene.js
└── Sketch.js
├── test
└── LOL2D-chatGPT
│ ├── index.js
│ ├── src
│ ├── utils.js
│ ├── buff.js
│ ├── spell.js
│ ├── champion.js
│ ├── main.js
│ └── map
│ │ ├── GroundMap.js
│ │ └── Camera.js
│ ├── style.css
│ └── index.html
├── README.md
├── index.html
└── lib
├── decomp.min.js
├── stats.js
├── state-machine.min.js
└── quadtree.js
/asset/link.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/css/game-scene.css:
--------------------------------------------------------------------------------
1 | /* game scene */
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "tabWidth": 4,
3 | "useTabs": false
4 | }
5 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "liveServer.settings.port": 5501
3 | }
--------------------------------------------------------------------------------
/temp/gameCore/maps/SummonersRift.js:
--------------------------------------------------------------------------------
1 | export default class SummonersRift {
2 |
3 | }
--------------------------------------------------------------------------------
/favicon/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/favicon/favicon.ico
--------------------------------------------------------------------------------
/asset/image/hud/item.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/hud/item.png
--------------------------------------------------------------------------------
/favicon/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/favicon/favicon-16x16.png
--------------------------------------------------------------------------------
/favicon/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/favicon/favicon-32x32.png
--------------------------------------------------------------------------------
/asset/image/cursor/alt.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/cursor/alt.cur
--------------------------------------------------------------------------------
/asset/image/cursor/busy.ani:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/cursor/busy.ani
--------------------------------------------------------------------------------
/asset/image/cursor/diag1.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/cursor/diag1.cur
--------------------------------------------------------------------------------
/asset/image/cursor/diag2.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/cursor/diag2.cur
--------------------------------------------------------------------------------
/asset/image/cursor/help.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/cursor/help.cur
--------------------------------------------------------------------------------
/asset/image/cursor/horiz.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/cursor/horiz.cur
--------------------------------------------------------------------------------
/asset/image/cursor/link.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/cursor/link.cur
--------------------------------------------------------------------------------
/asset/image/cursor/loc.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/cursor/loc.cur
--------------------------------------------------------------------------------
/asset/image/cursor/move.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/cursor/move.cur
--------------------------------------------------------------------------------
/asset/image/cursor/text.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/cursor/text.cur
--------------------------------------------------------------------------------
/asset/image/cursor/vert.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/cursor/vert.cur
--------------------------------------------------------------------------------
/asset/image/hud/ability.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/hud/ability.png
--------------------------------------------------------------------------------
/asset/image/hud/avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/hud/avatar.png
--------------------------------------------------------------------------------
/asset/image/more/biglogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/more/biglogo.png
--------------------------------------------------------------------------------
/asset/image/more/newlogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/more/newlogo.png
--------------------------------------------------------------------------------
/asset/image/spell/Flash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/spell/Flash.png
--------------------------------------------------------------------------------
/css/hextech-css/img/btn.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/css/hextech-css/img/btn.jpg
--------------------------------------------------------------------------------
/favicon/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/favicon/apple-touch-icon.png
--------------------------------------------------------------------------------
/favicon/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/favicon/mstile-150x150.png
--------------------------------------------------------------------------------
/playzone/hud/asset/item.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/playzone/hud/asset/item.png
--------------------------------------------------------------------------------
/asset/image/cursor/README.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/cursor/README.txt
--------------------------------------------------------------------------------
/asset/image/cursor/normal.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/cursor/normal.cur
--------------------------------------------------------------------------------
/asset/image/cursor/oldhand.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/cursor/oldhand.cur
--------------------------------------------------------------------------------
/asset/image/cursor/person.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/cursor/person.cur
--------------------------------------------------------------------------------
/asset/image/cursor/preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/cursor/preview.png
--------------------------------------------------------------------------------
/asset/image/cursor/working.ani:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/cursor/working.ani
--------------------------------------------------------------------------------
/playzone/hud/asset/ability.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/playzone/hud/asset/ability.png
--------------------------------------------------------------------------------
/playzone/hud/asset/avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/playzone/hud/asset/avatar.png
--------------------------------------------------------------------------------
/asset/image/cursor/crosshair.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/cursor/crosshair.cur
--------------------------------------------------------------------------------
/src/app.js:
--------------------------------------------------------------------------------
1 | import Sketch from "./Sketch.js";
2 |
3 | for (let o in Sketch) {
4 | window[o] = Sketch[o];
5 | }
6 |
--------------------------------------------------------------------------------
/asset/image/cursor/handwriting.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/cursor/handwriting.cur
--------------------------------------------------------------------------------
/asset/image/cursor/unavailable.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/cursor/unavailable.cur
--------------------------------------------------------------------------------
/favicon/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/favicon/android-chrome-192x192.png
--------------------------------------------------------------------------------
/favicon/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/favicon/android-chrome-512x512.png
--------------------------------------------------------------------------------
/css/hextech-css/fonts/Beaufort-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/css/hextech-css/fonts/Beaufort-Bold.ttf
--------------------------------------------------------------------------------
/css/hextech-css/fonts/Beaufort-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/css/hextech-css/fonts/Beaufort-Bold.woff
--------------------------------------------------------------------------------
/css/hextech-css/fonts/Spiegel-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/css/hextech-css/fonts/Spiegel-Italic.ttf
--------------------------------------------------------------------------------
/asset/image/champion/ahri/Charm.ability.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/champion/ahri/Charm.ability.png
--------------------------------------------------------------------------------
/asset/image/champion/jinx/Zap.ability.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/champion/jinx/Zap.ability.png
--------------------------------------------------------------------------------
/css/hextech-css/fonts/Beaufort-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/css/hextech-css/fonts/Beaufort-Italic.ttf
--------------------------------------------------------------------------------
/css/hextech-css/fonts/Beaufort-Italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/css/hextech-css/fonts/Beaufort-Italic.woff
--------------------------------------------------------------------------------
/css/hextech-css/fonts/Beaufort-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/css/hextech-css/fonts/Beaufort-Regular.ttf
--------------------------------------------------------------------------------
/css/hextech-css/fonts/Beaufort-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/css/hextech-css/fonts/Beaufort-Regular.woff
--------------------------------------------------------------------------------
/css/hextech-css/fonts/Spiegel-Italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/css/hextech-css/fonts/Spiegel-Italic.woff
--------------------------------------------------------------------------------
/css/hextech-css/fonts/Spiegel-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/css/hextech-css/fonts/Spiegel-Regular.ttf
--------------------------------------------------------------------------------
/css/hextech-css/fonts/Spiegel-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/css/hextech-css/fonts/Spiegel-Regular.woff
--------------------------------------------------------------------------------
/asset/image/champion/ahri/Ahri.avatar.circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/champion/ahri/Ahri.avatar.circle.png
--------------------------------------------------------------------------------
/asset/image/champion/ahri/Ahri.avatar.square.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/champion/ahri/Ahri.avatar.square.png
--------------------------------------------------------------------------------
/asset/image/champion/ahri/Fox-Fire.ability.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/champion/ahri/Fox-Fire.ability.png
--------------------------------------------------------------------------------
/asset/image/champion/jinx/Jinx.avatar.circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/champion/jinx/Jinx.avatar.circle.png
--------------------------------------------------------------------------------
/asset/image/champion/jinx/Jinx.avatar.sqaure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/champion/jinx/Jinx.avatar.sqaure.png
--------------------------------------------------------------------------------
/asset/image/champion/ahri/Spirit-Rush.ability.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/champion/ahri/Spirit-Rush.ability.png
--------------------------------------------------------------------------------
/asset/image/champion/jinx/Flame-Chompers.ability.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/champion/jinx/Flame-Chompers.ability.png
--------------------------------------------------------------------------------
/temp/_enums/Packets/ChatType.js:
--------------------------------------------------------------------------------
1 | const ChatType = {
2 | ALL: 0,
3 | TEAM: 1,
4 | };
5 |
6 | Object.freeze(ChatType);
7 | export default ChatType;
8 |
--------------------------------------------------------------------------------
/test/LOL2D-chatGPT/index.js:
--------------------------------------------------------------------------------
1 | import * as f from "./src/main.js";
2 |
3 | console.log(f);
4 |
5 | for (let _ in f) {
6 | window[_] = f[_];
7 | }
8 |
--------------------------------------------------------------------------------
/asset/image/champion/ahri/Orb-of-Deception.ability.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/champion/ahri/Orb-of-Deception.ability.png
--------------------------------------------------------------------------------
/asset/image/champion/jinx/Switcheroo.Fishbones.ability.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/champion/jinx/Switcheroo.Fishbones.ability.png
--------------------------------------------------------------------------------
/asset/image/champion/jinx/Switcheroo.Pow-Pow.ability.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/champion/jinx/Switcheroo.Pow-Pow.ability.png
--------------------------------------------------------------------------------
/temp/_enums/DrawPathMode.js:
--------------------------------------------------------------------------------
1 | const DrawPathMode = {
2 | Disabled: 0,
3 | Line: 1,
4 | };
5 |
6 | Object.freeze(DrawPathMode);
7 | export default DrawPathMode;
8 |
--------------------------------------------------------------------------------
/asset/image/champion/jinx/Super-Mega-Death-Rocket.ability.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOL2D/LOL2D-Core/HEAD/asset/image/champion/jinx/Super-Mega-Death-Rocket.ability.png
--------------------------------------------------------------------------------
/temp/_enums/AttackType.js:
--------------------------------------------------------------------------------
1 | const AttackType = {
2 | RADIAL: 1,
3 | MELEE: 2,
4 | TARGETED: 3,
5 | };
6 |
7 | Object.freeze(AttackType);
8 | export default AttackType;
9 |
--------------------------------------------------------------------------------
/temp/_enums/InhibitorState.js:
--------------------------------------------------------------------------------
1 | const InhibitorState = {
2 | DEAD: 0x00,
3 | ALIVE: 0x01,
4 | };
5 |
6 | Object.freeze(InhibitorState);
7 | export default InhibitorState;
8 |
--------------------------------------------------------------------------------
/temp/enums/TeamID.js:
--------------------------------------------------------------------------------
1 | const TeamID = {
2 | TEAM_BLUE: 0x64,
3 | TEAM_PURPLE: 0xc8,
4 | TEAM_NEUTRAL: 0x12c,
5 | };
6 |
7 | Object.freeze(TeamID);
8 | export default TeamID;
9 |
--------------------------------------------------------------------------------
/test/LOL2D-chatGPT/src/utils.js:
--------------------------------------------------------------------------------
1 | export function disableRightClick(ele) {
2 | ele.addEventListener("contextmenu", (e) => {
3 | e.preventDefault();
4 | });
5 | }
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # LOL2D Core
2 |
3 | ## Live demo
4 |
5 | [Play now](https://lol2d.github.io/LOL2D-Core/)
6 |
7 | ## Trello
8 |
9 | [Link to Trello](https://trello.com/b/I7StGpWX/lol2d-core)
10 |
--------------------------------------------------------------------------------
/temp/_enums/DamageType.js:
--------------------------------------------------------------------------------
1 | const DamageType = {
2 | PHYSICAL: 0x0,
3 | MAGICAL: 0x1,
4 | TRUE: 0x2,
5 | MIXED: 0x3,
6 | };
7 |
8 | Object.freeze(DamageType);
9 | export default DamageType;
10 |
--------------------------------------------------------------------------------
/temp/_enums/SpellState.js:
--------------------------------------------------------------------------------
1 | const SpellState = {
2 | READY: 1,
3 | CASTING: 2,
4 | COOLDOWN: 3,
5 | CHANNELING: 4,
6 | };
7 |
8 | Object.freeze(SpellState);
9 | export default SpellState;
10 |
--------------------------------------------------------------------------------
/temp/_enums/Packets/Emotions.js:
--------------------------------------------------------------------------------
1 | const Emotions = {
2 | DANCE: 0,
3 | TAUNT: 1,
4 | LAUGH: 2,
5 | JOKE: 3,
6 | UNK: 4,
7 | };
8 |
9 | Object.freeze(Emotions);
10 | export default Emotions;
11 |
--------------------------------------------------------------------------------
/temp/_enums/Packets/Pings.js:
--------------------------------------------------------------------------------
1 | const Pings = {
2 | DEFAULT: 0,
3 | DANGER: 2,
4 | MISSING: 3,
5 | ON_MY_WAY: 4,
6 | ASSIST: 6,
7 | };
8 |
9 | Object.freeze(Pings);
10 | export default Pings;
11 |
--------------------------------------------------------------------------------
/temp/_enums/Packets/MoveType.js:
--------------------------------------------------------------------------------
1 | const MoveType = {
2 | EMOTE: 1,
3 | MOVE: 2,
4 | ATTACK: 3,
5 | ATTACKMOVE: 7,
6 | STOP: 10,
7 | };
8 |
9 | Object.freeze(MoveType);
10 | export default MoveType;
11 |
--------------------------------------------------------------------------------
/temp/_enums/MinionSpawnType.js:
--------------------------------------------------------------------------------
1 | const MinionSpawnType = {
2 | MELEE: 0x00,
3 | CASTER: 0x03,
4 | CANNON: 0x02,
5 | SUPER: 0x01,
6 | };
7 |
8 | Object.freeze(MinionSpawnType);
9 | export default MinionSpawnType;
10 |
--------------------------------------------------------------------------------
/temp/_enums/Packets/MasterMask.js:
--------------------------------------------------------------------------------
1 | const MasterMask = {
2 | ONE: 0x01,
3 | TWO: 0x02,
4 | THREE: 0x04,
5 | FOUR: 0x08,
6 | FIVE: 0x10,
7 | };
8 |
9 | Object.freeze(MasterMask);
10 | export default MasterMask;
11 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/component/core/MonoBehaviour.js:
--------------------------------------------------------------------------------
1 | import Behaviour from "./Behaviour.js";
2 |
3 | export default class MonoBehaviour extends Behaviour {
4 | constructor() {
5 | super();
6 | }
7 |
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/game/enums/SpellKeys.js:
--------------------------------------------------------------------------------
1 | const SpellKeys = {
2 | A: 65, // basic attack
3 | Q: 81,
4 | W: 87,
5 | E: 69,
6 | R: 82,
7 | D: 68,
8 | F: 70,
9 | };
10 |
11 | Object.freeze(SpellKeys);
12 | export default SpellKeys;
13 |
--------------------------------------------------------------------------------
/src/managers/InputManager.js:
--------------------------------------------------------------------------------
1 | import Game from "../game/Game";
2 |
3 | export default class InputManager {
4 | constructor(game) {
5 | /** @type Game */
6 | this.game = game;
7 | // this.queue = [];
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/temp/_enums/TurretType.js:
--------------------------------------------------------------------------------
1 | const TurretType = {
2 | OUTER_TURRET: 1,
3 | INNER_TURRET: 2,
4 | INHIBITOR_TURRET: 3,
5 | NEXUS_TURRET: 4,
6 | FOUNTAIN_TURRET: 5,
7 | };
8 |
9 | Object.freeze(TurretType);
10 | export default TurretType;
11 |
--------------------------------------------------------------------------------
/temp/_enums/Packets/SurrenderReason.js:
--------------------------------------------------------------------------------
1 | const SurrenderReason = {
2 | FAILED: 0,
3 | TOO_EARLY: 1,
4 | TOO_QUICKLY: 2,
5 | ALREADY_VOTED: 3,
6 | PASSED: 4,
7 | };
8 |
9 | Object.freeze(SurrenderReason);
10 | export default SurrenderReason;
11 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/component/core/Scene.js:
--------------------------------------------------------------------------------
1 | export default class Scene {
2 | constructor(name) {
3 | this.name = name;
4 | }
5 |
6 | init() {}
7 | update(dt) {}
8 | draw() {}
9 | onEnter() {}
10 | onExit() {}
11 | }
12 |
--------------------------------------------------------------------------------
/temp/_enums/Announces.js:
--------------------------------------------------------------------------------
1 | const Announces = {
2 | WELCOME_TO_SR: 0x77,
3 | THIRY_SECONDS_TO_MINIONS_SPAWN: 0x78,
4 | MINIONS_HAVE_SPAWNED: 0x7f,
5 | MINIONS_HAVE_SPAWNED2: 0x76,
6 | };
7 |
8 | Object.freeze(Announces);
9 | export default Announces;
10 |
--------------------------------------------------------------------------------
/temp/_enums/Packets/Channel.js:
--------------------------------------------------------------------------------
1 | const Channel = {
2 | HANDSHAKE: 0,
3 | C2S: 1,
4 | GAMEPLAY: 2,
5 | S2C: 3,
6 | LOW_PRIORITY: 4,
7 | COMMUNICATION: 5,
8 | LOADING_SCREEN: 7,
9 | };
10 |
11 | Object.freeze(Channel);
12 | export default Channel;
13 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/command/README.md:
--------------------------------------------------------------------------------
1 | # Command Pattern
2 |
3 | Command Pattern in Book [Link](http://gameprogrammingpatterns.com/command.html)
4 |
5 | Medium post [Link](https://medium.com/dev-genius/a-game-designers-thoughts-on-programming-patterns-command-pattern-4f6329f9b30d)
6 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/component/README.md:
--------------------------------------------------------------------------------
1 | # Command Pattern
2 |
3 | Command Pattern in Book [Link](http://gameprogrammingpatterns.com/command.html)
4 |
5 | Medium post [Link](https://medium.com/dev-genius/a-game-designers-thoughts-on-programming-patterns-command-pattern-4f6329f9b30d)
6 |
--------------------------------------------------------------------------------
/temp/_enums/MinionSpawnPosition.js:
--------------------------------------------------------------------------------
1 | const MinionSpawnPosition = {
2 | BLUE_TOP: 1,
3 | BLUE_BOT: 2,
4 | BLUE_MID: 3,
5 | RED_TOP: 4,
6 | RED_BOT: 5,
7 | RED_MID: 6,
8 | };
9 |
10 | Object.freeze(MinionSpawnPosition);
11 | export default MinionSpawnPosition;
12 |
--------------------------------------------------------------------------------
/temp/_enums/DamageResultType.js:
--------------------------------------------------------------------------------
1 | const DamageResultType = {
2 | INVULNERABLE: 0x0,
3 | INVULNERABLENOMESSAGE: 0x1,
4 | DODGE: 0x2,
5 | CRITICAL: 0x3,
6 | NORMAL: 0x4,
7 | MISS: 0x5,
8 | };
9 |
10 | Object.freeze(DamageResultType);
11 | export default DamageResultType;
12 |
--------------------------------------------------------------------------------
/temp/enums/EventType.js:
--------------------------------------------------------------------------------
1 | const EventType = {
2 | // p5js events
3 | KEY_PRESSED: 0,
4 | KEY_RELEASED: 1,
5 | MOUSE_PRESSED: 2,
6 | MOUSE_RELEASED: 3,
7 | MOUSE_WHEEL: 4,
8 | MOUSE_MOVED: 5
9 | }
10 |
11 | Object.freeze(EventType);
12 |
13 | export default EventType;
14 |
--------------------------------------------------------------------------------
/favicon/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | #da532c
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/test/LOL2D-chatGPT/style.css:
--------------------------------------------------------------------------------
1 | /* make webpage background nice dark */
2 | body {
3 | background-color: #333;
4 | }
5 |
6 | /* make canvas center - middle of page */
7 | canvas {
8 | position: absolute;
9 | top: 50%;
10 | left: 50%;
11 | transform: translate(-50%, -50%);
12 | }
--------------------------------------------------------------------------------
/src/game/enums/StatusFlags.js:
--------------------------------------------------------------------------------
1 | const StatusFlags = {
2 | CanCast: 1 << 1, // Có thể dùng chiêu
3 | CanMove: 1 << 2, // Có thể di chuyển
4 | CanAttack: 1 << 3, // Có thể đánh thường
5 | NoRender: 1 << 4, // Tàng hình
6 | };
7 |
8 | Object.freeze(StatusFlags);
9 | export default StatusFlags;
10 |
--------------------------------------------------------------------------------
/temp/_enums/LaneID.js:
--------------------------------------------------------------------------------
1 | const LaneID = {
2 | BOTTOM: 1,
3 | MIDDLE: 2,
4 | TOP: 3,
5 | ///
6 | /// Used for newly created turrets, Azir turrets, Nexus turrets, and Fountain turrets.
7 | ///
8 | NONE: 4,
9 | };
10 |
11 | Object.freeze(LaneID);
12 | export default LaneID;
13 |
--------------------------------------------------------------------------------
/playzone/buffer/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Buffer test
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/temp/_enums/GroundAttackMode.js:
--------------------------------------------------------------------------------
1 | const GroundAttackMode = {
2 | Disabled: 0x0,
3 | ReplaceMove: 0x1,
4 | ReplaceSelect: 0x2,
5 | ReplaceMoveAndSelect: 0x3,
6 | ReplaceAttackMove: 0x4,
7 | AutoTriggerAtCursor: 0x5,
8 | };
9 |
10 | Object.freeze(GroundAttackMode);
11 | export default GroundAttackMode;
12 |
--------------------------------------------------------------------------------
/src/utils/Helpers.js:
--------------------------------------------------------------------------------
1 | export function preventRightClick(canvas) {
2 | canvas.addEventListener(
3 | "contextmenu",
4 | function (evt) {
5 | evt.preventDefault();
6 | },
7 | false
8 | );
9 | }
10 |
11 | export function HasFlag(status, flag) {
12 | return status & flag;
13 | }
14 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/component/components/TestComponent.js:
--------------------------------------------------------------------------------
1 | import Component from "../core/Component.js";
2 |
3 | export default class TestComponent extends Component {
4 | constructor() {
5 | super();
6 | }
7 |
8 | doSomething(params) {
9 | console.log("TestComponent doSomething()", ...params);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/temp/_enums/UnitAnnounces.js:
--------------------------------------------------------------------------------
1 | const UnitAnnounces = {
2 | DEATH: 0x04,
3 | INHIBITOR_DESTROYED: 0x1f,
4 | INHIBITOR_ABOUT_TO_SPAWN: 0x20,
5 | INHIBITOR_SPAWNED: 0x21,
6 | TURRET_DESTROYED: 0x24,
7 | SUMMONER_DISCONNECTED: 0x47,
8 | SUMMONER_RECONNECTED: 0x48,
9 | };
10 |
11 | Object.freeze(UnitAnnounces);
12 | export default UnitAnnounces;
13 |
--------------------------------------------------------------------------------
/playzone/fixedupdate/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Fixed update test
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/playzone/sight/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Sight test
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/playzone/contour/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Contour test
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/playzone/gradient/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Gradient test
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/temp/_enums/CrowdControlType.js:
--------------------------------------------------------------------------------
1 | const CrowdControlType = {
2 | AIRBORNE: 1,
3 | BLIND: 2,
4 | DISARM: 3,
5 | GROUND: 4,
6 | INVULNERABLE: 5,
7 | NEARSIGHT: 6,
8 | ROOT: 7,
9 | SILENCE: 8,
10 | STASIS: 9,
11 | STUN: 10,
12 | SUPPRESSION: 11,
13 | SNARE: 12,
14 | };
15 |
16 | Object.freeze(CrowdControlType);
17 | export default CrowdControlType;
18 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/command/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Command Pattern
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/temp/_enums/MoveOrder.js:
--------------------------------------------------------------------------------
1 | const MoveOrder = {
2 | ATTACKMOVE: 1,
3 | ATTACKTERRAIN_ONCE: 2,
4 | ATTACKTERRAIN_SUSTAINED: 3,
5 | ATTACKTO: 4,
6 | HOLD: 5,
7 | MOVETO: 6,
8 | PETHARDATTACK: 7,
9 | PETHARDMOVE: 8,
10 | PETHARDRETURN: 9,
11 | PETHARDSTOP: 10,
12 | STOP: 11,
13 | TAUNT: 12,
14 | };
15 |
16 | Object.freeze(MoveOrder);
17 | export default MoveOrder;
18 |
--------------------------------------------------------------------------------
/test/LOL2D-chatGPT/src/buff.js:
--------------------------------------------------------------------------------
1 | export default class Buff {
2 | constructor(name, duration) {
3 | this.name = name;
4 | this.duration = duration;
5 | }
6 |
7 | apply(champion) {
8 | // Implement buff logic here
9 | champion.size += 20;
10 | }
11 |
12 | remove(champion) {
13 | // Implement buff removal logic here
14 | champion.size -= 20;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/observer/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Observer Pattern
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/playzone/sat/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Sat test
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/temp/_enums/PrimaryAbilityResourceType.js:
--------------------------------------------------------------------------------
1 | const PrimaryAbilityResourceType = {
2 | MANA: 0,
3 | ENERGY: 1,
4 | NONE: 2,
5 | SHIELD: 3,
6 | BATTLE_FURY: 4,
7 | DRAGON_FURY: 5,
8 | RAGE: 6,
9 | HEAT: 7,
10 | FEROCITY: 8,
11 | BLOOD_WELL: 9,
12 | WIND: 10,
13 | OTHER: 11,
14 | };
15 |
16 | Object.freeze(PrimaryAbilityResourceType);
17 | export default PrimaryAbilityResourceType;
18 |
--------------------------------------------------------------------------------
/playzone/animejs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | AnimeJS
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/playzone/quadtree/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Quadtree bug test
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/temp/gameCore/ObjectManager.js:
--------------------------------------------------------------------------------
1 | export default class ObjectManager {
2 | constructor(game) {
3 | this.game = game;
4 | this.champions = [];
5 | }
6 |
7 | update() {
8 | for (let champion of this.champions) {
9 | champion.update();
10 | }
11 | }
12 |
13 | draw() {
14 | for (let champion of this.champions) {
15 | champion.draw();
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/playzone/decomp-polygon/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Decomp polygon test
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/observer/main.js:
--------------------------------------------------------------------------------
1 | import EventEmitter from "./EventEmitter.js";
2 |
3 | let ee;
4 |
5 | window.setup = function () {
6 | createVector(500, 500);
7 |
8 | ee = new EventEmitter();
9 |
10 | ee.on("play", () => console.log("play"));
11 | ee.on("play", () => console.log("play 2"));
12 | };
13 |
14 | window.draw = function () {};
15 |
16 | window.keyPressed = function () {
17 | ee.emit("play");
18 | };
19 |
--------------------------------------------------------------------------------
/playzone/visibility/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Visibility test
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/temp/gameCore/maps/GameMap.js:
--------------------------------------------------------------------------------
1 | import GroundMap from "./GroundMap.js";
2 |
3 | export default class GameMap {
4 | constructor(game) {
5 | this.game = game;
6 | this.groundMap = new GroundMap();
7 | }
8 |
9 | update() {
10 | }
11 |
12 | draw() {
13 | let viewport = this.game.camera.getViewport();
14 |
15 | this.groundMap.drawEdge();
16 | this.groundMap.drawGrid(viewport);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/component/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Component Pattern
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/component/core/Camera.js:
--------------------------------------------------------------------------------
1 | // https://docs.unity3d.com/ScriptReference/Camera.html
2 | import Behaviour from "./Behaviour.js";
3 |
4 | export default class Camera extends Behaviour {
5 | // Returns all cameras in the Scene.
6 | static #allCameras = [];
7 | static main = null;
8 |
9 | static get allCameras() {
10 | return Camera.#allCameras;
11 | }
12 |
13 | constructor() {
14 | super();
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/temp/_enums/NavigationGridCellFlags.js:
--------------------------------------------------------------------------------
1 | const NavigationGridCellFlags = {
2 | HAS_GRASS: 0x1,
3 | NOT_PASSABLE: 0x2,
4 | BUSY: 0x4,
5 | TARGETTED: 0x8,
6 | MARKED: 0x10,
7 | PATHED_ON: 0x20,
8 | SEE_THROUGH: 0x40,
9 | OTHER_DIRECTION_END_TO_START: 0x80,
10 | HAS_GLOBAL_VISION: 0x100,
11 | // HAS_TRANSPARENT_TERRAIN : 0x42 // (SeeThrough | NotPassable)
12 | };
13 |
14 | Object.freeze(NavigationGridCellFlags);
15 | export default NavigationGridCellFlags;
16 |
--------------------------------------------------------------------------------
/src/game/stats/StatModifier.js:
--------------------------------------------------------------------------------
1 | export default class StatModifier {
2 | constructor(
3 | baseValue = 0,
4 | baseBonus = 0,
5 | percentBaseBonus = 0,
6 | flatBonus = 0,
7 | percentBonus = 0
8 | ) {
9 | this.baseValue = baseValue;
10 | this.baseBonus = baseBonus;
11 | this.percentBaseBonus = percentBaseBonus;
12 | this.flatBonus = flatBonus;
13 | this.percentBonus = percentBonus;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/component/core/Behaviour.js:
--------------------------------------------------------------------------------
1 | import Component from "./Component.js";
2 |
3 | // Behaviours are Components that can be enabled or disabled.
4 | // https://docs.unity3d.com/ScriptReference/Behaviour.html
5 |
6 | export default class Behaviour extends Component {
7 | constructor() {
8 | super();
9 |
10 | this.enabled = true;
11 | }
12 |
13 | get isActiveAndEnabled() {
14 | return this.enabled && this.gameObject.active;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/test/LOL2D-chatGPT/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Document
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/asset/sound/test_bosca.ceol:
--------------------------------------------------------------------------------
1 | 3,0,0,0,80,16,4,6,0,0,0,128,0,256,290,0,1,128,0,256,217,0,1,128,0,256,92,0,2,128,0,256,181,0,2,128,0,256,14,0,2,128,0,256,3,0,0,0,0,19,53,1,1,0,52,1,3,0,53,1,6,0,53,1,7,0,52,1,9,0,48,1,12,0,50,1,1,0,50,1,13,0,50,1,7,0,40,1,11,0,41,1,10,0,53,1,15,0,38,1,13,0,57,1,2,0,58,1,5,0,56,1,8,0,58,1,11,0,59,1,13,0,58,1,15,0,0,0,0,0,0,8,62,1,1,0,63,1,3,0,60,1,5,0,62,1,10,0,62,1,11,0,63,1,8,0,62,1,13,0,75,1,12,0,0,0,0,0,0,0,0,4,0,4,-1,1,-1,-1,-1,-1,-1,-1,-1,1,-1,-1,-1,-1,-1,-1,0,1,-1,-1,-1,-1,-1,-1,0,-1,-1,-1,-1,-1,-1,-1,
--------------------------------------------------------------------------------
/temp/_enums/ClassifyUnit.js:
--------------------------------------------------------------------------------
1 | const ClassifyUnit = {
2 | CHAMPION_ATTACKING_CHAMPION: 1,
3 | MINION_ATTACKING_CHAMPION: 2,
4 | MINION_ATTACKING_MINION: 3,
5 | TURRET_ATTACKING_MINION: 4,
6 | CHAMPION_ATTACKING_MINION: 5,
7 | MINION: 6,
8 | SUPER_OR_CANNON_MINION: 7,
9 | CASTER_MINION: 8,
10 | MELEE_MINION: 9,
11 | TURRET: 10,
12 | CHAMPION: 11,
13 | INHIBITOR: 12,
14 | NEXUS: 13,
15 | DEFAULT: 14,
16 | };
17 |
18 | Object.freeze(ClassifyUnit);
19 | export default ClassifyUnit;
20 |
--------------------------------------------------------------------------------
/favicon/site.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "",
3 | "short_name": "",
4 | "icons": [
5 | {
6 | "src": "favicon/android-chrome-192x192.png",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | },
10 | {
11 | "src": "favicon/android-chrome-512x512.png",
12 | "sizes": "512x512",
13 | "type": "image/png"
14 | }
15 | ],
16 | "theme_color": "#ffffff",
17 | "background_color": "#ffffff",
18 | "display": "standalone"
19 | }
20 |
--------------------------------------------------------------------------------
/temp/_enums/Packets/SummonerSpellIds.js:
--------------------------------------------------------------------------------
1 | const SummonerSpellIds = {
2 | REVIVE: 0x05c8b3a5,
3 | SMITE: 0x065e8695,
4 | EXHAUST: 0x08a8bae4,
5 | BARRIER: 0x0ccfb982,
6 | TELEPORT: 0x004f1364,
7 | GHOST: 0x064acc95,
8 | HEAL: 0x0364af1c,
9 | CLEANSE: 0x064d2094,
10 | CLARITY: 0x03657421,
11 | IGNITE: 0x06364f24,
12 | PROMOTE: 0x0410ff72,
13 | CLAIR: 0x09896765,
14 | FLASH: 0x06496ea8,
15 | TEST: 0x0103d94c,
16 | };
17 |
18 | Object.freeze(SummonerSpellIds);
19 | export default SummonerSpellIds;
20 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/component/core/Transform.js:
--------------------------------------------------------------------------------
1 | // https://docs.unity3d.com/ScriptReference/Transform.html
2 | import Component from "./Component.js";
3 | import Vector2 from "./Vector.js";
4 |
5 | export default class Transform extends Component {
6 | constructor(position, scale, rotation) {
7 | super();
8 |
9 | this.position = position || Vector2.zero;
10 | this.scale = scale || Vector2.zero;
11 | this.rotation = rotation || Vector2.zero;
12 | }
13 |
14 | translate(vec2) {
15 | this.position.add(vec2);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/README.md:
--------------------------------------------------------------------------------
1 | # Game Programming Patterns
2 |
3 | **Book** [Link](http://gameprogrammingpatterns.com/contents.html)
4 |
5 | - pattern trong Js [Link](https://www.dofactory.com/javascript/design-patterns) [Link2](https://addyosmani.com/resources/essentialjsdesignpatterns/book/)
6 |
7 | - demo max hay: [Link](https://ovenfresh.itch.io/design-with-patterns)
8 |
9 | - code hơi kỳ cục: [Link](http://vasir.net/blog/game-development/how-to-build-entity-component-system-in-javascript)
10 |
11 | - composite pattern? : [Link](https://x-team.com/blog/understanding-the-composite-pattern/)
--------------------------------------------------------------------------------
/playzone/hud/main.js:
--------------------------------------------------------------------------------
1 | function setup() {
2 | createCanvas(windowWidth, windowHeight)
3 | .position(0, 0)
4 | .parent("canvas-container");
5 |
6 | textSize(30);
7 | textAlign(CENTER, CENTER);
8 | fill("white");
9 | }
10 |
11 | function draw() {
12 | background(30);
13 |
14 | text(
15 | "Không dùng html để render HUD nữa, render bằng p5js luôn!!\nAi giỏi css html làm dùm thì xin cám ơn :)))",
16 | width * 0.5,
17 | height * 0.5
18 | );
19 | }
20 |
21 | function windowResized() {
22 | resizeCanvas(windowWidth, windowHeight, true);
23 | }
24 |
--------------------------------------------------------------------------------
/css/style.css:
--------------------------------------------------------------------------------
1 | /* @import url(//db.onlinewebfonts.com/c/12420e8c141ca7c3dff41de2d59df13e?family=BeaufortforLOL-Bold); */
2 |
3 | * {
4 | font-family: 'Courier New', Courier, monospace;
5 | outline-style: none;
6 | color: #eee;
7 | }
8 |
9 | html,
10 | body {
11 | height: 100%;
12 | }
13 |
14 | body {
15 | margin: 0;
16 | position: relative;
17 | background-color: #1E1E1E;
18 | overflow: hidden;
19 | }
20 |
21 | .center-page-container>div {
22 | position: absolute;
23 | top: 50%;
24 | left: 50%;
25 | transform: translate(-50%, -50%);
26 |
27 | display: none;
28 | }
--------------------------------------------------------------------------------
/test/LOL2D-chatGPT/src/spell.js:
--------------------------------------------------------------------------------
1 | import Buff from "./Buff.js";
2 |
3 | export default class Spell {
4 | constructor(name, cooldown, range, castTime, cost) {
5 | this.name = name;
6 | this.cooldown = cooldown;
7 | this.range = range;
8 | this.castTime = castTime;
9 | this.cost = cost;
10 | }
11 |
12 | cast(caster, target) {
13 | // Implement spell logic here
14 | let b = new Buff("Fireball", 1000);
15 | b.apply(target);
16 |
17 | setTimeout(() => {
18 | b.remove(target);
19 | }, b.duration);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/css/loading-scene.css:
--------------------------------------------------------------------------------
1 | /* loading scene */
2 | .loading {
3 | height: 40px;
4 | width: 40px;
5 | background: rgba(0, 0, 0, 0.4);
6 | border-radius: 50%;
7 | border-top: 2px solid #1D9AF2;
8 | border-right: 2px solid transparent;
9 | border-bottom: none;
10 | border-left: none;
11 | animation: spinner5 700ms linear infinite;
12 | }
13 |
14 | @keyframes spinner5 {
15 | to {
16 | transform: rotate(360deg);
17 | }
18 | }
19 |
20 | .loading-text {
21 | margin-top: 10px;
22 | text-align: center;
23 | }
24 |
25 | .error-text {
26 | margin-top: 10px;
27 | text-align: center;
28 | color: red;
29 | }
--------------------------------------------------------------------------------
/temp/gameScripts/champions/Ahri/Q.js:
--------------------------------------------------------------------------------
1 | export default class AhriQ {
2 | constructor() {}
3 |
4 | onActivate(owner) {
5 | console.log("activate");
6 | }
7 |
8 | onDeactivate(owner) {
9 | console.log("deactivate");
10 | }
11 |
12 | onStartCasting(owner, spell, target) {
13 | console.log("start casting");
14 | }
15 |
16 | onFinishCasting(owner, spell, target) {
17 | console.log("finish casting");
18 | }
19 |
20 | applyEffects(owner, target, spell, projectile) {
21 | console.log("apply effect");
22 | }
23 |
24 | onUpdate() {
25 | // console.log("update")
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/component/main.js:
--------------------------------------------------------------------------------
1 | import GameObject from "./core/GameObject.js";
2 | import Camera from "./core/Camera.js";
3 | import TestComponent from "./components/TestComponent.js";
4 |
5 | window.setup = function () {
6 | createCanvas(500, 500);
7 |
8 | let go = new GameObject();
9 | go.name = "abc";
10 | go.tag = "player";
11 | let c = go.addComponent(TestComponent);
12 | c.sendMessage("doSomething", 1, 2, 3, 4, 5, 6, 7);
13 |
14 | let mainCamera = new GameObject();
15 | mainCamera.tag = "MainCamera";
16 | mainCamera.addComponent(Camera);
17 | };
18 |
19 | window.draw = function () {
20 | background(30);
21 | };
22 |
--------------------------------------------------------------------------------
/temp/_enums/ActionState.js:
--------------------------------------------------------------------------------
1 | const ActionState = {
2 | CAN_ATTACK: 1 << 0,
3 | CAN_CAST: 1 << 1,
4 | CAN_MOVE: 1 << 2,
5 | CAN_NOT_MOVE: 1 << 3,
6 | STEALTHED: 1 << 4,
7 | REVEAL_SPECIFIC_UNIT: 1 << 5,
8 | TAUNTED: 1 << 6,
9 | FEARED: 1 << 7,
10 | IS_FLEEING: 1 << 8,
11 | CAN_NOT_ATTACK: 1 << 9,
12 | IS_ASLEEP: 1 << 10,
13 | IS_NEAR_SIGHTED: 1 << 11,
14 | IS_GHOSTED: 1 << 12,
15 |
16 | CHARMED: 1 << 15,
17 | NO_RENDER: 1 << 16,
18 | FORCE_RENDER_PARTICLES: 1 << 17,
19 |
20 | UNKNOWN: 1 << 23, // set to 1 by default, interferes with targetability
21 | };
22 |
23 | Object.freeze(ActionState);
24 |
25 | export default ActionState;
26 |
--------------------------------------------------------------------------------
/temp/gameCore/utils/Uuid.js:
--------------------------------------------------------------------------------
1 | // https://stackoverflow.com/a/2117523
2 | export function uuidv4_old() {
3 | return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
4 | /[xy]/g,
5 | function (c) {
6 | var r = (Math.random() * 16) | 0,
7 | v = c == "x" ? r : (r & 0x3) | 0x8;
8 | return v.toString(16);
9 | }
10 | );
11 | }
12 |
13 | export function uuidv4() {
14 | return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
15 | (
16 | c ^
17 | (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))
18 | ).toString(16)
19 | );
20 | }
21 |
22 | export default uuidv4;
23 |
--------------------------------------------------------------------------------
/temp/gameCore/gameObjects/stats/StatModifier.js:
--------------------------------------------------------------------------------
1 | const COMPARE_EPSILON = 0.0001;
2 |
3 | export default class StatModifier {
4 | constructor(baseBonus, percentBaseBonus, flatBonus, percentBonus) {
5 | this.baseBonus = baseBonus;
6 | this.percentBaseBonus = percentBaseBonus;
7 | this.flatBonus = flatBonus;
8 | this.percentBonus = percentBonus;
9 | }
10 |
11 | isStatModified() {
12 | return (
13 | Math.Abs(BaseBonus) > COMPARE_EPSILON ||
14 | Math.Abs(PercentBaseBonus) > COMPARE_EPSILON ||
15 | Math.Abs(FlatBonus) > COMPARE_EPSILON ||
16 | Math.Abs(PercentBonus) > COMPARE_EPSILON
17 | );
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/scenes/MenuScene.js:
--------------------------------------------------------------------------------
1 | import { Scene } from "../managers/SceneManager.js";
2 | import PreGameScene from "./PreGameScene.js";
3 |
4 | export default class MenuScene extends Scene {
5 | setup() {
6 | this.menuSceneDiv = document.querySelector("#menu-scene");
7 | this.playBtn = document.querySelector("#play-btn");
8 |
9 | this.playBtn.addEventListener("click", () => {
10 | this.sceneManager.showScene(PreGameScene);
11 | });
12 | }
13 | enter() {
14 | // reset dom
15 | this.menuSceneDiv.style.display = "block";
16 | this.sceneManager.showScene(PreGameScene);
17 | }
18 |
19 | exit() {
20 | // hide dom
21 | this.menuSceneDiv.style.display = "none";
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/component/core/Vector.js:
--------------------------------------------------------------------------------
1 | // https://docs.unity3d.com/ScriptReference/Vector3.html
2 |
3 | export default class Vector2 {
4 | static get zero() {
5 | return new Vector2(0, 0);
6 | }
7 |
8 | constructor(x, y) {
9 | this.x = x || 0;
10 | this.y = y || 0;
11 | }
12 |
13 | mag() {
14 | return Math.sqrt(this.sqrMag());
15 | }
16 |
17 | sqrMag() {
18 | return this.x * this.x + this.y * this.y;
19 | }
20 |
21 | set(x, y) {
22 | this.x = x;
23 | this.y = y;
24 | }
25 |
26 | add(vec2) {
27 | this.x += vec2.x;
28 | this.y += vec2.y;
29 | }
30 |
31 | equal(vec2) {
32 | return this.x === vec2.x && this.y === vec2.y;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/playzone/buffer/main.js:
--------------------------------------------------------------------------------
1 | var buffer;
2 | var circles = 10000;
3 |
4 | function setup() {
5 | createCanvas(400, 400);
6 | buffer = createGraphics(width, height);
7 | makeCircleBuffer();
8 | }
9 |
10 | function draw() {
11 | if (mouseIsPressed) {
12 | image(buffer, 0, 0);
13 | } else {
14 | drawCircles();
15 | }
16 |
17 | textSize(36);
18 | text(frameRate(), 50, height * 0.5);
19 | }
20 |
21 | function drawCircles() {
22 | randomSeed(0);
23 | for (var i = 0; i < circles; i++) {
24 | ellipse(random(width), random(height), 20, 20);
25 | }
26 | }
27 |
28 | function makeCircleBuffer() {
29 | randomSeed(1);
30 | for (var i = 0; i < circles; i++) {
31 | buffer.ellipse(random(width), random(height), 20, 20);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/playzone/animejs/main.js:
--------------------------------------------------------------------------------
1 | // https://animejs.com/documentation/
2 |
3 | var player = {
4 | x: 100,
5 | y: 100,
6 | r: 20,
7 | };
8 |
9 | let animation;
10 |
11 | function setup() {
12 | createCanvas(500, 500);
13 |
14 | fill(255);
15 | noStroke();
16 |
17 | animation = anime({
18 | targets: player,
19 | x: "*=3",
20 | y: "*=2",
21 | // round: 2,
22 | easing: "easeOutSine",
23 | direction: "alternate",
24 | loop: true,
25 | update: function () {
26 | text(JSON.stringify(player), 10, 10);
27 | },
28 | autoplay: false,
29 | });
30 | }
31 |
32 | function draw() {
33 | background(30);
34 |
35 | animation.tick(millis());
36 |
37 | circle(player.x, player.y, player.r * 2);
38 | }
39 |
--------------------------------------------------------------------------------
/temp/_enums/BuffType.js:
--------------------------------------------------------------------------------
1 | const BuffType = {
2 | INTERNAL: 1,
3 | AURA: 2,
4 | COMBAT_ENCHANCER: 3,
5 | COMBAT_DEHANCER: 4,
6 | SPELL_SHIELD: 5,
7 | STUN: 6,
8 | INVISIBILITY: 7,
9 | SILENCE: 8,
10 | TAUNT: 9,
11 | POLYMORPH: 10,
12 | SLOW: 11,
13 | SNARE: 12,
14 | DAMAGE: 13,
15 | HEAL: 14,
16 | HASTE: 15,
17 | SPELL_IMMUNITY: 16,
18 | PHYSICAL_IMMUNITY: 17,
19 | INVULNERABILITY: 18,
20 | SLEEP: 19,
21 | NEAR_SIGHT: 20,
22 | FRENZY: 21,
23 | FEAR: 22,
24 | CHARM: 23,
25 | POISON: 24,
26 | SUPPRESSION: 25,
27 | BLIND: 26,
28 | COUNTER: 27,
29 | SHRED: 28,
30 | FLEE: 29,
31 | KNOCKUP: 30,
32 | KNOCKBACK: 31,
33 | DISARM: 32,
34 | };
35 |
36 | Object.freeze(BuffType);
37 | export default BuffType;
38 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/component/scenes/TestScene.js:
--------------------------------------------------------------------------------
1 | import Scene from "../core/Scene.js";
2 |
3 | export default class TestScene extends Scene {
4 | constructor(name) {
5 | super(name);
6 | }
7 |
8 | /**
9 | * @override
10 | */
11 | init() {
12 | console.log("Init ", this);
13 | }
14 |
15 | /**
16 | * @override
17 | */
18 | update(dt) {}
19 |
20 | /**
21 | * @override
22 | */
23 | draw() {
24 | fill(255);
25 | circle(mouseX, mouseY, 30);
26 | }
27 |
28 | /**
29 | * @override
30 | */
31 | onEnter() {
32 | console.log("Đã vào scene " + this.name);
33 | }
34 |
35 | /**
36 | * @override
37 | */
38 | onExit() {
39 | console.log("Đã thoát scene " + this.name);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Sketch.js:
--------------------------------------------------------------------------------
1 | import SceneManager from "./managers/SceneManager.js";
2 | import LoadingScene from "./scenes/LoadingScene.js";
3 |
4 | function setup() {
5 | createCanvas(windowWidth, windowHeight).parent("#game-scene");
6 |
7 | // global p5js setting
8 | strokeJoin(ROUND);
9 | strokeCap(ROUND);
10 | imageMode(CENTER);
11 | rectMode(CENTER);
12 | textAlign(CENTER, CENTER);
13 | textStyle(BOLD);
14 | textFont("monospace");
15 | textSize(17);
16 |
17 | // scene manager
18 | let mgr = new SceneManager();
19 | mgr.wire();
20 |
21 | // holding global data
22 | mgr.gameData = {};
23 |
24 | // open loading scene
25 | mgr.showScene(LoadingScene);
26 | }
27 |
28 | function windowResized() {
29 | resizeCanvas(windowWidth, windowHeight, true);
30 | }
31 |
32 | export default { setup, windowResized };
33 |
--------------------------------------------------------------------------------
/temp/_enums/BuffAddType.js:
--------------------------------------------------------------------------------
1 | /// Determines how a buff should be treated when added.
2 |
3 | const BuffAddType = {
4 | /// Replaces any existing buffs of the same name.
5 | REPLACE_EXISTING: 1,
6 |
7 | /// Restarts the timer on any buffs of the same name already applied to the buff's target.
8 | RENEW_EXISTING: 2,
9 |
10 | /// Adds a stack to any buffs of the same name already applied and restarts all other stacks' timers.
11 | /// Functionally treated as a single buff with a single timer and stack count.
12 | STACKS_AND_RENEWS: 3,
13 |
14 | /// Adds a completely new buff instance to the buff target regardless of any other buffs of the same name applied.
15 | /// Inherits stack count of the oldest buff of the same name.
16 | STACKS_AND_OVERLAPS: 4,
17 | };
18 |
19 | Object.freeze(BuffAddType);
20 | export default BuffAddType;
21 |
--------------------------------------------------------------------------------
/playzone/hud/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | HUD test
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | avatar
21 |
22 |
23 |
24 |
25 | ability
26 |
27 |
28 |
29 |
30 | item
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/temp/_enums/DamageSource.js:
--------------------------------------------------------------------------------
1 | const DamageSource = {
2 | /// Unmitigated.
3 | RAW: 1,
4 |
5 | /// Executes, pure.
6 | INTERNALRAW: 2,
7 |
8 | /// Buff spell dots.
9 | PERIODIC: 3,
10 |
11 | /// Causes Proc (spell specific or attack based) events to fire, pre initial damage.
12 | PROC: 4,
13 |
14 | /// On proc.
15 | REACTIVE: 5,
16 |
17 | /// Unknown, self-explanatory?
18 | ONDEATH: 6,
19 |
20 | /// Single instance spell damage.
21 | SPELL: 7,
22 |
23 | /// Attack based spells (proc onhit effects).
24 | ATTACK: 8,
25 |
26 | /// Buff Summoner spell damage (single and multi instance)
27 | DEFAULT: 9,
28 |
29 | /// Any area based spells.
30 | SPELLAOE: 10,
31 |
32 | /// Passive, on update or timed repeat.
33 | SPELLPERSIST: 11,
34 |
35 | /// Unknown, self-explanatory?
36 | PET: 12,
37 | };
38 |
--------------------------------------------------------------------------------
/temp/_enums/FloatTextType.js:
--------------------------------------------------------------------------------
1 | const FloatTextType = {
2 | Invulnerable: 0x0,
3 | Special: 0x1,
4 | Heal: 0x2,
5 | ManaHeal: 0x3,
6 | ManaDamage: 0x4,
7 | Dodge: 0x5,
8 | PhysicalDamageCritical: 0x6,
9 | MagicalDamageCritical: 0x7,
10 | TrueDamageCritical: 0x8,
11 | Experience: 0x9,
12 | Gold: 0xa,
13 | Level: 0xb,
14 | Disable: 0xc,
15 | QuestReceived: 0xd,
16 | QuestComplete: 0xe,
17 | Score: 0xf,
18 | PhysicalDamage: 0x10,
19 | MagicalDamage: 0x11,
20 | TrueDamage: 0x12,
21 | EnemyPhysicalDamage: 0x13,
22 | EnemyMagicalDamage: 0x14,
23 | EnemyTrueDamage: 0x15,
24 | EnemyPhysicalDamageCritical: 0x16,
25 | EnemyMagicalDamageCritical: 0x17,
26 | EnemyTrueDamageCritical: 0x18,
27 | Countdown: 0x19,
28 | OnMyWay: 0x1a,
29 | Absorbed: 0x1b,
30 | Debug: 0x1c,
31 | };
32 |
33 | Object.freeze(FloatTextType);
34 | export default FloatTextType;
35 |
--------------------------------------------------------------------------------
/playzone/hud/style.css:
--------------------------------------------------------------------------------
1 | html,
2 | body {
3 | padding: 0;
4 | margin: 0;
5 | height: 100%;
6 | }
7 |
8 | /* #hud-container {
9 | position: relative;
10 | height: 100%;
11 | } */
12 |
13 | #hud-container {
14 | position: absolute;
15 | bottom: 0;
16 | width: 100%;
17 | color: white;
18 |
19 | display: flex;
20 | justify-content: center;
21 | align-items: center
22 | }
23 |
24 | #hud-avatar-container {
25 | width: 150px;
26 | height: 150px;
27 |
28 | background-image: url("./asset/avatar.png");
29 | background-size: cover;
30 | }
31 |
32 | #hud-ability-container {
33 | width: 410px;
34 | height: 150px;
35 |
36 | background-position: -60px 0;
37 | background-image: url("./asset/ability.png");
38 | background-size: cover;
39 | }
40 |
41 | #hud-item-container {
42 | width: 200px;
43 | height: 150px;
44 |
45 | background-image: url("./asset/item.png");
46 | background-size: cover;
47 | }
--------------------------------------------------------------------------------
/playzone/programming-patterns/component/core/Component.js:
--------------------------------------------------------------------------------
1 | // https://docs.unity3d.com/ScriptReference/Component.html
2 |
3 | import BaseObject from "./BaseObject.js";
4 |
5 | export default class Component extends BaseObject {
6 | constructor() {
7 | super();
8 |
9 | this.gameObject = null;
10 | }
11 |
12 | get tag() {
13 | return this.gameObject.tag;
14 | }
15 | set tag(value) {
16 | this.gameObject.tag = value;
17 | }
18 |
19 | get transform() {
20 | return this.gameObject.transform;
21 | }
22 |
23 | attachTo(gameObject) {
24 | this.gameObject = gameObject;
25 | }
26 |
27 | getComponent(type) {
28 | return this.gameObject.getComponent(type);
29 | }
30 |
31 | getComponents(type) {
32 | return this.gameObject.getComponents(type);
33 | }
34 |
35 | sendMessage(methodName, ...params) {
36 | this.gameObject.sendMessage(methodName, ...params);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/game/stats/StatsModifier.js:
--------------------------------------------------------------------------------
1 | import StatModifier from "./StatModifier.js";
2 |
3 | export default class StatsModifier {
4 | constructor() {
5 | this.healthPoints = new StatModifier(); // máu tối đa
6 | this.manaPoints = new StatModifier(); // mana tối đa
7 | this.healthRegen = new StatModifier(); // hồi máu
8 | this.manaRegen = new StatModifier(); // hồi năng lượng
9 | this.moveSpeed = new StatModifier(); // tốc chạy
10 | this.attackSpeed = new StatModifier(); // tốc đánh
11 | this.attackDamage = new StatModifier(); // sát thương vật lý
12 | this.magicDamage = new StatModifier(); // sát thương phép
13 | this.attackRange = new StatModifier(); // tầm đánh
14 | this.attackSpeedMult = new StatModifier(); // % tốc đánh cộng thêm
15 | this.cooldownReduction = new StatModifier(); // giảm thời gian hồi chiêu
16 | this.lifeSteal = new StatModifier(); // hút máu
17 | this.size = new StatModifier(); // kích thước
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/observer/Subject.js:
--------------------------------------------------------------------------------
1 | // https://webdevstudios.com/2019/02/19/observable-pattern-in-javascript/
2 |
3 | class Subject {
4 | constructor() {
5 | this.observers = [];
6 | }
7 |
8 | // Add an observer to this.observers.
9 | addObserver(observer) {
10 | this.observers.push(observer);
11 | }
12 |
13 | // Remove an observer from this.observers.
14 | removeObserver(observer) {
15 | const removeIndex = this.observers.findIndex((obs) => {
16 | return observer === obs;
17 | });
18 |
19 | if (removeIndex !== -1) {
20 | this.observers = this.observers.slice(removeIndex, 1);
21 | }
22 | }
23 |
24 | // Loops over this.observers and calls the update method on each observer.
25 | // The state object will call this method everytime it is updated.
26 | notify(data) {
27 | if (this.observers.length > 0) {
28 | this.observers.forEach((observer) => observer.update(data));
29 | }
30 | }
31 | }
32 |
33 | export default Subject;
34 |
--------------------------------------------------------------------------------
/src/game/stats/Stat.js:
--------------------------------------------------------------------------------
1 | import StatModifier from "./StatModifier.js";
2 |
3 | export default class Stat extends StatModifier {
4 | total() {
5 | return (
6 | ((this.baseValue + this.baseBonus) * (1 + this.percentBaseBonus) +
7 | this.flatBonus) *
8 | (1 + this.percentBonus)
9 | );
10 | }
11 |
12 | applyModifier(statModifier = new StatModifier()) {
13 | this.baseValue += statModifier.baseValue;
14 | this.baseBonus += statModifier.baseBonus;
15 | this.percentBaseBonus += statModifier.percentBaseBonus;
16 | this.flatBonus += statModifier.flatBonus;
17 | this.percentBonus += statModifier.percentBonus;
18 | }
19 |
20 | removeModifier(statModifier = new StatModifier()) {
21 | this.baseValue -= statModifier.baseValue;
22 | this.baseBonus -= statModifier.baseBonus;
23 | this.percentBaseBonus -= statModifier.percentBaseBonus;
24 | this.flatBonus -= statModifier.flatBonus;
25 | this.percentBonus -= statModifier.percentBonus;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/css/hextech-css/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Lucas Fernandes
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.
22 |
--------------------------------------------------------------------------------
/temp/gameCore/gameObjects/stats/ChampionStats.js:
--------------------------------------------------------------------------------
1 | export default class ChampionStats {
2 | teamId;
3 |
4 | assists;
5 | kills;
6 | deaths;
7 | unrealKills;
8 | doubleKills;
9 | tripleKills;
10 | quadraKills;
11 | pentaKills;
12 |
13 | currentKillingSpree;
14 | largestKillingSpree;
15 |
16 | goldEarned;
17 | goldSpent;
18 |
19 | largestCriticalStrike;
20 | largestMultiKill;
21 | longestTimeSpentLiving;
22 |
23 | magicDamageDealt;
24 | magicDamageDealtToChampions;
25 | magicDamageTaken;
26 |
27 | minionsKilled;
28 | neutralMinionsKilled;
29 | neutralMinionsKilledInEnemyJungle;
30 | neutralMinionsKilledInTeamJungle;
31 |
32 | physicalDamageDealt;
33 | physicalDamageDealtToChampions;
34 | physicalDamageTaken;
35 |
36 | totalDamageDealt;
37 | totalDamageDealtToChampions;
38 | totalDamageTaken;
39 | totalHeal;
40 | totalTimeCrowdControlDealt;
41 | totalTimeSpentDead;
42 | totalUnitsHealed;
43 |
44 | trueDamageDealt;
45 | trueDamageDealtToChampions;
46 | trueDamageTaken;
47 |
48 | turretsKilled;
49 | barracksKilled;
50 |
51 | wardsKilled;
52 | wardsPlaced;
53 | }
54 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/observer/EventEmitter.js:
--------------------------------------------------------------------------------
1 | // https://gist.github.com/mudge/5830382#gistcomment-2623252
2 | export default class EventEmitter {
3 | constructor() {
4 | this.events = {};
5 | }
6 |
7 | on(event, listener) {
8 | if (typeof this.events[event] !== "object") {
9 | this.events[event] = [];
10 | }
11 | this.events[event].push(listener);
12 | return () => this.removeListener(event, listener);
13 | }
14 |
15 | removeListener(event, listener) {
16 | if (typeof this.events[event] === "object") {
17 | const idx = this.events[event].indexOf(listener);
18 | if (idx > -1) {
19 | this.events[event].splice(idx, 1);
20 | }
21 | }
22 | }
23 |
24 | emit(event, ...args) {
25 | if (typeof this.events[event] === "object") {
26 | this.events[event].forEach((listener) =>
27 | listener.apply(this, args)
28 | );
29 | }
30 | }
31 |
32 | once(event, listener) {
33 | const remove = this.on(event, (...args) => {
34 | remove();
35 | listener.apply(this, args);
36 | });
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/temp/_enums/SpellFlags.js:
--------------------------------------------------------------------------------
1 | const SpellFlags = {
2 | AutoCast: 0x2,
3 | InstantCast: 0x4,
4 | PersistThroughDeath: 0x8,
5 | NonDispellable: 0x10,
6 | NoClick: 0x20,
7 | AffectImportantBotTargets: 0x40,
8 | AllowWhileTaunted: 0x80,
9 | NotAffectZombie: 0x100,
10 | AffectUntargetable: 0x200,
11 | AffectEnemies: 0x400,
12 | AffectFriends: 0x800,
13 | AffectNeutral: 0x4000,
14 | AffectAllSides: 0x4c00,
15 | AffectBuildings: 0x1000,
16 | AffectMinions: 0x8000,
17 | AffectHeroes: 0x10000,
18 | AffectTurrets: 0x20000,
19 | AffectAllUnitTypes: 0x38000,
20 | NotAffectSelf: 0x2000,
21 | AlwaysSelf: 0x40000,
22 | AffectDead: 0x80000,
23 | AffectNotPet: 0x100000,
24 | AffectBarracksOnly: 0x200000,
25 | IgnoreVisibilityCheck: 0x400000,
26 | NonTargetableAlly: 0x800000,
27 | NonTargetableEnemy: 0x1000000,
28 | TargetableToAll: 0x2000000,
29 | NonTargetableAll: 0x1800000,
30 | AffectWards: 0x4000000,
31 | AffectUseable: 0x8000000,
32 | IgnoreAllyMinion: 0x10000000,
33 | IgnoreEnemyMinion: 0x20000000,
34 | IgnoreLaneMinion: 0x40000000,
35 | IgnoreClones: 0x80000000,
36 | };
37 |
38 | Object.freeze(SpellFlags);
39 | export default SpellFlags;
40 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/component/core/BaseObject.js:
--------------------------------------------------------------------------------
1 | // https://docs.unity3d.com/ScriptReference/Object.html
2 |
3 | export default class BaseObject {
4 | static _objects = [];
5 | static _idGenerator = idGenerator();
6 |
7 | static findObjectOfType(type) {
8 | return this._objects.find((o) => o instanceof type) || null;
9 | }
10 |
11 | static findObjectsOfType(type) {
12 | return this._objects.filter((o) => o instanceof type) || [];
13 | }
14 |
15 | static instantiate(obj) {
16 | throw new Error("BaseObject.instantiate() not supported yet!");
17 | }
18 |
19 | static destroy(obj) {
20 | BaseObject._objects = BaseObject._objects.filter((o) => o !== obj);
21 | }
22 |
23 | constructor() {
24 | this.name = "";
25 | this.id = BaseObject._idGenerator.next().value;
26 |
27 | BaseObject._objects.push(this);
28 | }
29 | }
30 |
31 | function* idGenerator(start = 0) {
32 | let index = start;
33 | while (true) yield "" + index++;
34 | }
35 |
36 | function uuidv4() {
37 | // https://stackoverflow.com/a/2117523/11898496
38 | return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
39 | (
40 | c ^
41 | (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))
42 | ).toString(16)
43 | );
44 | }
45 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/component/core/SceneManager.js:
--------------------------------------------------------------------------------
1 | export default class SceneManager {
2 | static #scenes = [];
3 | static #activeScene = null;
4 |
5 | constructor() {}
6 |
7 | static update(dt) {
8 | if (this.#activeScene) this.#activeScene.update(dt);
9 | }
10 |
11 | static draw() {
12 | if (this.#activeScene) this.#activeScene.draw();
13 | }
14 |
15 | static addScene(scene) {
16 | try {
17 | scene.init();
18 | this.#activeScene = scene;
19 | this.#scenes.push(scene);
20 | return true;
21 | } catch {
22 | return false;
23 | }
24 | }
25 |
26 | static setActiveScene(scene) {
27 | if (!scene) return;
28 |
29 | if (this.#scenes.indexOf(scene) < 0) {
30 | this.#scenes.push(scene);
31 | }
32 |
33 | if (this.#activeScene) {
34 | this.#activeScene.onExit();
35 | }
36 |
37 | this.#activeScene = scene;
38 | this.#activeScene.onEnter();
39 | }
40 |
41 | static getSceneByName(name) {
42 | let scene = this.#scenes.find((s) => s.name === name);
43 | if (scene) {
44 | return scene;
45 | }
46 | return null;
47 | }
48 |
49 | static getActiveScene() {
50 | return this.#activeScene;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/temp/gameCore/Game.js:
--------------------------------------------------------------------------------
1 | import ObjectManager from "./ObjectManager.js";
2 | import Camera from "./maps/Camera.js";
3 | import GameMap from "./maps/GameMap.js";
4 |
5 | const fps = 60; // fixed update fps
6 |
7 | export default class Game {
8 | constructor() {}
9 |
10 | enter() {
11 | this.accumulator = 0;
12 |
13 | this.camera = new Camera();
14 | this.gameMap = new GameMap(this);
15 | this.objectManager = new ObjectManager(this);
16 | }
17 |
18 | exit() {}
19 |
20 | gameLoop() {
21 | // https://medium.com/@tglaiel/how-to-make-your-game-run-at-60fps-24c61210fe75
22 | this.accumulator += Math.min(deltaTime, 250);
23 |
24 | while (this.accumulator > 1000 / (fps + 1)) {
25 | this.fixedUpdate();
26 | this.accumulator -= 1000 / (fps - 1);
27 |
28 | if (this.accumulator < 1000 / (fps - 1) - 1000 / fps)
29 | this.accumulator = 0;
30 | }
31 |
32 | this.update();
33 | this.draw();
34 | }
35 |
36 | fixedUpdate() {}
37 |
38 | update() {
39 | this.objectManager.update();
40 | this.camera.update();
41 | }
42 |
43 | draw() {
44 | background("#1E1E1E");
45 |
46 | this.camera.beginState();
47 | this.gameMap.draw();
48 | this.objectManager.draw();
49 | this.camera.endState();
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/playzone/contour/main.js:
--------------------------------------------------------------------------------
1 | let cd = 1;
2 | let cooldown = 3;
3 |
4 | function setup() {
5 | createCanvas(400, 300);
6 | textSize(16);
7 | }
8 |
9 | function draw() {
10 | background(255);
11 |
12 | let b = {
13 | x: width * 0.5 - 50,
14 | y: height * 0.5 - 50,
15 | w: 100,
16 | h: 100,
17 | };
18 |
19 | if (cd > 0) cd -= 1 / 60;
20 | else cd = cooldown;
21 |
22 | // cooldown
23 | let h = ~~map(cd, cooldown, 0, b.h * 0.5, 0);
24 | fill("black");
25 | text(h, 10, 20);
26 |
27 | stroke("white");
28 | fill("#222d");
29 |
30 | let out = [
31 | [b.x, b.y],
32 | [b.x + b.w, b.y],
33 | [b.x + b.w, b.y + b.h],
34 | [b.x, b.y + b.h],
35 | ];
36 |
37 | let ins = [
38 | [b.x + h, b.y + b.h - h],
39 | [b.x + b.w - h, b.y + b.h - h],
40 | [b.x + b.w - h, b.y + h],
41 | [b.x + h, b.y + h],
42 | ];
43 |
44 | beginShape();
45 | for (let p of out) {
46 | vertex(p[0], p[1]);
47 | }
48 |
49 | beginContour();
50 | for (let p of ins) {
51 | vertex(p[0], p[1]);
52 | }
53 | endContour();
54 |
55 | endShape(CLOSE);
56 |
57 | fill("red");
58 | for (let p of out) {
59 | circle(p[0], p[1], 10);
60 | }
61 |
62 | fill("blue");
63 | for (let p of ins) {
64 | circle(p[0], p[1], 10);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/scenes/GameScene.js:
--------------------------------------------------------------------------------
1 | import StatsJs from "../../lib/stats.js";
2 | import Game from "../game/Game.js";
3 | import { emit } from "../managers/EventManager.js";
4 | import { Scene } from "../managers/SceneManager.js";
5 | import { preventRightClick } from "../utils/Helpers.js";
6 |
7 | export default class GameScene extends Scene {
8 | setup() {
9 | this.gameSceneDiv = document.querySelector("#game-scene");
10 | preventRightClick(document.querySelector("#game-scene canvas"));
11 |
12 | // stats show fps
13 | // this.statsJs = new StatsJs();
14 | // this.statsJs.showPanel(0);
15 | // document.body.appendChild(this.statsJs.dom);
16 | }
17 |
18 | enter() {
19 | // reset dom
20 | this.gameSceneDiv.style.display = "block";
21 | // this.statsJs.dom.style.display = "block";
22 |
23 | this.game = new Game();
24 | }
25 |
26 | draw() {
27 | // this.statsJs.begin();
28 | this.game.gameLoop(deltaTime);
29 | // this.statsJs.end();
30 | }
31 |
32 | exit() {
33 | this.gameSceneDiv.style.display = "none";
34 | // this.statsJs.dom.style.display = "none";
35 | }
36 |
37 | mousePressed() {
38 | this.game.onMousePressed();
39 | }
40 |
41 | keyPressed() {
42 | this.game.onKeyPressed();
43 | }
44 |
45 | mouseWheel(e) {
46 | this.game.onMouseWheel(e);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/test/LOL2D-chatGPT/src/champion.js:
--------------------------------------------------------------------------------
1 | export default class Champion {
2 | constructor(x, y, spells = []) {
3 | this.destination = createVector(x, y);
4 | this.spells = spells;
5 |
6 | this.position = createVector(x, y);
7 | this.color = 150;
8 | this.speed = 3;
9 | this.size = 40;
10 | }
11 |
12 | run() {
13 | this.update();
14 | this.draw();
15 | }
16 |
17 | update() {
18 | if (
19 | this.position.x !== this.destination.x ||
20 | this.position.y !== this.destination.y
21 | ) {
22 | let distance = p5.Vector.dist(this.position, this.destination);
23 | if (distance <= this.speed) {
24 | this.position.set(this.destination);
25 | } else {
26 | let direction = p5.Vector.sub(this.destination, this.position);
27 | direction.setMag(this.speed);
28 | this.position.add(direction);
29 | }
30 | }
31 | }
32 |
33 | draw() {
34 | fill(this.color);
35 | circle(this.position.x, this.position.y, this.size);
36 | }
37 |
38 | setDestination(x, y) {
39 | this.destination.set(x, y);
40 | }
41 |
42 | castSpell(spellIndex) {
43 | if (this.spells[spellIndex]) {
44 | this.spells[spellIndex].cast(this.position.x, this.position.y);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/temp/gameCore/gameObjects/stats/Stat.js:
--------------------------------------------------------------------------------
1 | export default class Stat {
2 | constructor(
3 | baseValue = 0,
4 | baseBonus = 0,
5 | percentBaseBonus = 0,
6 | flatBonus = 0,
7 | percentBonus = 0
8 | ) {
9 | this.modified = false;
10 | this.baseValue = baseValue;
11 | this.baseBonus = baseBonus;
12 | this.flatBonus = flatBonus;
13 | this.percentBonus = percentBonus;
14 | this.precentBaseBonus = percentBaseBonus;
15 | }
16 |
17 | total() {
18 | return (
19 | ((this.baseValue + this.baseBonus) * (1 + this.percentBaseBonus) +
20 | this.flatBonus) *
21 | (1 + this.percentBonus)
22 | );
23 | }
24 |
25 | applyStatModifier(statModifier) {
26 | if (!statModifier.isStatModified) {
27 | return false;
28 | }
29 | this.baseBonus += statModifier.baseBonus;
30 | this.percentBaseBonus += statModifier.percentBaseBonus;
31 | this.flatBonus += statModifier.flatBonus;
32 | this.percentBonus += statModifier.percentBonus;
33 |
34 | return true;
35 | }
36 |
37 | removeStatModifier(statModifier) {
38 | if (!statModifier.isStatModified) {
39 | return false;
40 | }
41 | this.baseBonus -= statModifier.baseBonus;
42 | this.percentBaseBonus -= statModifier.percentBaseBonus;
43 | this.flatBonus -= statModifier.flatBonus;
44 | this.percentBonus -= statModifier.percentBonus;
45 |
46 | return true;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/playzone/gradient/main.js:
--------------------------------------------------------------------------------
1 | // tip: https://www.w3schools.com/graphics/canvas_gradients.asp
2 | // live demo: https://editor.p5js.org/HoangTran0410/sketches/iMYZsZR1f
3 |
4 | let grd;
5 | let colorStops;
6 |
7 | function setup() {
8 | createCanvas(400, 400);
9 |
10 | colorStops = [
11 | { stop: 0, color: "#4AECF211" },
12 | //{stop: 0.5, color: "#1119"},
13 | { stop: 1, color: "#4AECF233" },
14 | ];
15 | }
16 |
17 | function draw() {
18 | background(30);
19 |
20 | // things
21 | circle(150, 100, 100)
22 |
23 | // NOTE, do not use noFill before create Gradient
24 | //noFill();
25 |
26 | //linearGradient();
27 | stroke("#4AECF2ee");
28 | strokeWeight(3);
29 |
30 | createLinearGradient(50, 50, 100, 50, colorStops);
31 | rect(50, 50, 100, 50);
32 |
33 | createRadialGradient(mouseX, mouseY, 50, 100, colorStops);
34 | circle(mouseX, mouseY, 200);
35 |
36 | fill(255);
37 | noStroke();
38 | text("FPS: " + ~~frameRate(), 10, 10);
39 | }
40 |
41 | function createLinearGradient(x, y, w, h, colorStops) {
42 | grd = drawingContext.createLinearGradient(x, y, x + w, y);
43 | for (let i = 0; i < colorStops.length; i++) {
44 | grd.addColorStop(colorStops[i].stop, colorStops[i].color);
45 | }
46 | drawingContext.fillStyle = grd;
47 | }
48 |
49 | function createRadialGradient(x, y, r1, r2, colorStops) {
50 | grd = drawingContext.createRadialGradient(x, y, r1, x, y, r2);
51 | for (let i = 0; i < colorStops.length; i++) {
52 | grd.addColorStop(colorStops[i].stop, colorStops[i].color);
53 | }
54 | drawingContext.fillStyle = grd;
55 | }
--------------------------------------------------------------------------------
/asset/image/cursor/Install.inf:
--------------------------------------------------------------------------------
1 | [Version]
2 | signature="$CHICAGO$"
3 |
4 | [DefaultInstall]
5 | CopyFiles = Scheme.Cur, Scheme.Txt
6 | AddReg = Scheme.Reg
7 |
8 | [DestinationDirs]
9 | Scheme.Cur = 10,"%CUR_DIR%"
10 | Scheme.Txt = 10,"%CUR_DIR%"
11 |
12 | [Scheme.Reg]
13 | HKCU,"Control Panel\Cursors\Schemes","%SCHEME_NAME%",,"%10%\%CUR_DIR%\%pointer%,%10%\%CUR_DIR%\%help%,%10%\%CUR_DIR%\%work%,%10%\%CUR_DIR%\%busy%,%10%\%CUR_DIR%\%cross%,%10%\%CUR_DIR%\%Text%,%10%\%CUR_DIR%\%Hand%,%10%\%CUR_DIR%\%unavailable%,%10%\%CUR_DIR%\%Vert%,%10%\%CUR_DIR%\%Horz%,%10%\%CUR_DIR%\%Dgn1%,%10%\%CUR_DIR%\%Dgn2%,%10%\%CUR_DIR%\%move%,%10%\%CUR_DIR%\%alternate%,%10%\%CUR_DIR%\%link%,%10%\%CUR_DIR%\%loc%,%10%\%CUR_DIR%\%person%"
14 |
15 | [Scheme.Cur]
16 | alt.cur
17 | working.ani
18 | busy.ani
19 | crosshair.cur
20 | diag1.cur
21 | diag2.cur
22 | handwriting.cur
23 | help.cur
24 | horiz.cur
25 | link.cur
26 | loc.cur
27 | normal.cur
28 | move.cur
29 | person.cur
30 | text.cur
31 | unavailable.cur
32 | vert.cur
33 |
34 | [Scheme.Txt]
35 | README.txt
36 |
37 | [Strings]
38 | CUR_DIR = "Cursors\Summoner"
39 | SCHEME_NAME = "Summoner"
40 | pointer = "normal.cur"
41 | help = "help.cur"
42 | work = "working.ani"
43 | busy = "busy.ani"
44 | text = "text.cur"
45 | unavailable = "unavailable.cur"
46 | vert = "vert.cur"
47 | horz = "horiz.cur"
48 | dgn1 = "diag1.cur"
49 | dgn2 = "diag2.cur"
50 | move = "move.cur"
51 | link = "link.cur"
52 | cross = "crosshair.cur"
53 | hand = "handwriting.cur"
54 | alternate = "alt.cur"
55 | loc = "loc.cur"
56 | person = "person.cur"
--------------------------------------------------------------------------------
/temp/enums/StatusFlags.js:
--------------------------------------------------------------------------------
1 | // Enum of all statuses that can be applied to a unit.
2 | const StatusFlags = {
3 | CallForHelpSuppressor: 1 << 0, // ??
4 | CanAttack: 1 << 1, // Có thể đánh thường
5 | CanCast: 1 << 2, // Có thể dùng chiêu
6 | CanMove: 1 << 3, // Có thể di chuyển
7 | CanMoveEver: 1 << 4, // ??
8 | Charmed: 1 << 5, // Bị quyến rũ (E Ahri, ..)
9 | DisableAmbientGold: 1 << 6, // Không nhận được vàng từ lính chết xung quanh
10 | Disarmed: 1 << 7, // Không đánh thường được
11 | Feared: 1 << 8, // Sợ hãi
12 | ForceRenderParticles: 1 << 9, // ??
13 | GhostProof: 1 << 10, // ?? Flee?
14 | Ghosted: 1 << 11, // ??
15 | IgnoreCallForHelp: 1 << 12, // ??
16 | Immovable: 1 << 13, // Không thể di chuyển
17 | Invulnerable: 1 << 14, // Miễn nhiễm mọi sát thương
18 | MagicImmune: 1 << 15, // Miễn nhiềm sát thương phép thuật
19 | NearSighted: 1 << 16, // Giảm tầm nhìn
20 | Netted: 1 << 17, // Đánh lưới, Bị làm chậm ??
21 | NoRender: 1 << 18, // Tàng hình
22 | Pacified: 1 << 19, // Làm dịu ??
23 | PhysicalImmune: 1 << 20, // Miễn nhiễm sát thương vật lý
24 | RevealSpecificUnit: 1 << 21, // Tiết lộ đơn vị cụ thể ??
25 | Rooted: 1 << 22, // Bị sa lầy
26 | Silenced: 1 << 23, // Bị câm lặng - không thể dùng chiêu
27 | Sleep: 1 << 24, // Ngủ
28 | Stealthed: 1 << 25, // Bị đánh cắp ??
29 | Stunned: 1 << 26, // Bị làm choáng
30 | SuppressCallForHelp: 1 << 27, // ??
31 | Suppressed: 1 << 28, // Bị đàn áp ??
32 | Targetable: 1 << 29, // Có thể chọn làm mục tiêu
33 | Taunted: 1 << 30, // Bị khiêu kích (E Rammus)
34 | };
35 |
36 | Object.freeze(StatusFlags);
37 | export default StatusFlags;
38 |
--------------------------------------------------------------------------------
/test/LOL2D-chatGPT/src/main.js:
--------------------------------------------------------------------------------
1 | import Camera from "./map/Camera.js";
2 | import GroundMap from "./map/GroundMap.js";
3 | import Champion from "./Champion.js";
4 | import { disableRightClick } from "./utils.js";
5 |
6 | let player;
7 | let champions = [];
8 | let camera, groundMap;
9 |
10 | export function setup() {
11 | let c = createCanvas(windowWidth, windowHeight);
12 | disableRightClick(c.elt);
13 |
14 | for (let i = 0; i < 10; i++)
15 | champions.push(new Champion(random(width), random(height)));
16 |
17 | player = champions[0];
18 | player.color = 255;
19 |
20 | camera = new Camera();
21 | groundMap = new GroundMap();
22 |
23 | camera.follow(player.position);
24 | }
25 |
26 | export function draw() {
27 | background(30);
28 |
29 | camera.update();
30 | camera.beginState();
31 |
32 | groundMap.drawEdge(camera);
33 | groundMap.drawGrid(camera);
34 |
35 | for (let champ of champions) {
36 | champ.run();
37 | }
38 |
39 | if (mouseIsPressed && mouseButton === RIGHT) {
40 | let worldPosition = camera.canvasToWorld(mouseX, mouseY);
41 | player.setDestination(worldPosition.x, worldPosition.y);
42 | }
43 |
44 | camera.endState();
45 | }
46 |
47 | export function mouseWheel(event) {
48 | camera.scaleTo -= event.delta / 1000;
49 | if (camera.scaleTo < 0.5) camera.scaleTo = 0.5;
50 | }
51 |
52 | export function mousePressed() {}
53 |
54 | export function keyPressed() {
55 | if (key === "q") {
56 | player.castSpell(0);
57 | }
58 | }
59 |
60 | export function windowResized() {
61 | resizeCanvas(windowWidth, windowHeight, true);
62 | }
63 |
--------------------------------------------------------------------------------
/temp/gameCore/gameObjects/GameObject.js:
--------------------------------------------------------------------------------
1 | import TeamID from "../../enums/TeamID.js";
2 |
3 | export default class GameObject {
4 | constructor(
5 | game,
6 | position = createVector(),
7 | collisionRadius = 40,
8 | visionRadius = 0,
9 | teamId = TeamID.TEAM_NEUTRAL,
10 | ) {
11 | this.game = game;
12 | this.position = position;
13 | this.direction = createVector();
14 | this.collisionRadius = collisionRadius;
15 | this.visionRadius = visionRadius;
16 | this.teamId = teamId;
17 | this.visibleByTeam = new Set();
18 | this.isToRemove = false;
19 | }
20 |
21 | // Sets the position of this object.
22 | setPosition(x, y) {
23 | if (x instanceof p5.Vector) this.position.set(x.x, x.y);
24 | else this.position.set(x, y);
25 | }
26 |
27 | // Sets this GameObject's current orientation
28 | faceDirection(newDirection, isInstant = true, turnTime = 0.083) {
29 | // TODO: implement isInstant and turnTime
30 | this.direction.set(newDirection.x, newDirection.y);
31 | }
32 |
33 | // Whether or not the specified object is colliding with this object.
34 | isCollidingWith(gameObject) {
35 | return (
36 | p5.Vector.dist(this.position, gameObject.position) <
37 | this.collisionRadius + this.gameObject.collisionRadius
38 | );
39 | }
40 |
41 | // Sets the object's team.
42 | setTeam(teamId) {
43 | this.visibleByTeam.delete(this.teamId);
44 | this.teamId = teamId;
45 | this.visibleByTeam.add(this.teamId);
46 | }
47 |
48 | display() {
49 | fill(255);
50 | circle(this.position.x, this.position.y, this.collisionRadius * 2);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/playzone/programming-patterns/command/main.js:
--------------------------------------------------------------------------------
1 | function makeMoveUnitCommand(unit, x, y) {
2 | var xBefore, yBefore;
3 | return {
4 | execute: function () {
5 | xBefore = unit.getX();
6 | yBefore = unit.getY();
7 | unit.moveTo(x, y);
8 | },
9 | undo: function () {
10 | unit.moveTo(xBefore, yBefore);
11 | },
12 | };
13 | }
14 |
15 | let player, undoButton, moveButton;
16 |
17 | function setup() {
18 | createCanvas(500, 500);
19 |
20 | player = {
21 | x: 10,
22 | y: 10,
23 | r: 20,
24 | xTo: 10,
25 | yTo: 20,
26 | moveCommand: null,
27 | getX: function () {
28 | return this.x;
29 | },
30 | getY: function () {
31 | return this.y;
32 | },
33 | show: function () {
34 | fill(100);
35 | circle(this.x, this.y, this.r * 2);
36 | },
37 | move: function () {
38 | this.x = lerp(this.x, this.xTo, 0.1);
39 | this.y = lerp(this.y, this.yTo, 0.1);
40 | },
41 | moveTo: function (x, y) {
42 | this.xTo = x;
43 | this.yTo = y;
44 | },
45 | };
46 |
47 | undoButton = createButton("Undo");
48 | undoButton.mousePressed(() => {
49 | player.moveCommand?.undo();
50 | });
51 |
52 | moveButton = createButton("Move");
53 | moveButton.mousePressed(() => {
54 | let moveCommand = makeMoveUnitCommand(
55 | player,
56 | random(width),
57 | random(height)
58 | );
59 |
60 | player.moveCommand = moveCommand;
61 | player.moveCommand.execute();
62 | });
63 | }
64 |
65 | function draw() {
66 | background(30);
67 |
68 | player.move();
69 | player.show();
70 | }
71 |
--------------------------------------------------------------------------------
/src/scenes/LoadingScene.js:
--------------------------------------------------------------------------------
1 | import AssetManager from "../managers/AssetManager.js";
2 | import { Scene } from "../managers/SceneManager.js";
3 | import MenuScene from "./MenuScene.js";
4 |
5 | export default class LoadingScene extends Scene {
6 | setup() {
7 | this.loadingSceneDiv = document.querySelector("#loading-scene");
8 | this.loadingAnimation = this.loadingSceneDiv.querySelector(".loading");
9 | this.loadingText = this.loadingSceneDiv.querySelector(".loading-text");
10 | this.errorText = this.loadingSceneDiv.querySelector(".error-text");
11 | }
12 |
13 | enter() {
14 | // reset dom
15 | this.loadingSceneDiv.style.display = "block";
16 | this.loadingAnimation.style.display = "block";
17 | this.loadingText.innerHTML = "0%";
18 | this.errorText.innerHTML = "";
19 |
20 | const errorAssets = [];
21 |
22 | // load assets
23 | AssetManager.loadAssets(
24 | // progress
25 | ({ index, total, path }) => {
26 | this.loadingText.innerHTML = round((index / total) * 100) + "%";
27 | },
28 |
29 | // success
30 | () => {
31 | setTimeout(() => {
32 | this.sceneManager.showScene(MenuScene);
33 | }, 1);
34 | },
35 |
36 | // failed
37 | (error) => {
38 | this.loadingAnimation.style.display = "none";
39 | errorAssets.push(error.path[0].currentSrc);
40 | this.errorText.innerHTML = `ERROR: Failed to load assets. ${errorAssets.join(
41 | "\n"
42 | )}`;
43 | }
44 | );
45 | }
46 |
47 | exit() {
48 | // hide dom
49 | this.loadingSceneDiv.style.display = "none";
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/playzone/fixedupdate/main.js:
--------------------------------------------------------------------------------
1 | // source https://stackoverflow.com/a/39834661/11898496
2 |
3 | var t = 0;
4 | var dt = 0.01;
5 |
6 | var currentTime;
7 | var accumulator = 0;
8 |
9 | var previousState = { x: 100, v: 0 };
10 | var currentState = { x: 100, v: 0 };
11 |
12 | var canvas = document.getElementById("myCanvas");
13 | var ctx = canvas.getContext("2d");
14 |
15 | // start animation loop
16 | requestAnimationFrame(animate);
17 |
18 | function animate(newTime) {
19 | requestAnimationFrame(animate);
20 |
21 | if (currentTime) {
22 | var frameTime = newTime - currentTime;
23 | if (frameTime > 250) frameTime = 250;
24 | accumulator += frameTime;
25 |
26 | while (accumulator >= dt) {
27 | previousState = currentState;
28 | currentState = integrate(currentState, t, dt);
29 | t += dt;
30 | accumulator -= dt;
31 | }
32 |
33 | var alpha = accumulator / dt;
34 | var interpolatedPosition =
35 | currentState.x * alpha + previousState.x * (1 - alpha);
36 |
37 | render(interpolatedPosition);
38 | }
39 |
40 | currentTime = newTime;
41 | }
42 |
43 | // Move simulation forward
44 | function integrate(state, time, fixedDeltaTime) {
45 | var fixedDeltaTimeSeconds = fixedDeltaTime / 1000;
46 | var f = (200 - state.x) * 3;
47 | var v = state.v + f * fixedDeltaTimeSeconds;
48 | var x = state.x + v * fixedDeltaTimeSeconds;
49 | return { x: x, v: v };
50 | }
51 |
52 | // Render the scene
53 | function render(position) {
54 | // Clear
55 | ctx.fillStyle = "white";
56 | ctx.fillRect(0, 0, canvas.width, canvas.height);
57 |
58 | // Draw circle
59 | ctx.fillStyle = "black";
60 | ctx.beginPath();
61 | ctx.arc(position, 100, 50, 0, 2 * Math.PI);
62 | ctx.closePath();
63 | ctx.fill();
64 | }
65 |
--------------------------------------------------------------------------------
/src/managers/AssetManager.js:
--------------------------------------------------------------------------------
1 | const AssetPaths = [
2 | // hud
3 | "asset/image/hud/ability.png",
4 | "asset/image/hud/item.png",
5 | "asset/image/hud/avatar.png",
6 |
7 | // spell
8 | "asset/image/spell/Flash.png",
9 |
10 | // ahri
11 | "asset/image/champion/ahri/Ahri.avatar.circle.png",
12 | "asset/image/champion/ahri/Ahri.avatar.square.png",
13 | "asset/image/champion/ahri/Charm.ability.png",
14 | "asset/image/champion/ahri/Fox-Fire.ability.png",
15 | "asset/image/champion/ahri/Orb-of-Deception.ability.png",
16 | "asset/image/champion/ahri/Spirit-Rush.ability.png",
17 |
18 | // jinx
19 | "asset/image/champion/jinx/Jinx.avatar.circle.png",
20 | ];
21 |
22 | export default class AssetManager {
23 | static _asset = {};
24 |
25 | static getAsset(path) {
26 | return this._asset[path];
27 | }
28 |
29 | static loadAssets(onProgress, onSuccess, onFailed) {
30 | let loadedCount = 0;
31 | let hasError = false;
32 |
33 | for (let path of AssetPaths) {
34 | loadImage(
35 | path,
36 | // success
37 | (data) => {
38 | this._asset[path] = data;
39 | loadedCount++;
40 |
41 | onProgress &&
42 | onProgress({
43 | index: loadedCount,
44 | total: AssetPaths.length,
45 | path: path,
46 | });
47 |
48 | if (loadedCount == AssetPaths.length && !hasError) {
49 | onSuccess && onSuccess();
50 | }
51 | },
52 | // failed
53 | (error) => {
54 | hasError = true;
55 | onFailed && onFailed(error);
56 | }
57 | );
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/css/pre-game-scene.css:
--------------------------------------------------------------------------------
1 | #pre-game-scene {
2 | display: none;
3 | }
4 |
5 | #pre-game-scene * {
6 | font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
7 | }
8 |
9 | #pre-game-scene h2 {
10 | text-align: center;
11 | font-weight: bold;
12 | font-size: 1.5em;
13 | margin-bottom: 20px;
14 | }
15 |
16 | .spells-chooser {
17 | width: 565px;
18 | }
19 |
20 | .spells-container {
21 | padding: 10px;
22 | /* display: flex; */
23 | /* flex-wrap: wrap; */
24 | height: 400px;
25 | overflow: auto;
26 | }
27 |
28 | .spells-container .spell {
29 | display: inline-block;
30 | text-align: center;
31 | padding: 5px;
32 | border-bottom: 5px transparent solid;
33 | transition: .2s all;
34 | opacity: 0.5;
35 | }
36 |
37 | .spells-container .spell:hover {
38 | /* background-color: aliceblue; */
39 | opacity: 1;
40 | }
41 |
42 | .spells-container .spell img {
43 | width: 3.5em;
44 | height: 3.5em;
45 | transition: .2s all;
46 | }
47 |
48 | .spells-container .spell .spell-name {
49 | font-size: 0.9em;
50 | }
51 |
52 | .spells-container .spell:hover {
53 | border-color: rgb(80, 80, 80);
54 | cursor: pointer;
55 | transform: translateY(-5px);
56 | }
57 |
58 | .spells-container .spell:hover img {
59 | transform: scale(1.1);
60 | /* font-weight: bold; */
61 | }
62 |
63 | .spell-info {
64 | height: 130px;
65 | overflow: auto;
66 | }
67 |
68 | .spell-info-header {
69 | display: inline-flex;
70 | margin: 10px;
71 | }
72 |
73 | .spell-info-header img {
74 | width: 3em;
75 | height: 3em;
76 | margin-right: 10px;
77 | }
78 |
79 | .spell-info .spell-title {
80 | font-size: 1.2em;
81 | font-weight: bold;
82 | }
83 |
84 | .spell-info .spell-name {
85 | font-style: italic;
86 | }
87 |
88 | .spell-info .spell-description {
89 | font-size: 0.9em;
90 | }
--------------------------------------------------------------------------------
/playzone/programming-patterns/component/core/GameObject.js:
--------------------------------------------------------------------------------
1 | // https://docs.unity3d.com/ScriptReference/GameObject.html
2 |
3 | import BaseObject from "./BaseObject.js";
4 | import Transform from "./Transform.js";
5 |
6 | export default class GameObject extends BaseObject {
7 | static find(name) {
8 | let gameObjs = BaseObject.findObjectsOfType(GameObject);
9 | return gameObjs.filter((g) => g.name === name) || null;
10 | }
11 |
12 | static findGameObjectsWithTag(tag) {
13 | let gameObjs = BaseObject.findObjectsOfType(GameObject);
14 | return gameObjs.filter((g) => g.tag === tag) || [];
15 | }
16 |
17 | static findWithTag() {
18 | let gameObjs = BaseObject.findObjectsOfType(GameObject);
19 | return gameObjs.find((g) => g.tag === tag) || [];
20 | }
21 |
22 | constructor() {
23 | super();
24 |
25 | this.transform = new Transform();
26 | this.transform.attachTo(this);
27 |
28 | this.components = [];
29 | this.active = true;
30 | this.scene = null;
31 | this.tag = "";
32 | }
33 |
34 | addComponent(componentType) {
35 | let component = new componentType();
36 | component.attachTo(this);
37 | this.components.push(component);
38 |
39 | return component;
40 | }
41 |
42 | getComponent(type) {
43 | return this.components.find((c) => c instanceof type) || null;
44 | }
45 |
46 | getComponents(type) {
47 | return this.components.filter((c) => c instanceof type) || [];
48 | }
49 |
50 | // Calls the method named methodName on every MonoBehaviour in this game object.
51 | sendMessage(methodName, ...params) {
52 | let received = false;
53 | for (let c of this.components) {
54 | if (c[methodName]) {
55 | c[methodName](params);
56 | received = true;
57 | }
58 | }
59 |
60 | return received;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/css/menu-scene.css:
--------------------------------------------------------------------------------
1 | /* menu scene */
2 | #menu-scene {
3 | text-align: center;
4 | }
5 |
6 | #menu-scene button {
7 | margin-top: 50px;
8 | }
9 |
10 | .shiny {
11 | display: block;
12 | height: 200px;
13 | width: 450px;
14 | position: relative;
15 | overflow: hidden;
16 | }
17 |
18 | .shiny img {
19 | position: absolute;
20 | top: 0;
21 | left: 0;
22 | height: 100%;
23 | width: 100%;
24 | }
25 |
26 | .shiny:before {
27 | content: "";
28 | z-index: 10;
29 | position: absolute;
30 | height: 200%;
31 | width: 200%;
32 | top: -120%;
33 | left: -120%;
34 | background: linear-gradient(transparent 0%, rgba(255, 255, 255, 0.1) 45%, rgba(255, 255, 255, 0.5) 50%, rgba(255, 255, 255, 0.1) 55%, transparent 100%);
35 | transition: all 2s;
36 | transform: rotate(-45deg);
37 | animation: shine 5s infinite forwards;
38 | }
39 |
40 | @keyframes shine {
41 | 0% {
42 | top: -120%;
43 | left: -120%;
44 | }
45 |
46 | 40% {
47 | left: 100%;
48 | top: 100%;
49 | }
50 |
51 | 100% {
52 | left: 100%;
53 | top: 100%;
54 | }
55 | }
56 |
57 | .p2d {
58 | position: absolute;
59 | top: 0;
60 | right: 0;
61 | text-transform: uppercase;
62 | font-family: verdana;
63 | font-size: 4em;
64 | font-weight: 700;
65 | color: #edf2f4;
66 | transform: rotate(25deg) translateX(20px) translateY(-50px);
67 |
68 | text-shadow: 1px 1px 1px #8d99ae,
69 | 1px 2px 1px #8d99ae,
70 | 1px 3px 1px #8d99ae,
71 | 1px 4px 1px #8d99ae,
72 | 1px 5px 1px #8d99ae,
73 | 1px 6px 1px #8d99ae,
74 | 1px 7px 1px #8d99ae,
75 | 1px 8px 1px #8d99ae,
76 | 1px 9px 1px #8d99ae,
77 | 1px 10px 1px #8d99ae,
78 | 1px 18px 6px rgba(16, 16, 16, 0.4),
79 | 1px 22px 10px rgba(16, 16, 16, 0.2),
80 | 1px 25px 35px rgba(16, 16, 16, 0.2),
81 | 1px 30px 60px rgba(16, 16, 16, 0.4);
82 | }
--------------------------------------------------------------------------------
/playzone/sat/main.js:
--------------------------------------------------------------------------------
1 | let p;
2 | let c;
3 |
4 | function setup() {
5 | createCanvas(2000, 2000);
6 |
7 | p = [
8 | { x: 85, y: 57 },
9 | { x: 146, y: 39 },
10 | { x: 156, y: 75 },
11 | { x: 152, y: 156 },
12 | { x: 150, y: 212 },
13 | { x: 169, y: 264 },
14 | { x: 217, y: 332 },
15 | { x: 296, y: 404 },
16 | { x: 369, y: 463 },
17 | { x: 457, y: 511 },
18 | { x: 524, y: 530 },
19 | { x: 614, y: 531 },
20 | { x: 708, y: 525 },
21 | { x: 761, y: 492 },
22 | { x: 811, y: 493 },
23 | { x: 868, y: 520 },
24 | { x: 917, y: 515 },
25 | { x: 993, y: 535 },
26 | { x: 677, y: 813 },
27 | { x: 628, y: 813 },
28 | { x: 576, y: 773 },
29 | { x: 415, y: 711 },
30 | { x: 147, y: 657 },
31 | { x: 133, y: 632 },
32 | { x: 183, y: 570 },
33 | { x: 206, y: 522 },
34 | { x: 204, y: 466 },
35 | { x: 176, y: 397 },
36 | { x: 130, y: 352 },
37 | { x: 76, y: 321 },
38 | { x: 58, y: 268 },
39 | { x: 54, y: 197 },
40 | ];
41 | }
42 |
43 | function draw() {
44 | background(30);
45 |
46 | let cx = mouseX;
47 | let cy = mouseY;
48 |
49 | let SATpolygon = new SAT.Polygon(
50 | new SAT.Vector(),
51 | p.map((point) => new SAT.Vector(point.x, point.y))
52 | );
53 |
54 | let SATcircle = new SAT.Circle(new SAT.Vector(cx, cy), 20);
55 |
56 | let response = new SAT.Response();
57 | let collided = SAT.testPolygonCircle(SATpolygon, SATcircle, response);
58 |
59 | if (collided) {
60 | fill("red");
61 | // console.log(response);
62 | cx += response.overlapV.x;
63 | cy += response.overlapV.y;
64 | } else {
65 | fill("white");
66 | }
67 |
68 | beginShape();
69 | for (let point of p) {
70 | vertex(point.x, point.y);
71 | }
72 | endShape();
73 |
74 | circle(cx, cy, 40);
75 | }
76 |
--------------------------------------------------------------------------------
/src/managers/EventManager.js:
--------------------------------------------------------------------------------
1 | // source: https://github.com/behnammodi/jetemit/blob/master/src/index.js
2 |
3 | /**
4 | * @description subscribes repo
5 | * @private
6 | */
7 | const subscribes = new Map();
8 |
9 | /**
10 | * @description add listener
11 | * @public
12 | * @param {string} name name listener
13 | * @param {function} func function for call
14 | * @returns {function} unsubscribe function
15 | */
16 | function on(name, func) {
17 | if (!subscribes.has(name)) subscribes.set(name, []);
18 | subscribes.get(name).push(func);
19 | return () => unsubscribeOf(name, func);
20 | }
21 |
22 | /**
23 | * @description like "on" but just run once
24 | * @public
25 | * @param {string} name name listener
26 | * @param {function} func function for call
27 | * @returns {function} unsubscribe function
28 | */
29 | function once(name, func) {
30 | const unsubscribe = on(name, function () {
31 | func.apply(undefined, arguments);
32 | unsubscribe();
33 | });
34 | return unsubscribe;
35 | }
36 |
37 | /**
38 | * @description dispatch all listener
39 | * @public
40 | * @param {string} name name listener
41 | * @param {any} arg argument for send to on(...)
42 | * @returns {array} refunds all listen can return data
43 | */
44 | function emit(name, arg) {
45 | const refunds = [];
46 | if (subscribes.has(name))
47 | subscribes.get(name).forEach((func) => {
48 | if (func) refunds.push(func(arg));
49 | });
50 | return refunds;
51 | }
52 |
53 | /**
54 | * @description unsubscribe listener
55 | * @public
56 | * @param {string} name name listener
57 | * @param {function} func the function that you want to unsubscribe If not defined, all subscriptions will be canceled
58 | * @returns {undefined} nothing
59 | */
60 | function unsubscribeOf(name, func) {
61 | if (func)
62 | subscribes.set(
63 | name,
64 | subscribes.get(name).filter((f) => f !== func)
65 | );
66 | else subscribes.delete(name);
67 | }
68 |
69 | export { on, emit, once, unsubscribeOf };
70 |
71 |
--------------------------------------------------------------------------------
/playzone/decomp-polygon/main.js:
--------------------------------------------------------------------------------
1 | // https://github.com/schteppe/poly-decomp.js/
2 |
3 | let path = [];
4 | let polys = [];
5 | let spacing = 30;
6 | let colors = ["#f99", "#9f9", "#99f", "#ff9"];
7 |
8 | function setup() {
9 | createCanvas(500, 500);
10 |
11 | strokeWeight(3);
12 | }
13 |
14 | function draw() {
15 | background(30);
16 |
17 | // ========== polygon ==========
18 | // shape
19 | stroke("gray");
20 | noFill();
21 | beginShape();
22 | for (let p of path) {
23 | vertex(p[0], p[1]);
24 | }
25 | endShape(CLOSE);
26 |
27 | // points
28 | fill("red");
29 | noStroke();
30 | for (let p of path) {
31 | circle(p[0], p[1], 10);
32 | }
33 |
34 | // ========== decomped polygon ==========
35 | for (let i = 0; i < polys.length; i++) {
36 | fill(colors[i % colors.length]);
37 |
38 | beginShape();
39 | for (let p of polys[i]) {
40 | vertex(p[0], p[1]);
41 | }
42 | endShape();
43 | }
44 |
45 | // hint
46 | fill("white");
47 | noStroke();
48 | text("Drag mouse to draw polygon", 10, 15);
49 | }
50 |
51 | function mousePressed() {
52 | // reset polygon
53 | path = [];
54 | polys = [];
55 | }
56 |
57 | function mouseReleased() {
58 | polys = decompPolygon(path);
59 | }
60 |
61 | function mouseDragged() {
62 | let canAddPoint = true;
63 |
64 | if (path.length > 0) {
65 | let lastPoint = path[path.length - 1];
66 | let d = dist(lastPoint[0], lastPoint[1], mouseX, mouseY);
67 |
68 | if (d < spacing) {
69 | canAddPoint = false;
70 | }
71 | }
72 |
73 | if (canAddPoint) {
74 | path.push([mouseX, mouseY]);
75 | }
76 | }
77 |
78 | function decompPolygon(_path) {
79 | if (_path.length < 3) return [];
80 |
81 | // Make sure the polygon has counter-clockwise winding. Skip this step if you know it's already counter-clockwise.
82 | decomp.makeCCW(_path);
83 |
84 | // Decompose into convex polygons, using the faster algorithm
85 | return decomp.quickDecomp(_path);
86 | }
87 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | LOL2D Core
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
Chọn chiêu thức
38 |
42 |
43 |
44 |
49 |
50 |
60 |
61 |
62 |
Setting
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/src/game/Game.js:
--------------------------------------------------------------------------------
1 | import Champion from "./champions/Champion.js";
2 | import SpellKeys from "./enums/SpellKeys.js";
3 | import Camera from "./maps/Camera.js";
4 | import GroundMap from "./maps/GroundMap.js";
5 | import Stats from "./stats/Stats.js";
6 |
7 | const fps = 60; // fixed update fps
8 | let accumulator = 0;
9 |
10 | export default class Game {
11 | constructor() {
12 | this.camera = new Camera();
13 | this.groundMap = new GroundMap(this);
14 |
15 | this.player = new Champion(
16 | this,
17 | createVector(100, 100),
18 | "asset/image/champion/ahri/Ahri.avatar.circle.png",
19 | new Stats(),
20 | {
21 | [SpellKeys.A]: () => {
22 | console.log("a");
23 | },
24 | }
25 | );
26 |
27 | this.camera.follow(this.player.position);
28 | }
29 |
30 | gameLoop(diff) {
31 | // https://medium.com/@tglaiel/how-to-make-your-game-run-at-60fps-24c61210fe75
32 | accumulator += Math.min(diff, 250);
33 |
34 | while (accumulator > 1000 / (fps + 1)) {
35 | this.fixedUpdate();
36 | accumulator -= 1000 / (fps - 1);
37 | if (accumulator < 1000 / (fps - 1) - 1000 / fps) accumulator = 0;
38 | }
39 |
40 | this.update();
41 | this.draw();
42 | }
43 |
44 | fixedUpdate() {
45 | if (mouseIsPressed) {
46 | let m = this.camera.canvasToWorld(mouseX, mouseY);
47 | this.player.wayPoints = [createVector(m.x, m.y)];
48 | }
49 |
50 | this.player.update();
51 | this.player.bound(this.groundMap);
52 | this.camera.update();
53 | }
54 |
55 | update() {}
56 |
57 | draw() {
58 | background("#1E1E1E");
59 | this.camera.beginState();
60 |
61 | this.groundMap.drawEdge();
62 | this.groundMap.drawGrid();
63 |
64 | fill(255);
65 | circle(100, 100, 50);
66 |
67 | this.player.draw();
68 |
69 | this.camera.endState();
70 | }
71 |
72 | onMousePressed() {}
73 |
74 | onKeyPressed() {
75 | let spell = this.player.spells[keyCode];
76 | if (spell) spell();
77 | }
78 |
79 | onMouseWheel(e) {
80 | let delta = (this.camera.scaleTo / 10) * (e.delta > 0 ? -1 : 1);
81 | this.camera.scaleTo += delta;
82 | this.camera.scaleTo = constrain(this.camera.scaleTo, 0.1, 5);
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/favicon/safari-pinned-tab.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
40 |
--------------------------------------------------------------------------------
/playzone/visibility/main.js:
--------------------------------------------------------------------------------
1 | // data from http://www.byronknoll.com/visibility.html
2 | let polygons=[[[240,240],[260,240],[260,260],[240,260]],[[240,260],[260,260],[260,280],[240,280]],[[260,240],[280,240],[280,260],[260,260]],[[440,240],[460,240],[460,260],[440,260]],[[250,100],[260,140],[240,140]],[[280,100],[290,60],[270,60]],[[310,100],[320,140],[300,140]],[[50,450],[60,370],[70,450]],[[450,450],[460,370],[470,450]],[[50,50],[60,30],[70,50]],[[450,50],[460,30],[470,50]],[[140,340],[160,240],[180,340],[360,340],[360,360],[250,390],[140,360]],[[140,140],[150,130],[150,145],[165,150],[160,160],[140,160]],[[100,150],[100,100]],[[50,125],[100,125]],[[450,100],[400,150]],[[450,150],[400,100]],[[50,250],[100,250]],[[50,250],[100,250]],[[140,40],[140,60]],[[140,60],[160,60]],[[160,60],[160,40]],[[160,40],[140,40]]];
3 |
4 | function setup() {
5 | createCanvas(500, 500);
6 | strokeWeight(2);
7 |
8 | for (var i = 0; i < 20; ++i) {
9 | polygons.push([
10 | [240, 410 + i * 4],
11 | [245, 410 + i * 4],
12 | [245, 411 + i * 4],
13 | [240, 411 + i * 4],
14 | ]);
15 | }
16 | }
17 |
18 | function draw() {
19 | background("#666666");
20 |
21 | // move polygons
22 | let delX = 0,
23 | delY = 0,
24 | speed = 3;
25 | if (keyIsDown(LEFT_ARROW)) delX = speed;
26 | if (keyIsDown(RIGHT_ARROW)) delX = -speed;
27 | if (keyIsDown(UP_ARROW)) delY = speed;
28 | if (keyIsDown(DOWN_ARROW)) delY = -speed;
29 |
30 | for (let poly of polygons) {
31 | for (let p of poly) {
32 | p[0] += delX;
33 | p[1] += delY;
34 | }
35 | }
36 |
37 | // draw polygons
38 | fill("#FFA500");
39 | stroke("#000");
40 | for (let poly of polygons) {
41 | beginShape();
42 | for (let p of poly) {
43 | vertex(p[0], p[1]);
44 | }
45 | endShape(CLOSE);
46 | }
47 |
48 | var sourcelight = [mouseX, mouseY];
49 |
50 | // calculate
51 | let segments = VisibilityPolygon.convertToSegments(polygons);
52 | segments = VisibilityPolygon.breakIntersections(segments);
53 |
54 | var viewportVisibility = VisibilityPolygon.computeViewport(
55 | sourcelight,
56 | segments,
57 | [0, 0],
58 | [width, height]
59 | );
60 |
61 | // show result
62 | fill("#AAA");
63 | noStroke();
64 | beginShape();
65 | for (let p of viewportVisibility) {
66 | vertex(p[0], p[1]);
67 | }
68 | endShape(CLOSE);
69 |
70 | // draw source light
71 | fill("#FF0");
72 | stroke("#000");
73 | circle(sourcelight[0], sourcelight[1], 10);
74 |
75 | // help
76 | fill("white");
77 | noStroke();
78 | text("Use ARROW KEY to move, move mouse to move light source.", 10, 20);
79 | text("FPS: " + ~~frameRate(), 10, 40);
80 | }
81 |
--------------------------------------------------------------------------------
/src/game/champions/Champion.js:
--------------------------------------------------------------------------------
1 | import AssetManager from "../../managers/AssetManager.js";
2 | import { HasFlag } from "../../utils/Helpers.js";
3 | import StatusFlags from "../enums/StatusFlags.js";
4 | import Game from "../Game.js";
5 | import GroundMap from "../maps/GroundMap.js";
6 | import Stats from "../stats/Stats.js";
7 |
8 | export default class Champion {
9 | constructor(
10 | /** @type Game */ game,
11 | position = createVector(),
12 | skin = "",
13 | stats = new Stats(),
14 | spells = {}
15 | ) {
16 | this.game = game;
17 | this.position = position;
18 | this.skin = skin;
19 | this.stats = stats;
20 | this.status =
21 | StatusFlags.CanCast | StatusFlags.CanMove | StatusFlags.CanAttack;
22 | this.spells = spells;
23 |
24 | this.wayPoints = [];
25 | }
26 |
27 | update(diff) {
28 | if (!this.isDead() && this.canMove() && this.wayPoints.length > 0) {
29 | this.move();
30 | }
31 | }
32 |
33 | draw() {
34 | image(
35 | AssetManager.getAsset(this.skin),
36 | this.position.x,
37 | this.position.y,
38 | this.stats.size.total(),
39 | this.stats.size.total()
40 | );
41 | }
42 |
43 | move() {
44 | let direction = p5.Vector.sub(this.wayPoints[0], this.position);
45 | let distance = direction.mag();
46 | let speed = this.stats.moveSpeed.total();
47 | if (distance > 0) {
48 | let d = min(speed, distance);
49 | let v = direction.setMag(d);
50 |
51 | this.position.add(v);
52 | } else {
53 | this.wayPoints.shift();
54 | }
55 | }
56 |
57 | bound(/** @type GroundMap */ groundMap) {
58 | let radius = this.stats.size.total() / 2;
59 | let { top, bottom, left, right } = groundMap.getBound();
60 |
61 | if (this.position.x < left + radius) {
62 | this.position.x = left + radius;
63 | } else if (this.position.x > right - radius) {
64 | this.position.x = right - radius;
65 | }
66 |
67 | if (this.position.y < top + radius) {
68 | this.position.y = top + radius;
69 | } else if (this.position.y > bottom - radius) {
70 | this.position.y = bottom - radius;
71 | }
72 | }
73 |
74 | setStatus(statusFlag, enabled) {
75 | if (enabled) this.status |= statusFlag;
76 | else this.status &= ~statusFlag;
77 | }
78 |
79 | isDead() {
80 | return this.stats.currentHealth <= 0;
81 | }
82 |
83 | canMove() {
84 | return HasFlag(this.status, StatusFlags.CanMove);
85 | }
86 |
87 | canCast() {
88 | return HasFlag(this.status, StatusFlags.CanCast);
89 | }
90 |
91 | canAttack() {
92 | return HasFlag(this.status, StatusFlags.CanAttack);
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/test/LOL2D-chatGPT/src/map/GroundMap.js:
--------------------------------------------------------------------------------
1 | export default class GroundMap {
2 | constructor({
3 | width = 1500,
4 | height = 1500,
5 | bgColor = "#555555",
6 | edgeColor = "#7779",
7 | edgeWeight = 3,
8 | showGrid = true,
9 | gridSize = 300,
10 | gridColor = "#5555",
11 | gridWeight = 3,
12 | } = {}) {
13 | this.width = width;
14 | this.height = height;
15 | this.bgColor = bgColor;
16 | this.edgeColor = edgeColor;
17 | this.edgeWeight = edgeWeight;
18 | this.showGrid = showGrid;
19 | this.gridSize = gridSize;
20 | this.gridColor = gridColor;
21 | this.gridWeight = gridWeight;
22 | }
23 |
24 | drawEdge(camera) {
25 | let { x, y, w, h } = camera.getViewport();
26 |
27 | x -= this.edgeWeight;
28 | y -= this.edgeWeight;
29 | w += this.edgeWeight * 2;
30 | h += this.edgeWeight * 2;
31 |
32 | let left = max(x, 0);
33 | let right = min(x + w, this.width);
34 | let top = max(y, 0);
35 | let bottom = min(y + h, this.height);
36 |
37 | stroke(this.edgeColor);
38 | strokeWeight(this.edgeWeight);
39 | noFill();
40 |
41 | rect(left, top, right - left, bottom - top);
42 | }
43 |
44 | drawGrid(camera) {
45 | let { x, y, w, h } = camera.getViewport();
46 | let leftScreen = x,
47 | rightScreen = x + w,
48 | topScreen = y,
49 | bottomScreen = y + h;
50 |
51 | let leftMap = max(leftScreen - 50, 0);
52 | let rightMap = min(rightScreen + 50, this.width);
53 | let topMap = max(topScreen - 50, 0);
54 | let bottomMap = min(bottomScreen + 50, this.height);
55 |
56 | // fill bgcolor
57 | //fill(this.bgColor);
58 | //rect(leftMap, topMap, rightMap - leftMap, bottomMap - topMap);
59 |
60 | // draw grid
61 | stroke(this.gridColor);
62 | strokeWeight(this.gridWeight);
63 |
64 | let delta = 1;
65 | for (let x = leftMap; x < rightMap; x += delta) {
66 | if (floor(x) % this.gridSize == 0) {
67 | /* while you find 1 x%this.gridSize==0
68 | => delta will equal this.gridSize => shorter loop */
69 | delta = this.gridSize;
70 | line(x, topMap, x, bottomMap);
71 | }
72 | }
73 |
74 | // do the same thing to y axis
75 | delta = 1;
76 | for (let y = topMap; y < bottomMap; y += delta) {
77 | if (floor(y) % this.gridSize == 0) {
78 | delta = this.gridSize;
79 | line(leftMap, y, rightMap, y);
80 | }
81 | }
82 | }
83 |
84 | getBound() {
85 | return {
86 | top: 0,
87 | bottom: this.height,
88 | left: 0,
89 | right: this.width,
90 | };
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/game/stats/Stats.js:
--------------------------------------------------------------------------------
1 | import Stat from "./Stat.js";
2 | import StatsModifier from "./StatsModifier.js";
3 |
4 | export default class Stats {
5 | constructor() {
6 | this.healthPoints = new Stat(700); // máu tối đa
7 | this.manaPoints = new Stat(500); // mana tối đa
8 | this.healthRegen = new Stat(); // hồi máu
9 | this.manaRegen = new Stat(); // hồi năng lượng
10 | this.moveSpeed = new Stat(3); // tốc chạy
11 | this.attackSpeed = new Stat(1); // tốc đánh
12 | this.attackDamage = new Stat(65); // sát thương vật lý
13 | this.magicDamage = new Stat(0); // sát thương phép
14 | this.attackRange = new Stat(150); // tầm đánh
15 | this.attackSpeedMult = new Stat(); // % tốc đánh cộng thêm
16 | this.cooldownReduction = new Stat(); // giảm thời gian hồi chiêu
17 | this.lifeSteal = new Stat(); // hút máu
18 | this.size = new Stat(65); // kích thước
19 | }
20 |
21 | get currentHealth() {
22 | return this.healthPoints.total();
23 | }
24 |
25 | get currentMana() {
26 | return this.manaPoints.total();
27 | }
28 |
29 | addModifier(statsModifier = new StatsModifier()) {
30 | this.healthPoints.addModifier(statsModifier.healthPoints);
31 | this.manaPoints.addModifier(statsModifier.manaPoints);
32 | this.healthRegen.addModifier(statsModifier.healthRegen);
33 | this.manaRegen.addModifier(statsModifier.manaRegen);
34 | this.moveSpeed.addModifier(statsModifier.moveSpeed);
35 | this.attackSpeed.addModifier(statsModifier.attackSpeed);
36 | this.attackDamage.addModifier(statsModifier.attackDamage);
37 | this.magicDamage.addModifier(statsModifier.magicDamage);
38 | this.attackRange.addModifier(statsModifier.attackRange);
39 | this.attackSpeedMult.addModifier(statsModifier.attackSpeedMult);
40 | this.cooldownReduction.addModifier(statsModifier.cooldownReduction);
41 | this.lifeSteal.addModifier(statsModifier.lifeSteal);
42 | this.size.addModifier(statsModifier.size);
43 | return this;
44 | }
45 |
46 | removeModifier(statsModifier = new StatsModifier()) {
47 | this.healthPoints.removeModifier(statsModifier.healthPoints);
48 | this.manaPoints.removeModifier(statsModifier.manaPoints);
49 | this.healthRegen.removeModifier(statsModifier.healthRegen);
50 | this.manaRegen.removeModifier(statsModifier.manaRegen);
51 | this.moveSpeed.removeModifier(statsModifier.moveSpeed);
52 | this.attackSpeed.removeModifier(statsModifier.attackSpeed);
53 | this.attackDamage.removeModifier(statsModifier.attackDamage);
54 | this.magicDamage.removeModifier(statsModifier.magicDamage);
55 | this.attackRange.removeModifier(statsModifier.attackRange);
56 | this.attackSpeedMult.removeModifier(statsModifier.attackSpeedMult);
57 | this.cooldownReduction.removeModifier(statsModifier.cooldownReduction);
58 | this.lifeSteal.removeModifier(statsModifier.lifeSteal);
59 | this.size.removeModifier(statsModifier.size);
60 | return this;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/game/maps/Camera.js:
--------------------------------------------------------------------------------
1 | export default class Camera {
2 | constructor(
3 | position = createVector(width / 2, height / 2),
4 | target = null, // target is a gameObject's position
5 | isFollow = true,
6 | followLerp = 0.1,
7 | scale = 1,
8 | scaleTo = 1,
9 | scaleLerp = 0.07,
10 | borderSize = 25,
11 | borderSpeed = 30
12 | ) {
13 | // default value
14 | this.position = position;
15 | this.target = target;
16 | this.isFollow = isFollow;
17 | this.followLerp = followLerp;
18 | this.scale = scale;
19 | this.scaleTo = scaleTo;
20 | this.scaleLerp = scaleLerp;
21 | this.borderSize = borderSize;
22 | this.borderSpeed = borderSpeed;
23 | }
24 |
25 | update() {
26 | // update scale
27 | this.scale = lerp(this.scale, this.scaleTo, this.scaleLerp);
28 |
29 | // follow target
30 | if (this.isFollow) {
31 | this.position = p5.Vector.lerp(
32 | this.position,
33 | this.target,
34 | this.followLerp
35 | );
36 | }
37 |
38 | // move camera on edge
39 | else if (this.isMouseOnEdge()) {
40 | let vec = createVector(
41 | mouseX - width * 0.5,
42 | mouseY - height * 0.5
43 | ).setMag(this.borderSpeed);
44 | this.position.add(vec);
45 | }
46 | }
47 |
48 | beginState() {
49 | push();
50 | translate(width * 0.5, height * 0.5);
51 | scale(this.scale);
52 | translate(-this.position.x, -this.position.y);
53 | }
54 |
55 | endState() {
56 | pop();
57 | }
58 |
59 | follow(target, immediately) {
60 | this.target = target;
61 |
62 | if (immediately) this.position.set(target.x, target.y);
63 | }
64 |
65 | getViewport() {
66 | let topLeftCanvas = this.canvasToWorld(0, 0);
67 | let bottomRightCanvas = this.canvasToWorld(width, height);
68 |
69 | return {
70 | x: topLeftCanvas.x,
71 | y: topLeftCanvas.y,
72 | w: bottomRightCanvas.x - topLeftCanvas.x,
73 | h: bottomRightCanvas.y - topLeftCanvas.y,
74 | };
75 | }
76 |
77 | canvasToWorld(canvasX, canvasY) {
78 | let worldX = (canvasX - width * 0.5) / this.scale + this.position.x;
79 | let worldY = (canvasY - height * 0.5) / this.scale + this.position.y;
80 |
81 | return createVector(worldX, worldY);
82 | }
83 |
84 | worldToCanvas(worldX, worldY) {
85 | let canvasX = (worldX - this.position.x) * this.scale + width * 0.5;
86 | let canvasY = (worldY - this.position.y) * this.scale + height * 0.5;
87 |
88 | return createVector(canvasX, canvasY);
89 | }
90 |
91 | isMouseOnEdge() {
92 | return (
93 | mouseX > width - this.borderSize ||
94 | mouseX < this.borderSize ||
95 | mouseY > height - this.borderSize ||
96 | mouseY < this.borderSize
97 | );
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/game/maps/GroundMap.js:
--------------------------------------------------------------------------------
1 | import Game from "../Game.js";
2 |
3 | export default class GroundMap {
4 | constructor(
5 | /** @type Game */
6 | game,
7 | width = 1500,
8 | height = 1500,
9 | bgColor = "#555555",
10 | edgeColor = "#7779",
11 | edgeWeight = 3,
12 | showGrid = true,
13 | gridSize = 200,
14 | gridColor = "#5555",
15 | gridWeight = 3
16 | ) {
17 | this.game = game;
18 | this.width = width;
19 | this.height = height;
20 | this.bgColor = bgColor;
21 | this.edgeColor = edgeColor;
22 | this.edgeWeight = edgeWeight;
23 | this.showGrid = showGrid;
24 | this.gridSize = gridSize;
25 | this.gridColor = gridColor;
26 | this.gridWeight = gridWeight;
27 | }
28 |
29 | drawEdge() {
30 | // Vẽ biên
31 | // dùng 4 đỉnh đê vẽ hình chữ nhât
32 | let topleft = createVector(0, 0); // đỉnh trên trái
33 | let topright = createVector(this.width, 0); // đỉnh trên phải
34 | let botleft = createVector(0, this.height); // đỉnh dưới trái
35 | let botright = createVector(this.width, this.height); // đỉnh dưới phải
36 |
37 | stroke(this.edgeColor);
38 | strokeWeight(this.edgeWeight);
39 |
40 | // Ve duong thang qua cac dinh
41 | line(topleft.x, topleft.y, topright.x, topright.y);
42 | line(topright.x, topright.y, botright.x, botright.y);
43 | line(botright.x, botright.y, botleft.x, botright.y);
44 | line(botleft.x, botleft.y, topleft.x, topleft.y);
45 | }
46 |
47 | drawGrid() {
48 | let { x, y, w, h } = this.game.camera.getViewport();
49 | let leftScreen = x,
50 | rightScreen = x + w,
51 | topScreen = y,
52 | bottomScreen = y + h;
53 |
54 | let leftMap = max(leftScreen - 50, 0);
55 | let rightMap = min(rightScreen + 50, this.width);
56 | let topMap = max(topScreen - 50, 0);
57 | let bottomMap = min(bottomScreen + 50, this.height);
58 |
59 | // fill bgcolor
60 | //fill(this.bgColor);
61 | //rect(leftMap, topMap, rightMap - leftMap, bottomMap - topMap);
62 |
63 | // draw grid
64 | stroke(this.gridColor);
65 | strokeWeight(this.gridWeight);
66 |
67 | let delta = 1;
68 | for (let x = leftMap; x < rightMap; x += delta) {
69 | if (floor(x) % this.gridSize == 0) {
70 | /* while you find 1 x%this.gridSize==0
71 | => delta will equal this.gridSize => shorter loop */
72 | delta = this.gridSize;
73 | line(x, topMap, x, bottomMap);
74 | }
75 | }
76 |
77 | // do the same thing to y axis
78 | delta = 1;
79 | for (let y = topMap; y < bottomMap; y += delta) {
80 | if (floor(y) % this.gridSize == 0) {
81 | delta = this.gridSize;
82 | line(leftMap, y, rightMap, y);
83 | }
84 | }
85 | }
86 |
87 | getBound() {
88 | return {
89 | top: 0,
90 | bottom: this.height,
91 | left: 0,
92 | right: this.width,
93 | };
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/test/LOL2D-chatGPT/src/map/Camera.js:
--------------------------------------------------------------------------------
1 | export default class Camera {
2 | constructor({
3 | position = createVector(width / 2, height / 2),
4 | target = null, // target is a gameObject's position
5 | isFollow = true,
6 | followLerp = 0.1,
7 | scale = 1,
8 | scaleTo = 1,
9 | scaleLerp = 0.07,
10 | borderSize = 25,
11 | borderSpeed = 30,
12 | } = {}) {
13 | // default value
14 | this.position = position;
15 | this.target = target;
16 | this.isFollow = isFollow;
17 | this.followLerp = followLerp;
18 | this.scale = scale;
19 | this.scaleTo = scaleTo;
20 | this.scaleLerp = scaleLerp;
21 | this.borderSize = borderSize;
22 | this.borderSpeed = borderSpeed;
23 | }
24 |
25 | update() {
26 | // update scale
27 | this.scale = lerp(this.scale, this.scaleTo, this.scaleLerp);
28 |
29 | // follow target
30 | if (this.isFollow) {
31 | this.position = p5.Vector.lerp(
32 | this.position,
33 | this.target,
34 | this.followLerp
35 | );
36 | }
37 |
38 | // move camera on edge
39 | else if (this.isMouseOnEdge()) {
40 | let vec = createVector(
41 | mouseX - width * 0.5,
42 | mouseY - height * 0.5
43 | ).setMag(this.borderSpeed);
44 | this.position.add(vec);
45 | }
46 | }
47 |
48 | beginState() {
49 | push();
50 | translate(width * 0.5, height * 0.5);
51 | scale(this.scale);
52 | translate(-this.position.x, -this.position.y);
53 | }
54 |
55 | endState() {
56 | pop();
57 | }
58 |
59 | follow(target, immediately) {
60 | this.target = target;
61 |
62 | if (immediately) this.position.set(target.x, target.y);
63 | }
64 |
65 | getViewport() {
66 | let topLeftCanvas = this.canvasToWorld(0, 0);
67 | let bottomRightCanvas = this.canvasToWorld(width, height);
68 |
69 | return {
70 | x: topLeftCanvas.x,
71 | y: topLeftCanvas.y,
72 | w: bottomRightCanvas.x - topLeftCanvas.x,
73 | h: bottomRightCanvas.y - topLeftCanvas.y,
74 | };
75 | }
76 |
77 | canvasToWorld(canvasX, canvasY) {
78 | let worldX = (canvasX - width * 0.5) / this.scale + this.position.x;
79 | let worldY = (canvasY - height * 0.5) / this.scale + this.position.y;
80 |
81 | return createVector(worldX, worldY);
82 | }
83 |
84 | worldToCanvas(worldX, worldY) {
85 | let canvasX = (worldX - this.position.x) * this.scale + width * 0.5;
86 | let canvasY = (worldY - this.position.y) * this.scale + height * 0.5;
87 |
88 | return createVector(canvasX, canvasY);
89 | }
90 |
91 | isMouseOnEdge() {
92 | return (
93 | mouseX > width - this.borderSize ||
94 | mouseX < this.borderSize ||
95 | mouseY > height - this.borderSize ||
96 | mouseY < this.borderSize
97 | );
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/playzone/shader/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/playzone/quadtree/main.js:
--------------------------------------------------------------------------------
1 | let rects = [];
2 | let quadtree;
3 |
4 | let rectTest = [
5 | { x: 128, y: 521, w: 62, h: 77 },
6 | { x: 395, y: 397, w: 134, h: 106 },
7 | { x: 497, y: 563, w: 125, h: 94 },
8 | { x: 22, y: 466, w: 62, h: 56 },
9 | { x: 48, y: 515, w: 113, h: 32 },
10 | { x: 623, y: 364, w: 85, h: 131 },
11 | { x: 250, y: 211, w: 27, h: 20 },
12 | { x: 493, y: 29, w: 32, h: 73 },
13 | { x: 482, y: 541, w: 51, h: 60 },
14 | { x: 781, y: 561, w: 48, h: 38 },
15 | { x: 68, y: 47, w: 117, h: 113 },
16 | { x: 322, y: 70, w: 117, h: 81 },
17 | { x: 744, y: 222, w: 21, h: 98 },
18 | { x: 223, y: 365, w: 97, h: 81 },
19 | { x: 322, y: 101, w: 124, h: 79 },
20 | { x: 486, y: 127, w: 37, h: 57 },
21 | { x: 277, y: 157, w: 137, h: 128 },
22 | { x: 392, y: 407, w: 149, h: 149 },
23 | { x: 95, y: 44, w: 21, h: 130 },
24 | { x: 255, y: 433, w: 92, h: 14 },
25 | { x: 285, y: 293, w: 121, h: 42 },
26 | { x: 421, y: 268, w: 39, h: 89 },
27 | { x: 214, y: 428, w: 31, h: 123 },
28 | { x: 344, y: 281, w: 61, h: 122 },
29 | { x: 624, y: 342, w: 72, h: 117 },
30 | ];
31 |
32 | function setup() {
33 | createCanvas(800, 600);
34 |
35 | // generate rects
36 | // let i = 0;
37 | // while (i++ < 25) {
38 | // rects.push({
39 | // x: ~~random(width),
40 | // y: ~~random(height),
41 | // w: ~~random(10, 150),
42 | // h: ~~random(10, 150),
43 | // });
44 | // }
45 |
46 | rects = rectTest;
47 |
48 | // init quadtree
49 | quadtree = new Quadtree(
50 | {
51 | x: 0,
52 | y: 0,
53 | w: width,
54 | h: height,
55 | },
56 | 2
57 | );
58 |
59 | // add rects to quadtree
60 | for (let r of rects) {
61 | quadtree.insert({
62 | x: r.x,
63 | y: r.y,
64 | w: r.w,
65 | h: r.h,
66 | ref: r, // reference to rect object
67 | });
68 | }
69 | }
70 |
71 | function draw() {
72 | background(30);
73 |
74 | // draw grid
75 | drawQuadtree(quadtree);
76 |
77 | // draw rects
78 | for (let r of rects) {
79 | fill("yellow");
80 | noStroke();
81 | circle(r.x, r.y, 10);
82 |
83 | fill("#9995");
84 | stroke("white");
85 | rect(r.x, r.y, r.w, r.h);
86 | }
87 |
88 | // get rect near mouse
89 | let range = {
90 | x: mouseX,
91 | y: mouseY,
92 | w: 20,
93 | h: 20,
94 | };
95 | let data = quadtree.retrieve(range);
96 |
97 | // hight light rects near mouse
98 | fill("white");
99 | for (let r of data) {
100 | rect(r.x, r.y, r.w, r.h);
101 | }
102 |
103 | // show mouse
104 | noFill();
105 | stroke("white");
106 | rect(range.x, range.y, range.w, range.h);
107 | }
108 |
109 | function drawQuadtree(node) {
110 | var bounds = node.bounds;
111 |
112 | //no subnodes? draw the current node
113 | if (node.nodes.length === 0) {
114 | stroke("#f003");
115 | noFill();
116 | strokeWeight(1);
117 | rect(bounds.x, bounds.y, bounds.w, bounds.h);
118 |
119 | //has subnodes? drawQuadtree them!
120 | } else {
121 | for (var i = 0; i < node.nodes.length; i++) {
122 | this.drawQuadtree(node.nodes[i]);
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/playzone/sight/main.js:
--------------------------------------------------------------------------------
1 | // live preview: https://editor.p5js.org/HoangTran0410/sketches/7Dlqz7z77
2 |
3 | let overlay;
4 | let overlayColor = "#000e";
5 | let groundColor = "#1af";
6 | let champColor = "blue";
7 | let fovRadius = 250;
8 | let useBlendMode = false;
9 | let things = [];
10 |
11 | function setup() {
12 | createCanvas(600, 600);
13 | overlay = createGraphics(600, 600);
14 | overlay.noStroke();
15 |
16 | angleMode(DEGREES);
17 |
18 | for (let i = 0; i < 15; i++) {
19 | things.push({
20 | pos: createVector(random(width), random(height)),
21 | vel: createVector(random(-3, 3), random(-3, 3)),
22 | color: [random(255), random(255), random(255)],
23 | r: random(10, 50),
24 | });
25 | }
26 | }
27 |
28 | function draw() {
29 | if (useBlendMode) {
30 | drawUseBlendMode();
31 | } else {
32 | drawUseErase();
33 | }
34 | }
35 |
36 | function mousePressed() {
37 | useBlendMode = !useBlendMode;
38 | }
39 |
40 | // ---------------- ERASE -----------------
41 | function drawUseErase() {
42 | // draw ground and things
43 | background(groundColor);
44 | drawThings();
45 |
46 | // clear overlay with overlay color
47 | overlay.clear();
48 | overlay.background(overlayColor);
49 |
50 | // magic here
51 | fovUsingErase(mouseX, mouseY, fovRadius);
52 | fovUsingErase(width * 0.5, height * 0.5, fovRadius);
53 |
54 | // show overlay on top of ground
55 | image(overlay, 0, 0);
56 |
57 | // show fps
58 | fill("white");
59 | text("click to switch mode", 10, height - 15);
60 | text("FPS: " + ~~frameRate() + " - ERASE", 10, 15);
61 | }
62 |
63 | function fovUsingErase(x, y, d) {
64 | overlay.erase();
65 | overlay.fill(255);
66 |
67 | radialGradient(x, y, d * 0.5 - 50, d * 0.5, "#FFF", "#0001");
68 | overlay.ellipse(x, y, d);
69 | overlay.noErase();
70 | }
71 |
72 | // ---------------- BLEND MODE -----------------
73 | function drawUseBlendMode() {
74 | // draw ground and things
75 | background(groundColor);
76 | drawThings();
77 |
78 | // clear overlay with overlay color
79 | overlay.clear();
80 | overlay.blendMode(BLEND);
81 | overlay.background(overlayColor);
82 |
83 | // magic here
84 | fovUsingBlendMode(mouseX, mouseY, fovRadius);
85 | fovUsingBlendMode(width * 0.5, height * 0.5, fovRadius);
86 |
87 | // show overlay on top of ground
88 | image(overlay, 0, 0);
89 |
90 | // show fps
91 | fill("white");
92 | text("click to switch mode", 10, height - 15);
93 | text("FPS: " + ~~frameRate() + " - BLEND MODE", 10, 15);
94 | }
95 |
96 | function fovUsingBlendMode(x, y, d) {
97 | overlay.blendMode(REMOVE);
98 | //overlay.fill(255);
99 | radialGradient(x, y, d * 0.5 - 50, d * 0.5, "#FFF", "#0001");
100 | overlay.ellipse(x, y, d);
101 | overlay.blendMode(BLEND);
102 | }
103 |
104 | // -------------- HELPER ---------------
105 | function radialGradient(x, y, r1, r2, c1, c2) {
106 | let grd = overlay.drawingContext.createRadialGradient(x, y, r1, x, y, r2);
107 | grd.addColorStop(0, c1);
108 | grd.addColorStop(1, c2);
109 | overlay.drawingContext.fillStyle = grd;
110 | }
111 |
112 | function drawThings() {
113 | stroke(30);
114 | strokeWeight(2);
115 |
116 | for (let t of things) {
117 | fill(t.color);
118 | ellipse(t.pos.x, t.pos.y, t.r * 2);
119 |
120 | t.pos.add(t.vel);
121 |
122 | if (t.pos.x < 0 || t.pos.x > width) t.vel.x *= -1;
123 | if (t.pos.y < 0 || t.pos.y > height) t.vel.y *= -1;
124 |
125 | t.pos.x = constrain(t.pos.x, 0, width);
126 | t.pos.y = constrain(t.pos.y, 0, height);
127 | }
128 | }
129 |
130 | // -------------- TEST ------------------
131 | // overlay.fill(255, 50);
132 | // overlay.ellipse(x, y, d);
133 | // overlay.ellipse(x, y, d / 1.25);
134 | // overlay.ellipse(x, y, d / 1.5);
135 | // overlay.ellipse(x, y, d / 1.75);
136 | // overlay.ellipse(x, y, d * 0.5);
137 |
--------------------------------------------------------------------------------
/temp/gameCore/gameObjects/attackableUnits/Champion.js:
--------------------------------------------------------------------------------
1 | import { HasFlag } from "../../utils/Helpers.js";
2 | import StatusFlags from "../../../enums/StatusFlags.js";
3 | import TeamID from "../../../enums/TeamID.js";
4 | import AssetManager from "../../../AssetManager.js";
5 | import GameObject from "../GameObject.js";
6 | import Stats from "../stats/Stats.js";
7 |
8 | export default class Champion extends GameObject {
9 | constructor(
10 | game,
11 | model = AssetManager.getAsset(
12 | "asset/image/champion/ahri/Ahri.avatar.circle.png"
13 | ),
14 | stats = new Stats(),
15 | position = createVector(),
16 | collisionRadius = 40,
17 | visionRadius = 200,
18 | teamId = TeamID.TEAM_BLUE
19 | ) {
20 | super(game, position, collisionRadius, visionRadius, teamId);
21 |
22 | this.stats = stats;
23 | this.model = model;
24 | this.buffs = [];
25 | this.wayPoints = [];
26 |
27 | this.status =
28 | StatusFlags.CanAttack |
29 | StatusFlags.CanCast |
30 | StatusFlags.CanMove |
31 | StatusFlags.CanMoveEver;
32 | }
33 |
34 | update() {
35 | if (this.canMove()) {
36 | this.move();
37 | }
38 | }
39 |
40 | // override
41 | display() {
42 | image(
43 | this.model,
44 | this.position.x,
45 | this.position.y,
46 | this.collisionRadius * 2,
47 | this.collisionRadius * 2
48 | );
49 | }
50 |
51 | // Moves this unit to its specified waypoints, updating its position along the way.
52 | move() {}
53 |
54 | // Enables or disables the given status on this unit.
55 | setStatus(statusFlag, enabled) {
56 | if (enabled) this.status |= statusFlag;
57 | else this.status &= ~statusFlag;
58 | }
59 |
60 | isDead() {
61 | return this.stats.currentHealth <= 0;
62 | }
63 |
64 | canMove() {
65 | // TODO: Verify if Dashes should bypass this.
66 | return !(
67 | this.isDead() ||
68 | !(
69 | HasFlag(this.status, StatusFlags.CanMove) ||
70 | HasFlag(this.status, StatusFlags.CanMoveEver)
71 | ) ||
72 | HasFlag(this.status, StatusFlags.Immovable) ||
73 | HasFlag(this.status, StatusFlags.Netted) ||
74 | HasFlag(this.status, StatusFlags.Rooted) ||
75 | HasFlag(this.status, StatusFlags.Sleep) ||
76 | HasFlag(this.status, StatusFlags.Stunned) ||
77 | HasFlag(this.status, StatusFlags.Suppressed)
78 | );
79 | }
80 |
81 | canAttack() {
82 | // TODO: Verify if all cases are accounted for.
83 | return !(
84 | !HasFlag(this.status, StatusFlags.CanAttack) ||
85 | HasFlag(this.status, StatusFlags.Charmed) ||
86 | HasFlag(this.status, StatusFlags.Disarmed) ||
87 | HasFlag(this.status, StatusFlags.Feared) ||
88 | // TODO: Verify
89 | HasFlag(this.status, StatusFlags.Pacified) ||
90 | HasFlag(this.status, StatusFlags.Sleep) ||
91 | HasFlag(this.status, StatusFlags.Stunned) ||
92 | HasFlag(this.status, StatusFlags.Suppressed)
93 | );
94 | }
95 |
96 | canCast() {
97 | // TODO: Verify if all cases are accounted for.
98 | return !(
99 | !HasFlag(this.status, StatusFlags.CanCast) ||
100 | HasFlag(this.status, StatusFlags.Charmed) ||
101 | HasFlag(this.status, StatusFlags.Feared) ||
102 | // TODO: Verify
103 | HasFlag(this.status, StatusFlags.Pacified) ||
104 | HasFlag(this.status, StatusFlags.Silenced) ||
105 | HasFlag(this.status, StatusFlags.Sleep) ||
106 | HasFlag(this.status, StatusFlags.Stunned) ||
107 | HasFlag(this.status, StatusFlags.Suppressed) ||
108 | HasFlag(this.status, StatusFlags.Taunted)
109 | );
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/temp/gameCore/gameObjects/stats/Stats.js:
--------------------------------------------------------------------------------
1 | import Stat from "./Stat.js";
2 |
3 | export default class Stats {
4 | constructor() {
5 | //this.spellCostReduction = 0; // giảm sử dụng mana???
6 | //this.manaCost = []; // new float[64]() // idk
7 | this.isTargetable = true; // có thể chọn làm mục tiêu hay không
8 | this.actionState =
9 | ActionState.CAN_ATTACK |
10 | ActionState.CAN_CAST |
11 | ActionState.CAN_MOVE |
12 | ActionState.UNKNOWN;
13 |
14 | this.abilityPower = new Stat(); // sức mạnh phép thuật
15 | this.armor = new Stat(); // giáp
16 | this.attackDamage = new Stat(); // sức mạnh vật lý
17 | this.healthPoints = new Stat(); // máu
18 | this.magicResist = new Stat(); // kháng phép
19 | this.manaPoints = new Stat(); // năng lượng
20 | this.moveSpeed = new Stat(); // tốc độ di chuyển
21 | this.attackRange = new Stat(); // tầm đánh
22 | this.size = new Stat(1, 0, 0, 0, 0); // kích thước
23 |
24 | this.currentHealth = this.healthPoints.total(); // máu hiện tại
25 | this.currentMana = this.manaPoints.total(); // năng lượng hiện tại
26 |
27 | this.level = 1;
28 |
29 | // this.manaRegeneration = new Stat(); // hồi năng lượng
30 | // this.magicPenetration = new Stat(); // xuyên phép
31 | // this.healthRegeneration = new Stat(); // hồi máu
32 | // this.lifeSteal = new Stat(); // hút máu
33 | // this.armorPenetration = new Stat(); // xuyên giáp
34 | // this.attackSpeedMultiplier = new Stat(1, 0, 0, 0, 0); // % tốc đánh cộng thêm
35 | // this.cooldownReduction = new Stat(); // giảm thời gian hồi chiêu
36 | // this.criticalChance = new Stat(); // tỉ lệ chí mạng
37 | // this.criticalDamage = new Stat(2, 0, 0, 0, 0); // sát thương chí mạng
38 | // this.goldPerSecond = new Stat(); // vàng/giây
39 | // this.spellVamp = new Stat(); // giảm thời gian hồi chiêu khi đánh thường???
40 | // this.tenacity = new Stat(); // kháng làm chậm ???
41 | }
42 |
43 | addModifier(modifier) {
44 | this.abilityPower.ApplyStatModifier(modifier.abilityPower);
45 | this.armor.ApplyStatModifier(modifier.armor);
46 | this.attackDamage.ApplyStatModifier(modifier.attackDamage);
47 | this.healthPoints.ApplyStatModifier(modifier.healthPoints);
48 | this.magicResist.ApplyStatModifier(modifier.magicResist);
49 | this.manaPoints.ApplyStatModifier(modifier.manaPoints);
50 | this.moveSpeed.ApplyStatModifier(modifier.moveSpeed);
51 | this.attackRange.ApplyStatModifier(modifier.attackRange);
52 | this.size.ApplyStatModifier(modifier.size);
53 |
54 | // this.manaRegeneration.ApplyStatModifier(modifier.manaRegeneration);
55 | // this.magicPenetration.ApplyStatModifier(modifier.magicPenetration);
56 | // this.healthRegeneration.ApplyStatModifier(modifier.healthRegeneration);
57 | // this.lifeSteal.ApplyStatModifier(modifier.lifeSteal);
58 | // this.armorPenetration.ApplyStatModifier(modifier.armorPenetration);
59 | // this.attackSpeedMultiplier.ApplyStatModifier(modifier.attackSpeedMultiplier);
60 | // this.criticalChance.ApplyStatModifier(modifier.criticalChance);
61 | // this.criticalDamage.ApplyStatModifier(modifier.criticalDamage);
62 | // this.goldPerSecond.ApplyStatModifier(modifier.goldPerSecond);
63 | // this.spellVamp.ApplyStatModifier(modifier.spellVamp);
64 | // this.tenacity.ApplyStatModifier(modifier.tenacity);
65 | }
66 |
67 | removeModifier(modifier) {
68 | this.abilityPower.removeModifier(modifier.abilityPower);
69 | this.armor.removeModifier(modifier.armor);
70 | this.attackDamage.removeModifier(modifier.attackDamage);
71 | this.healthPoints.removeModifier(modifier.healthPoints);
72 | this.magicResist.removeModifier(modifier.magicResist);
73 | this.manaPoints.removeModifier(modifier.manaPoints);
74 | this.moveSpeed.removeModifier(modifier.moveSpeed);
75 | this.attackRange.removeModifier(modifier.attackRange);
76 | this.size.removeModifier(modifier.size);
77 |
78 | // this.manaRegeneration.removeModifier(modifier.manaRegeneration);
79 | // this.magicPenetration.removeModifier(modifier.magicPenetration);
80 | // this.healthRegeneration.removeModifier(modifier.healthRegeneration);
81 | // this.lifeSteal.removeModifier(modifier.lifeSteal);
82 | // this.armorPenetration.removeModifier(modifier.armorPenetration);
83 | // this.attackSpeedMultiplier.removeModifier(modifier.attackSpeedMultiplier);
84 | // this.criticalChance.removeModifier(modifier.criticalChance);
85 | // this.criticalDamage.removeModifier(modifier.criticalDamage);
86 | // this.goldPerSecond.removeModifier(modifier.goldPerSecond);
87 | // this.spellVamp.removeModifier(modifier.spellVamp);
88 | // this.tenacity.removeModifier(modifier.tenacity);
89 | }
90 |
91 | // update() {
92 | // // HealthRegeneration
93 | // // Generating Gold
94 | // // ManaRegeneration
95 | // }
96 |
97 | // levelUp() {
98 | // this.level++;
99 | // // TODO: upgrade stats
100 | // }
101 | }
102 |
--------------------------------------------------------------------------------
/lib/decomp.min.js:
--------------------------------------------------------------------------------
1 | !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.decomp=e()}}(function(){return function e(f,o,n){function d(t,l){if(!o[t]){if(!f[t]){var u="function"==typeof require&&require;if(!l&&u)return u(t,!0);if(i)return i(t,!0);throw new Error("Cannot find module '"+t+"'")}var p=o[t]={exports:{}};f[t][0].call(p.exports,function(e){var o=f[t][1][e];return d(o?o:e)},p,p.exports,e,f,o,n)}return o[t].exports}for(var i="function"==typeof require&&require,t=0;t=0&&1>=u&&p>=0&&1>=p}function i(e,f,o){return(f[0]-e[0])*(o[1]-e[1])-(o[0]-e[0])*(f[1]-e[1])}function t(e,f,o){return i(e,f,o)>0}function l(e,f,o){return i(e,f,o)>=0}function u(e,f,o){return i(e,f,o)<0}function p(e,f,o){return i(e,f,o)<=0}function s(e,f,o,n){if(n){var d=F,t=G;d[0]=f[0]-e[0],d[1]=f[1]-e[1],t[0]=o[0]-f[0],t[1]=o[1]-f[1];var l=d[0]*t[0]+d[1]*t[1],u=Math.sqrt(d[0]*d[0]+d[1]*d[1]),p=Math.sqrt(t[0]*t[0]+t[1]*t[1]),s=Math.acos(l/(u*p));return n>s}return 0===i(e,f,o)}function c(e,f){var o=f[0]-e[0],n=f[1]-e[1];return o*o+n*n}function y(e,f){var o=e.length;return e[0>f?f%o+o:f%o]}function a(e){e.length=0}function m(e,f,o,n){for(var d=o;n>d;d++)e.push(f[d])}function r(e){for(var f=0,o=e,n=1;no[f][0])&&(f=n);return t(y(e,f-1),y(e,f),y(e,f+1))?!1:(w(e),!0)}function w(e){for(var f=[],o=e.length,n=0;n!==o;n++)f.push(e.pop());for(var n=0;n!==o;n++)e[n]=f[n]}function b(e,f){return u(y(e,f-1),y(e,f),y(e,f+1))}function g(e,f,o){var d,i,t=H,u=I;if(l(y(e,f+1),y(e,f),y(e,o))&&p(y(e,f-1),y(e,f),y(e,o)))return!1;i=c(y(e,f),y(e,o));for(var s=0;s!==e.length;++s)if((s+1)%e.length!==f&&s!==f&&l(y(e,f),y(e,o),y(e,s+1))&&p(y(e,f),y(e,o),y(e,s))&&(t[0]=y(e,f),t[1]=y(e,o),u[0]=y(e,s),u[1]=y(e,s+1),d=n(t,u),c(y(e,f),d)f)for(var i=f;o>=i;i++)d.push(e[i]);else{for(var i=0;o>=i;i++)d.push(e[i]);for(var i=f;i0?k(e,f):[e]}function k(e,f){if(0===f.length)return[e];if(f instanceof Array&&f.length&&f[0]instanceof Array&&2===f[0].length&&f[0][0]instanceof Array){for(var o=[e],n=0;nn;n++)if(d(o[f],o[f+1],o[n],o[n+1]))return!1;for(f=1;fi)return console.warn("quickDecomp: max level ("+i+") reached."),f;for(var G=0;Gv&&(j=v,r=w,q=H))),t(y(E,G+1),y(E,G),y(E,H+1))&&p(y(E,G+1),y(E,G),y(E,H))&&(w=z(y(E,G+1),y(E,G),y(E,H),y(E,H+1)),t(y(E,G-1),y(E,G),w)&&(v=c(E[G],w),g>v&&(g=v,a=w,k=H)));if(q===(k+1)%e.length)w[0]=(r[0]+a[0])/2,w[1]=(r[1]+a[1])/2,n.push(w),k>G?(m(C,E,G,k+1),C.push(w),D.push(w),0!==q&&m(D,E,q,E.length),m(D,E,0,G+1)):(0!==G&&m(C,E,G,E.length),m(C,E,0,k+1),C.push(w),D.push(w),m(D,E,q,G+1));else{if(q>k&&(k+=e.length),h=Number.MAX_VALUE,q>k)return f;for(var H=q;k>=H;++H)l(y(E,G-1),y(E,G),y(E,H))&&p(y(E,G+1),y(E,G),y(E,H))&&(v=c(y(E,G),y(E,H)),h>v&&x(E,G,H)&&(h=v,B=H%e.length));B>G?(m(C,E,G,B+1),0!==B&&m(D,E,B,F.length),m(D,E,0,G+1)):(0!==G&&m(C,E,G,F.length),m(C,E,0,B+1),m(D,E,B,G+1))}return C.length3&&n>=0;--n)s(y(e,n-1),y(e,n),y(e,n+1),f)&&(e.splice(n%e.length,1),o++);return o}function C(e,f){for(var o=e.length-1;o>=1;--o)for(var n=e[o],d=o-1;d>=0;--d)E(n,e[d],f)&&e.splice(o,1)}function D(e,f,o){return o=o||0,Math.abs(e-f)<=o}function E(e,f,o){return D(e[0],f[0],o)&&D(e[1],f[1],o)}f.exports={decomp:h,quickDecomp:A,isSimple:q,removeCollinearPoints:B,removeDuplicatePoints:C,makeCCW:r};var F=[],G=[],H=[],I=[]},{}]},{},[1])(1)});
--------------------------------------------------------------------------------
/lib/stats.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author mrdoob / http://mrdoob.com/
3 | */
4 |
5 | var Stats = function () {
6 | var mode = 0;
7 |
8 | var container = document.createElement("div");
9 | container.style.cssText =
10 | "position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000";
11 | container.addEventListener(
12 | "click",
13 | function (event) {
14 | event.preventDefault();
15 | showPanel(++mode % container.children.length);
16 | },
17 | false
18 | );
19 |
20 | //
21 |
22 | function addPanel(panel) {
23 | container.appendChild(panel.dom);
24 | return panel;
25 | }
26 |
27 | function showPanel(id) {
28 | for (var i = 0; i < container.children.length; i++) {
29 | container.children[i].style.display = i === id ? "block" : "none";
30 | }
31 |
32 | mode = id;
33 | }
34 |
35 | //
36 |
37 | var beginTime = (performance || Date).now(),
38 | prevTime = beginTime,
39 | frames = 0;
40 |
41 | var fpsPanel = addPanel(new Stats.Panel("FPS", "#0ff", "#002"));
42 | var msPanel = addPanel(new Stats.Panel("MS", "#0f0", "#020"));
43 |
44 | if (self.performance && self.performance.memory) {
45 | var memPanel = addPanel(new Stats.Panel("MB", "#f08", "#201"));
46 | }
47 |
48 | showPanel(0);
49 |
50 | return {
51 | REVISION: 16,
52 |
53 | dom: container,
54 |
55 | addPanel: addPanel,
56 | showPanel: showPanel,
57 |
58 | begin: function () {
59 | beginTime = (performance || Date).now();
60 | },
61 |
62 | end: function () {
63 | frames++;
64 |
65 | var time = (performance || Date).now();
66 |
67 | msPanel.update(time - beginTime, 200);
68 |
69 | if (time >= prevTime + 1000) {
70 | fpsPanel.update((frames * 1000) / (time - prevTime), 100);
71 |
72 | prevTime = time;
73 | frames = 0;
74 |
75 | if (memPanel) {
76 | var memory = performance.memory;
77 | memPanel.update(
78 | memory.usedJSHeapSize / 1048576,
79 | memory.jsHeapSizeLimit / 1048576
80 | );
81 | }
82 | }
83 |
84 | return time;
85 | },
86 |
87 | update: function () {
88 | beginTime = this.end();
89 | },
90 |
91 | // Backwards Compatibility
92 |
93 | domElement: container,
94 | setMode: showPanel,
95 | };
96 | };
97 |
98 | Stats.Panel = function (name, fg, bg) {
99 | var min = Infinity,
100 | max = 0,
101 | round = Math.round;
102 | var PR = round(window.devicePixelRatio || 1);
103 |
104 | var WIDTH = 80 * PR,
105 | HEIGHT = 48 * PR,
106 | TEXT_X = 3 * PR,
107 | TEXT_Y = 2 * PR,
108 | GRAPH_X = 3 * PR,
109 | GRAPH_Y = 15 * PR,
110 | GRAPH_WIDTH = 74 * PR,
111 | GRAPH_HEIGHT = 30 * PR;
112 |
113 | var canvas = document.createElement("canvas");
114 | canvas.width = WIDTH;
115 | canvas.height = HEIGHT;
116 | canvas.style.cssText = "width:80px;height:48px";
117 |
118 | var context = canvas.getContext("2d");
119 | context.font = "bold " + 9 * PR + "px Helvetica,Arial,sans-serif";
120 | context.textBaseline = "top";
121 |
122 | context.fillStyle = bg;
123 | context.fillRect(0, 0, WIDTH, HEIGHT);
124 |
125 | context.fillStyle = fg;
126 | context.fillText(name, TEXT_X, TEXT_Y);
127 | context.fillRect(GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT);
128 |
129 | context.fillStyle = bg;
130 | context.globalAlpha = 0.9;
131 | context.fillRect(GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT);
132 |
133 | return {
134 | dom: canvas,
135 |
136 | update: function (value, maxValue) {
137 | min = Math.min(min, value);
138 | max = Math.max(max, value);
139 |
140 | context.fillStyle = bg;
141 | context.globalAlpha = 1;
142 | context.fillRect(0, 0, WIDTH, GRAPH_Y);
143 | context.fillStyle = fg;
144 | context.fillText(
145 | round(value) +
146 | " " +
147 | name +
148 | " (" +
149 | round(min) +
150 | "-" +
151 | round(max) +
152 | ")",
153 | TEXT_X,
154 | TEXT_Y
155 | );
156 |
157 | context.drawImage(
158 | canvas,
159 | GRAPH_X + PR,
160 | GRAPH_Y,
161 | GRAPH_WIDTH - PR,
162 | GRAPH_HEIGHT,
163 | GRAPH_X,
164 | GRAPH_Y,
165 | GRAPH_WIDTH - PR,
166 | GRAPH_HEIGHT
167 | );
168 |
169 | context.fillRect(
170 | GRAPH_X + GRAPH_WIDTH - PR,
171 | GRAPH_Y,
172 | PR,
173 | GRAPH_HEIGHT
174 | );
175 |
176 | context.fillStyle = bg;
177 | context.globalAlpha = 0.9;
178 | context.fillRect(
179 | GRAPH_X + GRAPH_WIDTH - PR,
180 | GRAPH_Y,
181 | PR,
182 | round((1 - value / maxValue) * GRAPH_HEIGHT)
183 | );
184 | },
185 | };
186 | };
187 |
188 | export default Stats;
189 |
--------------------------------------------------------------------------------
/css/hextech-css/hextech.min.css:
--------------------------------------------------------------------------------
1 | /*! hextech-css | MIT License | github.com/pxlucasf/hextech-css */@font-face{font-family:'Beaufort';src:url('fonts/Beaufort-Regular.woff') format('woff'),url('fonts/Beaufort-Regular.ttf') format('truetype')}@font-face{font-family:'Beaufort';src:url('fonts/Beaufort-Bold.woff') format('woff'),url('fonts/Beaufort-Bold.ttf') format('truetype');font-weight:bold}@font-face{font-family:'Spiegel';src:url('fonts/Spiegel-Regular.woff') format('woff'),url('fonts/Spiegel-Regular.ttf') format('truetype')}@font-face{font-family:'Spiegel';src:url('fonts/Spiegel-Italic.woff') format('woff'),url('fonts/Spiegel-Italic.ttf') format('truetype');font-style:italic}html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}ul{list-style:none}button,input,select,textarea{margin:0}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}img,video{height:auto;max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:left}body{font-family:Spiegel}.row.is-mobile{display:flex}.row:not(:last-child){margin-bottom:calc(1.5rem - .75rem)}.row.is-multiline{flex-wrap:wrap}.column{display:flex;flex-direction:column;flex-basis:0;flex-grow:1;flex-shrink:1;padding:.75rem;box-sizing:border-box}.row.is-gapless .column{padding:0}@media screen and (max-width:768px){.column.is-1-mobile,.column.is-2-mobile,.column.is-3-mobile,.column.is-4-mobile,.column.is-5-mobile,.column.is-6-mobile,.column.is-7-mobile,.column.is-8-mobile,.column.is-9-mobile,.column.is-10-mobile,.column.is-11-mobile,.column.is-12-mobile{flex:none}.column.is-1-mobile{width:8.33333%}.column.is-2-mobile{width:16.66667%}.column.is-3-mobile{width:25%}.column.is-4-mobile{width:33.33333%}.column.is-5-mobile{width:41.66667%}.column.is-6-mobile{width:50%}.column.is-7-mobile{width:58.33333%}.column.is-8-mobile{width:66.66667%}.column.is-9-mobile{width:75%}.column.is-10-mobile{width:83.33333%}.column.is-11-mobile{width:91.66667%}.column.is-12-mobile{width:100%}}@media screen and (min-width:769px){.row{display:flex}.column.is-1,.column.is-2,.column.is-3,.column.is-4,.column.is-5,.column.is-6,.column.is-7,.column.is-8,.column.is-9,.column.is-10,.column.is-11,.column.is-12,.column.is-1-tablet,.column.is-2-tablet,.column.is-3-tablet,.column.is-4-tablet,.column.is-5-tablet,.column.is-6-tablet,.column.is-7-tablet,.column.is-8-tablet,.column.is-9-tablet,.column.is-10-tablet,.column.is-11-tablet,.column.is-12-tablet{flex:none}.column.is-1,.column.is-1-tablet{width:8.33333%}.column.is-2,.column.is-2-tablet{width:16.66667%}.column.is-3,.column.is-3-tablet{width:25%}.column.is-4,.column.is-4-tablet{width:33.33333%}.column.is-5,.column.is-5-tablet{width:41.66667%}.column.is-6,.column.is-6-tablet{width:50%}.column.is-7,.column.is-7-tablet{width:58.33333%}.column.is-8,.column.is-8-tablet{width:66.66667%}.column.is-9,.column.is-9-tablet{width:75%}.column.is-10,.column.is-10-tablet{width:83.33333%}.column.is-11,.column.is-11-tablet{width:91.66667%}.column.is-12,.column.is-12-tablet{width:100%}}@media screen and (min-width:1024px){.column.is-1-desktop,.column.is-2-desktop,.column.is-3-desktop,.column.is-4-desktop,.column.is-5-desktop,.column.is-6-desktop,.column.is-7-desktop,.column.is-8-desktop,.column.is-9-desktop,.column.is-10-desktop,.column.is-11-desktop,.column.is-12-desktop{flex:none}.column.is-1-desktop{width:8.33333%}.column.is-2-desktop{width:16.66667%}.column.is-3-desktop{width:25%}.column.is-4-desktop{width:33.33333%}.column.is-5-desktop{width:41.66667%}.column.is-6-desktop{width:50%}.column.is-7-desktop{width:58.33333%}.column.is-8-desktop{width:66.66667%}.column.is-9-desktop{width:75%}.column.is-10-desktop{width:83.33333%}.column.is-11-desktop{width:91.66667%}.column.is-12-desktop{width:100%}}button:focus{outline:0}.button{font-family:'Beaufort';text-transform:uppercase;font-size:18px;color:#f0e6d2;padding:.75rem 2rem}.button.is-tiny{font-size:16px;padding:.375rem 2rem;border-width:2px!important}.button[disabled]{border-image:linear-gradient(#4c5155,#4c5155) 1!important;background:#1f242a!important;color:#4c5155!important}.button.is-primary{border:3px solid transparent;background:#1e2328;border-image:linear-gradient(#08abac,#01698b) 1;transition:all ease .5s}.button.is-primary:not([disabled]):hover{background-image:url(img/btn.jpg);background-position:center center;background-size:cover;box-shadow:0 0 10px 4px rgba(192,252,253,.4),inset 0 0 5px 2px rgba(192,252,253,.3);border:3px solid rgba(192,252,253,.75);cursor:pointer}.button.is-secondary{border:3px solid;border-radius:0;background:#242731;border-image:linear-gradient(#f6c97f,#ca9d4b) 1;transition:all ease .25s}.button.is-secondary:not([disabled]):hover{box-shadow:0 0 5px 2px rgba(192,252,253,.4),inset 0 0 5px 2px rgba(192,252,253,.3);border:3px solid #eee2cc;cursor:pointer}.arrow-button{display:inline-flex;position:relative;background-color:#000a17;padding:5px;border:1px solid #c8a763;border-top-left-radius:25px;border-bottom-left-radius:25px}.arrow-button::before{content:'';position:absolute;top:5px;right:5px;height:32px;width:32px;box-sizing:border-box;border:2px solid #05222d}.arrow-button .main{shape-outside:polygon(0 0,calc(100% - 20px) 0,100% 50%,calc(100% - 20px) 100%,0% 100%);clip-path:polygon(0 0,calc(100% - 15px) 0,100% 50%,calc(100% - 15px) 100%,0% 100%);background:linear-gradient(#018699,#006284);height:32px;min-width:150px;cursor:pointer;border:0;font-family:'Beaufort';font-weight:bold;font-size:16px;color:#a3c0c0;text-transform:uppercase;position:relative;margin-left:-16px;padding:0 48px}.arrow-button .main::before{content:'';position:absolute;top:0;left:0;shape-outside:polygon(2px 2px,calc(100% - 22px) 2px,calc(100% - 4px) 50%,calc(100% - 22px) calc(100% - 2px),2px calc(100% - 2px));clip-path:polygon(2px 2px,calc(100% - 16px) 2px,calc(100% - 3px) 50%,calc(100% - 16px) calc(100% - 2px),2px calc(100% - 2px));background-color:#1e222c;height:32px;width:100%;z-index:-1}.arrow-button .main::after{content:'';position:absolute;top:-7px;left:-23px;height:42px;width:42px;box-sizing:content-box;border-radius:50%;border:2px solid transparent;background:linear-gradient(#000a17,#000a17) padding-box,linear-gradient(#018699,#006284) border-box}.arrow-button .circle{height:32px;width:32px;border-radius:50%;border:2px solid transparent;background:linear-gradient(#202425,#202425) padding-box,linear-gradient(#c8a763,#715b29) border-box;color:#c5c09a;cursor:pointer;z-index:1}.arrow-button:not(.is-disabled) .main:hover{background:linear-gradient(#83d7ca,#1f8faf);color:#e2e2d8}.arrow-button:not(.is-disabled) .main:hover::before{background:linear-gradient(#152932,#0d394a)}.arrow-button:not(.is-disabled) .main:hover::after{background:linear-gradient(#000a17,#000a17) padding-box,linear-gradient(#83d7ca,#1f8faf) border-box}.arrow-button:not(.is-disabled) .circle:hover{background:linear-gradient(#202425,#202425) padding-box,linear-gradient(#d4cdca,#a37b2e) border-box;color:#f4eada}.arrow-button.is-disabled .main{background:#4c5155;color:#4c5155}.arrow-button.is-disabled .main::before{background:#1f242a}.arrow-button.is-disabled .main::after{background:linear-gradient(#000a17,#000a17) padding-box,linear-gradient(#4c5155,#4c5155) border-box}.arrow-button.is-disabled .circle{background:linear-gradient(#1f242a,#1f242a) padding-box,linear-gradient(#4c5155,#4c5155) border-box;color:#4c5155}
--------------------------------------------------------------------------------
/src/managers/SceneManager.js:
--------------------------------------------------------------------------------
1 | // original source: Marian Veteanu - https://github.com/mveteanu/p5.SceneManager
2 | // modified by Hoang Tran
3 |
4 | const P5Events = [
5 | "mouseClicked",
6 | "mousePressed",
7 | "mouseReleased",
8 | "mouseMoved",
9 | "mouseDragged",
10 | "doubleClicked",
11 | "mouseWheel",
12 | "keyPressed",
13 | "keyReleased",
14 | "keyTyped",
15 | "touchStarted",
16 | "touchMoved",
17 | "touchEnded",
18 | "deviceMoved",
19 | "deviceTurned",
20 | "deviceShaken",
21 | ];
22 |
23 | export class Scene {
24 | // inject sceneManager and p5_instant as a property of the scene
25 | constructor(sceneManager, p5) {
26 | /** @type SceneManager */
27 | this.sceneManager = sceneManager;
28 | this.p5 = p5;
29 | }
30 |
31 | /**
32 | * Được gọi khi scene được khởi tạo, chỉ gọi 1 lần.
33 | * Được dùng để khởi tạo các giá trị ban đầu cho scene
34 | */
35 | setup() {}
36 |
37 | /**
38 | * Được gọi khi scene được hiển thị (SceneManager.showScene).
39 | * Có thể được gọi nhiều lần, mỗi khi sceneManager chuyển tới scene này
40 | */
41 | enter() {}
42 |
43 | /**
44 | * Được gọi liên tục (max là 60 lần/s tương ứng 60fps).
45 | * Vòng lặp game sẽ được cho vào trong hàm này
46 | */
47 | draw() {}
48 |
49 | /**
50 | * Được gọi khi sceneManager đang từ scene này chuyển qua scene mới
51 | */
52 | exit() {}
53 |
54 | // p5 events
55 | mouseClicked() {}
56 | mousePressed() {}
57 | mouseReleased() {}
58 | mouseMoved() {}
59 | mouseDragged() {}
60 | doubleClicked() {}
61 | mouseWheel(e) {}
62 | keyPressed() {}
63 | keyReleased() {}
64 | keyTyped() {}
65 | touchStarted() {}
66 | touchMoved() {}
67 | touchEnded() {}
68 | deviceMoved() {}
69 | deviceTurned() {}
70 | deviceShaken() {}
71 | }
72 |
73 | export default class SceneManager {
74 | constructor(p5) {
75 | this.scenes = [];
76 | this.scene = null;
77 | this.p5 = p5;
78 | }
79 |
80 | // Wire relevant p5.js events, except setup()
81 | // If you don't call this method, you need to manually wire events
82 | wire() {
83 | let me = this;
84 | let p5 = this.p5 != null ? this.p5 : window;
85 |
86 | // Wire draw manually for speed reasons...
87 | p5.draw = function () {
88 | me.draw();
89 | };
90 |
91 | // This loop will wire automatically all P5 events to each scene like this:
92 | // p5.mouseClicked = function() { me.handleEvent("mouseClicked"); }
93 | for (let i = 0; i < P5Events.length; i++) {
94 | let sEvent = P5Events[i]; // let is necesary to set the scope at the level of for
95 | p5[sEvent] = function () {
96 | // https://github.com/mveteanu/p5.SceneManager/pull/8/commits
97 | me.handleEvent(sEvent, [].slice.call(arguments));
98 | };
99 | }
100 |
101 | return me;
102 | }
103 |
104 | // Add a scene to the collection
105 | // You need to add all the scenes if intend to call .showNextScene()
106 | addScene(fnScene) {
107 | let oScene = new fnScene(this, this.p5);
108 |
109 | // create scene container
110 | var o = {
111 | fnScene: fnScene,
112 | oScene: oScene,
113 | hasSetup: "setup" in oScene,
114 | hasEnter: "enter" in oScene,
115 | hasDraw: "draw" in oScene,
116 | hasExit: "exit" in oScene,
117 | };
118 |
119 | // trigger setup event on scene
120 | if (o.hasSetup) o.oScene.setup();
121 |
122 | // add scene container to array scenes
123 | this.scenes.push(o);
124 | return o;
125 | }
126 |
127 | // Return the index of a scene in the internal collection
128 | findSceneIndex(fnScene) {
129 | for (let i = 0; i < this.scenes.length; i++) {
130 | let o = this.scenes[i];
131 | if (o.fnScene == fnScene) return i;
132 | }
133 |
134 | return -1;
135 | }
136 |
137 | // Return a scene object wrapper
138 | findScene(fnScene) {
139 | let i = this.findSceneIndex(fnScene);
140 | return i >= 0 ? this.scenes[i] : null;
141 | }
142 |
143 | // Returns true if the current displayed scene is fnScene
144 | isCurrent(fnScene) {
145 | if (this.scene == null) return false;
146 | return this.scene.fnScene == fnScene;
147 | }
148 |
149 | // Show a scene based on the function name
150 | // Optionally you can send arguments to the scene
151 | // Arguments will be retrieved in the scene via .sceneArgs property
152 | showScene(fnScene, sceneArgs) {
153 | let o = this.findScene(fnScene);
154 |
155 | if (o == null) o = this.addScene(fnScene);
156 |
157 | // trigger exit event on current scene
158 | if (this.scene != null && this.scene.hasExit) this.scene.oScene.exit();
159 |
160 | // switch scene
161 | this.scene = o;
162 |
163 | // inject sceneArgs as a property of the scene
164 | o.oScene.sceneArgs = sceneArgs;
165 |
166 | // trigger enter event on new scene
167 | if (o.hasEnter) o.oScene.enter();
168 | }
169 |
170 | // Show the next scene in the collection
171 | // Useful if implementing demo applications
172 | // where you want to advance scenes automatically
173 | showNextScene(sceneArgs) {
174 | if (this.scenes.length == 0) return;
175 |
176 | let nextSceneIndex = 0;
177 |
178 | if (this.scene != null) {
179 | // search current scene...
180 | // can be optimized to avoid searching current scene...
181 | let i = this.findSceneIndex(this.scene.fnScene);
182 | nextSceneIndex = i < this.scenes.length - 1 ? i + 1 : 0;
183 | }
184 |
185 | let nextScene = this.scenes[nextSceneIndex];
186 | this.showScene(nextScene.fnScene, sceneArgs);
187 | }
188 |
189 | // This is the SceneManager .draw() method
190 | // This will dispatch the main draw() to the
191 | // current scene draw() method
192 | draw() {
193 | // take the current scene in a variable to protect it in case
194 | // it gets changed by the user code in the events such as setup()...
195 | let currScene = this.scene;
196 | if (currScene == null) return;
197 |
198 | if (currScene.hasDraw) currScene.oScene.draw();
199 | }
200 |
201 | // Handle a certain even for a scene...
202 | // It is used by the anonymous functions from the wire() function
203 | handleEvent(sEvent, args) {
204 | if (this.scene == null || this.scene.oScene == null) return;
205 |
206 | let fnSceneEvent = this.scene.oScene[sEvent];
207 | if (fnSceneEvent) fnSceneEvent.apply(this.scene.oScene, args);
208 | }
209 |
210 | // Legacy method... preserved for maintaining compatibility
211 | mousePressed() {
212 | this.handleEvent("mousePressed");
213 | }
214 |
215 | // Legacy method... preserved for maintaining compatibility
216 | keyPressed() {
217 | this.handleEvent("keyPressed");
218 | }
219 | }
220 |
--------------------------------------------------------------------------------
/lib/state-machine.min.js:
--------------------------------------------------------------------------------
1 | // https://github.com/jakesgordon/javascript-state-machine
2 | !function(t,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define("StateMachine",[],n):"object"==typeof exports?exports.StateMachine=n():t.StateMachine=n()}(this,function(){return function(t){function n(e){if(i[e])return i[e].exports;var s=i[e]={i:e,l:!1,exports:{}};return t[e].call(s.exports,s,s.exports,n),s.l=!0,s.exports}var i={};return n.m=t,n.c=i,n.i=function(t){return t},n.d=function(t,i,e){n.o(t,i)||Object.defineProperty(t,i,{configurable:!1,enumerable:!0,get:e})},n.n=function(t){var i=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(i,"a",i),i},n.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},n.p="",n(n.s=5)}([function(t,n,i){"use strict";t.exports=function(t,n){var i,e,s;for(i=1;i=0:this.state===t},isPending:function(){return this.pending},can:function(t){return!this.isPending()&&!!this.seek(t)},cannot:function(t){return!this.can(t)},allStates:function(){return this.config.allStates()},allTransitions:function(){return this.config.allTransitions()},transitions:function(){return this.config.transitionsFor(this.state)},seek:function(t,n){var i=this.config.defaults.wildcard,e=this.config.transitionFor(this.state,t),s=e&&e.to;return"function"==typeof s?s.apply(this.context,n):s===i?this.state:s},fire:function(t,n){return this.transit(t,this.state,this.seek(t,n),n)},transit:function(t,n,i,e){var s=this.config.lifecycle,r=this.config.options.observeUnchangedState||n!==i;return i?this.isPending()?this.context.onPendingTransition(t,n,i):(this.config.addState(i),this.beginTransit(),e.unshift({transition:t,from:n,to:i,fsm:this.context}),this.observeEvents([this.observersForEvent(s.onBefore.transition),this.observersForEvent(s.onBefore[t]),r?this.observersForEvent(s.onLeave.state):a,r?this.observersForEvent(s.onLeave[n]):a,this.observersForEvent(s.on.transition),r?["doTransit",[this]]:a,r?this.observersForEvent(s.onEnter.state):a,r?this.observersForEvent(s.onEnter[i]):a,r?this.observersForEvent(s.on[i]):a,this.observersForEvent(s.onAfter.transition),this.observersForEvent(s.onAfter[t]),this.observersForEvent(s.on[t])],e)):this.context.onInvalidTransition(t,n,i)},beginTransit:function(){this.pending=!0},endTransit:function(t){return this.pending=!1,t},failTransit:function(t){throw this.pending=!1,t},doTransit:function(t){this.state=t.to},observe:function(t){if(2===t.length){var n={};n[t[0]]=t[1],this.observers.push(n)}else this.observers.push(t[0])},observersForEvent:function(t){for(var n,i=0,e=this.observers.length,s=[];i verticalMidpoint,
114 | endIsSouth = pRect.y + pRect.w > horizontalMidpoint;
115 |
116 | //top-right quad
117 | if(startIsNorth && endIsEast) {
118 | indexes.push(0);
119 | }
120 |
121 | //top-left quad
122 | if(startIsWest && startIsNorth) {
123 | indexes.push(1);
124 | }
125 |
126 | //bottom-left quad
127 | if(startIsWest && endIsSouth) {
128 | indexes.push(2);
129 | }
130 |
131 | //bottom-right quad
132 | if(endIsEast && endIsSouth) {
133 | indexes.push(3);
134 | }
135 |
136 | return indexes;
137 | };
138 |
139 |
140 | /**
141 | * Insert the object into the node. If the node
142 | * exceeds the capacity, it will split and add all
143 | * objects to their corresponding subnodes.
144 | * @param Object pRect bounds of the object to be added { x, y, w, h }
145 | */
146 | Quadtree.prototype.insert = function(pRect) {
147 |
148 | var i = 0,
149 | indexes;
150 |
151 | //if we have subnodes, call insert on matching subnodes
152 | if(this.nodes.length) {
153 | indexes = this.getIndex(pRect);
154 |
155 | for(i=0; i this.max_objects && this.level < this.max_levels) {
166 |
167 | //split if we don't already have subnodes
168 | if(!this.nodes.length) {
169 | this.split();
170 | }
171 |
172 | //add all objects to their corresponding subnode
173 | for(i=0; i= index;
206 | });
207 |
208 | return returnObjects;
209 | };
210 |
211 |
212 | /**
213 | * Clear the quadtree
214 | */
215 | Quadtree.prototype.clear = function() {
216 |
217 | this.objects = [];
218 |
219 | for(var i=0; i < this.nodes.length; i++) {
220 | if(this.nodes.length) {
221 | this.nodes[i].clear();
222 | }
223 | }
224 |
225 | this.nodes = [];
226 | };
227 |
228 | //export for commonJS or browser
229 | if(typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
230 | module.exports = Quadtree;
231 | } else {
232 | window.Quadtree = Quadtree;
233 | }
234 |
235 | })();
--------------------------------------------------------------------------------
/lib/quadtree.js:
--------------------------------------------------------------------------------
1 | /**
2 | * quadtree-js
3 | * @version 1.2.3
4 | * @license MIT
5 | * @author Timo Hausmann
6 | */
7 |
8 | /* https://github.com/timohausmann/quadtree-js.git v1.2.3 */
9 |
10 | /*
11 | Copyright © 2012-2020 Timo Hausmann
12 |
13 | Permission is hereby granted, free of charge, to any person obtaining
14 | a copy of this software and associated documentation files (the
15 | "Software"), to deal in the Software without restriction, including
16 | without limitation the rights to use, copy, modify, merge, publish,
17 | distribute, sublicense, and/or sell copies of the Software, and to
18 | permit persons to whom the Software is furnished to do so, subject to
19 | the following conditions:
20 |
21 | The above copyright notice and this permission notice shall be
22 | included in all copies or substantial portions of the Software.
23 |
24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 | */
32 |
33 | ;(function() {
34 |
35 | /**
36 | * Quadtree Constructor
37 | * @param Object bounds bounds of the node { x, y, width, height }
38 | * @param Integer max_objects (optional) max objects a node can hold before splitting into 4 subnodes (default: 10)
39 | * @param Integer max_levels (optional) total max levels inside root Quadtree (default: 4)
40 | * @param Integer level (optional) depth level, required for subnodes (default: 0)
41 | */
42 | function Quadtree(bounds, max_objects, max_levels, level) {
43 |
44 | this.max_objects = max_objects || 10;
45 | this.max_levels = max_levels || 4;
46 |
47 | this.level = level || 0;
48 | this.bounds = bounds;
49 |
50 | this.objects = [];
51 | this.nodes = [];
52 | };
53 |
54 |
55 | /**
56 | * Split the node into 4 subnodes
57 | */
58 | Quadtree.prototype.split = function() {
59 |
60 | var nextLevel = this.level + 1,
61 | subWidth = this.bounds.width/2,
62 | subHeight = this.bounds.height/2,
63 | x = this.bounds.x,
64 | y = this.bounds.y;
65 |
66 | //top right node
67 | this.nodes[0] = new Quadtree({
68 | x : x + subWidth,
69 | y : y,
70 | width : subWidth,
71 | height : subHeight
72 | }, this.max_objects, this.max_levels, nextLevel);
73 |
74 | //top left node
75 | this.nodes[1] = new Quadtree({
76 | x : x,
77 | y : y,
78 | width : subWidth,
79 | height : subHeight
80 | }, this.max_objects, this.max_levels, nextLevel);
81 |
82 | //bottom left node
83 | this.nodes[2] = new Quadtree({
84 | x : x,
85 | y : y + subHeight,
86 | width : subWidth,
87 | height : subHeight
88 | }, this.max_objects, this.max_levels, nextLevel);
89 |
90 | //bottom right node
91 | this.nodes[3] = new Quadtree({
92 | x : x + subWidth,
93 | y : y + subHeight,
94 | width : subWidth,
95 | height : subHeight
96 | }, this.max_objects, this.max_levels, nextLevel);
97 | };
98 |
99 |
100 | /**
101 | * Determine which node the object belongs to
102 | * @param Object pRect bounds of the area to be checked, with x, y, width, height
103 | * @return Array an array of indexes of the intersecting subnodes
104 | * (0-3 = top-right, top-left, bottom-left, bottom-right / ne, nw, sw, se)
105 | */
106 | Quadtree.prototype.getIndex = function(pRect) {
107 |
108 | var indexes = [],
109 | verticalMidpoint = this.bounds.x + (this.bounds.width/2),
110 | horizontalMidpoint = this.bounds.y + (this.bounds.height/2);
111 |
112 | var startIsNorth = pRect.y < horizontalMidpoint,
113 | startIsWest = pRect.x < verticalMidpoint,
114 | endIsEast = pRect.x + pRect.width > verticalMidpoint,
115 | endIsSouth = pRect.y + pRect.height > horizontalMidpoint;
116 |
117 | //top-right quad
118 | if(startIsNorth && endIsEast) {
119 | indexes.push(0);
120 | }
121 |
122 | //top-left quad
123 | if(startIsWest && startIsNorth) {
124 | indexes.push(1);
125 | }
126 |
127 | //bottom-left quad
128 | if(startIsWest && endIsSouth) {
129 | indexes.push(2);
130 | }
131 |
132 | //bottom-right quad
133 | if(endIsEast && endIsSouth) {
134 | indexes.push(3);
135 | }
136 |
137 | return indexes;
138 | };
139 |
140 |
141 | /**
142 | * Insert the object into the node. If the node
143 | * exceeds the capacity, it will split and add all
144 | * objects to their corresponding subnodes.
145 | * @param Object pRect bounds of the object to be added { x, y, width, height }
146 | */
147 | Quadtree.prototype.insert = function(pRect) {
148 |
149 | var i = 0,
150 | indexes;
151 |
152 | //if we have subnodes, call insert on matching subnodes
153 | if(this.nodes.length) {
154 | indexes = this.getIndex(pRect);
155 |
156 | for(i=0; i this.max_objects && this.level < this.max_levels) {
167 |
168 | //split if we don't already have subnodes
169 | if(!this.nodes.length) {
170 | this.split();
171 | }
172 |
173 | //add all objects to their corresponding subnode
174 | for(i=0; i= index;
207 | });
208 |
209 | return returnObjects;
210 | };
211 |
212 |
213 | /**
214 | * Clear the quadtree
215 | */
216 | Quadtree.prototype.clear = function() {
217 |
218 | this.objects = [];
219 |
220 | for(var i=0; i < this.nodes.length; i++) {
221 | if(this.nodes.length) {
222 | this.nodes[i].clear();
223 | }
224 | }
225 |
226 | this.nodes = [];
227 | };
228 |
229 | //export for commonJS or browser
230 | if(typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
231 | module.exports = Quadtree;
232 | } else {
233 | window.Quadtree = Quadtree;
234 | }
235 |
236 | })();
--------------------------------------------------------------------------------
/temp/gameCore/utils/Collision.js:
--------------------------------------------------------------------------------
1 | // docs http://www.jeffreythompson.org/collision-detection/table_of_contents.php
2 | // TIPS https://gamedev.stackexchange.com/questions/22765/how-do-i-check-collision-when-firing-bullet
3 |
4 | // collision in center mode
5 | export const Collision = {
6 | rectRect(_r1x, _r1y, r1w, r1h, _r2x, _r2y, r2w, r2h) {
7 | let r1x = _r1x - r1w / 2;
8 | let r1y = _r1y - r1h / 2;
9 | let r2x = _r2x - r2w / 2;
10 | let r2y = _r2y - r2h / 2;
11 |
12 | return (
13 | r1x + r1w >= r2x &&
14 | r1x <= r2x + r2w &&
15 | r1y + r1h >= r2y &&
16 | r1y <= r2y + r2h
17 | );
18 | },
19 | };
20 |
21 | // collision in corner mode
22 | export const CollisionFull = {
23 | // http://www.jeffreythompson.org/collision-detection/point-point.php
24 | pointPoint(x1, y1, x2, y2, buffer = 0) {
25 | return sqr(x1 - x2) <= buffer && sqr(y1 == y2) <= buffer;
26 | },
27 |
28 | // http://www.jeffreythompson.org/collision-detection/point-circle.php
29 | pointCircle(px, py, cx, cy, r) {
30 | let distX = px - cx;
31 | let distY = py - cy;
32 | let distance = sqrt(distX * distX + distY * distY);
33 | return distance <= r;
34 | },
35 |
36 | // http://www.jeffreythompson.org/collision-detection/circle-circle.php
37 | circleCircle(c1x, c1y, c1r, c2x, c2y, c2r) {
38 | let distX = c1x - c2x;
39 | let distY = c1y - c2y;
40 | let distance = sqrt(distX * distX + distY * distY);
41 | return distance <= c1r + c2r;
42 | },
43 |
44 | // http://www.jeffreythompson.org/collision-detection/point-rect.php
45 | pointRect(px, py, rx, ry, rw, rh) {
46 | return px >= rx && px <= rx + rw && py >= ry && py <= ry + rh;
47 | },
48 |
49 | // http://www.jeffreythompson.org/collision-detection/rect-rect.php
50 | rectRect(r1x, r1y, r1w, r1h, r2x, r2y, r2w, r2h) {
51 | return (
52 | r1x + r1w >= r2x &&
53 | r1x <= r2x + r2w &&
54 | r1y + r1h >= r2y &&
55 | r1y <= r2y + r2h
56 | );
57 | },
58 |
59 | // http://www.jeffreythompson.org/collision-detection/circle-rect.php
60 | circleRect(cx, cy, radius, rx, ry, rw, rh) {
61 | let testX = cx;
62 | let testY = cy;
63 | if (cx < rx) testX = rx;
64 | else if (cx > rx + rw) testX = rx + rw;
65 | if (cy < ry) testY = ry;
66 | else if (cy > ry + rh) testY = ry + rh;
67 | let distX = cx - testX;
68 | let distY = cy - testY;
69 | let distance = sqrt(distX * distX + distY * distY);
70 | return distance <= radius;
71 | },
72 |
73 | // http://www.jeffreythompson.org/collision-detection/line-point.php
74 | linePoint(x1, y1, x2, y2, px, py, buffer = 0.1) {
75 | let d1 = dist(px, py, x1, y1);
76 | let d2 = dist(px, py, x2, y2);
77 | let lineLen = dist(x1, y1, x2, y2);
78 | return d1 + d2 >= lineLen - buffer && d1 + d2 <= lineLen + buffer;
79 | },
80 |
81 | // http://www.jeffreythompson.org/collision-detection/line-circle.php
82 | lineCircle(x1, y1, x2, y2, cx, cy, r) {
83 | let inside1 = this.pointCircle(x1, y1, cx, cy, r);
84 | let inside2 = this.pointCircle(x2, y2, cx, cy, r);
85 | if (inside1 || inside2) return true;
86 | let distX = x1 - x2;
87 | let distY = y1 - y2;
88 | let len = sqrt(distX * distX + distY * distY);
89 | let dot = ((cx - x1) * (x2 - x1) + (cy - y1) * (y2 - y1)) / pow(len, 2);
90 | let closestX = x1 + dot * (x2 - x1);
91 | let closestY = y1 + dot * (y2 - y1);
92 | let onSegment = this.linePoint(x1, y1, x2, y2, closestX, closestY);
93 | if (!onSegment) return false;
94 | distX = closestX - cx;
95 | distY = closestY - cy;
96 | let distance = sqrt(distX * distX + distY * distY);
97 | return distance <= r;
98 | },
99 |
100 | // http://www.jeffreythompson.org/collision-detection/line-line.php
101 | lineLine(x1, y1, x2, y2, x3, y3, x4, y4) {
102 | let uA =
103 | ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) /
104 | ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1));
105 | let uB =
106 | ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) /
107 | ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1));
108 | return uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1;
109 | },
110 |
111 | // http://www.jeffreythompson.org/collision-detection/line-rect.php
112 | lineRect(x1, y1, x2, y2, rx, ry, rw, rh) {
113 | return (
114 | this.lineLine(x1, y1, x2, y2, rx, ry, rx, ry + rh) ||
115 | this.lineLine(x1, y1, x2, y2, rx + rw, ry, rx + rw, ry + rh) ||
116 | this.lineLine(x1, y1, x2, y2, rx, ry, rx + rw, ry) ||
117 | this.lineLine(x1, y1, x2, y2, rx, ry + rh, rx + rw, ry + rh)
118 | );
119 | },
120 |
121 | // http://www.jeffreythompson.org/collision-detection/poly-point.php
122 | polyPoint(vertices, px, py) {
123 | let collision = false;
124 | let next = 0;
125 | for (let current = 0; current < vertices.length; current++) {
126 | next = current + 1;
127 | if (next == vertices.length) next = 0;
128 | let vc = vertices[current];
129 | let vn = vertices[next];
130 | if (
131 | ((vc.y >= py && vn.y < py) || (vc.y < py && vn.y >= py)) &&
132 | px < ((vn.x - vc.x) * (py - vc.y)) / (vn.y - vc.y) + vc.x
133 | ) {
134 | collision = !collision;
135 | }
136 | }
137 | return collision;
138 | },
139 |
140 | // http://www.jeffreythompson.org/collision-detection/poly-circle.php
141 | polyCircle(vertices, cx, cy, r) {
142 | let next = 0;
143 | for (let current = 0; current < vertices.length; current++) {
144 | next = current + 1;
145 | if (next == vertices.length) next = 0;
146 | let vc = vertices[current];
147 | let vn = vertices[next];
148 | if (this.lineCircle(vc.x, vc.y, vn.x, vn.y, cx, cy, r)) return true;
149 | }
150 | return this.polyPoint(vertices, cx, cy);
151 | },
152 |
153 | // http://www.jeffreythompson.org/collision-detection/poly-rect.php
154 | polyRect(vertices, rx, ry, rw, rh, isCheckInside = false) {
155 | let next = 0;
156 | for (let current = 0; current < vertices.length; current++) {
157 | next = current + 1;
158 | if (next == vertices.length) next = 0;
159 | let vc = vertices[current];
160 | let vn = vertices[next];
161 | if (this.lineRect(vc.x, vc.y, vn.x, vn.y, rx, ry, rw, rh)) {
162 | return isCheckInside ? this.polyPoint(vertices, rx, ry) : true;
163 | }
164 | }
165 |
166 | return false;
167 | },
168 |
169 | // http://www.jeffreythompson.org/collision-detection/poly-line.php
170 | polyLine(vertices, x1, y1, x2, y2) {
171 | let next = 0;
172 | for (let current = 0; current < vertices.length; current++) {
173 | next = current + 1;
174 | if (next == vertices.length) next = 0;
175 | let x3 = vertices[current].x;
176 | let y3 = vertices[current].y;
177 | let x4 = vertices[next].x;
178 | let y4 = vertices[next].y;
179 | if (this.lineLine(x1, y1, x2, y2, x3, y3, x4, y4)) {
180 | return true;
181 | }
182 | }
183 |
184 | // never got a hit
185 | return false;
186 | },
187 |
188 | // http://www.jeffreythompson.org/collision-detection/poly-poly.php
189 | polyPoly(poly1, poly2) {
190 | let next = 0;
191 | for (let current = 0; current < poly1.length; current++) {
192 | next = current + 1;
193 | if (next == poly1.length) next = 0;
194 | let vc = poly1[current];
195 | let vn = poly1[next];
196 | if (this.polyLine(poly2, vc.x, vc.y, vn.x, vn.y)) return true;
197 | if (this.polyPoint(poly1, poly2[0].x, poly2[0].y)) return true;
198 | }
199 |
200 | return false;
201 | },
202 |
203 | // http://www.jeffreythompson.org/collision-detection/tri-point.php
204 | triPoint(x1, y1, x2, y2, x3, y3, px, py) {
205 | let areaOrig = abs((x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1));
206 | let area1 = abs((x1 - px) * (y2 - py) - (x2 - px) * (y1 - py));
207 | let area2 = abs((x2 - px) * (y3 - py) - (x3 - px) * (y2 - py));
208 | let area3 = abs((x3 - px) * (y1 - py) - (x1 - px) * (y3 - py));
209 | return area1 + area2 + area3 == areaOrig;
210 | },
211 | };
212 |
213 | export default Collision;
214 |
--------------------------------------------------------------------------------