Open alfonsogarciacaro opened 8 years ago
@whitetigle All these ideas look awesome! And absolutely, behaviors are great and I think they fit the functional paradigm very well (simple functions, composable...) Do you have anything that we can use as a basis to write samples using behaviors?
On my side I don't have anything yet but I've been investigating a bit about web workers and I think it could be possible to write a kindda proto-game engine that puts physics calculation to a webworker and sends it to the main thread on every requestAnimationFrame
cycle so it can be used by the behaviors. As usual, the main limitation for this is my time budget :/
About cool tiny samples for quick testing it'd be really nice to have an online editor to edit the samples in real time (again, time constraints...). Sonic-Pi looks really awesome! Is there any prototype of how interaction with a foreign language through OCS messages could work?
BTW, any news about upgrading to Pixi 4? I think @davidtme already has some bindings for it?
I've abandoned using pixi mainly due to slow (and understandable) bug fixes and I was spending most of my time trying to keep the mutable scene in check (didn't feel very functional). I'm happy to help get the binding up to v4 (or any other way) because I do love the engine just. I used pixi v4 with the v3 binding and just fixed any funnies as I went along. I don't know how different it is really https://gist.github.com/davidtme/cb3d58024c2fdfa0cc6acca45cbbabff
I'll try and post up (in that gist) any other helpers I made or snippets - like importing .glsl with webpack which I think v4 uses
I do agree with @davidtme about the bugs. I have been watching the issues since the release of the v4 and there have been quite a lot of things that just did not work. Now things seem to get better. Still I don't know if it's worth the work right now.
BTW the API seems to have quite a few changes: v3 vs v4
FYI there's some demo with 3D physics engine oimo.js with workers here.
I do have samples to showcase. I could easily create simple ones. But right now, what would be Uber cool would be define the right architecture to use them. And here I need your help.
There are a few things that I am currently not happy with:
"Start this and then when it's done, let's start that and that and when it's done start this new thing and then when all is done, eventually trigger this"
Relying on ESprite wich inherits Sprite: maybe have a BehaveSprite that takes a sprite in it's constructor? But ESprite has one constructor vs two for Sprite.
Not functional: my current version is not while yours is. So it's a great time to merge π
So here is the current (dirty) state of the Behavior System I have been using.
And here are the Easing functions I use. and that we could add to fable/graphics
So what I can prepare is a simple complete sample written like I usually do with behaviors and see how we can transform this? Then I will base all my samples on this new architecture.
Here is some Erlang test.. There's a javascript lib that I can try to use: OSC.js. So it seems that it should not take long to know if it works.
I think that having one simple complete sample like you usually do can be a good start. And like you said from here we could, start tweaking your code with feedbacks from others.
PS: I have little during this 1-2 weeks but later I should be free again to work on Pixi.JS again.
Hi there! I just finished a simple complete sample using behaviors.
@alfonsogarciacaro: I have updated just a little bit your architecture to fit my needs and so we have promises, behaviors as functions, and ESprite with IDisposable.
In order not to create a new branch in fable repository yet, I created a new repository here: https://github.com/whitetigle/fable-behaviors. If we decide to use this sample once cleaned-up, then you'll tell me where to move it (samples?)
Since GitHub allows hosting, there's also a live demo to play with: https://whitetigle.github.io/fable-behaviors/
So I decided to have fun with GitHub API and get some data to display. So here we have the history of additions and deletions per week since last year (doc / fable actual data )
For each week, I spawn additions particles that go to the fable repo/planet and deletion particles that leave the repo to vanish in space.
Then I also update counters that sum deletions and additions (I could do that better, but it's a start). What's interesting is that some week just display huge activity. That's quite funny to watch. And some none (holydays maybe?)
Since this uses the GitHub API without authorization, and we do have a limit (60 queries/hour) I also cache the data for the current day in Local Storage.
Everything being far from perfect, sometimes getting the data does not work (I don't know why) and so I create an empty array [] in LocalStorage. So to make it work again, we need to remove the content of the LocalStorage.
So as you can see there's some more work to do if we want to use this sample.
Last but not least, sorry for this "space" theme, but to go fast I just reused some of the logic of my previous project. (and I kind of love space themes π )
So I am still using Pixi v3.0. In this sample we have a few interesting things to comment upon (if we want to use and document this sample):
Ah just before I forget: I did not use scaling. So the sample works in a set resolution of 1024x600.
Nothing's better than a cool pic. So here it is!
Hope you'll like it!
@whitetigle Really cool showcase :)
I will try to play with it a little and learn about Behaviors etc.
Thanks @MangelMaxime! The code is not that pretty yet. So if you need help ping me :)
Nice stuff!!
On 29 Nov 2016 8:39 a.m., "Whitetigle" notifications@github.com wrote:
Thanks @MangelMaxime https://github.com/MangelMaxime! The code is not that pretty yet. So if you need help ping me :)
β You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/fable-compiler/fable-graphics/issues/4#issuecomment-263509096, or mute the thread https://github.com/notifications/unsubscribe-auth/AAAMH-psmXtmN9LL1m8AykfvWaU30j_Eks5rC-TQgaJpZM4J6up3 .
Thanks! π
Hi @whitetigle! Sorry I didn't reply before. The app is beyond awesome, fantastic work! π
With your code and all the information you've provided, now I have a lot of ideas, but I'd rather start little by little or nothing will be done at the end :wink: I'll try to send you a PR this weekend to ask your opinions. Some of the ideas I'm considering:
That's my food for thought at the moment. I'll try to send some actual code soon :+1: And again, thanks a lot for your awesome contributions @whitetigle!
Thanks @alfonsogarciacaro ! So I'll wait for your PR so we can review all the things to do and discuss all the points you raised one by one.
Hi! just so you know, as planned, I just finished a simple proof of concept to interact with Sonic-Pi from a web page using Fable. I think we'll be able to build fun things with that from now on.
It's there with full instructions.
By the way thanks @alfonsogarciacaro for your help today. I was desperatly trying to use osc.js and could not find my way. Now it works π
Woooow, looking awesome!! NP! Any time you need help just ping me, you can also contact me (and other Fable users) in Gitter for quick answers π
@alfonsogarciacaro I took some time to review and start answering your remarks
- I'll probably make the Behaviours synchronous again, I'm afraid some of the promises may take too long to fulfil, locking the animation loop.
ok
- I'll try to separate the skeleton of the app into a reusable file/lib.
ok
- Would it be useful if, instead of sprites, behaviours act on a custom model and then the model is used to update the sprite? This would make the code more decoupled from Pixi, but maybe it's not that convenient at the end. At the very least, Behaviours should accept custom types deriving from ESprite.
I don't know. Although I understand the desired effect, I am not a fan of generic systems. For instance, Pixi is made for speed and is clearly an agnostic engine. Its goal is not the same as Phaser which provides with a game centric approach although they do share a great part of the same code (at least for now)
So in the end I think I would prefer having several behaviour systems, each one tailored for the underlying engine: pixi-behaviors, phaser-behaviors, pandajs-behaviors?
Well it's clearly a vast topic, I need to think more about this. Maybe you would have some ideas in mind?
- Organize the objects in hierarchies, as with React components for example. This way, calculations made in the parent can be passed to the children. How do containers work in Pixi?
Well a Container is a DisplayObject and a Sprite is a Container and then we have ParticleContainers which are deriving from Container as well and have their own optimised code under hood.
So sometimes my root container is a Sprite so that I can apply effects to the whole stage. The shake effect works like this for instance.
In the end it's all about having Containers or ParticleContainers.
- Implement an event system. Probably a different (fictitious) thread should be collection event messages and then feed them to the behaviours in each iteration of the animation loop.
ok
- [Future] Add object pools so we can reuse memory. I have some ideas to use JS hacks in a way that it looks like you're actually constructing and destructing objects in F#.
ok
- [Future] Move intensive calculations to a web worker and collect the results (preferably passed with a shared Array Buffer) as if they were events.
ok
@alfonsogarciacaro about the model: were you thinking about using behaviors with CSS or canvas as well for instance? Maybe we could find something to do.
Hi everybody! First of all, Happy new year! π I wish all your professional and personal projects all the best!
I don't know what @alfonsogarciacaro thinks but it seems like 2016 has been a great year for Fable. And I hope 2017 will even be better!
I have been quite busy the last few weeks with teaching so I did not write any new F#/Fable things. But I do have Fable things planned:
If you are ok, I think I could turn some of these projects into Fable samples? I would also like to do the same with the GitHub data project since it seemed to trigger some interest but I am still stuck on the architecture side. I will try to refactor things. but If you have time to continue our discussion, I would of course be happy to follow new leads.
Now, if you would like me to go any another way to promote Fable through samples, please tell me what you would need.
A last word, special thanks to @alfonsogarciacaro and @MangelMaxime for your help regarding the learning process of F# and Fable. I have been able to do great and fun things thanks to your energy. I will try to contribute to help you reach your goals too in 2017 π
Hey, happy new year to you too @whitetigle
It's would be really great to have some of your projects are samples.
I think, this would be a great things to have a real but small game (perhaps several) as a sample. Because, on every projects we are always showing small part of the libs etc. but the gap between a sample and a real case is too big.
For example, in Fable Arch we have something like 10 samples showing the basics. But nothing showing what a real web app could look likes and this is really much the harder part than just making a clock or a counter :). This is why, I am writing the docs website using Fable arch itself to serve as a concrete sample.
I probably made a little digression here but nevermind. :)
I would love to help you work on the samples/documentations part for pixi.js if you want @whitetigle we could discuss about it on Gitter. I think we really need to dig dipper about the bahaviors system which was looking really promising the last time I checked it.
I think, this would be a great things to have a real but small game (perhaps several) as a sample. Because, on every projects we are always showing small part of the libs etc. but the gap between a sample and a real case is too big.
Ok! I think I understand your point.
I would love to help you work on the samples/documentations part for pixi.js if you want @whitetigle we could discuss about it on Gitter.
Great! We'll do that then π
I think we really need to dig dipper about the bahaviors system which was looking really promising the last time I checked it.
Cool! We'll see that then.
Just wanted to share status of my current work.
I am writing a minimal game and the goal is to see how functional I can make it. I am not allowing a lot of mutable state in the game architecture because performance are not a problem yet ^^. And also, by having the minimal mutation possible I think we can minimise the side effects.
Here is the GameState record:
type GameState =
{ Renderer: WebGLRenderer
Id: int
SpriteSheets: Map<string, ResizeArray<Texture>>
State: State
Root: Container
MouseState: Inputs.Mouse.MouseState
KeyboardState: Inputs.Keyboard.KeyboardState
Data: obj
Containers: Map<string, Container>
Resources: loaders.ResourceDictionary
}
[<PassGenerics>]
member self.GetData<'T>() =
unbox<'T> self.Data
member self.ClearStage() =
self.Root.destroy(true)
{ self with
Root = new Container()
}
member self.GetCenterX () =
self.Renderer.width / 2.
member self.GetCenterY () =
self.Renderer.height / 2.
member self.Survivors
with get () = self.SpriteSheets.[Survivors.SPRITES_SHEETS_KEY]
As you can see from this record we have access to inputs state (Mouse and Keyboard) and most important we have Data property. This property will be where the user store all the information he wants.
We simply use GetData<'T>
to unbox the data type and get intellisence etc. Let's just consider it's working I need to polish this part and advance more on the sample.
Initializing the inputs is as simple as:
let state : GameState =
{ [....]
MouseState = Inputs.Mouse.init stage
KeyboardState = Inputs.Keyboard.init renderer.view
[....]
}
The keyboard inputs are attached directly to the canvas because they are globals to the application.
However the mouse inputs are attached to a Container
this allow more flexibility (could be attach to a sprite for example).
The goal here is to give access to a functional representation of the inputs.
For example, the Mouse is simply a record containing the X, Y position etc.
type MouseState =
{ mutable X: float
mutable Y: float
mutable Left: ButtonState
mutable Right: ButtonState
mutable Middle: ButtonState
}
The property are marked mutable but the user do not need to update the value only read it. The values will be updated thanks to the listener register by Inputs.Mouse.init
A game is dynamic and we need to know how to update the GameState or even the view depending if we are on a SplashScreen, Loading, play a level etc.
To do that, I use Discriminated Union to represent the current state.
type BasicSceneDU
= Init
| Run
| Pause
type Scene
= Level1 of BasicSceneDU
type LoadingDU
= Init
| Waiting
type State
= Nothing
| Loading of LoadingDU
| Scene of Scene
| SplashScreen of BasicSceneDU
Thanks to this DU, I know that when the state is Scene (Level1 BasicSceneDU.Init)
I need to create the scene data and set the next state to be Scene (Level1 basicSceneDU.Run)
The gameLoop is the function which contain all the game logic.
For example, if we take the last scene here is the code used to handle the scene init and logic to play during the level.
let rec gameLoop (gameState: GameState) (dt: float) =
let newState =
match gameState.State with
| Scene subScene ->
match subScene with
| Level1 sceneDU ->
match sceneDU with
| BasicSceneDU.Init ->
let state' = gameState.ClearStage()
let ground = new Container()
state.Survivors?(Survivors.SPRITE_GUN)
|> unbox<Texture>
|> makeSprite
|> setPosition 100. 100.
|> addToContainer ground
|> ignore
createText("Level 1")
|> setPosition (state'.GetCenterX()) 50.
|> setAnchor 0.5 0.5
|> (fun x -> state'.Root.addChild(x))
|> ignore
state'.Root.addChild(ground)
|> ignore
// Set the state used to resolve the next Frame
{ state' with
State = Scene (Level1 Run) }
| Run ->
// Add here the game logic
// Example: Player movement
gameState
| Pause -> gameState
// Mutable the state variable
// This is the only mutation needed
state <- newState
// Render the view
state.Renderer.render(state.Root)
Browser.window.requestAnimationFrame(fun dt ->
gameLoop state dt)
|> ignore
There is a lot of code in this message sorry :). If we try to summarise:
Another benefit but not yet shown, will be the possibility to write a TypeProvider to have intellisence over the spritesheets.
I hope my explanation was clear if you have any questions/remarks don't hesitate :). I will try to post my code later, when I will have played with the game logic and the Behaviors system developed by @whitetigle and @alfonsogarciacaro
Excellent work @MangelMaxime thanks for taking time to share with us. π₯ And while I am at it thanks for the awesome doc on fable-arch. π
I will try to play with both architectures in my next projects and give you feedback.
Meanwhile, I think it's now time to move to Pixi v4 since v3 is now being deprecated even from the examples. (https://github.com/pixijs/examples/pull/24) I will take a look next week to see how we can move to v4. But maybe @davidtme would have some updated versions of the bindings?
Question: what if we use this electron app to hold the mini samples I was talking about ? I had a haxe based NW.js project which worked like that. We could have a front page/menu with a tiled display. Clicking on a tile would launch the mini sample with the inline doc and highlighted code?
PS : ok to use Kenney assets too !
Le 30/01/2017 Γ 22:24, Maxime Mangel a Γ©crit :
@whitetigle https://github.com/whitetigle I just made my code available here https://github.com/MangelMaxime/PixiTraining
This is not the best code ^^ but I am just raging on Pixi and also game dev (it's never go the way I want ^^) at the moment. So I need to make a pause. My idea was to use functions like in Mario sample http://fable.io/samples/mario/index.html to handle the steps inside the Scene Run.
I think the code can be enough to show the "function way" I was trying to follow. If you have any question please ask them here, or open an issue on my projet or even on gitter :).
PS: For the moment, we just have a player moment left and right ^^. PS2: I am using assets from Kenney - Abstract Platformer http://kenney.nl/assets/abstract-platformer
PS : I put your message there so we can get it for history.
^^ I was removing somehow on purpose because I don't want to give up ahah (change my mind after a good sleep π ).
For me this is ok to use electron to hold the mini samples. I am just trying to focus on the architecture for the moment but nothing prevent us to add a step before to make the page/menu.
Today goals for me is to animated the sprite with a walk animation.
@whitetigle I added a function to add animation for the player (really basic it's don't ensure full animation cycle, etc.). Just wanted to point this out because I saw you fork my repo :)
I will stop here (for real) for the moment. I don't know how to implement the collision and would like to know if you have any idea or sample for it.
Oh well I usually use physics based collision detection through engines like nape or box2d.
So today in the javascript world, there's matter.js we talked about. (cool pen by the way here)
One of my latest experiment with Fable was with SAT.js. I did not finish this sample but if I remember well basic collision was working. So I could go on with that if you wished.
Since I also use game engines based on physics like Construct2 or even 3D things like Unreal, I think our best move would start using one and avoid trying to reinvent the wheel or stick with simple things like this one.
Now I'm a bit biased on the question because on the frontend side I have always been more into puzzle games with lot of particles than action games especially platformers (shmups collisions being easier to solve). And usually collision has been just a matter of bounding boxes, hit points and basic distance tests without all the penetration stuff and complex shapes.
So being very pragmatic, when I need more then I simply go with a physic engine. So for the samples since what's at stake is making things functional whatever the underlying engine, we could choose one for all our collision needs? It would also allow for neat samples right away and would allow us to work on the logic rather than on that part of the engine. And make shiny things to show on social networks to promote Fable faster.
Hi @whitetigle and @MangelMaxime! Let's start a new issue as the previous one went off-topic long ago ;)
I've a bit of experience with game engines in the past (before I learnt functional programming) so here are my thoughts:
render
with something like Canvas is different from a GUI framework like DOM (or Windows Forms or whatever). In the latter,render
means updating the GUI component hierarchy to make some changes. This is expensive and it doesn't need to be done for every frame (actually the concept of frame is foreign to GUI frameworks), but virtualdom allows us to update the state without worrying too much about the actual DOM. On the other hand, with Canvas you draw raw pixel and everything must be rendered every frame (the only optimisation is to skip rendering of elements that are completely hidden).update
method, as it often involves expensive physic calculations. We need to receive the time elapsed (the argument in the callback to animation frame), first to do calculations by time and not by time frame (e.g. so bunnies rotate at the same speed even if the frame rate drops) and second to skip calculations that are not needed at that point.So we need to take the classic game loop and try to make it more functional:
I have a couple of concerns at the moment:
update
function. Any ideas?