#my impression is that most of the lua
1 messages ยท Page 1 of 1 (latest)
Minor quibble on the use of "canvas" - in my experience canvas usually means the opposite of "draw all the game graphics on it from scratch every frame", although it is sometimes used with that meaning. I only bring this up because IMHO it's a very useful term if a community can agree on what it means in their domain.
I'm not familiar with a similar common general term for "draw all the game graphics on it from scratch every frame" APIs which require you to clear and redraw everything yourself with graphics primitives, but examples would be a Windows DC (device context), pyGame Surface, frame buffers, etc... Unfortunately, the Java AWT choose to overload the term contrary to common usage and represent this pattern using Canvas, which introduced confusion into what was (and IMHO mostly still is) a very useful term in the context of software development. (Neither the first nor last case example of choices which could plausibly have been motivated by a desire to displace other systems by introducing confusion and FUD - Java hasn't tended to "play well with others" - but that's a pet peeve we don't need to discuss here)
A canvas is generally is a collection of objects (text, shapes, ...) with attributes (colors, size, z-index, ...) which are rendered (and scaled, scrolled, etc.) for you by the framework providing the canvas. I'm not sure it originated with TCL/TK, but it goes back at least that far (35-ish years). It is used explicitly by LVGL Canvas, python TKInter.Canvas, [HTML <canvas> element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/canvas], Unity Canvas, C#/XAML Canvas, snap Lens-Studio Canvas.
Again, not implying you were "wrong"
I'm not particularly attached to that word, we can use framebuffer instead
This just happens to be a term I'm rather fond of ๐
In any case, a graphics library based on that concept could be a good alternative to displayio
(FWIW I consider the "canvas" pattern to represent 2D hierarchies, with "scene-graph" representing the same concepr for 3D)
you would set up dma to just blast the entire buffer to the display every frame in the background, and then use blits and/or drawing commands to fill it every frame
with double buffering to avoid artifacts
this especially makes sense with full screen scrolling and first person 3d
Finding embedded controllers with support for DMA display updating might be tricky. You can get part of the way with DMA support for SPI, but without a lot of extra effort that could be rather inefficient
every single microcontroller that runs circuitpython has dma for its spi peripheral
Realistically, if your target is CircuitPython on embedded controllers, this would usually mean doing all the work in software on the MCU. Kinda begs the question "why" - yeah, you could get something to work, but it's not going to work nearly as well as a system with GPU support,
plenty of pretty good games on the PC before it had gpus
and not just doom
modern mcus are roughly comparable to a pentium computer
Which is why I mentioned it. DMA over SPI is certainly "better than nothing", but it's much slower than parallel transfer and worlds apart from shared memory. And without an intelligent way to identify (on the MCU) and send "partial updates" (only what has changed) it's even worse.
esp32 and pi pico have dma with parallel too
the samd and nrf I'm not sure, but probably new boards wouldn't be made with those
not for games anyways
besides, from my experiments, the parallel displays are not that much faster, because you have to use much slower clocks
(speaking about the displays that have built-in memory here, of course the lcds that are driven directly from the mcu are instant)
Sure, which means you ought to be able to run an actual OS (like Raspbian on them and then build/use one of the many options for such tasks. IMHO the issue isn't whether the hardware is sufficient, but rather how much effort it would take to support something like this within CircuitPython. And even if you did, it might not make it into the "standard" firmware build for most controllers, because this would take a good bit of additional C-code and FLASH space is limited.
dos didn't really have that much of an OS stuff, and circuitpython already has most of it
it was mostly a filesystem
It would be cool, but it's also a fairly niche application for CircuitPython which may not even be usable on most builds.
I'm not saying you have to run dos on it, I'm just saying it's comparable in terms of computing power and memory
obviously the hardware is completely different
and the flash memory is actually much faster than a diskette
And it would be a lot of work, because porting existing python wrapped C level frameworks into Micro/CircuitPython isn't a simple task
I'm not talking about porting existing games
I'm just saying it should be possible to write new games at the same level as the games that ran on the pentium
this is a game written for the samd21 https://hackaday.io/project/164367-40-fps-16-bpp-platform-game-on-a-cortex-m0-board
A poor's man hand-held console is made using a small Cortex M0+ board (Arduino Zero compatible), some switches, a widespread 1.8โ 160x128 pixels TFT display and few other external components. In this project we focus on a platform game.
The framerate is fixed at 40 fps (without frame cap, the frame rate would vary between 41 and 51...
if you want do do custom firmware builds, and run it on beefy MCUs with lots of ram and FLASH, that could work. But adding enough native compiled code to support a decent graphics subsystem within the constraints of the "standardized" CircuitPython firmware FLASH partition layouts could be a problem. FWIW that also may be an issue with LVGL, which could easily add over 100K to the firmware size.
For an updated video, showing score and health overlay: https://youtu.be/1ekTeCCWKNI
For more details: https://next-hack.com/
uChip can be bought from Itaca Innovation's webstore (https://shop.itaca-innovation.com/).
obviously the new library would be compiled into the standard circuitpython firmware
at least the parts that need to be fast
Again, not saying the hardware isn't there. just questioning whether CircuitPython is the right platform for something like this. It's already going to be complex enough to be well beyond "beginner" skill levels, so Arduino C/C++ shouldn't be a problem and would provide better performance and a wider variety of libraries to work with.
That's kinda my point ๐ . I've only started dabbling with writing C extension wrapper code for CircuitPython, but I've done a lot of that with CPython and it's a different beast. You'd basically need to find a decent C level implementation, then effectively create a new extension wrapper from scratch (even if it already had CPython API-based wrapper). And there are quite a few subtilties which need to handled - especially regarding object inheritance and virtual dispatch. Not to mention threading - something like this could benefit significantly from running most of the pipeline on a separate core for MCUs which have them (like an EPS32 S3), but properly handling virtual callbacks into python code from the rendering thread is hard with CPython. Not sure if it would even be possible (at least without a lot of major blocking in the render thread) with CircuitPython.
In short, I've done this before for CPython, and it's a lot of work and it would be even harder with CircuitPython - at least if you want to get much beyond the realm of 8-bit era graphics.
this is what it took for the _stage module: https://github.com/adafruit/circuitpython/pull/398/files
it's not super complicated
(today the code would be slightly different, because some of the macros changed, but it wouldn't be much larger)
about half of it is boilerplate
it rarely is at first.... If you just want a simplistic "draw everything manually" API it might stay fairly straightforward. But that also means there's much more work for the user, and much more of the "low level" stuff in python code. And eventually someone will want a canvas, some MCU will add more advanced display hardware support (integrated GPU/shared memory bus/...) requiring a lot of refactoring, etc.
you are not obligated to work on anything, I just made _stage the minimum required, and then put all the convenient api for the gamedevs in stage.py
this way you can also experiment with different frameworks in python using the same low-level functions
besides, I don't think there are any gpu chips out there you could easily use in hobby projects
Stage looks like an interesting option for experimenting a bit with simple 2D graphics.
those projects exist for over two decades
maybe not yet, but there are some out there and eventually we'll see GPU support added to MCU families with CircuitPython boards
that's the advantage of minimal part in C -- you can always rewrite the parts you need for particular hardware, and keep the python api the same
sure, the point is that UI libraries tend to grow - users always want more
then they are free to add more
nobody is forcing you to work on anything you don't want to work on
you are not obligated to add the features they ask for
Yeah, I understand that
stage is pretty much unchanged since the first commit, except for bug fixes and an added 2x scaling
and if this is just something you really want to do, that's more than enough reason to do it (I have my own windmills...)
then I have no idea why this discussion in the first place?
but I suspect there are other things you could spend time on that would benefit a much wider slice of the CircuitPython comminity
but I'm not getting paid for benefitting the cp community, so they can spend their own time on those things
and it can also end up being a very deep rabbit hole
you can go as deep as you want
if it's primarily for your own amusement/exploration, unless it's specifically about the challenge of doing it with MicroPython/CircuitPython there are probably much easier options to do "python game coding" in an embedded-size package. A Raspberry Pi Zero 2 W is pretty small and can run "real" python. If you have room for a full sized Pi board, the Pi 5 actually has a GPU.
shockingly, it's not easier
you get the whole overhead of the operating system, kernel modules for handling the display and the buttons, device trees, sd card corruption, power problems, and so on
I made that library and the game console for it specifically to make it possible to just plug in a device and write a game for it, like you did with basic in the good old days
but you also get a much larger ecosystem of ready to use code you can build on
if your goal is writing stuff similar to what you could manage on a Commodore 64, that's definitely plausible
it takes about 50 lines of code to make a snake game in Stage, it's more like 500 in PyGame
do you have links for some examples?
my goal is for that stuff to be equally simple, and for the more complex stuff to be still possible
I have a space invaders clone at https://github.com/python-ugame/vacuum-invaders and unfinished platformer at https://github.com/python-ugame/jumper-wire
you can play them if you have a pygamer, pybadge, pico-system or similar circuitpython device
I'm working on a top-down adventure game too, but it's not published yet
I'm late to the discussion, but hearing about your experience with this is very interesting. My perspective on adding features to enable building games on CircuitPython is oriented a lot towards:
- What missing pieces can I fill in to enable writing guides for interesting-but-not-too-complex projects that people would hopefully find non-intimidating and want to try on their own?
- Trying to understand what level of game-building stuff makes sense to do in CircuitPython. Like, at what point is it the wrong tool for the job?
So far, I've found it works pretty well to do simple games using displayio TileGrid where there's a fixed background that mostly doesn't change, then some stuff moves around on top of that.
But, I'm getting to the point where I'd like to try fancier things
As I think through the kind of graphics stuff I'd need to build some of the ideas I have in mind, it seems like it could end up being a lot of work -- as with the stuff you described.
One of the big factors in my mental calculus around this stuff is that a lot of the fancier game engine and framework things are too complicated, and they often evolve too fast. I've read various horror stories over the years from folks who put a lot of time in on a project, only to have some company decide to do a rug pull and totally change some API, then the poor game dev is stuck either doing a big re-write or not being able to build their game any more.
One thing I like a lot about doing little games for Adafruit boards is that it doesn't feel so risky in that way (compared to say, iOS or Unity). So, it's usually a much more student and beginner friendly process. And by "friendly", I'm including the risk of somebody being heartbroken a year or two down the road because it becomes impossible to build and run their old project.
One of the big motivations for the question I asked the other day is I'm trying to understand what might be a reasonable upper limit on complexity of games to build in CircuitPython.
Anyhow, thanks for the thoughts and perspectives on what it's been like to build some different projects at various levels of complexity.