{ "info": { "author": "Steve Johnson", "author_email": "steve@steveasleep.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6" ], "description": "clubsandwich\n============\n\n**A roguelike framework for Python 3 using**\n`BearLibTerminal `_\n\n`Source code `_\n\n`API docs `_\n\nWhat is this?\n-------------\n\nImagine you want to write a roguelike, you don't want to roll your own\nframework from scratch, and you want to use Python.\n\nThe most mature option for doing this is\n`libtcod-cffi `_, which is a\nkitchen sink of roguelike development utilities like terminal graphics,\npathfinding, random numbers, noise generators, config file parsers, and data\nstructures. But it's pretty heavy, the docs aren't great, and it's an icky\nC API. And while it covers a lot of things you need for a roguelike, it doesn't\nhelp you much with your UI or state management.\n\nIf that sounds like a decent tradeoff, go try ``libtcod-cffi`` and be happy!\nBut there's another library,\n`BearLibTerminal `_, that only\nhandles terminal graphics. It's tiny and understandable. Clubsandwich\nbuilds on BearLibTerminal (BLT...) to add a nice API, state management, easy\nUI, and some other helpful stuff.\n\nFeatures\n~~~~~~~~\n\nScroll down for examples.\n\n* Event loop\n* Scene manager\n* Geometry data structures\n* Convenience functions\n* UIKit-like interface framework\n* Script runner to help you iterate quickly\n\nDependencies\n~~~~~~~~~~~~\n\n* Python 3.4+\n* And BearLibTerminal, of course\n\nInstallation\n------------\n\nThis package is not yet on PyPI. It is under heavy development. But you can\nexpect reasonable API stability!\n\n.. code:: python\n\n pip install -e 'git://github.com/irskep/clubsandwich.git@master#egg=clubsandwich'\n\n\n.. image:: readme_images/screenshot1.png\n\n.. image:: readme_images/screenshot2.png\n\nFeature examples\n----------------\n\nAn event loop\n~~~~~~~~~~~~~\n\nclubsandwich uses the `asyncio`_ library to run an asynchronous update loop.\nThe ``terminal_read(val)`` method is called whenever events are in the queue.\n``terminal_update()`` is called every frame.\n\n.. _asyncio: https://docs.python.org/3/library/asyncio.html\n\n.. code:: python\n\n from clubsandwich.loop import BearLibTerminalEventLoop\n\n class BasicLoop(BearLibTerminalEventLoop):\n def terminal_read(self, val):\n print(\"User pressed a key:\", val)\n\n def terminal_update(self):\n # this is called every frame\n self.draw()\n\n\n if __name__ == '__main__':\n BasicLoop().run()\n\nA scene manager\n~~~~~~~~~~~~~~~\n\nMost games have more than one screen! This simple \"director\" object manages\nthem for you in a really obvious way.\n\n.. code:: python\n\n from bearlibterminal import terminal\n from clubsandwich.director import DirectorLoop, Scene\n\n class BasicLoop2(DirectorLoop):\n def get_initial_scene(self):\n return MainMenuScene()\n\n class MainMenuScene(Scene):\n def terminal_update(self):\n print(0, 0, \"Press Enter to begin game, Esc to quit\")\n\n def terminal_read(self, val):\n if val == terminal.TK_ENTER:\n self.director.push_scene(GameScene())\n elif val == terminal.TK_ESCAPE:\n self.director.pop_scene()\n\n class GameScene(Scene):\n def terminal_update(self):\n print(0, 0, \"You are playing the game, it is so fun! Press Esc to stop.\")\n\n def terminal_read(self, val):\n if val == terminal.TK_ESCAPE:\n self.director.pop_scene()\n\n if __name__ == '__main__':\n BasicLoop2().run()\n\nA geometry library\n~~~~~~~~~~~~~~~~~~\n\nBasic data structures for ``Rect``, ``Point``, and ``Size``, and a very thin\nwrapper around ``bearlibterminal.terminal`` to support them.\n\n.. code:: python\n\n from clubsandwich.blt.nice_terminal import terminal\n from clubsandwich.geom import Rect, Size, Point\n\n terminal.open()\n terminal.bkcolor('#ff0000')\n terminal.clear_area(Rect(Point(2, 2), Size(10, 10)))\n terminal.refresh()\n terminal.read()\n terminal.close()\n\nConvenient terminal state access\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nA super simple wrapper around ``terminal.state()`` to conveniently read state\nvalues.\n\n.. code:: python\n\n from clubsandwich.blt.state import blt_state\n from clubsandwich.blt.nice_terminal import terminal\n from clubsandwich.geom import Rect, Size, Point\n\n terminal.open()\n terminal.bkcolor('#ff0000')\n terminal.clear_area(Rect(Point(2, 2), Size(10, 10)))\n terminal.refresh()\n # less verbose than terminal.state(terminal.TK_ESCAPE)!\n while not blt_state.escape:\n terminal.read()\n terminal.close()\n\nTransform stack\n~~~~~~~~~~~~~~~\n\nEasily translate view coordinates between frames of reference.\n\n.. code:: python\n\n from clubsandwich.blt.state import blt_state\n from clubsandwich.blt.context import BearLibTerminalContext\n from clubsandwich.geom import Rect, Size, Point\n\n terminal = BearLibTerminalContext()\n\n terminal.open()\n terminal.bkcolor('#ff0000')\n with terminal.translate(Point(blt_state.width, blt_state.height)):\n terminal.clear_area(Rect(Point(2, 2), Size(10, 10)))\n terminal.refresh()\n # less verbose than terminal.state(terminal.TK_ESCAPE)!\n while not blt_state.escape:\n terminal.read()\n terminal.close()\n\nA UIKit-like user interface library\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThis is too sophisticated for a short demo, but here's the code for the scene\nin the first screenshot:\n\n.. code:: python\n\n from clubsandwich.ui import (\n LabelView,\n ButtonView,\n UIScene,\n )\n LOGO = \"\"\"\n _______ __ ____ __ _ __ \n / ___/ /_ __/ / / __/__ ____ ___/ / __(_)___/ / \n / /__/ / // / _ \\ _\\ \\/ _ `/ _ \\/ _ / |/|/ / / __/ _ \\\\\n \\___/_/\\_,_/_.__/ /___/\\_,_/_//_/\\_,_/|__,__/_/\\__/_//_/\n \"\"\"\n class MainMenuScene(UIScene):\n def __init__(self, *args, **kwargs):\n views = [\n LabelView(\n LOGO[1:].rstrip(),\n layout_options=LayoutOptions.row_top(0.5)),\n LabelView(\n \"Try resizing the window!\",\n layout_options=LayoutOptions.centered('intrinsic', 'intrinsic')),\n ButtonView(\n text=\"Play\", callback=self.play,\n layout_options=LayoutOptions.row_bottom(4).with_updates(\n left=0.2, width=0.2, right=None)),\n ButtonView(\n text=\"Settings\", callback=self.show_settings,\n layout_options=LayoutOptions.row_bottom(4).with_updates(\n left=0.4, width=0.2, right=None)),\n ButtonView(\n text=\"Quit\", callback=lambda: self.director.pop_scene(),\n layout_options=LayoutOptions.row_bottom(4).with_updates(\n left=0.6, width=0.2, right=None)),\n ]\n super().__init__(views, *args, **kwargs)\n\n def play(self):\n self.director.push_scene(CharacterCreationScene())\n\n def show_settings(self):\n self.director.push_scene(SettingsScene())\n\nScript runner\n~~~~~~~~~~~~~\n\nWhen you install clubsandwich, it adds a script called ``babysit`` to your\npath. This script does one very simple thing: it runs a command, and when that\ncommand exits, it runs it again. This repeats until you Ctrl+C the ``babysit``\nprocess.\n\nThis is useful when writing games because you don't want to have to keep\nswitching back to your terminal to run your script. Using ``babysit``, you can\njust quit your game whenever you make a change and it'll start back up again.\n\nYou can try it with the demo script like this:\n\n.. code:: sh\n\n babysit python demo.py", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://steveasleep.com/clubsandwich", "keywords": "bearlibterminal,roguelike", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "clubsandwich", "package_url": "https://pypi.org/project/clubsandwich/", "platform": "", "project_url": "https://pypi.org/project/clubsandwich/", "project_urls": { "Homepage": "http://steveasleep.com/clubsandwich" }, "release_url": "https://pypi.org/project/clubsandwich/0.1.3/", "requires_dist": null, "requires_python": "", "summary": "A roguelike framework", "version": "0.1.3" }, "last_serial": 2888095, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "15e9ac1c6c9280e2434f4447f6a70342", "sha256": "ff7e5f4379263e129312be68f1a9026b798b5cb914c3da44046221379c9977cb" }, "downloads": -1, "filename": "clubsandwich-0.1.0.tar.gz", "has_sig": false, "md5_digest": "15e9ac1c6c9280e2434f4447f6a70342", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 34180, "upload_time": "2017-05-21T03:03:03", "url": "https://files.pythonhosted.org/packages/b9/17/6a5234bfb2db6db55e493d9ff7cdde685e2022f56b76ea4010a1c6ce699e/clubsandwich-0.1.0.tar.gz" } ], "0.1.0a1": [ { "comment_text": "", "digests": { "md5": "d25b3fd29f8ab98a8ca952945ce19429", "sha256": "b0c98a2b2c870af74307080ec21a2266493398e425f83eb08e7dbcaf3abdfade" }, "downloads": -1, "filename": "clubsandwich-0.1.0a1-py3.5.egg", "has_sig": false, "md5_digest": "d25b3fd29f8ab98a8ca952945ce19429", "packagetype": "bdist_egg", "python_version": "3.5", "requires_python": null, "size": 96378, "upload_time": "2017-05-21T03:03:05", "url": "https://files.pythonhosted.org/packages/3b/a0/496c0b4f0d91325fcb8c5b24028925d12ec58c2c53599f10c9cd1fc5b735/clubsandwich-0.1.0a1-py3.5.egg" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "5842f86b3ca504d255b990d14a8ff290", "sha256": "5a1bce2f0914a1800fcdf7c9d3300be433853709140d873df5dbcbc889e635e6" }, "downloads": -1, "filename": "clubsandwich-0.1.1.tar.gz", "has_sig": false, "md5_digest": "5842f86b3ca504d255b990d14a8ff290", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 34218, "upload_time": "2017-05-21T03:07:41", "url": "https://files.pythonhosted.org/packages/f7/2b/24ad8416f63ed69de33d7fa9265b7b4a87cd84c4efd7df35bd8bf7641252/clubsandwich-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "e93b2b95b4984e7dd2f703a2f53127e1", "sha256": "19b94c680628424899ab367cc8024bd63cc8b69e43b4d468677dd301a0951e2e" }, "downloads": -1, "filename": "clubsandwich-0.1.2.tar.gz", "has_sig": false, "md5_digest": "e93b2b95b4984e7dd2f703a2f53127e1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 34245, "upload_time": "2017-05-21T03:08:48", "url": "https://files.pythonhosted.org/packages/8d/92/34fced576bb5d53d4ab8e7c22ff1c71e5d98464b66f0d1ba73c3e51376ab/clubsandwich-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "b6d4d580196fa2c3ca98774c1602e5cb", "sha256": "78469078f6093ae9a7f03f9954b273285970b4ef763b3a0ca75b09c651511bb4" }, "downloads": -1, "filename": "clubsandwich-0.1.3.tar.gz", "has_sig": false, "md5_digest": "b6d4d580196fa2c3ca98774c1602e5cb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 37563, "upload_time": "2017-05-21T03:12:28", "url": "https://files.pythonhosted.org/packages/e5/18/3cdde64407f4eac991b8b02a47d24f5c917012483747a991b44285ca5388/clubsandwich-0.1.3.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "b6d4d580196fa2c3ca98774c1602e5cb", "sha256": "78469078f6093ae9a7f03f9954b273285970b4ef763b3a0ca75b09c651511bb4" }, "downloads": -1, "filename": "clubsandwich-0.1.3.tar.gz", "has_sig": false, "md5_digest": "b6d4d580196fa2c3ca98774c1602e5cb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 37563, "upload_time": "2017-05-21T03:12:28", "url": "https://files.pythonhosted.org/packages/e5/18/3cdde64407f4eac991b8b02a47d24f5c917012483747a991b44285ca5388/clubsandwich-0.1.3.tar.gz" } ] }