Comments (12)
As I work with the pointer code, I'm wondering if I should flatten the kontra
object so there are no keys
, pointer
, etc. sub-objects.
The reason for this is that the functions exported by both of these don't make much sense out of context. Pointer has pressed
, onUp
, onDown
, over
, track
and untrack
. Keys has pressed
, bind
, and unbind
. These functions aren't very clear what they are doing out of the context of the keys
and pointer
objects if you were to import them by themselves. I already have to rename the two pressed
functions to be keyPressed
and pointerPressed
, so I might as well do the same for the rest of the functions.
// what exactly is onDown? Is it a key onDown event? Hard to know without the
// `pointer` context from before
import { onDown } from 'kontra';
This would mean I would move the pointer
and keys
context to the function names themselves and just have them be off the kontra
object directly. This gives two advantages that I see:
- There would be a 1:1 parity between function name and
kontra
function. Instead of havingkontra.keys.pressed
be one function butkeyPressed
be the function you have to import, it would just always bekeyPressed
. - The exported function names make more sense when imported.
onDown
isn't very specific butonPointerDown
is.
from kontra.
I'd like to help out with this, but haven't done this stuff before. Perhaps you could get one done and I can use it to mimic on some others.
from kontra.
Sounds great. The main problem is I've been trying to learn how tree shaking works. As the code is now, it's not very tree shakable so you get the entire library when you do some things. Things like adding event listeners on keyboard and pointer events in the main scope cause lots of problems.
The only thing I've been able to find is moving those things to their own functions that either the user has to call, like an init
function but for keyboard, pointer, assets, etc., or doing some creative code refactoring to make sure those things are auto inited when the user calls the standard functions. So when a user calls the bind
or pressed
functions of keyboard, the keyboard events are setup at that point instead of before (which means the first call will always fail since there's no events set up).
Example of option 1:
import { keys} from 'kontra';
keys.init(); // set up event listeners
keys.bind('a', () => {
// do things on 'a' key
});
Example of option 2:
import { keys } from 'kontra'
// calling pressed will setup event listeners, which means
// this is always false until after the function runs
if (kontra.keys.pressed('a')) {
}
I'm not really excited about either of these options but I'm not really finding anything else that can be done to make the code tree shaking friendly (which is mostly the entire reason to move to es6 module imports IMO).
from kontra.
Alright, so I think I found a compromise that will work (or will have to work). I've pushed my current workings to the es6Modules branch. I have currently done:
- animation
- core
- events
- gameLoop
- keys
If you look at keys.js
, I have to export the init function that adds the event listeners. Anyone who imports any function from that file will just have call the initKeys
function themselves since I can't find any way to to do it for them while still removing it from tree shaking if it's not imported.
import { initKeys, pressed } from 'kontra'
initKeys();
if (pressed('a'), () => {
// a key pressed
});
However, in kontra.defaults.js
, I add the init function to the kontra
object, and then can test to see if that function exists inside the main init function of core.js
, and if it does I can call it there. That will auto init the keyboard listener for anyone who imports the entire library or downloads the generated output of the entire library.
import kontra from 'kontra';
kontra.init(); // this will also call the keys init function now
My Guidelines so far
The general approach I'm currently taking is to extract all the objects (keys
, assets
, pointer
, etc.) and just make them export their functions. Then inside kontra.defaults.js
construct the objects with their functions to maintain the current API. That way you can import just the functions needed from those files and let tree shaking remove the rest.
I've also tried to make all the constructor functions (sprite
, animation
, vector
, etc.) Classes where it makes sense. There are some things (like the gameLoop
) where the amount of private variables would just bloat the code with so many this
references that it's noticeably smaller to leave it as is. For any Class, I've exported the factory function wrapper (so you don't have to call new
) and added the Class as the prototype to the function.
Lastly, I have a test file in examples/test.js
that I run rollup on and edit as I go to see how the output out.js
looks. You can generate it by running npm run rollup
. This lets me test things and make sure I'm not doing something that breaks tree shaking. Mostly what I've found is that accessing any global object/function, chaining functions, or using any imported variables/functions at the top scope will cause a side effect and break tree shaking. That's why in assets.js
the canUse
object was turned into a function since it needed access to a global Audio
call and chained the result.
Anyway, that's a lot to take in and this is still a lot of trial and error. Hopefully this works for the rest of the code.
from kontra.
Doing some work on this now, looks like I'm digging into assets, keys and sprite.
from kontra.
from kontra.
Alright, latest changes pushed. Although most of the files are converted to es6 modules, the organization and what is exported / how is still undecided for me. I don't like having to export init
functions for keys and pointer, but I can't think of any other way to do it while still having it work for tree shaking. I also went ahead an implemented your asset feature to return the asset if it already was loaded.
I also am still debating between lowercase or upper case for any factory function / class name export. Lower case is more like it is v5, but prevents using that name in your code
import { sprite } from 'kontra.js'
// cant name a variable `sprite` anymore
Upper case solves this but I'm just not sure how I feel about it.
import { Sprite } from 'kontra.js'
let sprite = Sprite();
Lastly, I'm trying to do all the breaking changes in this version, so if you have any breaking changes you've been wanting to make, let me know.
from kontra.
You might not have noticed that this change makes binding "space" doesn't work any more, now it's " ".
from kontra.
Ya... I wanted to use event.code
so it'd be space
but it's not widely supported. We could go back to keycodes, but the building up of it would have to move to the init
function as well (can't loop over the object and add properties in the main scope)
from kontra.
keys doesn't seem so hard, couldn't you give it an let initialized = false
variable and on the first line of bindKeys
and keyPressed
add if (!initialized) initKeys()
I suppose that doesn't work for keyPressed at first, which is a concern...
from kontra.
Is it possible to put a on('init', initKeys())
somewhere, like pointer used to do.
from kontra.
#66 works for me.
from kontra.
Related Issues (20)
- Render on whole pixels? HOT 3
- drotation HOT 2
- Link to Web Maker broken HOT 2
- TileEngine and Pointer Click HOT 1
- Cannot prevent children from rendering in class that extends SpriteClass
- Docs cut off first letter of prop description HOT 1
- Move tests to GitHub action
- Make dom nodes public HOT 1
- Vertical text alignment
- addToDom utility function should only look for direct children
- Idea: Community chat/forum? HOT 2
- Add container option to all components that create a DOM node
- Allow Sprite to draw single image from spritesheet / tilemap HOT 2
- Allow seedRand to save / load seed state
- Support padding for `SpriteSheet`
- GameLoop `tick` event not in correct place
- Allow `randInt` to accept a seeded random object HOT 3
- Allow `randSeed` to accept a number as well as a string
- Allow `randInt` to take a random function to generate the random number
- Add `preventScroll: true` to any `elm.focus()` calls
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from kontra.