├── 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 |
39 |
40 |
41 |
42 |
43 | 44 |
45 |
46 |
47 |

48 |
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 | 7 | 8 | Created by potrace 1.11, written by Peter Selinger 2001-2013 9 | 10 | 12 | 38 | 39 | 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 | --------------------------------------------------------------------------------