New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add decorator support to Arcade #126

Closed
r0the opened this Issue Sep 20, 2017 · 34 comments

Comments

Projects
3 participants
@r0the
Contributor

r0the commented Sep 20, 2017

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

This comment has been minimized.

Contributor

r0the commented Sep 21, 2017

Here is a suggestion for the implementation: r0the@9a15352
And here is an example: r0the@e7edb25

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

@pauleveritt

This comment has been minimized.

Collaborator

pauleveritt commented Sep 21, 2017

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

This comment has been minimized.

Contributor

r0the commented Sep 21, 2017

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

This comment has been minimized.

Owner

pvcraven commented Sep 24, 2017

I figure there are three main styles for doing things:

  • Derive from a parent class
  • Use a callback
  • Use decorators

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 pvcraven added the enhancement label Oct 3, 2017

@pvcraven pvcraven added this to To Do in Release 1.3 Dec 5, 2017

@pvcraven pvcraven changed the title from Add possibility to register callbacks for events to Add decorator support to Arcade Dec 5, 2017

@pvcraven

This comment has been minimized.

Owner

pvcraven commented Dec 5, 2017

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

@pauleveritt

This comment has been minimized.

Collaborator

pauleveritt commented Dec 5, 2017

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

This comment has been minimized.

Owner

pvcraven commented Dec 9, 2017

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

This comment has been minimized.

Collaborator

pauleveritt commented Dec 9, 2017

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:

  • Should support function-oriented and class-oriented

  • Should not be conceptually harder than current Arcade (hopefully conceptually easier, once you get over the decorator). For example, we can give them a pre-made game instance and all they do is provide a draw_text that gets passed a working game

  • Should intermediate the pyglet API, so we can provide something easier/simpler

Nice to haves:

  • Should be easier to test (by not needing pyglet)

  • Easier to write faster games (by us doing batching behind the scenes)

Perhaps beyond scope:

  • Building a bigger, pluggable ecosystem (Esper has ECS)
@pvcraven

This comment has been minimized.

Owner

pvcraven commented Dec 9, 2017

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

  • 1.2 branch is for minor improvements
  • 1.3 branch the focus should be on decorators.

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

This comment has been minimized.

Owner

pvcraven commented Dec 9, 2017

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

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

@pauleveritt

This comment has been minimized.

Collaborator

pauleveritt commented Dec 9, 2017

@pvcraven

This comment has been minimized.

Owner

pvcraven commented Dec 9, 2017

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

This comment has been minimized.

Collaborator

pauleveritt commented Dec 10, 2017

@pvcraven

This comment has been minimized.

Owner

pvcraven commented Dec 10, 2017

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

This comment has been minimized.

Collaborator

pauleveritt commented Dec 10, 2017

@pvcraven

This comment has been minimized.

Owner

pvcraven commented Dec 10, 2017

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

This comment has been minimized.

Owner

pvcraven commented Dec 10, 2017

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

This comment has been minimized.

Collaborator

pauleveritt commented Dec 10, 2017

  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.

  2. 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

This comment has been minimized.

Owner

pvcraven commented Dec 10, 2017

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

This comment has been minimized.

Collaborator

pauleveritt commented Dec 10, 2017

@pvcraven

This comment has been minimized.

Owner

pvcraven commented Dec 10, 2017

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

@pauleveritt

This comment has been minimized.

Collaborator

pauleveritt commented Dec 10, 2017

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

This comment has been minimized.

Collaborator

pauleveritt commented Dec 10, 2017

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

@pauleveritt

This comment has been minimized.

Collaborator

pauleveritt commented Dec 11, 2017

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

This comment has been minimized.

Collaborator

pauleveritt commented Dec 11, 2017

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

This comment has been minimized.

Collaborator

pauleveritt commented Dec 11, 2017

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

This comment has been minimized.

Owner

pvcraven commented Dec 13, 2017

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

This comment has been minimized.

Owner

pvcraven commented Dec 20, 2017

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)

pvcraven added a commit that referenced this issue Dec 20, 2017

@pauleveritt

This comment has been minimized.

Collaborator

pauleveritt commented Dec 22, 2017

@pvcraven

This comment has been minimized.

Owner

pvcraven commented Dec 22, 2017

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

This comment has been minimized.

Owner

pvcraven commented Dec 22, 2017

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

This comment has been minimized.

Collaborator

pauleveritt commented Dec 22, 2017

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 added a commit that referenced this issue Dec 22, 2017

@pvcraven

This comment has been minimized.

Owner

pvcraven commented Dec 29, 2017

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 added a commit that referenced this issue Jan 2, 2018

pvcraven added a commit that referenced this issue Jan 2, 2018

@pvcraven pvcraven moved this from To Do to In Progress in Release 1.3 Jan 11, 2018

@pvcraven pvcraven moved this from In Progress to Done in Release 1.3 Feb 11, 2018

@pvcraven

This comment has been minimized.

Owner

pvcraven commented Feb 11, 2018

Initial stab at support in 1.3.0.

@pvcraven pvcraven closed this Feb 11, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment