2018-04-28 21:09:36

Hello.
Now I would like to solve the problem of a simple game in Python.
I did this in C#, now I would like to see this in Python.
A few questions about Python:
1. pygame or pyglet. What is the difference and what is better and why?
2. In the pyglet, I saw the implementation through decorators and through OOP. What is more effective?
I do not quite understand the decorators, but if it's more effective, I can figure it out.
3. If you are a Python developer. What libraries can you recommend for Python? Sound, physics, other?
4. If you have any examples with Python, please share it!
Python attracts me the most, and I hope that I can realize my task.
My task:
Create a game window;
Field 20 by 20 cells;
Moving with the arrow keys;
Sound objects scattered across the field.
Thank you.

Thumbs up

2018-04-28 22:16:40

I've seen FPS in Python somewhere. Who has, share, please!

Thumbs up

2018-04-28 22:19:34

About pyglet:
Now I'm thinking about developing games in Python. Many people use the pyglet, but I can not figure it out.
In the original, decorators are used. I saw examples with OOP.
But this is confusing. When we write a game in C++ or C#, we write an algorithm. Everything is clear, what for what.
If I can use other libraries for development, I would be very happy.

Thumbs up

2018-04-28 23:52:16

Hello.
Can not use ScreenReader.
I can not compile Tolk.
When installing, Acceseble_output writes that the output module was not found, about pyttsx, the engine module.
What can I use?

Thumbs up

2018-04-29 00:24:51

Pygame tends to be a bit better with 2D projects, whereas Pyglet can do better with 3D due to its OpenGL bindings. I've also got a few scripts around that can augment Pyglets  OpenAL bindings to better support 3D audio, HRTF, and special effects like reverb, filters, etc. If I understand you correctly regarding decorators, it doesn't really matter. Working with classes seems more straightforward, though opinions may vary.

Libaudioverse has become a bit more popular and versatile, though I still tend to use pyglets built in OpenAL bindings. Numpy is also useful if you want to get more out of your data arrays, then there's the usual Pyttsx or Tolk for TTS or screen reader support. The thing with Tolk is that you need to download the right distro off appveyor [here], then copy over Tolk.DLL to your working directory along with the screen reader drivers in the x86 or x64 folders.

As for examples, I have a bunch available in my repository, the source for my Audiocraft FPS prototype is included with it, though I can provide a few simpler 3D examples if required.

[Audiocraft]
[i2s Filter examples]
[OpenAL Example]
[OpenAL HRTF]
[OpenAL Effects]

-BrushTone v1.3.3: Accessible Paint Tool
-AudiMesh3D v1.0.0: Accessible 3D Model Viewer

Thumbs up

2018-04-29 03:44:12

Spam.

2018-04-29 08:46:49

magurp244, I remember that you are a good Pyglet developer. I would like to show you your code with classes and ask questions about it:
import pyglet
from pyglet.window import key

#main class
class Example(pyglet.window.Window):
    def __init__(self):
        super(Example, self).__init__(640, 480, caption="Example")
    #load a sound
        self.sound = pyglet.media.load('example.wav',streaming=False)
    #load an image
        self.picture = pyglet.image.load('example.png')
    #run our update function continuously
        pyglet.clock.schedule_interval(self.update, .01)

#primary update loop
    def update(self,dt):
    #draw screen
        self.draw()

#draw to the screen
    def draw(self):
        self.clear()
        self.picture.blit(0,0)

#capture key presses       
    def on_key_press(self,symbol,modifiers):
    #if space is pressed, play sound
        if symbol == key.SPACE:
            self.sound.play()
    #if escape pressed, quit
        if symbol == key.ESCAPE:
            self.close()

window = Example()
pyglet.app.run()
In the beginning, we import the pyglet.
In the class, we redefine the constructor.
Next, we load the sound.
pyglet.clock.schedule_interval(self.update, .01)
Why is this needed?
def update(self,dt):
Why is this method needed?
I've heard that the dt parameter has time since the last time the method was run. But I do not know if this is so, and why.
self.draw()
Does this method display the screen or what? Without this method, the screen will not work?
    def draw(self):
        self.clear()
Why, if we called clear in the constructor?

Thumbs up

2018-04-29 08:51:41

How can I work with time?
For example, when traveling. In BGT or C#, I do a check if the timer is elapsed to example 150. How do I do this in Python?

Thumbs up

2018-04-29 09:35:25 (edited by magurp244 2018-04-29 09:39:24)

The main class in that particular example is a sub-classing of pyglets window function, in essence it inherets all of the originals functions but allows you to add functions or variables and change how it operates. Super is used in this case to help with calling the inherited functions from the parent class, pyglets window function.

The pyglet.clock.schedule line is to run the update function continuously as our main loop, this is more to have events occur without player input, such as autonomous AI behavior, physics, animations, etc. but may also include calling and updating other supporting classes like maps, the players character, etc. One of the requirements of the schedule function however is that the called function has to accept a time value, in this case dt which is the last time since the variable was called in milliseconds, it can also be useful for calculating, timing, or syncronizing events, or can be ignored if so desired. For example, if you want to check if 150 seconds have passed what you could do is store the dt value and do a check like so:

class Example(pyglet.window.Window):
    def __init__(self):
        super(Example, self).__init__(640, 480, caption="Example")
        ...
        self.counter = 0

    def update(self,dt):
        self.counter += dt
        if self.counter > 150.0:
            print "150 seconds have passed!"
            self.counter = 0

Also yes, the draw function does display the screen. The clear function is called to wipe the frame buffer clean before drawing the next frame, if it wasn't cleared you'd end up with an echo effect with the previous frame blending with the current frame. If clear were never called at program start or during the draw function, it would display everything ever drawn or whatever glitchy artifacts were in the frame buffer last. Technically you don't have to write it that way, though I tend to prefer to control when in the update loop the program redraws the display to ensure objects have been properly updated each cycle. You could easily get away with just using pyglets built in on_draw like so:

import pyglet
from pyglet.window import key

#main class
class Example(pyglet.window.Window):
    def __init__(self):
        super(Example, self).__init__(640, 480, caption="Example")
    #load a sound
        self.sound = pyglet.media.load('example.wav',streaming=False)
    #load an image
        self.picture = pyglet.image.load('example.png')
    #run our update function continuously
        pyglet.clock.schedule_interval(self.update, .01)

#primary update loop
    def update(self,dt):
        pass

#draw to the screen
    def on_draw(self):
        self.clear()
        self.picture.blit(0,0)

#capture key presses       
    def on_key_press(self,symbol,modifiers):
    #if space is pressed, play sound
        if symbol == key.SPACE:
            self.sound.play()
    #if escape pressed, quit
        if symbol == key.ESCAPE:
            self.close()

window = Example()
pyglet.app.run()
-BrushTone v1.3.3: Accessible Paint Tool
-AudiMesh3D v1.0.0: Accessible 3D Model Viewer

Thumbs up

2018-04-29 10:08:59

Thank you. What about the timer?

Thumbs up

2018-04-29 10:29:12

About Tolk.
In the folder with the game I put Tolk.pyo. But it does not see the Tolk module.

Thumbs up

2018-04-29 11:08:30

You need to put Tolk.dll as well

Thumbs up

2018-04-29 17:26:10

And all the APIs for screen readers

The bipeds think this place belongs to them, how cute.

Thumbs up

2018-04-30 00:00:37

@jonikster
There are a few weays to handle timing, as I mentioned when you schedule an event you can collect the dt number passed to the called function as a factor of time. When using pyglet.clock.schedule you supply the name of the function to call, followed by how long to wait before calling it, in the given example thats .01 seconds. Depending on how much your processing and latency issues the actual time it takes to call that function may be more or less, and you can find out how long it actually takes by printing the dt variable when update is called. When the function run's though you can also add up the dt variable to measure how much time has passed in total until a set point, like a timer. You can read a bit more about pyglets timing functions [here]. Here's my own example again:

class Example(pyglet.window.Window):
    def __init__(self):
        super(Example, self).__init__(640, 480, caption="Example")
        self.counter = 0

    def update(self,dt):
        self.counter += dt
        if self.counter > 150.0:
            print "150 seconds have passed!"
            self.counter = 0

There are a few other ways to handle time, such as pythons built in time.time() or time.clock() functions, or a few different ways to handle pyglets clock, but the above method is straight forward enough.

-BrushTone v1.3.3: Accessible Paint Tool
-AudiMesh3D v1.0.0: Accessible 3D Model Viewer

Thumbs up

2018-04-30 02:38:41

The BGT style timer is generally not the sort of thing you want to use for anything but establishing a frame rate. Objects that need to track how much time has passed will have a variable or property with the elapsed time, and it will be updated through the object's step or update method.
Consider a game with many objects with timers. If you do anything which interrupts the game, every timer must be paused, then resumed. If you have timers that are applied to objects, those must also be paused and resumed. If you add or remove one of these, you must update every section of code that manages timers.
If you use a single master timer, and use a fixed frame rate to update everything, you can skip all of that. If the game state is paused, it can still update frames, but since it's paused, the game objects behave as though no time has passed, and you didn't change anything to make this happen.
If you make your game objects inherit from a class to handle this method of managing time, you can save yourself the need to repeat the code for updating the time in each class. This was the purpose of the clock.bgt and FiniteStateMachine.bgt scripts, to simplify this model for BGT. Python already has a clock for this purpose (clock.bgt was partially based on Python's Time module), so all you need is the abstract class for game objects to inherit.

There are only two disadvantages to the frame method. One is resolution, but notice that 24 to 60 frames per second has been an exceptable time resolution for video for decades. The other is the risk of lag, if one frame takes too long to process, which has always been a risk to consider when developing software.

Some of my games
Keep up to date by following @Jeqofire on twitter!
Ear Ninja?

Thumbs up +1

2018-04-30 16:41:44

I'd just like to put in a good word for decorators... I have no idea why these confused me for so long, but they did.

Consider this code:

def f():
    pass
print(f)

Anyone can see that in that code you're creating a function, then printing it. That code is actually identical to:

@print
def f():
    pass

So using a decorator is exactly the same as calling the decoratING function with the decoratED function as the first argument.

When I'm writing tests as using throw-away functions (usually print), I'll often do something like:

assert decorator(print) is print

This is because the usual form is to return the decorated form of the function.

To give a more useful example:

from time import time, sleep


def timer(func):
    """Time how long it takes for func to complete."""

    def inner(*args, **kwargs):
        started = time()
        ret = func(*args, **kwargs)
        print(
            'Function %r completed in %.2f seconds.' % (func, time() - started)
        )
        return ret
    return inner


@timer
def print_after(seconds, message):
    sleep(seconds)
    print(message)


print_after(5.0, 'Hello world.')

Running python timer.py gives me:

Hello world.
Function <function print_after at 0x055990C0> completed in 5.00 seconds.

Depending on how you're structuring your code, decorators make a lot of sense.

With Mindspace I'm using the for commands.

I could do:

from mindspace_protocol import MindspaceParser


class Parser(MindspaceParser):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.commands['message'] = self.message

    def message(self, con, msg):
        print(msg)


parser = Parser()

Or I could do:

from mindspace_protocol import MindspaceParser

parser = MindspaceParser()


@parser.command
def message(self, con, msg):
    print(msg)

You can see at a glance which is less typing.

Either way, decorators are syntactic sugar and should not be treated as any great mystery. They're another tool available to the Python programmer to either use or not.

If I've still not convinced you, consider this:

Would you rather have one function which handles all keypresses in your game with a snakes nest of if statements? Or would you rather have a list of lines like:

@key('SPACE')
def handle_space():
    """Fire a weapon."""
    shoot()
Take care,
Chris Norman
Selling my soul to andertons.co.uk since 2012.

2018-04-30 18:27:16

I do like that layout. I find decorators are appropriate to use and inappropriate in other places. You shouldn't use them everywhere -- that creates function bloat. Use them where you feel they're appropriate.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.

Thumbs up

2018-05-02 00:03:41

Traceback (most recent call last):
  File "game.py", line 3, in <module>
    import Tolk
ModuleNotFoundError: No module named 'Tolk'
Folder structure:
Python_game
game.py
Tolk.dll
Tolk.pyo
I'll try code in game.py:
import pyglet
from pyglet.window import key
import Tolk
Tolk.load()
window = pyglet.window.Window(fullscreen=True, caption='Game')
window.set_exclusive_mouse()
@window.event
def on_draw():
    window.clear()
@window.event
def on_key_pressed(symbol, modifiers):
    if symbol == key.SPACE:
        Tolk.output("Space pressed...")
pyglet.app.run()
And another question. How can I make the closing event of the game? For example, where can I call Tolk.unload()?

Thumbs up

2018-05-02 00:27:24 (edited by magurp244 2018-05-02 01:03:22)

I seem to remember running into an issue with Tolk.pyo, try putting Tolk.py into your working directory instead. As for unload, you can add a quit option in the on_key_pressed() function like so:

@window.event
def on_key_press(symbol,modifiers):
    if symbol == key.ESCAPE:
        Tolk.unload()
        window.close()

Another way would be to add it to pyglets built in on_close() function, which is automatically called when the window is closed:

@window.event
def on_key_press(symbol,modifiers):
    if symbol == key.ESCAPE:
        window.close()

@window.event
def on_close():
    Tolk.unload()
-BrushTone v1.3.3: Accessible Paint Tool
-AudiMesh3D v1.0.0: Accessible 3D Model Viewer

Thumbs up

2018-05-02 09:12:46

Just a small pick with that last code: I'm sure you just wrote it off the bat as an example, but for anyone who's reading this and doesn't already use a code-checking tool like flake8, PEP8 requires two blank lines before and after function or class definitions.

Fact, anyone who's not using Flake8 (or something better that I've not heard of) really should be. smile

Cheers

Take care,
Chris Norman
Selling my soul to andertons.co.uk since 2012.

2018-05-02 16:04:20

magurp244, Where can I get Tolk.py?

Thumbs up

2018-05-03 00:57:20

Its in the same appveyor package as everything else in the src/python/ directory.

-BrushTone v1.3.3: Accessible Paint Tool
-AudiMesh3D v1.0.0: Accessible 3D Model Viewer

Thumbs up

2018-05-03 20:21:40

My code does not work. The game window opens, but when I press the space, nothing happens.
import pyglet
from pyglet.window import key
import Tolk
Tolk.load()
window = pyglet.window.Window(fullscreen=True, caption='Game')
window.set_exclusive_mouse()
@window.event
def on_draw():
    window.clear()
@window.event
def on_key_pressed(symbol, modifiers):
    if symbol == key.SPACE:
        Tolk.output("Space pressed...")
pyglet.app.run()

Thumbs up

2018-05-03 22:06:16

What have you tried so far? All looks good to me. Only thing I can think of is that you got the event name wrong. Have you checked pyglet's docs?

HTH,

Take care,
Chris Norman
Selling my soul to andertons.co.uk since 2012.

2018-05-03 22:12:26

chrisnorman7, Yes you are right.

Thumbs up