-
-
Notifications
You must be signed in to change notification settings - Fork 186
Developer Log
Hi I'm Quinton Ashley and this is my journal about the creation of p5play. I'll be updating it periodically with behind the scenes info!
Project Roadmap: https://github.com/users/quinton-ashley/projects/5
p5play manages much of the frame cycle (aka "game loop") processes behind the scenes, before and after the draw
function. My priority with this design was to keep things super simple. Yet thus, in typical use, not much drawing happens in a function called draw
, which probably seems odd to beginners not already familiar with Processing/p5/q5.
In most game in which physics updates are synced with frame updates, frame creation occurs in this order:
- handle user input
- game logic
- physics simulation
- draw
- post-processing
Previously in p5play, steps 1, 2, and 4 were done in or after the draw
function, before each physics sim update. I didn't realize that this essentially adds a one frame delay to physics body movement. I had to fix this!
In v3.26 I added a new global function named update
, named after Unity's MonoBehavior.Update
function. It runs before the physics simulation, ensuring that changes to physics body movement will take immediate effect and then be displayed.
For backwards compatibility p5play v3.26+ will still run draw
before physics updates, but automatic drawing of sprites is now done after. Changing existing code is not strictly necessary. In v4 I’ll make draw
run after the physics update, which will be a breaking change. By soft launching these changes in v3, user can start writing code that’ll be compatible with version 4.
The update
function is for input handling and game logic. It's also fine to do static drawing in update
, using functions like clear and background.
The drawFrame
function is for custom drawing using sprite.draw()
and group. draw()
I've updated all the p5play Learn reference pages to use the update
and drawFrame
functions, when optimal!
The first Learn page explains what the setup
and update
functions are for.
https://p5play.org/learn/sprite.html
Nearly all p5play.org examples rely on automatic drawing, so drawFrame
is only used in examples that use the camera.
https://p5play.org/learn/camera.html
Examples like this one definitely feel more responsive:
https://p5play.org/learn/sprite.html?page=14
I gained a better understanding of how game loops work by reading this chapter in "Game Programming Patterns" by Robert Nystorm.
https://gameprogrammingpatterns.com/game-loop.html
@Tezumie also suggested adding a postProcess
function, which I added to q5.js.
https://q5js.org/learn/#postProcess
In other news, exciting work is being done by Birch-san and contributors porting Box2D v3 to wasm.
https://github.com/Birch-san/box2d3-wasm
I will start development on "q5play" (p5play v4) in the new year!
https://q5js.substack.com/p/q5js-webgpu-a-love-letter-to-processing
https://q5js.substack.com/p/the-p5js-reference-pages-are-bad
Update v3.25 includes my first draft of the “p5play Personal License”, which will continue to enable free, open-source, personal use of p5play, while replacing the AGPL.
Although I’ve consistently outlined my interpretation of the AGPL on p5play.org and in p5play’s EULA, I believe that switching to a custom license with clearly defined terms is a more transparent and effective way to protect my work and market p5play for educational and commercial game development use going forward.
Educational use requires the p5play Educational License. https://p5play.org/teach
Commercial game development requires the p5play Professional License. https://p5play.org/pro
I also resolved an issue with the p5play Professional License regarding “portfolio projects”—games or apps no longer in active development. I will not require users to maintain a Pro subscription just to showcase past work to clients or to sell older projects.
Additionally, while I’d hope that anyone achieving commercial success with a project made using p5play would naturally want to give back to the community, I’ve added a revenue-sharing clause to ensure this. If a user earns over $1,000 USD in gross revenue from a p5play-based project, 5% will go towards supporting the development of p5play, q5.js, and free p5play tutorials on YouTube. By keeping upfront costs low and tying greater costs to actual success, this model could support sustainable growth. In the future I hope to remove the upfront cost of the Pro subscription for student developers.
Finally, I’ve updated the p5play Educational License to confirm that student accounts will retain access to the Learn pages indefinitely, even after the instructional term covered by the license has ended.
I'd appreciate any feedback be sent via a direct message on Discord or email. Thank you!
The "Learn" section of p5play.org is an interactive textbook I've been writing for the past two years. 👨🏫 Making it publicly available during this time provided me with a lot of useful feedback, which I'm grateful for! 📖
Now that it’s finished, this resource will still be free for personal use, but educators/schools need to pay for a p5play Educational License to use it in class or coursework. The $5 per-student, per-semester cost is fair and affordable! 📚
I'm trying to strike a balance here between open source and monetization. I don't want the p5play library to lack core features that users would need to pay a premium for. I think the only way to deeply learn how software works is being able to look at the source code.
But I also believe that the hundreds of hours I've put into writing the Learn pages has resulted in something of real value for CS educators. I hope you agree and will support my development of p5play.
If your school or university would prefer a custom invoice with a different time frame, I can make one. Let me know how many students will use p5play and the duration of use.
Some people have suggested I put advertisements before running student’s code or on the Learn pages instead of charging schools to use them. I will never do that! I think it’s unethical to sell student's attention to advertisers during instructional time or when they're doing coursework. I believe that schools should pay to provide high quality educational resources for their students, not essentially forcing their students to pay via ads.
I also don't expect teachers to have time to cover all of p5play's features during class, so charging for beyond the basics wouldn't be an incentive. My intent behind including so many core features is to entice students to learn p5play. It's what makes p5play different from a lot of Ed Tech platforms that are so basic, they're only good for teaching intro level CS. As a student I felt like everything I was doing in school was just eternal preparation for the next thing. I want students to feel empowered by p5play.
If you think your school or district will not pay, please still petition them to do so. I can answer any questions they might have to try to persuade them. If they deny your request, don’t misdirect your anger at me. I don’t think any teacher should have to pay out of pocket for learning resources and supplies. If the costs are a legitimate barrier for you or your school, please let me know.
p5play isn’t some big corporation, I need to find a way to sustain my work so the project doesn’t die again. I promise that if p5play ever gets sufficient institutional funding, I will make the Learn pages completely free. Until then, I need grassroots funding to continue working on p5play.
Hi I'm Quinton Ashley, the creator of p5play v3.
I've spent thousands of hours over the past two years developing p5play but I still haven't been able to meet the community's demand for new features and maintenance updates. I want to find a way to work on p5play full time and eventually hire other developers to help make p5play the best it can be. That's why I need your financial support!
I've found a good balance between open source and monetization with the multi-licensing model. I based it off other successful open source projects like Qt and MySQL.
On the one hand, I want to offer p5play as a fully featured game engine to anyone that might be interested in using it. I don't want users to feel like it lacked core features they'd need to pay a premium for. I also believe the only way to deeply learn how software works is being able to look at the source code.
Also, none of p5play's licenses allow users to make closed source modifications to the library itself, this ensures that any improvements made to p5play will be shared with the community.
On the other hand, I want p5play to generate revenue so I can continue to develop it and make it better. I think p5play's ease of use compared to other game engines has real value. If you financially benefit from using p5play, it's only fair that you support its development.
If you have a strong opinion about p5play's business model, I'd like to hear it! Please send me an email to [email protected]
Patreon supporters now have access to iOS app templates!
WebGPU is the latest and greatest graphics API for the web.
If you have a chromium based browser, check out this WebGPU demo. It can draw millions of flocking boids using BabylonJS! https://www.reddit.com/r/GraphicsProgramming/comments/13cemv5/webgpu_millions_of_flocking_boids_with_babylonjs/
Dec 21, 2023 : Starting in Safari Technology Preview 185, WebGPU can be enabled for early testing and development. https://webkit.org/blog/14879/webgpu-now-available-for-testing-in-safari-technology-preview/ https://mil-tokyo.github.io/webdnn/docs/tips/enable_webgpu_ios.html
January 17, 2024 : The Chrome team is excited to announce that WebGPU is now enabled by default in Chrome 121 on devices running Android 12 and greater powered by Qualcomm and ARM GPUs. https://developer.chrome.com/blog/new-in-webgpu-121
WebGPU will probably be supported by all major browsers soon. But when will p5.js support WebGPU? Probably much later... maybe never.
I want to make a new version of q5.js, which implements p5's 2D API with WebGPU. Only one problem, I don't know much about low level graphics programming!
For now I'm going to prioritize working on p5play.
Resources:
https://www.youtube.com/watch?v=m6T-Mq1BPXg https://developer.mozilla.org/en-US/docs/Web/API/GPUCanvasContext/configure https://codelabs.developers.google.com/your-first-webgpu-app https://webgpufundamentals.org/webgpu/lessons/webgpu-orthographic-projection.html
Many moons ago I wanted v4 of p5play to use liquidfun-play-2 under the hood. It's the latest version of box2d-wasm with google's liquidfun extension. https://github.com/Birch-san/liquidfun-play-2
Since then planck.js v1 was released, it performs significantly better compared to the alpha versions. Also there are benefits to having direct access to the physics simulation in JS. For example, advanced users can do things in planck that I haven't put a nice p5play wrapper on yet, for example Discord user @ coding 's recent use of world.rayCast
.
JavaScript is actually really fast at doing math nowadays and in a head to head test with emscripten compiled C code running in wasm, the results are basically the same! https://jtiscione.github.io/webassembly-wave/
I'd need to do a real test comparing planck.js and liquidfun-play-2 to actually see the difference.
For now I'll be sticking with planck!
Back in August, I had rather naively hoped to release a p5play iOS app template in late September. But a LOT of work needed to be done before I could provide p5play users a proper mobile development experience.
Here's a summary of my progress:
- achieved feature parity between p5.js v1.9.0 and q5.js, a smaller and faster implementation of the 2D p5.js API
- implemented a text image caching system that improved rotated text performance by 90x
- refactored the core of p5play, its contact (collision and overlap) handling system, for better readability and performance
- fixed all known issues with p5play, the next release will be marked as stable
- wrote the p5play Novice and Professional licenses, which will legally enable app store publishing
This is what I plan to do by the end of this month:
- implement p5play input functions
presses
,pressing
,released
for touch objects - release the iOS app template project for Patreon members
- add mobile development features to the p5play Visual Studio Code extension
- publish the "p5play dev" iOS app that will enable users to test out their projects on mobile for free
My second attempt at creating a new collision and overlap handling system is so much simpler and just better in every way than the previous ones. After I figured it out I thought, "Why hadn't I thought of this before?", but such clarity was only achieved after slogging through 2 months of refactoring. I was not having a good time by the end of it lol but it really had to be done and I'm quite happy with the results!
There were unfortunately quite a few bugs with v3.16 though, despite all my new tests. v3.17 is finally holding water though!
Until now, I actually haven't attempted to create a full game with p5play myself. It's been great to analyze the library as a whole, after spending so long hyper-focussing on individual parts.
My biggest issue with p5.js in terms of workflow, is the necessity of the preload
and setup
functions, because it forces users to create variables on the file level but define them separately. In q5 I've implemented a global mode that solves this issue. Just put new Q5()
at the top of a sketch and everything you'd normally put in preload
can go after that. If a setup
function is defined, it'll run after loading is complete. (I found that it's necessary to create sprites in setup
if they use group animations, which need to be loaded before they're copied internally for use by group sprites.)
Using q5's improved global mode is so nice, I'm definitely going to make a YouTube video about it!
I recently did a big overhaul of the collision and overlap system in p5play v3.15, but I think I could do better.
The main issue with the previous system, in v3.14 and before, was inside the sprites' _step
function, which gets run on every physics world step. If a callback was not found between the sprites, it'd search between their groups starting from their first group: allSprites. Searching for callbacks on every frame is inefficient, especially when one might not even exist. It'd actually search twice, since the order of inputs to the callback function matters.
In v3.15, I kind of solved the issue by using more memory to save sprite-to-group or group-to-group contact callbacks inside every sprite in a group. The contact relationships of the group are inherited by any sprite added to it as well.
But it has a big problem, take a look at the following example:
let group0 = new Group();
let group1 = new Group();
let spriteA = new group0.Sprite();
let spriteB = new group1.Sprite();
group0.overlaps(group1, cb1);
spriteA.overlaps(spriteB, cb0);
Only cb0
would get run on overlap. If the last two lines are reversed, then the group overlap would override the sprite overlap. I don't like that! So my first attempt at refactoring the contact handling system has failed, it's not going to stick.
I want to implement a new contact handling system that could run both overlap callbacks. I'm going to try a hybrid approach that will consume less memory and only do a little searching to get group callbacks. Stay tuned!
For the past 2 months, as soon as I fixed an issue with p5play I'd find another one... 🐞🐛🪲🪳🪳🪳🪳😭
It felt like I'd never be able to finish this update, and yet here we are! 😅
And yeah... it seems like every month I re-announce that p5play v3 is "quite nearly finished"TM, but then I get some other idea for something that'd be cool to add to it. 😆
But p5play now has over 1,000 users per day, so I'm going to start prioritizing stability and performance over adding new features. The rate of mainline releases will decrease, and I'll make incremental progress in https://p5play.org/v3/p5play.beta.js
so people can opt-in to beta testing or not.
It's a bit demoralizing to find mistakes in my code, but as the old saying goes, "You have to break a few eggs to make an omelette!". That means, "In order to achieve something, it's inevitable and necessary that some mistakes are made or some sacrifices must occur." 🥚🍳
So please continue reporting any issues with p5play on Discord or GitHub, it really helps me out.
My #1 goal is to make using p5play a great experience, so I hope you all enjoy the update! 🎊
p5.js has event functions such as mousePressed
and keyPressed
which give developers an easy way to respond to input events, similar to plain ol' JavaScript. But, it'd be a bit cumbersome to program combinatory input actions (Ex. do x when mouse pressing and the 'up' key being held) if developers were limited to these event functions.
So p5.js also provides variables like mouseX
and key
which developers can access in anywhere in their sketch. The problem is that games often require more precise tracking of what state the input is in, not just if a user is pressing a key or not.
p5play has its own InputDevice
paradigm that solves both of these issues, enabling developers to easily check for a combination of inputs and the status of the input. See the Input page for examples.
I had examples on p5play.org that used sprite.ani = 'name'
to change which animation a sprite was currently displaying. I realized that's actually super confusing because the primary purpose of sprite.ani
is to enable users to easily access the sprite's current animation. This caused users to be confused about how to check the animation's name (via sprite.ani.name
).
I've changed all the examples on p5play.org so they use the sprite.changeAni('name')
function for changing which animation the sprite displays and sprite.ani
is only accessed, not set.
p5play v3 is basically finished! 🎊
Its performance is great on my M1 MacBook Air, achieving 60fps fullscreen, even with 500+ sprites on screen. But it leaves much to be desired on older hardware. Although, I am impressed that it can do ~60fps on my wife's iPhone 11, albeit with low sprite counts.
When I started working on p5play v3, I knew that planck.js was slow compared to matter.js, but my main goal was to use the highest quality JS physics simulator available. Yet, v3 technically could've been made in 2017. It doesn't take advantage of WASM, which has been available in all modern browsers (most recently including Safari) since March 2023. Physics engines basically just do a bunch of intensive math problems, so taking advantage of WASM represents a huge leap in performance.
Just a few months after I started working on p5play v3 back in 2022, I found out about Birch-san's box2d-wasm, the latest version of which is liquidfun-play-2, released in 2021. It only has 26 stars on GitHub. I think it's not very popular because it's even harder to use than planck.js, but it's truly on the cutting edge of both performance and quality among JS physics engines.
The reason I didn't immediately stop working on p5play v3 to work on a v4 with box2d-wasm is that I'd already put a ton of work into v3 and wanted to "finish" it. I also thought I'd make v4 a Pro version, only available to paying Patreon members. But if I had developed v3 and v4 concurrently and made any mistakes, it'd be prohibitively time consuming to do bug fixes for both versions. I opted to focus on making v3 solid first so I could use it as a base for v4. In hindsight that was a great decision because user issue reports (especially from Raj Raizada, @ Tezumie, @ Day, and Caleb Foss) have been critical in helping me find bugs that I might've never encountered on my own. It's also become apparent that to really compete with Phaser and Unity, p5play v4 will need to be free to use.
Also currently, mobile app publishing on iPhone is prohibitively expensive for many students and schools. Apple requires developers pay them a $100 fee for the privilege of publishing apps. But that will change soon, since the EU ruled that Apple must allow other app stores on iOS.
Part of the problem with performance on iPhone was that for years I think Apple purposefully made iOS Safari's HTML5 canvas implementation slow, so that users could only download performant games from Apple's App Store. Currently every other browser on iOS must use WebKit (Safari) under the hood, due to Apple's restrictions. But the EU has also outlawed Apple's monopoly on iOS web browsing. My dream is that Google will implement a completely custom version of Chrome on iOS. They'd write a better HTML5 canvas implementation, which could cause Apple to improve theirs, or perhaps Google will release a ChromeKit module for Swift.
All of this is great news for the future of p5play game development on mobile devices!
But personally, the thought of implementing v4 right now, even with the benefit of using v3 as a base, is quite daunting.
Here are my plans for the future (in no particular order):
- update the p5play.org homepage
- finish editing and publish a few videos about p5play on social media
- release an iOS app template to Patreon members, enabling them to publish apps
- publish the "p5play dev" iOS app, which is basically just the template app but it will enable users test out games on iPhone for free
- try to get more funding for p5play by reaching out to Universities
- develop my own game using p5play and publish it on the App Store
Officially introducing Joints! https://p5play.org/learn/joints.html
On a personal note, v3.9 feels like the culmination of over a year's worth of work since I released v3. At the time, I was honestly worried that it could be a fruitless attempt to revive the project. 😬
I'm so grateful that my new version has been embraced by so many people around the world. It's been a great gift to see all of your creations made with p5play! 🎁 Also, a few days ago I found out that CodeHS created a course called "Introduction to Game Design with p5play" that includes videos and interactive lessons, cool stuff!
In the coming months I want to focus on growing this community via YouTube, Instagram, and TikTok.
I will be releasing v3.1.0, a big update to p5play, soon! This update will contain changes to the input system. I'm sorry to make these changes kind of late in p5play v3's development but I think it's important p5play uses the same verb conjugations for all timing related functions.
I was inspired to make these changes because I'm adding a new paradigm for custom collide and overlap event handling that won't require the use of callback functions and can be used in if
statements. This feature has been highly requested by my students!
In technical terms, single frame initiative timing functions will use present simple tense naming. Continuous timing functions will use present continuous tense naming. Single frame cessation timing functions will use past simple tense naming. For example collides
, colliding
, and collided
. This will allow users greater control over customizing collision and overlap event response!
The past tense functions pressed
and held
will become alternatives to released
. Their old functionality will be replaced by the new presses
and holds
functions. presses
will return true on the first frame the user presses an input. holds
will return true when the users holds an input for 12 frames (by default). The mouse functions for detecting hovering will be changed to hovers
, hovering
, and hovered
.
Here is an example of the new collides
function in action. The "old way" will still work too.
// old way
player.collide(block, () => {
block.remove();
});
// new way
if (player.collides(block)) {
block.remove();
}
Note my preference for if
statements over callbacks. if
statements are taught at the beginning of any intro level programming class and are more readable.
In the preceding example, collides
returns true on the first frame a sprite collides with a target sprite, colliding
returns true while a sprite collides with a target, and collided
returns true on the frame when contact between the sprite and target end. overlaps
, overlapping
, and overlapped
functions will be available too.
You all can thank my wife for these naming changes, she's an English teacher!
A Sprite in p5play is a container that can have visual components AND/OR a physics body.
The new and old versions of p5play use this design for the Sprite class, and so do other modern game engines, even though historically the term "sprite" is more narrowly defined as a bit-map image that could move across a screen via hardware rendering. Kids don't have that preconception though.
As teachers we must always be willing to challenge our preconceptions about how things should work and be open to the possibilities of how things could work. Building on what was to teach what is. The JavaScript language itself embodies this philosophy, having received major feature updates in recent years. The JavaScript community is also, for better or worse, filled with independent thinkers that use varied programming paradigms. Thus, JavaScript programs made this year may look significantly different from JS programs made 10 years ago. That's not true for other languages like Java, which hasn't significantly changed since Java 8.
In this Dev Log I'm going to give really in-depth and technical explanations of stuff that I've seen is innate for kids learning p5play.
When young students want to create a sprite, the assumption I based p5play's new design on is that they also want a collider, so creating a sprite adds a box collider to the sprite by default. Not a super radical design choice for a physics based game engine right?
Throughout the codebase, I tried to use sensible defaults so that users can write less code. The code users write should feel impactful. I wanted to avoid forcing users to write boilerplate code which they don't understand. For example, students learning Java have to first write or at least get a template of a Java class that has a static void main method, simply for them to write their first line of code!
class MyClass {
public static void main(String[] args) {
System.out.print("Hello World!");
}
}
That's a load of nonsense just to print "Hello World!" in the console. Java teachers have to hand wave away this complexity at first, telling students that they'll learn what it means in the future, which is not a good experience. Also because students don't understand it, Java's main method can be hard for students to memorize. Better designed languages like C# do not require command line programs to be inside of a main method of a class, C# encapsulates user's code behind the scenes during compilation.
On the first few Sprite reference pages I have mini-examples that don't use any inputs in the Sprite constructor or functions. My goal is to make the p5play learning curve as flat as possible by decreasing the knowledge and skill barriers required for students to start using p5play. Multi-parameter constructors and functions, even rigid ones with only one set of valid inputs, require the user to memorize how inputs must be ordered or refer to documentation. They're inherently not as readable and beginner friendly as verbosely setting property values. Also students are familiar with variables from Algebra class. They already understand that =
sets the value of a variable.
sprite = new Sprite();
sprite.width = 40;
sprite.height = 20;
p5play can seamlessly replace the sprite's default box collider with a circle collider if the user sets a diameter for the sprite. This happens "behind the scenes" in the diameter setter.
let sprite = new Sprite();
sprite.diameter = 50;
This was not possible before JS property getters and setters were introduced! This is a bit remarkable for us seasoned programmers but it's irrelevant to beginner programmers. They think, "Why wouldn't setting the sprite's diameter make it have a circle collider?". Remember, they have no intellectual baggage regarding what properties, constructors, and methods are. Yet, when I learned how getters and setters could be used in JavaScript, I had to replace my old mental model I had from using Java that functions were for doing stuff and properties were for storing stuff.
Another interesting use of getters and setters in p5play is with the custom draw function. Users can set custom draw functions for sprites like this:
sprite.draw = () => {
rect(0, 0, 30, 50);
};
The draw function can then be used to draw sprites in the p5.js draw loop:
sprite.draw();
But wait, sprite.draw
, is actually a getter/setter and it's not getting and setting the same function! sprite.draw
sets the user's custom sprite._draw
function and sprite.draw
gets the sprite._display
function, which does some stuff before and after calling the default or user's custom sprite._draw
function.
// p5play source
get draw() {
return this._display;
}
set draw(val) {
this._draw = val;
}
Beginner programmers using p5play don't need to know or care that this is happening behind the scenes but it's necessary for the user not to re-implement all the code that's in the display function. In previous versions of p5play, custom draw functions for sprites were achieved by having the user actually set the sprite.draw
property but then use drawSprite(sprite);
which used the private sprite.display
function for displaying the sprite, which is a bit cumbersome by comparison.
Another clever use of getters and setters is with the ani
property. Here's the old paradigm for changing the sprite's animation:
sprite.changeAnimation('jump');
And here's the new paradigm:
sprite.ani = 'jump';
Isn't that cool?
I also deprecated setSpeed
which used to take speed and direction angle parameters.
sprite.setSpeed(5, 90);
Now users can set speed and direction separately, and the line order is not important!
sprite.speed = 5;
sprite.direction = 90;
Anyways, back to the Sprite
constructor, which can be used to define the sprite's collider. p5play sprites don't need to have a p5.Image
or SpriteAnimation
.
let ball = new Sprite(x, y, d);
An image or animation can be added to a sprite after it gets created.
let ball = new Sprite(x, y, d);
ball.image = img;
The Sprite
constructor can also be used with a loaded image or animation, from which it can derive the width and height of the collider.
let box = new Sprite(img, x, y);
...or both the visuals and physics collider of the sprite can be specified in the constructor.
let box = new Sprite(img, x, y, w, h);
let ball = new Sprite(img, x, y, d);
The flexibility that the Sprite constructor offers might seem unusual for older programmers that are used to more rigid APIs but I'd argue this flexibility is quite nice for kids learning how to code.
Yet, just because you can fully load the constructor, doesn't mean you should...
// (img/ani, x, y, w, h, collideType);
let box = new Sprite(ballImage, 0, 70, 10, 30, 'static');
If you think the Sprite constructor is able to do too much, you can just use it for less. Its flexibility means you can use it the way you want. Remember that it's not even strictly necessary to add any inputs to the Sprite constructor at all. The amount of valid use combinations that the Sprite constructor has isn't easily definable, but it doesn't need to be. Part of what makes JavaScript so great is that methods and constructors don't need to have a rigid set of valid inputs.
For the Sprite constructor I think it's pretty easy to remember the order of the inputs, which is the same regardless of the collider shape:
(animation, position, dimensions, colliderType)
width, height // box
diameter // circle
sideLength, polygonName // regular polygons
Whenever possible I tried to keep functions simple and flexible. However, for SpriteAnimation Spritesheet atlases I went with the more standard "options in an object" approach, which I think works well for something that has sooo many different options: {width, height, size, pos, line, x, y, frames, delay, rotation}. Imagine how bad this would be:
// x, y, w, h, frames, delay, rotation)
sprite.addAni('imageFolder/spritesheet.png', 4, 6, null, null, 11, 50, 90); // BAD!!
The "options in an object" approach is great because the options can be in any order and it's easy to read what the numbers are defining.
sprite.addAni('imageFolder/spritesheet.png', { pos: [4, 6], frames: 11, delay: 50, rotation: 90 });
But this approach does require students to understand objects, so there are two other modes for loading animations, sequence and list, that don't require objects are simpler to use.
When designing the Sprite
constructor I didn't want to impose upon beginners the necessity of learning object syntax or a bunch of magic constructor spells like ImageSprite
, BoxSprite
, CircleSprite
, BoxImageSprite
, CircleImageSprite
, ChainSprite
, PolygonSprite
etc.
If you're really dying to have something like this...
new BoxSprite(x, y, w, h);
new CircleSprite(x, y, d);
new ChainSprite(x, y, lines);
new PolygonSprite(x, y, lines);
...then you could always add this to your code:
window.BoxSprite = Sprite;
window.CircleSprite = Sprite;
window.ChainSprite = Sprite;
window.PolygonSprite = Sprite;
BUT I think those constructor names would be misleading because a Sprite
object can have its physics body swapped out or removed. A BoxSprite
won't necessarily always have a box shape collider. In a student's game they might want the sprite to have a collider sometimes and sometimes not have a collider. The way I see it, its like if you had a Legs
class you wouldn't want RunningLegs
, SwimmingLegs
, and JumpingLegs
constructors, you just use a Legs
object to do all those different actions. You may see the different collider shape types more akin to CowLegs
, ChickenLegs
, GooseLegs
, etc. which is understandable but from a technical standpoint that's the wrong way to think about the Sprite
class. A sprite is a sprite regardless of what collider shape its physics body has.
So anyway there's my super long explanation on why the Sprite
constructor is the way it is. Hope you enjoyed it. 😅
The old p5play logo was very cute, and I'm still going to keep the little asterisk guy in the examples, but I figured it didn't communicate what I'm trying to have p5play v3 represent. I still want the logo to look fun but not too childish. p5play has grown up a bit! The new logo communicates with its shape that this version of p5play has some more advanced features but it is simple too, using only two flat colors.
I've been working on the reference documentation for the p5play website over the past few days. I created mie (mini editor) to embed p5.js sketches with instance mode previews. Even with 22 running on one page, the performance is great!
I'm making these reference pages because most documentation pages are just a big info dump and not a good way for beginners to learn about code libraries. When I first started teaching CS, I constantly made the mistake of giving my students too much information at once. I learned that I have to give kids the minimum amount of information at each step in the learning process so they have space to think of questions and thus be more interested in seeking out answers. Teachers are storytellers in a sense. Giving too much info at once is ruining the story but going too slow/being too pedantic is boring too. I want my reference pages to be an online textbook that people can use to interactively learn about p5play at their own pace.
On a personal note, one of my motivations for making p5play v3, apart from the old versions being outdated, was so that I could provide young programmers the kind of extensive documentation that I wanted, but never got, from Apple when I tried to learn how to use their SpriteKit game engine for iOS back in 2014. Objective-C was already considered a crusty old language at the time, so that certainly didn't help. But Apple's documentation was so awful that if I was a less stubborn determined person I probably would've quit programming altogether. I did end up realizing that SpriteKit was too slow and debugging was impossible (you couldn't have more than a dozen debug sprites on the screen without it crashing or frame crawling), so I quit using it. I was duped by Apple's Developer's Conference videos of SpriteKit and their promise of native performance advantages. Also I found that using Xcode was, and still is, terrible, which is a sentiment many developers agree with. If I could go back in time, I would've learned Unity instead, since their documentation and tutorials are great.
Fortunately I didn't let that awful experience with SpriteKit put me off programming in general! I learned a valuable lesson, for creatives like myself, the developer experience is much more important than resulting performance.
While I was working on p5play v3 over the past few months I had a lot of time to think about why students should learn how to use p5play.
First of course, using p5play is a great way for educators to introduce students to Object Oriented programming and JavaScript is commonly taught in AP CS Principles and similar courses.
Secondly, students can just focus on the code. Everything in a p5play sketch has to be created programmatically. Although I do think having a visual level editor for placing sprites would be nice, it's also nice that students don't also have to learn how to use a big editor app. For example, Unity has tons of advanced features and huge menus that can overwhelm beginners. Users don't have to install anything to get started with p5play, since it runs in web browsers.
Thirdly, while Unity is great for experienced programmers that can type out a bunch of code before testing it, beginners benefit from being able to easily test each line they write. Beginners don't trust that they're doing the right thing unless they can see it work. I've heard from students with older computers that having to repeatedly wait, even a few seconds, for Unity to compile C# and load their game really hurts the beginner dev experience. By comparison, the immediacy of running JS is a huge asset.