├── gol-engine.d.ts
├── .browserslistrc
├── .firebaserc
├── public
├── favicon.ico
└── index.html
├── src
├── rxjs
│ ├── index.ts
│ └── message.ts
├── shims-vue.d.ts
├── views
│ ├── HowTo.vue
│ ├── Home.vue
│ ├── About.vue
│ └── Gol.vue
├── assets
│ ├── fonts.scss
│ ├── theme_pastel.scss
│ ├── theme_love.scss
│ └── style.scss
├── App.vue
├── shims-tsx.d.ts
├── concerns
│ └── store_concerns.ts
├── main.ts
├── router
│ └── index.ts
├── components
│ ├── ModalPage.vue
│ ├── Controls.vue
│ └── TopBar.vue
└── store
│ └── index.ts
├── babel.config.js
├── firebase.json
├── .gitignore
├── .eslintrc.js
├── webpack.config.js
├── tsconfig.json
├── package.json
├── .firebase
└── hosting.ZGlzdA.cache
└── README.md
/gol-engine.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'gol-engine';
--------------------------------------------------------------------------------
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/.firebaserc:
--------------------------------------------------------------------------------
1 | {
2 | "projects": {
3 | "default": "gameoflife-ts"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/letItCurl/vue-gol-ts/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/src/rxjs/index.ts:
--------------------------------------------------------------------------------
1 | import {interval} from 'rxjs'
2 |
3 | export const flow = interval(100)
4 |
5 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.vue' {
2 | import Vue from 'vue'
3 | export default Vue
4 | }
5 |
--------------------------------------------------------------------------------
/src/views/HowTo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
This is an How to page
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/assets/fonts.scss:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Comic+Neue:ital@1&family=Permanent+Marker&display=swap');
2 |
3 | $marker: 'Permanent Marker', cursive;
4 | $comic: 'Comic Neue', cursive;
--------------------------------------------------------------------------------
/src/assets/theme_pastel.scss:
--------------------------------------------------------------------------------
1 |
2 | $text-primary: rgba(221, 97, 74, 1);
3 | $text-secondary: rgba(244, 134, 104, 1);
4 | $grey: rgb(141, 139, 94);
5 | $bg-primary: rgba(203, 118, 158, 0.548);
6 | $bg-secondary: rgba(115, 165, 128, 0.459);
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/rxjs/message.ts:
--------------------------------------------------------------------------------
1 | import { Subject } from 'rxjs';
2 |
3 | const subject = new Subject();
4 |
5 | export const dataBus = {
6 | sendMessage: (message: any) => subject.next({ message }),
7 | clearMessages: () => subject.next(),
8 | getMessage: () => subject.asObservable()
9 | };
--------------------------------------------------------------------------------
/firebase.json:
--------------------------------------------------------------------------------
1 | {
2 | "hosting": {
3 | "public": "dist",
4 | "ignore": [
5 | "firebase.json",
6 | "**/.*",
7 | "**/node_modules/**"
8 | ],
9 | "rewrites": [
10 | {
11 | "source": "**",
12 | "destination": "/index.html"
13 | }
14 | ]
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw?
22 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | >
13 |
14 |
20 |
--------------------------------------------------------------------------------
/src/assets/theme_love.scss:
--------------------------------------------------------------------------------
1 | $text-primary: #fab0ee;
2 | $text-secondary: rgb(255, 0, 242);
3 | $grey: rgba(255, 157, 255, 0.363);
4 | $bg-primary: rgba(96, 0, 70, 0.3);
5 | $bg-secondary: rgba(195, 0, 255, 0.308);
6 | $shadow: rgb(195, 0, 255);
7 | $speed: 600ms;
8 |
9 | $lines: #df00f3;
10 | $active-color: rgb(215, 255, 140);
--------------------------------------------------------------------------------
/src/shims-tsx.d.ts:
--------------------------------------------------------------------------------
1 | import Vue, { VNode } from 'vue'
2 |
3 | declare global {
4 | namespace JSX {
5 | // tslint:disable no-empty-interface
6 | interface Element extends VNode {}
7 | // tslint:disable no-empty-interface
8 | interface ElementClass extends Vue {}
9 | interface IntrinsicElements {
10 | [elem: string]: any;
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/concerns/store_concerns.ts:
--------------------------------------------------------------------------------
1 | export function backConcern(state: any, astroWorld: any){
2 | const time = astroWorld.history.length;
3 | if(time > 1){
4 | const back = astroWorld.history[time-2]
5 | state.map = [...back]
6 | astroWorld.map = [...back]
7 | astroWorld.history.pop()
8 | return true
9 | }else{
10 | astroWorld.history.pop()
11 | return false
12 | }
13 | }
--------------------------------------------------------------------------------
/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
20 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | 'extends': [
7 | 'plugin:vue/essential',
8 | 'eslint:recommended',
9 | '@vue/typescript/recommended'
10 | ],
11 | parserOptions: {
12 | ecmaVersion: 2020
13 | },
14 | rules: {
15 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
16 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | module: {
3 | rules: [
4 | // ... other rules omitted
5 |
6 | // this will apply to both plain `.scss` files
7 | // AND `
35 |
--------------------------------------------------------------------------------
/.firebase/hosting.ZGlzdA.cache:
--------------------------------------------------------------------------------
1 | index.html,1587667340109,4544e65ee6f5a5bf08a790202c5b33f56a4b80ac1193426dfd474e10a4c4540c
2 | css/about.aeccb8a9.css,1587667340109,913dc54c8f3c18937a586c47738f5bed0a3d91e2c1c780e29b0c0d8e93a49ead
3 | favicon.ico,1587667340113,e0535b2041a7a1721cdec785c903980d41fdf0d810a4ea9726b6ffd1371bbc28
4 | css/app.59097944.css,1587667340113,e6deb471db3e8586526617225a76eeba8012c10292ee57e41276abc9fc5738b5
5 | css/chunk-vendors.d8f4d95f.css,1587667340113,60f15680001bc0350595af547ee970b62fb778d5e12ac92622429e555c697ed1
6 | css/gol.22c264af.css,1587667340113,20c163ee9597e5c0923e79f6c56217b1b90aca07079f4a23613f141dba02e532
7 | js/about.4b1a27b9.js,1587667340113,a9923bd168a9b45f1a9c30dc52253c0f9c258cf350eb48c00ee1e9edf7fc46aa
8 | js/app.b56a45b2.js,1587667340109,ccb9b07384dab46432b20ada94797e7456ea3f861427b887012648c7d41c1973
9 | js/app.b56a45b2.js.map,1587667340113,5901d29a4aecb68eba2ba599577c814496866e523f0920b87e8062114834224e
10 | js/gol.de140de1.js,1587667340113,e0ef7e7cba3594fdd4b7af7d41cf3dd1f62bd28ab0dc866247febecdb675d5aa
11 | js/howto.bc371b6e.js,1587667340113,c740ae41970b9f8b681ed49f51146f13453cb38985e4586c9f62eda3138eb919
12 | js/howto.bc371b6e.js.map,1587667340113,ab24c42114b0b845e049210e0e063c2bd68b079f49a1c86c647c082d15530a63
13 | js/about.4b1a27b9.js.map,1587667340113,d10641df7717cc0f630246122b2adb83212346cd330248dcf361d3bd27549c15
14 | js/gol.de140de1.js.map,1587667340113,805f989cb78ea3edaa9ad4d91a5a6420b3431d4e220ef4a99f088754c0371959
15 | js/chunk-vendors.da93afeb.js,1587667340113,7f6556a4a232a3f561704fe5b143ec76777208f8b41c563a22e2bb908cbcfe43
16 | js/chunk-vendors.da93afeb.js.map,1587667340113,ac150ff2d693a5e830626935d48bd34a44c6004d0b754f1500d8d1d23c622331
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Click here to try it !
10 |
11 | # Features [](https://www.linkedin.com/in/roland-lopez-developer/?locale=en_US)
12 |
13 | - Drag and drop on desktop.
14 | - Hold touch event on mobile.
15 | - Infinite map generation.
16 | - Can spwan items during the playing action.
17 | - Map length resized in function of the view port.
18 | - Rewind generations.
19 | - Go backward and frontward step by step.
20 |
21 | # Technical stack
22 | - Vue.Js / Ts template
23 | - Canvas
24 | - VueX
25 | - RxJs
26 | - Vue touch events
27 | - Firebase Hosting
28 |
29 | # About
30 | Project made from scratch by me, for you, with <3.
31 | It uses a custom node_module , developed by me, coded also in Typescript.
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
Hey there !
42 | I'm letItCurl, fullstack developer engineer in freelance a.k.a Roland in real life :p
43 | If you have any question you can contact me if you wish !
44 |
I'm always ready to help !
45 |
Email me
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/components/ModalPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 |
16 |
17 |
18 |
19 |
20 | >
29 |
30 |
90 |
--------------------------------------------------------------------------------
/src/views/Gol.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
110 |
126 |
--------------------------------------------------------------------------------
/src/store/index.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import {world} from "gol-engine"
4 | import { flow } from '@/rxjs/index'
5 | import { backConcern } from '@/concerns/store_concerns'
6 | import { dataBus } from '@/rxjs/message';
7 |
8 |
9 | var astroWorld = new world["default"](70); // eslint-disable-line
10 |
11 | astroWorld.initWorld()
12 |
13 | Vue.use(Vuex)
14 |
15 | export default new Vuex.Store({
16 | state: {
17 | map: astroWorld.map,
18 | time: flow.subscribe(),
19 | mobileActive: 'barFive',
20 | size: 2000,
21 | grid: 70
22 | },
23 | mutations: {
24 | NEXT(state){
25 | astroWorld.nextDay()
26 | state.map = [...astroWorld.map]
27 | },
28 | BACK(state){
29 | backConcern(state, astroWorld)
30 | },
31 | PLAY_PAUSE(state, payload){
32 | if(!payload){
33 | state.time = flow.subscribe(x=>{
34 | astroWorld.nextDay()
35 | state.map = [...astroWorld.map]
36 | })
37 | }else{
38 | state.time.unsubscribe()
39 | }
40 | },
41 | REWIND(state, payload){
42 | if(!payload){
43 | state.time = flow.subscribe(x=>{
44 | if(!backConcern(state, astroWorld)){
45 | state.time.unsubscribe()
46 | dataBus.sendMessage('UNLOCK');
47 | }
48 | })
49 | }else{
50 | state.time.unsubscribe()
51 | }
52 | },
53 | CLEAR(state){
54 | astroWorld.clear()
55 | state.map = [...astroWorld.map]
56 | },
57 | SET_BAR_FIVE(state, payload){
58 | astroWorld.barFive(payload.X,payload.Y)
59 | state.map = [...astroWorld.map]
60 | },
61 | SET_FROG(state, payload){
62 | astroWorld.frog(payload.X,payload.Y)
63 | state.map = [...astroWorld.map]
64 | },
65 | SET_GLIDER(state, payload){
66 | astroWorld.glider(payload.X,payload.Y)
67 | state.map = [...astroWorld.map]
68 | },
69 | SET_U_CLOWN(state, payload){
70 | astroWorld.uClown(payload.X,payload.Y)
71 | state.map = [...astroWorld.map]
72 | },
73 | MOBILE_ACTIVE(state, payload){
74 | state.mobileActive = payload
75 | },
76 | MOBILE_RESIZE(state, payload){
77 | state.grid = payload.grid;
78 | state.size = payload.size;
79 | astroWorld = new world["default"](payload.grid);
80 | astroWorld.initWorld()
81 | }
82 | },
83 | actions: {
84 | back(context): void {
85 | context.commit('BACK')
86 | },
87 | playPause(context, payload): void {
88 | context.commit('PLAY_PAUSE', payload)
89 | },
90 | next(context): void {
91 | context.commit('NEXT')
92 | },
93 | clear(context): void{
94 | context.commit('CLEAR')
95 | },
96 | barFive(context, payload){
97 | context.commit('SET_BAR_FIVE', payload)
98 | },
99 | frog(context, payload){
100 | context.commit('SET_FROG', payload)
101 | },
102 | glider(context, payload){
103 | context.commit('SET_GLIDER', payload)
104 | },
105 | uClown(context, payload){
106 | context.commit('SET_U_CLOWN', payload)
107 | },
108 | rewind(context, payload){
109 | context.commit('REWIND', payload)
110 | },
111 | mobileActive(context, payload){
112 | context.commit('MOBILE_ACTIVE', payload)
113 | }
114 | },
115 | getters:{
116 | map(state){
117 | return state.map
118 | },
119 | mobileActive(state){
120 | return state.mobileActive
121 | },
122 | size(state){
123 | return state.size
124 | },
125 | grid(state){
126 | return state.grid
127 | }
128 | },
129 | modules: {
130 | }
131 | })
132 |
--------------------------------------------------------------------------------
/src/components/Controls.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
65 |
66 |
--------------------------------------------------------------------------------
/src/components/TopBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
51 |
52 |
--------------------------------------------------------------------------------