pythonarcade / arcade

Easy to use Python library for creating 2D arcade games.
http://arcade.academy
Other
1.71k stars 329 forks source link

Add decorator support to Arcade #126

Closed r0the closed 6 years ago

r0the commented 7 years ago

Hi

I'm planning on using the library in CS undergraduate classes, where I don't want to introduce inheritance, but would like to be able to work with user input.

It would be great if there was a possibility to register callback functions for events, like:

def on_mouse_press(self, x, y, button, modifiers):
    # do stuff

arcade.mouse_press_callback(on_mouse_press)

Thank you for considering my suggestion.

r0the commented 7 years ago

Here is a suggestion for the implementation: https://github.com/r0the/arcade/commit/9a1535279590778b6f566ffcfc79d264a5610638 And here is an example: https://github.com/r0the/arcade/commit/e7edb25523ac1d640c450d7a30c66c1cd4d07b25

If you like, I'm happy to make a pull request.

pauleveritt commented 7 years ago

Glad to see that you're looking at teaching with Arcade. I'm teaching my 16-year-old and it's confronting me with how some "normal" things in Python are hard when you get started.

You're right to think about function-oriented. Paul Craven has been talking to me about it. I've done some prototypes in the direction of decorator-based (using Dectate and/or reg).

We'd have to decide if we all agreed it was worth going in that direction. I'm personally interested in a radical improvement in the newcomer experience, which also scales further in the building-high-end-performant-games vector.

r0the commented 7 years ago

Actually, I'm quite new to Python myself. At my school, we were teaching Java for quite some time. I developed a Java framework that is quite similar to arcade (2D graphics, physics engine, Tiled integration, ...).

We switched to teaching Python as first language a year ago, which I'm very happy about. It's a great language! But we used Pygame last year, which is not very pythonesque and rather complicated for beginners. So I'm very happy I've discovered arcade.

I have the experience that it is very hard to teach object-oriented programming to younger students, so I usually try to everything without having to define classes.

A function- or decorator-oriented approach sounds promising.

Here is a growing collection of examples I created with arcade: https://github.com/r0the/arcade_examples. Feel free to use them.

pvcraven commented 7 years ago

I figure there are three main styles for doing things:

Picking just one alienates people who prefer one style. Allowing all three could cause programmers (particularly beginners) to get confused by having too many options. We've all seen programmers who can't decide on a style.

The Python mantra is to have only one way to do things. (But it notably ignores that in the case of print formatting.)

My initial thought would lean towards offering all three methods. With clear examples for each method, perhaps the confusion could be mitigated. From an instructional standpoint, showing new programmers the different ways of doing things might be worth-while.

pvcraven commented 6 years ago

I'd like to see this be the center point for release 1.3.

pauleveritt commented 6 years ago

FWIW, I've been working on a decorator-based system for Sphinx. (In fact, it's what has sucked up all my planned Arcade time. It's intended to be a cool static site generator for Arcade.)

It's based on Dectate. I have hundreds of hours now sitting in front of it, constantly thinking how I would do something for Arcade, or atop Esper, etc. Wouldn't mind doing some prototypes, though I have to close my other Arcade tickets before I'll have any credibility.

pvcraven commented 6 years ago

Is it an improvement to the Sphinx code, or does it live separate? Do you document via decorators? Or does it allow easier documentation of decorators?

pauleveritt commented 6 years ago

If you don't mind, perhaps we could discuss some goals and non-goals for this decorator discussion. If this is for a 1.3, then revolution shouldn't be in scope.

Some points from me:

Nice to haves:

Perhaps beyond scope:

pvcraven commented 6 years ago

I like all of these points. I'd like to keep backwards-compatibility if at all possible.

I have no idea how disruptive decorators will actually be to the main code base. I was hoping it could be done in an "add on" fashion. Not sure if that is practical.

pvcraven commented 6 years ago

Oh, I am using the projects tab to try and sort what goes in each release.

https://github.com/pvcraven/arcade/projects

pauleveritt commented 6 years ago

My Sphinx thing is almost exactly like what is discussed here: an existing framework (Sphinx or pyglet) with its own plugin system, albeit baroque, that we’d like to wrap with an alternate extension system.

Here’s an example of my thing. With this:

https://github.com/pauleveritt/kaybee/blob/master/docs/typedefs/demotype/__init__.py https://github.com/pauleveritt/kaybee/blob/master/docs/typedefs/demotype/__init__.py

…and a Jinja2 template:

https://github.com/pauleveritt/kaybee/blob/master/docs/typedefs/demotype/demotype.html https://github.com/pauleveritt/kaybee/blob/master/docs/typedefs/demotype/demotype.html

…I can write a Sphinx document like this:

https://raw.githubusercontent.com/pauleveritt/kaybee/master/docs/demopage.rst https://raw.githubusercontent.com/pauleveritt/kaybee/master/docs/demopage.rst

The decorator @kb.resource('demotype’) registers a new “resource” in my system. Which then:

…and lots of other things.

For the purpose of an Arcade discussion:

One could imagine some Arcade directive-based examples. However, none of them fit the current API, as the current API leaves pyglet in control. Instead, it’s a parallel “game” API:

https://gist.github.com/pauleveritt/85fd56e0cd33370b4bfaaa4542df536d

—Paul

pvcraven commented 6 years ago

Your docs project looks great! I have wished we could generate better docs for Python. For example, it isn't even easy to see what package an item really is in:

https://stackoverflow.com/questions/47273286/need-a-different-module-name-when-using-pythons-sphinx-automodule-directive?noredirect=1#comment81499893_47273286

And then one huge long scrolling list of "everything?" Not wild about that.

pauleveritt commented 6 years ago

Any thoughts about the gist at the bottom with discussion of a “game” API?

—Paul

On Dec 9, 2017, at 3:21 PM, Paul V Craven notifications@github.com wrote:

Your docs project looks great! I have wished we could generate better docs for Python. For example, it isn't even easy to see what package an item really is in:

https://stackoverflow.com/questions/47273286/need-a-different-module-name-when-using-pythons-sphinx-automodule-directive?noredirect=1#comment81499893_47273286 https://stackoverflow.com/questions/47273286/need-a-different-module-name-when-using-pythons-sphinx-automodule-directive?noredirect=1#comment81499893_47273286 And then one huge long scrolling list of "everything?" Not wild about that.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/pvcraven/arcade/issues/126#issuecomment-350502995, or mute the thread https://github.com/notifications/unsubscribe-auth/AAbx5rEltqb_igBjmTN_IrGiQ5HARLqlks5s-uvjgaJpZM4PeHrZ.

pvcraven commented 6 years ago

I like it. I tried to comment so at the bottom of the gist. I like that you have both a function and class example for it.

I feel like the main library we have now is working well and have had time to "shake things out." Decorator support is the next big thing I'd like to work on.

pauleveritt commented 6 years ago

Oops sorry, didn’t see the comment there. Want to discuss on the gist or on this ticket?

Just to be clear, that was science fiction. The stuff behind the scenes can go in a lot of directions. Some big questions:

1) Do you think having Arcade intermediate between pyglet and a game is right or wrong?

2) If right, then it probably means some differences from the current API.

3) Do you want to leverage an existing decorator config system (e.g. Dectate) or do something much smaller, no dependency?

4) Do you want to expand the scope to try and do something like implicit batching, or exclude the scope to “simpler API”?

—Paul

On Dec 10, 2017, at 10:21 AM, Paul V Craven notifications@github.com wrote:

I like it. I tried to comment so at the bottom of the gist. I like that you have both a function and class example for it.

I feel like the main library we have now is working well and have had time to "shake things out." Decorator support is the next big thing I'd like to work on.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/pvcraven/arcade/issues/126#issuecomment-350555615, or mute the thread https://github.com/notifications/unsubscribe-auth/AAbx5k1Y110UPm8s3SYHTmawvUnV9RLkks5s-_b-gaJpZM4PeHrZ.

pvcraven commented 6 years ago

1.) I see continuing to use Pyglet for OpenGL bindings. I don't want to maintain that as part of Arcade. The window and event management isn't as important to me, but it is a nice shortcut from coding right now. I don't use their sprite, drawing, or vertex buffer work.

2.) I tend to lean towards fewer dependencies. How active it Dectate? They aren't yet advertising it as a 1.0 release, and hasn't had a release since 2016 December. I'm not very familiar with decorator config systems.

3.) By batching, are you looking towards multi-threading, or batch drawing with vertex buffer objects? I'm not sure which you are talking about.

pvcraven commented 6 years ago

Which makes me think more, I should do some multi-threading for collision detection. That is currently one of the more expensive operations in sprite based games.

pauleveritt commented 6 years ago

1) I do mean keeping pyglet of course, I just mean not having our games get called directly by pyglet. We instead craft something simpler that lets us help users.

3) I just meant VBO batching.

I guess I should go back to the beginning. What problems with current Arcade would you like to address with a decorator approach?

pvcraven commented 6 years ago

I wouldn't call them problems, but I'd like to support programming by functions-only, or by using classes without inheriting from Arcade's class. Exactly what you sketched out in your gist.

pauleveritt commented 6 years ago

In my gist, we construct the pyglet window behind-the-scenes, which fixes some things e.g. start_render. You ok experimenting with that?

I agree on Dectate. If we had big ambitions about decoupling gravity and collisions into components in a plugin system, then we’d need more plugin architecture.

—Paul

On Dec 10, 2017, at 12:23 PM, Paul V Craven notifications@github.com wrote:

I wouldn't call them problems, but I'd like to support programming by functions-only, or by using classes without inheriting from Arcade's class. Exactly what you sketched out in your gist.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/pvcraven/arcade/issues/126#issuecomment-350563728, or mute the thread https://github.com/notifications/unsubscribe-auth/AAbx5oaoH3-l3nCgP7Ul7nAvhz0aypKFks5s_BN2gaJpZM4PeHrZ.

pvcraven commented 6 years ago

Fixing the need for start_render would be a nice thing to have.

pauleveritt commented 6 years ago

Regarding PEP 557 and DataClasses, I think they are only important if we want to encourage an ECS approach. I don't see how they'd help on this ticket, but I might be wrong.

pauleveritt commented 6 years ago

In addition to start_render, needing to call super() is something I'd be interested in no longer needing to teach people.

pauleveritt commented 6 years ago

Here's a working prototype. It went better than expected, but highlights a bunch of things to discuss. https://github.com/pauleveritt/arcade_decorator

pauleveritt commented 6 years ago

I just pushed a change to handle the imperative approach, meaning instead of callbacks, just have some lines in a file. E.g.:

from game_api import game

game.draw_text('Hello World', 10, 200, (0, 0, 0), 20) game.run(420, 240, background_color=(100, 100, 100))

pauleveritt commented 6 years ago

As a note, that example can be shorter:

from game_api import game

game.draw_text('Hello World', 10, 200, (0, 0, 0), 20) game.run()

...will use the default window size, color, and title.

pvcraven commented 6 years ago

I'm still looking at this. I like it so far. I need to push through some end-of-semester grading so I can get some quality early-morning time to look at it.

pvcraven commented 6 years ago

I still like this gist. Trying to figure out naming. Does something like this work, or is there some Python naming weirdness I'm not aware of?

@arcade.decorator.draw
def draw_the_ball(window):
    arcade.draw_circle_filled(window.ball.x_position, window.height // 2,
                              window.ball.radius, arcade.color.GREEN)
pauleveritt commented 6 years ago

Sorry for delay, we in Munich for work.

Instead of looking at the gist, look at the arcade_repo with the implementation. You can then change the arcadeapi class to “decorator” and get @arcade.decorator.draw.

My repo tried to tackle the global pyglet window. It (faked) keeping the current implementation while adding a parallel set of drawing functions (as class methods. I also tinkered with a branch to do implicit batching.

—Paul

On Dec 19, 2017, at 9:38 PM, Paul V Craven notifications@github.com wrote:

I still like this gist. Trying to figure out naming. Does something like this work, or is there some Python naming weirdness I'm not aware of?

@arcade.decorator.draw def draw_the_ball(window): arcade.draw_circle_filled(window.ball.x_position, window.height // 2, window.ball.radius, arcade.color.GREEN)

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/pvcraven/arcade/issues/126#issuecomment-352948124, or mute the thread https://github.com/notifications/unsubscribe-auth/AAbx5pN0RGgfAq8ohzv7EtR9EFRbWdS0ks5tCHMJgaJpZM4PeHrZ.

pvcraven commented 6 years ago

Yes, I pulled from that and put the API part in the 1.3 branch. I think I might work on it a bit and ask for some wider input.

pvcraven commented 6 years ago

API part, I'll have some example code soon. I need to look over yours and try it myself.

https://github.com/pvcraven/arcade/blob/Version_1.3/arcade/decorator_support.py

pauleveritt commented 6 years ago

The major unresolved question: Do you want this only for convenience, or also to eliminate the global window? If the former, my API gets simpler as it doesn't manage a window instance and pass it in. If the latter, we need to overhaul the existing function implementations.

I suspect any discussion such as implicity batching could be delayed. Although it might be useful to choose a design now that tolerates that decision later.

pvcraven commented 6 years ago

Unless I'm wrong, adding a window parameter would really complicate the API, for the rare cases when a programmer wants to manage two open windows. I like the simplicity of a simple "draw" decorator that "draws" and not have to worry about what window it is drawing to.

pvcraven commented 6 years ago

Initial stab at support in 1.3.0.