-
-
Save ReiiSky/d05d20475782774a0b38ba287c0a61b9 to your computer and use it in GitHub Desktop.
Revisions
-
JAForbes revised this gist
Mar 11, 2016 . 1 changed file with 18 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -118,3 +118,21 @@ unlike class/prototype based approaches. Also notice how focused each system is. You could easily imaginee reusing any of these systems across many applications. But you get the banana without the gorilla and the rest of the jungle. #### State Graph Because all your state is stored in one place, you can easily implement quicksave/quickload functionality. ``` QuickSave(quicksave, entity){ components.SaveState[entity] = JSON.stringify(components) } QuickLoad(quickload, entity){ components = JSON.parse(components.SaveSate[entity]) } ``` #### Live programming You can also interact with your game live in a REPL with ease. By modifiying the state you can test elaborate scenarios. It's trivial to clone an entity `n` times, or adjust the strength of a particular force and see the results immediately. -
JAForbes revised this gist
Mar 11, 2016 . 1 changed file with 4 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,5 @@ #### Entities and Components An entity is just a number. There is a graph of components, indexed by the entity id. @@ -42,6 +44,8 @@ Also notice the `game` entity has no `Position` or `Sprite`. It is just an iden components.Timer[6] = { count: 0, interval: 1000, on: { ScreenShake: { x: 1, y: 0 } } } ``` #### Systems ```js //gameloop systems -
JAForbes revised this gist
Mar 11, 2016 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -37,7 +37,7 @@ A `potplant` never moves, so it just has a `Position` and a `Sprite`. Because i Also notice the `game` entity has no `Position` or `Sprite`. It is just an identifier with some associated data. In this case it has a Timer component that will make the screen shake every 1000 milliseconds. There are no callbacks, or event listeners, it is just an object literal with some numbers in it. ```js //look ma, no callbacks components.Timer[6] = { count: 0, interval: 1000, on: { ScreenShake: { x: 1, y: 0 } } } ``` -
JAForbes revised this gist
Mar 11, 2016 . 1 changed file with 4 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -37,6 +37,10 @@ A `potplant` never moves, so it just has a `Position` and a `Sprite`. Because i Also notice the `game` entity has no `Position` or `Sprite`. It is just an identifier with some associated data. In this case it has a Timer component that will make the screen shake every 1000 milliseconds. There are no callbacks, or event listeners, it is just an object literal with some numbers in it. ``` //look ma, no callbacks components.Timer[6] = { count: 0, interval: 1000, on: { ScreenShake: { x: 1, y: 0 } } } ``` ```js //gameloop systems -
JAForbes revised this gist
Mar 11, 2016 . 1 changed file with 7 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -33,6 +33,11 @@ Systems iterate over a specific component type. If that component type is empty This is very different to the traditional iteration over all entities, which is wasteful and grounded in thinking every entity is an object instead of just an identifier. A `potplant` never moves, so it just has a `Position` and a `Sprite`. Because it has no `Velocity` component the code that handles Movement will never be activated for those entities. Also notice the `game` entity has no `Position` or `Sprite`. It is just an identifier with some associated data. In this case it has a Timer component that will make the screen shake every 1000 milliseconds. There are no callbacks, or event listeners, it is just an object literal with some numbers in it. ```js //gameloop systems @@ -103,3 +108,5 @@ See how the Move system pulls in the position data by accessing the component gr Because all references are local to a function call, deleting a component from the graph will immediately release it into memory unlike class/prototype based approaches. Also notice how focused each system is. You could easily imaginee reusing any of these systems across many applications. But you get the banana without the gorilla and the rest of the jungle. -
JAForbes revised this gist
Mar 11, 2016 . 1 changed file with 28 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,9 @@ An entity is just a number. There is a graph of components, indexed by the entity id. All state is stored in one place. ```js var components = { Position: {}, Velocity:{}, Spite: {}, Timer: {}, ScreenShake: {}, RemoveComponents: {} } @@ -22,6 +28,11 @@ potplants.forEach(function(potplant, i){ components.Timer[6] = { count: 0, interval: 1000, on: { ScreenShake: { x: 1, y: 0 } } } ``` Systems iterate over a specific component type. If that component type is empty for that game loop, those systems do not run. This is very different to the traditional iteration over all entities, which is wasteful and grounded in thinking every entity is an object instead of just an identifier. ```js //gameloop systems @@ -75,4 +86,20 @@ function RemoveComponents(remove, entity){ delete components.ScreenShake[entity] }) } ``` Each system accepts a single component and the entity id for that component. The id allows the system to pull in other components for that entity. ```js function Move(velocity, entity){ var p = component.Position[entity] p.x += velocity.x p.y += velocity.y } ``` See how the Move system pulls in the position data by accessing the component graph directly. Because all references are local to a function call, deleting a component from the graph will immediately release it into memory unlike class/prototype based approaches. -
JAForbes revised this gist
Mar 11, 2016 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -71,7 +71,7 @@ function ScreenShake(screenshake, entity){ } function RemoveComponents(remove, entity){ remove.components.forEach(function(){ delete components.ScreenShake[entity] }) } -
JAForbes created this gist
Mar 11, 2016 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,78 @@ ```js var components = { Position: {}, Velocity:{}, Spite: {}, Timer: {}, ScreenShake: {}, RemoveComponents: {} } var player = 1 var enemy = 2 var potplants = [3,4,5] var game = 6 components.Position[player] = { x:100, y: 100 } components.Velocity[player] = { x: 0.5, y: 0 } components.Sprite[player] = sprites.player components.Position[enemy] = { x: 0, y: 100} components.Velocity[enemy] = { x: 1, y: 0} components.Sprite[enemy] = sprites.enemy potplants.forEach(function(potplant, i){ components.Position[potplant] = { x: i * 100, y: 200 } components.Sprite[potplant] = sprites.potplant }) components.Timer[6] = { count: 0, interval: 1000, on: { ScreenShake: { x: 1, y: 0 } } } ``` ```js //gameloop systems [ [Move, components.Velocity] [Timer, components.Timer], [Screenshake, components.Screenshake], [Render, components.Sprite], [RemoveComponents, components.RemoveComponents], ].forEach(callSystem) function callSystem([system, components]){ _.each(components, system) } function Move(velocity, entity){ var p = component.Position[entity] p.x += velocity.x p.y += velocity.y } function Render(sprite, entity){ var p = component.Position[entity] context.drawImage(p.x, p.y, ..., sprite.img ) } function Timer(timer, entity){ if(timer.count > timer.timer){ if(timer.repeat){ timer.count = 0 } else { components.RemoveComponents[entity] = { components: ['Timer'] } } _.each(components.on, function(data, name){ components[name] = data }) } timer.count ++ } function ScreenShake(screenshake, entity){ //shake the screen components.RemoveComponents[entity] = { components: ['ScreenShake']} } function RemoveComponents(remove, entity){ remove.forEach(function(){ delete components.ScreenShake[entity] }) } ```