-
Notifications
You must be signed in to change notification settings - Fork 8
Pixi: fail to use renderer #1
Comments
Hi there! The Pixi bindings aren't very tested so there may be some rough edges, sorry for that! The erased union types are indeed erased in runtime that's why you cannot do type testing against them. I'm not sure if it'll solve the problem but probably the best thing is to cast the returned valued directly with let currentRenderer =
Globals.autoDetectRenderer( 800., 600. )
|> unbox<SystemRenderer> |
Ok that works and it's simpler. Thanks! Regarding the Erased unions, I was following the example from https://fable-compiler.github.io/docs/interacting.html page:
Now you gave me the answer, I just tried to compile this example and it gives the same error I got. I should have started with this and ask you to understand what was happening. So to summarize we don't have to do the whole matching but we can just unbox to the desired type. Is that so? Now, I have done quite a few projects using Pixi in another language (Haxe). I am actually trying to port one using Fable and F# so If I encounter other problems may I ping you from time to time? Anyway thanks for your help! |
I put my notes here while I am working (please tell me if you want to start another discussion elsewhere). 1. optional values VS default values Let's take an example. Setting optional parameters for the renderer. JS F#
If I understand correctly interfaces in F# we must explicitely define all members. So setting a None value when the JS code is waiting for, let's say, a float value is certainly not what we want to do.. *So here is my question: is there a way to define default values instead or make options becomes REALLY optional (create the object in JS without the field) * For instance, the resolution parameter of my Options object is 1.0 by default. But here since we use an interface, we must explicitely set Some(1.0) since None is not what we want. In JS we just omit the parameter. In Haxe, we omit the field and it will create an anonymous object without the parameter. Can we achieve the same in F#? Am i right regarding the use of interfaces in F#? Thanks |
Fable Samples using Pixi: Instead of porting my app, The best move I can do now is to port the official samples so we check everything is working. [EDIT]: just found the samples dir https://github.com/fable-compiler/Fable/tree/master/samples/browser/pixi However since there are a lot of samples, I wonder how to define a single build file to generate the .js files from all the .fsx files located in a folder. I have not yet found a way to do this easily using fableconfig.json (any hint in the doc?) Do I need to use a .fsproj file? (excuse these newbie questions) [EDIT 2] I will go for a simple system script for now :) |
So far so good. Went up the 5 first samples without any problem. (although it may not be the best f# code one can read since it's quite new for me) Anyway I have prepared a simple html page that lists the samples and loads each of them dynamically showing both the f# source code and the sample. It's not live yet (in a private repository). I will go through all the samples and then we'll see what to make of all this codebase. Screenshot: https://postimg.org/image/coogcm4c5/ |
Sorry for the late reply. This is an awesome job! 👏 It'd be fantastic to add the samples to Fable's website 😄 I'll try to answer your questions now:
Thanks for pointing this out! This was actually a bug in Fable, it should be possible to type test erased union types (e.g.
Of course you can ping me :) Gitter is good for short questions and there're also other people listening there so you may get an answer faster there. But GH issues are also good to record answers so other people can easily find the info. Whatever is more convenient for you will work.
Yeah, this is an issue as unfortunately there's no way in F# to have optional members 😕 But as most of the times in JS this is done for option objects (as in this case) we have an alternate way: key value lists. Unfortunately, [<KeyValueList>]
type RendererOptions =
| View of HTMLCanvasElement
| Transparent of bool
| Antialias of bool
| AutoResize of bool
| Resolution of float
| ClearBeforeRendering of bool
| PreserveDrawingBuffer of bool
| ForceFXAA of bool
| RoundPixels of bool
| BackgroundColor of float Now you can only specify the options you need: let currentRenderer =
let options = [
Antialias true
Resolution 1.
BackgroundColor (float 0x000000)
]
Globals.autoDetectRenderer( 800., 600., options )
|> unbox<SystemRenderer>
It depends if you consider all samples to be part of the same project (in this case we may think of a project as one HTML page). I hope this helps! Please tell me if you have more questions and thanks a lot for your contribution! |
Hi! So in the JS sample there's the following piece of code var rt = new PIXI.RenderTexture(renderer, 300, 200, PIXI.SCALE_MODES.LINEAR, 0.1); So as you can see we've got this PIXI.SCALE_MODES.LINEAR value which comes from pixi.js SCALE_MODES: {
DEFAULT: 0,
LINEAR: 0,
NEAREST: 1
} So I still have this problem regarding default values and how to make sure we don't end up putting some wrong values in critical parts of the applications especially when these values already exist in JS So in our Pixi bindings our SCALE_MODES gets converted to type ScaleModes =
abstract member DEFAULT: float
abstract member LINEAR: float
abstract member NEAREST: float F# 1st way : way too complicated in my opinion and clearly not safe type ScaleMode() =
interface ScaleModes with
member this.LINEAR = 0.
member this.DEFAULT = 0.
member this.NEAREST = 1.
let mode = new ScaleMode()
let linear = mode :> ScaleModes
let rt = new RenderTexture(U2.Case2 renderer, 300., 200., linear.LINEAR, 0.1); F# 2nd way : same result and really not safe let LINEAR = 0. // this is the value as found in pixi.js code
let rt = new RenderTexture(U2.Case2 renderer, 300., 200., LINEAR, 0.1); F# 3rd way : safe as long as we don't emit wrong code. Too slow when it comes to testing: we must compile and then check at runtime [<Emit("PIXI.SCALE_MODES.LINEAR")>]
let LINEAR : float = failwith "JS only"
let rt = new RenderTexture(U2.Case2 renderer, 300., 200., LINEAR, 0.1); I did not use Key Value lists since in this case it would not help better Of course, I may miss other ways to do this since I miss experience in F#. |
We could used the third solution like this: module PIXI =
type SCALE_MODES =
[<Emit("PIXI.SCALE_MODES.LINEAR")>]
static member LINEAR : float = failwith "JS only" Here is how we can access it: let access = PIXI.SCALE_MODES.LINEAR Which is transparent with Pixi way from JavaScript point of view. @whitetigle I am also interested in Pixi.JS binding. If you want we could discuss on Gitter private channel to make our effort coordinate. |
Hi @MangelMaxime So far, my F# experiments have proven much more concise and robust that my previous attempt at functional code style using scala. Also the code is much more easier to read. So since I have some time to dig further these days, my next goal is to port one of my former Pixi project made in Haxe and evaluate the Pros & Cons of this approach. So for starters, with the help of @alfonsogarciacaro, I have started to port the official samples from Pixi.js; I am nearly done with the 12 samples from the basics section (http://pixijs.github.io/examples/index.html?s=demos&f=movieclip-demo.js&title=MovieClip#/basics/basic.js) Since the v4 just came out, of course I will be very interested to work with it and if we can make the codebase more robust with solutions like you mentioned then it will be a win for everybody. I must repeat but I am a F# newbie so these days I often stumble on basic stuff mostly things I haven't yet played with. (like fun vs Func this morning) But I learn fast. So like I said to @alfonsogarciacaro I think can help here by porting the samples and post issues / thoughts on the bindings to eventually have a clean, readable and robust codebase. Now regarding the V4, since it's very new, I think that we should keep a v3 and v4. The v3 has been there for quite a long time so it would allow non F#/Fable users - if such audience exists - to speed up their porting and it would also allow for a fallback. I say this because this morning when working on the TextStyle object I saw that the way to declare a font has changed leading to breaking changes. So we need to be careful with this to avoid at all costs errors coming from wrong bindings. I wrote/used several bindings in Haxe and Scala so I know how much time one can lose to eventually find that the bindings where plain wrong. Anyway, I will be glad to help as much as I can and also ask for help when needed. ++ |
In general I think it's not a good idea to access modules directly with Please note that, because of the way TypeScript definitions are usually written, "static" values in the bindings won't be represented as static members in F# but just as a normal interface and then you can access an instance of this interface in the |
PIXI.Globals. SCALE_MODES.LINEAR works just fine. Thanks! |
@whitetigle Ok. And thanks for showing the breaking change. I will play a little with v3 so in order to used a more "mature" lib. And will migrate later when confident with Pixi. :) |
I just set my repository to public.
you can serve the files from the root and see the samples + their relative .fsx Note: Bitbucket is my by default source code server to play. So I started there. But I can move to github if needed early. |
That really cool thanks. :) I just needed to change the name in the package.json file because it's wasn't installing the dependencies as it's not compliant with the convention I think. |
Ah yes, sorry, edited that. Thanks! I have 2 new questions regarding the current sample: 1 - createObject syntax I needed to create an uniform like in the sample and since the function was waiting for an obj I ended up writing this let customUniform = createObj [
"customUniform" ==>
createObj [
"type" ==> "1f"
"value" ==> "0"]
] While it works, is this the relevant syntax or is there another way to write objs? 2 - casting an obj to a string let fragmentSrc = resources?shader?data I then cast the data to a string like this: let fragmentSrcString : string = sprintf "%O" fragmentSrc Is this the correct way to do this in F#? [EDIT] let filters = new ResizeArray<AbstractFilter>()
filters.Add(filter)
bg.filters <- filters bg.filters = [filter]; 4 - change mutable value from an obj filter.uniforms.customUniform.value += 0.04; in F# filter.uniforms is a property then how can I change the value of its inner object (if that's an object?) I was thinking about reading then writing the value like this let curValue = filter?uniforms?customUniform?value
filter?uniforms?customUniform?value <- curValue + 0.04 But curValue being an obj I can not add it to a float (I know it is trivial but I can't find it in the docs) Thanks! |
Fantastic work, @whitetigle! I had a look at the samples and they look really good 👏 As you commented, the "least elegant" part is option declaration. So I just pushed I new version (0.0.4) of the Pixi bindings that replaces the interfaces with the
Yes, that's the correct syntax. It may be a bit verbose but I wanted to avoid conflicts. You can still define your own operators to make it terser as in this example (inlining the operators avoids unnecessary function calls in the generated JS code).
That syntax is correct, but if you just want to convert the object to string with no additional formatting you can simply use the let fragmentSrcString = string resources?shader?data If you just want to cast the object to string. That is, you're sure the object is a string and you want to tell that the compiler (of course, this is less safe) let fragmentSrcString = unbox<string> resources?shader?data
// let fragmentSrcString: string = unbox resources?shader?data // This is equivalent syntax
Yeah, ResizeArray can be a bit verbose. Actually, both F# bg.filters <- ResizeArray [|filter|] (It's a bit more performant if you use a literal array but it works with any |
F# doesn't include the let curValue = unbox<float> filter?uniforms?customUniform?value
filter?uniforms?customUniform?value <- curValue + 0.04 |
I just retrieved your latest version but compilation fails:
I tried to change this but ionide crashes Atom each time I load such a big file. Will try in VS. |
Error is right there (line395) [<KeyValueList>]
and RendererOptions =
| View of HTMLCanvasElement
| Transparent of bool
| Antialias of bool
| AutoResize of bool
| Resolution of float
| ClearBeforeRendering of bool
| PreserveDrawingBuffer of bool
| ForceFXAA of bool
| RoundPixels of bool
| BackgroundColor of float [EDIT]
Going to check the samples now. |
OK with patch applied it works! Bravo @alfonsogarciacaro @! 👍 [EDIT] tried unbox and ResizeArray and it works. Thanks! |
Damn! I should have checked better before publishing, sorry for that! 😅 I fixed the error following your indications and republished the bindings (0.0.5). Is Atom crashing with a file of that size? I'd recommend Visual Studio Code, it has more or less the same features and Ionide is available for it too 👍 |
Well I do have VS Code somewhere so I will give it a try. Thanks! |
Ok, here I am for some new questions (sorry!). In javascript I have button.on('mousedown', onButtonDown)
function onButtonDown()
{
this.alpha = 1;
} where this is the current button. Here is my current attempt in F# which fails let onButtonDown context =
let button = unbox<Sprite> context?button
button.alpha <- 1.
let context = createObj[ "button" ==> button ]
button?on("mousedown", fun e -> onButtonDown(context)) |> ignore
it fails to capture the local context and thus is applied to the last button I set (I create buttons in a loop). Passing the button object leads to the same result. So how can I do this in F#? |
Argh! I hate when JS libs do funny things with |
In Haxe we do keep the local context. For instance: button.click = function( data ) {
doStuff(button);
} But the first years (back in 2008 I think) we had to create a local context object and pass this object. I tell you this because the Haxe compiler is made in OCAML so maybe there are things to get from here? (Not a compiler guy myself. It's just a thought) |
If you can attach the event handlers directly to the object, deriving may work. Could you please try this? type MyButton(texture) =
inherit PIXI.Sprite(texture)
member this.mousedown() =
this?isdown <- true
this?alpha <- 1. |
Hi! Last question for today! I have started to port this sample: http://pixijs.github.io/examples/index.html?s=demos&f=movieclip-demo.js&title=MovieClip#/demos/text-demo.js Here we mix Text and BitmapTextObjects. So I started fiddling with our Pixi Bindings to use KeyValueList instead of long interfaces which led to: and [<KeyValueList>]
TextStyle =
| Font of string
| Fill of U2<string,float>
| Align of string
| Stroke of U2<string,float>
| StrokeThickness of float
| WordWrap of bool
| WordWrapWidth of float
| LineHeight of float
| DropShadow of bool
| DropShadowColor of U2<string, float>
| DropShadowAngle of float
| DropShadowDistance of float
| Padding of float
| TextBaseline of string
| LineJoin of string
| MiterLimit of float I did the same for BitmapTextStyle and ended up with : [<KeyValueList>]
type BitmapTextStyle =
| Font of U2<string, obj>
| Align of string
| Tint of float I then modified parameter accesses whenever it was needed from TextStyle to TextStyle list and the same for BitmapTextstyle. However F# does not seem to like having KeyFontValue types with Keys having the same name thus leading to errors when I try to do this: // BitmapTextStyle
let fontStyle = [
Font (U2.Case1 "35px Desyrel")
Align "right"
]
let mutable bitmapFontText = new extras.BitmapText("pixi bitmap fonts in f# are\n now supported", fontStyle)
// TextStyle
let style = [
Font "35px Arial"
Fill (U2.case1 "white")
Align "left"
]
let mutable textSample : Fable.Import.PIXI.Text = Fable.Import.PIXI.Text("Rich text with a lot of options and across multiple lines", style)
In fact my problem is that the compiler does not know how to make the difference between both styles. So what can I do? (updated bindings here: https://gist.github.com/whitetigle/b03e4689823d2950b711a81d4793df04) |
All pure pixi samples done! Notes:
|
Pixi being in the process to work, I will need
So, eventually I will have to port Howler.js too :) |
By tweening you mean purely math operations? It that's so, maybe there's something for in F#/.NET we could translate, but I'm not sure. If it requires something more platform related (like image manipulation), it'll be difficult to translate and it's probably better to find a JS lib. |
OK. I'll see. Thanks! |
@whitetigle I reviewed the samples, great job! :) I've made some small changes, mainly about formatting (shortening lines so they fit better in the web, etc), in the hope they will make the code a bit clearer for other users. You can check them and ask me if you have any question :) 621e856 |
@alfonsogarciacaro thanks! Cleaner is better! 👍 Question : what purpose lies behind the redesign of the animate function? [EDIT] You wrote a few days ago;
so does this sample mean we're good to go?
Also what does the false,xxx syntax mean?
Thanks! |
@whitetigle The refactoring of And yes, the bug for making pattern matching with erased unions is fixed 👍 Thanks a lot for discovering it! In the sample above, returning a tuple and then destructuring in the assignments is a common pattern in F# to return two values in one go ( |
@alfonsogarciacaro Thanks for these explanations! Everything's quite clear! Now I have been playing a little bit to port one of my project.
Here a sample which is directly applied from one of my very small project. type GameStates =
| Init
| LevelUp
| Play
| GameOver of GameStates
let rec animate =
let mutable state = Init
let rec animate (dt:float) =
count <- count + 1.
match state with
| Init ->
printfn "Init"
if count > 100. then
state <- Play
| Play ->
printfn "Play"
match Math.random() * 10. with
| x when x < 2. ->
state <- GameOver Init
| _ ->
match count with
| x when x > 100. ->
state <- LevelUp
| _ -> ()
| LevelUp ->
printfn "LevelUp"
count <- 0.
state <- Play
| GameOver nextState ->
printfn "gameover"
count <- 0.
state <- nextState
renderer.render(stage)
window.requestAnimationFrame(FrameRequestCallback animate) |> ignore
animate
// start animating
animate 0.
My main problem is since Thanks a lot for your help! |
@whitetigle I am not sure but I think the architecture used in the project https://github.com/fable-compiler/fable-virtualdom can be a solution. The idea behind Fable Architecture is that we react over Message that with use to update the Model and when the Model has been updated with can Draw the view from the Model. When playing with the architecture I needed something like 50-60lines to support manage the application. I don't know if it's what we should go with for games. Perhaps wait for the answer of Alfonso |
@MangelMaxime thanks for the hint! I will definitely take a look. |
@whitetigle It'd be nice to adapt the architecture developed by @mastoj and @MangelMaxime to a game engine (aka Fable architecture 😉). I've to admit I didn't have much time to play with it myself so I'm not sure if it's a good fit or not. Probably @MangelMaxime can correct me, but my concern is the Fable architecture (as well as other architectures designed for business applications like Elm or Redux) is event-driven (the updates are triggered when an event like a button click happens in the GUI) but in a game loop updates happen for every frame. At a very basic level what you need is an asynchronous recursive function so you can feed the function with the updated state instead of storing a copy somewhere and keep everything immutable and nice 😸 This can be done with F# // Convert requestAnimationFrame to Async
let awaitAnimationFrame() =
Async.FromContinuations <| fun (cont,_,_) ->
window.requestAnimationFrame(FrameRequestCallback cont) |> ignore
let rec animate state = async {
let state = update state // Update the state
let! _ = awaitAnimationFrame() // Wait for next frame
return! animate state // Recursive call
}
animate initState |> Async.StartImmediate Maybe this meets your needs. I've modified the blur-filter sample in the async-recursion branch to check the code works... and it does 👍 |
You are true about that Fable architecture is event-driven. But it's can also react to subscriber in order to push an update. Here is an example of a clock. I think this should be sufficient for certain type of games for example, this tetris game is made using Elm and the Elm architecture. (Fable architecture is actually a port from the elm one). Another solution is to follow the implementation shown by Elm games samples for example this mario game ported to Fable: https://fable-compiler.github.io/samples/mario/index.html But here the abstraction is really thin. There are others solutions existing in Elm, Purescript etc. but I find the two quoted above the most versatile and powerful. Because both enforce you to structure the program over a model. Initial Model -> Update Model -> Render Model -> Update Model -> Render Model -> ... And I find this structure really nice and you can build a lot of great tools over it to help you. Like time travel, watcher, debug (what again a time travel :) ) |
Right! I missed the part about producers in Fable architecture, sorry 😅 |
No problem :) I work with it all the day and night that help a little :) |
First of all, thank you both for your help. I begin to get a clearer and broader vision of F# and Fable. And I like it a lot 😄 So for starters I tried a first approach with the async idea from @alfonsogarciacaro. type GameState =
{
Count: float;
Level: int;
}
type State =
| Init of GameState
| LevelUp of GameState
| Play of GameState
| GameOver of State * GameState
let awaitAnimationFrame() =
Async.FromContinuations <| fun (cont,_,_) ->
window.requestAnimationFrame(FrameRequestCallback cont) |> ignore
let rec animate state = async {
let state =
match state with
| Init state->
printfn "Init"
let updatedState = {state with Count = 0.; Level = 0}
Play updatedState
| LevelUp state ->
printfn "LevelUp"
let updatedState = {state with Level = state.Level + 1}
printfn "Level is now %i" updatedState.Level
Play updatedState
| Play state ->
printfn "Play"
let updatedState = {state with Count = state.Count + 0.1}
match updatedState.Count with
| x when x > 100. ->
let stateAfterGameOver = Init updatedState
GameOver (stateAfterGameOver, updatedState)
| value ->
let nextLevel = (Math.floor(value) |> int) % 2 = 0
if nextLevel then
LevelUp updatedState
else
Play updatedState
| GameOver (nextState, gameState) ->
printfn "GameOver"
printfn "Level is %i" gameState.Level
nextState
renderer.render(stage)
let! _ = awaitAnimationFrame()
return! animate state
}
// start animating
let startingState = {Count=0.; Level=0}
let StartState = Init startingState
animate StartState |> Async.StartImmediate So it's a basic loop that updates a GameState record. There's the render call for the current frame that does nothing in this sample but would update sprites, effects, etc.. So it is working, it looks like what I was looking for and I think it's a good basis for discussion. |
@whitetigle Yes this could be adapted to Fable architecture. I will try to implement a simple version with your sample just to have a comparison. |
I must also say that I overengineered my solution above a bit. The same effect can also be achieved without let rec animate state =
let state = update state
renderer.render(stage)
window.requestAnimationFrame(FrameRequestCallback(fun _ -> animate count)) |> ignore
animate initState |
|
@MangelMaxime I was wondering this morning about having the ui components in the dom to leverage the virtual dom approach and let the core game rendering with requestAnimationFrame as usual. |
@whitetigle VirtualDom support what we call Producers and Subscribers. So if you want to communicate with the external world you can use them. For example, this is how we are managing the SPA approach for the router part (the browser detect the
Here is a sample of a Producer: https://github.com/fable-compiler/fable-virtualdom/blob/master/samples/clock/clock.fsx#L68 Here is a sample of a Subscriber: https://github.com/fable-compiler/fable-virtualdom/blob/master/samples/subscriberexample/subscriberexample.fsx#L54 Also, in a future version of VirtualDom we will have support for a plugin structure which will allow us to capture not only the messages but also the Model. At the current point I think Producer/Subscriber can be enough because I don't think we want to share the whole model between the Pixi world and VirtualDom world. The Model will have more information than just the useful one like HP amount, clicked, etc. For example, in VirtualDom you need to keep track of the value in the input. And as I am working on the Fable Architecture version for Pixi binding we could probably have a Pixi App and a VirtualDom App. I hope to publish a first version today. Off scope of your question: |
@whitetigle I have pushed on a new branch a sample showing how we could implement the Fable Architecture over Pixi. I like this kind architecture which enforce the separation between the View / Model / Update. But here the view function is quite hacky because we don't have the support of VirtualDom / React to help us handle the diff, patch, rendering etc. I think you have a better experience of Pixi than me and probably you will another way of handling the view. I don't really know how we use Pixi to do that :) (learning it since 1 week^^) I put a lot of comment to help understand what's going on but if you have a question don't hesitate to ping me. @alfonsogarciacaro Ping you, if you want to take a look. From my point of view, this architecture could be viable if we find a better way to handle the View part. If you have any idea I am open :) Perhaps we should try to make a really simple game like pong with both and try to see which one fit the best our needs. |
Well just a few thoughts about pixi before I dwelve into the details of your sample (very impressive by the way 👍 ) : We do need requestAnimationFrame since that's the only method that guarantee that the next draw will happen as soon as possible. It's kind of Browser enforced. SetInterval tries as fast as it can but can be delayed by system calls or whatever "noise" so there's absolutely no guarantee we'll get a stable frame rate. Then we would have different needs:
Then we do have events that need to interact with both kind of objects. For fast rendering we have two scenarios:
There too Pixi takes care of the events for us and we want to communicate as fast as possible to avoid any lag. Now all games are different.
So most of the games want 40-60 fps and they want it smooth (hence the need for requestAnimationFrame). But there's an outstanding number of games that do not need more. So there are several choices we could make that would just be pragmatic and allow us to ask for fast rendering just when it's needed, not for all components, not all the time if it allows us to have a good and robust architecture. So I will dive into your code and try to understand as much as I can. |
Thanks for all this explanations and this is what I what thinking when writing the sample. For me we should dig in the direction of your proposition and the mario architecture. And perhaps simply offer the user helper library like Keyboard event management, tween, etc. But not "forcing" them to Fable Architecture or a similar one has it's probably to complex for a game. We could probably simply say here is the recommended way to go with Fable + Pixi and let them experiment they own architecture if they want. I have always hated play with Engine because they force you to do things their way and usually I don't like it :). [Edit]: I will wait your impression on the work done. And perhaps we could simply take inspiration from part of the work. |
@MangelMaxime Great work! I've limited access to my computer until Friday so I cannot have a deep look yet but I'll check later to see if I can so some comment (though I think you've now much more expertise on Fable architecture than me 😉). In any case, I agree with @whitetigle that |
Yes I agree too about the requestAnimationFrame just did think about it on the moment. I will change the producer to use this function. Probably true about Fable architecture but you still have a better understanding of the Functional paradigm :) So you could probably think of a better way to handle the view function which is not has good has it should be ^^. (But I didn't find a good structure). |
Ok. I would like to make a test with porting bunnymark http://www.goodboydigital.com/pixijs/bunnymark_v3/ to your architectrue and see what happens. What do you think? Could you just update the code so we use |
Hi! If it's ok for you, Since it's quite a complete sample, I plan to add it to the samples when done with the inline documentation. Featuring:
So a kind of Pixi soup 😉 To change the speed of the animation, just move your mouse close or far from the center of the screen. farther = faster. closer = slower. Mouse up and down to fade the animation et voilà! Last but not least, I will push some new changes to the bindings this week since I have found new little optimizations. |
@whitetigle That looks über cool! 👏 https://twitter.com/FableCompiler/status/775310166988324865 |
@whitetigle It's a really cool sample. I love it :) Nice work 👏 |
Thanks! 😄 I'm glad you enjoy it! Oh, by the way, Uuntil I'm ready to push the sample, the source is there One more thing, @alfonsogarciacaro since you use twitter, and I can't get access anymore to my old account @whitetigle, I have created an new account: @thewhitetigle. |
Hi!
I am trying to setup a very simple Pixi project. However I fail right at the start with a compilation error.
Since I am new to both Fable & F# there may be things I do wrong. Or maybe I did not understand the Erase attribute sample in the doc since Globals.autodetectRenderer returns a U2<WebGLRenderer, CanvasRenderer>
Anyway here is my code :
When I compile it says :
which corresponds to my renderer value
I use fable-core 0.5.5.
I have tried other ways but I can't get past this error.
Thanks for your kind help!
The text was updated successfully, but these errors were encountered: